directshow window
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
DirectShow显示视频:
l Video Renderer 过滤器. 该过滤器可用于所有的支持DirectX的平台,它对平台没有其它特殊的要求。可以是它,或GDI来显示视频。它是在WindowsXP之前操作系统的默认视频显示过滤器。
l Video Mixing Renderer Filter 7 (VMR-7). VMR-7可用于WindowsXP操作系统,并且是该系统下的默认视频显示过滤器。与老的视频显示过滤器相比,它具有一些更强大的性能,包括采用插件模式来控制DirectShow显示。
l Video Mixing Renderer Filter 9 (VMR-9). VMR-9是一个更新的视频混合显示过滤器,它采用了Direct3D来显示。它可用于所有的支持DirectX的平台。它不是默认的显示过滤器,因为它与其它的显示过滤器相比,对系统要求更高。
一般来说,在视频显示应用上,VMR-9是首选。因为,它使用了最新的图像API,并且提供了最好的性能。
窗体模式和非窗体模式
DirectShow视频显示可以选择在窗体模式或者非窗体模式下进行。
l 在窗体模式下,视频将创建一个它自己的窗体来显示。
l 在非窗体模式下,视频可以自己在你程序的一个窗口上显示,而不让视频自己区创建窗体来显示。
Video Renderer过滤器只支持窗体模式,VMR-7和VMR-9支持这两种模式。它们默认状态是窗体模式。
设置视频窗口
在窗体模式下,视频将创建一个窗口,然后在该窗口上显示视频。大多数情况下,你可能想要把该窗口绑定到你的应用程序中。通过使用IVideoWindow接口,可以设置视频窗口的类型和位置。
在开始播放前,在过滤器图表管理器中去查找IVideoWindow接口:
IVideoWindow *pVidWin = NULL;
pGraph->QueryInterface(IID_IVideoWindow, (void **)&g_pVidWin);
调用IVideoWindow::put_Owner方法去处理你应用程序的窗体。该方法提供了一个OAHWND 类型的变量,所以要把句柄转换为该类型:
pVidWin->put_Owner((OAHWND)hwnd);
调用IVideoWindow::Put_WindowStyle来改变视频窗体的类型:
pVidWin->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS);
WS_CHILD标志设置视频窗体为一个子窗体,WS_CLIPSIBLINGS标志可以防止视频窗体在另一个子窗体的客户区内显示视频。
调用IVideoWindow::SetWindowPosition方法可以视频窗口的相对于你应用程序的客户区的位置。该方法的参数带了一个RECT参数,用它去指定视频窗口的位置。下例,让视频窗口和它父窗体的客户区想匹配。
RECT grc;
GetClientRect(hwnd, &grc);
pVidWin->SetWindowPosition(0, 0, grc.right, grc.bottom);
通过在过滤器图表管理器上调用IBaseicVide:GetVideoSize方法可以得到视频本身的尺寸大小。你可以通过这些信息让视频保持正确的纵横比例。
在应用程序退出前,停止图表并重置视频窗口为NULL。否则,窗口消息可能被错误的发送给错误的窗口,从而导致错误发生,
pControl->Stop();
pVidWin->put_Visible(OAFALSE);
pVidWin->put_Owner(NULL);
使用非窗体模式
视频混合显示过滤器(VMR-7和VMR-9)都支持非窗体模式。这里将描述窗体模式和非窗体模式之间的不同,以及如何使用非模式窗体。
为了向后兼容已经在使用的应用程序,VMR默认的显示模式为窗体模式。在窗体模式中,视频创建一个它自己的窗体去显示视频。应用程序设置这个视频窗体为它的一个子窗体。这个单独存在的窗体会导致如下问题:
l 最严重的是,如果窗体的消息在线程间发送可能导致消息死锁。
l 过滤器图表管理器必须传递某些window消息,比如WM_PAINT,给视频显示器(Video Renderer)。这些对IvideoWIndow的操作必须是由过滤器图表管理器来完成,而不是视频显示器来完成,所以要靠过滤器图表管理器来纠正内部状态。
l 要视频窗体的鼠标或者键盘事件,应用程序必须建立一个“消息通道”,让视频窗口把消息传递给应用程序。
l 为了防止剪接的情况,视频窗体还必须拥有正确的窗口状态。
非窗体模式通过使用VMR直接在应用程序的客户区上画图来避免了上述的问题。它使用DirectDraw去剪接视频矩形。非窗体模式极大程度减少了死锁的偶然发生。同样,应用程序不必去设置视频自身创建的窗口和窗口的状态。事实上,当VRM使用窗体模式时,它也不使用IVideoWindow接口。
要使用非窗体模式,你必须明确地去配置VMR。你会发现配置工作非常灵活并且比窗体模式更容易。
在配置VMR 前应建立过滤器图表(Filter graph):
创建过滤器图表管理器(Filter Graph Manager)。
创建VMR并添加到过滤器图表中(filter graph)。
在VMR中调用IVMRFilterConfig::SetRenderingMode设置VMRMode_Windowless标识。
在VMR中调用IVMRWindowlessControl::SetVideoClippingWindow去指定视频将要显示的窗体句柄。
现在调用IGraphBuilder::RenderFile完成过滤器图表余下的工作。过滤器图表管理器将自动使用这个你添加到过滤器图表中的VMR实例。
下面代码显示了这些工作:
HRESULT InitWindowlessVMR( HWND hwndApp, // 视频窗体
IGraphBuilder* pGraph, // 过滤器图表指针
IVMRWindowlessControl** ppWc, // 接收VMR指针
)
{
if (!pGraph || !ppWc) return E_POINTER;
IBaseFilter* pVmr = NULL;
IVMRWindowlessControl* pWc = NULL;
// 创建VMR
HRESULT hr = CoCreateInstance(CLSID_VideoMixingRenderer, NULL,
CLSCTX_INPROC, IID_IBaseFilter, (void**)&pVmr);
if (FAILED(hr))
{