非同期 MFT
このトピックでは、Media Foundation 変換 (MFT) の非同期データ処理について説明します。
手記
このトピックは Windows 7 以降に適用されます。
- 非同期 MFT について
- 一般的な要件の
- イベント
- ProcessInput
- ProcessOutput
- ドレイン
- フラッシュ
- マーカーの
- 書式の変更
- 属性の
- 非同期 MFT のロック解除の
- MFT のシャットダウンを する
- 登録と列挙
- 関連トピック
非同期 MFT について
Windows Vista で MFT が導入されたとき、API は同期 データ処理 用に設計されました。 そのモデルでは、MFT は常に入力の取得を待機しているか、出力の生成を待機しています。
一般的なビデオ デコーダーについて考えてみましょう。 デコードされたフレームを取得するために、クライアントは IMFTransform::P rocessOutputを呼び出します。 デコーダーにフレームをデコードするのに十分なデータがある場合は、MFT がフレームをデコードしている間に ProcessOutput ブロックを します。 それ以外の場合、ProcessOutput は MF_E_TRANSFORM_NEED_MORE_INPUTを返します。これは、クライアントが IMFTransform::P rocessInput呼び出す必要があることを示します。
このモデルは、デコーダーが 1 つのスレッドですべてのデコード操作を実行する場合に適切に機能します。 ただし、デコーダーが複数のスレッドを使用してフレームを並列にデコードするとします。 パフォーマンスを最大限に高めるには、デコード スレッドがアイドル状態になると、デコーダーは新しい入力を受け取る必要があります。 ただし、スレッドがデコード操作を完了する速度は、ProcessInput と ProcessOutputをするクライアントの呼び出しと正確には一致せず、スレッドは作業を待機します。
Windows 7 では、MFT のイベント ドリブン 非同期 処理が導入されています。 このモデルでは、MFT が入力を必要とするとき、または出力がある場合は常に、クライアントにイベントを送信します。
一般的な要件
このトピックでは、非同期 MFT と同期 MFT の違いについて説明します。 このトピックで説明する場合を除き、2 つの処理モデルは同じです。 (特に、フォーマット ネゴシエーションは同じです)。
非同期 MFT では、次のインターフェイスを実装する必要があります。
- IMFTransformをする
- IMFMediaEventGeneratorの
- IMFShutdown
イベント
非同期 MFT では、次のイベントを使用してデータ処理の状態が通知されます。
出来事 | 形容 |
---|---|
METransformNeedInput の | MFT がより多くの入力を受け入れる場合に送信されます。 |
METransformHaveOutput を する | MFT に出力があるときに送信されます。 |
METransformDrainComplete の | ドレイン操作が完了したときに送信されます。 ドレインを参照してください。 |
METransformMarker の | マーカーが処理されるときに送信されます。 「マーカー を参照してください。 |
これらのイベントは帯域外で送信されます。 MFT のコンテキストでの帯域内イベントと帯域外イベントの違いを理解することが重要です。
元の MFT 設計では、インバンド イベント サポートされています。 インバンド イベントには、形式の変更に関する情報など、データ ストリームに関する情報が含まれます。 クライアントは、IMFTransform::P rocessEvent呼び出すことによって、インバンド イベントを MFT に送信します。 MFT は、ProcessOutput メソッドでインバンド イベントをクライアントに送信できます。 (具体的には、イベントは、MFT_OUTPUT_DATA_BUFFER 構造体の pEvents メンバーで伝達されます)。
MFT は、次のように、IMFMediaEventGenerator インターフェイスを介して帯域外イベントを送信します。
- MFT は、Media Event Generatorsで説明されているように、IMFMediaEventGenerator インターフェイスを実装します。
- クライアントは、IMFMediaEventGenerator インターフェイスの MFT IUnknown::QueryInterface を呼び出します。 非同期 MFT では、このインターフェイスを公開する必要があります。 同期 MFT では、このインターフェイスを公開しないでください。
- クライアントは、IMFMediaEventGenerator::BeginGetEvent呼び出し、IMFMediaEventGenerator::EndGetEventをして、MFT から帯域外イベントを受信します。
ProcessInput
IMFTransform::P rocessInput メソッドは次のように変更されます。
- ストリーミングが開始されると、クライアントは MFT_MESSAGE_NOTIFY_START_OF_STREAM メッセージを送信します。
- ストリーミング中、MFT は METransformNeedInput イベントを送信してデータを要求します。 イベント データはストリーム識別子です。
- METransformNeedInput イベント ごとに、クライアントは指定されたストリームに対 ProcessInput を呼び出します。
- ストリーミングの終了時に、クライアントは MFT_MESSAGE_NOTIFY_END_OF_STREAM メッセージ ProcessMessage を呼び出すことができます。
実装に関する注意事項:
- MFT は、MFT_MESSAGE_NOTIFY_START_OF_STREAM メッセージを受信するまで、METransformNeedInput イベントを送信してはなりません。
- ストリーミング中、MFT は METransformNeedInput イベント いつでも送信できます。
- MFT は、METransformNeedInput イベント 保留中の数を保持する必要があります。 METransformNeedInput イベントに対応しない ProcessInputを呼び出すと、MF_E_NOTACCEPTINGが返される必要があります。
- MFT は、MFT_MESSAGE_NOTIFY_END_OF_STREAM メッセージを受信すると、METransformNeedInput イベント 保留中の数を 0 にリセットします。
- MFT は、MFT_MESSAGE_NOTIFY_END_OF_STREAM メッセージを受信した後、METransformNeedInput イベントを送信してはなりません。
- ProcessInput が MFT_MESSAGE_NOTIFY_START_OF_STREAM 前または MFT_MESSAGE_NOTIFY_END_OF_STREAM後に呼び出された場合、メソッドは MF_E_NOTACCEPTINGを返す必要があります。
ProcessOutput
IMFTransform::P rocessOutput メソッドは次のように変更されます。
- MFT が出力を持つたびに、METransformHaveOutput イベントが送信されます。
- METransformHaveOutput イベント ごとに、クライアントは ProcessOutput呼び出します。
実装に関する注意事項:
- クライアントが他 ProcessOutput を呼び出すと、メソッドは E_UNEXPECTEDを返します。
- 非同期 MFT は、ProcessOutput メソッドから MF_E_TRANSFORM_NEED_MORE_INPUT を返さないでください。 MFT により多くの入力が必要な場合は、METransformNeedInput イベントが送信されます。
排水
MFT をドレインすると、既に送信されている入力データからできる限り多くの出力が MFT によって生成されます。 非同期 MFT のドレインは次のように機能します。
- クライアントは、MFT_MESSAGE_COMMAND_DRAIN メッセージを送信します。
- MFT は、処理するデータがなくなったまで、METransformHaveOutput イベントを送信し続けます。 この間、METransformNeedInput イベント 送信されません。
- MFT は、最後の METransformHaveOutput イベントを送信した後、METransformDrainComplete イベントを送信します。
ドレインが完了すると、MFT は、MFT_MESSAGE_NOTIFY_START_OF_STREAM メッセージをクライアントから受信するまで、METransformNeedInput イベント 別のイベントを送信しません。
すいせん
クライアントは、MFT_MESSAGE_COMMAND_FLUSH メッセージを送信することで MFT をフラッシュできます。 MFT は、保持しているすべての入力サンプルと出力サンプルをドロップします。
MFT は、クライアントから MFT_MESSAGE_NOTIFY_START_OF_STREAM メッセージを受信するまで、METransformNeedInput イベント 別のイベントを送信しません。
マーカー
クライアントは、MFT_MESSAGE_COMMAND_MARKER メッセージを送信することで、ストリーム内のポイントをマークできます。 MFT は次のように応答します。
- MFT は、既存の入力データから可能な限り多くの出力サンプルを生成し、各出力サンプルに対して METransformHaveOutput イベントを送信します。
- すべての出力が生成されると、MFT は METransformMarker イベントを送信します。 このイベントは、すべての METransformHaveOutput イベントの後に送信する必要があります。
たとえば、デコーダーに 4 つの出力サンプルを生成するのに十分な入力データがあるとします。 クライアントが MFT_MESSAGE_COMMAND_MARKER メッセージを送信すると、MFT は METransformHaveOutput イベント (出力サンプルごとに 1 つ) 4 つをキューに入れ、その後に METransformMarker イベントをキューに入れます。
マーカー メッセージは、ドレイン メッセージに似ています。 ただし、ドレインはストリームの中断と見なされますが、マーカーは見なされません。 ドレインとマーカーには、次の違いがあります。
排水:
- ドレイン中、MFT は METransformNeedInput イベント 送信しません。
- MFT は、出力サンプルの作成に使用できない入力データを破棄します。
- 一部の MFT では、データの末尾に "tail" が生成されます。 たとえば、リバーブやエコーなどのオーディオ効果は、入力データが停止した後に追加のデータを生成します。 テールを生成する MFT は、ドレイン操作の終了時に行う必要があります。
- MFT のドレインが完了すると、次の出力サンプルが MFSampleExtension_Discontinuity 属性でマークされ、ストリーム内の不連続性が示されます。
マーカー:
- MFT は、マーカー イベントを送信する前 METransformNeedInput イベントを送信し続けます。
- MFT は入力データを破棄しません。 部分的なデータがある場合は、マーカー ポイントの後に処理する必要があります。
- MFT はマーカー ポイントで尾を生成しません。
- MFT は、マーカー ポイントの後に不連続性フラグを設定しません。
変更の書式設定
非同期 MFT は、ストリーム変更の処理 に関するの説明に従って、動的な形式の変更をサポートする必要があります。
属性
有効な属性ストアを返すには、非同期 MFT IMFTransform::GetAttributes メソッドを実装する必要があります。 非同期 MFT には、次の属性が適用されます。
属性 | 形容 |
---|---|
MF_TRANSFORM_ASYNC | MFT は、この属性を TRUE (1) 設定する必要があります。 クライアントは、この属性を照会して、MFT が非同期であるかどうかを検出できます。 |
MF_TRANSFORM_ASYNC_UNLOCK | |
MFT_SUPPORT_DYNAMIC_FORMAT_CHANGE | MFT は、この属性を TRUE (1) 設定する必要があります。 クライアントでは、この属性が設定されていると想定できます。 |
非同期 MFT のロック解除
非同期 MFT は、元の MFT データ処理モデルと互換性がありません。 非同期の MFT が既存のアプリケーションを壊さないようにするために、次のメカニズムが定義されています。
- クライアントは、MFT IMFTransform::GetAttributes を呼び出します。
クライアントは、この MF_TRANSFORM_ASYNC 属性に対してクエリを実行します。 非同期 MFT の場合、この属性の値は **TRUE** です。
MFT のロックを解除するには、MF_TRANSFORM_ASYNC_UNLOCK 属性を **TRUE** に設定する必要があります。
クライアントが MFT のロックを解除するまで、すべての IMFTransform メソッドは、次の例外を除き、MF_E_TRANSFORM_ASYNC_LOCKEDを返す必要があります。
- IMFTransform::GetAttributes (すべての非同期 MFT)
- IMFTransform::GetInputAvailableType (すべての非同期 MFT)
- IMFTransform::GetOutputCurrentType (エンコーダーのみ)
- IMFTransform::SetOutputType (エンコーダーのみ)
- IMFTransform::GetStreamCount (すべての非同期 MFT)
- IMFTransform::GetStreamIDs (すべての非同期 MFT)
次のコードは、非同期 MFT のロックを解除する方法を示しています。
HRESULT UnlockAsyncMFT(IMFTransform *pMFT)
{
IMFAttributes *pAttributes = NULL;
HRESULT hr = hr = pMFT->GetAttributes(&pAttributes);
if (SUCCEEDED(hr))
{
hr = pAttributes->SetUINT32(MF_TRANSFORM_ASYNC_UNLOCK, TRUE);
pAttributes->Release();
}
return hr;
}
MFT のシャットダウン
非同期 MFT は、IMFShutdown インターフェイスを実装する必要があります。
- シャットダウン: MFT はイベント キューをシャットダウンする必要があります。 標準イベント キューを使用している場合は、IMFMediaEventQueue::Shutdown呼び出します。 必要に応じて、MFT によって他のリソースが解放される場合があります。 Shutdownを呼び出した後、クライアントは MFT を使用しないでください。
- GetShutdownStatus: Shutdown が呼び出された後、MFT は pStatus パラメーターに MFSHUTDOWN_COMPLETED 値を返す必要があります。 MFSHUTDOWN_INITIATED値を返すべきではありません。
登録と列挙
非同期 MFT を登録するには、MFTRegister 関数を呼び出し、Flags パラメーターに MFT_ENUM_FLAG_ASYNCMFT フラグを設定します。 (以前は、このフラグは予約されていました)。
非同期 MFT を列挙するには、MFTEnumEx 関数を呼び出し、Flags パラメーターに MFT_ENUM_FLAG_ASYNCMFT フラグを設定します。 下位互換性のために、MFTEnum 関数は非同期の MFT を列挙しません。 そうしないと、ユーザーのコンピューターに非同期 MFT をインストールすると、既存のアプリケーションが壊れる可能性があります。
関連トピック