shithub: libvpx

Download patch

ref: c59e36fc76ce3c5dd0b9a40e8f95a225248ce018
parent: 7a18c81663cec6d445d3c2c408690827ae418482
parent: 4f36b7c6b9cc56bf39d5e4a3a4c7ad6f045ada81
author: Ronald S. Bultje <rbultje@google.com>
date: Thu Aug 30 05:11:41 EDT 2012

Merge "Add proper skip support to intra frames." into experimental

--- a/vp8/encoder/rdopt.c
+++ b/vp8/encoder/rdopt.c
@@ -1136,11 +1136,12 @@
                                       MACROBLOCK *x,
                                       int *rate,
                                       int *rate_tokenonly,
-                                      int *distortion) {
+                                      int *distortion,
+                                      int *skippable) {
   MB_PREDICTION_MODE mode;
   MB_PREDICTION_MODE UNINITIALIZED_IS_SAFE(mode_selected);
   int this_rate, this_rate_tokenonly;
-  int this_distortion;
+  int this_distortion, s;
   int64_t best_rd = INT64_MAX, this_rd;
 
   /* Y Search for 32x32 intra prediction mode */
@@ -1150,7 +1151,7 @@
                  build_intra_predictors_sby_s)(&x->e_mbd);
 
     super_block_yrd_8x8(x, &this_rate_tokenonly,
-                        &this_distortion, IF_RTCD(&cpi->rtcd), NULL);
+                        &this_distortion, IF_RTCD(&cpi->rtcd), &s);
     this_rate = this_rate_tokenonly +
                 x->mbmode_cost[x->e_mbd.frame_type]
                               [x->e_mbd.mode_info_context->mbmi.mode];
@@ -1162,6 +1163,7 @@
       *rate           = this_rate;
       *rate_tokenonly = this_rate_tokenonly;
       *distortion     = this_distortion;
+      *skippable      = s;
     }
   }
 
