shithub: libvpx

Download patch

ref: 2b368097c8b7837caaeddb189f46dcf068989792
parent: 1ff15fbffe35e45251089e86ef258baaa076f2cd
author: Yaowu Xu <yaowu@google.com>
date: Wed Mar 11 06:16:39 EDT 2015

vp9_pick_inter_mode(): Use single loop to evaluate inter modes

This commit changes to use single loop to evaluate all inter modes.
There is no impact on compression quality and speed, but allow future
experiment with the order of modes evaluated.

Change-Id: I71696ce1014cbe127e25e98710d835987f5ecc09

--- a/vp9/encoder/vp9_pickmode.c
+++ b/vp9/encoder/vp9_pickmode.c
@@ -590,13 +590,27 @@
   *rd_cost = best_rdc;
 }
 
-static const PREDICTION_MODE inter_mode_set[INTER_MODES] = {
-    ZEROMV, NEARESTMV, NEARMV, NEWMV,
-};
-
 static const int ref_frame_cost[MAX_REF_FRAMES] = {
     1235, 229, 530, 615,
 };
+
+typedef struct {
+  MV_REFERENCE_FRAME ref_frame;
+  PREDICTION_MODE pred_mode;
+} REF_MODE;
+
+#define RT_INTER_MODES 8
+static const REF_MODE ref_mode_set[RT_INTER_MODES] = {
+    {LAST_FRAME, ZEROMV},
+    {LAST_FRAME, NEARESTMV},
+    {LAST_FRAME, NEARMV},
+    {LAST_FRAME, NEWMV},
+    {GOLDEN_FRAME, ZEROMV},
+    {GOLDEN_FRAME, NEARESTMV},
+    {GOLDEN_FRAME, NEARMV},
+    {GOLDEN_FRAME, NEWMV}
+};
+
 // TODO(jingning) placeholder for inter-frame non-RD mode decision.
 // this needs various further optimizations. to be continued..
 void vp9_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x,
@@ -653,6 +667,7 @@
   const int pixels_in_block = bh * bw;
   int reuse_inter_pred = cpi->sf.reuse_inter_pred_sby && ctx->pred_pixel_ready;
   int ref_frame_skip_mask = 0;
