トップ 検索 一覧 ヘルプ RSS ログイン

x264(deadzone,trellis)の変更点

  • 追加された行はこのように表示されます。
  • 削除された行はこのように表示されます。
このページの全ては誤っているかもしれません。[[x264関連の記事に関して]]を読んでください。

(2009/09/01:全体に訂正)trellis=2の時はdeadzone不使用とのことなので全体に書き直しました。

!!!x264(deadzone,trellis)

本当はdeadzoneやtrellisがどのような動作をするオプションなのかを書くべきなのだろうけれど。

それはいつか書くとして、猫科研究所のx264関連記事は勉強の記録なので勉強したことを書く。
この2つのオプションは''大体''両立しない。今回はその「大体」の部分について書く。

!!deadzonne,trellisの目的

deadzoneもtrellisも''量子化後の端数処理についてのオプション''である。
量子化というのは大雑把に言うと、''割り算''を使ってある''値の取り得る範囲を限定する処理''だ。
例えば<256,128,64>という値が並んでいる場合に、これらをそのまま記録するのではなく、これまた例えば16で割った値を記録しようということ。
そうすると<256,128,64>は<16,8,4>となる。
例えば<256,64,128>という値が並んでいる場合に、これらをそのまま記録するのではなく、これまた例えば16で割った値を記録しようということ。
そうすると<256,64,128>は<16,4,8>となる。
これで何が嬉しいかというと、その後の''エントロピー圧縮(CABAC等)がよく効く''ようになる。

この例の場合、最初の値がいずれも16で割り切れるため、特に問題はない。
だが、現実のエンコード時には''割り切れない値''が普通に存在し、その場合に割り算の「余り」、つまり量子化による端数はデータとして出力されない。この「端数情報の破棄」こそ、H.264に限らず現代的な''不可逆映像・音声圧縮のコア''であり、その失われた情報が「量子化誤差」と呼ばれるものだ。
つまり、量子化とは「データを間引いてデータ量を減らす」処理に他ならない。
そして、いずれにせよ最終的に出力はしないものの、その''端数をどう扱うか''を指定するのがこれらのオプションになる。

deadzoneを一言で言えば、四捨五入, 五捨六入, 六捨七入のように、''閾値を定めて一律に端数を処理''するオプションだ。そしてtrellisは画質と出力データ量のバランスを計算して、''適応的に決めさせる''オプションである。当然、量子化誤差の量だけを勘案すれば、四捨五入が最も精度が良く劣化が少ないに決まっている。が、画質とサイズのトレードオフというRD観点では''必ずしも四捨五入が正解ではない''点がミソだ。

これ以上は詳説になるので省略するが、このようにdeadzoneとtrellisは、基本的に同じものを扱うオプションである。

!x264におけるdeadzone,trellis

端数処理という''同じ目的に対して2つのオプションがある''のだから、当然この2つは''両立しない''、'''はず'''。
[まるも大先生の2007/07/07の記事|http://www.marumo.ne.jp/db2007_7.htm#7]にもそう書いてあるし、自分の理解としても当然そうなると思っていた。

しかし、実は現状のx264はそうではない。この記事を書くきっかけは某巨大掲示板だったのだけれど、[trellis使用時もdeadzoneは使用されるとのこと|http://pc11.2ch.net/test/read.cgi/avi/1248750814/279-283]だった。
そしてx264の議論が開発者も含め活発に行われているDoom9でも、[「trellis使用時はdeadzoneは不使用じゃないの?」という質問|http://forum.doom9.org/showthread.php?p=1307457#post1307457]が出ていて、これにDark_Shikari氏が''「trellis=1でもMBのモード決定に影響する」''と答えている。
これが意外だったので検証すべくソースを漁った。

!!ソース検証

r1206で検証している。

deadzoneはcommon/set.cで内部的に変換の上、''quant4_bias, quant8_bias''という2つの配列に設定され、使用されている。
なので"quant._bias"で正規表現grepをかけてみた。すると、宣言、初期化、設定部分以外のほとんどは

 if( h->mb.b_trellis )

の''else側''で使用されており、やはり両立しない。

だが…''あった''。
encoder/macroblock.cのx264_macroblock_probe_skip()で3つほど、b_trellisで切り分けされていないquant._biasの使用箇所が。
macroblock_probe_skipなので、''p/bのスキップMBの判定に使用''されている。

つまり、trellis使用時にはdeadzoneは量子化の端数処理そのものには使用されない。
が、スキップMBの判定にはdeadzoneで指定の値が使用される。
スキップMBとは大雑把に言うと''"被参照MBと全く同一と見なすMB"''で、ビットが非常に節約できるため、その判定の役割は結構重要だ。
なお、ビットが節約できるからといってむやみにスキップMBにすればよいわけではない。スキップMBは量子化以外によるアーティファクト(ブロックノイズやモスキートノイズ以外のアーティファクト)の発生源だったりもするので、慎重な判断が必要だ。

!!考察

以前、前述の経緯を確認せずにこのページを書いたため、この節ではtrellis=2の場合にRD観点で決定しないのはおかしいと書いていたが、実際には上記の通りtrellis=1の場合のみdeadzone使用ということなので問題はないようだ。

ただし、今回の検証でコードを見た限りではtrellis=1の場合のみに"quant._bias"が使用されるように切り分けられているようには見えなかった。
直接的ではない内部パラメータでそのように動作するのかも知れないが、そこまで深追いはしなかった。

本当はJMではどうなってるのかとかも検証するべきなのだろうが、JMのソースは見たことがないしそこまでの気力もないので割愛。
本当はJMにtrellisがあるのなら、そちらではどうなってるのかも検証するべきなのだろうが、JMのソースは見たことがないしそこまでの気力もないので割愛。

!!結論

deadzoneとtrellisは''大体''排他的である。
つまりtrellis有効時にはdeadzoneの設定は不使用となる。
ただしtrellis=1の場合にスキップMBの判断はdeadzoneを基準として行われる。
r1206での検証なので将来的には不明。