@@ -1172,10 +1174,11 @@
 #endif
 
 static int64_t rd_pick_intra16x16mby_mode(VP8_COMP *cpi,
-                                      MACROBLOCK *x,
-                                      int *Rate,
-                                      int *rate_y,
-                                      int *Distortion) {
+                                          MACROBLOCK *x,
+                                          int *Rate,
+                                          int *rate_y,
+                                          int *Distortion,
+                                          int *skippable) {
   MB_PREDICTION_MODE mode;
   MB_PREDICTION_MODE UNINITIALIZED_IS_SAFE(mode_selected);
 #if CONFIG_COMP_INTRA_PRED
@@ -1187,6 +1190,8 @@
   int distortion;
   int64_t best_rd = INT64_MAX;
   int64_t this_rd;
+  int UNINITIALIZED_IS_SAFE(skip);
+  MACROBLOCKD *xd = &x->e_mbd;
 
   // Y Search for 16x16 intra prediction mode
   for (mode = DC_PRED; mode <= TM_PRED; mode++) {
@@ -1218,6 +1223,11 @@
       this_rd = RDCOST(x->rdmult, x->rddiv, rate, distortion);
 
       if (this_rd < best_rd) {
+#if CONFIG_TX16X16
+        skip = mby_is_skippable_16x16(xd);
+#else
+        skip = mby_is_skippable_8x8(xd);
+#endif
         mode_selected = mode;
 #if CONFIG_COMP_INTRA_PRED
         mode2_selected = mode2;
@@ -1232,6 +1242,7 @@
 #endif
   }
 
+  *skippable = skip;
   mbmi->mode = mode_selected;
 #if CONFIG_COMP_INTRA_PRED
   mbmi->second_mode = mode2_selected;
@@ -1590,7 +1601,8 @@
                                     MACROBLOCK *x,
                                     int *rate,
                                     int *rate_tokenonly,
-                                    int *distortion) {
+                                    int *distortion,
+                                    int *skippable) {
   MB_PREDICTION_MODE mode;
   MB_PREDICTION_MODE UNINITIALIZED_IS_SAFE(mode_selected);
 #if CONFIG_COMP_INTRA_PRED
@@ -1597,10 +1609,11 @@
   MB_PREDICTION_MODE mode2;
   MB_PREDICTION_MODE UNINITIALIZED_IS_SAFE(mode2_selected);
 #endif
+  MACROBLOCKD *xd = &x->e_mbd;
   MB_MODE_INFO * mbmi = &x->e_mbd.mode_info_context->mbmi;
   int64_t best_rd = INT64_MAX;
   int UNINITIALIZED_IS_SAFE(d), UNINITIALIZED_IS_SAFE(r);
-  int rate_to;
+  int rate_to, UNINITIALIZED_IS_SAFE(skip);
 
   for (mode = DC_PRED; mode <= TM_PRED; mode++) {
 #if CONFIG_COMP_INTRA_PRED
@@ -1640,6 +1653,7 @@
       this_rd = RDCOST(x->rdmult, x->rddiv, rate, distortion);
 
       if (this_rd < best_rd) {
+        skip = mbuv_is_skippable(xd);
         best_rd = this_rd;
         d = distortion;
         r = rate;
@@ -1654,6 +1668,7 @@
 
   *rate = r;
   *distortion = d;
+  *skippable = skip;
 
   mbmi->uv_mode = mode_selected;
 #if CONFIG_COMP_INTRA_PRED
@@ -1665,13 +1680,15 @@
                                         MACROBLOCK *x,
                                         int *rate,
                                         int *rate_tokenonly,
-                                        int *distortion) {
+                                        int *distortion,
+                                        int *skippable) {
+  MACROBLOCKD *xd = &x->e_mbd;
   MB_PREDICTION_MODE mode;
   MB_PREDICTION_MODE UNINITIALIZED_IS_SAFE(mode_selected);
   MB_MODE_INFO * mbmi = &x->e_mbd.mode_info_context->mbmi;
   int64_t best_rd = INT64_MAX;
   int UNINITIALIZED_IS_SAFE(d), UNINITIALIZED_IS_SAFE(r);
-  int rate_to;
+  int rate_to, UNINITIALIZED_IS_SAFE(skip);
 
   for (mode = DC_PRED; mode <= TM_PRED; mode++) {
     int rate;
@@ -1695,6 +1712,7 @@
     this_rd = RDCOST(x->rdmult, x->rddiv, rate, distortion);
 
     if (this_rd < best_rd) {
+      skip = mbuv_is_skippable_8x8(xd);
       best_rd = this_rd;
       d = distortion;
       r = rate;
@@ -1704,6 +1722,7 @@
   }
   *rate = r;
   *distortion = d;
+  *skippable = skip;
   mbmi->uv_mode = mode_selected;
 }
 
@@ -1711,9 +1730,10 @@
 static void super_block_uvrd_8x8(MACROBLOCK *x,
                                  int *rate,
                                  int *distortion,
-                                 const VP8_ENCODER_RTCD *rtcd) {
+                                 const VP8_ENCODER_RTCD *rtcd,
+                                 int *skippable) {
   MACROBLOCKD *const xd = &x->e_mbd;
-  int d = 0, r = 0, n;
+  int d = 0, r = 0, n, s = 1;
   const uint8_t *usrc = x->src.u_buffer, *udst = xd->dst.u_buffer;
   const uint8_t *vsrc = x->src.v_buffer, *vdst = xd->dst.v_buffer;
   int src_uv_stride = x->src.uv_stride, dst_uv_stride = xd->dst.uv_stride;
@@ -1736,6 +1756,7 @@
                           dst_uv_stride);
     vp8_transform_mbuv_8x8(x);
     vp8_quantize_mbuv_8x8(x);
+    s &= mbuv_is_skippable_8x8(xd);
 
     d += ENCODEMB_INVOKE(&rtcd->encodemb, mbuverr)(x) >> 2;
     xd->above_context = ta + x_idx;
@@ -1745,8 +1766,9 @@
 
   xd->above_context = ta;
   xd->left_context = tl;
-  *distortion = (d >> 2);
+  *distortion = d;
   *rate       = r;
+  *skippable  = s;
 
   xd->left_context = tl;
   xd->above_context = ta;
@@ -1758,12 +1780,13 @@
                                        MACROBLOCK *x,
                                        int *rate,
                                        int *rate_tokenonly,
-                                       int *distortion) {
+                                       int *distortion,
+                                       int *skippable) {
   MB_PREDICTION_MODE mode;
   MB_PREDICTION_MODE UNINITIALIZED_IS_SAFE(mode_selected);
   int64_t best_rd = INT64_MAX, this_rd;
   int this_rate_tokenonly, this_rate;
-  int this_distortion;
+  int this_distortion, s;
 
   for (mode = DC_PRED; mode <= TM_PRED; mode++) {
     x->e_mbd.mode_info_context->mbmi.uv_mode = mode;
@@ -1771,7 +1794,7 @@
                  build_intra_predictors_sbuv_s)(&x->e_mbd);
 
     super_block_uvrd_8x8(x, &this_rate_tokenonly,
-                         &this_distortion, IF_RTCD(&cpi->rtcd));
+                         &this_distortion, IF_RTCD(&cpi->rtcd), &s);
     this_rate = this_rate_tokenonly +
                 x->mbmode_cost[x->e_mbd.frame_type]
                               [x->e_mbd.mode_info_context->mbmi.mode];
@@ -1783,6 +1806,7 @@
       *rate           = this_rate;
       *rate_tokenonly = this_rate_tokenonly;
       *distortion     = this_distortion;
+      *skippable      = s;
     }
   }
 
@@ -3056,17 +3080,17 @@
   vp8_update_zbin_extra(cpi, x);
 
   rd_pick_intra_mbuv_mode(cpi, x, &uv_intra_rate,
-                          &uv_intra_rate_tokenonly, &uv_intra_distortion);
+                          &uv_intra_rate_tokenonly, &uv_intra_distortion,
+                          &uv_intra_skippable);
   uv_intra_mode = mbmi->uv_mode;
