サンプルの配信
[このページに関連付けられている機能 DirectShow は、従来の機能です。 MediaPlayer、IMFMediaEngine、Media Foundation のオーディオ/ビデオ キャプチャに置き換わりました。 これらの機能は、Windows 10とWindows 11用に最適化されています。 新しいコードでは、可能であれば、DirectShow ではなく Media Foundation で MediaPlayer、IMFMediaEngine、Audio/Video Capture を使用することを強くお勧めします。 Microsoft は、レガシ API を使用する既存のコードを、可能であれば新しい API を使用するように書き換えるよう提案しています。]
この記事では、フィルターがサンプルを提供する方法について説明します。 IMemInputPin メソッドを使用したプッシュ モデルと、IAsyncReader を使用したプル モデルの両方について説明します。
プッシュ モデル: サンプルの配信
出力ピンは 、IMemInputPin::Receive メソッドまたは IMemInputPin::ReceiveMultiple メソッドを呼び出すことによってサンプルを提供します。これは同等ですが、サンプルの配列を提供します。 入力ピンは 、Receive (または ReceiveMultiple) 内でブロックできます。 ピンがブロックされる可能性がある場合、 その IMemInputPin::ReceiveCanBlock メソッドはS_OKを返す必要があります。 ピンでブロックが保証されない場合、 ReceiveCanBlock はS_FALSEを返す必要があります。 S_OK戻り値は 、Receive が常にブロックすることを意味するわけではありません。
Receive はリソースが使用可能になるのを待つのをブロックできますが、アップストリーム フィルターからのより多くのデータを待機するようにブロックしないでください。 これにより、ダウンストリーム フィルターがサンプルを解放するまでアップストリーム フィルターが待機するデッドロックが発生する可能性があります。これは、ダウンストリーム フィルターがアップストリーム フィルターで待機しているために発生することはありません。 ただし、フィルターに複数の入力ピンがある場合、1 つのピンは別のピンがデータを受信するまで待機できます。 たとえば、 AVI Mux フィルターは、オーディオとビデオのデータをインターリーブできるようにこれを行います。
ピンは、さまざまな理由でサンプルを拒否する場合があります。
- ピンはフラッシュ中です (フラッシュ に関するページを参照)。
- ピンが接続されていません。
- フィルターが停止しています。
- その他のエラーが発生しました。
Receive メソッドは、最初のケースではS_FALSEを返し、それ以外の場合はエラー コードを返す必要があります。 戻りコードがS_OK以外の場合、アップストリーム フィルターはサンプルの送信を停止する必要があります。
最初の 3 つのケースは、サンプルを受け取るためにフィルターが間違った状態にあったという意味で、"予期される" エラーであると考えることができます。 予期しないエラーは、ピンが受信状態であっても、ピンがサンプルを拒否する原因となります。 この種類のエラーが発生した場合、ピンはストリームの終了通知をダウンストリームに送信し、 EC_ERRORABORT イベントを Filter Graph Manager に送信する必要があります。
DirectShow 基底クラスでは、 CBaseInputPin::CheckStreaming メソッドによって、一般的なエラー ケース (フラッシュ、停止など) がチェックされます。 派生クラスは、フィルターに固有のエラーをチェックする必要があります。 エラーが発生した場合、 CBaseInputPin::Receive メソッドはストリームの終了通知と EC_ERRORABORT イベントを送信します。
プル モデル: サンプルの要求
IAsyncReader インターフェイスでは、入力ピンは次のいずれかのメソッドを呼び出して、出力ピンからサンプルを要求します。
Request メソッドは非同期です。入力ピンは IAsyncReader::WaitForNext を呼び出して、要求が完了するまで待機します。 他の 2 つのメソッドは同期です。
データを配信するタイミング
フィルターは、実行中の状態で常にサンプルを配信します。 ほとんどの場合、フィルターは一時停止中にサンプルも配信します。 これにより、グラフがデータをキューアップして、 Run が呼び出されたときにすぐに再生が開始されるようにすることができます ( 「フィルター状態」を参照)。 フィルターが一時停止中にデータを配信しない場合、フィルターの IMediaFilter::GetState メソッドは一時停止状態のVFW_S_CANT_CUEを返す必要があります。 このリターン コードは、フィルター グラフが一時停止の切り替えを完了する前に、フィルターからのデータを待機しないように通知します。 それ以外の場合、 Pause メソッドは無期限にブロックされます。 コード例については、「 CBaseFilter::GetState」を参照してください。
フィルターがVFW_S_CANT_CUEを返す必要がある場合の例をいくつか次に示します。
- キャプチャ フィルターなどのライブ ソースは、一時停止中にデータを送信しないでください。 「キャプチャ フィルターでのデータの生成」を参照してください。
- スプリッター フィルターは、実装によっては、一時停止中にデータを送信する場合と送信しない場合があります。 フィルターが個別のスレッドを使用して各出力ピンのデータをキューに入れる場合は、一時停止中にデータを送信できます。 ただし、フィルターが出力ピンごとに 1 つのスレッドを使用する場合、最初のピンが Receive を呼び出すときにスレッドをブロックする可能性があります。これにより、他のピンがデータを送信できなくなります。 その場合は、VFW_S_CANT_CUEを返す必要があります。
- フィルターは散発的にデータを配信する場合があります。 たとえば、カスタム データ ストリームを解析し、他のパケットを配信しながら一部のパケットをフィルター処理する場合があります。 その場合、フィルターが一時停止中にデータを配信することが保証されない場合があります。
ソース フィルター (プッシュ モデルを使用) またはパーサー フィルター (プッシュ/プル モデルを使用) により、1 つ以上のストリーミング スレッドが作成され、可能な限り迅速にサンプルが提供されます。 デコーダーや変換などのダウンストリーム フィルターは、通常、入力ピンで Receive が呼び出された場合にのみデータを送信します。
関連トピック