kalli123 / webm

Automatically exported from code.google.com/p/webm
0 stars 0 forks source link

422 chroma prediction for 8x4/4x4 block sizes is incorrect #993

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
In vp9_dec_build_inter_predictors_sb(), this code will be triggered for 4:2:2 
chroma blocks with num_4x4_w=1 and num_4x4_h=2:

    if (xd->mi[0].src_mi->mbmi.sb_type < BLOCK_8X8) {
      int i = 0, x, y;
      assert(bsize == BLOCK_8X8);
      for (y = 0; y < num_4x4_h; ++y)
        for (x = 0; x < num_4x4_w; ++x)
          dec_build_inter_predictors(xd, plane, i++, bw, bh,
                                     4 * x, 4 * y, 4, 4, mi_x, mi_y);
    } else {

i++ is only incremented within the loop iterations, so the values in 
dec_build_inter_predictors for the top 4x4 chroma block is 0, and bottom is 1. 
This value is then used to get the final motion vector:

static void dec_build_inter_predictors(MACROBLOCKD *xd, int plane, int block,
                                       int bw, int bh,
                                       int x, int y, int w, int h,
                                       int mi_x, int mi_y) {
[..]
    const MV mv = mi->mbmi.sb_type < BLOCK_8X8
               ? average_split_mvs(pd, mi, ref, block)
               : mi->mbmi.mv[ref].as_mv;

which is:

static MV average_split_mvs(const struct macroblockd_plane *pd,
                            const MODE_INFO *mi, int ref, int block) {
  const int ss_idx = ((pd->subsampling_x > 0) << 1) | (pd->subsampling_y > 0);
  MV res = {0, 0};
  switch (ss_idx) {
    case 0:
      res = mi->bmi[block].as_mv[ref].as_mv;
      break;
    case 1:
      res = mi_mv_pred_q2(mi, ref, block, block + 2);
      break;
    case 2:
      res = mi_mv_pred_q2(mi, ref, block, block + 1);
      break;
    case 3:
      res = mi_mv_pred_q4(mi, ref);
      break;
    default:
      assert(ss_idx <= 3 && ss_idx >= 0);
  }
  return res;
}

The result of all this is that for the bottom 4x4 block in chroma blocks with 
lumasize=8x4 or 4x4, the indices for the luma motion vectors averaged into the 
final motion vector are 0 and 1 for the top block (which is correct), and 1 and 
2 for the bottom block (instead of 2 and 3), thus resulting in wacky chroma 
inter prediction.

I realize that you can't fix this in vp9, but it'd be nice to fix it in vp10. I 
found the bug while implementing ffvp9.

Original issue reported on code.google.com by rsbul...@gmail.com on 30 Apr 2015 at 3:57

GoogleCodeExporter commented 9 years ago
Thanks, it is a known issue, we will fix it in next generation codec.

Original comment by ya...@google.com on 7 May 2015 at 10:22