-  uv_intra_skippable = mbuv_is_skippable(&x->e_mbd);
 
   /* rough estimate for now */
   if (cpi->common.txfm_mode == ALLOW_8X8) {
     rd_pick_intra_mbuv_mode_8x8(cpi, x, &uv_intra_rate_8x8,
                                 &uv_intra_rate_tokenonly_8x8,
-                                &uv_intra_distortion_8x8);
+                                &uv_intra_distortion_8x8,
+                                &uv_intra_skippable_8x8);
     uv_intra_mode_8x8 = mbmi->uv_mode;
-    uv_intra_skippable_8x8 = mbuv_is_skippable_8x8(&x->e_mbd);
   }
 
   // Get estimates of reference frame costs for each reference frame
@@ -3602,21 +3626,22 @@
                       && this_mode != B_PRED
                       && this_mode != I8X8_PRED);
 
-#if CONFIG_TX16X16
-        if (this_mode <= TM_PRED ||
-            this_mode == NEWMV ||
-            this_mode == ZEROMV ||
-            this_mode == NEARESTMV ||
-            this_mode == NEARMV)
-          mb_skippable = mb_is_skippable_16x16(&x->e_mbd);
-        else
-#endif
         if ((cpi->common.txfm_mode == ALLOW_8X8) && has_y2) {
-          if (mbmi->ref_frame != INTRA_FRAME)
+          if (mbmi->ref_frame != INTRA_FRAME) {
+#if CONFIG_TX16X16
+            mb_skippable = mb_is_skippable_16x16(&x->e_mbd);
+#else
             mb_skippable = mb_is_skippable_8x8(&x->e_mbd);
-          else
+#endif
+          } else {
+#if CONFIG_TX16X16
             mb_skippable = uv_intra_skippable_8x8
+                           & mby_is_skippable_16x16(&x->e_mbd);
+#else
+            mb_skippable = uv_intra_skippable_8x8
                            & mby_is_skippable_8x8(&x->e_mbd);
+#endif
+          }
         } else {
           if (mbmi->ref_frame != INTRA_FRAME)
             mb_skippable = mb_is_skippable(&x->e_mbd, has_y2);
@@ -3878,26 +3903,37 @@
 void vp8_rd_pick_intra_mode_sb(VP8_COMP *cpi, MACROBLOCK *x,
                                int *returnrate,
                                int *returndist) {
+  VP8_COMMON *cm = &cpi->common;
+  MACROBLOCKD *xd = &x->e_mbd;
   int rate_y, rate_uv;
   int rate_y_tokenonly, rate_uv_tokenonly;
   int error_y, error_uv;
   int dist_y, dist_uv;
+  int y_skip, uv_skip;
 
   x->e_mbd.mode_info_context->mbmi.txfm_size = TX_8X8;
 
   error_uv = rd_pick_intra_sbuv_mode(cpi, x, &rate_uv, &rate_uv_tokenonly,
-                                     &dist_uv);
+                                     &dist_uv, &uv_skip);
   error_y = rd_pick_intra_sby_mode(cpi, x, &rate_y, &rate_y_tokenonly,
-                                   &dist_y);
+                                   &dist_y, &y_skip);
 
