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

[与此页面关联的功能 DirectShow 是旧版功能。 它已被 MediaPlayerIMFMediaEngineMedia Foundation 中的音频/视频捕获所取代。 这些功能已针对Windows 10和Windows 11进行了优化。 Microsoft 强烈建议新代码尽可能在 Media Foundation 中使用 MediaPlayerIMFMediaEngine音频/视频捕获 ,而不是 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 混合模式