一千萬個為什麽

搜索

Samplegrabber在AVI/MPEG文件上工作正常但與WMV不同

我一直在使用最新版本的 WPFMediaKit 。我要做的是編寫一個示例應用程序,它將使用Samplegrabber來捕獲視頻文件的視頻幀,這樣我就可以將它們作為單獨的位圖。

到目前為止,在構建和渲染圖形時,我對以下代碼運氣不錯。但是,當我使用此代碼播放.wmv視頻文件時,如果連接了samplegrabber,它將播放跳躍或波濤洶湧。如果我註釋掉我添加samplegrabber過濾器的行,它可以正常工作。同樣,它可以使用AVI/MPEG等正確使用samplegrabber。

 protected virtual void OpenSource()
    {
        FrameCount = 0;
        /* Make sure we clean up any remaining mess */
        FreeResources();

        if (m_sourceUri == null)
            return;

        string fileSource = m_sourceUri.OriginalString;

        if (string.IsNullOrEmpty(fileSource))
            return;

        try
        {
            /* Creates the GraphBuilder COM object */
            m_graph = new FilterGraphNoThread() as IGraphBuilder;

            if (m_graph == null)
                throw new Exception("Could not create a graph");


            /* Add our prefered audio renderer */
            InsertAudioRenderer(AudioRenderer);

            var filterGraph = m_graph as IFilterGraph2;

            if (filterGraph == null)
                throw new Exception("Could not QueryInterface for the IFilterGraph2");

            IBaseFilter renderer = CreateVideoMixingRenderer9(m_graph, 1);                                

            IBaseFilter sourceFilter;

            /* Have DirectShow find the correct source filter for the Uri */
            var hr = filterGraph.AddSourceFilter(fileSource, fileSource, out sourceFilter);
            DsError.ThrowExceptionForHR(hr);

            /* We will want to enum all the pins on the source filter */
            IEnumPins pinEnum;

            hr = sourceFilter.EnumPins(out pinEnum);
            DsError.ThrowExceptionForHR(hr);

            IntPtr fetched = IntPtr.Zero;
            IPin[] pins = { null };

            /* Counter for how many pins successfully rendered */
            int pinsRendered = 0;                

            m_sampleGrabber = (ISampleGrabber)new SampleGrabber();
            SetupSampleGrabber(m_sampleGrabber);
            hr = m_graph.AddFilter(m_sampleGrabber as IBaseFilter, "SampleGrabber");
            DsError.ThrowExceptionForHR(hr);

            /* Loop over each pin of the source filter */
            while (pinEnum.Next(pins.Length, pins, fetched) == 0)
            {
                if (filterGraph.RenderEx(pins[0],
                                         AMRenderExFlags.RenderToExistingRenderers,
                                         IntPtr.Zero) >= 0)
                pinsRendered++;

                Marshal.ReleaseComObject(pins[0]);
            }

            Marshal.ReleaseComObject(pinEnum);
            Marshal.ReleaseComObject(sourceFilter);

            if (pinsRendered == 0)
                throw new Exception("Could not render any streams from the source Uri");

            /* Configure the graph in the base class */
            SetupFilterGraph(m_graph);

            HasVideo = true;
            /* Sets the NaturalVideoWidth/Height */
            //SetNativePixelSizes(renderer);
        }
        catch (Exception ex)
        {
            /* This exection will happen usually if the media does
             * not exist or could not open due to not having the
             * proper filters installed */
            FreeResources();

            /* Fire our failed event */
            InvokeMediaFailed(new MediaFailedEventArgs(ex.Message, ex));
        }

        InvokeMediaOpened();
    }

和:

 private void SetupSampleGrabber(ISampleGrabber sampleGrabber)
    {
        FrameCount = 0;
        var mediaType = new AMMediaType
        {
            majorType = MediaType.Video,
            subType = MediaSubType.RGB24,
            formatType = FormatType.VideoInfo
        };

        int hr = sampleGrabber.SetMediaType(mediaType);

        DsUtils.FreeAMMediaType(mediaType);
        DsError.ThrowExceptionForHR(hr);

        hr = sampleGrabber.SetCallback(this, 0);
        DsError.ThrowExceptionForHR(hr);
    }

我已經閱讀了一些說明.wmv或.asf格式是異步的東西。我試圖插入一個WMAsfReader來解碼哪個有效,但是一旦它進入VMR9就會產生相同的行為。另外,當我註釋掉 IBaseFilter renderer = CreateVideoMixingRenderer9(m_graph,1); 行並且有 filterGraph.Render(pins [0]); - 唯一的缺點是現在它在自己的Activemovie寡婦中呈現而不是我的控制,但是samplegrabber正常運行而沒有任何跳過。所以我認為這個bug存在於某個地方的VMR9/samplegrabbing中。

有幫助嗎?我是新來的。

最佳答案

一些解碼器將使用DXVA進行硬件加速。這是通過協商部分解碼的格式,並將該部分解碼的數據傳遞給渲染器以完成解碼和渲染來實現的。如果在解碼器和渲染器之間插入配置為RGB24的樣本采集器,則將禁用硬件加速。

我確信,這是問題的癥結所在。我擔心細節仍然有點模糊,例如當你使用默認的VMR-7時它的工作原理,但是當你使用VMR-9時它會失敗。我猜想解碼器正在嘗試使用dxva並在vmr-9情況下失敗,但是它有一個合理的純軟件備份,在vmr-7中運行良好。

我不熟悉WPFMediaKit,但我認為最簡單的解決方案是用顯式vmr-7創建替換顯式vmr-9創建。也就是說,如果解碼器僅使用vmr-7進行軟件操作,那麽請使用它並集中精力修復窗口重新定位問題。

轉載註明原文: Samplegrabber在AVI/MPEG文件上工作正常但與WMV不同