フィルターの状態

フィルターには、停止、一時停止、実行の 3 つの状態があります。 一時停止状態の目的は、実行コマンドが直ちに応答するように、グラフ内のデータをキューに格納することです。 フィルター Graph マネージャーは、すべての状態遷移を制御します。 アプリケーションが IMediaControl::RunIMediaControl::P ause、または IMediaControl::Stop を呼び出すと、フィルター Graph マネージャーはすべてのフィルターで対応する IMediaFilter メソッドを呼び出します。 停止状態と実行中の切り替えは常に一時停止状態になるため、アプリケーションが停止したグラフで実行を呼び出すと、フィルター Graph マネージャーはグラフを実行する前に一時停止します。

ほとんどのフィルターでは、実行中の状態と一時停止中の状態は同じです。 次のフィルター グラフを検討してください。

ソース > 変換 > レンダラー

ソース フィルターがライブ キャプチャ ソースではないことを前提としています。 ソース フィルターが一時停止すると、新しいデータを生成し、できるだけ早くメディア サンプルに書き込むスレッドが作成されます。 スレッドは、変換フィルターの入力ピンで IMemInputPin::Receive を 呼び出すことによって、サンプルをダウンストリームに "プッシュ" します。 変換フィルターは、ソース フィルターのスレッドでサンプルを受け取ります。 ワーカー スレッドを使用してレンダラーにサンプルを配信できますが、通常は同じスレッドでサンプルを配信します。 レンダラーが一時停止されている間は、サンプルの受信を待機します。 1 つを受け取ると、そのサンプルがブロックされ、無期限に保持されます。 ビデオ レンダラーの場合は、サンプルをポスター イメージとして表示し、必要に応じてイメージを再描画します。

この時点で、ストリームは完全に完成し、レンダリングの準備が整います。 グラフが一時停止したままの場合、すべてのフィルターが Receive または IMemAllocator::GetBuffer でブロックされるまで、最初のサンプルの背後にあるグラフにサンプルが "山積み" されます。 ただし、データは失われません。 ソース スレッドのブロックが解除されると、単にブロックされた時点から再開されます。

ソース フィルターと変換フィルターは、一時停止から実行中への切り替えを無視します。データの処理は可能な限り高速に続行されます。 ただし、レンダラーを実行すると、サンプルのレンダリングが開始されます。 最初に、一時停止中に保持されたサンプルをレンダリングします。 次に、新しいサンプルを受け取るたびに、サンプルのプレゼンテーション時間が計算されます。 (詳細については、DirectShowの時刻とクロックを参照してください)。レンダラーは、プレゼンテーション時刻まで各サンプルを保持し、その時点でサンプルをレンダリングします。 プレゼンテーション時間を待機している間は、 Receive メソッドをブロックするか、キューを持つワーカー スレッドで新しいサンプルを受信します。 レンダラーの上流にあるフィルターは、スケジュール設定には関与しません。

キャプチャ デバイスなどのライブ ソースは、この一般的なアーキテクチャの例外です。 ライブ ソースでは、事前にデータをキューに入らすことは適切ではありません。 アプリケーションはグラフを一時停止してから、実行するまで長時間待つ場合があります。 グラフで "古い" サンプルをレンダリングしないでください。 したがって、ライブ ソースでは、実行中にのみ、一時停止中にサンプルは生成されません。 この事実を Filter Graph Manager に通知するために、ソース フィルターの IMediaFilter::GetState メソッドはVFW_S_CANT_CUEを返します。 この戻りコードは、レンダラーがデータを受信しなかった場合でも、フィルターが一時停止状態に切り替わったことを示します。

フィルターが停止すると、それ以上のサンプルが配信されなくなります。 ソース フィルターはストリーミング スレッドをシャットダウンし、他のフィルターは作成したワーカー スレッドをすべてシャットダウンします。 ピンはアロケーターのコミットを解除します。

状態遷移

フィルター Graph マネージャーは、レンダラーから始まり、ソース フィルターに逆方向に動作して、すべての状態遷移を上流の順序で実行します。 この順序付けは、サンプルが削除されるのを防ぎ、グラフのデッドロックを防ぐために必要です。 最も重要な状態遷移は、一時停止と停止の間です。

  • 停止から一時停止: 各フィルターが一時停止すると、次のフィルターからサンプルを受け取る準備が整います。 ソース フィルターは、最後に一時停止します。 ストリーミング スレッドを作成し、サンプルの配信を開始します。 すべてのダウンストリーム フィルターが一時停止されているため、どのフィルターもサンプルを拒否しません。 フィルター Graph マネージャーは、グラフ内のすべてのレンダラーがサンプルを受信するまで遷移を完了しません (前述のライブ ソースを除く)。
  • 停止するまで一時停止: フィルターが停止すると、保持されているサンプルが解放され、 GetBuffer で待機しているアップストリーム フィルターのブロックが解除されます。 フィルターが Receive メソッド内のリソースを待機している場合は、待機を停止し、呼び出し元のフィルターのブロックを解除する Receive から返されます。 そのため、フィルター Graph マネージャーが次のアップストリーム フィルターを停止すると、そのフィルターは GetBuffer または Receive でブロックされず、停止コマンドに応答できます。 アップストリーム フィルターでは、stop コマンドを取得する前にいくつかの追加のサンプルが提供される場合がありますが、ダウンストリーム フィルターは既に停止しているため、単にそれらを拒否します。

フィルター GraphのData Flow