Media Foundation での DXVA 2.0 のサポート

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

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

ヒント

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

 

Note

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

 

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

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

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

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

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

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

デコーダー構成の検索

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

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

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

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

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

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

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

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 では、グラフィックス ドライバーがインターレース解除に必要なサーフェスの数を EVR で指定する方法が提供されないため、この数は固定されています。 ドライバーには 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 仕様でこれらのデータ構造について説明します。

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

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

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

Media Foundation の変換