Tags: コラボレーションソリューション, リアルタイムメディア シリーズ, 高画質ビデオ, 高音質オーディオ
これまでのブログ記事で、SDP の概要と、オファー/アンサー交換によるネゴシエーションでの SDP の使用方法を説明してきました今回のブログでは、SDP で H.264 をネゴシエートする方法を見ていきます。
リアルタイムのビデオ会議で使用されるオーディオコーデックとビデオコーデックには、いずいれも SDP でのネゴシエーション方法に関する固有の仕様があります。このシリーズではこれらのコーデックのすべては取り上げず、H.264 ビデオコーデックに焦点を絞ります。H.264 は至るところで使用されているだけでなく、直感的であるとは言えない一連の複雑なコーデックパラメータがあるためです。さらに、その仕様には、常に準拠されるわけではない部分もあります。H.264 の仕様は RFC6184(以前は RFC3984)ですが、特定の側面については ITU シリーズ H の H.264 エンコーディング/デコーディング仕様 [英語] を参照する必要があります。
H.264 ネゴシエーションの単純な部分は、rtpmap です。ペイロードタイプとして「H264/90000」を指定するだけで、H.264 をネゴシエートできます。当然のことながら、fmtp 行に含まれるペイロード固有のパラメータとなると、複雑になってきます。fmtp 行の内容は、次の例のようになります。
a=fmtp:126 profile-level-id=42e016;packetization-mode=1;max-mbps=244800;max-fs=8160
このブログでは、これらの要素の意味について説明します。
H.264 では、6 文字のなかに多くの重要な制約事項がエンコードされています。この文字列は profile-level-id と呼ばれ、これを構成する文字の各ペアは 16 進数を表します。
最初の値は、サブプロファイルを定義する profile_idc です。サブプロファイルとは、基本的に H.264 をエンコードするときに使用できるツールのセットを指します。2 番目の値は、一連の制約フラグを定義する profile_iop です。profile_iop の最初の 6 ビットが 6 つの制約フラグを定義します(残りの 2 ビットは使用されません)。
Flag | Hex Mask | Binary Mask |
---|---|---|
CONSTRAINT_SET_0 | 0x80 | 10000000 |
CONSTRAINT_SET_1 | 0x40 | 01000000 |
CONSTRAINT_SET_2 | 0x20 | 00100000 |
CONSTRAINT_SET_3 | 0x10 | 00010000 |
CONSTRAINT_SET_4 | 0x08 | 00001000 |
CONSTRAINT_SET_5 | 0x04 | 00000100 |
たとえば、「0C」は CONSTRAINT_SET_4 と CONSTRAINT_SET_5 に対応します。
サブプロファイルと制約フラグの組み合わせが、実際のプロファイルになります。利用可能な幅広いプロファイルのうち、ビデオ会議で最も一般的にサポートされているのは、制約付きベースラインプロファイルと制約付きハイプロファイルです。相互運用性を考慮する実装では、サポート対象のオプションの 1つとして制約付きベースラインプロファイルのサポートをアドバタイズすることをお勧めします。以下の表に、実装で profile_idc と制約からどのようにプロファイルを認識するかを示します。
Profile | profile_idc | Constraints |
---|---|---|
Constrained Baseline Profile | 66 | CONSTRAINT_SET_1 |
Baseline Profile | 66 | |
Main Profile | 77 | |
Extended Profile | 88 | |
Constrained High Profile | 100 | CONSTRAINT_SET_4, CONSTRAINT_SET_5 |
High Profile | 100 |
profile-level-id の残りのバイトではレベルを指定します。レベルとして選択できる値は、一連の要素に対する上限の組み合わせを表します。これらのレベルは ITU H.264 仕様の表 A-1 で定義されています。参照しやすいように、その表をここにも記載します。
所定のレベル番号は、8 つの異なる最大値のセットに対応します。特定のレベル番号をアドバタイズするということは、それら 8 つの最大値の条件に準拠する H.264 ストリームをサポートすることを意味します。以下に、これらの値のうち、特に重要なものを取り上げて説明します。
profile-level-id=428016 を例に要約すると、最初の 2 文字は profile_idc を表します。たとえば、0x42 は 10 進数では 66 に相当します。次の 2 文字は profile_iop を表します。たとえば 0x80 は 0b10000000 であり、CONSTRAINT_SET_1 に対応します。つまり、この場合のプロファイルは制約付きベースラインとなります。最後の 2 文字はレベルを表します。たとえば、0x16 は 10 進数の 22 に相当するため、レベルは 2.2 ということになります。レベル 2.2 での max_mbps は 20,250 マクロブロック/秒、max-fs は 1,620 マクロブロック、max-br は 4 メガビット/秒です。
レベルだけでもかなりの柔軟性が許容されますが、fmtp でこれらの上限のそれぞれを引き上げることもできます。重要な上限としては、次の 3 つが挙げられます。
実装で H.264 をアドバタイズするときは、定義された上限のそれぞれ(場合によっては帯域幅の上限は例外とされます)をサポートできる最大のレベル番号を選択したうえで、追加のパラメータを使用して個々の上限を引き上げて調整することをお勧めします。帯域幅の上限は例外とされる場合がある理由は、レベルでの帯域幅の上限は、その他すべてのパラメータと比較して非常に高くなる傾向があるためです。また、帯域幅は「b=」行でも制限できるため、多くの実装では可能な限り大きいレベル番号を選択する際に帯域幅の上限を考慮しません。
実際のところ、SDP のほとんどの H.264 fmtp 行には max-fs 行と max-mbps 行が含まれます。H.264 fmtp 行を解析するときは、実装でまずレベル番号を読み取り、ルックアップテーブルを使用して、そのレベル番号で定義しているさまざまな最大値を取得します。そのうえで、fmtp 全体を読み取り、それらの最大値を引き上げているパラメータを見つけて、レベル番号から取得した値でそれらの特定の値を置き換える必要があります。
H.263 などの一部の古いコーデックでは特定の解像度をネゴシエートできますが、それとは異なり、標準的な H.264 はアスペクト比に対する制約を組み込むのではなく、フレームサイズのみを単一の値としてネゴシエートします。したがって、3,600 に設定された max-fs は 720p をサポートすることをシグナリングすると同時に、同じく 3,600 マクロブロックである 1,920×480 をサポートすることも示します。技術的には、H.264 では 8:1 または 1:8 までの任意のアスペクト比のサポートを要件としますが、相互運用性が重要である場合は、仕様での要件とは関係なく、十分にサポートされているアスペクト比に従うことが最善です。
また、標準的な H.264 のネゴシエーションでは、最大フレームレートを指定する手段がありません。108,000 は 1 秒あたり 30 フレームでの 720p に相当しますが、最大 60fps ではその半分のピクセル数の解像度、さらに高いフレームレートではより低い解像度も許容されます。仕様ではこのように規定されているものの、アスペクト比と同様に、遠端側で実際にサポートしていることを知る手段がある場合を除き、実装で 30fps を超えるフレームレートで送信することには十分に慎重になる必要があります。
プロファイルとレベル(およびレベルに関連する個々のパラメータ)の他にも、構成できる H.264 のパラメータは多数あります。以下に、特に広く使われているパラメータについて説明します。
重要なパラメータの一つとして挙げられるのは、packetization-mode です。通常、このパラメータは profile-level-id とともに、すべての H.264 fmtp 行に存在していなければなりません。H.264 では 3 種類のパケット化モードをサポートしています。そのうち、ビデオ会議で最もよく使われているのは 1(非インターリーブモード)、次によく使われているのは 0(シングル NALU モード)です。2(インターリーブモード)はそれほどよく使われていません。
最近の実装ではほとんど見かけませんが、sprop-parameter-sets パラメータもかなり一般的に使用されています。常にではありませんが、「sprop」は SDP パラメータが送信側プロパティであることを示すために通常使われる接頭辞です(SDP のパラメータは一般的に受信側の機能を定義するため)。このパラメータには、デコーダが H.264 フレーム(通常は、シーケンスパラメータと画像パラメータを表す、base64 でエンコードされた文字列のペアをコンマで区切った形式)を受信したときに必要とするデータが格納されます。ITU 仕様にこれらの文字列の処理方法に関する詳細が記載されています。相互運用性が重要であるいずれの実装でも、H.264 デコーダの作成時にこのパラメータの値を処理してデコーダに渡す必要があります。最近の実装の大半では、これらのシーケンスパラメータと画像パラメータは H.264 ペイロード自体の中で帯域内パラメータとして埋め込まれることの方が一般的であり、その場合は SDP で送信する必要はありません。sprop- 接頭辞で始まるパラメータは他にもありますが、見かけることはあまりありません。
level-asymmetry-allowed パラメータは、その名の通り、SDP アンサーでオファーとは異なるレベル値を使用できるかどうかをシグナリングします。仕様によると、アンサーで別のレベル番号を使用することを許可する場合は、このパラメータをオファーに含めて「1」に設定する必要があります(アンサーにもこのパラメータを含める必要があります)。実際には、実装固有の SDP にこのパラメータを含めずにレベルの非対称性を使用したり、遠端側からこのパラメータを読み取ったりすることは珍しくありません。そのような実装では、固有のオファーとアンサーにレベルの非対称性を組み込む必要があります(そうしないと、Chrome ブラウザなどのデバイスで問題が発生する可能性があります)。ただし、リモート SDP に非対称性の使用を強制しないようにしてください。
RFC6184 では他にも多くのパラメータが定義されていますが、上記の実装で、幅広いデバイスとの十分な相互運用性とパフォーマンスを確保できるはずです。仕様で必須として定義されている動作とは関係なく、サードパーティデバイスで他のフィールドを使用する際は、そのフールドがサポートされていない可能性もあるため注意が必要です。
H.264 のサポートをアドバタイズするときは、rtpmap/fmtp ペアのそれぞれが単一の機能セットのサポートをアドバタイズすることを念頭においてください。ただし、相互運用性を確保するためには、複数の機能セットをアドバタイズすることが役立つ場合もあります。それぞれのエントリで一般的に異なるパラメータには、profile-level-id の profile の部分と、packetization-mode の 2 つがあります。実用性の理由から(また、一部のエンドポイントとミドルボックスには処理可能なコーデックエントリの数や SDP のサイズに制限があるため)、実装でサポートできるあらゆる値の組み合わせをアドバタイズすることは不可能な場合があります。相互運用性を重視する場合は、次の要素を含めることをお勧めします。
こうすると、最も一般的なプロファイル(制約付きハイプロファイルと制約付きベースラインプロファイル)およびパケット化モードで最大限の相互運用性を確保できるだけでなく、上記と構成が異なる場合には「最善」の構成を提示することになります。
Rob の「リアルタイムメディア」シリーズと「最新のビデオ会議システム」シリーズのその他の記事もご覧ください。