Microsoft DirectX 8.0

変換フィルタの接続

ここでは、変換フィルタを作成する場合の接続に関するいくつかの問題を説明する。任意の 2 つのフィルタを接続するには、どのメディア タイプを使用するかを調整したり、サンプルを渡すための共有のアロケータを決定することが必要になる。変換フィルタは両側で接続され、また一部の変換フィルタはグラフ内の別のフィルタのメディア タイプとアロケータを使用することから、変換フィルタの接続に関する概念を理解することが重要である。

このトピックは、以下のセクションを含んでいる。

アロケータ ネゴシエーションの仕組み

メディア タイプやアロケータ ネゴシエーションを含めた接続プロセスについては、「フィルタの接続」を参照すること。変換フィルタの特性を決めるうえで、変換フィルタのアロケータ ネゴシエーションのモデルを理解しておくと役に立つ。

変換フィルタでコピー処理が必要な場合、変換フィルタは、入力ピンによって確立されたバッファから出力ピンによって確立されたバッファにメディア サンプルをコピーする。これらのバッファは、アロケータによって指定されるが、アロケータは実際にはほかのフィルタに存在する場合がある。中間にあるフィルタがデータをコピーしない場合は、いくつか先のフィルタに存在することもある。

コピー変換フィルタの場合、通常は入力ピンに対してはアップストリーム フィルタのアロケータが、出力ピンに対してはダウンストリーム フィルタのアロケータが使用される。接続プロセスの間、どのアロケータを使用してアップストリーム転送を行うかは、アップストリーム フィルタの出力ピンによって決定される。したがって、コピー変換の入力ピンは、接続されている出力ピンからその IMemInputPin::GetAllocator メソッドが呼び出された場合に、アップストリーム転送のアロケータを作成する準備ができていなければならない。基底クラスを使用することで、任意の接続の入力ピンから新しいアロケータを作成することができる。

一方、変換インプレイス フィルタはコピーを作成せずに、既存のバッファ内のデータを変更する。これらのフィルタは、必ずダウンストリーム フィルタからアップストリーム フィルタにアロケータを提供しなければならない。このためには再接続が必要となる。なぜなら、入力ピンが最初に接続されるときには、フィルタはダウンストリーム フィルタについて何も知らないからである。また、インプレイス変換はメディア タイプを変更しないので、ダウンストリーム フィルタからのメディア タイプを再接続時にアップストリーム フィルタに提供する必要がある。

フィルタ グラフの接続 : 例

変換インプレイス フィルタの割り当てモデルをわかりやすくするために、以下に単純で一般的なフィルタ グラフの例を示す。

フィルタ グラフの例

この単純な例は、ダウンストリーム アロケータをアップストリーム フィルタに提供する変換インプレイス フィルタのモデルを示している。InPlace E が VidRen F に接続された場合を考えてみよう。

接続時、ビデオ レンダラ フィルタ (VidRen F) はアップストリーム インプレイス フィルタ (InPlace E) から利用できるようにアロケータを提供する。これは変換インプレイス フィルタなので、InPlace E はアロケータをその前のアップストリーム フィルタ InPlace D に提供する。この再接続と再ネゴシエーションは、ソース フィルタまたはコピー変換フィルタに到達するまで繰り返される。この場合はデコンプレッサ CopyDec C に到達する。(コピー変換フィルタはコピー処理を実行しなければならないので、アロケータをアップストリームに提供できない。) デコンプレッサは、ビデオ レンダラのバッファに書き込みを直接行う (バッファは DirectDraw® サーフェスである場合もある)。これが、変換フィルタを変換インプレイス フィルタとして記述し、可能であればレンダラからのアロケータをアップストリームに渡すことが重要であることの理由である。

次に、フィルタ InPlace B と CopyDec C を考えてみよう。変換インプレイス フィルタからのダウンストリーム フィルタがレンダラではなくコピー変換フィルタであるとしたらどうなるだろう? この場合、コピー変換フィルタは、独自のアロケータを入力ピンに作成し (基底クラスがこの処理を行う)、変換インプレイス フィルタは再接続時にそのアロケータをアップストリームに提供する (レンダリング フィルタに接続されている場合と同じ)。

