From: Yunqing Wang Date: Tue, 21 Aug 2012 17:52:35 +0000 (-0700) Subject: Add biasing to ZEROMV for videos with static background X-Git-Tag: v1.2.0~94^2 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=24c346dffc3a8b48a6941241485d5bbe49b1a0ee;p=libvpx Add biasing to ZEROMV for videos with static background For videos with big static background(such as video conferencing clips), the mode decision was biased to ZEROMV in order to obtain a stable background. The percentage of ZEROMV on last frame was used to predict if there is static area in current frame, and checking already-encoded neighboring macroblocks' motion vectors to make sure the local area has low motion. Change-Id: I05b3241d3a56a0bda88b6681e5646c1c8baf2e57 --- diff --git a/vp8/encoder/onyx_if.c b/vp8/encoder/onyx_if.c index dc6080340..c371cdf58 100644 --- a/vp8/encoder/onyx_if.c +++ b/vp8/encoder/onyx_if.c @@ -1104,6 +1104,7 @@ void vp8_alloc_compressor_data(VP8_COMP *cpi) /* Data used for real time vc mode to see if gf needs refreshing */ cpi->inter_zz_count = 0; + cpi->zeromv_count = 0; cpi->gf_bad_count = 0; cpi->gf_update_recommended = 0; @@ -4306,6 +4307,7 @@ static void encode_frame_to_data_rate MODE_INFO *tmp = cm->mi; cpi->inter_zz_count = 0; + cpi->zeromv_count = 0; if(cm->frame_type != KEY_FRAME) { @@ -4315,6 +4317,8 @@ static void encode_frame_to_data_rate { if(tmp->mbmi.mode == ZEROMV && tmp->mbmi.ref_frame == LAST_FRAME) cpi->inter_zz_count++; + if(tmp->mbmi.mode == ZEROMV) + cpi->zeromv_count++; tmp++; } tmp++; @@ -5116,6 +5120,8 @@ int vp8_get_compressed_data(VP8_COMP *cpi, unsigned int *frame_flags, unsigned l vpx_usec_timer_start(&ticktimer); } + cpi->lf_zeromv_pct = (cpi->zeromv_count * 100)/cm->MBs; + #if CONFIG_REALTIME_ONLY & CONFIG_ONTHEFLY_BITPACKING { int i; diff --git a/vp8/encoder/onyx_int.h b/vp8/encoder/onyx_int.h index caccc60ae..3f1fad60b 100644 --- a/vp8/encoder/onyx_int.h +++ b/vp8/encoder/onyx_int.h @@ -515,6 +515,9 @@ typedef struct VP8_COMP * would be good to update the gf */ int inter_zz_count; + /* Count ZEROMV on all reference frames. */ + int zeromv_count; + int lf_zeromv_pct; int gf_bad_count; int gf_update_recommended; int skip_true_count; diff --git a/vp8/encoder/pickinter.c b/vp8/encoder/pickinter.c index b67f04b85..3cad8bfd9 100644 --- a/vp8/encoder/pickinter.c +++ b/vp8/encoder/pickinter.c @@ -480,7 +480,8 @@ static void check_for_encode_breakout(unsigned int sse, MACROBLOCK* x) } } -static int evaluate_inter_mode(unsigned int* sse, int rate2, int* distortion2, VP8_COMP *cpi, MACROBLOCK *x) +static int evaluate_inter_mode(unsigned int* sse, int rate2, int* distortion2, + VP8_COMP *cpi, MACROBLOCK *x, int rd_adj) { MB_PREDICTION_MODE this_mode = x->e_mbd.mode_info_context->mbmi.mode; int_mv mv = x->e_mbd.mode_info_context->mbmi.mv; @@ -503,10 +504,63 @@ static int evaluate_inter_mode(unsigned int* sse, int rate2, int* distortion2, V this_rd = RDCOST(x->rdmult, x->rddiv, rate2, *distortion2); + /* Adjust rd to bias to ZEROMV */ + if(this_mode == ZEROMV) + { + /* Bias to ZEROMV on LAST_FRAME reference when it is available. */ + if ((cpi->ref_frame_flags & VP8_LAST_FRAME & + cpi->common.refresh_last_frame) + && x->e_mbd.mode_info_context->mbmi.ref_frame != LAST_FRAME) + rd_adj = 100; + + this_rd = this_rd * rd_adj/100; + } + check_for_encode_breakout(*sse, x); return this_rd; } +static void calculate_zeromv_rd_adjustment(VP8_COMP *cpi, MACROBLOCK *x, + int *rd_adjustment) +{ + MODE_INFO *mic = x->e_mbd.mode_info_context; + int_mv mv_l, mv_a, mv_al; + int local_motion_check = 0; + + if (cpi->lf_zeromv_pct > 40) + { + /* left mb */ + mic -= 1; + mv_l = mic->mbmi.mv; + + if (mic->mbmi.ref_frame != INTRA_FRAME) + if( abs(mv_l.as_mv.row) < 8 && abs(mv_l.as_mv.col) < 8) + local_motion_check++; + + /* above-left mb */ + mic -= x->e_mbd.mode_info_stride; + mv_al = mic->mbmi.mv; + + if (mic->mbmi.ref_frame != INTRA_FRAME) + if( abs(mv_al.as_mv.row) < 8 && abs(mv_al.as_mv.col) < 8) + local_motion_check++; + + /* above mb */ + mic += 1; + mv_a = mic->mbmi.mv; + + if (mic->mbmi.ref_frame != INTRA_FRAME) + if( abs(mv_a.as_mv.row) < 8 && abs(mv_a.as_mv.col) < 8) + local_motion_check++; + + if (((!x->e_mbd.mb_to_top_edge || !x->e_mbd.mb_to_left_edge) + && local_motion_check >0) || local_motion_check >2 ) + *rd_adjustment = 80; + else if (local_motion_check > 0) + *rd_adjustment = 90; + } +} + void vp8_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int recon_uvoffset, int *returnrate, int *returndistortion, int *returnintra, int mb_row, @@ -525,6 +579,7 @@ void vp8_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int num00; int mdcounts[4]; int best_rd = INT_MAX; + int rd_adjustment = 100; int best_intra_rd = INT_MAX; int mode_index; int rate; @@ -594,6 +649,11 @@ void vp8_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, x->e_mbd.mode_info_context->mbmi.ref_frame = INTRA_FRAME; + /* If the frame has big static background and current MB is in low + * motion area, its mode decision is biased to ZEROMV mode. + */ + calculate_zeromv_rd_adjustment(cpi, x, &rd_adjustment); + /* if we encode a new mv this is important * find the best new motion vector */ @@ -981,7 +1041,8 @@ void vp8_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, rate2 += vp8_cost_mv_ref(this_mode, mdcounts); x->e_mbd.mode_info_context->mbmi.mv.as_int = mode_mv[this_mode].as_int; - this_rd = evaluate_inter_mode(&sse, rate2, &distortion2, cpi, x); + this_rd = evaluate_inter_mode(&sse, rate2, &distortion2, cpi, x, + rd_adjustment); break; default: @@ -1119,7 +1180,8 @@ void vp8_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, x->e_mbd.mode_info_context->mbmi.mode = ZEROMV; x->e_mbd.mode_info_context->mbmi.uv_mode = DC_PRED; x->e_mbd.mode_info_context->mbmi.mv.as_int = 0; - this_rd = evaluate_inter_mode(&sse, rate2, &distortion2, cpi, x); + this_rd = evaluate_inter_mode(&sse, rate2, &distortion2, cpi, x, + rd_adjustment); if (this_rd < best_rd) {