トップ 検索 一覧 差分 ソース ヘルプ RSS ログイン

x264(nal-hrd),H.264/AVC(HRD),MPEG-1/2(VBV)

このページの全ては誤っているかもしれません。x264関連の記事に関してを読んでください。

x264(nal-hrd),H.264/AVC(HRD),MPEG-1/2(VBV)

x264のr1480ではnal-hrd/pulldown/interlaceパッチがメインラインに取り込まれた。このうちnal-hrd部分に関して、H.264 / MPEG-4 Part10 AVC(ISO/IEC 14496-10)のHRDと、MPEG-1/2(ISO/IEC 11172-2とISO/IEC 13818-2)のVBVを絡めて説明を試みる。

なお、この記事ではVBVに関しては意味論しか語っていない。x264のVBV関連のパラメータに実際に指定する値を知りたい方は、x264(vbv-maxrate,vbv-bufsize,profile,level), H.264(Profile/Level)を参照のこと。

 x264の--nal-hrdオプション

この記事はどちらかといえばHRD/VBVの意味論を解説するもので、オプションの解説とは趣が異なる。しかし、中身なんぞどうでもいいから、オプションの使用方法だけ知りたい方のために簡単に書いておく。

普通は--nal-hrd vbrを付けておけば良い。これを使用するには--vbv-bufsize/--vbv-maxrateの指定が必須で、そのためCQPモードは使用できない。

--nal-hrdオプションを使用すると、HRD用のデータが付加される。その分サイズが膨らむor画質が低下することにはなるが、このデータが存在することで様々な環境での再生互換性が向上する。とくにBlu-ray disc関連での互換性が向上する(規格で要求されているらしい)ため、付けておいた方が後々のためになる。

--nal-hrdを付けない方がよいケースは、以下のような場合である。

  • VFRを使用している。
    • HRDはその設計上、基本的にあまりVFRを真剣に考慮していない。
  • 動画サイトへの投稿など。具体的には…
    • それにしか使用しない(保存目的ではない)。
    • 低ビットレートが要求されており、HRDデータさえも排除したい。

HRDのデータが付くことで再生互換性が低下することは通常ありえない。HRDを必要としない環境では単にこれを無視するのが仕様であり、無視できないデコーダやプレーヤが存在するとすれば、それはそちらのバグである。--audと同じで、おまじないのように付けておくと再生可能な環境が広がるものと思うとよいだろう。PS3ではaud+mp4で挙動不審になるケースがあるらしいが…。

なお、--nal-hrdにはcbrも指定できるが、特段の理由がない限りcbrを使う必要はない。ここでいうcbrは従来のx264で言う、--vbv-maxrate = --bitrateとした時のCBRモードを指すわけではない。--nal-hrd cbrとした場合、--nal-hrd vbrとした時に付加されるデータに加えて、fillerデータと言うなんの意味もないスカスカのデータが加えられる。つまり、mp4/mkv/flvなどのVBRを適切に扱えるコンテナに納める上では、単なるムダでしかない。そもそもx264は、mp4にmuxする場合、--nal-hrd cbrは扱えないようになっている。

 前口上

冒頭のパッチの取り込みを機に、予予から中途半端であったHRDの解説記事をなんとかしたいと思っていたのだが、いざ、説明を書こうとするとなかなか難しい。

まずこのパッチ自体、かなり複合的な意味を持つパッチで、全てを1つの記事に詰め込むのは妥当ではない。

とりあえずHRDだけを書きたいのだが、HRDを説明するにはVBVを語らねばならない。VBV自体はH.264の規格書には現れない言葉だが、H.264のHRDとはMPEG-1/2のVBVに相当するものであり、かつx264には--vbv-bufsizeなどのオプションがあるので、別物としては語れない。そして、VBVに関しては日本語で説明しているサイトが殆ど見つからない。

また、オプションが--nal-hrdというからには、NALに関しても説明しなければならない。SEI/SPS/PPSなどの用語にも軽くは触れておくべきだろう。こちらに関してはひとまず、H.264/AVC(NAL)でなんとかやっつけた。

これでなんとか手を付けられないかと書いてみたのが、この記事になる。

 大まかに理解する

