Media Foundation での DXVA 2.0 のサポート

このトピックでは、Microsoft Direct3D 9 を使用して Media Foundation 変換 (MFT) で DirectX ビデオ アクセラレーション (DXVA) 2.0 をサポートする方法について具体的に説明します。具体的には、トポロジ ローダーによって仲介されるデコーダーとビデオ レンダラーの間の通信について説明します。 このトピックでは、DXVA デコードを実装する方法については説明しません。

このトピックの残りの部分では、 デコーダー という用語は、圧縮されたビデオを受信し、圧縮されていないビデオを出力するデコーダー MFT を指します。 デコーダー デバイスという用語は、グラフィックス ドライバーによって実装されるハードウェア ビデオ アクセラレータを指します。

ヒント

Microsoft Direct3D 11 ビデオ デコードの詳細については、「 Media Foundation での Direct3D 11 ビデオ デコードのサポート」を参照してください。

 

Note

Windows ストア アプリでは、Direct3D 11 を使用する必要があります。

 

Media Foundation で DXVA 2.0 をサポートするためにデコーダーが実行する必要がある基本的な手順を次に示します。

  1. Direct3D 9 デバイスへのハンドルを開きます。
  2. DXVA デコーダー構成を見つけます。
  3. 圧縮されていないバッファーを割り当てます。
  4. フレームをデコードします。

これらの手順については、このトピックの残りの部分で詳しく説明します。

Direct3D デバイス ハンドルを開く

MFT は、Microsoft Direct3D デバイス マネージャーを使用して、Direct3D 9 デバイスへのハンドルを取得します。 デバイス ハンドルを開くには、次の手順に従います。

  1. 値 TRUE を 使用してMF_SA_D3D_AWARE 属性を公開 します。 トポロジ ローダーは、 IMFTransform::GetAttributes を呼び出してこの属性を照会します。 属性を TRUE に設定すると、MFT で DXVA がサポートされていることをトポロジ ローダーに通知します。
  2. フォーマット ネゴシエーションが開始されると、トポロジ ローダーは、MFT_MESSAGE_SET_D3D_MANAGER メッセージを使用して IMFTransform::P rocessMessage を呼び出します。 ulParam パラメーターは、ビデオ レンダラーの Direct3D デバイス マネージャーへの IUnknown ポインターです。 IDirect3DDeviceManager9 インターフェイスに対してこのポインターのクエリを実行します。
  3. IDirect3DDeviceManager9::OpenDeviceHandle を呼び出して、レンダラーの Direct3D デバイスへのハンドルを取得します。
  4. IDirect3DDeviceManager9::GetVideoService を呼び出し、デバイス ハンドルを渡します。 このメソッドは、 IDirectXVideoDecoderService インターフェイスへのポインターを返します。
  5. ポインターとデバイス ハンドルをキャッシュします。

デコーダー構成の検索

MFT は、DXVA デコーダー デバイスの互換性のある構成を見つける必要があります。 入力の種類を検証した後、 IMFTransform::SetInputType メソッド内で次の手順を実行します。

  1. IDirectXVideoDecoderService::GetDecoderDeviceGuids を呼び出します。 このメソッドは、デコーダー デバイス GUID の配列を返します。

  2. デコーダー GUID の配列をループ処理して、デコーダーがサポートするものを見つけます。 たとえば、MPEG-2 デコーダーの場合は、 DXVA2_ModeMPEG2_MOCOMPDXVA2_ModeMPEG2_IDCTまたはDXVA2_ModeMPEG2_VLDを探します。

  3. 候補デコーダー デバイス GUID が見つかったら、 GUID を IDirectXVideoDecoderService::GetDecoderRenderTargets メソッドに渡します。 このメソッドは、 D3DFORMAT 値として指定されたレンダー ターゲット形式の配列を返します。

  4. レンダー ターゲット形式をループ処理し、デコーダーでサポートされている形式を探します。

  5. IDirectXVideoDecoderService::GetDecoderConfigurations を呼び出します。 提案された出力形式を記述する DXVA2_VideoDesc 構造と共に、同じデコーダー デバイス GUID を渡します。 メソッドは、 DXVA2_ConfigPictureDecode 構造体の配列を返します。 各構造体は、デコーダー デバイスで使用可能な 1 つの構成について説明します。 デコーダーがサポートする構成を探します。

  6. レンダー ターゲットの形式と構成を格納します。

IMFTransform::GetOutputAvailableType メソッドでは、提案されたレンダー ターゲット形式に基づいて、圧縮されていないビデオ形式を返します。

IMFTransform::SetOutputType メソッドで、レンダー ターゲット形式に対してメディアの種類をチェックします。

ソフトウェアデコードへのフォールバック

