]> granicus.if.org Git - libvpx/commitdiff
Adaptive motion control on ref and search range
authorJingning Han <jingning@google.com>
Fri, 20 Dec 2013 23:24:22 +0000 (15:24 -0800)
committerJingning Han <jingning@google.com>
Fri, 27 Dec 2013 20:43:06 +0000 (12:43 -0800)
This commit takes a preliminary attempt to refine the motion search
control. It detects the SAD associated with mv predictor per reference
frame, and based on which to determine whether the encoder wants to
reduce the motion search range (if the predicted mv provides fairly
small SAD), or to skip the current reference frame (if there exists
another ref frame that gives much smaller SAD cost).

This feature is turned on in the settings of speed 1 and above.

In speed 1, compression performance changed
derf  -0.018%
yt    -0.043%
hd    -0.045%
stdhd -0.281%

speed-up
pedestrian_area_1080p at 4000 kbps 100 frames
199651ms -> 188846ms (5.5% speed-up)
blue_sky_1080p at 6000 kbps
443531ms -> 415239ms (6.3% speed-up)

In speed 2, compression performance changed
derf  -0.026%
yt    -0.090%
hd    -0.055%
stdhd -0.210%

speed-up
pedstrian 113949ms -> 108855ms (4.5% speed-up)
blue_sky  271057ms -> 257322ms (5% speed-up)

Change-Id: I1b74ea28278c94fea329d971d706d573983d810d

vp9/encoder/vp9_block.h
vp9/encoder/vp9_rdopt.c

