视频叠加快照





0/5 (0投票)
使用 DirectShow 截取视频叠加的快照
引言
这个项目将向开发者展示如何使用 DirectShow 截取视频播放的屏幕截图,并将图像转储到文件夹中。函数“InitWindowlessVMR
”是从 MSDN 摘取的(我没有理由重写它)。
背景
我们都遇到过使用 WMP(在 Windows XP 中)播放视频时截取屏幕截图的问题,这可能会有所帮助。原因是视频播放使用叠加方法。(它绕过了 Windows 标准渲染方法 (GDI),这就是为什么“Print Screen”键不起作用的原因。)
Using the Code
请将代码与文档一起使用。我们首先创建对象:IGraphBuilder
,我们使用 CComPtr
,它可以省去释放指针的麻烦(并为我们做其他一些智能操作)。
CComPtr<IGraphBuilder> pGraph=NULL;
CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
IID_IGraphBuilder, (void **)&pGraph);
然后我们需要使用 CreateWindow
创建一个窗口(无需对此进行解释)。我们必须将对象设置为无窗口控件,并将视频渲染目标指向它。这通过调用“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 或“D3DXSaveTextureToFile
”支持的任何其他格式。DX9 速度快,并且是一种非常高效的图形操作方法(尽管我的代码没有通过在函数作用域之外创建 DX9 对象来优化,从而最大限度地减少 DX9 创建调用)。
请参阅附带的代码。
请注意,我动态创建一个纹理对象,然后将其保存到文件。
hr=D3DXCreateTextureFromFileInMemory(pd3dDevice,pb,d,&pTexture_Movie);
D3DXSaveTextureToFile(_bstr_t("asif.bmp"),D3DXIFF_BMP ,pTexture_Movie,0);
关注点
通过此方法,我们学习了一些 DirectShow 和一点 DirectX9。我们可以使用 DX10、DX11 接口执行相同的操作(但那样会使其成为仅适用于 Windows Vista/7 的代码)。
对于那些编写 DirectX9/10/11 代码的人来说,您可以通过在游戏引擎中使用电影纹理来尝试更酷的东西。
历史
- 2010 年 8 月 10 日:初始发布