Microsoft DirectX 8.0 |
前の「フィルタ グラフとそのコンポーネント」では、DirectShow フィルタ グラフの基本的な構成要素について説明した。ここでは、マルチメディア データの処理を開始できるように、これらの構成要素を作成および接続する方法について説明する。最初の「一般的なグラフの構築」では、フィルタ グラフの構築に関する一般的な手法について説明する。次の「キャプチャ グラフの構築」では、キャプチャ グラフの構築に用いられる別の手法について説明する。キャプチャ グラフとは、DV カムコーダ、USB カメラ、TV チューナー カードなどのビデオ キャプチャ デバイスからのデータを処理するフィルタ グラフである。
フィルタ グラフを作成するには、必ず最初にフィルタ グラフ マネージャのインスタンスを作成して、次に示すように IGraphBuilder インターフェイスへのポインタを取得する。
IGraphBuilder* pIGB; HRESULT hr; hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&pIGB);
IGraphBuilder インターフェイスは、その名のとおり、フィルタ グラフのメソッドを格納する。これらのメソッドは、次のようなグラフ構築の 3 種類のアプローチを提供する。
アプローチ #1 は、AVI、MPEG、WAV、MP3 など、一部の既知のフォーマットのファイルを再生するだけの場合に向いている。この手法は、「ファイルの再生法」で具体的に示されている。DirectShow では、モニタにビデオ データを表示したり、システムのスピーカからオーディオ データを流したりする処理を表現するのに、再生よりもレンダリングという用語が使われることが多い。フィルタ グラフ マネージャに対して、指定されたファイルをレンダリングできるフィルタ グラフを自動作成するよう指示するために、アプリケーションは IGraphBuilder::RenderFile メソッドを使用する。次に、グラフを構築するためのフィルタ グラフ マネージャの基本手順について説明する。
フィルタ グラフを作成するには、まず必要なフィルタを検索してそのインスタンスを作成する。フィルタの選択処理は、主に、処理するデータのメディア タイプに基づく。これは、2 つのフィルタのピンは、両方が処理できる共通のメディア タイプを調整できない限り、接続できないからである。フィルタ グラフ マネージャは、さまざまなファイル名拡張子 (.wma、.avi、.wav など) に関連付けられたメディア タイプのレジストリを検索することで、データのメディア タイプを決定できる。拡張子との関連付けが存在しない場合、フィルタ グラフ マネージャは、ファイル内の特殊なチェック バイトを検索する。これらのチェック バイトから、フィルタ グラフ マネージャは、対応する DirectShow メディア タイプを決定し、そのメディア タイプを読み取り可能なソース フィルタの検索を開始できる。内部的には、RenderFile ロジックが IGraphBuilder::AddSourceFilter を呼び出すことで、このタスクを実行する。
すべての DirectShow フィルタは、フィルタの分類、サポートするメディア タイプ、フィルタのメリットなどに加えて、Windows レジストリ内の GUID で一意に識別される。フィルタ グラフ マネージャは、このすべての情報を検査して、どのフィルタのインスタンスを作成するかを決定する。フィルタ分類は、フィルタの一般的な機能を識別子、検索基準を最初に絞り込むために使われる。メディア タイプ情報は、フィルタが入力として受け付けることができるデータの種類、およびグラフ内の次のフィルタに出力として提供できるデータの種類を記述する。メリットの値は、グラフの自動構築処理中にフィルタが考慮されるべきかどうかを示す。システム上の 2 つのフィルタが似たメディア タイプ情報を持つ場合、フィルタ グラフ マネージャはメリット値の高い方のフィルタを選択する(一部のフィルタは、特殊なフィルタ グラフでのみの使用を目的としているので、メリット値を意図的に低くしている。そのようなフィルタは、アプリケーションによって個別にグラフに追加する必要がある)。
レジストリを検索するには、フィルタ グラフ マネージャは DirectShow フィルタ マッパー オブジェクトのインスタンスを作成し、IFilterMapper2::EnumMatchingFilters メソッドを呼び出して、検索を実行する。このメソッドは、分類やメディア タイプごとに DirectShow フィルタ (デコーダなどのハードウェア デバイスと同様) を列挙でき、検索基準に一致するすべてのフィルタおよびハードウェア デバイスまたはその一方に対するモニカを含む標準 COM IEnumMoniker オブジェクトを返す(COM モニカを使うと、このメソッドは、オブジェクトのインスタンスを実際に作成しなくてもオブジェクトを問い合わせたり、パスを作成したり、ハードウェア デバイスなど、実際は COM オブジェクトではないものを列挙したりすることができる)。
指定されたタイプのファイルを読み取ることができるソース フィルタをモニカが見つけると、フィルタ グラフ マネージャは CoCreateInstance を使って、返された GUID を使うことでフィルタのインスタンスを作成する。大部分のファイル タイプでは、ソース フィルタはファイル ソース (非同期) フィルタとなる。次に、フィルタ グラフ マネージャは、IGraphBuilder::AddFilter メソッドを呼び出してフィルタ グラフにフィルタを追加する。フィルタがグラフに追加されたことがフィルタに通知されると、読み取るファイルのタイプ用に構成された出力ピンを 1 つまたは複数作成する。ピンが作成されたら、フィルタ グラフ マネージャは、各ピンがサポートするメディア タイプを調べ、次にその入力ピンのメディア タイプを受け入れ可能なフィルタをレジストリで再び探す。適合するフィルタが見つかると、そのフィルタをグラフに追加する。
ダウンストリーム フィルタの追加時に、フィルタはピンを構成し、前の (アップストリーム) フィルタに接続する準備が完了する。フィルタ グラフ マネージャは、各フィルタに問い合わせて適切なピンを決定し、IGraphBuilder::Connect メソッドを呼び出して、アップストリーム フィルタの出力ピンをダウンストリーム フィルタの入力ピンに接続する。次に、2 つのピンは調整プロセスを実行してデータのメディア タイプを決定し、メディア サンプル オブジェクト用のメモリを割り当てるオブジェクト、およびサンプルのデータを保持するバッファはどちらのピンが提供するかを決定する。ピン接続プロセスの詳細については、「フィルタ開発者のための DirectShow アーキテクチャ」で解説される。
2 つのピンを接続したら、フィルタ グラフ マネージャは、新しいフィルタの出力ピンでサポートされるメディア タイプを調べ、そのメディア タイプを処理可能なフィルタを検索する。必要なフィルタがすべてグラフに追加されるまで、同じプロセスが繰り返される。ファイル再生グラフでは、2 番目のフィルタは通常、パーサーまたはスプリッタ フィルタとなる。これは、AVI や MPEG など未加工のデータ ストリームを読み取り、オーディオ ストリームとビデオ ストリームに分割するフィルタであり、ストリームごとに出力ピンが作成される。どちらかのストリームのデータが圧縮されている場合、各ストリームの次のフィルタはデコンプレッサ フィルタとなり、その後にレンダリング フィルタが続く。
グラフが構築されたら、アプリケーションは、フィルタ グラフ マネージャから IMediaControl インターフェイスを取得して、Run メソッドを呼び出してファイル再生を開始するだけでよい。
フィルタ グラフで単純にファイルをレンダリングする以外のことをする必要がある場合、少なくともグラフ構築作業の一部は、アプリケーション側で実行する必要がある。たとえば、AVI ファイルを MPEG ファイルに変換するフィルタ グラフを構築している場合、IGraphBuilder::RenderFile を呼び出すことで、引き続きフィルタ グラフ マネージャに AVI 再生グラフを作成させることもできるが、出力をモニタとスピーカではなく MPEG ファイルに送るために、後からグラフを修正する必要がある。これに伴い、ビデオおよびオーディオ レンダリング フィルタの接続を解除して削除し (IGraphBuilder::Disconnect および IGraphBuilder::RemoveFilter を使用)、MPEG ビデオおよびオーディオ コンプレッサ フィルタ、MPEG Multiplexer フィルタ、およびファイル ライタ フィルタと置き換える必要がある。
また、メディア タイプを MPEG コンプレッサが受け入れ可能なタイプに変換するために、中間フィルタを追加する必要がある。アプリケーションには、この中間フィルタを直接追加する方法と、IGraphBuilder::Connect メソッドを使う方法がある。このメソッドを呼び出すと、フィルタ グラフ マネージャは、まずフィルタに直接接続しようと試みる。そこでメディア タイプの調整が付かない場合、フィルタ グラフ マネージャは中間フィルタを検索する。フィルタ グラフ マネージャが特定のメディア タイプを処理可能なフィルタを検索するときは必ず、グラフに既に追加されているフィルタを最初に試す。フィルタ グラフ マネージャが中間フィルタを挿入しないようにするには、IGraphBuilder::ConnectDirect メソッドを使う。
前の例では、アプリケーションはグラフのダウンストリーム部分を構築した。別のシナリオでは、アプリケーションはグラフのアップストリーム部分を構築しなければならないことがある。その場合、手動で追加しなければならないフィルタを一度追加して接続したら、IGraphBuilder::Render メソッドを使って、指定された出力ピンから自動的にグラフを完成するようフィルタ グラフ マネージャに指示できる。オーディオ ピンとビデオ ピンなど、フィルタに 2 つの出力ピンがある場合、アプリケーションは各ピンに対して Render を呼び出す必要がある。
あるシナリオでは、アプリケーションが各フィルタを個別に追加および接続して、グラフ全体を構築しなければならないことがある。この場合は、どのフィルタをグラフに追加しなければならないかが明確に判明していることが多いので、Filter Mapper オブジェクトを使ってフィルタを見つける必要はない。IGraphBuilder::AddFilter メソッドを使って各フィルタをグラフに追加し、 Connect または ConnectDirect のどちらかを使ってフィルタを接続するだけである。
独立系ハードウェア ベンダ (IHV) および家電メーカーにより提供されるキャプチャ デバイスが多岐にわたるため、ビデオ キャプチャ グラフの構築プロセスはかなり複雑になる可能性がある。アプリケーション開発者の負担を軽減するために、DirectShow は別に Capture Graph Builder というオブジェクトを用意している。ビデオ キャプチャ アプリケーションは、このオブジェクトのインスタンスを作成し、その ICaptureGraphBuilder2 インターフェイス メソッドを使って、フィルタ グラフを構築する。グラフ構築の一般原則を理解していれば、キャプチャ グラフの構築作業もほぼ同じ方法で行えることがわかる。詳細については、「キャプチャ アプリケーションの書き方」を参照すること。