IVMRWindowlessControl9未呈现为父WPF窗口

时间:2016-09-23 17:46:16

标签: c# wpf video directshow directshow.net

我正在使用DirectShow.NET创建一个网络摄像头控件。我想将摄像机的视频渲染到WPF窗口中。目前正在发生的事情是,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

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

这是过滤器图表的图表: enter image description here

要回答一个潜在的问题(因为我以前遇到过这个问题),是的, walk(document.body); function walk(rootNode) { // Find all the text nodes in rootNode var walker = document.createTreeWalker( rootNode, NodeFilter.SHOW_TEXT, null, false ), node; // Modify each text node's value while (node = walker.nextNode()) { handleText(node); } } function handleText(textNode) { textNode.nodeValue = replaceText(textNode.nodeValue); } 正在设置/有一个值 - 所以windowlessControl确实有一个指向窗口的指针。

1 个答案:

答案 0 :(得分:1)

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

您的图形反转可以了解正在发生的事情:

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

提出问题的代码行是:

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

对于那些通过插入视频渲染器并期望拾取和连接它们来构建图形的人来说问题是quite typical,尤其是有时有效并且可能会找到此类代码段线上。

MSDN说:

  

如果pSink参数为NULL,则该方法尝试使用默认渲染器。 对于视频,它使用视频渲染器,对于音频,它使用DirectSound渲染器。

通话添加了另一个实例,您希望现有的实例连接起来。虽然RenderStream是一个强大的调用,并且过滤魔术来连接事物,但很容易让它以错误的方式完成某些事情。

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

  

...该方法尝试使用过滤器图形中已有的渲染器。 它不会向图表中添加新的渲染器。(如果需要,它将添加中间变换滤镜。)要使方法成功,图形必须包含相应的渲染器,并且它们必须具有未连接的输入引脚