MFT で DXVA 構成が見つからない場合 (たとえば、グラフィックス ドライバーに適切な機能がない場合)、SetInputType メソッドと SetOutputType メソッドからMF_E_UNSUPPORTED_D3D_TYPEエラー コードを返す必要があります。 トポロジ ローダーは、ulParam パラメーターの値 NULL使用してMFT_MESSAGE_SET_D3D_MANAGER メッセージを送信することで応答します。 MFT は 、IDirect3DDeviceManager9 インターフェイスへのポインターを解放する必要があります。 その後、トポロジ ローダーはメディアの種類を再ネゴシエーションし、MFT はソフトウェア デコードを使用できます。

圧縮されていないバッファーの割り当て

DXVA 2.0 では、デコーダーは、圧縮されていないビデオ バッファーとして使用する Direct3D サーフェスを割り当てる役割を担います。 デコーダーは、インターレース解除に使用する EVR 用に 3 つのサーフェスを割り当てる必要があります。 Media Foundation では、グラフィックス ドライバーがインターレース解除に必要なサーフェスの数を指定する方法が提供されないため、この数値は固定されています。 どのドライバーにも 3 つのサーフェスで十分である必要があります。

IMFTransform::GetOutputStreamInfo メソッドで、MFT_OUTPUT_STREAM_INFO構造体にMFT_OUTPUT_STREAM_PROVIDES_SAMPLES フラグを設定します。 このフラグは、MFT が独自の出力サンプルを割り当てることをメディア セッションに通知します。

サーフェスを作成するには、 IDirectXVideoAccelerationService::CreateSurface を呼び出します。 ( IDirectXVideoDecoderService インターフェイスは 、IDirectXVideoAccelerationService からこのメソッドを継承します)。レンダー ターゲットの形式を見つけた後、 SetInputType でこれを行うことができます。

サーフェスごとに MFCreateVideoSampleFromSurface を呼び出して、サーフェスを保持するメディア サンプルを作成します。 メソッドは、 IMFSample インターフェイスへのポインターを返します。

デコード

デコーダー デバイスを作成するには、 IDirectXVideoDecoderService::CreateVideoDecoder を呼び出します。 メソッドは、デコーダー デバイスの IDirectXVideoDecoder インターフェイスへのポインターを返します。

デコードは 、IMFTransform::P rocessOutput メソッド内で行う必要があります。 各フレームで IDirect3DDeviceManager9::TestDevice を呼び出して、デバイス ハンドルをテストします。 デバイスが変更された場合、メソッドは DXVA2_E_NEW_VIDEO_DEVICEを返します。 この場合は、次の操作を行います。

  1. IDirect3DDeviceManager9::CloseDeviceHandle を呼び出して、デバイス ハンドルを閉じます。
  2. IDirectXVideoDecoderService ポインターと IDirectXVideoDecoder ポインターを解放します。
  3. 新しいデバイス ハンドルを開きます。
  4. このページの「デコーダー構成の検索」で説明したように、新しいデコーダー構成をネゴシエートします。
  5. 新しいデコーダー デバイスを作成します。

デバイス ハンドルが有効であると仮定すると、デコード プロセスは次のように機能します。

  1. 現在使用されていない使用可能なサーフェスを取得します。 (最初は、すべてのサーフェスを使用できます)。
  2. IMFTrackedSample インターフェイスのメディア サンプルを照会します。
  3. IMFTrackedSample::SetAllocator を呼び出し、デコーダーによって実装された IMFAsyncCallback インターフェイスへのポインターを指定します。 ビデオ レンダラーがサンプルを解放すると、デコーダーのコールバックが呼び出されます。
  4. IDirectXVideoDecoder::BeginFrame を呼び出します。
  5. 次の操作を 1 回以上実行します。
    1. IDirectXVideoDecoder::GetBuffer を呼び出して、DXVA デコーダー バッファーを取得します。
    2. バッファーに入力します。
    3. IDirectXVideoDecoder::ReleaseBuffer を呼び出します。
    4. IDirectXVideoDecoder::Execute を呼び出して、フレームに対してデコード操作を実行します。

DXVA 2.0 では、デコード操作に DXVA 1.0 と同じデータ構造が使用されます。 DXVA プロファイルの元のセット (H.261、H.263、MPEG-2 の場合) については、これらのデータ構造については DXVA 1.0 仕様で説明されています。

BeginFrame/Execute 呼び出しの各ペア内で GetBuffer を複数回呼び出すことができますが、DXVA バッファーの種類ごとに 1 回だけ呼び出すことができます。 同じバッファー型で 2 回呼び出すと、データが上書きされます。

SetAllocator メソッド (手順 3) のコールバックを使用して、現在使用できるサンプルと使用中のサンプルを追跡します。

DirectX ビデオ アクセラレータ 2.0

Media Foundation の変換