-  // TODO(rbultje): add rate_uv
-  *returnrate = rate_y;
-  *returndist = dist_y + (dist_uv >> 2);
+  if (cpi->common.mb_no_coeff_skip && y_skip && uv_skip) {
+    *returnrate = rate_y + rate_uv - rate_y_tokenonly - rate_uv_tokenonly +
+                  vp8_cost_bit(get_pred_prob(cm, xd, PRED_MBSKIP), 1);
+    *returndist = dist_y + (dist_uv >> 2);
+  } else {
+    *returnrate = rate_y + rate_uv;
+    if (cpi->common.mb_no_coeff_skip)
+      *returnrate += vp8_cost_bit(get_pred_prob(cm, xd, PRED_MBSKIP), 0);
+    *returndist = dist_y + (dist_uv >> 2);
+  }
 }
 #endif
 
 void vp8_rd_pick_intra_mode(VP8_COMP *cpi, MACROBLOCK *x,
                             int *returnrate, int *returndist) {
+  VP8_COMMON *cm = &cpi->common;
   MACROBLOCKD *xd = &x->e_mbd;
   MB_MODE_INFO * mbmi = &x->e_mbd.mode_info_context->mbmi;
   int64_t error4x4, error16x16;
@@ -3905,12 +3941,12 @@
   int64_t error4x4d;
   int rate4x4d, dist4x4d;
 #endif
-  int rate4x4, rate16x16 = 0, rateuv;
-  int dist4x4, dist16x16, distuv;
+  int rate4x4, rate16x16 = 0, rateuv, rateuv8x8;
+  int dist4x4, dist16x16, distuv, distuv8x8;
   int rate;
   int rate4x4_tokenonly = 0;
   int rate16x16_tokenonly = 0;
-  int rateuv_tokenonly = 0;
+  int rateuv_tokenonly = 0, rateuv8x8_tokenonly = 0;
   int64_t error8x8;
   int rate8x8_tokenonly=0;
   int rate8x8, dist8x8;
@@ -3917,10 +3953,24 @@
   int mode16x16;
   int mode8x8[2][4];
   int dist;
+  int modeuv, modeuv8x8, uv_intra_skippable, uv_intra_skippable_8x8;
+  int y_intra16x16_skippable;
 
   mbmi->ref_frame = INTRA_FRAME;
-  rd_pick_intra_mbuv_mode(cpi, x, &rateuv, &rateuv_tokenonly, &distuv);
-  rate = rateuv;
+  rd_pick_intra_mbuv_mode(cpi, x, &rateuv, &rateuv_tokenonly, &distuv,
+                          &uv_intra_skippable);
+  modeuv = mbmi->uv_mode;
+  if (cpi->common.txfm_mode == ALLOW_8X8) {
+    rd_pick_intra_mbuv_mode_8x8(cpi, x, &rateuv8x8, &rateuv8x8_tokenonly,
+                                &distuv8x8, &uv_intra_skippable_8x8);
+    modeuv8x8 = mbmi->uv_mode;
+  } else {
+    uv_intra_skippable_8x8 = uv_intra_skippable;
+    rateuv8x8 = rateuv;
+    distuv8x8 = distuv;
+    rateuv8x8_tokenonly = rateuv_tokenonly;
+    modeuv8x8 = modeuv;
+  }
 
   // current macroblock under rate-distortion optimization test loop
 #if CONFIG_HYBRIDTRANSFORM
@@ -3928,7 +3978,8 @@
 #endif
 
   error16x16 = rd_pick_intra16x16mby_mode(cpi, x, &rate16x16,
-                                          &rate16x16_tokenonly, &dist16x16);
+                                          &rate16x16_tokenonly, &dist16x16,
+                                          &y_intra16x16_skippable);
   mode16x16 = mbmi->mode;
 
 #if CONFIG_HYBRIDTRANSFORM
