IVideoWindow 在directshow采集链路中的使用

dshow中一个完整采集链路一般如下:

Capture Device----->SampleGraber ------>Render

如果只要采集原始数据可以不用渲染链路那就如下:

Capture Device----->SampleGraber ------>Null Render

在很多dshow的demo中遇到过很多关于设置窗体的步骤,也就是标题 IVideoWindow 的设置。

以前没太注意过这个设置,看到别人的demo里有这个设置也就加上了,代码如下:

if (FAILED(graph_->QueryInterface(IID_IVideoWindow, (void **)&active_video_window_)))
        {
        return -1;
        }


        if (active_video_window_)
        {
        if (FAILED(active_video_window_->put_AutoShow(OAFALSE)))
        {
        return -1;
        }

上面的代码作用是吧渲染窗体隐藏,如果不隐藏的话,在连接整个链路运行的时候会自动弹出一个渲染窗体(如果上面的链路有Render filter)

后来对这一块代码仔细研究了一下发现如果我只是单纯的采集摄像头原始数据的话也就不需要设置隐藏窗体这一步骤了

所以后来就把这一块代码注释了。

再后来再一次测试使用 graph_->Render 智能连接的时候出现了问题。

使用graph_->Render 的话就需要吧上面的 NULL Render 废弃掉 链路如下:

Capture Device----->SampleGraber -----graph_->Render---->?

让Graph 去智能连接下面的链路的话,智能连接一般不会去给你连接一个Null Render 因为它不知道你是否想预览数据。

一般情况下使用filter 的智能连接 是不太透明的,在程序当中尽量避免使用智能连接,当然这种情况也有例外的情况比如:

virtual HRESULT STDMETHODCALLTYPE RenderStream( 
            /* [annotation][in] */ 
            _In_opt_  const GUID *pCategory,
            /* [in] */ const GUID *pType,
            /* [in] */ IUnknown *pSource,
            /* [in] */ IBaseFilter *pfCompressor,
            /* [in] */ IBaseFilter *pfRenderer) = 0;

RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video, A, B,C);

其中A,B,C 不为NULL 链路:----A------------B---------------------C----

如果上面这种指定filter的智能连接是可以使用的,因为目标比较明确,而且还省略了去获取IPin 的步骤让Graph 去自动帮你选择。

 

------------------------------------------

继续说上面的graph_->Render 这种用法如果使用了很大可能在闭合链路的时候graph 给你连接的链路如下:

Capture Device----->SampleGraber ------>Render

而这个时候就需要 标题 IVideoWindow 的设置,如果不设置的话,在run之后会自动弹出预览窗口(因为闭合链路的时候graph 连接的是一个 Render Filter )

从这个现象也就能明白 IVideoWindow 作用了。

总结有点乱,大致意思就是如果你使用的智能连接链路 那就需要注意一下 IVideoWindow  

参考:https://docs.microsoft.com/zh-cn/windows/desktop/DirectShow/combining-video-capture-and-preview

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
DirectShow是一个Microsoft Windows平台上的多媒体框架,用于播放和处理音频和视频文件。它提供了一个基于图形的编程模型,可以使用该模型构建复杂的多媒体处理应用程序。 以下是使用DirectShow播放视频的一些步骤: 1. 创建一个DirectShow的GraphBuilder对象,该对象用于构建多媒体处理图形。 2. 使用GraphBuilder对象的RenderFile方法来加载视频文件并将其渲染到视频窗口。 3. 创建一个视频窗口,该窗口用于显示视频。 4. 创建一个事件循环,该循环用于处理DirectShow的各种事件。 5. 在事件循环,处理DirectShow的各种事件,例如播放、暂停、停止视频等。 6. 最后,在程序退出时,释放DirectShow对象和资源。 下面是一个使用DirectShow播放视频的示例代码: ``` #include <windows.h> #include <dshow.h> #pragma comment(lib, "strmiids.lib") int main() { // 初始化COM库 CoInitialize(NULL); // 创建GraphBuilder对象 IGraphBuilder* pGraphBuilder = NULL; CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void**)&pGraphBuilder); // 加载视频文件并渲染到视频窗口 WCHAR* szFile = L"test.avi"; pGraphBuilder->RenderFile(szFile, NULL); // 创建视频窗口 HWND hWnd = CreateWindow(L"Static", L"Video", WS_OVERLAPPEDWINDOW, 0, 0, 640, 480, NULL, NULL, NULL, NULL); // 获取视频窗口的接口指针 IVideoWindow* pVideoWindow = NULL; pGraphBuilder->QueryInterface(IID_IVideoWindow, (void**)&pVideoWindow); // 设置视频窗口的位置和大小 pVideoWindow->put_Owner((OAHWND)hWnd); pVideoWindow->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN); pVideoWindow->put_MessageDrain((OAHWND)hWnd); pVideoWindow->SetWindowPosition(0, 0, 640, 480); // 播放视频 IMediaControl* pMediaControl = NULL; pGraphBuilder->QueryInterface(IID_IMediaControl, (void**)&pMediaControl); pMediaControl->Run(); // 创建事件循环 MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } // 停止播放并释放资源 pMediaControl->Stop(); pMediaControl->Release(); pVideoWindow->put_Visible(OAFALSE); pVideoWindow->put_Owner(NULL); pVideoWindow->Release(); pGraphBuilder->Release(); CoUninitialize(); return 0; } ``` 注意:上述示例代码的视频窗口使用Windows API的CreateWindow函数创建,因此需要包含Windows.h头文件。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值