shithub: libvpx

Download patch

ref: 8ba92a0bed9f05b79851b364c4fafd97ac88e824
parent: 232d90d8fd47cdc07625036bdd0e4c8f009b8c10
author: Yaowu Xu <[email protected]>
date: Fri May 17 08:50:40 EDT 2013

changes intra coding to be based on txfm block

This commit changed the encoding and decoding of intra blocks to be
based on transform block. In each prediction block, the intra coding
iterates thorough each transform block based on raster scan order.

This commit also fixed a bug in D135 prediction code.

TODO next:
The RD mode/txfm_size selection should take this into account when
computing RD values.

Change-Id: I6d1be2faa4c4948a52e830b6a9a84a6b2b6850f6

--- a/vp9/common/vp9_blockd.h
+++ b/vp9/common/vp9_blockd.h
@@ -192,6 +192,7 @@
     case BLOCK_SIZE_SB64X32:
     case BLOCK_SIZE_SB64X64: return 4;
     default: assert(0);
+      return -1;
   }
 }
 
@@ -215,6 +216,7 @@
     case BLOCK_SIZE_SB32X64:
     case BLOCK_SIZE_SB64X64: return 4;
     default: assert(0);
+      return -1;
   }
 }
 
--- a/vp9/common/vp9_reconintra.c
+++ b/vp9/common/vp9_reconintra.c
@@ -138,15 +138,11 @@
   ypred_ptr[y_stride] = ROUND_POWER_OF_TWO(yabove_row[-1] +
                                            yleft_col[0] * 2 +
                                            yleft_col[1], 2);
-  for (r = 2; r < bh - 1; ++r)
+  for (r = 2; r < bh; ++r)
     ypred_ptr[r * y_stride] = ROUND_POWER_OF_TWO(yleft_col[r - 2] +
                                                  yleft_col[r - 1] * 2 +
-                                                 yleft_col[r + 1], 2);
+                                                 yleft_col[r], 2);
 
