Capture Graph Builder を使ったグラフ作成
Capture Graph Builder は、その名前とは異なり、キャプチャ グラフだけでなく、さまざまな種類のカスタム フィルタ グラフ作成に役立つ。ここでは、このオブジェクトの使い方の概要を簡単に示す。
Capture Graph Builder は、ICaptureGraphBuilder2 インターフェイスを公開する。最初に、CoCreateInstance を呼び出して Capture Graph Builder とフィルタ グラフ マネージャを作成する。次に、Capture Graph Builder を初期化するため、次のようにフィルタ グラフ マネージャへのポインタを使って ICaptureGraphBuilder2::SetFiltergraph を呼び出す。
IGraphBuilder *pGraph = NULL;
ICaptureGraphBuilder2 *pBuilder = NULL;
// フィルタ グラフ マネージャを作成する。
HRESULT hr = CoCreateInstance(CLSID_FilterGraph, NULL,
CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&pGraph);
if (SUCCEEDED(hr))
{
// Capture Graph Builder を作成する。
hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL,
CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2,
(void **)&pBuilder);
if (SUCCEEDED(hr))
{
pBuilder->SetFiltergraph(pGraph);
}
};
フィルタの接続
ICaptureGraphBuilder2::RenderStream メソッドは 2 つまたは 3 つのフィルタをチェーン接続する。一般に、このメソッドが最もうまく動作するのは、各フィルタに同じタイプの入力ピンか出力ピンが 1 つしかない場合である。RenderStream の最初の 2 つのパラメータは無視し、最後の 3 つのパラメータから説明を始める。3 番目のパラメータは IUnknown ポインタである。このポインタは、フィルタ (IBaseFilter インターフェイス ポインタとして) または出力ピン (IPin インターフェイス ポインタとして) を指定できる。4 番目と 5 番目のパラメータは IBaseFilter ポインタを指定する。RenderStream メソッドは 3 つのフィルタをすべてチェーン接続する。たとえば、A、B、C がフィルタだとする。ここでは、各フィルタが 1 つの入力ピンと 1 つの出力ピンを持つと仮定する。次の呼び出しは A を B に接続した後、B を C に接続する。
RenderStream(NULL, NULL, A, B, C)
すべての接続は "インテリジェント" 接続である。つまり、必要に応じてさらにグラフにフィルタが追加される。詳細については、「インテリジェント接続」を参照すること。2 つのフィルタだけを接続するには、真ん中の値を NULL に設定する。たとえば、次の呼び出しは A を C に接続する。
RenderStream(NULL, NULL, A, NULL, C)
メソッドを 2 回呼び出すと、さらに長いチェーンを作成できる。
RenderStream(NULL, NULL, A, B, C)
RenderStream(NULL, NULL, C, D, E)
最後のパラメータが NULL である場合、メソッドは自動的にデフォルト レンダラを探す。ビデオにはビデオ レンダラ、オーディオには DirectSound レンダラを使う。つまり、次のようになる。
RenderStream(NULL, NULL, A, NULL, NULL)
上の例は次の例と等しい。
RenderStream(NULL, NULL, A, NULL, R)
ここで、R は該当するレンダラを示す。しかし、ビデオ レンダラの代わりに Video Mixing Renderer フィルタを接続するには、明示的に指定する必要がある。
3 番目のパラメータにピンではなくフィルタを指定する場合、接続に使う出力ピンの指定が必要なことがある。これがメソッドの最初の 2 つのパラメータが持つ役割である。最初のパラメータはキャプチャ フィルタにしか適用されない。このパラメータはピンのカテゴリを示す GUID を指定する。カテゴリの一覧については、「ピン プロパティ セット」を参照すること。次の 2 つのカテゴリは、すべてのキャプチャ フィルタに有効である。
- PIN_CATEGORY_CAPTURE
- PIN_CATEGORY_PREVIEW
キャプチャ フィルタがキャプチャとプレビュー用に別のピンを提供しない場合、RenderStream メソッドはスマート ティー フィルタを挿入する。このフィルタはストリームをキャプチャ ストリームとプレビュー ストリームに分割する。アプリケーション側から見ると、すべてのキャプチャ フィルタが異なるピンを持つものとして扱い、グラフの基になるトポロジを無視できる。
ファイル キャプチャでは、Mux フィルタにキャプチャ ピンを接続する。ライブ プレビューでは、レンダラにプレビュー ピンを接続する。2 つのカテゴリを切り替えると、グラフはファイル キャプチャ中に多数のフレームをドロップすることがある。しかし、グラフの接続が適切であれば、キャプチャ ストリームでのスループットを保持するため、必要に応じてプレビュー フレームがドロップする。
次の例は、両方のストリームを接続する方法を示す。
// ファイルへのキャプチャ。
pBuilder->RenderStream(&PIN_CATEGORY_CAPTURE, NULL, pCapFilter, NULL, pMux);
// プレビュー。
pBuilder->RenderStream(&PIN_CATEGORY_PREVIEW, NULL, pCapFilter, NULL, NULL);
一部のキャプチャ フィルタでは、PIN_CATEGORY_VBI により示されるクローズド キャプションもサポートしている。クローズド キャプションをファイルにキャプチャするには、Mux フィルタにこのカテゴリをレンダリングする。プレビュー ウィンドウにクローズド キャプションを表示するには、レンダラに接続する。
// ファイルへのキャプチャ。
pBuilder->RenderStream(&PIN_CATEGORY_VBI, NULL, pCapFilter, NULL, pMux);
// 画面でのプレビュー。
pBuilder->RenderStream(&PIN_CATEGORY_VBI, NULL, pCapFilter, NULL, NULL);
RenderFile の 2 番目のパラメータはメディア タイプを識別する。通常は、次のいずれか 1 つである。
- MEDIATYPE_Audio
- MEDIATYPE_Video
- MEDIATYPE_Interleaved (DV)
フィルタの出力ピンが優先メディア タイプの列挙をサポートしているときは、常にこのパラメータを使える。ファイル ソースの場合、Capture Graph Builder は必要に応じて自動的にパーサー フィルタを追加し、パーサーのメディア タイプを問い合わせる。(例については、「AVI ファイルの再圧縮」を参照すること。)また、チェーンの最後のフィルタに複数の入力ピンがある場合、メソッドはそのメディア タイプを列挙しようとする。ただし、この機能をサポートしていないフィルタもある。
フィルタとピンのインターフェイスの検索
グラフを作成した後、通常はグラフのフィルタとピンで公開されるさまざまなインターフェイスを検索する必要がある。たとえば、キャプチャ フィルタは IAMDroppedFrames インターフェイスを公開し、フィルタの出力ピンは IAMStreamConfig インターフェイスを公開することがある。
インターフェイスを検索する最も簡単な方法は、ICaptureGraphBuilder2::FindInterface メソッドを使うことである。このメソッドは、対象インターフェイスが見つかるまで、グラフ (フィルタとピン) をトラバースする。検索の始点を指定できる。また、フィルタの検索を始点からダウンストリーム方向かアップストリーム方向に限定できる。
次の例は、ビデオ プレビュー ピンで IAMStreamConfig インターフェイスを検索する。
IAMStreamConfig *pConfig = NULL;
HRESULT hr = pBuild->FindInterface(
&PIN_CATEGORY_PREVIEW,
&MEDIATYPE_Video,
pVCap,
IID_IAMStreamConfig,
(void**)&pConfig
);
if (SUCCESSFUL(hr))
{
/* ... */
pConfig->Release();
}
ピンの検索
ときには、フィルタ上にある個々のピンの検索が必要になることがある。ただし、ほとんどの場合、RenderStream メソッドと FindInterface メソッドを使えば、問題は解決する。どうしてもフィルタの個々のピンを検索する必要がある場合は、ICaptureGraphBuilder2::FindPin ヘルパー メソッドが役立つ。カテゴリ、メディア タイプ (ビデオまたはオーディオ)、方向、および未接続ピンであることが必要かどうかを指定する。
たとえば、次のコードはキャプチャ フィルタで未接続のビデオ プレビュー ピンを検索する。
IPin *pPin = NULL;
hr = pBuild->FindPin(
pCap, // 検索するフィルタへのポインタ。
PINDIR_OUTPUT, // 出力ピンの検索。
&PIN_CATEGORY_PREVIEW, // プレビュー ピンの検索。
&MEDIATYPE_Video, // ビデオ ピンの検索。
TRUE, // ピンは未接続でなければならない。
0, // 最初に一致するピンを返す (インデックス 0)。
&pPin); // この変数は IPin ポインタを受け取る。
if (SUCCESSFUL(hr))
{
/* ... */
pPin->Release();
}
参照