shithub: libvpx

Download patch

ref: 3275ad701a5c37041ab90b743cc6fec6a8340f80
parent: 31c97c2bdfdbfff1188f6eaf51df2ee9d7eb1de7
author: Jingning Han <[email protected]>
date: Wed Aug 14 12:50:45 EDT 2013

Enable early termination in uv rd loop

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

--- a/vp9/encoder/vp9_rdopt.c
+++ b/vp9/encoder/vp9_rdopt.c
@@ -1282,7 +1282,8 @@
 
 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 @@
   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 @@
 
   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 @@
   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 @@
 
   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 @@
                                  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 @@
 
   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,9 +2981,21 @@
     *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;
     *distortion += *distortion_uv;
@@ -3473,9 +3503,9 @@
                      (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 @@
       }
       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;