-  ypred_ptr[(bh - 1) * y_stride] = ROUND_POWER_OF_TWO(yleft_col[bh - 2] +
-                                                      yleft_col[bh - 1] * 3,
-                                                      2);
-
   ypred_ptr += y_stride;
   for (r = 1; r < bh; ++r) {
     for (c = 1; c < bw; c++)
@@ -396,11 +392,11 @@
 
 void vp9_predict_intra_block(MACROBLOCKD *xd,
                             int block_idx,
-                            BLOCK_SIZE_TYPE bsize,
+                            int bwl_in,
                             TX_SIZE tx_size,
                             int mode,
                             uint8_t *predictor, int pre_stride) {
-  const int bwl = b_width_log2(bsize) - tx_size;
+  const int bwl = bwl_in - tx_size;
   const int wmask = (1 << bwl) - 1;
   const int have_top =
       (block_idx >> bwl) || xd->up_available;
@@ -424,6 +420,6 @@
                           BLOCK_SIZE_TYPE bsize,
                           int mode,
                           uint8_t *predictor, int pre_stride) {
-  vp9_predict_intra_block(xd, block_idx, bsize, TX_4X4,
+  vp9_predict_intra_block(xd, block_idx, b_width_log2(bsize), TX_4X4,
                           mode, predictor, pre_stride);
 }
--- a/vp9/common/vp9_reconintra.h
+++ b/vp9/common/vp9_reconintra.h
@@ -23,7 +23,7 @@
 
 void vp9_predict_intra_block(MACROBLOCKD *xd,
                             int block_idx,
-                            BLOCK_SIZE_TYPE bsize,
+                            int bwl_in,
                             TX_SIZE tx_size,
                             int mode,
                             uint8_t *predictor, int pre_stride);
--- a/vp9/decoder/vp9_decodemv.c
+++ b/vp9/decoder/vp9_decodemv.c
@@ -154,11 +154,11 @@
   m->mbmi.uv_mode = read_uv_mode(r, cm->kf_uv_mode_prob[m->mbmi.mode]);
 
   if (cm->txfm_mode == TX_MODE_SELECT &&
-      !m->mbmi.mb_skip_coeff &&
+    !(m->mbmi.mb_skip_coeff && m->mbmi.ref_frame != INTRA_FRAME)
 #if CONFIG_AB4X4
-      m->mbmi.sb_type >= BLOCK_SIZE_SB8X8
+      && m->mbmi.sb_type >= BLOCK_SIZE_SB8X8
 #else
-      m->mbmi.mode != I4X4_PRED
+      && m->mbmi.mode != I4X4_PRED
 #endif
       ) {
     const int allow_16x16 = m->mbmi.sb_type >= BLOCK_SIZE_MB16X16;
@@ -880,7 +880,8 @@
   if (cm->txfm_mode == TX_MODE_SELECT && mbmi->mb_skip_coeff == 0 &&
       bsize >= BLOCK_SIZE_SB8X8) {
 #else
-  if (cm->txfm_mode == TX_MODE_SELECT && mbmi->mb_skip_coeff == 0 &&
+  if (cm->txfm_mode == TX_MODE_SELECT &&
+      (mbmi->mb_skip_coeff == 0 || mbmi->ref_frame == INTRA_FRAME) &&
       ((mbmi->ref_frame == INTRA_FRAME && mbmi->mode != I4X4_PRED) ||
        (mbmi->ref_frame != INTRA_FRAME && mbmi->mode != SPLITMV))) {
 #endif
--- a/vp9/decoder/vp9_decodframe.c
+++ b/vp9/decoder/vp9_decodframe.c
@@ -239,6 +239,59 @@
   }
 }
 
+static void decode_block_intra(int plane, int block, BLOCK_SIZE_TYPE bsize,
+                               int ss_txfrm_size, void *arg) {
+  MACROBLOCKD* const xd = arg;
+  int16_t* const qcoeff = BLOCK_OFFSET(xd->plane[plane].qcoeff, block, 16);
+  const int stride = xd->plane[plane].dst.stride;
+  const int raster_block = txfrm_block_to_raster_block(xd, bsize, plane,
+                                                       block, ss_txfrm_size);
+  uint8_t* const dst = raster_block_offset_uint8(xd, bsize, plane,
+                                                 raster_block,
+                                                 xd->plane[plane].dst.buf,
+                                                 stride);
+  const TX_SIZE tx_size = (TX_SIZE)(ss_txfrm_size / 2);
+  TX_TYPE tx_type;
+  int mode, b_mode;
+  int plane_b_size;
+  int tx_ib = raster_block >> tx_size;
+  mode = plane == 0? xd->mode_info_context->mbmi.mode:
+                     xd->mode_info_context->mbmi.uv_mode;
+
+  if (bsize <= BLOCK_SIZE_SB8X8 && mode == I4X4_PRED && plane == 0)
+    b_mode = xd->mode_info_context->bmi[raster_block].as_mode.first;
+  else
+    b_mode = mode;
+
+  plane_b_size = b_width_log2(bsize) - xd->plane[plane].subsampling_x;
+  vp9_predict_intra_block(xd, tx_ib, plane_b_size, tx_size,
+                          b_mode, dst, xd->plane[plane].dst.stride);
+
+  switch (ss_txfrm_size / 2) {
+    case TX_4X4:
+      tx_type = plane == 0 ? get_tx_type_4x4(xd, raster_block) : DCT_DCT;
+      if (tx_type == DCT_DCT)
+        xd->itxm_add(qcoeff, dst, stride, xd->plane[plane].eobs[block]);
+      else
+        vp9_iht_add_c(tx_type, qcoeff, dst, stride,
+                      xd->plane[plane].eobs[block]);
+      break;
+    case TX_8X8:
+      tx_type = plane == 0 ? get_tx_type_8x8(xd, raster_block) : DCT_DCT;
+      vp9_iht_add_8x8_c(tx_type, qcoeff, dst, stride,
+                        xd->plane[plane].eobs[block]);
+      break;
+    case TX_16X16:
+      tx_type = plane == 0 ? get_tx_type_16x16(xd, raster_block) : DCT_DCT;
+      vp9_iht_add_16x16_c(tx_type, qcoeff, dst, stride,
+                          xd->plane[plane].eobs[block]);
+      break;
+    case TX_32X32:
+      vp9_idct_add_32x32(qcoeff, dst, stride, xd->plane[plane].eobs[block]);
+      break;
+  }
+}
+
 static void decode_atom_intra(VP9D_COMP *pbi, MACROBLOCKD *xd,
                               vp9_reader *r,
                               BLOCK_SIZE_TYPE bsize) {
@@ -295,6 +348,26 @@
     foreach_transformed_block(xd, bsize, decode_block, xd);
 }
 
+static void decode_sb_intra(VP9D_COMP *pbi, MACROBLOCKD *xd,
+                          int mi_row, int mi_col,
+                          vp9_reader *r, BLOCK_SIZE_TYPE bsize) {
+  MB_MODE_INFO *const mbmi = &xd->mode_info_context->mbmi;
+  if (mbmi->mb_skip_coeff) {
+    vp9_reset_sb_tokens_context(xd, bsize);
+  } else {
+    // re-initialize macroblock dequantizer before detokenization
+    if (xd->segmentation_enabled)
+      mb_init_dequantizer(&pbi->common, xd);
+
+    if (!vp9_reader_has_error(r)) {
+      vp9_decode_tokens(pbi, xd, r, bsize);
+    }
+  }
+
+  foreach_transformed_block(xd, bsize, decode_block_intra, xd);
+}
+
+
 static void decode_sb(VP9D_COMP *pbi, MACROBLOCKD *xd, int mi_row, int mi_col,
                       vp9_reader *r, BLOCK_SIZE_TYPE bsize) {
   const int bwl = mi_width_log2(bsize), bhl = mi_height_log2(bsize);
@@ -422,12 +495,13 @@
   vp9_decode_mb_mode_mv(pbi, xd, mi_row, mi_col, r);
   set_refs(pbi, mi_row, mi_col);
 
+  if (xd->mode_info_context->mbmi.ref_frame == INTRA_FRAME)
+    decode_sb_intra(pbi, xd, mi_row, mi_col, r, bsize);
 #if CONFIG_AB4X4
-  if (bsize < BLOCK_SIZE_SB8X8)
+  else if (bsize < BLOCK_SIZE_SB8X8)
 #else
-  if (bsize == BLOCK_SIZE_SB8X8 &&
-      (xd->mode_info_context->mbmi.mode == SPLITMV ||
-       xd->mode_info_context->mbmi.mode == I4X4_PRED))
+  else if (bsize == BLOCK_SIZE_SB8X8 &&
+      xd->mode_info_context->mbmi.mode == SPLITMV)
 #endif
     decode_atom(pbi, xd, mi_row, mi_col, r, BLOCK_SIZE_SB8X8);
   else
--- a/vp9/decoder/vp9_onyxd_if.c
+++ b/vp9/decoder/vp9_onyxd_if.c
@@ -352,6 +352,16 @@
       vp9_loop_filter_frame(cm, &pbi->mb, cm->filter_level, 0,
                             cm->dering_enabled);
     }
+
+#if WRITE_RECON_BUFFER == 2
+    if (cm->show_frame)
+      write_dx_frame_to_file(cm->frame_to_show,
+                             cm->current_video_frame + 2000);
+    else
+      write_dx_frame_to_file(cm->frame_to_show,
+                             cm->current_video_frame + 3000);
+#endif
+
     vp9_extend_frame_borders(cm->frame_to_show,
                              cm->subsampling_x, cm->subsampling_y);
   }
--- a/vp9/encoder/vp9_bitstream.c
+++ b/vp9/encoder/vp9_bitstream.c
@@ -871,8 +871,9 @@
   if (((rf == INTRA_FRAME && mode != I4X4_PRED) ||
        (rf != INTRA_FRAME && mode != SPLITMV)) &&
       pc->txfm_mode == TX_MODE_SELECT &&
-      !(skip_coeff || vp9_segfeature_active(xd, segment_id,
-                                            SEG_LVL_SKIP)))
+      !(rf != INTRA_FRAME &&
+        (skip_coeff || vp9_segfeature_active(xd, segment_id,
+                                            SEG_LVL_SKIP))))
 #endif
   {
     TX_SIZE sz = mi->txfm_size;
@@ -941,7 +942,8 @@
       !(skip_coeff || vp9_segfeature_active(xd, segment_id, SEG_LVL_SKIP))) {
 #else
   if (ym != I4X4_PRED && c->txfm_mode == TX_MODE_SELECT &&
-      !(skip_coeff || vp9_segfeature_active(xd, segment_id, SEG_LVL_SKIP))) {
+    !(m->mbmi.ref_frame != INTRA_FRAME && (skip_coeff ||
+      vp9_segfeature_active(xd, segment_id, SEG_LVL_SKIP)))) {
 #endif
     TX_SIZE sz = m->mbmi.txfm_size;
     // FIXME(rbultje) code ternary symbol once all experiments are merged
--- a/vp9/encoder/vp9_encodeframe.c
+++ b/vp9/encoder/vp9_encodeframe.c
@@ -1703,21 +1703,16 @@
 #if CONFIG_AB4X4
   if (mbmi->ref_frame == INTRA_FRAME &&
       bsize < BLOCK_SIZE_SB8X8) {
-#else
-  if (mbmi->mode == I4X4_PRED) {
-    assert(bsize == BLOCK_SIZE_SB8X8 && mbmi->txfm_size == TX_4X4);
-#endif
-    vp9_encode_intra4x4mby(cm, x, BLOCK_SIZE_SB8X8);
+    vp9_encode_intra_block_y(cm, x, BLOCK_SIZE_SB8X8);
     vp9_build_intra_predictors_sbuv_s(xd, BLOCK_SIZE_SB8X8);
     vp9_encode_sbuv(cm, x, BLOCK_SIZE_SB8X8);
-
+#else
+  if (xd->mode_info_context->mbmi.ref_frame == INTRA_FRAME) {
+    vp9_encode_intra_block_y(cm, x, bsize);
+    vp9_encode_intra_block_uv(cm, x, bsize);
+#endif
     if (output_enabled)
       sum_intra_stats(cpi, x);
-  } else if (mbmi->ref_frame == INTRA_FRAME) {
-    vp9_build_intra_predictors_sby_s(xd, bsize);
-    vp9_build_intra_predictors_sbuv_s(xd, bsize);
-    if (output_enabled)
-      sum_intra_stats(cpi, x);
   } else {
     int idx = cm->ref_frame_map[get_ref_frame_idx(cpi, mbmi->ref_frame)];
     YV12_BUFFER_CONFIG *ref_fb = &cm->yv12_fb[idx];
@@ -1741,10 +1736,10 @@
   if (mbmi->ref_frame == INTRA_FRAME &&
       bsize < BLOCK_SIZE_SB8X8) {
 #else
-  if (mbmi->mode == I4X4_PRED) {
-    assert(bsize == BLOCK_SIZE_SB8X8);
+  if (xd->mode_info_context->mbmi.ref_frame == INTRA_FRAME) {
 #endif
-    vp9_tokenize_sb(cpi, xd, t, !output_enabled, BLOCK_SIZE_SB8X8);
+    vp9_tokenize_sb(cpi, xd, t, !output_enabled,
+                    (bsize < BLOCK_SIZE_SB8X8) ? BLOCK_SIZE_SB8X8 : bsize);
   } else if (!x->skip) {
     vp9_encode_sb(cm, x, (bsize < BLOCK_SIZE_SB8X8) ? BLOCK_SIZE_SB8X8 : bsize);
     vp9_tokenize_sb(cpi, xd, t, !output_enabled,
@@ -1771,8 +1766,9 @@
 
   if (output_enabled) {
     if (cm->txfm_mode == TX_MODE_SELECT &&
+        (mbmi->ref_frame == INTRA_FRAME ||
         !(mbmi->mb_skip_coeff ||
-          vp9_segfeature_active(xd, segment_id, SEG_LVL_SKIP))) {
+          vp9_segfeature_active(xd, segment_id, SEG_LVL_SKIP)))) {
       if (bsize >= BLOCK_SIZE_SB32X32) {
         cpi->txfm_count_32x32p[mbmi->txfm_size]++;
       } else if (bsize >= BLOCK_SIZE_MB16X16) {
@@ -1783,18 +1779,23 @@
     } else {
       int x, y;
       TX_SIZE sz = (cm->txfm_mode == TX_MODE_SELECT) ? TX_32X32 : cm->txfm_mode;
-
-      if (sz == TX_32X32 && bsize < BLOCK_SIZE_SB32X32)
-        sz = TX_16X16;
-      if (sz == TX_16X16 && bsize < BLOCK_SIZE_MB16X16)
-        sz = TX_8X8;
+       // The new intra coding scheme requires no change of transform size
+      if (mi->mbmi.ref_frame != INTRA_FRAME) {
+        if (sz == TX_32X32 && bsize < BLOCK_SIZE_SB32X32)
+          sz = TX_16X16;
+        if (sz == TX_16X16 && bsize < BLOCK_SIZE_MB16X16)
+          sz = TX_8X8;
 #if CONFIG_AB4X4
-      if (sz == TX_8X8 && bsize < BLOCK_SIZE_SB8X8)
+        if (sz == TX_8X8 && bsize < BLOCK_SIZE_SB8X8)
 #else
-      if (sz == TX_8X8 && (mbmi->mode == SPLITMV ||
-                           mbmi->mode == I4X4_PRED))
+        if (sz == TX_8X8 && mbmi->mode == SPLITMV)
 #endif
+          sz = TX_4X4;
+      } else if (mbmi->mode != I4X4_PRED) {
+        sz = mbmi->txfm_size;
+      } else {
         sz = TX_4X4;
+      }
 
       for (y = 0; y < bh; y++) {
         for (x = 0; x < bw; x++) {
--- a/vp9/encoder/vp9_encodeintra.h
+++ b/vp9/encoder/vp9_encodeintra.h
@@ -16,6 +16,9 @@
 int vp9_encode_intra(VP9_COMP *cpi, MACROBLOCK *x, int use_16x16_pred);
 void vp9_encode_intra16x16mby(VP9_COMMON *const cm, MACROBLOCK *x);
 void vp9_encode_intra16x16mbuv(VP9_COMMON *const cm, MACROBLOCK *x);
-void vp9_encode_intra4x4mby(VP9_COMMON *const cm, MACROBLOCK *mb,
-                            BLOCK_SIZE_TYPE bs);
+void vp9_encode_intra_block_y(VP9_COMMON *const cm, MACROBLOCK *mb,
+                              BLOCK_SIZE_TYPE bs);
+void vp9_encode_intra_block_uv(VP9_COMMON *const cm, MACROBLOCK *mb,
+                               BLOCK_SIZE_TYPE bs);
+
 #endif  // VP9_ENCODER_VP9_ENCODEINTRA_H_
--- a/vp9/encoder/vp9_encodemb.c
+++ b/vp9/encoder/vp9_encodemb.c
@@ -628,16 +628,23 @@
 
   const int txfm_b_size = 4 << tx_size;
   int ib = raster_block;
+  int tx_ib = ib >> tx_size;
+  int plane_b_size;
 
   TX_TYPE tx_type;
+  int mode, b_mode;
 
-  if (tx_size <= TX_16X16)
-    tx_type = txfm_map(xd->mode_info_context->bmi[ib].as_mode.first);
+  mode = plane == 0? xd->mode_info_context->mbmi.mode:
+                     xd->mode_info_context->mbmi.uv_mode;
+  if (bsize <= BLOCK_SIZE_SB8X8 && mode == I4X4_PRED && plane == 0)
+    b_mode = xd->mode_info_context->bmi[ib].as_mode.first;
   else
-    tx_type = DCT_DCT;
+    b_mode = mode;
 
-  vp9_predict_intra_block(&x->e_mbd, ib, bsize, tx_size,
-                          xd->mode_info_context->bmi[ib].as_mode.first,
+  assert(b_mode >= B_DC_PRED && b_mode <= B_TM_PRED);
+
+  plane_b_size = b_width_log2(bsize) - xd->plane[plane].subsampling_x;
+  vp9_predict_intra_block(xd, tx_ib, plane_b_size, tx_size, b_mode,
                           dst, xd->plane[plane].dst.stride);
   vp9_subtract_block(txfm_b_size, txfm_b_size,
                      src_diff, bw,
@@ -650,7 +657,6 @@
   if (x->optimize)
     vp9_optimize_b(plane, block, bsize, ss_txfrm_size, args->cm, x, args->ctx);
     */
-
   switch (ss_txfrm_size / 2) {
     case TX_32X32:
         vp9_short_idct32x32_add(BLOCK_OFFSET(xd->plane[plane].dqcoeff,
@@ -695,8 +701,8 @@
   }
 }
 
-void vp9_encode_intra4x4mby(VP9_COMMON *const cm, MACROBLOCK *x,
-                            BLOCK_SIZE_TYPE bsize) {
+void vp9_encode_intra_block_y(VP9_COMMON *const cm, MACROBLOCK *x,
+                              BLOCK_SIZE_TYPE bsize) {
   MACROBLOCKD* const xd = &x->e_mbd;
   struct optimize_ctx ctx;
   struct encode_b_args arg = {cm, x, &ctx};
@@ -703,5 +709,13 @@
 
   foreach_transformed_block_in_plane(xd, bsize, 0,
                                      encode_block_intra, &arg);
+}
+void vp9_encode_intra_block_uv(VP9_COMMON *const cm, MACROBLOCK *x,
+                              BLOCK_SIZE_TYPE bsize) {
+  MACROBLOCKD* const xd = &x->e_mbd;
+  struct optimize_ctx ctx;
+  struct encode_b_args arg = {cm, x, &ctx};
+
+  foreach_transformed_block_uv(xd, bsize, encode_block_intra, &arg);
 }
 
--- a/vp9/encoder/vp9_onyx_if.c
+++ b/vp9/encoder/vp9_onyx_if.c
@@ -3170,6 +3170,15 @@
   // Pick the loop filter level for the frame.
   loopfilter_frame(cpi, cm);
 
+#if WRITE_RECON_BUFFER
+  if (cm->show_frame)
+    write_cx_frame_to_file(cm->frame_to_show,
+                           cm->current_video_frame + 2000);
+  else
+    write_cx_frame_to_file(cm->frame_to_show,
+                           cm->current_video_frame + 3000);
+#endif
+
   // build the bitstream
   cpi->dummy_packing = 0;
   vp9_pack_bitstream(cpi, dest, size);