概念#
- SODB: データビット列 -> 最も原始的なエンコードデータ
- RBSP: 原始バイト列ペイロード ->SODB の後ろに終端ビット(RBSP trailing bits 1 ビットの “1”)といくつかのビット “0” を追加して、バイトアラインメントを行う。
- EBSP: 拡張バイト列ペイロード– >RBSP に基づいて擬似チェックバイト(0X03)を追加する。その理由は、NALU が Annexb に追加される際、各 NALU の前に開始コード StartCodePrefix を追加する必要がある。もしその NALU に対応するスライスがフレームの開始であれば 4 バイトで表現し、0x00000001、そうでなければ 3 バイトで表現する 0x000001。NALU 本体に開始コードと衝突するものを含めないようにするため、エンコード時に 2 バイトが連続して 0 の場合、1 バイトの 0x03 を挿入する。デコード時に 0x03 を取り除く。別名、デタッチ操作とも呼ばれる。
H.264 の機能は 2 層に分かれており、ビデオコーディング層(VCL)とネットワーク抽出層(NAL)である。
VCL データは、圧縮エンコードされた後のビデオデータ列である。VCL データは NAL ユニットにカプセル化された後、初めて転送または保存に使用できる。
H.264 のエンコードされたビデオ列は、一連の NAL ユニットを含み、各 NAL ユニットは RBSP を含む。表 1 を参照。エンコードされたスライス(データ分割スライス IDR スライスを含む)とシーケンス RBSP の終了符は VCL NAL ユニットとして定義され、残りは NAL ユニットである。典型的な RBSP ユニット列は図 2 に示されている。
各ユニットは独立した NAL ユニットとして送信される。ユニットの情報ヘッダー(1 バイト)は RBSP ユニットのタイプを定義し、NAL ユニットの残りの部分は RBSP データである。
NAL ユニット#
各 NAL ユニットは、一定の構文要素の可変長バイト列であり、1 バイトのヘッダー情報(データタイプを示すために使用)といくつかの整数バイトのペイロードデータを含む。1 つの NAL ユニットは、エンコードされたスライス、A/B/C 型データ分割、またはシーケンスまたは画像パラメータセットを運ぶことができる。
NALU ヘッダーは 1 バイトで構成され、その構文は以下の通りである:
NAL ユニットは RTP シーケンス番号に従って順番に送信される。その中で、T はペイロードデータタイプを示し、5 ビットを占める;R は重要性指示ビットで、2 ビットを占める;最後の F は禁止ビットで、1 ビットを占める。具体的には以下の通り:
- NALU タイプビットは NALU の 32 種類の異なるタイプの特徴を示すことができ、タイプ 1~12 は H.264 で定義され、タイプ 24~31 は H.264 以外で使用され、RTP ペイロード仕様はその中のいくつかの値を使用してパッケージの集約と分割を定義し、他の値は H.264 に予約されている。
- 重要性指示ビットは、再構築プロセス中に NAL ユニットの重要性をマークするために使用され、値が大きいほど重要である。値が 0 の場合、この NAL ユニットは予測に使用されないため、デコーダーはエラー拡散なしにこのユニットを破棄できる;値が 0 より大きい場合、この NAL ユニットはドリフトなしの再構築に使用され、値が大きいほどこの NAL ユニットの損失の影響が大きくなる。
- 禁止ビットは、エンコード時のデフォルト値が 0 であり、ネットワークがこのユニットにビットエラーが存在することを認識した場合、1 に設定して受信者がこのユニットを破棄できるようにする。これは、異なる種類のネットワーク環境(例えば、有線と無線が組み合わさった環境)に適応するために主に使用される。
264 の一般的なフレームヘッダーデータは:
00 00 00 01 67 (SPS)
00 00 00 01 68 (PPS)
00 00 00 01 65 (IDR フレーム)
00 00 00 01 61 (P フレーム)
上記の **67,68,65,61,** および 41 などは、NALU の識別レベルである。
F:禁止ビット、0 は正常、1 はエラー、一般的には 0 である。
NRI:重要レベル、11 は非常に重要である。
TYPE:この NALU のタイプを示す。
下表を参照すると、7 はシーケンスパラメータセット (SPS)、8 は画像パラメータセット (PPS)、5 は I フレームを表す。1 は非 I フレームを表す。
したがって、61 と 41 は実際には P フレーム(タイプ値は 1)であり、重要レベルが異なる(それらの NRI は一つが 11BIN、もう一つが 10BIN である)。
H264 (NAL の概要と I フレームの判断)#
最上部の図のビットストリームに対応するデータを段階的に分析し、00 00 00 01 で区切った後の次のバイトは NALU タイプであり、それをバイナリデータに変換すると、
解読順序は左から右に数える。以下の通り:
(1)第 1 ビットは禁止ビットで、値が 1 の場合は構文エラーを示す。
(2)第 2~3 ビットは参照レベルである。
(3)第 4~8 ビットは NAL ユニットタイプである。
例えば、上記の 00000001 の後に 67,68 および 65 がある。
0x67 のバイナリコードは:
0110 0111
4-8 は 00111 で、10 進数に変換すると 7、第二の図を参照:7 はシーケンスパラメータセット SPS に対応する。
0x68 のバイナリコードは:
0110 1000 4-8 は 01000 で、10 進数に変換すると 8、第二の図を参照:8 は画像パラメータセット PPS に対応する。
0x65 のバイナリコードは:
011 00101
4-8 ビットは 00101 で、10 進数に変換すると 5、第二の図を参照:5 は IDR 画像のスライス (I フレーム) に対応する。
したがって、I フレームかどうかを判断するアルゴリズムは:
(NALU タイプ & 0001 1111) = 5 すなわち (NALU タイプ & 31) = 5 例えば 0x65 & 31 = 5
RTP パッキング送信 H264 のパッケージ詳細#
RFC3984 は H.264 のベースラインビットストリームを RTP 方式で伝送するための規範である。
H264 のビットストリーム構造
単一 NALU#
12 バイトの RTP ヘッダーの後には音声と映像データが続き、比較的シンプルである。単一 NAL ユニットを RTP の NAL ユニットストリームにカプセル化する場合、RTP シーケンス番号は NAL ユニットのデコード順序に従う必要がある。NALU の長さが MTU サイズより小さいパッケージでは、一般的に単一 NAL ユニットモードを使用する。原始的な H.264 NALU ユニットは通常[Start Code] [NALU Header] [NALU Payload]
の 3 つの部分で構成され、Start Code は NALU ユニットの開始を示すために使用され、必ず “00 00 00 01” または “00 00 01” である。NALU ヘッダーは 1 バイトのみで、その後は NALU ユニットの内容である。
パッキング時には “00 00 01” または “00 00 00 01” の開始コードを取り除き、他のデータを RTP パッケージにカプセル化すればよい。
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|F|NRI| type | |
+-+-+-+-+-+-+-+-+ |
| |
| Bytes 2..n of a Single NAL unit |
| |
| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| :...OPTIONAL RTP padding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
例えば、H.264 の NALU が次のようである:
[00 00 00 01 67 42 A0 1E 23 56 0E 2F …]
これはシーケンスパラメータセット NAL ユニットである。[00 00 00 01] は 4 バイトの開始コードで、67 は NALU ヘッダー、42 から始まるデータは NALU 内容である。
RTP パッケージにカプセル化すると次のようになる:
[RTP Header] [67 42 A0 1E 23 56 0E 2F]
つまり、4 バイトの開始コードを取り除くだけでよい。
パッケージの集約#
NALU の長さが特に小さい場合、いくつかの NAL ユニットを 1 つの RTP パッケージに封入することができる。
有線ネットワークと無線ネットワークの MTU の巨大な差異に対応するために、RTP プロトコルはパッケージ集約戦略を定義している:
- STAP-A:集約された NALU のタイムスタンプはすべて同じで、DON(デコーディング順序番号)はない;
- STAP-B:集約された NALU のタイムスタンプはすべて同じで、DON がある;
- MTAP16:集約された NALU のタイムスタンプは異なり、タイムスタンプの差を 16 ビットで記録する;
- MTAP24:集約された NALU のタイムスタンプは異なり、タイムスタンプの差を 24 ビットで記録する;
- パッケージ集約時、RTP のタイムスタンプはすべての NALU タイムスタンプの最小値である;
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|F|NRI| Type | |
+-+-+-+-+-+-+-+-+ |
| |
| one or more aggregation units |
| |
| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| :...OPTIONAL RTP padding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Figure 3. RTP payload format for aggregation packets
STAP-A の例:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| RTP Header |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|STAP-A NAL HDR | NALU 1 Size | NALU 1 HDR |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| NALU 1 Data |
: :
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| | NALU 2 Size | NALU 2 HDR |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| NALU 2 Data |
: :
| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| :...OPTIONAL RTP padding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Figure 7. An example of an RTP packet including an STAP-A
containing two single-time aggregation units
FU-A の分割形式#
データが比較的大きい H264 ビデオパッケージは、RTP によって分割送信される。12 バイトの RTP ヘッダーの後には FU-A 分割が続く:NALU の長さが MTU を超える場合、NAL ユニットを分割してパッケージ化する必要がある。これをフラグメンテーションユニット(FUs)とも呼ぶ。
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| FU indicator | FU header | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| |
| FU payload |
| |
| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| :...OPTIONAL RTP padding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Figure 14. RTP payload format for FU-A
FU indicator の形式は以下の通り:
+---------------+
|0|1|2|3|4|5|6|7|
+-+-+-+-+-+-+-+-+
|F|NRI| Type |
+---------------+
FU 指示バイトのタイプ域 Type=28 は FU-A を示す。NRI 域の値は分割 NAL ユニットの NRI 域の値に基づいて設定されなければならない。
FU ヘッダーの形式は以下の通り:
+---------------+
|0|1|2|3|4|5|6|7|
+-+-+-+-+-+-+-+-+
|S|E|R| Type |
+---------------+
S: 1 ビット、1 に設定されると NALU の最初のフラグメントを示す。続く FU ペイロードが分割 NAL ユニットの開始でない場合、開始ビットは 0 に設定される。
E: 1 ビット、1 に設定されると NALU の最後のフラグメントを示す。すなわち、ペイロードの最後のバイトも分割 NAL ユニットの最後のバイトである。続く FU ペイロードが分割 NAL ユニットの最後のフラグメントでない場合、終了ビットは 0 に設定される。
R: 1 ビット、予約ビットは 0 に設定されなければならず、受信者はこのビットを無視しなければならない。
Type: 5 ビット、NAL ユニットペイロードタイプの定義は下表を参照。
ユニットタイプおよびペイロード構造の要約
.Type Packet Type name
---------------------------------------------------------
0 undefined -
1-23 NAL unit Single NAL unit packet per H.264
24 STAP-A Single-time aggregation packet
25 STAP-B Single-time aggregation packet
26 MTAP16 Multi-time aggregation packet
27 MTAP24 Multi-time aggregation packet
28 FU-A Fragmentation unit
29 FU-B Fragmentation unit
30-31 undefined
パッキングとアンパッキング
パッキング:エンコーダーがエンコード時に元の NAL を FU-A に分割する必要がある。元の NAL のユニットヘッダーと分割後の FU-A のユニットヘッダーには以下の関係がある:
元の NAL ヘッダーの最初の 3 ビットは FU indicator の最初の 3 ビットであり、元の NAL ヘッダーの後の 5 ビットは FU header の後の 5 ビットである。
FU indicator と FU header の残りのビット数は実際の状況に応じて決定される。
アンパッキング:受信側が FU-A の分割データを受け取ったとき、すべての分割パッケージを組み合わせて元の NAL パッケージに戻す必要がある。FU-A のユニットヘッダーと復元された NAL の関係は以下の通り:
復元された NAL ヘッダーの 8 ビットは FU indicator の最初の 3 ビットと FU header の後の 5 ビットで構成される。すなわち:
nal_unit_type = (fu_indicator & 0xe0) | (fu_header & 0x1f)