IVMRWindowlessControl9 未呈现到父 WPF window

IVMRWindowlessControl9 not being rendered into parent WPF window

我正在使用 DirectShow.NET 创建网络摄像头控件。我想将摄像机的视频渲染成 WPF window。目前正在发生的事情是 IVMRWindowlessControl9 似乎没有进入 windowless 模式并且没有成为我指定的 window 的父级,即使我是调用适当的方法。

为什么没有调用这些方法?还有什么我没做的吗?

下面是相关代码的片段:

IGraphBuilder graphBuilder = (IGraphBuilder) new FilterGraph();
ICaptureGraphBuilder2 captureGraphBuilder = (ICaptureGraphBuilder2)new CaptureGraphBuilder2();            
IMediaControl mediaControl = (IMediaControl) this.graphBuilder;
IBaseFilter renderFilter = (IBaseFilter) new VideoMixingRenderer9();

hr = this.captureGraphBuilder.SetFiltergraph(this.graphBuilder);
DsError.ThrowExceptionForHR(hr);

IBaseFilter sourceFilter = FindCaptureDevice();

hr = this.graphBuilder.AddFilter(sourceFilter, "Video Capture");                        
DsError.ThrowExceptionForHR(hr);

SetCaptureResolution();

IVMRFilterConfig9 filterConfig = (IVMRFilterConfig9)renderFilter;

hr = filterConfig.SetNumberOfStreams(1);
DsError.ThrowExceptionForHR(hr);

hr = filterConfig.SetRenderingMode(VMR9Mode.Windowless);
DsError.ThrowExceptionForHR(hr);

windowlessControl = (IVMRWindowlessControl9)renderFilter;

hr = this.graphBuilder.AddFilter(renderFilter, "Video Capture");
DsError.ThrowExceptionForHR(hr);

Window window = Window.GetWindow(this);
var wih = new WindowInteropHelper(window);
IntPtr hWnd = wih.Handle;
hr = windowlessControl.SetVideoClippingWindow(hWnd);
DsError.ThrowExceptionForHR(hr);

hr = windowlessControl.SetAspectRatioMode(VMR9AspectRatioMode.LetterBox);
DsError.ThrowExceptionForHR(hr);

hr = this.captureGraphBuilder.RenderStream(PinCategory.Capture, MediaType.Video, sourceFilter, null, null);
DsError.ThrowExceptionForHR(hr);

Marshal.ReleaseComObject(sourceFilter);

hr = this.mediaControl.Run();
DsError.ThrowExceptionForHR(hr);

这是正在发生的事情的图像(我将背景设为绿色以便于查看):

这是过滤图的示意图:

要回答一个潜在的问题(因为我以前遇到过这个问题),是的,hWnd 正在获取 set/has 一个值 - 所以 windowlessControl 确实有一个指针到 window。

当您 运行 过滤器图时创建的弹出窗口 "ActiveMovie Window" 是视频渲染器过滤器插入管道的症状,并且 运行 在默认模式下未配置为其他 UI 的一部分:嵌入为 child window 等

你对图表的反转揭示了正在发生的事情:

您插入并设置了一个视频渲染器过滤器,然后 API 添加了另一个并连接到您的输入。虽然第一个嵌入到您的 UI 中,但它保持空闲状态,另一个将视频渲染到弹出窗口中。

给出问题的代码行是:

hr = this.captureGraphBuilder.RenderStream(PinCategory.Capture,
    MediaType.Video, sourceFilter, null, null);

问题是 quite typical 对于那些通过插入视频渲染器构建图形并期望它们被拾取和连接的人来说,特别是它 有时 工作等等代码片段可以在网上找到。

MSDN 说:

If the pSink parameter is NULL, the method tries to use a default renderer. For video it uses the Video Renderer, and for audio it uses the DirectSound Renderer.

该呼叫添加了另一个实例,您希望连接现有的实例。虽然 RenderStream 是一个强大的调用并且可以过滤魔法来连接事物,但很容易以错误的方式结束它。

如果您已有视频渲染器,则可以将其用作此调用中的接收器参数。或者,您可以避免执行 RenderStream 并逐步添加您需要的过滤器,以确保一切都按照您的期望构建。或者,另一种选择是 IFilterGraph2::RenderEx 使用 AM_RENDEREX_RENDERTOEXISTINGRENDERERS 标志调用:

...the method attempts to use renderers already in the filter graph. It will not add new renderers to the graph. (It will add intermediate transform filters, if needed.) For the method to succeed, the graph must contain the appropriate renderers, and they must have unconnected input pins.