]> granicus.if.org Git - libvpx/commitdiff
Enable early termination in uv rd loop
authorJingning Han <jingning@google.com>
Wed, 14 Aug 2013 23:50:45 +0000 (16:50 -0700)
committerJingning Han <jingning@google.com>
Mon, 19 Aug 2013 23:31:19 +0000 (16:31 -0700)
This commit enables early termination in the rate-distortion
optimization search loop for chroma components. When the cumulative
rd cost is above the current best value, skip the rest per-block
transform/quantization/coeff_cost and continue to the next
prediction mode.

For bus_cif at 2000 kbps, the average run-time goes down from
168546ms -> 164678ms, (2% speed-up) at speed 0
 36197ms ->  34465ms, (4% speed-up) at speed 1

Change-Id: I9d3043864126e62bd0166250d66b3170d520b3c0

vp9/encoder/vp9_rdopt.c

index 6482615a304af4bfcf17a7e6a279f7addde42e45..36a77220095715f50711a815686241807847ea00 100644 (file)
@@ -1282,7 +1282,8 @@ static int64_t rd_pick_intra_sby_mode(VP9_COMP *cpi, MACROBLOCK *x,
 
 static void super_block_uvrd(VP9_COMMON *const cm, MACROBLOCK *x,
                              int *rate, int64_t *distortion, int *skippable,
-                             int64_t *sse, BLOCK_SIZE_TYPE bsize) {
+                             int64_t *sse, BLOCK_SIZE_TYPE bsize,
+                             int64_t ref_best_rd) {
   MACROBLOCKD *const xd = &x->e_mbd;
   MB_MODE_INFO *const mbmi = &xd->mode_info_context->mbmi;
   TX_SIZE uv_txfm_size = get_uv_tx_size(mbmi);
@@ -1290,6 +1291,9 @@ static void super_block_uvrd(VP9_COMMON *const cm, MACROBLOCK *x,
   int pnrate = 0, pnskip = 1;
   int64_t pndist = 0, pnsse = 0;
 
+  if (ref_best_rd < 0)
+    goto term;
+
   if (is_inter_block(mbmi))
     vp9_subtract_sbuv(x, bsize);
 
@@ -1300,12 +1304,22 @@ static void super_block_uvrd(VP9_COMMON *const cm, MACROBLOCK *x,
 
   for (plane = 1; plane < MAX_MB_PLANE; ++plane) {
     txfm_rd_in_plane(x, &pnrate, &pndist, &pnskip, &pnsse,
-                     INT64_MAX, plane, bsize, uv_txfm_size);
+                     ref_best_rd, plane, bsize, uv_txfm_size);
+    if (pnrate == INT_MAX)
+      goto term;
     *rate += pnrate;
     *distortion += pndist;
     *sse += pnsse;
     *skippable &= pnskip;
   }
+  return;
+
+  term:
+  *rate = INT_MAX;
+  *distortion = INT64_MAX;
+  *sse = INT64_MAX;
+  *skippable = 0;
+  return;
 }
 
 static int64_t rd_pick_intra_sbuv_mode(VP9_COMP *cpi, MACROBLOCK *x,
@@ -1324,7 +1338,9 @@ static int64_t rd_pick_intra_sbuv_mode(VP9_COMP *cpi, MACROBLOCK *x,
   for (mode = DC_PRED; mode <= last_mode; mode++) {
     x->e_mbd.mode_info_context->mbmi.uv_mode = mode;
     super_block_uvrd(&cpi->common, x, &this_rate_tokenonly,
-                     &this_distortion, &s, &this_sse, bsize);
+                     &this_distortion, &s, &this_sse, bsize, best_rd);
+    if (this_rate_tokenonly == INT_MAX)
+      continue;
     this_rate = this_rate_tokenonly +
                 x->intra_uv_mode_cost[cpi->common.frame_type][mode];
     this_rd = RDCOST(x->rdmult, x->rddiv, this_rate, this_distortion);
@@ -1353,7 +1369,7 @@ static int64_t rd_sbuv_dcpred(VP9_COMP *cpi, MACROBLOCK *x,
 
   x->e_mbd.mode_info_context->mbmi.uv_mode = DC_PRED;
   super_block_uvrd(&cpi->common, x, rate_tokenonly,
-                   distortion, skippable, &this_sse, bsize);
+                   distortion, skippable, &this_sse, bsize, INT64_MAX);
   *rate = *rate_tokenonly +
           x->intra_uv_mode_cost[cpi->common.frame_type][DC_PRED];
   this_rd = RDCOST(x->rdmult, x->rddiv, *rate, *distortion);
@@ -2593,7 +2609,8 @@ static int64_t handle_inter_mode(VP9_COMP *cpi, MACROBLOCK *x,
                                  int_mv (*mode_mv)[MAX_REF_FRAMES],
                                  int mi_row, int mi_col,
                                  int_mv single_newmv[MAX_REF_FRAMES],
-                                 int64_t *psse, int64_t ref_best_rd) {
+                                 int64_t *psse,
+                                 const int64_t ref_best_rd) {
   VP9_COMMON *cm = &cpi->common;
   MACROBLOCKD *xd = &x->e_mbd;
   MB_MODE_INFO *mbmi = &xd->mode_info_context->mbmi;
@@ -2944,7 +2961,8 @@ static int64_t handle_inter_mode(VP9_COMP *cpi, MACROBLOCK *x,
 
   if (!x->skip) {
     int skippable_y, skippable_uv;
-    int64_t sseuv = INT_MAX;
+    int64_t sseuv = INT64_MAX;
+    int64_t rdcosty = INT64_MAX;
 
     // Y cost and distortion
     super_block_yrd(cpi, x, rate_y, distortion_y, &skippable_y, psse,
@@ -2963,8 +2981,20 @@ static int64_t handle_inter_mode(VP9_COMP *cpi, MACROBLOCK *x,
     *rate2 += *rate_y;
     *distortion += *distortion_y;
 
-    super_block_uvrd(cm, x, rate_uv, distortion_uv,
-                     &skippable_uv, &sseuv, bsize);
+    rdcosty = RDCOST(x->rdmult, x->rddiv, *rate2, *distortion);
+    rdcosty = MIN(rdcosty, RDCOST(x->rdmult, x->rddiv, 0, *psse));
+
+    super_block_uvrd(cm, x, rate_uv, distortion_uv, &skippable_uv, &sseuv,
+                     bsize, ref_best_rd - rdcosty);
+    if (*rate_uv == INT_MAX) {
+      *rate2 = INT_MAX;
+      *distortion = INT64_MAX;
+      for (i = 0; i < MAX_MB_PLANE; i++) {
+        xd->plane[i].dst.buf = orig_dst[i];
+        xd->plane[i].dst.stride = orig_dst_stride[i];
+      }
+      return INT64_MAX;
+    }
 
     *psse += sseuv;
     *rate2 += *rate_uv;
@@ -3473,9 +3503,9 @@ int64_t vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x,
                      (int)this_rd_thresh, seg_mvs,
                      bsi, switchable_filter_index,
                      mi_row, mi_col);
-
         if (tmp_rd == INT64_MAX)
           continue;
+
         cpi->rd_filter_cache[switchable_filter_index] = tmp_rd;
         rs = get_switchable_rate(x);
         rs_rd = RDCOST(x->rdmult, x->rddiv, rs, 0);
@@ -3568,15 +3598,17 @@ int64_t vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x,
       }
       compmode_cost = vp9_cost_bit(comp_mode_p, is_comp_pred);
 
-      if (RDCOST(x->rdmult, x->rddiv, rate2, distortion2) <
-          best_rd) {
+      tmp_best_rdu = best_rd - RDCOST(x->rdmult, x->rddiv, rate2, distortion2);
+
+      if (tmp_best_rdu > 0) {
         // If even the 'Y' rd value of split is higher than best so far
         // then dont bother looking at UV
         vp9_build_inter_predictors_sbuv(&x->e_mbd, mi_row, mi_col,
                                         BLOCK_8X8);
-
         super_block_uvrd(cm, x, &rate_uv, &distortion_uv, &uv_skippable,
-                         &uv_sse, BLOCK_8X8);
+                         &uv_sse, BLOCK_8X8, tmp_best_rdu);
+        if (rate_uv == INT_MAX)
+          continue;
         rate2 += rate_uv;
         distortion2 += distortion_uv;
         skippable = skippable && uv_skippable;