プレゼンテーションクロック
プレゼンテーションクロック は、プレゼンテーションのクロック時間を生成するオブジェクトです。 プレゼンテーションクロックによって報告される時間は、プレゼンテーション時間と呼ばれます。 プレゼンテーション内のすべてのストリームは、プレゼンテーション時刻に同期されます。 プレゼンテーション クロックは、次のインターフェイスを公開します。
インターフェイス | 形容 |
---|---|
IMFPresentationClock | プレゼンテーション クロックを使用するためのプライマリ インターフェイス。 |
IMFRateControlの | クロック レートを制御します。 |
IMFTimerの | タイマー コールバックを提供します。 |
IMFShutdown | プレゼンテーション クロックをシャットダウンします。 |
メディア シンクでは、プレゼンテーション時間を使用して、サンプルをレンダリングするタイミングをスケジュールします。 メディア シンクは、新しいサンプルを受け取るたびに、サンプルからタイム スタンプを取得し、指定された時刻、または可能な限りその時刻に近い時点でサンプルをレンダリングします。 トポロジ内のすべてのメディア シンクは同じプレゼンテーション クロックを共有するため、複数のストリーム (オーディオやビデオなど) が同期されます。 メディア ソースと変換では、プレゼンテーション クロックは使用されません。これは、サンプルを配信するタイミングをスケジュールしないためです。 代わりに、パイプラインが新しいサンプルを要求するたびにサンプルを生成します。
再生にメディア セッションを使用している場合、メディア セッションは、プレゼンテーション クロックの作成、タイム ソースの選択、メディア シンクへの通知のすべての詳細を処理します。 アプリケーションでは、再生中にプレゼンテーションクロックを使用して現在のプレゼンテーション時間を取得できますが、それ以外の場合はプレゼンテーションクロックでメソッドを呼び出しません。
クロック時間とクロックの状態
プレゼンテーション クロックから最新のクロック時間を取得するには、IMFPresentationClock::GetTime呼び出します。 クロック時間は常に 100 ナノ秒単位であるため、1 秒は 10,000,000 (10^7) ティックです。 これは 10 MHz の周波数に対応します。
プレゼンテーション クロックには、実行中、一時停止、停止の 3 つの状態があります。
- クロックを実行するには、IMFPresentationClock::Start呼び出します。 Start メソッドは、クロックの開始時刻を指定します。 クロックの実行中、クロック時間は開始時刻から現在のクロック レートでインクリメントされます。
- クロックを一時停止するには、IMFPresentationClock::P ause呼び出します。 クロックが一時停止している間、クロック時間は進まず、GetTimeはクロックが一時停止された時刻を返します。
- クロックを停止するには、IMFPresentationClock::Stop呼び出します。 クロックが停止すると、クロック時間は進まず、GetTimeは 0 を返します。
既定では、クロックは 1.0 の速度で進みます。つまり、100 ナノ秒あたり 1 ティックです。 クロックが進む速度を変更するには、IMFRateControl インターフェイスのプレゼンテーション クロックに対してクエリを実行し、IMFRateControl::SetRate呼び出します。
オブジェクトは、プレゼンテーション クロックから状態変更 (レート変更を含む) の通知を受け取ることができます。 通知を受信するには、IMFClockStateSink インターフェイスを実装し、プレゼンテーション クロック IMFPresentationClock::AddClockStateSink を呼び出します。 シャットダウンする前 、IMFPresentationClock::RemoveClockStateSink を呼び出してオブジェクトの登録を解除します。 メディア シンクでは、このメカニズムを使用してクロックから通知を受信します。
プレゼンテーション時間
メディア シンクは、サンプルが正しい時刻にレンダリングされるように、または可能な限り正しい時刻に近いように、各サンプルのスケジュールを設定しようとします。 次の定義が適用されます。
- プレゼンテーション時間。 サンプルをレンダリングする時刻。 時間は 100 ナノ秒単位で指定されます。
- メディア時間。 コンテンツの開始位置を基準とした時間。 たとえば、ビデオ ファイルの長さが 10 秒の場合、ファイルの途中のポイントのメディア時間は 5 秒になります。
- タイム スタンプ。 メディア サンプルでマークされた時刻。 タイムスタンプを取得するには、IMFSample::GetSampleTimeを呼び出します。 メディア ソースは、サンプルを生成するときに、メディア時刻と等しいタイム スタンプを設定します。 メディア セッションは、タイム スタンプをプレゼンテーション時間に変換します。
既定では、メディア時間とプレゼンテーション時間は同じです。たとえば、ビデオ フレームがソース ファイルに 5 秒表示される場合、メディア時間とプレゼンテーション時間は両方とも 5 秒です。 Sequencer Sourceを使用している場合、セグメント間のスムーズな遷移を可能にするために、タイミング モデルはやや複雑になります。 シーケンサー ソースのタイミング モデルの詳細については、「シーケンス プレゼンテーション時間」を参照してください。
メディア ソースは、常にメディア時刻と等しいタイム スタンプを設定します。 プレゼンテーション時間がメディア時間と一致しない場合、メディア セッションはメディア サンプルのタイムスタンプを変換します。 シンクがサンプルを受け取る時点までに、サンプルのタイム スタンプはプレゼンテーション時間に変換されています。 シンクは、プレゼンテーション クロックの現在の時刻に対してサンプルをスケジュールします。 (レートレス シンクは、プレゼンテーション クロックを無視するため、例外です)。
アプリケーションが新しい位置にシークする場合、メディア セッションは指定されたシーク時間にプレゼンテーション クロックを再起動します。 たとえば、アプリケーションがファイル内の 5 秒の位置をシークする場合、メディア セッションは 5 秒でクロックを開始します。 シーク時間がキー フレーム境界に収まらない場合、メディア ソースは、少し前のタイム スタンプでサンプルを配信する可能性があります。 これは、デコーダーがすべてのフレームをデコードできるようにするために必要です。 メディア セッションは、要求されたシーク時間に合わせて、メディア シンクに到達する前にサンプルをドロップまたはトリミングします。 たとえば、シーク時間が 5 秒の場合、最初のオーディオ サンプルは 4.5 秒から始まる可能性があります。 メディア セッションは、デコードされた最初のオーディオ サンプルから最初の 0.5 秒をトリミングします。
プレゼンテーション クロックの作成
プレゼンテーション クロックを作成するには、MFCreatePresentationClock呼び出します。 クロックをシャットダウンするには、IMFShutdown インターフェイスを照会し、IMFShutdown::Shutdownを呼び出します。 MFCreatePresentationClock の呼び出し元は、Shutdownを呼び出す役割を担います。ほとんどの場合、これはアプリケーションではなくメディア セッションです。
プレゼンテーションの時間ソース
その名前にもかかわらず、プレゼンテーション クロックは実際にはクロックを実装しません。 代わりに、プレゼンテーションタイムソースと呼ばれる別のオブジェクトからクロックタイムを取得します。 タイム ソースには、正確なクロック ティックを生成し、IMFPresentationTimeSource インターフェイスを公開する任意のオブジェクトを指定できます。 次の図は、このプロセスを示しています。
プレゼンテーション クロックが最初に作成されるときは、タイム ソースがありません。 タイム ソースを設定するには、IMFPresentationClock::SetTimeSource を呼び出し、タイム ソースの IMFPresentationTimeSource インターフェイスへのポインターを指定します。 タイム ソースでは、プレゼンテーション クロックと同じ状態 (実行中、一時停止、停止) がサポートされており、IMFClockStateSink インターフェイスを実装する必要があります。 プレゼンテーション クロックでは、このインターフェイスを使用して、状態を変更するタイミングをタイム ソースに通知します。 このように、タイム ソースはクロック ティックを提供しますが、プレゼンテーション クロックはクロックの状態変更を開始します。
一部のメディア シンクは正確なクロックにアクセスできるため、IMFPresentationTimeSource インターフェイスが公開されます。 特に、オーディオ レンダラーでは、サウンド カードの周波数をクロックとして使用できます。 オーディオ再生では、オーディオ レンダラーがタイム ソースとして機能し、ビデオがオーディオ再生レートに同期されるようにすると便利です。 これは一般に、オーディオを外部クロックに一致させるよりも優れた結果を生成します。
Media Foundation には、システム クロックに基づくプレゼンテーションのタイム ソースも用意されています。 このオブジェクトを作成するには、MFCreateSystemTimeSource呼び出します。 システム タイム ソースは、タイム ソースを提供するメディア シンクがない場合に使用できます。
一般に、メディア シンクは、プレゼンテーション クロックが使用するタイム ソースに関係なく、提供されるプレゼンテーション クロックを使用する必要があります。 この規則は、メディア シンクが IMFPresentationTimeSource実装する場合でも適用されます。 プレゼンテーション クロックが他のタイム ソースを使用する場合、メディア シンクは、独自の内部クロックではなく、そのタイム ソースに従う必要があります。
メディア シンクがプレゼンテーション クロックに従わない場合は、次の 2 つの状況があります。
一部のメディア シンクはレートレス 。 メディア シンクがレートレスの場合、プレゼンテーション クロックに従ってスケジュールを設定することなく、可能な限り迅速にサンプルを消費します。 通常、レートレス シンクはデータをファイルに書き込むため、できるだけ早く操作を完了することが望ましいです。 レートレス シンクは、IMFMediaSink::GetCharacteristics メソッドでMEDIASINK_RATELESS フラグを返します。 トポロジ内のすべてのシンクがレートレスの場合、メディア セッションは可能な限り迅速にパイプラインを介してデータをプッシュします。
一部のメディア シンクでは、それ以外のタイム ソースとレートを一致させることはできません。 その場合、シンクは、GetCharacteristics メソッドでMEDIASINK_CANNOT_MATCH_CLOCK フラグを返します。 パイプラインでは別のタイム ソースを引き続き使用できますが、結果は最適ではありません。 シンクが遅れ、再生中にグリッチが発生する可能性があります。
関連トピック