次の方法で共有


キャプチャ グラフの制御

フィルタ グラフ マネージャの IMediaControl インターフェイスには、グラフ全体の実行、停止、ポーズを行うメソッドがある。しかし、フィルタ グラフにキャプチャ ストリームとプレビュー ストリームがある場合は、2 つのストリームを別々に制御する必要があることが多い。たとえば、ビデオをプレビューするが、キャプチャはしないことがある。この処理は、ICaptureGraphBuilder2::ControlStream メソッドを使って実行できる。

 :  このメソッドは ASF (Advanced Systems Format) ファイルへのキャプチャ時には動作しない。

キャプチャ ストリームの制御

次のコードは、グラフを実行した1 秒後にビデオ キャプチャ ストリームを開始し、4 秒間実行するように設定する。

// ビデオ キャプチャ ストリームを制御する。
REFERENCE_TIME rtStart = 10000000, rtStop = 50000000;
const WORD wStartCookie = 1, wStopCookie = 2;  // 任意の値。
hr = pBuild->ControlStream(
    &PIN_CATEGORY_CAPTURE, // ピン カテゴリ。
    &MEDIATYPE_Video,      // メディア タイプ。
    pCap,                  // キャプチャ フィルタ。
    &rtStart, &rtStop,     // 開始タイムおよび終了タイム。
    wStartCookie, wStopCookie  // 開始イベントおよび終了イベントの値。
);
pControl->Run();

最初の引数には、ピン カテゴリ GUID として制御するストリームを指定する。2 番目の引数にはメディア タイプを指定する。3 番目の引数はキャプチャ フィルタへのポインタである。グラフ内のすべてのキャプチャ ストリームを制御するには、2 番目と 3 番目の引数を NULL に設定する。

次の 2 つのパラメータには、グラフの実行開始時に相対して、ストリームの開始タイムと終了タイムを指定する。グラフを実行するため、IMediaControl::Run を呼び出す。グラフを実行するまで、ControlStream メソッドを呼び出しても効果はない。グラフが既に実行されている場合、設定はすぐに反映される。

最後の 2 つのパラメータは、ストリームの開始時と停止時にイベント通知を受け取るときに使う。このメソッドを使って制御するストリームごとに、フィルタ グラフはイベントのペアを送信する。ストリームの開始時には EC_STREAM_CONTROL_STARTED、ストリームの停止時には EC_STREAM_CONTROL_STOPPED を送信する。wStartCookiewStopCookie の値が 2 番目のイベント パラメータとして使われる。したがって、開始イベントの lParam2wStartCookie に等しく、終了イベントの lParam2wStopCookie に等しい。次のコードは、これらのイベントを受け取る方法を示している。

while (hr = pEvent->GetEvent(&evCode, &param1, &param2, 0), SUCCEEDED(hr))
{
    switch (evCode)
    {
    case EC_STREAM_CONTROL_STARTED: 
    // param2 == wStartCookie
    break;

    case EC_STREAM_CONTROL_STOPPED: 
    // param2 == wStopCookie
    break;
    
    } 
    pEvent->FreeEventParams(evCode, param1, param2);
}

ControlStream メソッドは開始タイムと終了タイムに特殊な値を定義する。

  開始 終了
MAXLONGLONG このストリームを開始しない。 グラフが停止するまで停止しない。
NULL グラフが実行されるとすぐに開始する。 すぐに停止する。

たとえば、次のコードはキャプチャ ストリームをすぐに停止する。

pBuild->ControlStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, pCap,
    0, 0,     // 開始タイムおよび終了タイム。
    wStartCookie, wStopCookie); 

キャプチャ ストリームを停止し、後で再開できるが、タイム スタンプにはギャップが発生する。再生時には、ギャップの間、ビデオは停止したように見える (ファイル フォーマットにより異なる)。

プレビュー ストリームの制御

プレビュー ピンを制御するには、ControlStream を呼び出すが、最初のパラメータは PIN_CATEGORY_PREVIEW に設定する。この場合、PIN_CATEGORY_CAPTURE を指定したときと同じように動作するが、プレビュー フレームにはタイム スタンプがないため、基準タイムを使って開始と停止は指定できない。したがって、NULL または MAXLONGLONG を使う必要がある。プレビュー ストリームを開始するには、NULL を使う。

pBuild->ControlStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video, pCap,
    NULL,    // すぐに開始する。
    0,       // (ここでは無関係。)
    wStartCookie, wStopCookie); 

プレビュー ストリームを停止するには、MAXLONGLONG を使う。

pBuild->ControlStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video, pCap,
    0,               // (ここでは無関係。)
    MAXLONGLONG,     // すぐに停止する。
    wStartCookie, wStopCookie); 

プレビュー ストリームをキャプチャ フィルタのプレビュー ピンから取得するか、スマート ティー フィルタから取得するかは問題ではない。ControlStream メソッドはどちらでも動作する。

しかし、ビデオ ポート ピンの場合、メソッドは失敗する。その場合、ビデオ ウィンドウを非表示にする方法がある。グラフに IVideoWindow を問い合わせ、IVideoWindow::put_Visible メソッドを使ってウィンドウの表示または非表示を切り替える。

// ビデオ ウィンドウを非表示にする。
IVideoWindow *pVidWin = 0;
hr = pGraph->QueryInterface(IID_IVideoWindow, (void**)&pVidWin);
if (SUCCEEDED(hr))
{
    pVidWin->put_Visible(OAFALSE);
    pVidWin->Release();
}

また、グラフを実行する前に値 OAFALSE を使って IVideoWindow::put_AutoShow を呼び出した場合、他に指定するまで、ビデオ レンダラ フィルタはウィンドウを非表示にする。デフォルトでは、グラフを実行すると、ビデオ レンダラはウィンドウを表示する。

ストリーム制御についての注意点

グラフが実行されるとき、ピンのデフォルト動作はサンプルの送信である。たとえば、PIN_CATEGORY_PREVIEW ではなく PIN_CATEGORY_CAPTURE を使って ControlStream を呼び出すとする。グラフを実行すると、プレビュー ストリームはすぐに実行され、キャプチャ ストリームは ControlStream で指定したタイムに実行される。

複数のストリームをキャプチャし、Mux フィルタに送信する場合 (たとえば、オーディオとビデオを AVI ファイルにキャプチャする場合)、両方のストリームを直列式に制御すること。そうしないと、Mux フィルタは 2 つのストリームをインターリーブしようとし、一方のストリームの到着を待ってブロックされることがある。グラフを実行する前に、すべてのキャプチャ ストリームに同じ開始タイムと停止タイムを設定すること。

pBuild->ControlStream(&PIN_CATEGORY_CAPTURE, 
    NULL, NULL,       // すべてのキャプチャ ストリーム。
    &rtStart, rtStop, 
    wStartCookie, wStopCookie); 

ControlStream メソッドは内部的に IAMStreamControl インターフェイスを使う。このインターフェイスは、キャプチャ フィルタ、スマート ティー フィルタ (存在する場合)、および場合によっては Mux フィルタのピンで公開される。ControlStream を呼び出す代わりに、このインターフェイスを直接使用できる。ただし、特に利点はない。