Move uv intra mode selection in rd loop.
authorPaul Wilkins <paulwilkins@google.com>
Tue, 16 Jul 2013 17:12:34 +0000 (18:12 +0100)
committerPaul Wilkins <paulwilkins@google.com>
Wed, 17 Jul 2013 10:11:21 +0000 (11:11 +0100)
Use an estimate based on DC_PRED for intra uv cost
within the rd loop then only do a full uv mode analysis
if an intra mode is chosen.

Significant speed gains in some cases. Currently only
enabled for speed 2 pending speed/quality tests.

Change-Id: Ie851a12400d5483bce47ec0e3ccb8516041e91c0

vp9/encoder/vp9_onyx_if.c
vp9/encoder/vp9_onyx_int.h
vp9/encoder/vp9_rdopt.c

index cbb9f87..2112719 100644 (file)
@@ -722,6 +722,7 @@ void vp9_set_speed_features(VP9_COMP *cpi) {
   sf->last_chroma_intra_mode = TM_PRED;
   sf->use_rd_breakout = 0;
   sf->skip_encode_sb = 0;
+  sf->use_uv_intra_rd_estimate = 0;
 
   // Skip any mode not chosen at size < X for all sizes > X
   // Hence BLOCK_SIZE_SB64X64 (skip is off)
@@ -793,6 +794,7 @@ void vp9_set_speed_features(VP9_COMP *cpi) {
         sf->last_chroma_intra_mode = DC_PRED;
         sf->use_rd_breakout = 1;
         sf->skip_encode_sb = 1;
+        sf->use_uv_intra_rd_estimate = 1;
       }
       if (speed == 3) {
         sf->comp_inter_joint_search_thresh = BLOCK_SIZE_TYPES;
index 48f5a12..4c700c6 100644 (file)
@@ -275,6 +275,7 @@ typedef struct {
   unsigned int mode_search_skip_flags;
   MB_PREDICTION_MODE last_chroma_intra_mode;
   int use_rd_breakout;
+  int use_uv_intra_rd_estimate;
 } SPEED_FEATURES;
 
 typedef struct VP9_COMP {
index e98e78e..9e9cbf1 100644 (file)
@@ -1524,6 +1524,24 @@ static int64_t rd_pick_intra_sbuv_mode(VP9_COMP *cpi, MACROBLOCK *x,
   return best_rd;
 }
 
+static int64_t rd_sbuv_dcpred(VP9_COMP *cpi, MACROBLOCK *x,
+                              int *rate, int *rate_tokenonly,
+                              int64_t *distortion, int *skippable,
+                              BLOCK_SIZE_TYPE bsize) {
+  int64_t this_rd;
+
+  x->e_mbd.mode_info_context->mbmi.uv_mode = DC_PRED;
+  super_block_uvrd(&cpi->common, x, rate_tokenonly,
+                   distortion, skippable, NULL, bsize);
+  *rate = *rate_tokenonly +
+          x->intra_uv_mode_cost[x->e_mbd.frame_type][DC_PRED];
+  this_rd = RDCOST(x->rdmult, x->rddiv, *rate, *distortion);
+
+  x->e_mbd.mode_info_context->mbmi.uv_mode = DC_PRED;
+
+  return this_rd;
+}
+
 static int cost_mv_ref(VP9_COMP *cpi, MB_PREDICTION_MODE mode,
                        int mode_context) {
   MACROBLOCK *const x = &cpi->mb;
@@ -3090,7 +3108,7 @@ int64_t vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x,
     frame_mv[ZEROMV][ref_frame].as_int = 0;
   }
 
-  // If intra is not masked off then get best uv intra mode rd.
+  // If intra is not masked off then get uv intra mode rd.
   if (!cpi->sf.use_avoid_tested_higherror
       || (cpi->sf.use_avoid_tested_higherror
           && (ref_frame_mask & (1 << INTRA_FRAME)))) {
@@ -3104,12 +3122,26 @@ int64_t vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x,
 
     mbmi->mode = DC_PRED;
     mbmi->ref_frame[0] = INTRA_FRAME;
+
+    // Test all possible UV transform sizes that may be used in the main loop
     for (i = min_uvtxfm_size; i <= max_uvtxfm_size; ++i) {
       mbmi->txfm_size = i;
-      rd_pick_intra_sbuv_mode(cpi, x, &rate_uv_intra[i],
-                              &rate_uv_tokenonly[i], &dist_uv[i], &skip_uv[i],
-                              (bsize < BLOCK_SIZE_SB8X8) ? BLOCK_SIZE_SB8X8 :
-                                                           bsize);
+
+      // Use an estimated rd for uv_intra based on DC_PRED if the
+      // appropriate speed flag is set.
+      if (cpi->sf.use_uv_intra_rd_estimate) {
+        rd_sbuv_dcpred(cpi, x, &rate_uv_intra[i],
+                       &rate_uv_tokenonly[i], &dist_uv[i], &skip_uv[i],
+                       (bsize < BLOCK_SIZE_SB8X8) ? BLOCK_SIZE_SB8X8 :
+                                                    bsize);
+      // Else do a proper rd search for each possible transform size that may
+      // be considered in the main rd loop.
+      } else {
+        rd_pick_intra_sbuv_mode(cpi, x, &rate_uv_intra[i],
+                                &rate_uv_tokenonly[i], &dist_uv[i], &skip_uv[i],
+                                (bsize < BLOCK_SIZE_SB8X8) ? BLOCK_SIZE_SB8X8
+                                                           : bsize);
+      }
       mode_uv[i] = mbmi->uv_mode;
     }
   }
@@ -3761,6 +3793,20 @@ int64_t vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x,
       break;
   }
 
+  // If we used an estimate for the uv intra rd in the loop above...
+  if (cpi->sf.use_uv_intra_rd_estimate) {
+    // Do Intra UV best rd mode selection if best mode choice above was intra.
+    if (vp9_mode_order[best_mode_index].ref_frame == INTRA_FRAME) {
+      TX_SIZE uv_tx_size = get_uv_tx_size(mbmi);
+      rd_pick_intra_sbuv_mode(cpi, x, &rate_uv_intra[uv_tx_size],
+                              &rate_uv_tokenonly[uv_tx_size],
+                              &dist_uv[uv_tx_size],
+                              &skip_uv[uv_tx_size],
+                              (bsize < BLOCK_SIZE_SB8X8) ? BLOCK_SIZE_SB8X8
+                                                         : bsize);
+    }
+  }
+
   // If indicated then mark the index of the chosen mode to be inspected at
   // other block sizes.
   if (bsize <= cpi->sf.unused_mode_skip_lvl) {