画像エンコーディング#
1 枚の画像は 2 次元の行列で表現でき、行列の各点はピクセルと呼ばれます。各ピクセルの色は三原色で表現され、すなわち赤、緑、青です。
各ピクセルは異なるビット数で表現でき、一般的な量子化ビット数には 16 ビット、24 ビット、32 ビットなどがあります。
- 24 ビットビットモード:各ピクセル 24 ビット(bits per pixel、bpp)でエンコードされた RGB 値:赤、緑、青の強度を表すために 3 つの 8 ビットの符号なし整数(0 から 255)を使用します。
- 16 ビットビットモード:各原色に 5 ビットが割り当てられ、緑は 6 ビットです。これは人間の目が緑の色調をより正確に識別できるためですが、特定の状況では各原色が 5 ビットずつ割り当てられ、残りの 1 ビットは使用されません。
- 32 ビットビットモード:24 ビットビットモードと同様で、残りの 8 ビットはピクセルの透明度(アルファ)を表します。
画像にはもう 1 つ重要な属性があり、それは解像度で、幅 × 高さで表されます。
画像や動画を処理する際のもう 1 つの属性はアスペクト比で、これは画像やピクセルの幅と高さの比率を示します。一般的な比率には 4:3、16:9、21:9 があり、通常は表示アスペクト比(DAR)を指します。同様に、ピクセルにも異なるアスペクト比があり、これをピクセルアスペクト比(PAR)と呼びます。
YUV カラーモデル#
RGB は人間の目による色彩の感知に訴えかけ、YUV は視覚の明るさに対する感度に重点を置いています。Y は明るさ(輝度、ルミナンス)を表し、UV は色度(クロミナンス / クロマ)を表します(したがって白黒映画では UV を省略でき、RGB に近くなります)。それぞれ Cr と Cb で表されるため、YUV の記録は通常 Yの形式で表示されます。
帯域幅を節約するために、ほとんどの YUV フォーマットは平均して各ピクセルのビット数が 24 ビット未満です。主要なサンプリング(サブサンプル)フォーマットには YCbCr 4:2:0、YCbCr 4:2:2、YCbCr 4:1:1、YCbCr 4:4:4 があります。YUV の表記法は A:B表記法と呼ばれます:
- 4:4:4 は完全サンプリングを示します。
- 4:2:2 は 2:1 の水平方向のサンプリングで、垂直方向は完全サンプリングです。
- 4:2:0 は 2:1 の水平方向のサンプリングで、垂直方向は 2:1 のサンプリングです。
- 4:1:1 は 4:1 の水平方向のサンプリングで、垂直方向は完全サンプリングです。
RGB と YUV の変換#
# 最初のステップは明るさを計算します
Y = 0.299R + 0.587G + 0.114B
# 明るさが得られたら、色(青色と赤色)を分割できます:
Cb = 0.564(B - Y)
Cr = 0.713(R - Y)
# YCbCrを使用して変換することもでき、RGBを得ることもできます
R = Y + 1.402Cr
B = Y + 1.772Cb
G = Y - 0.344Cb - 0.714Cr
サンプリングレート、ビットレート、フレームおよびフィールドの概念#
画像はアナログ信号をサンプリング量子化して得られ、動画は一連の画像で構成されています。収集時に画像の解像度や量子化ビット数が高いほど、表現できる情報が多く、画面はより鮮明になります。動画にはサンプリング周波数の属性があり、単位時間あたりのサンプリング回数を示します。動画のサンプリング周波数は人間の目の制限を受け、通常は 1 秒あたり 20〜30 フレームの範囲です。サンプリング周波数が 1 秒あたり 10〜20 フレームの場合、速い動きの画像では人間の目には滑らかさが感じられず、サンプリング周波数が 20〜30 フレームに上がると、目には比較的滑らかに見えます。サンプリング周波数をさらに上げると、人間の目にはその差を感じることが難しくなります。これが現在の映画撮影で 24 フレームまたは 30 フレームのサンプリング周波数が使用される理由です。
動画を表示するために必要な毎秒のビット数はビットレートと呼ばれ、またはコーディングレートとも呼ばれます。計算式はビットレート=幅 高 深度 毎秒フレーム数
です。例えば、圧縮を一切行わない場合、毎秒 30 フレーム、各ピクセル 24 ビット、480x240 解像度の動画は 82,944,000 ビット / 秒または 82.944 Mbps(30x480x240x24)を必要とします。
ビットレートがほぼ一定の場合は恒常ビットレート(CBR)と呼ばれますが、変動する場合は可変ビットレート(VBR)と呼ばれます。下の図は制限された VBR を示しており、フレームが黒のときにはあまりビットを消費しません。
動画サンプリングで逐次スキャンによって得られた完全な画像は 1 フレームと呼ばれ、通常のフレームレートは 25 フレーム(PAL 方式)、30 フレーム毎秒(NTSC 方式)です。インターレーススキャン(奇数、偶数行)を使用すると、1 フレームの画像が 2 つのフィールドに分割され、通常のフィールドレートは 50Hz(PAL 方式)、60Hz(NTSC 方式)です。これは初期にエンジニアが提案した技術で、追加の帯域幅を消費せずにディスプレイの知覚フレームレートを倍増させることができます。この技術はインターレース動画と呼ばれ、基本的には 1 フレームで画面の半分を送信し、次のフレームで残りの半分を送信します。
H264 の概要#
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 を含みます。エンコードされたスライス(データ分割スライス 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 フレームを表します。
{% asset_img h264-header.png h264-header %}
これにより、61 と 41 は実際には P フレーム(タイプ値は 1)であり、重要レベルが異なることがわかります(それらの NRI は一方が 11 BIN、もう一方が 10 BIN です)。
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、図 2 を参照すると:7 はシーケンスパラメータセット SPS に対応します。
0x68 のバイナリコードは:
0110 1000 4-8 は 01000 で、10 進数に変換すると 8、図 2 を参照すると:8 は画像パラメータセット PPS に対応します。
0x65 のバイナリコードは:
011 00101
4-8 ビットは 00101 で、10 進数に変換すると 5、図 2 を参照すると: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 単位は[開始コード] [NALUヘッダー] [NALUペイロード]
の 3 つの部分で構成され、開始コードは 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ヘッダー] [67 42 A0 1E 23 56 0E 2F]
つまり、4 バイトの開始コードを削除するだけで済みます。
パッケージ集約#
NALU の長さが特に短い場合、いくつかの NALU 単位を 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 を超える場合、NALU 単位を分割してパッケージ化する必要があります。これをフラグメンテーションユニット(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 インジケーターは以下の形式です:
+---------------+
|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 インジケーターの最初の 3 ビットであり、元の NAL ヘッダーの後の 5 ビットは FU ヘッダーの後の 5 ビットです。
FU インジケーターと FU ヘッダーの残りのビット数は実際の状況に応じて決定されます。
** 解凍:** 受信側が FU-A の分割データを受信した場合、すべての分割パッケージを組み合わせて元の NAL パッケージに戻す必要があります。FU-A の単位ヘッダーと復元された NAL の関係は次の通りです:
復元された NAL ヘッダーの 8 ビットは FU インジケーターの最初の 3 ビットと FU ヘッダーの後の 5 ビットで構成されます。すなわち:
nal_unit_type = (fu_indicator & 0xe0) | (fu_header & 0x1f)