※この文書は間違った内容を記載している可能性があります。信じすぎないようにしてください。
このページでは「H.264 データを解析する」ということを手段にして、その構造や考え方を解説します。データの解析をすることが、デコーダー、エンコーダーを使用するのにも、作成するのにも一番の近道です。
0. 基礎知識
0.1. 規格書
通称「H.264」は、別名「MPEG-4 AVC」、あるいは「ISO/IEC 14496-10」と言い、世界標準規格のビデオ圧縮コーデックです。
2003年に最初の仕様が規格化され、何度か互換性を保ちつつ拡張されています。
最新の規格書を下記サイトから入手できます。
規格名 | URL | メモ |
---|---|---|
ITU-T Rec. H.264 ISO/IEC 14496-10 Advanced Video Coding | http://www.itu.int/rec/T-REC-H.264/en | 無料 |
JT-H264 オーディオビジュアルサービス全般のための高度ビデオ符号化方式 | http://www.ttc.or.jp | 社団法人情報通信技術委員会の会員になる必要あり。 |
また、H.264 参照ソフトウェア を使用すれば、より詳しく内容を知ることができます。
0.2. ビデオ圧縮の基礎知識
H.264 ビデオを含め、ほとんどのビデオデータは、何枚もの静止画をパラパラと切り替えて表示していくことで、動画(Moving Picture)として振舞います。H.264 ビデオには音声データは含まれていないので、別途、符号化した音声データと多重化して MPEG-2 TS のようなコンテナデータに格納し、再生時に音声とビデオを同期しながら再生することで、映画のような、まさにムービーとなります。
※ちなみに「ムービー」といえば、たいていビデオと音声を含んだデータで、「ビデオ」といえば、映像のみのデータになります。
基本的には、動画を先頭から再生し続けるためのデータですから、ビデオデータには先頭の静止画から順に静止画が格納されています。ただ、単純に静止画を並べただけだと、データ量が多すぎるので圧縮し、データ量を削減します。その際、静止画1枚1枚を圧縮するのはもちろん、静止画同士の似た部分を1つにまとめ、小さくすることもします。また、より圧縮効率を高めるため、静止画の順序を入れ替えることもあります。
なお、H.264 というのは非常に広い規格であることから、そのままではアプリケーションを開発する人の負担になってしまいます。そのため「プロファイル」や「レベル」、「運用規定」といったもので制約を設けて、より小さな規格を作って、テレビ放送、Blu-rayディスク、インターネット放送、ビデオオンデマンドサービスなどに使われています。
1. H.264データ構造の概要
本章でH.264のデータ構造を説明します。
1.1. 基本構造 - NAL ユニット
H.264 データは、階層構造になっています。解析を始めて、最初に現れる、最上位の階層が「NAL」です。NALは、Network Abstraction Layer(ネットワーク抽象レイヤー)の略称で、動画データを効率良く伝送するための機能を担うレイヤー(階層)です。
NAL は、 n 個の NAL ユニットが連なっており、その1つ1つを順に解析することで、デコード(復号)できるようになっています。
NALの構成 | ||||||
---|---|---|---|---|---|---|
NAL unit(1) | NAL unit(2) | NAL unit(3) | NAL unit(4) | … | NAL unit(n-1) | NAL unit(n) |
各 NAL ユニットは、よくあるファイルフォーマットと同じく、ヘッダー部とボディ部から構成されています。それぞれ「NAL ユニットヘッダー」と「RBSP」という名前がついています。
NALユニットの構成 | |
---|---|
NALユニットヘッダー | RBSP |
NAL ユニットヘッダーの内容に応じて、RBSPに格納されるデータの内容は全く異なり、ビデオデータそのものが入ることもあれば、圧縮ビデオデータをデコード(復号)するのに必要な補助情報を表すデータだけが入ることもあります。ビデオデータを含むNALユニットのことを特に「VCL NALユニット」と呼び、ビデオデータ以外の情報を含んだNALユニットを「非VCL NALユニット」と呼びます。
「VCL NALユニット」のRBSPには、VCLのデータを含みます。VCLは、Video Coding Layer(映像符号化レイヤー)の略称で、前述の通り、ビデオデータの圧縮そのものの機能を担うレイヤーです。
「非VCL NALユニット」には、VCLデータは含みませんが、VCLデータを解釈するのに重要な情報を含んでいます。たとえば、解像度の情報や、フレームレート、デコード(復号)するのに必要なメモリ量などの情報が書かれており、ビデオデータそのものではないものの、デコードするためには絶対必要な情報が含まれています。
このようにNALには大きく2種類のNALユニットが存在していますが、それらを区別する情報は、NALユニットヘッダーの5ビットの情報「nal_unit_type」を読み取って、確認します。5ビットなので、0~31の値を表現できますが、2015年6月現在、18種のNALユニットしか規定されていません(1~15と19~21)。
1.2. 基本構造 - バイトストリームフォーマット
H.264 の NAL 構造は、2つの異なるフォーマットが使われます。
1つが「Packet Transport Protocol」で、元々、ネットワーク配信する場合などに多く用いられる方法で、一切、余計なものをつけない方法です。たとえばビデオ配信で有名なプロトコル「RTP」(Real-time Transport Protocol」で、H.264ビデオを配信する場合はNALユニットごとにパッケット化して配信しており、パケットの終わりがNALユニットの終わり(つまり、RBSPのデータサイズと言える)となっていて、簡単に解析できるようになっています。(RTPでの、H.264のパケット化の方法については「RFC6184」)
もう1つが「Byte Stream Format」で、規格書「ITU-T Rec. H.264 | ISO/IEC 14496-10 Advanced Video Coding」の付属資料B(通称「Annex.B」)に、そのフォーマットが規定されています。
以降では、「Byte Stream Format」について解析します。
1.2.1. バイトストリームフォーマットの解析 - 基本
バイトストリームフォーマットでは、 NAL ユニットの区切りを明確にするため、下記のような構造をとっています。
例:(cf. ITU-T H.264 (02/2014) - B.1.1 Byte stream NAL unit syntax)
バイトストリームフォーマット(Annex.B) | ||||||
---|---|---|---|---|---|---|
1つ目のバイトストリームNALユニット | 2つ目の… | … | ||||
leading_zero_8bits | zero_byte | start_code_prefix_one_3bytes | nal_unit | trailing_zero_8bits | … | … |
基本的に「start_code_prefix_one_3bytes」(以降「スタートコード」)を探していけば、NALユニットの始まりを探すことができます。スタートコードは、その値が「0x000001」の3バイトのことで、バイトストリームNALユニットの区切りを示します。
他の要素で重要なのは、nal_unit で、この構文要素に NAL ユニットが格納されています。
他の要素は無視して構いませんが、一応、解説します。
まず、leading_zero_8bits と trailing_zero_8bits は、必ず 0 となるビット(バイト)です。leading_zero_8bits と trailing_zero_8bits に分かれてはいますが、1つ目のバイトストリームNALユニットの trailing_zero_8bits と2つ目のバイトストリーム NAL ユニットの leading_zero_8bits が同じバイトを指します。
次に、zero_byte は名前の通り、0を表すバイトで、NALユニットの内容によって入ったり入らなかったりします。しかし、結局は0なので解析処理にはほとんど影響を与えません。
バイトストリームNALユニットの具体的な解析処理は、たとえば、オープンソースソフトウェアの OpenH264 では下記のファイルで行っています。
https://github.com/cisco/openh264/blob/master/codec/decoder/core/src/au_parser.cpp
この中でDetectStartCodePrefix() 関数でスタートコードを探しています。処理内容は、0を示すバイトの個数を変数iIdxで数え、1を示すバイトが現れた際に 3個以上の 0 が連なっていたらスタートコードだったという判断をして、スタートコードの次の nal_unit を指すポインタを返しています。
次にParseNalHeader()関数で NALユニットヘッダーを解析しています。
これらの関数の呼び出しは、次のファイルのWelsDecodeBs()関数で行っています。
https://github.com/cisco/openh264/blob/master/codec/decoder/core/src/decoder.cpp
あと、もうちょっと馬鹿正直にやるなら、リファレンスソフトの次のソースで、FindStartCode() 関数。
http://iphome.hhi.de/suehring/tml/doc/ldec/html/annexb_8c_source.html
アプリケーションによっては、スタートコード位置がわからない状態だっていう場合、もうちょっと探索スピードを上げたいなら、Boyer-Moore法を使用すると素早く探索できます。
次のソースの gst_h264_find_next_nal_code() 関数が参考になります。
http://downloads.isee.biz/pub/files/igep-dsp-gst-framework-3_40_00/gstreamer-ti_svnr962/src/gsttiquicktime_h264.c
1.2.2. バイトストリームフォーマットの解析 - エスケープ文字的なもの
ところで、nal_unit中にスタートコードと同じ「0x000001」が現れた場合、どう解析すれば良いのでしょうか?
安心してください。
nal_unit中には「0x000001」は現れません。これは、規格書上では「emulation_prevention_three_byte」という構文要素の説明に現れますが、簡単に言えば、C言語でいうところの「エスケープ文字」です。
つまり、 nal_unit中に「0x000001」と同じ値が現れた場合、エンコーダー(符号器)は「0x00000301」と値をエスケープすることが規定されていて、H.264 解析時には、これを考慮して解析する必要があります。
また、「0x000001」という16進数表記ではわかりにくいですが、2進数表記にすると
「0x000001」は「0000 0000 0000 0000 0000 0001」であり、
「0x000002」は「0000 0000 0000 0000 0000 0010」であり、
「0x000003」は「0000 0000 0000 0000 0000 0011」ですので、
「0x000002」と「0x000003」も、「emulation_prevention_three_byte」でエスケープして
「0x00000302」と「0x00000303」とします。
1.3. 基本構造 - NALユニットヘッダーの解析
NALユニットは、前述の通り、NALユニットヘッダーとRBSPから成ります。
NALユニットヘッダーは、1バイト(=8ビット)で下記の構造を持ちます。
名称 | ビット数 | 概要 |
---|---|---|
forbidden_zero_bit | 1 | 必ず0となる。0でない場合、伝送エラー等が発生している。 |
nal_ref_idc | 2 | 参照ピクチャまたは参照フレームまたは参照フィールドを含むNALユニットかどうかを示す。 「idc」は「indicator」で「標識」の意味。 |
nal_unit_type | 5 | NALユニットの種別を表す。値がどの種別を示すかは別表で説明する。 |
ここで、nal_unit_type は次表のような値を取ります。
nal_unit_type値 | NAL ユニット名 | 概要 |
---|---|---|
0 | Unspecified | 無指定 |
1 | Coded slice of a non-IDR picture | |
2 | Coded slice data partition A | |
3 | Coded slice data partition B | |
4 | Coded slice data partition C | |
5 | Coded slice of an IDR picture | |
6 | Supplemental enhancement information | 通称「SEI」。 |
7 | Sequence parameter set | 通称「SPS」。 |
8 | Picture parameter set | 通称「PPS」。 |
9 | Access unit delimiter | 通称「AUD」。 |
10 | End of sequence | |
11 | End of stream | |
12 | Fillter data | |
13 | Sequence parameter set extension | |
14 | Prefix NAL unit | |
15 | Subset sequence parameter set | |
16-18 | Reserved | 予約 |
19 | Coded slice of an auxiliaryy coded picture without partitioning | |
20 | Coded slice extension | |
21 | Coded slice extension for depth view components | |
22-23 | Reserved | 予約 |
24-31 | Unspecified | 無指定 |
個々の意味は、後ほど。
1.4. 基本構造 - RBSPの解析
1.4.1. EBSPとRBSP
さて、今まで規格書にならって「RBSP」と書いてきましたが、実は正確ではありません。
Byte Stream Format (Annex.B) は、次の構造でした。
【Byte Stream】 =【Start Code】+【NALU】+ …+【Start Code】+【NALU】
※leading_zero_8bitsやtrailing_zero_8bitsは省略してます。
次に、NALUこと、NALユニットは次の構造と説明しました。
【NALU】 = 【NALU Header】+【RBSP】
しかし、正確には【NALU】は【RBSP】で構成されるのではなく、【EBSP】で構成されます。
【NALU】 = 【NALU Header】+【EBSP】
これは、先の「1.2.2. バイトストリームフォーマットの解析 - エスケープ文字的」(H.264#n7ba3ff7)で説明したエスケープ文字があるからです。
【EBSP】は、次の構造をしています。
【EBSP】=【RBSP part(1)】 +【0x03】 +【RBSP part(2)】+【0x03】 +… +【RBSP part(n)】
そして、エスケープ文字的な「0x03」をアンエスケープ処理して、RBSP part(x) を連結することで、RBSPとなります。
【RBSP】 = 【RBSP part(1)】 +【RBSP part(2)】+… +【RBSP part(n)】
なお、【EBSP】という略語は規格書には登場しませんが、一般的に通用する名称になっています。
英語の意味としては
【RBSP】は、「Raw Byte Sequence Payload」の略語で、「生のバイト列データ」といった意味で、
【EBSP】は、「Encapsulate Byte Sequence Payload」の略語で、「カプセルに入れたバイト列データ」といった意味です。
小さなカプセルにバイト列データを刻んで入れた…というイメージすると良いかと思います。
(実際には、「小さなカプセル」っていうほど、粒ぞろいな感じではなく、都合に合わせて切ってるだけですが。)
1.4.2. RBSPとSODB
さて、本来、少しでもビットを削ろうとしている H.264 において、そんなに都合よくペイロードデータがバイト単位の区切りに揃うわけがありません。
そのもっとも生なデータを「SODB」(String of Data Bits、データビット記号列)で、バイト単位に切り上げるためのビットを「RBSP stop bit」と呼びます。
RBSPとの関係は、下記の構造が示す通りです。
【RBSP】 =【SODB】 +【RBSP stop bit】
この関係性が図で示されていることは少ないですが、規格書 ITU-T H.264 (02/2014) の "3.149 string of data bits (SODB" や "7.4.1 NAL unit semantics" の「rbsp_byte」の説明を読むとわかります。
2. HRDの概要
2.1. HRDの仮定
A. 付録
A.1. 機能一覧
カテゴリ | 機能名 | Baseline | Extended | Main | High | High10 | High4:2:2 | Hight4:4:4 |
エントロピー符号化 | CABAC | - | - | OK | OK | OK | OK | OK |
エントロピー符号化 | CAVLC | OK | OK | OK | OK | OK | OK | OK |
デブロッキングフィルタ | OK | OK | OK | OK | OK | OK | OK | |
変換 | 4×4整数変換 | OK | OK | OK | OK | OK | OK | OK |
変換 | 8×8整数変換 | - | - | - | OK | OK | OK | OK |
予測 | インター予測 | - | OK | OK | OK | OK | OK | OK |
予測 | イントラ予測 | OK | OK | OK | OK | OK | OK | OK |
予測 | 重み付き予測 | - | OK | OK | OK | OK | OK | OK |
ロスレス符号化 | - | - | - | - | - | - | OK | |
カラーフォーマット | αプレーン | |||||||
カラーフォーマット | YCgCo | - | - | - | - | - | OK | OK |
カラーフォーマット | ITU-R Recommendation BT.2020 | |||||||
スライス | I スライス | OK | OK | OK | OK | OK | OK | OK |
スライス | P スライス | OK | OK | OK | OK | OK | OK | OK |
スライス | B スライス | - | OK | OK | OK | OK | OK | OK |
スライス | SP,SI スライス | - | OK | - | - | - | - | - |
スライス | 任意スライス順序 | OK | - | - | - | - | - | - |
スライス | スライスグループ | OK | - | - | - | - | - | - |
スライス | 冗長スライス | OK | - | - | - | - | - | - |
A.2. レベル一覧
レベル名 | level_idc | MaxMBPS | MaxFS | MaxDpbMbs | MaxBR | MaxCPB | 追加時期 |
1 | 10 | 1,485 | 99 | 396 | 64 | 175 | Version 1: (2003-05-30) |
1b | 9 | 1,485 | 99 | 396 | 128 | 350 | Version 2: (2005-03-01) |
1.1 | 11 | 3,000 | 396 | 900 | 192 | 500 | Version 1: (2003-05-30) |
1.2 | 12 | 6,000 | 396 | 2,376 | 384 | 1,000 | Version 1: (2003-05-30) |
1.3 | 13 | 11,880 | 396 | 2,376 | 768 | 2,000 | Version 1: (2003-05-30) |
2 | 20 | 11,880 | 396 | 2,376 | 2,000 | 2,000 | Version 1: (2003-05-30) |
2.1 | 21 | 19,800 | 792 | 4,752 | 4,000 | 4,000 | Version 1: (2003-05-30) |
2.2 | 22 | 20,250 | 1,620 | 8,100 | 4,000 | 4,000 | Version 1: (2003-05-30) |
3 | 30 | 40,500 | 1,620 | 8,100 | 10,000 | 10,000 | Version 1: (2003-05-30) |
3.1 | 31 | 108,000 | 3,600 | 18,000 | 14,000 | 14,000 | Version 1: (2003-05-30) |
3.2 | 32 | 216,000 | 5,120 | 20,480 | 20,000 | 20,000 | Version 1: (2003-05-30) |
4 | 40 | 245,760 | 8,192 | 32,768 | 20,000 | 25,000 | Version 1: (2003-05-30) |
4.1 | 41 | 245,760 | 8,192 | 32,768 | 50,000 | 62,500 | Version 1: (2003-05-30) |
4.2 | 42 | 522,240 | 8,704 | 34,816 | 50,000 | 62,500 | Version 1: (2003-05-30) |
5 | 50 | 589,824 | 22,080 | 110,400 | 135,000 | 135,000 | Version 1: (2003-05-30) |
5.1 | 51 | 983,040 | 36,864 | 184,320 | 240,000 | 240,000 | Version 1: (2003-05-30) |
5.2 | 52 | 2,073,600 | 36,864 | 184,320 | 240,000 | 240,000 | Version 6: (2011-06-29) |
6 | 60 | 4,177,920 | 139,264 | 696,320 | 240,000 | 240,000 | Version 11: (2016-10-14) |
6.1 | 61 | 8,355,840 | 139,264 | 696,320 | 480,000 | 480,000 | Version 11: (2016-10-14) |
6.2 | 62 | 16,711,680 | 139,264 | 696,320 | 800,000 | 800,000 | Version 11: (2016-10-14) |
Unconstrained | 0 | - | - | - | - | - | Version 1: (2003-05-30) |
MaxMBPSはマクロブロック速度で、単位はマクロブロック数毎秒。
MaxFS, MaxDpbMbsはマクロブロック数。
MaxBRとMacCPBの単位は、cpbBrVclFactor bitsもしくはcpbBrNalFactor bitsで、下記のテーブルで与えられる。
プロファイル | cpbBrVclFactor | cpbBrNalFactor |
Baseline | 1000 | 1200 |
Main | 1000 | 1200 |
Extended | 1000 | 1200 |
High | 1250 | 1500 |
Progressive High | 1250 | 1500 |
Constrained High | 1250 | 1500 |
High 10 | 3000 | 3600 |
High 10 Intra | 3000 | 3600 |
High 4:2:2 | 4000 | 4800 |
High 4:2:2 Intra | 4000 | 4800 |
High 4:4:4 Predictive | 4000 | 4800 |
High 4:4:4 Intra | 4000 | 4800 |
CAVLC 4:4:4 Intra | 4000 | 4800 |
A.3. プロファイル一覧
プロファイル名 | profile_idc | 追加時期 |
Baseline | 66 | Version 1: (May 30, 2003) |
Main | 77 | Version 1: (May 30, 2003) |
Extended | 88 | Version 1: (May 30, 2003) |
High | 100 | Version 3: (March 1, 2005) |
High 10 | 110 | Version 3: (March 1, 2005) |
High 4:2:2 | 122 | Version 3: (March 1, 2005) |
High 4:4:4 | 244 | Version 3: (March 1, 2005) |
CAVLC 4:4:4 | 44 | Version 7: (April 6, 2007) |
A.4. 関連リンク
- H.264
- ITU が公開している規格書。
- H.264用語集
- この Wikipedia 内で、H.264 に関する用語をまとめたページです。
- OpenH264
- Cisco 社が開発しているオープンソースの H.264 デコーダーです。
- H.264/AVC JM Reference Software
- オープンソースの H.264 デコーダー&エンコーダーです。規格書の通りに実装することを目指していて、規格の策定する際にも使用しています。
- 情報源符号化部 H.264 MPEG-4 AVC 規格の概要
- 総務省のホームページで公開されているPDF。結構わかりやすいと思う。
- ARIB 標準規格(放送分野)一覧表
- 地上デジタル放送などの規定。H.264 はワンセグ放送で使われている。
- デジタルテレビ情報化研究会
- こちらも放送系。IPTV/VODサービスの多くがこの規定をもとにしている。2011年11月30日に活動を停止。2015年度で情報公開終了。
- POSTD H.264の秘密
- H.264の技術をわかりやすく解説している。
A.4. ピクチャとフレームとフィールド
「ピクチャ」は「フレーム」または「フィールド」で構成され、1枚の画像を示します。
「フレーム」はピクチャの構造の1つで、プログレッシブ映像での1枚の画像を示します。
「フィールド」はピクチャの構造の1つで、インタレース映像での1枚の画像を示します。
ただし、インタレースにおいて、1ピクチャごとにフィールドにするかフレームにするかを決めることができる機能(PAFF)があるため、インタレース映像でもフレームになることはあります。
プログレッシブであることは「frame_mbs_only_flag」(Sequence parameter setに存在するフラグ)が非0にすることで明示できます。
A.5. SDK
- http://www.videolan.org/developers/x264.html
- http://www.mainconcept.com/jp/home.html
- http://www.ntt-at.co.jp/product/rfs/
- Intel QuickSync Video
Memo
フレームレート
- SPS (Sequence Parameter Set) の timing_info_present_flag が 1 になっていて、sps.time_scale / sps.num_units_in_tick で求められる。
- もしtiming_info_present_flag が 0 と見なされる場合には、ピクチャに附随する PPS (Picture Timing SEI) の PTS/DTS によって時刻がわかるので、ここから推定する。
- 可変フレームレートの場合は、むしろこの方法以外でピクチャの表示開始時刻をしることはできない。
- ただし、これさえも存在しないこともあり得るため、最終的にはシステム全体としてデフォルト値は必要。