H.264/AVCのHRDはHypothetical Reference Decoderの略で、「仮想参照デコーダ」と訳されることが多いようだ。ただしここでのReferenceは恐らく、ハードウェア関連で「リファレンスボード」や「リファレンスドライバ」と言う場合のそれと同じで、「標準」という意味が強いように思う。このため、敢えて訳さず「仮想リファレンスデコーダ」とするか、「仮想標準デコーダ」と呼ぶ方が理解しやすいだろう。HRDに関しては、Microsoftの映像圧縮形式であるVC-1でも同様のものが規定されているらしい。

一方、MPEG-1/2のVBVはVideo Buffering Verifierの略で、標準的な日本語訳というものは目にしたことがない。無理矢理日本語にするなら「映像バッファ確認機」とでもなるのだろうか。VBV自体はMPEG-1/2固有というわけでもないのだろうが、手元にある資料の範囲でそう記載させてもらった。

HRDとVBVは、大雑把にいって同じものを指している。なにせ、MPEG-2の"Annex C Video buffering verifier"には、"The VBV is a hypothetical decoder"と書かれている。どちらもデコーダのバッファ管理をモデル化したものであり、エンコーダはHRD/VBVのバッファをオーバーフローまたはアンダーフローさせないようなデータを作成しなければならない。

ただし、VBVに比べるとHRDはかなり複雑、かつ詳細に規定されている。MPEG-1の時には2〜3ページだったVBVの規定は、インターレース対応などを含んだMPEG-2では5ページ以上に増え、HRDと名を変えたH.264/AVCでは10ページ以上に増えている。

つまるところ、MPEG系の映像圧縮規格におけるバッファ管理は非常に複雑であるため、その正当性を検証する仕組みとして規定されているものがHRD/VBVだ。

HRD/VBVの必要性

実は、HRDとVBVはデコーダ側にとっては必須ではない。単にデコードするだけならば、コンテナにも含まれるタイムスタンプやSTC(System Time Clock)、そして他のパラメータから演繹的に求められる最大バッファサイズを使用して、処理は行えるはずだからだ。

これが規格において敢えてnormative(規範的=必須)と規定されているのは、幾つか理由が考えられる。例えば、

  • デコーダが正常に扱えるデータ、つまり規格に適合するビットストリームに関してより具体的に示しておくため。
  • 複雑なバッファ管理に関して、冗長(重複)ではあっても、まとめて規定するため。
  • 規格本体は基本的にデコーダに関してのみ規定しているが、エンコーダに対する配慮として示しておくため。
  • HRDの場合、ビットストリームとデコーダの規格適合性テストの一部として使用させるため。

といった理由が推測される。

規格書には規定の動機が直接的に書かれている訳ではないので、真相はわからない。しかし実際のところ、少なくともVBVに関しては、多くのエンコーダでレートコントロールの検証システムとして使用されている。

そして関連する規格、特にメジャーな規格であるBlu-ray discでは、HRDに対応していることが必須であるらしい。これはHRDで必要とされるデータが、ストリームに含まれている必要があることを意味する。規格書を斜め読みした限りでは、VBVへの対応にはそれに必要とされる特別なデータはない(vbv_delayとlow_delay程度)が、HRDへの対応はストリーム中にHRD用のデータを埋め込む必要がある。

なぜBDでこれが必須なのかはやはり謎(規格書を見たこともないので筆者が知らないだけかも知れない)だ。しかし、VCD(Video CD)やSVCD(Super Video CD)、DVD等では、それらの規格に厳密に従わないものが数多くあったため、より再生互換性を確保する目的で、HRDの対応が必須とされているのかも知れない。少なくとも、HRDがついているストリームは、それなりの意識を持って開発されたエンコーダが使用されていることは期待できる。また、通常のデコーダが処理する仕組みとは別に、HRDデータによってエンコーダの意図するバッファ管理を確認することができる。HRDデータは冗長ではあるが、規格適合性・互換性チェックを行うコンプライアンスの観点では非常に有用だと言えるだろう。

x264との関わり

前項の事柄は、x264の動作を見ればある程度確かめることができる。

まず、--vbv-bufsize/--vbv-maxrateというオプションが存在すること、--vbv-maxrate指定時にqpmaxを小さめに指定するとVBV underflowの警告が発生することでVBVが含まれていることは分かる。x264がVBV的な仕組みを意識していること、そしてVBVがエンコーダにレートコントロールの目的で使用されることの証左と言えるだろう。

この際のもうひとつのポイントは、--nal-hrdオプションが無くとも(r1480より前のリビジョンでも)これらが存在することだ。r1480までのx264はHRDには対応していなかったが、VBVには対応していたということになる。逆に言えば--nal-hrdオプションはHRD用の追加データを埋め込むためだけのオプションだと理解できる。つまり、--nal-hrdがなくとも、バッファ管理やレートコントロールの仕組みそのものがないわけでは(当たり前だが)ない。

本当のところはx264のオリジナルの開発者にでも聞いてみなければ分からないが、x264が単に--maxrateというオプションではなく--vbv-maxrateにしたのには、「絶対に守るべき」ビットレートであるという意図が込められているのかもしれない。

 Filler-NALユニットに関して

x264で--nal-hrd cbrとした場合、Filler-NALユニットが使用される。これは文字通り「埋める」ためのものであって、いわゆるパディングにあたる。

CBRの幻想で既に書いている通り、現代的な圧縮技術において、真のCBRというものは存在しない。だがレートコントロールとVBVの働きで、CBRに限りなく近くすることはできる。ここまでがこれまでのx264が言うCBRモードだ。

--nal-hrd cbrは、そこからさらにこのFiller-NALユニットを使用し、残りの僅かな誤差、ビットレートのブレを埋めることで、擬制的に真のCBRに見えるストリームが作成できることを意味している。

しかし、現代において擬制的CBRを使う意味は殆ど見いだせない。データ量の見積りには従来のCBRモードで十分であるし、画質が向上するわけでもなく、現代的なコンテナを使う上では処理の高速化も期待できない。H.264を使用する関連規格で求められる(そんな規格があるのかは知らないが)ようなケース以外では、--nal-hrd cbrを使う意味は、全くない

 VBVのアンダーフロー・オーバーフロー

ところで、x264が発する警告であるところのVBV underflowだが、「なぜオーバーフローではなくアンダーフローなのか」と疑問に感じたことはないだろうか。

一般的なPCユーザーがオーバーフローと言われれば、「データが多すぎてバッファから溢れる」ことを想像する。逆にアンダーフローと言われれば、CD-R/DVD±Rの書き込み時に処理が間に合わず、「バッファにデータが足りない」ことを想像するだろう。x264がVBV underflowを発するのは、あるスライスが複雑すぎて、許されたqpmaxでは大きすぎる符号化データしか生成できなかった時だ。データが大きいのに、オーバーフローではなくアンダーフローと言われるとしっくりこない方もいるだろう。

これは、VBV(またはHRD)が擬似的なデコーダであることを思い出せば理解しやすい。実はVBVでは、オーバーフローだけでなく、アンダーフローでもバッファはある程度埋まっていることが多い。デコーダは本来、無制限に符号化データを受け取ったり、展開画像データを出力する機械ではない。タイムスタンプやSTC(System Time Clock)を元に、決められた時刻にデータを受け取り、決められた時刻にデータを出力するものだ、というところにポイントが有る。

オーバーフロー

まずはオーバーフローがどのような場合に発生するのかを考えてみよう。

デコーダの出力側において、出力先がデータをなかなか受け取ってくれなかったとする。するとデコーダは決められた期間より長くそのデータを保持しなければならなくなる。入力側は通常通り決められた時刻にデータを受け取らねばならないが、バッファには空きがなく、データを受け取れない

はたまた、エンコーダのタイムスタンプ管理が疎かで、デコーダには本来より遅い出力時刻が渡されたとする。この場合にはデコーダが信じる「決められた時刻」が遅いのであるから、デコーダは本来「空き」になるべきバッファを保持し続け、やはりバッファが溢れて新たな入力を受け取ることが出来ない

これがVBVのオーバーフローであり、デコーダの入力側(つまりエンコーダの出力側)のデータサイズとは必ずしも関係はない。

アンダーフロー

ではアンダーフローとはどういう状況か。

