タイム スタンプと期間
このトピックでは、 Media Foundation Transforms でタイム スタンプを処理する方法について説明します。
MFT は、すべての出力サンプルで可能な限り正確なタイム スタンプと期間を設定する必要があります。 1 つの入力バッファーを受け取り、出力バッファーに完全に処理する単純な MFT の場合、MFT は入力サンプルから出力サンプルにタイム スタンプと期間を直接コピーするだけです。 ただし、多くの変換はこれよりも複雑であり、出力時間のより複雑な計算が必要になる場合があります。 すべての MFT は、次の基本的な規則に従う必要があります。
- MFT では、入力サンプルに正確なタイム スタンプまたは期間が指定されているか、計算できる場合は、圧縮されていないすべてのビデオまたはオーディオ出力サンプルにタイム スタンプと期間を設定する必要があります。 一部の出力タイムスタンプ (特にデコーダーの場合) には補間が必要になる場合があります。
- 入力サンプルのタイム スタンプと期間は、可能な限り出力サンプルに保持する必要があります。
- MFT がデータを保持しているか、出力を入力とは異なるサイズに分割しているため、出力タイム スタンプまたは期間が入力と一致しない可能性があります。 その場合、MFT は、出力サンプルの作成に使用されるデータを含む最も古い入力サンプルから出力タイム スタンプを計算する必要があります。 出力タイムスタンプを計算するには、適切な入力サンプルの入力タイム スタンプを、そのサンプルから既に変換されているデータの期間に追加します。 このセクションの最後にある 2 番目の例は、このアイデアを示しています。
- 入力サンプルに期間がある場合は、その期間を保持する必要があります。 入力サンプルに期間がない場合、MFT は、可能であれば、出力バッファーのサイズまたはメディアの種類によって指定されたデータ レートから期間を計算する必要があります。
- 計算された期間は、最も近い増分に丸めずに切り捨てる (切り捨てる) 必要があります。 パイプラインには、少し不正確な期間を処理するのに十分な余裕がありますが、1% 長すぎる期間よりも 1% 短すぎる期間をパイプラインで処理する方が簡単です。 とはいえ、丸め以外に意図的に期間を短縮する理由はありません。
デコーダー
デコーダーは、圧縮されたパケットを非圧縮データに変換します。 出力は圧縮されていないため、デコーダーにはタイム スタンプと期間を正しく取得する特別な義務があります。 一部の圧縮形式 (特に MPEG-2) には、すべての入力パケットにタイム スタンプがなく、多くの場合、パケットの期間がありません。 これらの形式では、デコーダーは、すべての出力サンプルに有効なタイム スタンプと期間を設定し、最後のタイムスタンプ入力サンプル以降のすべての出力の暗黙の期間を合計します。
ビデオの場合、期間が圧縮形式で使用できない場合、デコーダーはフレーム レートの逆として期間を計算し、100 ナノ秒単位に変換して切り捨てる必要があります。
オーディオの場合、期間が圧縮形式で使用できない場合、デコーダーは、オーディオ サンプル レートの逆数に出力バッファー内のサンプル数を乗算し、100 ナノ秒単位に変換し、切り捨てて期間を計算する必要があります。
変換がタイム スタンプなしでサンプルを出力する唯一の時間は、MFT が入力サンプルのタイム スタンプを受信したことがない場合、または前の入力タイム スタンプから正確な出力タイムスタンプを計算する方法がない場合です。
オーディオ デコーダー
オーディオ デコーダーの場合、各出力サンプルの期間は、オーディオ サンプリング レートと出力バッファー内のチャネルあたりの PCM サンプル数から計算されます。
出力タイムスタンプを計算する正しい方法は、入力サンプルにタイム スタンプが含まれているかどうかによって異なります。
入力サンプルにタイム スタンプが含まれている場合、デコーダーは次のように入力タイムスタンプから出力タイムスタンプを計算します。
- 各入力バッファーに 1 つ以上の完全な圧縮フレームが含まれている場合、部分的なフレームがない場合、出力タイム スタンプは入力タイム スタンプと等しく、デコーダーの既知の待機時間を差し引いた値になります。 たとえば、Dolby Digital (AC-3) デコーダーの待機時間は 256 個の PCM サンプルです。 たとえば、48 kHz のサンプリング レートでは、待機時間は 5.33 ミリ秒 (ミリ秒) です。 したがって、入力タイム スタンプが 1000 ミリ秒の場合、出力タイム スタンプは 1000 – 5.33 = 994.66 ミリ秒です。 入力バッファーに圧縮されたフレーム全体が複数含まれている場合、デコーダーは入力サンプル内のすべてのフレームに対して 1 つの出力サンプルを生成します。 すべての出力サンプルには、ギャップが生じないため、正しくタイムスタンプが設定されます。
- トランスポート形式によっては、入力バッファーに部分フレームが含まれる場合があります。 たとえば、バッファーには、前の入力バッファーのフレームの一部が含まれている場合があり、その後に 1 つ以上の完全なフレームが続き、次のフレームの開始が続きます。 この場合、通常は、入力タイム スタンプがバッファー内で開始される最初のフレームに対応していると仮定するのが正しいです。 (つまり、前のバッファーで開始された部分フレームは、現在のバッファーのタイム スタンプには含まれません)。それに応じて出力タイムスタンプを計算します。
入力サンプルにタイム スタンプが含まれていない場合:
- デコーダーは、最初の出力タイム スタンプを 0 に設定して、独自のタイム スタンプを生成する必要があります。
- サンプル期間は、バッファー内の出力サンプルの数とサンプル レートから計算されます。
- 後続のタイム スタンプは、前のタイム スタンプと期間から計算されます。 現在のタイム スタンプ + 現在の期間 = 次のタイム スタンプ。 出力タイム スタンプにギャップはありません。
入力ストリームに最初にタイム スタンプが含まれているが、何らかの理由でタイム スタンプが切り替わる場合、デコーダーは連続していてギャップが生じないため、独自の出力タイム スタンプを生成し続ける必要があります。
入力ストリームにタイム スタンプが含まれているが、時刻にギャップがある場合、デコーダーはこれらのギャップを伝達するだけです。 つまり、デコーダーは、入力ストリーム内の一貫性のないタイム スタンプを修正しようとしないでください。
ミキサー
注意
Windows Vista では、Media Foundation パイプラインでは、複数の入力を持つ MFT はサポートされていません。 Windows 7 では、複数入力の MFT がサポートされています。
ミキサーは複数の入力を受け取り、1 つの出力にミックスします。 入力ストリームが完全にレートロックされていない場合、または互いにわずかにオフセットされている場合は、出力に設定する時間があいまいになる可能性があります。 メディアの種類に応じて、いくつかのガイドラインを次に示します。
オーディオ。 起動時またはドレインまたはフラッシュの直後に、オーディオ ミキサーは、必要なすべての入力ストリームで入力サンプルを受信するまで、出力サンプルの生成を待機する必要があります。 その時点で、出力タイム スタンプのベースラインとして使用する初期サンプルの最も古いタイム スタンプを選択する必要があります。 他のストリームは、時間の不一致を埋めるために無音で埋め込む必要があります。 省略可能な入力ストリームでサンプルを受け取る場合は、計算にも考慮する必要があります。 その時点から、MFT は出力タイム スタンプの連続した切れ目のないチェーンを生成するように努める必要があります。 一般に、MFT では、あるストリームが別のストリームに対して相対的にドリフトすることを考慮しないでください。 代わりに、ベースライン タイム スタンプ、出力レート、バッファー サイズから出力タイム スタンプを計算する必要があります。 別のドレインまたはフラッシュが発生すると、MFT はベースライン タイム スタンプをリセットする必要があります。
ビデオ。 起動時またはドレインまたはフラッシュの直後に、ビデオ ミキサーは、必要なすべての入力ストリームで入力サンプルを受信するまで、出力サンプルの生成を待機する必要があります。 その時点で、出力タイム スタンプのベースラインとして使用する初期サンプルの最も古いタイム スタンプを選択する必要があります。 一般に、入力フレームを繰り返すことで、必要に応じて、入力が規則的でない場合でも、継続的かつ定期的な出力タイムスタンプと固定期間を維持するように努める必要があります。
エンコーダー
エンコーダーは、圧縮されていないオーディオまたはビデオを圧縮されたパケットに変換します。 エンコーダーは、次のガイドラインに従う必要があります。
エンコーダーは、出力形式の規則に従う必要があります。 形式が通常、MPEG-2 のようにすべてのサンプルにタイム スタンプを設定しない場合、すべての出力サンプルにタイム スタンプと期間が必要なわけではありません。
アプリケーション自体など、別のソースからより適切なタイム情報を使用できる場合を除き、形式にタイム スタンプのフィールドがある場合は、入力タイムスタンプを出力形式で保持する必要があります。
マルチプレクサー
注意
Windows Vista では、Media Foundation パイプラインでは、複数の入力を持つ MFT はサポートされていません。 Windows 7 では、複数入力の MFT がサポートされています。
マルチプレクサーは、2 つの異なるオーディオまたはビデオ ストリームを、AVI や MPEG-2 トランスポート ストリームなどの 1 つのインターリーブ形式に結合します。 マルチプレクサーは、次のガイドラインに従う必要があります。
マルチプレクサは、出力形式の規則に従う必要があります。 形式が通常、MPEG-2 のようにすべてのサンプルにタイム スタンプを設定しない場合、すべての出力サンプルにタイム スタンプと期間が必要なわけではありません。
タイム スタンプには、そのパケットで始まるフレームに配置される最も早い時刻、またはそのパケットからデコードされる最初のオーディオ サンプルの時刻が反映されます。 出力形式の規則と競合する場合は、このガイドラインを無視します。
デマルチプレクサー
デマルチプレクサーは、AVI や MPEG-2 トランスポート ストリームなどのインターリーブ形式を基になるオーディオストリームとビデオ ストリームに分割します。
形式に、入力タイムスタンプに基づいて正確な出力タイム スタンプを計算するために使用できる特定のタイム スタンプ情報が含まれている場合は、その情報を使用する必要があります。 ただし、書式に、入力タイム スタンプに関係のないまったく異なるベースの時刻が含まれており、入力タイム スタンプへの正確なオフセットを計算できない場合は、書式の独自の時刻を無視する必要があります。
形式に使用可能なタイム スタンプ情報がない場合、デマルチプレクサーは次の規則に従う必要があります。
圧縮されていない出力ストリームには、可能であれば、最も近い以前の入力タイム スタンプから計算された有効なタイム スタンプと期間が必要です。
圧縮された出力ストリームには、タイム スタンプを含む入力サンプルから派生した最初の出力サンプルにのみタイム スタンプが含まれている必要があります。 入力サンプルにタイム スタンプがない場合、その入力サンプルから派生した出力サンプルにはタイム スタンプを含める必要はありません。 入力サンプルが複数の出力サンプルに分割されている場合は、最初の出力サンプルのみがタイム スタンプを持ち、残りにはタイム スタンプを含めてはなりません。
例
例 1. ビデオ効果は常に圧縮されていない入力フレームを受け取り、効果を適用して出力にコピーするとします。 フレームを保持したり、入力をバッファーしたりすることはありません。 この MFT は、入力サンプルから出力サンプルにタイム スタンプと期間をコピーするだけで、使用可能な場合は出力サンプルにコピーされ、時間計算はまったく行われません。
例 2. オーディオ効果が各入力バッファーの 10 ミリ秒 (ms) を超えるすべてを変換し、追加の 10 ミリ秒を保存して次のバッファーと結合するとします。 すべての期間が 50 ミリ秒であるサンプルのストリームを取得します。 入力時間を次の表に示します。
サンプル | 入力時間 | 入力期間 | 出力時間 | 出力期間 |
---|---|---|---|---|
1 | 20 | 50 | 20 | 40 |
2 | 70 | 50 | 60 | 50 |
3 | 121 | 50 | 110 | 50 |
4 | 171 | 50 | 161 | 50 |
サンプル 2 の実際の期間と、次のタイム スタンプ (121 ? 70 = 51) に基づく暗黙の期間の間の 1 ミリ秒の不一致に注意してください。
MFT は 10 ミリ秒を保持するため、入力サンプル 1 の最初の 40 ミリ秒を出力サンプル 1 として出力し、タイム スタンプは 20 ミリ秒、期間は 40 ミリ秒です。
出力サンプル 2 は、以前に保持されていた 10 ミリ秒と 40 ミリ秒の入力サンプル 2 を組み合わせたものになります。 このサンプルには、60 ミリ秒 (前の入力サンプルのタイム スタンプ、20 ミリ秒、そのサンプルから既に処理されたデータの期間、40 ミリ秒) が与えられます。 期間は 50 ミリ秒です。
同様に、次のサンプルのタイム スタンプは 110 ミリ秒 (70 ミリ秒 + 40 ミリ秒) で、期間は 50 ミリ秒です。
次の計算の方が興味深いです。 以前の出力時刻と期間からの暗黙的なタイム スタンプは 160 ミリ秒 (タイム スタンプ 110 ms + 期間 50 ミリ秒) になります。 ただし、出力タイム スタンプは、出力サンプルに時間単位で重なる最も古い入力サンプルの入力タイム スタンプと、そのサンプルから既に処理されているデータの長さを加えた値から計算されます。 最も近い重複する入力サンプルはサンプル 4 (タイム スタンプ = 171) ですが、これは最も古いサンプルではありません。 最も古い重複するサンプルは、サンプル 3 (タイム スタンプ = 121) です。 そのサンプルから既に処理されている 40 ミリ秒を追加すると、結果は 161 になります。
関連トピック