GoogleがVP8をWebMとしてオープン化しました。本日よりソースコードがダウンロードできます。

第一印象は、H.264から効果の少ないモードやプロファイルを取り去ってシンプル化した上に、新しいツールを組み込んだCODECかなという所です。基本はH.264などと同じ、DCTと1/4画素予測の動き補償を併用したハイブリッド符号化です。

ブロック符号化の要であるブロックサイズについては、dct.hで

typedef prototype_fdct(*vp8_fdct_fn_t);
typedef struct
{
vp8_fdct_fn_t short4x4;
vp8_fdct_fn_t short8x4;
vp8_fdct_fn_t fast4x4;
vp8_fdct_fn_t fast8x4;
vp8_fdct_fn_t walsh_short4x4;
} vp8_fdct_rtcd_vtable_t;

と定義されていて、最大DCTサイズが4x4と、16x16の264に比べて極めて小さいのが独特ですね。フルHDだと264の方が性能が高くなりそうです。dct8x4は最初、インターマクロブロックタイプに応じて適応的にDCTの形状を変えているのかと思っていたんですが、実際はdct4x4を二回呼び出しているだけでした。

動き探索は

extern int vp8_hex_search
(
MACROBLOCK *x,
BLOCK *b,
BLOCKD *d,
MV *ref_mv,
MV *best_mv,
int search_param,
int error_per_bit,
int *num00,
vp8_variance_fn_t vf,
vp8_sad_fn_t sf,
int *mvsadcost[2],
int *mvcost[2]

);

typedef prototype_full_search_sad(*vp8_full_search_fn_t);
extern prototype_full_search_sad(vp8_full_search_sad);
extern prototype_full_search_sad(vp8_full_search_sadx3);

typedef prototype_diamond_search_sad(*vp8_diamond_search_fn_t);
extern prototype_diamond_search_sad(vp8_diamond_search_sad);
extern prototype_diamond_search_sad(vp8_diamond_search_sadx4);

と、ヘキサゴンサーチとダイヤモンドサーチを併用していそうな予感をさせています。

また、動きベクトル精度に関しては、
 int vp8_find_best_sub_pixel_step_iteratively(MACROBLOCK *x, BLOCK *b, BLOCKD *d, MV *bestmv,  MV *ref_mv, int error_per_bit, vp8_subpixvariance_fn_t svf, vp8_variance_fn_t vf, int *mvcost[2])
にて
// 1/2 pel
// 1/4 pel
というコメントがあるので1/4pelですね。

イントラ予測はblockd.hにて、264から少し数を減らしたようなモードが定義されています。

typedef enum
{
B_DC_PRED, // average of above and left pixels
B_TM_PRED,

B_VE_PRED, // vertical prediction
B_HE_PRED, // horizontal prediction

B_LD_PRED,
B_RD_PRED,

B_VR_PRED,
B_VL_PRED,
B_HD_PRED,
B_HU_PRED,

LEFT4X4,
ABOVE4X4,
ZERO4X4,
NEW4X4,

B_MODE_COUNT
} B_PREDICTION_MODE;

VP7,8のお家芸、ループフィルタについてはloopfilter.cにて。

// Horizontal MB filtering
// Vertical MB Filtering

これも264に近く、水平・垂直方向にフィルタをかけているようです。

if (mb_col > 0)
cm->lf_mbv(y_ptr, 0, 0, post->y_stride, 0, &lfi[filter_level], 0);

if (mbd->mode_info_context->mbmi.dc_diff > 0)
cm->lf_bv(y_ptr, 0, 0, post->y_stride, 0, &lfi[filter_level], 0);

// don't apply across umv border
if (mb_row > 0)
cm->lf_mbh(y_ptr, 0, 0, post->y_stride, 0, &lfi[filter_level], 0);

if (mbd->mode_info_context->mbmi.dc_diff > 0)
cm->lf_bh(y_ptr, 0, 0, post->y_stride, 0, &lfi[filter_level], 0);

マクロブロック単位でこんな感じ。vp8_mbloop_filter_horizontal_edge_cという記述があるので何かしらエッジ適応をしていそうです。また、#define MAX_LOOP_FILTER 63という数字が少し気になります。大量のフィルタを用意しておいてブロックに応じて変えている?

後はインターマクロブロックモードがどのくらいあるか気になりますねー。それとPSNRを計ってみたい。

ということでソースコードはJMに比べて非常に読みやすいです。なおかつ、非常にコンパクトなので、モバイル向けにも結構いい性能が出そうな予感がしています。ただ、ベースはほぼ264で、有効なツールだけを残してかなり整理した印象があるので、エンコーダ最適化の伸び白という意味では264の方が大きいかもしれません。264は何でも入っていて、それぞれエンコーダでON/OFFできるので、思ってもいなかった組み合わせで性能が上がったりもするのが面白いですね。

AdobeのFLASHでデフォルトサポートされたり、FirefoxとChromeで今日から使えるというのも本気を感じますね。264陣営とWebM陣営の面白い戦いが見れそうです。ただ、本当にパテントフリーかは注意する必要があるかもです。OggVorbisのようにMP3やAACから、MDCTという点を除けばかなり特殊なことをやっていたのと違い、こちらは大分264に近い印象があるので、そのあたりで各社がどう出るかも楽しみですね。それと、OggVorbisのデファクト化は、2002年のver1.0から考えると実に8年越しで、とても感慨深いです。OggVorbisは独創的でいいCODECなので、これを機会に普及するといいですね。

ということで速報でした。30分ぐらいしかコード読んでいないので間違っている可能性が多々あることにご注意下さい。さて会社行かねば。