From 0586460938ed3ab04fc8b09764f981e29061fa0c Mon Sep 17 00:00:00 2001 From: Jingning Han Date: Tue, 22 Mar 2016 16:38:27 -0700 Subject: [PATCH] Rework the predicted motion vector for sub8x8 block This commit makes the sub8x8 block to use its nearest neighbor's motion vector as predicted motion vector for NEWMV mode. It improves the coding performance by 0.12%. Change-Id: I99e56715b327573ce7e8a26e3515a4984dadfd98 --- vp10/decoder/decodemv.c | 13 ++-- vp10/encoder/rdopt.c | 136 +++++++++++++++++++++++++++++++++++----- 2 files changed, 130 insertions(+), 19 deletions(-) diff --git a/vp10/decoder/decodemv.c b/vp10/decoder/decodemv.c index a76d5d869..8035e063d 100644 --- a/vp10/decoder/decodemv.c +++ b/vp10/decoder/decodemv.c @@ -1390,7 +1390,7 @@ static void read_inter_block_mode_info(VP10Decoder *const pbi, if (b_mode != ZEROMV && b_mode != ZERO_ZEROMV) { #else - if (b_mode == NEARESTMV || b_mode == NEARMV) { + if (b_mode != ZEROMV) { #endif // CONFIG_EXT_INTER #if CONFIG_REF_MV CANDIDATE_MV ref_mv_stack[2][MAX_REF_MV_STACK_SIZE]; @@ -1411,8 +1411,8 @@ static void read_inter_block_mode_info(VP10Decoder *const pbi, #if CONFIG_EXT_INTER mv_ref_list, #endif // CONFIG_EXT_INTER - &nearest_sub8x8[ref], - &near_sub8x8[ref]); + &nearest_sub8x8[ref], + &near_sub8x8[ref]); #if CONFIG_EXT_INTER if (have_newmv_in_inter_mode(b_mode)) { mv_ref_list[0].as_int = nearest_sub8x8[ref].as_int; @@ -1424,8 +1424,13 @@ static void read_inter_block_mode_info(VP10Decoder *const pbi, #endif // CONFIG_EXT_INTER } - for (ref = 0; ref < 2; ++ref) { + for (ref = 0; ref < 1 + is_compound && b_mode != ZEROMV; ++ref) { +#if CONFIG_REF_MV + ref_mv_s8[ref] = nearest_sub8x8[ref]; + lower_mv_precision(&ref_mv_s8[ref].as_mv, allow_hp); +#else ref_mv_s8[ref] = nearestmv[ref]; +#endif } #if CONFIG_EXT_INTER (void)ref_mv_s8; diff --git a/vp10/encoder/rdopt.c b/vp10/encoder/rdopt.c index 3939e698c..b73e05db0 100644 --- a/vp10/encoder/rdopt.c +++ b/vp10/encoder/rdopt.c @@ -4772,8 +4772,10 @@ static int64_t rd_pick_best_sub8x8_mode(VP10_COMP *cpi, MACROBLOCK *x, #endif // CONFIG_EXT_INTER BEST_SEG_INFO *bsi_buf, int filter_idx, int mi_row, int mi_col) { - int i; BEST_SEG_INFO *bsi = bsi_buf + filter_idx; +#if CONFIG_REF_MV + int_mv tmp_ref_mv[2]; +#endif MACROBLOCKD *xd = &x->e_mbd; MODE_INFO *mi = xd->mi[0]; MB_MODE_INFO *mbmi = &mi->mbmi; @@ -4805,8 +4807,20 @@ static int64_t rd_pick_best_sub8x8_mode(VP10_COMP *cpi, MACROBLOCK *x, bsi->mvp.as_int = best_ref_mv->as_int; bsi->mvthresh = mvthresh; - for (i = 0; i < 4; i++) - bsi->modes[i] = ZEROMV; + for (idx = 0; idx < 4; ++idx) + bsi->modes[idx] = ZEROMV; + +#if CONFIG_REFMV + for (idx = 0; idx < 4; ++idx) { + for (k = NEARESTMV; k <= NEWMV; ++k) { + bsi->rdstat[idx][INTER_OFFSET(k)].pred_mv[0].as_int = INVALID_MV; + bsi->rdstat[idx][INTER_OFFSET(k)].pred_mv[1].as_int = INVALID_MV; + + bsi->rdstat[idx][INTER_OFFSET(k)].mvs[0].as_int = INVALID_MV; + bsi->rdstat[idx][INTER_OFFSET(k)].mvs[1].as_int = INVALID_MV; + } + } +#endif memcpy(t_above, pd->above_context, sizeof(t_above)); memcpy(t_left, pd->left_context, sizeof(t_left)); @@ -4856,6 +4870,13 @@ static int64_t rd_pick_best_sub8x8_mode(VP10_COMP *cpi, MACROBLOCK *x, &frame_mv[NEARESTMV][frame], &frame_mv[NEARMV][frame]); +#if CONFIG_REF_MV + tmp_ref_mv[ref] = frame_mv[NEARESTMV][mbmi->ref_frame[ref]]; + lower_mv_precision(&tmp_ref_mv[ref].as_mv, cm->allow_high_precision_mv); + bsi->ref_mv[ref] = &tmp_ref_mv[ref]; + mbmi_ext->ref_mvs[frame][0] = tmp_ref_mv[ref]; +#endif + #if CONFIG_EXT_INTER mv_ref_list[0].as_int = frame_mv[NEARESTMV][frame].as_int; mv_ref_list[1].as_int = frame_mv[NEARMV][frame].as_int; @@ -4900,6 +4921,7 @@ static int64_t rd_pick_best_sub8x8_mode(VP10_COMP *cpi, MACROBLOCK *x, #endif // CONFIG_EXT_INTER const struct buf_2d orig_src = x->plane[0].src; struct buf_2d orig_pre[2]; + int run_rd_check = 0; mode_idx = INTER_OFFSET(this_mode); #if CONFIG_EXT_INTER @@ -4912,6 +4934,55 @@ static int64_t rd_pick_best_sub8x8_mode(VP10_COMP *cpi, MACROBLOCK *x, if (!(inter_mode_mask & (1 << this_mode))) continue; +#if CONFIG_REF_MV + run_rd_check = 2; +#if !CONFIG_EXT_INTER + if (filter_idx > 0) { + BEST_SEG_INFO* ref_bsi = bsi_buf; + if (seg_mvs[i][mbmi->ref_frame[0]].as_int == + ref_bsi->rdstat[i][mode_idx].mvs[0].as_int && + ref_bsi->rdstat[i][mode_idx].mvs[0].as_int != INVALID_MV) + if (bsi->ref_mv[0]->as_int == + ref_bsi->rdstat[i][mode_idx].pred_mv[0].as_int) + --run_rd_check; + + if (!has_second_rf) { + --run_rd_check; + } else { + if (seg_mvs[i][mbmi->ref_frame[1]].as_int == + ref_bsi->rdstat[i][mode_idx].mvs[1].as_int && + ref_bsi->rdstat[i][mode_idx].mvs[1].as_int != INVALID_MV) + if (bsi->ref_mv[1]->as_int == + ref_bsi->rdstat[i][mode_idx].pred_mv[1].as_int) + --run_rd_check; + } + + if (run_rd_check != 0 && filter_idx > 1) { + ref_bsi = bsi_buf + 1; + run_rd_check = 2; + + if (seg_mvs[i][mbmi->ref_frame[0]].as_int == + ref_bsi->rdstat[i][mode_idx].mvs[0].as_int && + ref_bsi->rdstat[i][mode_idx].mvs[0].as_int != INVALID_MV) + if (bsi->ref_mv[0]->as_int == + ref_bsi->rdstat[i][mode_idx].pred_mv[0].as_int) + --run_rd_check; + + if (!has_second_rf) { + --run_rd_check; + } else { + if (seg_mvs[i][mbmi->ref_frame[1]].as_int == + ref_bsi->rdstat[i][mode_idx].mvs[1].as_int && + ref_bsi->rdstat[i][mode_idx].mvs[1].as_int != INVALID_MV) + if (bsi->ref_mv[1]->as_int == + ref_bsi->rdstat[i][mode_idx].pred_mv[1].as_int) + --run_rd_check; + } + } + } +#endif // CONFIG_EXT_INTER +#endif // CONFIG_REF_MV + if (!check_best_zero_mv(cpi, mbmi_ext->mode_context, #if CONFIG_REF_MV && CONFIG_EXT_INTER mbmi_ext->compound_mode_context, @@ -4933,7 +5004,8 @@ static int64_t rd_pick_best_sub8x8_mode(VP10_COMP *cpi, MACROBLOCK *x, seg_mvs[i][mv_idx][mbmi->ref_frame[0]].as_int == INVALID_MV #else this_mode == NEWMV && - seg_mvs[i][mbmi->ref_frame[0]].as_int == INVALID_MV + (seg_mvs[i][mbmi->ref_frame[0]].as_int == INVALID_MV || + run_rd_check) #endif // CONFIG_EXT_INTER ) { #if CONFIG_EXT_INTER @@ -4958,11 +5030,13 @@ static int64_t rd_pick_best_sub8x8_mode(VP10_COMP *cpi, MACROBLOCK *x, bsi->mvp.as_int = bsi->ref_mv[0]->as_int; #else // use previous block's result as next block's MV predictor. +#if !CONFIG_REF_MV if (i > 0) { bsi->mvp.as_int = mi->bmi[i - 1].as_mv[0].as_int; if (i == 2) bsi->mvp.as_int = mi->bmi[i - 2].as_mv[0].as_int; } +#endif #endif // CONFIG_EXT_INTER } if (i == 0) @@ -4981,8 +5055,13 @@ static int64_t rd_pick_best_sub8x8_mode(VP10_COMP *cpi, MACROBLOCK *x, step_param = cpi->mv_step_param; } +#if CONFIG_REF_MV + mvp_full.row = best_ref_mv->as_mv.row >> 3; + mvp_full.col = best_ref_mv->as_mv.col >> 3; +#else mvp_full.row = bsi->mvp.as_mv.row >> 3; mvp_full.col = bsi->mvp.as_mv.col >> 3; +#endif if (cpi->sf.adaptive_motion_search) { mvp_full.row = x->pred_mv[mbmi->ref_frame[0]].row >> 3; @@ -5090,7 +5169,7 @@ static int64_t rd_pick_best_sub8x8_mode(VP10_COMP *cpi, MACROBLOCK *x, #else this_mode == NEWMV && #endif // CONFIG_EXT_INTER - mbmi->interp_filter == EIGHTTAP_REGULAR) { + (mbmi->interp_filter == EIGHTTAP_REGULAR || run_rd_check)) { // adjust src pointers mi_buf_shift(x, i); if (cpi->sf.comp_inter_joint_search_thresh <= bsize) { @@ -5208,8 +5287,34 @@ static int64_t rd_pick_best_sub8x8_mode(VP10_COMP *cpi, MACROBLOCK *x, if (!subpelmv && have_ref && ref_bsi->rdstat[i][mode_idx].brdcost < INT64_MAX) { +#if CONFIG_REF_MV + bsi->rdstat[i][mode_idx].pred_mv[0].as_int = + bsi->ref_mv[0]->as_int; + + if (has_second_rf) + bsi->rdstat[i][mode_idx].pred_mv[1].as_int = + bsi->ref_mv[1]->as_int; + + bsi->rdstat[i][mode_idx].byrate = + ref_bsi->rdstat[i][mode_idx].byrate; + bsi->rdstat[i][mode_idx].bdist = + ref_bsi->rdstat[i][mode_idx].bdist; + bsi->rdstat[i][mode_idx].bsse = + ref_bsi->rdstat[i][mode_idx].bsse; + bsi->rdstat[i][mode_idx].brate += + ref_bsi->rdstat[i][mode_idx].byrate; + bsi->rdstat[i][mode_idx].eobs = + ref_bsi->rdstat[i][mode_idx].eobs; + memcpy(bsi->rdstat[i][mode_idx].ta, + ref_bsi->rdstat[i][mode_idx].ta, + sizeof(bsi->rdstat[i][mode_idx].ta)); + memcpy(bsi->rdstat[i][mode_idx].tl, + ref_bsi->rdstat[i][mode_idx].tl, + sizeof(bsi->rdstat[i][mode_idx].tl)); +#else memcpy(&bsi->rdstat[i][mode_idx], &ref_bsi->rdstat[i][mode_idx], sizeof(SEG_RDSTAT)); +#endif if (num_4x4_blocks_wide > 1) bsi->rdstat[i + 1][mode_idx].eobs = ref_bsi->rdstat[i + 1][mode_idx].eobs; @@ -5320,23 +5425,24 @@ static int64_t rd_pick_best_sub8x8_mode(VP10_COMP *cpi, MACROBLOCK *x, if (bsi->segment_rd > best_rd) return INT64_MAX; /* set it to the best */ - for (i = 0; i < 4; i++) { - mode_idx = INTER_OFFSET(bsi->modes[i]); - mi->bmi[i].as_mv[0].as_int = bsi->rdstat[i][mode_idx].mvs[0].as_int; + for (idx = 0; idx < 4; idx++) { + mode_idx = INTER_OFFSET(bsi->modes[idx]); + mi->bmi[idx].as_mv[0].as_int = bsi->rdstat[idx][mode_idx].mvs[0].as_int; if (has_second_ref(mbmi)) - mi->bmi[i].as_mv[1].as_int = bsi->rdstat[i][mode_idx].mvs[1].as_int; + mi->bmi[idx].as_mv[1].as_int = bsi->rdstat[idx][mode_idx].mvs[1].as_int; #if CONFIG_REF_MV - mi->bmi[i].pred_mv_s8[0] = bsi->rdstat[i][mode_idx].pred_mv[0]; + mi->bmi[idx].pred_mv_s8[0] = bsi->rdstat[idx][mode_idx].pred_mv[0]; if (has_second_ref(mbmi)) - mi->bmi[i].pred_mv_s8[1] = bsi->rdstat[i][mode_idx].pred_mv[1]; + mi->bmi[idx].pred_mv_s8[1] = bsi->rdstat[idx][mode_idx].pred_mv[1]; #endif #if CONFIG_EXT_INTER - mi->bmi[i].ref_mv[0].as_int = bsi->rdstat[i][mode_idx].ref_mv[0].as_int; + mi->bmi[idx].ref_mv[0].as_int = bsi->rdstat[idx][mode_idx].ref_mv[0].as_int; if (has_second_rf) - mi->bmi[i].ref_mv[1].as_int = bsi->rdstat[i][mode_idx].ref_mv[1].as_int; + mi->bmi[idx].ref_mv[1].as_int = + bsi->rdstat[idx][mode_idx].ref_mv[1].as_int; #endif // CONFIG_EXT_INTER - x->plane[0].eobs[i] = bsi->rdstat[i][mode_idx].eobs; - mi->bmi[i].as_mode = bsi->modes[i]; + x->plane[0].eobs[idx] = bsi->rdstat[idx][mode_idx].eobs; + mi->bmi[idx].as_mode = bsi->modes[idx]; } /* -- 2.40.0