2008年9月18日

H.264 CAVLC

日本語の記事をあまり見かけないのでちょっと解説しておく。H.264/AVCといえばCABAC(コンテクスト適応算術符号化)が注目されがちだが、CAVLC(コンテクスト適応可変長符号化)もMPEG-1/2/4など今までの可変長符号(VLC)と大きく異なる。 MPEG-1/2はJPEGの可変長符号とほとんど同じで、DC係数は係数の値から決定するVLC、AC係数はゼロランと非ゼロの係数から決定する2次元VLCを用いている。MPEG-4ではそこに最後の非ゼロの係数かどうかも加えて3次元VLCとするらしいのだが、詳しく勉強していないのでよくわからない。H.264/AVCのCAVLCなのだが、実際に"コンテクスト適応"となっているのは最初の符号だけで中身はもっと複雑だ。以下にCAVLCの処理の概要を示す。


  1.  「ジグザグスキャン順で最後に続く絶対値が1の係数の数」、「非ゼロの係数の数」、「左と上の4x4ブロックの非ゼロの係数の数の平均(nC)」のコンテクスト適応VLC(3次元VLC)。各コンテクスト毎に「ジグザグスキャン順で最後に続く絶対値1の係数の数(trailing_ones)」と「非ゼロの係数の数(total_coeff)」の2次元VLCを符号化する。ここでいうコンテクストというのは「左と上の4x4ブロックの非ゼロの係数の数の平均(nC)」のことで、上の2次元にこのコンテクストを加えて3次元VLCと見ることもできる。 
  2. 「最後に続く絶対値が1の係数」の符号。「(スキャン順で)最後に続く絶対値が1の係数の符号」を符号化する。CAVLCにおける「最後に続く絶対値が1の係数」の数の最大値は3であるから、ここでは0~3bit書き込まれることになる。この連続する1の数が4以上のときはまだ検証していないのでここでは言及しない。
  3. 「係数のレベル」をプレフィックスとサフィックスに分けて符号化。「最後に続く絶対値1の係数の符号」を書き込んだ後にようやく係数のレベルを符号化する。係数のレベルの符号化は、負の値を奇数、正の値を偶数に変換してすべて非負の値にした後にプレフィックスとサフィックスに分けて符号化する。サフィックスの長さは「非ゼロの係数の数(total_coef)」と「ジグザグスキャン順で最後に続く絶対値1の係数の数(trailing_ones)」から初期値を求め、符号化対象係数ごとに算出する。最大値は6である。サフィックスの長さがわかれば非負値にした係数をその長さ分だけ右シフトすればプレフィックスも求めることができる。プレフィックスはユーナリー符号、サフィックスはそのままのビットが符号化される。
  4.  「非ゼロの係数の数」と「ゼロの係数の数」の2次元VLC 
  5. 「符号化対象の係数の前のすべての非ゼロの係数の数」と「符号化対象の係数の前に続くゼロラン」の2次元VLC。この符号は「非ゼロの係数の数(total_coef)」だけある。 


このように、今までのVLCと違ってH.264/AVCではかなり工夫がされている。ここでは、CAVLCということで、予測誤差をDCTと量子化した後の係数の符号化方法のみを示した。ブロックタイプ、予測モード/MV、デルタQP、CBPなどのブロックのパラメータの符号化は指数ゴロム符号化などがおこなわれる。効率がかなり良くなるCABACの陰に隠れがちだが、CABACの方は1ビット符号化(復号)毎に数回の演算が必要だから、演算速度は現在ではそれほど差が出ないかもしれないが、消費電力は結構差が出るかもしれない。ということで、ビットレートと画質が十分に出せれば、消費電力の観点からCABACオフにしてもいいかもしれない。 

CABACはブロックのパラメータをVLCにして係数もすべて0/1にして、各ビットをコンテクストに振り分けて、算術符号化(Range Coder)する。コンテクストはHigh Profileで460個もある。VLCと違って算術符号化はエントロピー(理論限界)に到達するし、符号化/復号で処理が対象的になるのが個人的に好きなのだが、H.264/AVCのコンテクストは多いように思う。コンテクストモデリングはOn2(WebM)のVP8がもう少しすっきりしているのかもしれない。まだ調査していないけど。また次世代では、処理速度が算術符号化に比較して符号化で3~5倍、復号で少なくとも2倍で、エントロピーの点でも算術符号化に迫る性能で、並列化にも適応できるV2V Codeなんてのも検討されているらしい。2値化とコンテクストモデリングはCABACと共通で2値算術符号化の部分だけ置き換える技術らしいがアルゴリズムの詳細はよくわからない。