65.9K
CodeProject 正在变化。 阅读更多。
Home

视频叠加快照

emptyStarIconemptyStarIconemptyStarIconemptyStarIconemptyStarIcon

0/5 (0投票)

2010 年 8 月 10 日

CPOL

2分钟阅读

viewsIcon

27410

downloadIcon

910

使用 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 日:初始发布
© . All rights reserved.