Microsoft DirectX 8.0 |
ここでは、DirectShow® アーキテクチャにおけるタイムとクロックについて概説する。このトピックは、以下のセクションを含んでいる。
フィルタ グラフ マネージャの 1 つの機能として、グラフ内のフィルタを同期化させることがある。このために、フィルタ グラフ マネージャとフィルタは、基準クロックと呼ばれる同一のクロックを使用する。IReferenceClock インターフェイスをサポートするすべてのオブジェクトは基準クロックとしてのサービスを提供することができる。ハードウェア タイマにアクセスするフィルタは、クロックを提供することができ (たとえばオーディオ レンダラ)、フィルタ グラフ マネージャはシステム タイムを使用するクロックを作成することができる。
実行時、フィルタ グラフ マネージャは基準クロックを選択し、すべてのフィルタの IMediaFilter::SetSyncSource を呼び出してその選択内容を通知する。アプリケーションは、フィルタ グラフ マネージャの SetSyncSource を呼び出すことによって、フィルタ グラフ マネージャが選択したクロックをオーバーライドすることができる。この操作は、別のクロックを使用する明確な理由がある場合にのみ行うこと。
フィルタ グラフ マネージャは、以下の条件に基づいて基準クロックを選択する。
基準クロックは、100 ナノ秒間隔でタイムを計測する。クロックの現在のタイムを取得するには、IReferenceClock::GetTime メソッドを呼び出す。クロックの基線、すなわちカウントを開始するタイムは、クロックの実装に依存するので、返される特定のタイム値は本質的に意味のあるものではない。重要なのは、100 ナノ秒に 1 回の割合で単調増加する値を返すということである。
DirectShow では、基準タイムとストリーム タイムの 2 つの関連クロック タイムを定義している。
フィルタ グラフを実行するためにアプリケーションが IMediaControl::Run を呼び出すと、フィルタ グラフ マネージャはそれぞれのフィルタで IMediaFilter::Run を呼び出す。各フィルタが実行を開始するまでに要するわずかなタイムを補正するために、フィルタ グラフ マネージャは、わずかに進めた開始タイムを指定する。
メディア サンプルは、タイム スタンプとメディア タイムの 2 つのタイム ベースのプロパティを持つ。
タイム スタンプは、ストリーム タイムで示されるサンプルの開始タイムと終了タイムを定義する。タイム スタンプは、プレゼンテーション時間と呼ばれることもある。
フィルタを受け取ると、レンダリング フィルタはタイム スタンプに基づいてレンダリングをスケジュールする。サンプルの到着が遅れたり、タイム スタンプがない場合、フィルタは即座にそのサンプルのレンダリングを開始する。それ以外の場合、フィルタはサンプルの開始タイムまで待ってからそのサンプルのレンダリングを開始する。(フィルタは、IReferenceClock::AdviseTime メソッドを呼び出して開始タイムを待つ。)
ソース フィルタとパーサー フィルタは、処理対象のサンプルに適切なタイム スタンプを設定する責任を負う。以下のガイドラインを使用する。
サンプルにタイム スタンプを設定するには、IMediaSample::SetTime メソッドを呼び出す。
メディア タイムは、シーク可能なメディア内のサンプルの本来の位置 (たとえばディスク上のファイル) を指定する。ビデオの場合、メディア タイムはフレーム番号を表す。オーディオの場合、メディア タイムはパケット内のサンプル番号を表す。たとえば、各パケットに 1 秒の 44.1 kHz オーディオが含まれている場合、最初のパケットのメディア開始タイムはゼロ、メディア終了タイムは 44100 となる。レンダリング フィルタは、メディア タイムのギャップをチェックすることで、フレームまたはサンプルがドロップされたかどうかを調べることができる。
タイム スタンプは、たとえばシーク レートや再生レートなどのソース外の要因に依存するが、メディア タイムは常にオリジナルのソースを基準として計算される。
サンプルのメディア タイムを設定するには、IMediaSample::SetMediaTime メソッドを呼び出す。
プッシュ ソースとも呼ばれるライブ ソースは、メディア データをリアルタイムで受け取る。たとえば、ビデオ キャプチャやネットワーク ブロードキャストなどが例として挙げられる。一般に、ライブ ソースはデータが到着するレートを制御することはできない。ライブ ソース フィルタは、出力ピンで IAMPushSource インターフェイスを実装しなければならない。フィルタ グラフ マネージャはこのインターフェイスを使用して、ライブ ソースがレンダリングされるときに発生する可能性のある 2 つの問題に対処する。
フィルタの遅延時間とは、フィルタがサンプルを処理するのに要する時間である。ライブ ソースの場合、遅延時間はサンプルを保持するためのバッファのサイズによって決まる。たとえばフィルタ グラフがビデオ ソースをレンダリングする際に 33 ミリ秒 (ms) の遅延時間があり、オーディオ ソースをレンダリングする際に 500 ms の遅延時間があるとする。この場合、各ビデオ フレームは、対応するオーディオ サンプルがオーディオ レンダラに到着する約 470 ms 前にビデオ レンダラに到着する。この差異をグラフで補正しないと、オーディオとビデオは同期しない。
アプリケーションが IAMGraphStreams::SyncUsingStreamOffset メソッドを呼び出して同期化を有効にしない限り、フィルタ グラフ マネージャはライブ ソースを同期化しない。同期化が有効にされた場合、フィルタ グラフ マネージャはそれぞれのソース フィルタに対して IAMPushSource インターフェイスを照会する。IAMPushSource をサポートするすべてのフィルタに対して、グラフは IAMLatency::GetLatency を呼び出してフィルタの予想遅延時間を取得し、これらの値から予想最大遅延時間を求める。グラフは次に IAMPushSource::SetStreamOffset を呼び出して各ソース フィルタにストリーム オフセットを与える。フィルタは、このストリーム オフセットを生成するタイム スタンプに加える。
レンダリング フィルタが 1 つの基準クロックを使ってサンプルをスケジュールする一方で、ソース フィルタが異なるクロックを使用してサンプルを生成した場合、再生時にグリッチが発生することがある。レンダラがソースよりも高速に実行すると、データにギャップが生じる。レンダラがソースよりも低速に実行すると、サンプルの処理が"追いつかなくなり"、どこかでデータをドロップしなければならなくなる。通常、ライブ ソースはそのプロダクション レートを制御することができないので、レンダラ側でソースとクロック レートを一致させる。
レート マッチングを行うためには、レンダリング フィルタは別のクロックに従ってそのクロックを設定しなければならない。どのクロックを使用するかは、ソース フィルタがどのようにタイム スタンプを生成するかに依存する。
レンダラは、ソース フィルタの IAMPushSource::GetPushSourceFlags を呼び出して、ソース フィルタがどのようにタイム スタンプを設定するかを求める。オーディオ再生におけるグリッチはビデオにおけるそれよりも著しいので、現在、オーディオ レンダラだけがレート マッチングを実行する。