shithub: libvpx

Download patch

ref: 4e08fa96f32b30a9302a2de1b1d7d5c7f8ed8397
parent: 22d7f0703a105e7e7b80bb84514b66a52ea91d45
parent: 8ba92a0bed9f05b79851b364c4fafd97ac88e824
author: Paul Wilkins <paulwilkins@google.com>
date: Wed May 22 02:53:12 EDT 2013

Merge "changes intra coding to be based on txfm block" into experimental

--- 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);