アプリケーションが提供するビットマップを合成イメージ上に表示する
アプリケーションは VMR の "ミキサービットマップ" 機能を使い、アルファ ブレンドされたチャンネル ロゴ、ユーザー インターフェイス、または広告の一部か全体をビデオ矩形内に表示できる。ブレンディングはグラフィック プロセッサによりハードウェアで実行されるため、ビデオ ストリームの再生のパフォーマンスはほとんど影響を受けず、検出可能なフリッカーや予期せぬ表示は発生しない。アプリケーションは、表示するイメージを必要に応じて何回でも変更できる。変更が画面に反映されるのは、DirectShow フィルタ グラフが実行状態になっているときである点に注意すること。
VMR はミキサー コンポーネントを使ってビットマップを合成イメージにオーバーレイする。VMR-7 の場合、ビデオ ストリームが 1 つしかないときでも、アプリケーションは VMR のミキサーをロードする必要がある。VMR-9 はデフォルトでミキサーをロードするため、このような処理は必要ない。
静的ビットマップ イメージをビデオ ストリームとブレンドするには、アプリケーションは VMR を作成してグラフに追加し、IVMRFilterConfig::SetNumberOfStreams を呼び出す。この関数に渡す値は、VMR が作成する入力ピンの数を示す。アプリケーションは 1 から MAX_MIXER_STREAMS までの任意の値を指定できる。1 つのビデオ ストリームしか表示しない場合は、値 1 を指定しても有効である。VMR-7 にはデフォルトで 1 つの入力ピンがあるが、ミキサー コンポーネントを強制的にロードするため、このメソッドを呼び出す必要がある。(VMR-9 はデフォルトでミキサーをロードし、4 つのピンをセットアップする。)
ビットマップは GDI デバイス コンテキストへのハンドル (hDC) または DirectDraw サーフェイス インターフェイスにより指定できる。アプリケーションがイメージに埋め込みアルファ情報 (ピクセル単位アルファとも呼ばれる) を入れる必要がある場合、イメージ データは DirectDraw サーフェイス インターフェイスに置かなければならない。現在は、GDI デバイス コンテキストを使ってピクセル単位のアルファ情報を配置できないためである。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;
// ビデオ イメージの左上角にビットマップ全体を表示する。
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;
// 透過値を設定する (1.0 は不透明、0.0 は透明)。
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 サンプル サンプル アプリケーションに示されている。