banner
fwrite

fwrite

好好生活
twitter
github
email

H264

概念#

  • 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 に示されている。

2_1656856049435_0

各ユニットは独立した NAL ユニットとして送信される。ユニットの情報ヘッダー(1 バイト)は RBSP ユニットのタイプを定義し、NAL ユニットの残りの部分は RBSP データである。

NAL ユニット#

各 NAL ユニットは、一定の構文要素の可変長バイト列であり、1 バイトのヘッダー情報(データタイプを示すために使用)といくつかの整数バイトのペイロードデータを含む。1 つの NAL ユニットは、エンコードされたスライス、A/B/C 型データ分割、またはシーケンスまたは画像パラメータセットを運ぶことができる。

NALU ヘッダーは 1 バイトで構成され、その構文は以下の通りである:

NAL ユニットは RTP シーケンス番号に従って順番に送信される。その中で、T はペイロードデータタイプを示し、5 ビットを占める;R は重要性指示ビットで、2 ビットを占める;最後の F は禁止ビットで、1 ビットを占める。具体的には以下の通り:

3_1656856064741_0

  1. NALU タイプビットは NALU の 32 種類の異なるタイプの特徴を示すことができ、タイプ 1~12 は H.264 で定義され、タイプ 24~31 は H.264 以外で使用され、RTP ペイロード仕様はその中のいくつかの値を使用してパッケージの集約と分割を定義し、他の値は H.264 に予約されている。
  2. 重要性指示ビットは、再構築プロセス中に NAL ユニットの重要性をマークするために使用され、値が大きいほど重要である。値が 0 の場合、この NAL ユニットは予測に使用されないため、デコーダーはエラー拡散なしにこのユニットを破棄できる;値が 0 より大きい場合、この NAL ユニットはドリフトなしの再構築に使用され、値が大きいほどこの NAL ユニットの損失の影響が大きくなる。
  3. 禁止ビットは、エンコード時のデフォルト値が 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 フレームを表す。

4_1656856114733_0

したがって、61 と 41 は実際には P フレーム(タイプ値は 1)であり、重要レベルが異なる(それらの NRI は一つが 11BIN、もう一つが 10BIN である)。

H264 (NAL の概要と I フレームの判断)#

h264_1656856123091_0

最上部の図のビットストリームに対応するデータを段階的に分析し、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 のビットストリーム構造

5_1656856166759_0

単一 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)

libx264#

libx264 学習ノート

ffmpeg による libx264 の呼び出し

読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。