在运行视频时显示动画图像






3.38/5 (10投票s)
2006 年 9 月 9 日
5分钟阅读

295814

5104
一个简单的类,它隐藏了 DirectShow 的所有复杂性,并有助于在播放的视频上显示图像,您还可以控制图像的透明度。简要描述了如何完成所有这些操作。
引言
在播放的视频上显示任何内容似乎都不是一项简单的任务。在这篇文章中,我尝试在运行的视频上显示一张图片。不是静态图像,而在这篇更新的文章中,它会让图像动起来。
更新
我更新了我的 cVideo
类以显示动画图像。不仅如此,您现在还可以控制该图像的透明度级别。请参阅下面的“深入了解 DirectShow”。
背景
在视频上显示图片需要对 DirectShow 有一些了解,以及 如何构建过滤器图。并且,在图表中添加自定义过滤器,如 VMR9(视频混合渲染器)。这个 VMR9 是关键,它是允许我们在视频上显示图片的渲染器。
构建环境
所有希望使用 DirectShow 的应用程序都必须包含头文件 Dshow.h,并使用库 Strmiids.lib。
深入了解 DirectShow
在视频上显示图像的基本动力是接口 IVMRMixerBitmap9
。基本上,这个接口只有三个成员函数。
GetAlphaBitmapParameters()
SetAlphaBitmap()
UpdateAlphaBitmapParameters()
另一个基本内容是结构体 VMR9AlphaBitmap
。它基本上用于在函数之间传递数据。下面讨论的 VMR9AlphaBitmap
的一些成员如下:
DWORD dwFlags; HDC hdc; RECT rSrc; VMR9NormalizedRect rDest; FLOAT fAlpha; COLORREF clrSrcKey;
现在的问题是如何使用它们。让我们看看如何首次初始化。首先,我们需要知道
- 我们已选择(
SelectObject
)图像的设备上下文句柄hDC
, - 另一个重要的事情是图像的尺寸,
- 第三个需要的是在视频上显示图像的位置(一个矩形),
- 透明度级别,它告诉图像在视频上会有多透明。
- 色键,如果您想隐藏图像的背景色;将其设置为背景色;不一定只隐藏背景,您可以给出任何颜色值,给定的颜色将在视频上显示为透明,
- 最后,我们填写的值的设置标志。
现在一切就绪,只需调用 SetAlphaBitmap()
。
基本初始化
首先,我们需要创建过滤器图管理器的一个对象(过滤器图管理器用于控制过滤器和数据流)。这个过程是通过调用 CoCreateInstance()
来完成的。这样,我们创建了过滤器图管理器的一个对象,并获取了 IGraphBuilder
接口的指针。然后,该接口用于构建自定义过滤器图(过滤器图是播放媒体文件的完整 DirectShow 过滤器集)。
CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
IID_IGraphBuilder, (void **)&pGraph);
创建过滤器图管理器后,另一个重要问题是将 VMR9 添加到过滤器图中。但在添加之前,我们需要创建它,创建后,我们将该过滤器(VMR9)添加到我们的过滤器图中。CoCreateInstance(CLSID_VideoMixingRenderer9, NULL, CLSCTX_INPROC, IID_IBaseFilter, (void**)&pVmr); pGraph->AddFilter(pVmr, L"Video");现在我们需要根据我们的自定义需求配置 VMR9。例如,在这里,我们将其设置为在我们提供的窗口中显示视频,设置视频位置。
pVmr->QueryInterface(IID_IVMRFilterConfig9, (void**)&pConfig); pConfig->SetRenderingMode(VMR9Mode_Windowless); pVmr->QueryInterface(IID_IVMRWindowlessControl9, (void**)&pWC); pWC->SetVideoPosition(NULL, pRect); pWC->SetVideoClippingWindow(pParentWnd->m_hWnd);
以下 IVMRMixerBitmap9
是提供我们在视频上显示图像功能的接口。而 bmpInfo
是一个结构体,它保存有关我们要显示在视频上的图像的数据。在这里,我们首次将其初始化为全零。
pWC->QueryInterface(IID_IVMRMixerBitmap9, (LPVOID *)&pBmp);
ZeroMemory(&bmpInfo, sizeof(bmpInfo) );
以下是在任何 DirectShow 应用程序中都非常必要的接口,因为它们提供了通过 IMediaControl
控制数据流的功能,并向我们的应用程序通知发生的任何重要事件。例如,文件结束,提供此功能的接口是 IMediaEventEx
。通过此接口,我们需要设置要通知的窗口。另一个重要的接口是 IMediaSeeking
,它提供了在媒体文件中进行搜索的功能。
pGraph->QueryInterface(IID_IMediaControl, (void **)&pMC); pGraph->QueryInterface(IID_IMediaEventEx, (void **)&pME); pME->SetNotifyWindow ( ( OAHWND ) pParentWnd->GetParent()->m_hWnd, WM_GRAPHNOTIFY, 0 ) ; pGraph->QueryInterface(IID_IMediaSeeking, (void **)&pMS);现在创建自定义过滤器图。然后运行它。之后,视频将在我们给定的窗口中开始播放。
pGraph->RenderFile(mFileToPlay, NULL); pMC->Run();
显示图像
我们需要了解的包括图像被选择的设备上下文句柄,图像大小,图像背景的颜色值,如果您想使图像背景透明(称为色键)。现在让我们开始。首先,获取要在其上播放视频的窗口的设备上下文。现在我们需要另一个设备上下文,它必须与视频窗口设备上下文兼容,然后将所需的图像选择在该设备上下文中。
CDC * pdc = GetDC(); CDC mCompatibleDC; mCompatibleDC.CreateCompatibleDC(pdc); mCompatibleDC.SelectObject(hBitmap); CRect reSrc(0,0,mBitmapWidth,mBitmapHeight);
现在,实际的图像显示工作开始。使用所需值初始化 bmpInfo
结构体,例如设置标志。设置设备上下文和源矩形,即图像大小。
bmpInfo.dwFlags |= VMRBITMAP_HDC;
bmpInfo.hdc = pDC->m_hDC;
bmpInfo.rSrc = rectSize; // Size of the image
设置目标矩形,即要在屏幕上显示图像的区域。
// rDest specifies the destination rectangle in composition space (0.0f to 1.0f) bmpInfo.rDest.right = 1.0f; bmpInfo.rDest.left = 1.0f - 0.3; bmpInfo.rDest.top =1.0 - 0.3; bmpInfo.rDest.bottom = 1.0f;设置透明度级别。
// Set the transparency value (1.0 is opaque, 0.0 is transparent). bmpInfo.fAlpha = 0.0;
设置色键值及其标志。这里设置为绿色。这意味着图像上的任何绿色都将被视为透明。
// Set the COLORREF so that the bitmap outline will be transparent bmpInfo.dwFlags |= VMRBITMAP_SRCCOLORKEY; bmpInfo.clrSrcKey = RGB(0, 255, 0); pBmp->SetAlphaBitmap(&bmpInfo);
Using the Code
我尽量保持事情简单。我构建了一个名为 cVideo
的类。这个类隐藏了所有复杂性。您只需调用这个类的各种方法,其余所有事情都由这个类处理。
这个类有以下方法:
void InitInterfaces(BSTR mFileToPlay, CWnd* pParentWnd, CRect* pRect); void Clean(void); void Play(void); void ShowImage(CDC* pDC, CRect rectSize); void HideImage(void); void SetTransparency( int tansparencyLevel ) void Animate();
InitInterfaces()
隐藏了 DirectShow 图构建的所有奥秘。play()
,顾名思义,播放一个文件。ShowImage()
只提供您选择要显示的图片的设备上下文指针(CDC* pDC
)。HideImage()
只隐藏显示的图像。SetTransparency(int transparencyLevel)
控制图像在视频上的透明度级别。Animate()
更新显示图像的矩形,模拟动画。- 最后,
Clean()
释放 DirectShow 接口。
历史
- 更新于 2006 年 9 月 16 日 - 现在所有内容都清晰地描述了。
- 更新于 2006 年 9 月 15 日 - 添加了动画图像和透明度控制。
- 2006 年 9 月 9 日 - 初始版本。