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 つのフィルタをすべてチェーン接続する。たとえば、ABC がフィルタだとする。ここでは、各フィルタが 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();
}

参照