在复合图像上显示应用提供的位图

[与此页面关联的功能(DirectShow)是一项旧功能。 它已被 MediaPlayerIMFMediaEngine取代,并在媒体基金会 音频/视频捕获。 这些功能已针对 Windows 10 和 Windows 11 进行了优化。 Microsoft强烈建议新代码尽可能使用 MediaPlayerIMFMediaEngineMedia Foundation 中的音频/视频捕获,而不是 DirectShow。 Microsoft建议重写使用旧 API 的现有代码,以尽可能使用新 API。]

应用程序可以使用 VMR 的混合模式在视频矩形中部分或完全显示 alpha 混合通道徽标、用户界面或播发。 由于混合由图形处理器在硬件中执行,因此对视频流的播放性能的影响最小,并且没有可检测到的闪烁或撕裂项目。 应用程序可以根据需要更改显示的图像。 应注意的是,仅当 DirectShow 筛选器图处于运行状态时,更改才会反映在屏幕上。

VMR 使用其混音器组件将位图覆盖到复合图像上。 使用 VMR-7 时,应用程序必须强制 VMR 加载其混音器,即使只有单个视频流也是如此。 VMR-9 不需要这样做,因为它默认加载其混音器。

若要将静态位图图像与视频流混合,应用程序将创建 VMR 并将其添加到图形,然后调用 IVMRFilterConfig::SetNumberOfStreams。 传递给此函数的值标识 VMR 应创建的输入引脚数。 应用程序可以指定介于 1 和 MAX_MIXER_STREAMS 之间的任何值;如果应用程序只打算显示单个视频流,则指定值 1 有效。 尽管 VMR-7 默认具有单个输入引脚,但必须调用此方法以强制加载其混音器组件。 (VMR-9 加载其混音器,并默认设置四个引脚。

若要设置位图,请使用 VMR-7 上的 IVMRMixerBitmap 接口或 VMR-9 上的 IVMRMixerBitmap9 接口。

位图可以通过 GDI 设备上下文(hDC)的句柄或 DirectDraw Surface 接口指定。 如果应用程序希望图像包含嵌入的 alpha 信息(也称为每像素 alpha),则必须将图像数据放置在 DirectDraw Surface 接口中。 这是因为目前无法使用 GDI 设备上下文放置每像素 alpha 信息。 DirectDraw 图面必须是 RGB32 或 ARGB32,最好是系统内存图面。 表面尺寸不必为 2 的幂。

VMR 允许应用程序指定映像的位置和总体透明度值。 以下代码演示如何将映像数据向下传递到 VMR 进行后续混合:

HRESULT BlendApplicationImage( 
  HWND hwndApp,
  IVMRWindowlessControl* pWc,
  HBITMAP hbm
)
{
    LONG cx, cy;
    HRESULT hr;
    hr = pWc->GetNativeVideoSize(&cx, &cy, NULL, NULL);
    if (FAILED(hr))
        return hr;
    
    HDC hdc = GetDC(hwndApp);
    if (hdc == NULL)
    {
        return E_FAIL;
    }
    
    HDC hdcBmp = CreateCompatibleDC(hdc);
    ReleaseDC(hwndApp, hdc);
    
    if (hdcBmp == NULL)
    {
        return E_FAIL;
    }
    
    BITMAP bm;
    if (0 == GetObject(hbm, sizeof(bm), &bm))
    {
        DeleteDC(hdcBmp);
        return E_FAIL;
    }
    
    HBITMAP hbmOld = (HBITMAP)SelectObject(hdcBmp, hbm);
    if (hbmOld == 0)
    {
        DeleteDC(hdcBmp);
        return E_FAIL;
    }
    
    VMRALPHABITMAP bmpInfo;
    ZeroMemory(&bmpInfo, sizeof(bmpInfo) );
    bmpInfo.dwFlags = VMRBITMAP_HDC;
    bmpInfo.hdc = hdcBmp;
    
    // Show the entire bitmap in the top-left corner of the video image.
    SetRect(&bmpInfo.rSrc, 0, 0, bm.bmWidth, bm.bmHeight);
    bmpInfo.rDest.left = 0.f;
    bmpInfo.rDest.top = 0.f;
    bmpInfo.rDest.right = (float)bm.bmWidth / (float)cx;
    bmpInfo.rDest.bottom = (float)bm.bmHeight / (float)cy;
    
    // Set the transparency value (1.0 is opaque, 0.0 is transparent).
    bmpInfo.fAlpha = 0.2f;
    
    IVMRMixerBitmap* pBmp;
    hr = pWc->QueryInterface(IID_IVMRMixerBitmap, (LPVOID *)&pBmp);
    if (SUCCEEDED(hr)) 
    {
        pBmp->SetAlphaBitmap(&bmpInfo);
        pBmp->Release();
    }
    
    DeleteObject(SelectObject(hdcBmp, hbmOld));
    DeleteDC(hdcBmp);
    return hr;
}

本主题中讨论的概念在 VMRPlayer 示例 示例应用程序中演示。

使用位图图像创建简单动画

若要创建简单的动画位图徽标,请将所有位图“帧”放入单个图像中,如下图所示。

vmr 映像条带

最初使用 IVMRMixerBitmap::SetAlphaBitmap设置位图时,如果位图位于 HDC 中,请将 VMRALPHABITMAP 结构的 rSrc 字段设置为指定 HDC 中整个位图的大小。 结构 顶部 和左 成员设置为 0,底部 成员是位图的宽度和高度。 如果位图位于 DirectDraw 图面中,则图面的大小已知,因此无需在此方法中指定 rSrc。

调用 IVMRMixerBitmap::UpdateAlphaBitmapParameters时,请使用 HDC 和 DirectDraw 位图的 rSrc 成员来指定要显示的图像中的特定帧或矩形,并在 dwFlags 成员中设置 VMRBITMAP_SRCRECT 标志。

使用 VMR 混合模式