将DirectShow视频窗口附加到WPF控件

时间:2016-09-20 22:32:59

标签: c# wpf video directshow directshow.net

我正在使用DirectShow.NET为WPF创建网络摄像头控件。我已经成功创建了一个图表,可以从相机中获取视频以显示在我的屏幕上。但是,视频输出完全独立于正在创建的WPF控件。

我通过调用videoWindow.put_owner(hWnd)来设置视频窗口的所有者,其中hWnd是当前WPF窗口的窗口句柄。我使用WindowInteropHelper得到了那个窗口句柄。

这是主要例程:

public void CaptureVideo()
        {
            int hr = 0;
            IBaseFilter sourceFilter = null;

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

                sourceFilter = FindCaptureDevice();

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

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

                Marshal.ReleaseComObject(sourceFilter);

                SetupVideoWindow();

                hr = this.mediaControl.Run();
                DsError.ThrowExceptionForHR(hr);
            }
            catch
            {
                Console.WriteLine("An unrecoverable DirectShow error has occurred.");
            }
        }

SetupVideoWindow()的代码:

public void SetupVideoWindow()
        {
            int hr = 0;

            Window window = Window.GetWindow(this);
            var wih = new WindowInteropHelper(window);
            IntPtr hWnd = wih.Handle;

            hr = this.videoWindow.put_Owner(hWnd);
            DsError.ThrowExceptionForHR(hr);

            hr = this.videoWindow.put_WindowStyle(DirectShowLib.WindowStyle.Child | DirectShowLib.WindowStyle.ClipChildren);
            DsError.ThrowExceptionForHR(hr);

            this.videoWindow.SetWindowPosition(0, 0, (int)this.Width, (int)this.Height);

            hr = this.videoWindow.put_Visible(OABool.True);
            DsError.ThrowExceptionForHR(hr);
        }

以下是正在发生的事情的图像: DirectShow.NET Video Window and WPF MainWindow Control

2 个答案:

答案 0 :(得分:2)

特别是在窗口模式下运行的视频渲染器(同样适用于无窗口)要求您提供有效的HWND窗口句柄,以便视频可以与标准UI准确集成。您的SetupVideoWindow代码段正在准确初始化视频"作为子控件"。

WPF是一种新的UI概念,它不需要为每个UI控件创建窗口句柄,并且没有明确的直接属性来请求句柄以便传递给VMR初始化。因此,除了有效句柄之外,正确使用的WindowInteropHelper在实际分配时才可用,这不是表单构造函数。

使用零句柄指示视频渲染器将视频发送到桌面窗口,您所看到的行为是可预期且易于理解的。

您需要使用调试器检查句柄值,如果它为零,则将配置代码移动到表单构造的稍后阶段。设置时非零有效窗口句柄应将视频放置到位。

答案 1 :(得分:0)

据我记忆,DirectShow使用直接视频内存访问在屏幕上显示内容以获得最佳性能,因此this.videoWindow.SetWindowPosition(0, 0, (int)this.Width, (int)this.Height);很可能需要在屏幕坐标中。

即。你需要在屏幕上获取托管WPF窗口的位置和它的大小(使用WinApi),并传递给SetWindowPosition方法。当窗口移动/调整大小时,每次都这样做。

很抱歉答案不完整(没有提供确切的代码来解决问题),因为我多年前在C ++中使用WinApi完成了这项工作。