キャプチャ グラフの制御
フィルタ グラフ マネージャの 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 を送信する。wStartCookie と wStopCookie の値が 2 番目のイベント パラメータとして使われる。したがって、開始イベントの lParam2 は wStartCookie に等しく、終了イベントの lParam2 は wStopCookie に等しい。次のコードは、これらのイベントを受け取る方法を示している。
while (hr = pEvent->GetEvent(&evCode, ¶m1, ¶m2, 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 を呼び出す代わりに、このインターフェイスを直接使用できる。ただし、特に利点はない。