今度は、デコーダの出力側は正常に動作しているとする。入力側は決められた時刻に、--vbv-maxrateの指定に従い、十分な量のバッファの空きを用意してデータの到着を待っている。しかし、その空きバッファが全て埋まっても、1つのピクチャ(フレーム)を展開するにはデータが足りない状況が考えられる。バッファは(少なくともある程度は)埋まっているにも関わらず、1ピクチャ分に満たないため、決められた時刻にデータを出力することができない。これがVBVのアンダーフローであり、指定されたビットレートでは転送が間に合わず、デコーダが十分なデータを受け取れない可能性がある事を示している。

この際、デコーダのバッファに余剰の空きがあり、デコーダの入力側に接続されている機器が十分な転送能力を持っていれば、ズルをして間に合うように処理してしまうことは不可能ではない。しかし、これは規格に定められた厳密で適正な処理とは言えない。また、転送が可能でもデコーダのバッファに空きが無ければ、それはアンダーフローであると同時にオーバーフローであるということになる。そのようなストリームを出力するエンコーダは規格に適合しているとは言えない。

なお、デコーダの入力側が通信機器などであり、その転送能力の問題によってデコーダが展開済みの画像データを出力側に供給できないこともある。これもアンダーフローではあるが、ここで問題にしているのはVBV/HRDであり、つまりエンコーダ内の仮想的なデコーダにおけるものだ。仮想的なデコーダに対して転送能力の問題は発生しないので、「VBVのアンダーフロー」とはつまりエンコーダの出力の問題になる。また、仮想的なデコーダに対して出力側の問題も発生しない(タイムスタンプが間違っていなければ)ので、x264のエンコードではVBV overflowも基本的に発生することはない。

オーバーフロー・アンダーフローの結論

つまるところ、VBVのオーバーフローもアンダーフローもエンコーダの出力に起因することはある。このうち、映像データの特性とユーザの指定パラメータ次第でデコーダの入力側で起こるバッファの問題がアンダーフローだ。これはエンコーダにバグが無くとも起こりうる。逆に、基本的にはデコーダの出力側で起こる問題がオーバーフローで、VBVという仮想的なデコーダでこれが発生する状況は、エンコーダのバグである。

なお、CBRの幻想もレートコントロール・VBVの理解に資するかもしれないので、興味のある方はそちらも参照のこと。

 HRDの詳細

ここからは上級者向けになる。とは言っても、この情報を必要とするような人は規格書を直接読むべきなので、ここではそのガイドとしての簡単な記述に留める。

この項を理解するためには、先にH.264/AVC(NAL)を読んでおいた方がいい。x264のオプションは--nal-hrdという名前であるにもかかわらず、ここまでは敢えてNALに触れてこなかったが、ここでは大まかにNALが理解できている前提で進める。

規格書上のHRDの構成

H.264の規格書上、HRDはAnnex CにHypothetical reference decoderとして規定されている。厳密な仕様としては最新のバージョンを読むべきだが、最近のH.264の仕様にはSVC(x264(constrained-intra)を参照)やMVC(Multiview Video Coding)の関連項目が含まれており、HRDにもこれら関連の情報が入っているため、読みづらい。200305版や200503版ならばこれらの項目が導入される以前なので、比較的読みやすいだろう。ここでは200305版を基準に話を進める。

規格書はまず、ストリームの種別を2つ定義している。

TYPE I
VCL-NALユニットとfiller-NALユニットのみのビットストリーム。
TYPE II
VCL-NALユニットとfiller-NALユニット以外を含むビットストリーム。Annex BのByte stream formatを使う場合も、そうでない場合も含む。

これらNALユニットの種類に関しては、規格書の7.4 Semanticsで述べられているが、VCL/非VCLの区別が表に含まれているのは200711版以降(200503版のCorやAmdでどうかは見ていない)になる。簡単に言ってしまえばスライスデータが含まれるNALユニットはVCLで、それ以外(SPS/PPS/SEI/filler等)は非VCLだ。

次に、HRDに必要なパラメータが埋め込まれる箇所について2つ言及している。一つはSPSの一部であるVUIで、バッファサイズ等、多くの主要パラメータがこの中に埋め込まれる。もう一つはSEIで、SEIに複数あるメッセージ種別のうち、Buffering periodとPicture timingがそれである。これらのデータがビットストリーム中でなく別途供給される場合に関してイチイチ注記が入るが、無視していいだろう。なお、PPSには直接HRDと関連するデータはないようだが、デコードを行うという意味でPPSの存在自体は必須だ。