index 8300c952219720a2c421f806012891ae77bd2436..4b33f7a1f1e044e823faa0ec33bb552dcad4e78c 100644 (file)
@@ -118,7 +118,8 @@ struct macroblock {
   int mv_best_ref_index[MAX_REF_FRAMES];
   unsigned int max_mv_context[MAX_REF_FRAMES];
   unsigned int source_variance;
-  unsigned int pred_sse;
+  unsigned int pred_sse[MAX_REF_FRAMES];
+  int pred_mv_sad[MAX_REF_FRAMES];
 
   int nmvjointcost[MV_JOINTS];
   int nmvcosts[2][MV_VALS];
index d457d9344aaeef94f12048fdf51c4a9ae3e9f914..a2276e832d5d541e171798223f46c8a23cb8accd 100644 (file)
@@ -417,6 +417,8 @@ static void model_rd_for_sb(VP9_COMP *cpi, BLOCK_SIZE bsize,
   // Hence quantizer step is also 8 times. To get effective quantizer
   // we need to divide by 8 before sending to modeling function.
   int i, rate_sum = 0, dist_sum = 0;
+  int ref = xd->mi_8x8[0]->mbmi.ref_frame[0];
+  unsigned int sse;
 
   for (i = 0; i < MAX_MB_PLANE; ++i) {
     struct macroblock_plane *const p = &x->plane[i];
@@ -425,9 +427,11 @@ static void model_rd_for_sb(VP9_COMP *cpi, BLOCK_SIZE bsize,
     int rate;
     int64_t dist;
     (void) cpi->fn_ptr[bs].vf(p->src.buf, p->src.stride,
-                              pd->dst.buf, pd->dst.stride, &x->pred_sse);
+                              pd->dst.buf, pd->dst.stride, &sse);
+    if (i == 0)
+      x->pred_sse[ref] = sse;
     // sse works better than var, since there is no dc prediction used
-    model_rd_from_var_lapndz(x->pred_sse, 1 << num_pels_log2_lookup[bs],
+    model_rd_from_var_lapndz(sse, 1 << num_pels_log2_lookup[bs],
                              pd->dequant[1] >> 3, &rate, &dist);
 
     rate_sum += rate;
@@ -1839,7 +1843,8 @@ static void rd_check_segment_txsize(VP9_COMP *cpi, MACROBLOCK *x,
                                          x->errorperbit, v_fn_ptr,
                                          0, cpi->sf.subpel_iters_per_step,
                                          x->nmvjointcost, x->mvcost,
-                                         &distortion, &x->pred_sse);
+                                         &distortion,
+                                         &x->pred_sse[mbmi->ref_frame[0]]);
 
             // save motion search result for use in compound prediction
             seg_mvs[i][mbmi->ref_frame[0]].as_int = mode_mv[NEWMV].as_int;
@@ -2134,6 +2139,7 @@ static void mv_pred(VP9_COMP *cpi, MACROBLOCK *x,
   // Note the index of the mv that worked best in the reference list.
   x->mv_best_ref_index[ref_frame] = best_index;
   x->max_mv_context[ref_frame] = max_mv;
+  x->pred_mv_sad[ref_frame] = best_sad;
 }
 
 static void estimate_ref_frame_costs(VP9_COMP *cpi, int segment_id,
@@ -2381,6 +2387,30 @@ static void single_motion_search(VP9_COMP *cpi, MACROBLOCK *x,
     step_param = MAX(step_param, boffset);
   }
 
+  if (cpi->sf.adaptive_motion_search) {
+    int bwl = b_width_log2_lookup[bsize];
+    int bhl = b_height_log2_lookup[bsize];
+    int i;
+    int tlevel = x->pred_mv_sad[ref] >> (bwl + bhl + 4);
+
+    if (tlevel < 5)
+      step_param += 2;
+
+    for (i = LAST_FRAME; i <= ALTREF_FRAME && cpi->common.show_frame; ++i) {
+      if ((x->pred_mv_sad[ref] >> 3) > x->pred_mv_sad[i]) {
+        x->pred_mv[ref].as_int = 0;
+        tmp_mv->as_int = INVALID_MV;
+
+        if (scaled_ref_frame) {
+          int i;
+          for (i = 0; i < MAX_MB_PLANE; i++)
+            xd->plane[i].pre[0] = backup_yv12[i];
+        }
+        return;
+      }
+    }
+  }
+
   mvp_full.as_int = x->mv_best_ref_index[ref] < MAX_MV_REF_CANDIDATES ?
       mbmi->ref_mvs[ref][x->mv_best_ref_index[ref]].as_int :
       x->pred_mv[ref].as_int;
@@ -2429,7 +2459,7 @@ static void single_motion_search(VP9_COMP *cpi, MACROBLOCK *x,
                                  &cpi->fn_ptr[bsize],
                                  0, cpi->sf.subpel_iters_per_step,
                                  x->nmvjointcost, x->mvcost,
-                                 &dis, &x->pred_sse);
+                                 &dis, &x->pred_sse[ref]);
   }
   *rate_mv = vp9_mv_bit_cost(&tmp_mv->as_mv, &ref_mv.as_mv,
                              x->nmvjointcost, x->mvcost, MV_COST_WEIGHT);
@@ -2491,7 +2521,6 @@ static void joint_motion_search(VP9_COMP *cpi, MACROBLOCK *x,
   for (ite = 0; ite < 4; ite++) {
     struct buf_2d ref_yv12[2];
     int bestsme = INT_MAX;
-    unsigned int bestsse = INT_MAX;
     int sadpb = x->sadperbit16;
     int_mv tmp_mv;
     int search_range = 3;
@@ -2542,6 +2571,7 @@ static void joint_motion_search(VP9_COMP *cpi, MACROBLOCK *x,
 
     if (bestsme < INT_MAX) {
       int dis; /* TODO: use dis in distortion calculation later. */
+      unsigned int sse;
       bestsme = cpi->find_fractional_mv_step_comp(
           x, &tmp_mv.as_mv,
           &ref_mv[id].as_mv,
@@ -2550,7 +2580,7 @@ static void joint_motion_search(VP9_COMP *cpi, MACROBLOCK *x,
           &cpi->fn_ptr[bsize],
           0, cpi->sf.subpel_iters_per_step,
           x->nmvjointcost, x->mvcost,
-          &dis, &bestsse, second_pred,
+          &dis, &sse, second_pred,
           pw, ph);
     }
 
@@ -2560,7 +2590,6 @@ static void joint_motion_search(VP9_COMP *cpi, MACROBLOCK *x,
     if (bestsme < last_besterr[id]) {
       frame_mv[refs[id]].as_int = tmp_mv.as_int;
       last_besterr[id] = bestsme;
-      x->pred_sse = bestsse;
     } else {
       break;
     }
@@ -2852,7 +2881,6 @@ static int64_t handle_inter_mode(VP9_COMP *cpi, MACROBLOCK *x,
     vp9_build_inter_predictors_sb(xd, mi_row, mi_col, bsize);
   }
 
-
   if (cpi->sf.use_rd_breakout && ref_best_rd < INT64_MAX) {
     int tmp_rate;
     int64_t tmp_dist;
@@ -3147,6 +3175,8 @@ int64_t vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x,
     best_filter_rd[i] = INT64_MAX;
   for (i = 0; i < TX_SIZES; i++)
     rate_uv_intra[i] = INT_MAX;
+  for (i = 0; i < MAX_REF_FRAMES; ++i)
+    x->pred_sse[i] = INT_MAX;
 
   *returnrate = INT_MAX;
 
@@ -3184,6 +3214,7 @@ int64_t vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x,
   }
 
   for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ref_frame++) {
+    x->pred_mv_sad[ref_frame] = INT_MAX;
     if (cpi->ref_frame_flags & flag_list[ref_frame]) {
       setup_buffer_inter(cpi, x, tile, idx_list[ref_frame], ref_frame,
                          block_size, mi_row, mi_col,