ただし、CopyDec C が (IMemInputPin::GetAllocator メソッドを使用して) 独自のアロケータを作成することができる一方で、ソース フィルタ Source A は独自のバッファ (たとえばファイル) を使用する。したがって、InPlace B が CopyDec C に接続するとき、InPlace B は既にソース フィルタのアロケータを受け入れていることになり、自身とデコンプレッサ フィルタの間で転送を行う場合に強制的にそのアロケータを使用する。InPlace B はアップストリーム フィルタの Source A に対して CopyDec C から提供されたアロケータを使用するオプションを提示するが、ソース フィルタは、ファイル バッファからデコンプレッサの入力バッファへの余分なコピーを実行しなくて済むように、このアロケータを拒否する。

したがって、すべてのアップストリーム フィルタはそのアロケータをダウンストリームで使用するように強制することができるが、そうする理由を持たなければならない (たとえばすでにバッファがあるなど)。この例では、ファイル バッファとビデオ メモリの間で (デコンプレッサ フィルタによって) コピーが 1 つだけ作成される。

メディア タイプ接続の確立

異なるフィルタのピンを接続する場合、ピン間で交換されるサンプルの共通のメディア タイプを決めなければならない。ここでは、変換フィルタがどのようにメディア タイプのネゴシエーションを扱うかを理解するために、接続メカニズムを簡単に説明する。

このトピックは、以下のセクションを含んでいる。

接続プロセス : 要約

フィルタ グラフ マネージャがあるフィルタの出力ピンを呼び出して 2 番目のフィルタの入力ピンに接続する場合、IPin::Connect メソッドが呼び出される。次にこのメソッドは、CBaseOutputPin::CheckConnect を呼び出して接続するピンからインターフェイスを取得し、CBasePin::AgreeMediaType を使って共通のメディア タイプを調べる。

AgreeMediaType は、メディア タイプ列挙子を使用して各ピンに希望のメディア タイプを照会する CBasePin::TryMediaTypes を呼び出す。IEnumMediaTypes は、TryMediaTypes が最初に使用する、接続先の入力ピン上のインターフェイスである。基底クラスは IEnumMediaTypes を使用して、リスト内のそれぞれのメディア タイプについて CBasePin メンバ関数 GetMediaType を繰り返し呼び出す。このメンバ関数を入力および出力ピン クラスで使用して、ピンで希望されるメディア タイプを返す。

TryMediaTypes は、返された入力タイプそれぞれについて出力ピンの CheckMediaType メンバ関数を呼び出す。CheckMediaType を使用して、このタイプが許容されるかどうかを確認しなければならない。メディア タイプが見つからない (たとえば、GetMediaType が接続先の入力ピンで使用されていない、または許容できないメディア タイプを返した) 場合、AgreeMediaType は出力ピンのメディア タイプ列挙子を取得して、順番にメディア タイプを調べる。ここで、派生した出力ピンの GetMediaType メンバ関数がそれぞれのタイプについて再び呼び出される。この場合、フィルタの入力ピンによって確立された既存の接続に関して照会を行うことによってメディア タイプを判定することができる。

再接続のタイミング

入力ピンから出力ピンの間でメディア タイプを変更しない変換フィルタ (ほとんどのインプレイス変換および多くのコピー変換) の場合、ダウンストリーム フィルタのメディア タイプをアップストリーム フィルタに提供するために再接続スキームが用意されていなければならない。これを理解するために、次の図の変換インプレイス Filter B のメディア タイプ ネゴシエーションを検討する。

フィルタとピンの配置を示す図

Filter B の入力ピンが最初に接続され、アップストリームの出力ピン (AOutPin) とメディア タイプを確立する。次に Filter B の出力ピンを接続する場合、出力ピンには専用の列挙子がないので、接続されているアップストリーム フィルタの出力ピン (AOutPin) からの列挙子を使用しなければならない。

ダウンストリーム フィルタ CInPin のピンがこのメディア タイプを受け付けた場合、接続は完了する。今度は、Filter C がこのメディア タイプを受け付けずに、Filter B が扱えるメディア タイプを処理するケースを考えてみる。

メディア タイプを扱えるかどうかを判定する前に、Filter B は AOutPin の IPin::QueryAccept メソッドを呼び出して、そのメディア タイプが許容されることを確認する。すべてのフィルタで許容されるメディア タイプを検出できない場合、BOutPin から CInPin への接続は失敗する。(変換インプレイス フィルタがそのアップストリームまたはダウンストリームに接続することはできるが、両方に同時には接続できない。)

適切なタイプが見つかった場合、BOutPin はフィルタ全体に再接続を強制して、AOutPin と BInPin が再び接続されたときに、確立されたメディア タイプ (CInPin のメディア タイプ) を AOutPin に渡す。