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

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

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.38/5 (10投票s)

2006 年 9 月 9 日

5分钟阅读

viewsIcon

295814

downloadIcon

5104

一个简单的类,它隐藏了 DirectShow 的所有复杂性,并有助于在播放的视频上显示图像,您还可以控制图像的透明度。简要描述了如何完成所有这些操作。

Sample Image - VideoPicture.jpg

引言

在播放的视频上显示任何内容似乎都不是一项简单的任务。在这篇文章中,我尝试在运行的视频上显示一张图片。不是静态图像,而在这篇更新的文章中,它会让图像动起来。

更新

我更新了我的 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 日 - 初始版本。
© . All rights reserved.