在Windows XP操作系统中,使用Windows Media Player播放视频时,经常会遇到需要截取视频画面的需求。然而,由于视频播放通常采用覆盖方式,绕过了Windows标准的渲染方法(GDI),导致传统的截屏方法(如Print Screen)无法直接使用。本文将介绍如何利用DirectShow和DirectX9技术,开发一个能够截取视频播放画面的工具。
DirectShow是一个用于多媒体数据流处理的COM库,而DirectX9则是微软推出的一套针对游戏和多媒体应用程序的编程接口。通过结合使用这两种技术,可以开发出功能强大的视频截图工具。
首先,需要创建一个IGraphBuilder对象,这是DirectShow中用于构建媒体数据流的核心接口。使用CComPtr来管理这个对象,这样可以避免手动释放指针的繁琐工作。
CComPtr<IGraphBuilder> pGraph = NULL;
CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void**)&pGraph);
接下来,需要创建一个窗口,并将视频渲染到这个窗口中。这需要调用InitWindowlessVMR函数,并将视频剪辑窗口设置为刚刚创建的窗口的句柄。
pWc->SetVideoClippingWindow(hwndApp);
然后,需要选择要截取屏幕截图的视频文件。
pGraph->RenderFile(L"MyMovie.avi", NULL);
为了控制视频播放,还需要创建IMediaControl接口的对象。如果需要跳转到特定的帧进行截图,还可以使用IMediaSeeking接口。
hr = pGraph->QueryInterface(IID_IMediaControl, (void**)&pControl);
hr = pGraph->QueryInterface(IID_IMediaSeeking, (void**)&pSeek);
使用pControl接口(IMediaControl类型)开始播放视频。
pControl->Run();
现在,来到了截取屏幕截图的部分。通过使用pSeek(IMediaSeeking类型)调整要截取屏幕截图的帧号,然后使用无窗口控制接口(通过调用InitWindowlessVMR获得)获取当前图像。
pWc->GetCurrentImage(&pb);
BITMAPINFOHEADER *pBMIH = (BITMAPINFOHEADER*) pb;
DWORD d = pBMIH->biSize + pBMIH->biSizeImage;
接下来,利用DirectX9将图像转换为BMP或其他格式。DirectX9在图形处理方面非常高效,尽管代码没有优化,以减少DirectX9对象的创建调用。
hr=D3DXCreateTextureFromFileInMemory(pd3dDevice,pb,d,&pTexture_Movie);
D3DXSaveTextureToFile(_bstr_t("asif.bmp"),D3DXIFF_BMP ,pTexture_Movie,0);
通过这个过程,不仅学习了DirectShow和DirectX9的基础知识,还可以尝试使用DirectX10、DirectX11等更高级的接口,但这将限制代码只能在Windows Vista/7及以上版本上运行。
本文介绍的技术要点包括: