From a4ce53f14d25ffea989fc83ee7f039762a142c83 Mon Sep 17 00:00:00 2001 From: Jingning Han Date: Fri, 20 Dec 2013 15:24:22 -0800 Subject: [PATCH] Adaptive motion control on ref and search range 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 | 3 ++- vp9/encoder/vp9_rdopt.c | 47 ++++++++++++++++++++++++++++++++++------- 2 files changed, 41 insertions(+), 9 deletions(-) diff --git a/vp9/encoder/vp9_block.h b/vp9/encoder/vp9_block.h index 8300c9522..4b33f7a1f 100644 --- a/vp9/encoder/vp9_block.h +++ b/vp9/encoder/vp9_block.h @@ -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]; diff --git a/vp9/encoder/vp9_rdopt.c b/vp9/encoder/vp9_rdopt.c index d457d9344..a2276e832 100644 --- a/vp9/encoder/vp9_rdopt.c +++ b/vp9/encoder/vp9_rdopt.c @@ -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,