1

我一直在使用最新版本的WPFMediaKit。我要做的是编写一个示例应用程序,该应用程序将使用 Samplegrabber 来捕获视频文件的视频帧,以便我可以将它们作为单独的位图。

到目前为止,在构建和渲染我的图表时,我对以下代码很幸运。但是,当我使用此代码播放 .wmv 视频文件时,当附加了 samplegrabber 时,它会播放跳跃或断断续续的。如果我注释掉添加 samplegrabber 过滤器的行,它可以正常工作。同样,它可以与 AVI/MPEG 等正确使用采样采集器。

 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 正常运行并且没有任何跳过。所以我认为这个错误是在 VMR9 / samplegrabbing 某处。

有什么帮助吗?我是新来的。

4

2 回答 2

1

一些解码器将使用 DXVA 进行硬件加速。这是通过协商一个部分解码的格式,并将这个部分解码的数据传递给渲染器完成解码和渲染来实现的。如果在解码器和渲染器之间插入配置为 RGB24 的采样采集器,您将禁用硬件加速。

我敢肯定,这就是问题的症结所在。恐怕细节仍然有点模糊,例如为什么它在使用默认 VMR-7 时有效,但在使用 VMR-9 时失败。我猜想解码器尝试使用 dxva 并在 vmr-9 的情况下失败了,但有一个合理的纯软件备份,在 vmr-7 中运行良好。

我不熟悉 WPFMediaKit,但我认为最简单的解决方案是将显式 vmr-9 创建替换为显式 vmr-7 创建。也就是说,如果解码器仅与 vmr-7 一起使用软件,则使用它并专注于修复窗口重父问题。

于 2010-04-16T09:07:12.983 回答
0

它最终得到了我发布的代码(我从 Jeremiah Morrill 的 WPFMediakit 源代码中对其本身进行了相当无耻的轻微修改)实际上足以呈现 .WMV 文件并被样本抓取。

似乎波动与通过 VS 调试器或 VS2008 本身运行有关。在可视化编辑器中处理 XAML 一段时间后,然后运行应用程序,我将引入这种断断续续的行为。关闭 VS2008 似乎可以补救。:P

所以没有太多的答案,但至少有一个(烦人的 - 重新启动 VS2008)修复它出现时。

于 2010-04-16T13:28:54.660 回答