+  int idx;
 
   if (reuse_inter_pred) {
     int i;
@@ -736,10 +751,18 @@
   if (cpi->rc.frames_since_golden == 0)
     ref_frame_skip_mask |= (1 << GOLDEN_FRAME);
 
-  for (ref_frame = LAST_FRAME; ref_frame <= GOLDEN_FRAME; ++ref_frame) {
-    PREDICTION_MODE this_mode;
-    int i = (ref_frame == LAST_FRAME) ? GOLDEN_FRAME : LAST_FRAME;
+  for (idx = 0; idx < RT_INTER_MODES; ++idx) {
+    int rate_mv = 0;
+    int mode_rd_thresh;
+    int mode_index;
+    int i;
+    PREDICTION_MODE this_mode = ref_mode_set[idx].pred_mode;
 
+    ref_frame = ref_mode_set[idx].ref_frame;
+    mode_index = mode_idx[ref_frame][INTER_OFFSET(this_mode)];
+
+    i = (ref_frame == LAST_FRAME) ? GOLDEN_FRAME : LAST_FRAME;
+
     if (!(cpi->ref_frame_flags & flag_list[ref_frame]))
       continue;
 
@@ -760,211 +783,193 @@
     mbmi->ref_frame[0] = ref_frame;
     set_ref_ptrs(cm, xd, ref_frame, NONE);
 
-    for (i = 0; i < INTER_MODES; ++i) {
-      int rate_mv = 0;
-      int mode_rd_thresh;
-      int mode_index;
-      this_mode = inter_mode_set[i];
-      mode_index = mode_idx[ref_frame][INTER_OFFSET(this_mode)];
+    if (const_motion[ref_frame] && this_mode == NEARMV)
+      continue;
 
-      if (const_motion[ref_frame] && this_mode == NEARMV)
-        continue;
+    if (!(cpi->sf.inter_mode_mask[bsize] & (1 << this_mode)))
+      continue;
 
-      if (!(cpi->sf.inter_mode_mask[bsize] & (1 << this_mode)))
-        continue;
+    mode_rd_thresh = best_mode_skip_txfm ?
+            rd_threshes[mode_index] << 1 : rd_threshes[mode_index];
+    if (rd_less_than_thresh(best_rdc.rdcost, mode_rd_thresh,
+                            rd_thresh_freq_fact[mode_index]))
+      continue;
 
-      mode_rd_thresh = best_mode_skip_txfm ? rd_threshes[mode_index] << 1 :
-                                             rd_threshes[mode_index];
-      if (rd_less_than_thresh(best_rdc.rdcost, mode_rd_thresh,
-                              rd_thresh_freq_fact[mode_index]))
+    if (this_mode == NEWMV) {
+      if (cpi->sf.partition_search_type != VAR_BASED_PARTITION
+          && best_rdc.rdcost < (int64_t) (1 << num_pels_log2_lookup[bsize]))
         continue;
+      if (ref_frame > LAST_FRAME) {
+        int tmp_sad;
+        int dis, cost_list[5];
 
-      if (this_mode == NEWMV) {
-        if (cpi->sf.partition_search_type != VAR_BASED_PARTITION &&
-            best_rdc.rdcost < (int64_t)(1 << num_pels_log2_lookup[bsize]))
+        if (bsize < BLOCK_16X16)
           continue;
 
-        if (ref_frame > LAST_FRAME) {
-          int tmp_sad;
-          int dis, cost_list[5];
+        tmp_sad = vp9_int_pro_motion_estimation(cpi, x, bsize);
+        if (tmp_sad > x->pred_mv_sad[LAST_FRAME])
+          continue;
 
-          if (bsize < BLOCK_16X16)
-            continue;
+        frame_mv[NEWMV][ref_frame].as_int = mbmi->mv[0].as_int;
+        rate_mv = vp9_mv_bit_cost(&frame_mv[NEWMV][ref_frame].as_mv,
+          &mbmi->ref_mvs[ref_frame][0].as_mv,
+          x->nmvjointcost, x->mvcost, MV_COST_WEIGHT);
+        frame_mv[NEWMV][ref_frame].as_mv.row >>= 3;
+        frame_mv[NEWMV][ref_frame].as_mv.col >>= 3;
 
-          tmp_sad = vp9_int_pro_motion_estimation(cpi, x, bsize);
-          if (tmp_sad > x->pred_mv_sad[LAST_FRAME])
-            continue;
-
-          frame_mv[NEWMV][ref_frame].as_int = mbmi->mv[0].as_int;
-          rate_mv = vp9_mv_bit_cost(&frame_mv[NEWMV][ref_frame].as_mv,
-                                    &mbmi->ref_mvs[ref_frame][0].as_mv,
-                                    x->nmvjointcost, x->mvcost, MV_COST_WEIGHT);
-          frame_mv[NEWMV][ref_frame].as_mv.row >>= 3;
-          frame_mv[NEWMV][ref_frame].as_mv.col >>= 3;
-
-          cpi->find_fractional_mv_step(x, &frame_mv[NEWMV][ref_frame].as_mv,
-                                       &mbmi->ref_mvs[ref_frame][0].as_mv,
-                                       cpi->common.allow_high_precision_mv,
-                                       x->errorperbit,
-                                       &cpi->fn_ptr[bsize],
-                                       cpi->sf.mv.subpel_force_stop,
-                                       cpi->sf.mv.subpel_iters_per_step,
-                                       cond_cost_list(cpi, cost_list),
-                                       x->nmvjointcost, x->mvcost, &dis,
-                                       &x->pred_sse[ref_frame], NULL, 0, 0);
-        } else if (!combined_motion_search(cpi, x, bsize, mi_row, mi_col,
-                                           &frame_mv[NEWMV][ref_frame],
-                                           &rate_mv, best_rdc.rdcost)) {
-          continue;
-        }
+        cpi->find_fractional_mv_step(x, &frame_mv[NEWMV][ref_frame].as_mv,
+          &mbmi->ref_mvs[ref_frame][0].as_mv,
+          cpi->common.allow_high_precision_mv,
+          x->errorperbit,
+          &cpi->fn_ptr[bsize],
+          cpi->sf.mv.subpel_force_stop,
+          cpi->sf.mv.subpel_iters_per_step,
+          cond_cost_list(cpi, cost_list),
+          x->nmvjointcost, x->mvcost, &dis,
+          &x->pred_sse[ref_frame], NULL, 0, 0);
+      } else if (!combined_motion_search(cpi, x, bsize, mi_row, mi_col,
+        &frame_mv[NEWMV][ref_frame], &rate_mv, best_rdc.rdcost)) {
+        continue;
       }
+    }
 
-      if (this_mode != NEARESTMV &&
-          frame_mv[this_mode][ref_frame].as_int ==
-              frame_mv[NEARESTMV][ref_frame].as_int)
-        continue;
+    if (this_mode != NEARESTMV && frame_mv[this_mode][ref_frame].as_int ==
+        frame_mv[NEARESTMV][ref_frame].as_int)
+      continue;
 
-      mbmi->mode = this_mode;
-      mbmi->mv[0].as_int = frame_mv[this_mode][ref_frame].as_int;
+    mbmi->mode = this_mode;
+    mbmi->mv[0].as_int = frame_mv[this_mode][ref_frame].as_int;
 
-      // Search for the best prediction filter type, when the resulting
-      // motion vector is at sub-pixel accuracy level for luma component, i.e.,
-      // the last three bits are all zeros.
-      if (reuse_inter_pred) {
-        if (!this_mode_pred) {
-          this_mode_pred = &tmp[3];
-        } else {
-          this_mode_pred = &tmp[get_pred_buffer(tmp, 3)];
-          pd->dst.buf = this_mode_pred->data;
-          pd->dst.stride = bw;
-        }
+    // Search for the best prediction filter type, when the resulting
+    // motion vector is at sub-pixel accuracy level for luma component, i.e.,
+    // the last three bits are all zeros.
+    if (reuse_inter_pred) {
+      if (!this_mode_pred) {
+        this_mode_pred = &tmp[3];
+      } else {
+        this_mode_pred = &tmp[get_pred_buffer(tmp, 3)];
+        pd->dst.buf = this_mode_pred->data;
+        pd->dst.stride = bw;
       }
+    }
 
-      if ((this_mode == NEWMV || filter_ref == SWITCHABLE) &&
-          pred_filter_search && (ref_frame == LAST_FRAME) &&
-          ((mbmi->mv[0].as_mv.row & 0x07) != 0 ||
-           (mbmi->mv[0].as_mv.col & 0x07) != 0)) {
-        int pf_rate[3];
-        int64_t pf_dist[3];
-        unsigned int pf_var[3];
-        unsigned int pf_sse[3];
-        TX_SIZE pf_tx_size[3];
-        int64_t best_cost = INT64_MAX;
-        INTERP_FILTER best_filter = SWITCHABLE, filter;
-        PRED_BUFFER *current_pred = this_mode_pred;
+    if ((this_mode == NEWMV || filter_ref == SWITCHABLE) && pred_filter_search
+        && (ref_frame == LAST_FRAME)
+        && (((mbmi->mv[0].as_mv.row | mbmi->mv[0].as_mv.col) & 0x07) != 0)) {
+      int pf_rate[3];
+      int64_t pf_dist[3];
+      unsigned int pf_var[3];
+      unsigned int pf_sse[3];
+      TX_SIZE pf_tx_size[3];
+      int64_t best_cost = INT64_MAX;
+      INTERP_FILTER best_filter = SWITCHABLE, filter;
+      PRED_BUFFER *current_pred = this_mode_pred;
 
-        for (filter = EIGHTTAP; filter <= EIGHTTAP_SHARP; ++filter) {
-          int64_t cost;
-          mbmi->interp_filter = filter;
-          vp9_build_inter_predictors_sby(xd, mi_row, mi_col, bsize);
-          model_rd_for_sb_y(cpi, bsize, x, xd, &pf_rate[filter],
-                            &pf_dist[filter], &pf_var[filter], &pf_sse[filter]);
-          pf_rate[filter] += vp9_get_switchable_rate(cpi, xd);
-          cost = RDCOST(x->rdmult, x->rddiv, pf_rate[filter], pf_dist[filter]);
-          pf_tx_size[filter] = mbmi->tx_size;
-          if (cost < best_cost) {
-            best_filter = filter;
-            best_cost = cost;
-            skip_txfm = x->skip_txfm[0];
+      for (filter = EIGHTTAP; filter <= EIGHTTAP_SHARP; ++filter) {
+        int64_t cost;
+        mbmi->interp_filter = filter;
+        vp9_build_inter_predictors_sby(xd, mi_row, mi_col, bsize);
+        model_rd_for_sb_y(cpi, bsize, x, xd, &pf_rate[filter], &pf_dist[filter],
+                          &pf_var[filter], &pf_sse[filter]);
+        pf_rate[filter] += vp9_get_switchable_rate(cpi, xd);
+        cost = RDCOST(x->rdmult, x->rddiv, pf_rate[filter], pf_dist[filter]);
+        pf_tx_size[filter] = mbmi->tx_size;
+        if (cost < best_cost) {
+          best_filter = filter;
+          best_cost = cost;
+          skip_txfm = x->skip_txfm[0];
 
-            if (reuse_inter_pred) {
-              if (this_mode_pred != current_pred) {
-                free_pred_buffer(this_mode_pred);
-                this_mode_pred = current_pred;
-              }
+          if (reuse_inter_pred) {
+            if (this_mode_pred != current_pred) {
+              free_pred_buffer(this_mode_pred);
+              this_mode_pred = current_pred;
+            }
 
-              if (filter < EIGHTTAP_SHARP) {
-                current_pred = &tmp[get_pred_buffer(tmp, 3)];
-                pd->dst.buf = current_pred->data;
-                pd->dst.stride = bw;
-              }
+            if (filter < EIGHTTAP_SHARP) {
+              current_pred = &tmp[get_pred_buffer(tmp, 3)];
+              pd->dst.buf = current_pred->data;
+              pd->dst.stride = bw;
             }
           }
         }
+      }
 
-        if (reuse_inter_pred && this_mode_pred != current_pred)
-          free_pred_buffer(current_pred);
+      if (reuse_inter_pred && this_mode_pred != current_pred)
+        free_pred_buffer(current_pred);
 
-        mbmi->interp_filter = best_filter;
-        mbmi->tx_size = pf_tx_size[mbmi->interp_filter];
-        this_rdc.rate = pf_rate[mbmi->interp_filter];
-        this_rdc.dist = pf_dist[mbmi->interp_filter];
-        var_y = pf_var[mbmi->interp_filter];
-        sse_y = pf_sse[mbmi->interp_filter];
-        x->skip_txfm[0] = skip_txfm;
-      } else {
-        mbmi->interp_filter = (filter_ref == SWITCHABLE) ? EIGHTTAP: filter_ref;
-        vp9_build_inter_predictors_sby(xd, mi_row, mi_col, bsize);
-        model_rd_for_sb_y(cpi, bsize, x, xd, &this_rdc.rate, &this_rdc.dist,
-                          &var_y, &sse_y);
-        this_rdc.rate += cm->interp_filter == SWITCHABLE ?
-            vp9_get_switchable_rate(cpi, xd) : 0;
-      }
+      mbmi->interp_filter = best_filter;
+      mbmi->tx_size = pf_tx_size[mbmi->interp_filter];
+      this_rdc.rate = pf_rate[mbmi->interp_filter];
+      this_rdc.dist = pf_dist[mbmi->interp_filter];
+      var_y = pf_var[mbmi->interp_filter];
+      sse_y = pf_sse[mbmi->interp_filter];
+      x->skip_txfm[0] = skip_txfm;
+    } else {
+      mbmi->interp_filter = (filter_ref == SWITCHABLE) ? EIGHTTAP : filter_ref;
+      vp9_build_inter_predictors_sby(xd, mi_row, mi_col, bsize);
+      model_rd_for_sb_y(cpi, bsize, x, xd, &this_rdc.rate, &this_rdc.dist,
+                        &var_y, &sse_y);
+      this_rdc.rate +=
+          cm->interp_filter == SWITCHABLE ?
+              vp9_get_switchable_rate(cpi, xd) : 0;
+    }
 
-      // chroma component rate-distortion cost modeling
-      if (x->color_sensitivity[0] || x->color_sensitivity[1]) {
-        int uv_rate = 0;
-        int64_t uv_dist = 0;
-        if (x->color_sensitivity[0])
-          vp9_build_inter_predictors_sbp(xd, mi_row, mi_col, bsize, 1);
-        if (x->color_sensitivity[1])
-          vp9_build_inter_predictors_sbp(xd, mi_row, mi_col, bsize, 2);
-        model_rd_for_sb_uv(cpi, bsize, x, xd, &uv_rate, &uv_dist,
-                           &var_y, &sse_y);
-        this_rdc.rate += uv_rate;
-        this_rdc.dist += uv_dist;
-      }
+    // chroma component rate-distortion cost modeling
+    if (x->color_sensitivity[0] || x->color_sensitivity[1]) {
+      int uv_rate = 0;
+      int64_t uv_dist = 0;
+      if (x->color_sensitivity[0])
+        vp9_build_inter_predictors_sbp(xd, mi_row, mi_col, bsize, 1);
+      if (x->color_sensitivity[1])
+        vp9_build_inter_predictors_sbp(xd, mi_row, mi_col, bsize, 2);
+      model_rd_for_sb_uv(cpi, bsize, x, xd, &uv_rate, &uv_dist, &var_y, &sse_y);
+      this_rdc.rate += uv_rate;
+      this_rdc.dist += uv_dist;
+    }
 
-      this_rdc.rate += rate_mv;
-      this_rdc.rate += cpi->inter_mode_cost[mbmi->mode_context[ref_frame]]
-                                  [INTER_OFFSET(this_mode)];
-      this_rdc.rate += ref_frame_cost[ref_frame];
-      this_rdc.rdcost = RDCOST(x->rdmult, x->rddiv,
-                               this_rdc.rate, this_rdc.dist);
+    this_rdc.rate += rate_mv;
+    this_rdc.rate +=
+        cpi->inter_mode_cost[mbmi->mode_context[ref_frame]][INTER_OFFSET(
+            this_mode)];
+    this_rdc.rate += ref_frame_cost[ref_frame];
+    this_rdc.rdcost = RDCOST(x->rdmult, x->rddiv, this_rdc.rate, this_rdc.dist);
 
-      // Skipping checking: test to see if this block can be reconstructed by
-      // prediction only.
-      if (cpi->allow_encode_breakout) {
-        encode_breakout_test(cpi, x, bsize, mi_row, mi_col, ref_frame,
-                             this_mode, var_y, sse_y, yv12_mb,
-                             &this_rdc.rate, &this_rdc.dist);
-        if (x->skip) {
-          this_rdc.rate += rate_mv;
-          this_rdc.rdcost = RDCOST(x->rdmult, x->rddiv,
-                                   this_rdc.rate, this_rdc.dist);
-        }
+    // Skipping checking: test to see if this block can be reconstructed by
+    // prediction only.
+    if (cpi->allow_encode_breakout) {
+      encode_breakout_test(cpi, x, bsize, mi_row, mi_col, ref_frame, this_mode,
+                           var_y, sse_y, yv12_mb, &this_rdc.rate,
+                           &this_rdc.dist);
+      if (x->skip) {
+        this_rdc.rate += rate_mv;
+        this_rdc.rdcost = RDCOST(x->rdmult, x->rddiv, this_rdc.rate,
+                                 this_rdc.dist);
       }
+    }
 
 #if CONFIG_VP9_TEMPORAL_DENOISING
-      if (cpi->oxcf.noise_sensitivity > 0)
-        vp9_denoiser_update_frame_stats(mbmi, sse_y, this_mode, ctx);
+    if (cpi->oxcf.noise_sensitivity > 0)
+      vp9_denoiser_update_frame_stats(mbmi, sse_y, this_mode, ctx);
 #else
-      (void)ctx;
+    (void)ctx;
 #endif
 
-      if (this_rdc.rdcost < best_rdc.rdcost || x->skip) {
-        best_rdc = this_rdc;
-        best_mode = this_mode;
-        best_pred_filter = mbmi->interp_filter;
-        best_tx_size = mbmi->tx_size;
-        best_ref_frame = ref_frame;
-        best_mode_skip_txfm = x->skip_txfm[0];
+    if (this_rdc.rdcost < best_rdc.rdcost || x->skip) {
+      best_rdc = this_rdc;
+      best_mode = this_mode;
+      best_pred_filter = mbmi->interp_filter;
+      best_tx_size = mbmi->tx_size;
+      best_ref_frame = ref_frame;
+      best_mode_skip_txfm = x->skip_txfm[0];
 
-        if (reuse_inter_pred) {
-          free_pred_buffer(best_pred);
-          best_pred = this_mode_pred;
-        }
-      } else {
-        if (reuse_inter_pred)
-          free_pred_buffer(this_mode_pred);
+      if (reuse_inter_pred) {
+        free_pred_buffer(best_pred);
+        best_pred = this_mode_pred;
       }
-
-      if (x->skip)
-        break;
+    } else {
+      if (reuse_inter_pred)
+        free_pred_buffer(this_mode_pred);
     }
-
-    // Check that a prediction mode has been selected.
-    assert(best_rdc.rdcost < INT64_MAX);
 
     if (x->skip)
       break;