少々脱線するが、nal-hrd/pulldown/interlaceパッチは3つの機能を統合したパッチとして提供されていた。その理由はここにあり、pulldownとinterlaceで必要なpic_structフラグは、このSEIのPicture timingメッセージに存在することによる。なぜPicture timingにpic_structが?と疑問に思わないでもないが、pic_structにはNumClockTSという値が関連付けられており、これがタイミングの計算式に影響するため、ということのようだ。

次にHRDの構成に関して、HSS, CPB, instantaneous decoding process, DPBからなる図が示される。これらも簡単に説明しておこう。

HSS(Hypothetical Stream Scheduler)
ある意味HRDのキモ(その割にはあまり詳細に語られないが)で、上記のunderflow/overflowを説明した際の「決められた時刻に入力する」を担当する部分。デコーダの入力は転送能力に制限のあるネットワーク回線であることも考えられるため、CPBに渡すデータはそのタイミングと量を厳密に管理されねばならない。
CPB(Coded Picture Buffer)
符号化されているスライスデータを格納するバッファ。x264の--vbv-bufsizeで示すバッファサイズは、このバッファのサイズになる。規格書ではレベルごとにTable A-1 Level limitsで規定されているので、これを使うのが標準的だが、関連規格で指定されている場合にはその値を使うことになるだろう。このサイズはVUIから得ることになる。
instantaneous decoding process
そのまま訳せば、「即時デコード処理」となる。HRDは仮想的なデコーダなので、デコード処理は瞬時に完了すると仮定されている。
DPB(Decoded Picture Buffer)
展開された画像データ、つまり生のYUV4:2:0などのピクセルデータを格納するバッファ。CPBと同様に規格書に規定がある。このサイズもVUIから得ることになる。

この後は、具体的なcpb_initial_arrival_time, cpb_removal_time, dpb_output_delayなどを駆使しての処理が規定されている。この記事は「HRDを自作しよう!」という記事ではないので、ここではタイトルのみ羅列するに留める。

  • C.1 Operation of coded picture buffer (CPB)
    • C.1.1 Timing of bitstream arrival
    • C.1.2 Timing of coded picture removal
  • C.2 Operation of the decoded picture buffer (DPB)
    • C.2.1 Decoding of gaps in frame_num and storage of "non-existing" frames
    • C.2.2 Picture decoding and output
    • C.2.3 Removal of pictures from the DPB before possible insertion of the current picture
    • C.2.4 Current decoded picture marking and storage
    • C.2.4.1 Marking and storage of a reference decoded picture into the DPB
    • C.2.4.2 Storage of a non-reference picture into the DPB
  • C.3 Bitstream conformance
  • C.4 Decoder conformance
    • C.4.1 Operation of the output order DPB
    • C.4.2 Decoding of gaps in frame_num and storage of "non-existing" pictures
    • C.4.3 Picture decoding
    • C.4.4 Removal of pictures from the DPB before possible insertion of the current picture
    • C.4.5 Current decoded picture marking and storage
      • C.4.5.1 Storage and marking of a reference decoded picture into the DPB
      • C.4.5.2 Storage and marking of a non-reference decoded picture into the DPB
      • C.4.5.3 "Bumping" process

このように、H.264/AVCのHRDは、MPEG-1/2に比べてもかなり事細かに記述されている。

 補足

幾つか気になる点に関して、補足しておく。

TYPEとVCL-HRD

ここまで読んだ方は、恐らく以下のような疑問が湧くだろう。

  • ビットストリームのタイプを定義したのに、これはどこで使われるのか。
  • TYPE Iのビットストリームは非VCL-NALユニットを含まないのに、SPS(VUI)/PPS/SEIを使うとはどういうことか。
  • x264のオプションは--nal-hrdと名付けられているが、NALではないHRDとは何か。

これらの質問の答は、恐らく同じ部分に帰結する。要は、H.264の規格書は、H.264のストリームを、一般的な形式であるTYPE IIの形式で運用しなければならないとは言っていない点にポイントはある。非VCL-NALユニットはH.264のストリームに埋め込まれていなければならないわけではない。このようなビットストリームは"stand-alone" Type I bitstreamsと呼ばれている。これを強調するために、しつこく"by (some) other means not specified in this Recommendation | International Standard"という文言が繰り返されていると言ってもよさそうなくらいだ。

