プレゼンテーションクロック
プレゼンテーションクロックは、プレゼンテーションのクロック時間を生成するオブジェクトです。 プレゼンテーション クロックによって報告される時間は、 プレゼンテーション時間と呼ばれます。 プレゼンテーション内のすべてのストリームは、プレゼンテーション時刻に同期されます。 プレゼンテーション クロックは、次のインターフェイスを公開します。
インターフェイス | 説明 |
---|---|
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 インターフェイスを公開する任意のオブジェクトを指定できます。 次に、このプロセスの図を示します。
プレゼンテーション クロックが最初に作成されるときは、タイム ソースがありません。 タイム ソースを設定するには、タイム ソースの IMFPresentationTimeSource インターフェイスへのポインターを使用して、IMFPresentationClock::SetTimeSource を呼び出します。 タイム ソースでは、プレゼンテーション クロックと同じ状態 (実行中、一時停止、停止) がサポートされており、 IMFClockStateSink インターフェイスを実装する必要があります。 プレゼンテーション クロックでは、このインターフェイスを使用して、状態を変更するタイミングをタイム ソースに通知します。 このように、タイム ソースはクロック ティックを提供しますが、プレゼンテーション クロックはクロックの状態の変化を開始します。
一部のメディア シンクでは正確なクロックにアクセスできるため、 IMFPresentationTimeSource インターフェイスが公開されます。 特に、オーディオ レンダラーでは、サウンド カードの周波数をクロックとして使用できます。 オーディオ再生では、オーディオ レンダラーがタイム ソースとして機能し、ビデオがオーディオ再生レートに同期されるようにすると便利です。 これは一般に、オーディオを外部クロックに一致させるよりも優れた結果を生成します。
Media Foundation には、システム クロックに基づくプレゼンテーションのタイム ソースも用意されています。 このオブジェクトを作成するには、 MFCreateSystemTimeSource を呼び出します。 システム タイム ソースは、タイム ソースを提供するメディア シンクがない場合に使用できます。
一般に、メディア シンクでは、プレゼンテーション クロックが使用するタイム ソースに関係なく、提供されるプレゼンテーション クロックを使用する必要があります。 この規則は、メディア シンクが IMFPresentationTimeSource を実装する場合でも適用されます。 プレゼンテーション クロックで他のタイム ソースを使用する場合、メディア シンクは、独自の内部クロックではなく、そのタイム ソースに従う必要があります。
メディア シンクがプレゼンテーション クロックに従わない場合は、次の 2 つの状況があります。
一部のメディア シンクは レートレスです。 メディア シンクがレートレスの場合、プレゼンテーション クロックに従ってスケジュールを設定することなく、可能な限り迅速にサンプルを消費します。 通常、レートレス シンクはデータをファイルに書き込むため、できるだけ早く操作を完了することが望ましいです。 レートレス シンクは、 IMFMediaSink::GetCharacteristics メソッドでMEDIASINK_RATELESS フラグを返します。 トポロジ内のすべてのシンクがレートレスの場合、メディア セッションは可能な限り迅速にパイプラインを介してデータをプッシュします。
一部のメディア シンクでは、それ自体以外のタイム ソースとレートを一致させることはできません。 その場合、シンクは GetCharacteristics メソッドでMEDIASINK_CANNOT_MATCH_CLOCK フラグを返します。 パイプラインでは別のタイム ソースを引き続き使用できますが、結果は最適ではありません。 シンクが遅れ、再生中に不具合が発生する可能性があります。
関連トピック