@@ -3965,8 +4016,15 @@
                                         &dist4x4d, error16x16, 1, 0);
 #endif
 
-  if (error8x8 > error16x16) {
+  if (cpi->common.mb_no_coeff_skip &&
+      y_intra16x16_skippable && uv_intra_skippable_8x8) {
+    mbmi->uv_mode = modeuv;
+    rate = rateuv8x8 + rate16x16 - rateuv8x8_tokenonly - rate16x16_tokenonly +
+           vp8_cost_bit(get_pred_prob(cm, xd, PRED_MBSKIP), 1);
+    dist = dist16x16 + (distuv8x8 >> 2);
+  } else if (error8x8 > error16x16) {
     if (error4x4 < error16x16) {
+      rate = rateuv;
 #if CONFIG_COMP_INTRA_PRED
       rate += (error4x4d < error4x4) ? rate4x4d : rate4x4;
       if (error4x4d >= error4x4) // FIXME save original modes etc.
@@ -3978,14 +4036,17 @@
       rate += rate4x4;
 #endif
       mbmi->mode = B_PRED;
-      dist = dist4x4;
+      dist = dist4x4 + (distuv >> 2);
     } else {
       mbmi->mode = mode16x16;
-      rate += rate16x16;
-      dist = dist16x16;
+      rate = rate16x16 + rateuv8x8;
+      dist = dist16x16 + (distuv8x8 >> 2);
     }
+    if (cpi->common.mb_no_coeff_skip)
+      rate += vp8_cost_bit(get_pred_prob(cm, xd, PRED_MBSKIP), 0);
   } else {
     if (error4x4 < error8x8) {
+      rate = rateuv;
 #if CONFIG_COMP_INTRA_PRED
       rate += (error4x4d < error4x4) ? rate4x4d : rate4x4;
       if (error4x4d >= error4x4) // FIXME save original modes etc.
@@ -3997,18 +4058,19 @@
       rate += rate4x4;
 #endif
       mbmi->mode = B_PRED;
-      dist = dist4x4;
+      dist = dist4x4 + (distuv >> 2);
     } else {
       mbmi->mode = I8X8_PRED;
       set_i8x8_block_modes(x, mode8x8);
-      rate += rate8x8;
-      dist = dist8x8;
+      rate = rate8x8 + rateuv;
+      dist = dist8x8 + (distuv >> 2);
     }
+    if (cpi->common.mb_no_coeff_skip)
+      rate += vp8_cost_bit(get_pred_prob(cm, xd, PRED_MBSKIP), 0);
   }
 
-  // TODO(rbultje): should add rateuv here also
-  *returnrate = rate - rateuv;
-  *returndist = dist + (distuv >> 2);
+  *returnrate = rate;
+  *returndist = dist;
 }
 
 #if CONFIG_SUPERBLOCKS
--- a/vp8/encoder/tokenize.h
+++ b/vp8/encoder/tokenize.h
@@ -38,6 +38,7 @@
 extern int mbuv_is_skippable_8x8(MACROBLOCKD *xd);
 extern int mb_is_skippable_8x8(MACROBLOCKD *xd);
 extern int mb_is_skippable_16x16(MACROBLOCKD *xd);
+extern int mby_is_skippable_16x16(MACROBLOCKD *xd);
 
 #ifdef ENTROPY_STATS
 void init_context_counters();