概念#
- 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 の最後のフラグメントであることを示します。続く 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)