HRDの定義としてはそのようなストリームに対しても機能を提供したい。これはNALレベルの検証機能というよりもVCLレベルの検証機能だと言える。そのため、TYPE Iのストリームに対しては、VCL-HRDが提供される。ただし、そのために必要な情報は結局、(ストリームとは別に提供されるはずの)VUIに埋め込まれる。

このVCL-HRDの情報はフォーマットとしてはNAL-HRDと全く同じだ。規格書上でも全く同じ、"hrd_parameters()"で表現されている。TYPE IをVCL-HRDで検証する上では、ビットレートの計算上、VCL-NALユニットとfiller-NALユニットのみを算入して検証する。TYPE IIをNAL-HRDで検証する上では、TYPE Iと同じ内容に加えて、全てのNALユニットをビットレート計測上のデータ量として算入して検証する。つまり、NAL-HRDとVCL-HRDは対象とするデータの範囲が異なるだけで、コンセプトは全く同じものだ。このあたりはもう少し込み入った話もあるので、興味のある方はC.3 Bitstream conformanceとA.3.1のi)とj)を読んでみて欲しい。

まとめると、まずHRDにはVCL-HRDとNAL-HRDがある。x264が出力するのは非VCL-NALユニットを含むTYPE IIのストリームだ。従ってx264が--nal-hrdで実現するのは、そのストリームに対するNALレベルのHRD機能だということだ。

規格書上のアンダーフロー・オーバーフロー

最後に、VBVのoverflow/underflowに関して補足しておく。

規格書のC.3 Bitstream conformanceには、正式なoverflow/underflowの定義が書いてある。数式を読み解きたくないので説明しなかったが、本来の理解としてはこちらを参照すべきだ。簡単に言って、オーバーフローに関してはCPBが溢れた時を指す。そしてアンダーフローに関しては、ピクチャ(フレーム)をCPBから削除(つまりデコード)しなければならないタイミングにおいて、CPBに当該ピクチャのデータが揃っていない時、となっている。

 あとがき

思ったよりも大型の記事になったので少し所感を。

タイトルに困る

この記事のタイトルには困った。

x264のオプションを解説したいわけだが、内容的には多くがMPEG-1/2のVBVで、HRDに絡む部分はH.264の規格の解説としての色の方が強い。タイトルは検索エンジンに引っ掛けてもらう上でも重要なので、下手に限定したタイトルにはしたくない。しかし、全ての要素を入れるとごちゃごちゃになりすぎる。

まぁ結局のところ、全部入りにしてしまったわけなのだけれど。

苦労

この記事を書くのには、少なく見積もっても合計12時間以上はかかった。総文字数は10k文字を超え、ちょっとした大学生の夏のレポート並になった。

なぜこれほどまでに時間をかけねばならなかったのか。考えてみると、そもそもVBVというのが、一般には具体的な中身のイメージを伴って理解されてはいないのだと思われる。VBVの概念がわかっていれば、この記事の内容は半分以下にはなる。つまり、この記事の半分以上は、VBVの説明なのだ。

では、なぜVBVは一般に知られていないのか。今回、当然のようにVBVでWebの検索はかけたのだが、日本語でVBVを説明しているページは非常に少ない。これは恐らくだが、VBVを具体的に知らなければならない人間にとっては、VBVは当たり前の存在なのだろう。なにせMPEG-1では2ページ弱程度しかない物で、その頃からエンコーダに関わっている人間にとっては、とても軽い話題だ。そしてVBVを曖昧にしか知らなくていい人間にとっては、「レートコントロールのナニか」くらいでも問題がない。なにせ外部から触れるのは最大ビットレートとバッファサイズ程度で、一般的にはバッファサイズもレベルやプロファイルに包含され、見えないことも多いからだ。

筆者はx264に興味を持ったのがr1000付近からで、多少慣れては来たものの、まだまだnewbieだ。その筆者が最初にx264cliに触れたとき抱いた疑問の一つが、--vbv-maxrateの名前だ。

「VBVってナンだ?」

この記事に書いていることは、まさに当時の筆者が知りたかったことそのものだ。願わくば、同じようなnewbieの理解の助けにならんことを。

最終更新時間:2010年04月10日 21時58分29秒