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) {