Commit 05864609 authored by Jingning Han's avatar Jingning Han

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
parent fa761029
......@@ -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;
......
......@@ -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];
}
/*
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment