基本的な MFT 処理モデル

このトピックでは、クライアントが Media Foundation 変換 (MFT) を使用してデータを処理する方法について説明します。 クライアントは、MFT でメソッドを直接呼び出すあらゆるものです。 これは、アプリケーションまたは Media Foundation パイプラインである可能性があります。

次の場合は、このトピックをお読みください。

  • 1 つ以上の MFT を直接呼び出すアプリケーションを記述する。
  • カスタム MFT を記述し、MFT の予期される動作を理解する必要があります。

このトピックでは、 同期 処理モデルについて説明します。 このモデルでは、すべてのデータ処理メソッドが完了するまでブロックされます。 MFT は 非同期 モデルもサポートできます。非同期モデルについては、「 非同期 MFT」のトピックで説明されています。

基本的な処理モデル

MFT を作成する

MFT を作成するには、いくつかの方法があります。

  • MFTEnum 関数を呼び出します。
  • MFTEnumEx 関数を呼び出します。
  • MFT の CLSID が既にわかっている場合は、 CoCreateInstance を呼び出すだけです。

一部の MFT には、特殊な作成関数などの他のオプションが用意されている場合があります。

ストリーム識別子を取得する

MFT には 1 つ以上の ストリームがあります。 入力ストリームは入力データを受信し、出力ストリームは出力データを生成します。 ストリームは、個別のオブジェクトとして表されません。 代わりに、さまざまな MFT メソッドがストリーム識別子をパラメーターとして受け取ります。

一部の MFT では、クライアントが入力ストリームを追加または削除できます。 ストリーミング中に、MFT は出力ストリームを追加または削除できます。 (クライアントは出力ストリームを追加または削除できません。

  1. (省略可能)。) IMFTransform::GetStreamLimits を呼び出して、MFT でサポートできるストリームの最小数と最大数を取得します。 最小値と最大値が同じ場合、MFT には固定数のストリームがあります。
  2. IMFTransform::GetStreamCount を呼び出して、ストリームの初期数を取得します。
  3. IMFTransform::GetStreamIDs を呼び出して、ストリーム識別子を取得します。 このメソッドがE_NOTIMPLを返す場合は、MFT に固定数のストリームがあり、ストリーム識別子が 0 から連続していることを意味します。
  4. (省略可能)。)MFT に固定数のストリームがない場合は、 IMFTransform::AddInputStreams を呼び出して入力ストリームを追加するか、 IMFTransform::D eleteInputStream を呼び出して入力ストリームを削除します。 (出力ストリームを追加または削除することはできません。

メディアの種類を設定する

MFT がデータを処理する前に、クライアントは MFT のストリームごとにメディアの種類を設定する必要があります。 MFT では、出力の種類を設定する前にクライアントが入力の種類を設定する必要がある場合や、反対の順序 (最初に出力の種類) が必要になる場合があります。 一部の MFT には注文の要件がありません。

MFT では、ストリームに推奨されるメディアの種類の一覧を提供できます。 また、この情報をレジストリに追加することで、MFT がサポートする一般的な形式を示すことができます。

メディアの種類を設定するには、次の操作を行います。

  1. (省略可能)。)各入力ストリームについて、 IMFTransform::GetInputAvailableType を呼び出して、そのストリームの優先される型の一覧を取得します。
    • このメソッドがMF_E_TRANSFORM_TYPE_NOT_SETを返す場合は、最初に出力の種類を設定する必要があります。手順 3 に進みます。
    • メソッドがE_NOTIMPLを返す場合、MFT には優先入力の種類の一覧がありません。手順 2 に進みます。
  2. 入力ストリームごとに、 IMFTransform::SetInputType を呼び出して入力の種類を設定します。 手順 1 のメディアの種類、または入力データを記述する型を使用できます。 ストリームがMF_E_TRANSFORM_TYPE_NOT_SETを返す場合は、手順 3 に進みます。
  3. (省略可能)。)出力ストリームごとに 、IMFTransform::GetOutputAvailableType を呼び出して、そのストリームの優先される型の一覧を取得します。
    • このメソッドがMF_E_TRANSFORM_TYPE_NOT_SETを返す場合は、最初に入力の種類を設定する必要があります。手順 1 に戻ります。
    • ストリームがE_NOTIMPLを返す場合、MFT には推奨される出力の種類の一覧がありません。手順 4 に進みます。
  4. 出力ストリームごとに、 IMFTransform::SetOutputType を呼び出して出力の種類を設定します。 手順 3 のメディアの種類、または必要な出力形式を記述する型を使用できます。
  5. 入力ストリームにメディアの種類がない場合は、手順 1 に戻ります。

バッファー要件の取得

クライアントがメディアの種類を設定した後、各ストリームのバッファー要件を取得する必要があります。

データの処理

MFT は、信頼性の高いステート マシンとして設計されています。 クライアントへの呼び出しは行われません。

  1. MFT_MESSAGE_NOTIFY_BEGIN_STREAMING メッセージを使用して IMFTransform::P rocessMessage を呼び出します。 このメッセージは、ストリーミング中に必要なリソースを割り当てるよう MFT に要求します。
  2. 少なくとも 1 つの入力ストリームで IMFTransform::P rocessInput を呼び出して、入力サンプルを MFT に配信します。
  3. (省略可能)。) IMFTransform::GetOutputStatus を呼び出して、MFT が出力サンプルを生成できるかどうかを照会します。 メソッドが S_OKを返す場合は、pdwFlags パラメーターをチェックします。 pdwFlagsMFT_OUTPUT_STATUS_SAMPLE_READY フラグが含まれている場合は、手順 4 に進みます。 pdwFlags が 0 の場合は、手順 2 に戻ります。 メソッドがE_NOTIMPLを返す場合は、手順 4 に進みます。
  4. IMFTransform::P rocessOutput を呼び出して、出力データを取得します。
    • メソッドが MF_E_TRANSFORM_NEED_MORE_INPUTを返す場合は、MFT により多くの入力データが必要です。手順 2 に戻ります。
    • メソッドが MF_E_TRANSFORM_STREAM_CHANGEを返す場合は、出力ストリームの数が変更されたか、出力形式が変更されたことを意味します。 クライアントでは、新しいストリーム識別子のクエリを実行するか、新しいメディアの種類を設定する必要がある場合があります。 詳細については、 ProcessOutput のドキュメントを参照してください。
  5. 処理する入力データがまだ存在する場合は、手順 2 に進みます。 MFT で使用可能なすべての入力データが消費されている場合は、手順 6 に進みます。
  6. MFT_MESSAGE_NOTIFY_END_OF_STREAM メッセージを使用して ProcessMessage を呼び出します。
  7. MFT_MESSAGE_COMMAND_DRAIN メッセージを使用して ProcessMessage を呼び出します。
  8. ProcessOutput を呼び出して、残りの出力を取得します。 メソッドが MF_E_TRANSFORM_NEED_MORE_INPUTを返すまで、この手順を繰り返します。 この戻り値は、すべての出力が MFT からドレインされたことを示します。 (これはエラー条件として扱わないでください。)

ここで説明するシーケンスは、MFT で可能な限り少ないデータを保持します。 ProcessInput を呼び出すたびに、クライアントは出力の取得を試みます。 1 つの出力サンプルを生成するには、いくつかの入力サンプルが必要な場合もあれば、1 つの入力サンプルで複数の出力サンプルが生成される場合もあります。 クライアントの最適な動作は、MFT に多くの入力が必要になるまで MFT から出力サンプルをプルすることです。

ただし、MFT はクライアントによって異なる順序のメソッド呼び出しを処理できる必要があります。 たとえば、クライアントは ProcessInputProcessOutput の呼び出しを単に交互に行う場合があります。 MFT は、生成する出力がある場合は常に ProcessInput からMF_E_NOTACCEPTINGを返すことによって、取得する入力の量を制限する必要があります。

ここで説明するメソッド呼び出しの順序は、イベントの唯一の有効なシーケンスではありません。 たとえば、手順 3 と 4 では、クライアントが入力型で始まり、出力の種類を試すとします。 クライアントは、この順序を逆にして、出力の種類から始めることもできます。 どちらの場合も、MFT で逆の順序が必要な場合は、エラー コード MF_E_TRANSFORM_TYPE_NOT_SETが返されます。

クライアントは、ストリーミング中にいつでも GetInputCurrentTypeGetOutputStreamInfo などの情報メソッドを呼び出すことができます。 クライアントは、いつでもメディアの種類の変更を試みることもできます。 これが有効な操作でない場合、MFT はエラー コードを返す必要があります。 要するに、MFT は、呼び出し自体に記載されているもの以外に、操作の順序についてほとんど想定しないでください。

次の図は、このトピックで説明する手順のフローチャートを示しています。

入力の種類を設定し、入力を取得し、出力を処理するループを介してストリーム識別子を取得するフロー チャート

Basic モデルの拡張機能

必要に応じて、MFT は基本的なストリーミング モデルの一部の拡張機能をサポートできます。

  • 遅延読み取りストリーム。 IMFTransform::GetOutputStreamInfo メソッドが出力ストリームのMFT_OUTPUT_STREAM_LAZY_READ フラグを返す場合、クライアントはその出力ストリームからデータを収集する必要はありません。 MFT は入力を受け入れ続け、ある時点で MFT はそのストリームからの出力データを破棄します。 すべての出力ストリームにこのフラグがある場合、MFT は入力の受け入れに失敗することはありません。 たとえば、視覚化変換などです。この変換では、視覚化を描画するための予備の CPU サイクルがある場合にのみ、クライアントが出力を取得します。
  • 破棄可能なストリーム。 GetOutputStreamInfo メソッドが出力ストリームのMFT_OUTPUT_STREAM_DISCARDABLE フラグを返す場合、クライアントは MFT に出力の破棄を要求できますが、MFT は要求されない限り出力を破棄しません。 MFT が最大入力バッファーに達すると、クライアントは出力データを収集するか、MFT に出力を破棄するように要求する必要があります。
  • オプションのストリーム。 GetOutputStreamInfo メソッドが出力ストリームのMFT_OUTPUT_STREAM_OPTIONAL フラグを返す場合、または IMFTransform::GetInputStreamInfo メソッドが入力ストリームのMFT_INPUT_STREAM_OPTIONAL フラグを返す場合、そのストリームは省略可能です。 クライアントは、ストリームにメディアの種類を設定する必要はありません。 クライアントが型を設定しない場合、ストリームの選択は解除されます。 選択解除された出力ストリームはサンプルを生成せず、 クライアントは ProcessOutput を呼び出すときにストリームのバッファーを提供しません。 選択解除された入力ストリームでは、入力データは受け入れられません。 MFT では、すべての入力ストリームと出力ストリームを省略可能としてマークできます。 ただし、MFT を機能させるには、少なくとも 1 つの入力と 1 つの出力を選択する必要があります。
  • 非同期処理。 非同期処理モデルは Windows 7 で導入されました。 詳細については、 トピック「非同期 MFT」を参照してください

IMF2DBuffer

MFT が非圧縮ビデオ データを処理する場合は、 IMF2DBuffer インターフェイスを使用してサンプル バッファーを操作する必要があります。 このインターフェイスを取得するには、任意の入力バッファーまたは出力バッファーで IMFMediaBuffer インターフェイスに対してクエリを実行します。 このインターフェイスを使用できない場合は、追加のバッファー コピーが発生する可能性があります。 このインターフェイスを適切に使用するには、IMF2DBuffer が使用可能な場合に、変換で IMFMediaBuffer インターフェイスを使用してバッファーをロックしないようにする必要があります。

ビデオ データの処理の詳細については、「 圧縮されていないビデオ バッファー」を参照してください。

MFT のフラッシュ

MFT をフラッシュすると、MFT によってすべての入力データが破棄されます。 これにより、出力ストリームに中断が発生する可能性があります。 通常、クライアントがデータの損失を気にしない場合、クライアントは入力ストリーム内の新しいポイントにシークするか、新しい入力ストリームに切り替える前に MFT をフラッシュします。

MFT をフラッシュするには、MFT_MESSAGE_COMMAND_FLUSH メッセージと共に IMFTransform::P rocessMessage を呼び出します。

MFT のドレイン

MFT をドレインすると、MFT は、既に送信されている入力データからできる限り多くの出力を生成します。 MFT が使用可能な入力から完全な出力サンプルを生成できない場合は、入力データがドロップされます。 通常、クライアントは、ソース ストリームの末尾に達したとき、またはソース ストリームの形式が変更される直前に MFT をドレインします。 MFT をドレインするには、次の操作を行います。

  1. MFT_MESSAGE_COMMAND_DRAIN メッセージを使用して ProcessMessage を呼び出します。 このメッセージは、既に送信されている入力データからできる限り多くの出力データを配信する必要があることを MFT に通知します。
  2. ProcessOutput を呼び出して、メソッドがMF_E_TRANSFORM_NEED_MORE_INPUTを返すまで出力データを取得します。

MFT がドレインされている間は、それ以上の入力は受け入れられません。

サンプル属性

入力サンプルには、対応する出力サンプルにコピーする必要がある属性がある場合があります。

  • MFT が MFPKEY_EXATTRIBUTE_SUPPORTED プロパティのVARIANT_TRUEを返す場合、MFT は属性をコピーする必要があります。
  • MFPKEY_EXATTRIBUTE_SUPPORTED プロパティがVARIANT_FALSEまたは設定されていない場合、クライアントは属性をコピーする必要があります。

1 つの入力と 1 つの出力を持つ MFT の場合は、次の一般的な規則を使用できます。

  • 各入力サンプルで出力サンプルが 1 つだけ生成される場合は、クライアントに属性をコピーさせることができます。 MFPKEY_EXATTRIBUTE_SUPPORTED プロパティの設定は解除したままにします。
  • 入力サンプルと出力サンプルの間に一対一の対応がない場合、MFT は出力サンプルの正しい属性を決定する必要があります。 MFPKEY_EXATTRIBUTE_SUPPORTED プロパティを VARIANT_TRUE に設定します。

不連続

不連続性とは、オーディオまたはビデオ ストリームの中断です。 不連続性は、ネットワーク接続上のパケットのドロップ、ファイル データの破損、あるソース ストリームから別のソース ストリームへの切り替え、またはその他のさまざまな原因によって発生する可能性があります。 不連続性は、不連続性の後の最初のサンプルで MFSampleExtension_Discontinuity 属性を設定することによって通知されます。 サンプルの途中で不連続性を通知することはできません。 したがって、不連続データは別のサンプルで送信する必要があります。

一部の変換 (特にオーディオやビデオの効果など、非圧縮データを処理する変換) では、入力データを処理するときに不連続性を無視する必要があります。 これらの MFT は一般に、連続データを処理するように設計されており、不連続性が発生した後でも、受信したデータを連続として扱う必要があります。

MFT が入力データの不連続性を無視する場合でも、出力サンプルに入力サンプルと同じタイム スタンプがある場合は、出力サンプルに不連続性フラグを設定する必要があります。 ただし、出力サンプルに異なるタイム スタンプがある場合、MFT は不連続性を伝達しないでください。 (たとえば、一部のオーディオ リサンプリングラーでは、このケースが発生します)。ストリーム内の間違った場所での不連続性は、不連続性よりも悪くなります。

不連続性は次のサンプルの解釈に影響するため、ほとんどのデコーダーは不連続性を無視できません。 MPEG-2 など、フレーム間圧縮を使用するエンコード テクノロジは、このカテゴリに分類されます。 一部のエンコード 方式では、DV や MJPEG など、フレーム内圧縮のみを使用します。 これらのデコーダーは、不連続性を無視しても問題ありません。

不連続性に応答する変換は、通常、不連続性の前にできるだけ多くのデータを出力し、残りを破棄する必要があります。 不連続性フラグを持つ入力サンプルは、ストリームの最初のサンプルであるかのように処理する必要があります。 (この動作は、MFT_MESSAGE_COMMAND_DRAIN メッセージに指定されているもの 一致します)。ただし、正確な詳細はメディア形式によって異なります。

デコーダーが不連続性を軽減するために何も行わない場合は、不連続性フラグを出力データにコピーする必要があります。 圧縮データを完全に処理するデマルチプレクサーやその他の MFT は、出力ストリームに不連続性をコピーする必要があります。 そうしないと、ダウンストリーム コンポーネントで圧縮データを正しくデコードできない場合があります。 一般に、MFT に不連続性を滑らかにするための明示的なコードが含まれている場合を除き、ほぼ常に下流で不連続性を渡すことは正しいです。

動的書式の変更

ストリーミング中に形式が変更される可能性があります。 たとえば、縦横比はビデオ ストリームの途中で変化する可能性があります。

MFT によるストリーム変更の処理方法の詳細については、「 ストリーム変更の処理」を参照してください。

Stream イベント

MFT にイベントを送信するには、 IMFTransform::P rocessEvent を呼び出します。 メソッドが MF_S_TRANSFORM_DO_NOT_PROPAGATE_EVENTを返す場合、MFT は ProcessOutput の後続の呼び出しで呼び出し元にイベントを返します。 メソッドが他の HRESULT 値を返す場合、 MFT は ProcessOutput でクライアントにイベントを返しません。 その場合、クライアントは、該当する場合、パイプライン内の次のコンポーネントにダウンストリームでイベントを伝達する必要があります。 詳細については、「 IMFTransform::P rocessOutput」を参照してください。

Media Foundation Transforms