Merge "Enable dynamic motion vector referencing for newmv mode" into nextgenv2
diff --git a/vp10/decoder/decodemv.c b/vp10/decoder/decodemv.c
index 34e9a17..f52fae4 100644
--- a/vp10/decoder/decodemv.c
+++ b/vp10/decoder/decodemv.c
@@ -155,7 +155,29 @@
uint8_t ref_frame_type = vp10_ref_frame_type(mbmi->ref_frame);
mbmi->ref_mv_idx = 0;
- if (xd->ref_mv_count[ref_frame_type] > 2) {
+ if (xd->ref_mv_count[ref_frame_type] > 1 && mbmi->mode == NEWMV) {
+ uint8_t drl_ctx = vp10_drl_ctx(xd->ref_mv_stack[ref_frame_type], 0);
+ vpx_prob drl_prob = cm->fc->drl_prob0[drl_ctx];
+
+ if (!vpx_read(r, drl_prob)) {
+ mbmi->ref_mv_idx = 0;
+ return;
+ }
+ mbmi->ref_mv_idx = 1;
+
+ if (xd->ref_mv_count[ref_frame_type] > 2) {
+ drl_ctx = vp10_drl_ctx(xd->ref_mv_stack[ref_frame_type], 1);
+ drl_prob = cm->fc->drl_prob0[drl_ctx];
+ if (!vpx_read(r, drl_prob)) {
+ mbmi->ref_mv_idx = 1;
+ return;
+ }
+ mbmi->ref_mv_idx = 2;
+ }
+ return;
+ }
+
+ if (xd->ref_mv_count[ref_frame_type] > 2 && mbmi->mode == NEARMV) {
uint8_t drl0_ctx = vp10_drl_ctx(xd->ref_mv_stack[ref_frame_type], 1);
vpx_prob drl0_prob = cm->fc->drl_prob0[drl0_ctx];
if (vpx_read(r, drl0_prob)) {
@@ -1246,7 +1268,7 @@
#endif // CONFIG_REF_MV && CONFIG_EXT_INTER
r, mode_ctx);
#if CONFIG_REF_MV
- if (mbmi->mode == NEARMV)
+ if (mbmi->mode == NEARMV || mbmi->mode == NEWMV)
read_drl_idx(cm, xd, mbmi, r);
#endif
}
@@ -1439,6 +1461,22 @@
mbmi->mv[0].as_int = mi->bmi[3].as_mv[0].as_int;
mbmi->mv[1].as_int = mi->bmi[3].as_mv[1].as_int;
} else {
+ int ref;
+ for (ref = 0; ref < 1 + is_compound && mbmi->mode == NEWMV; ++ref) {
+ int_mv ref_mv = nearestmv[ref];
+#if CONFIG_REF_MV
+ uint8_t ref_frame_type = vp10_ref_frame_type(mbmi->ref_frame);
+ if (xd->ref_mv_count[ref_frame_type] > 1) {
+ ref_mv = (ref == 0) ?
+ xd->ref_mv_stack[ref_frame_type][mbmi->ref_mv_idx].this_mv :
+ xd->ref_mv_stack[ref_frame_type][mbmi->ref_mv_idx].comp_mv;
+ clamp_mv_ref(&ref_mv.as_mv, xd->n8_w << 3, xd->n8_h << 3, xd);
+ lower_mv_precision(&ref_mv.as_mv, allow_hp);
+ }
+#endif
+ nearestmv[ref] = ref_mv;
+ }
+
xd->corrupted |= !assign_mv(cm, xd, mbmi->mode,
#if CONFIG_REF_MV
0,
diff --git a/vp10/encoder/bitstream.c b/vp10/encoder/bitstream.c
index d6e72e6..386a17e 100644
--- a/vp10/encoder/bitstream.c
+++ b/vp10/encoder/bitstream.c
@@ -193,7 +193,31 @@
const MB_MODE_INFO_EXT *mbmi_ext,
vpx_writer *w) {
uint8_t ref_frame_type = vp10_ref_frame_type(mbmi->ref_frame);
- if (mbmi_ext->ref_mv_count[ref_frame_type] > 2) {
+
+ assert(mbmi->ref_mv_idx < 3);
+
+ if (mbmi_ext->ref_mv_count[ref_frame_type] > 1 && mbmi->mode == NEWMV) {
+ uint8_t drl_ctx =
+ vp10_drl_ctx(mbmi_ext->ref_mv_stack[ref_frame_type], 0);
+ vpx_prob drl_prob = cm->fc->drl_prob0[drl_ctx];
+
+ vpx_write(w, mbmi->ref_mv_idx != 0, drl_prob);
+ if (mbmi->ref_mv_idx == 0)
+ return;
+
+ if (mbmi_ext->ref_mv_count[ref_frame_type] > 2) {
+ drl_ctx = vp10_drl_ctx(mbmi_ext->ref_mv_stack[ref_frame_type], 1);
+ drl_prob = cm->fc->drl_prob0[drl_ctx];
+ vpx_write(w, mbmi->ref_mv_idx != 1, drl_prob);
+ }
+ if (mbmi->ref_mv_idx == 1)
+ return;
+
+ assert(mbmi->ref_mv_idx == 2);
+ return;
+ }
+
+ if (mbmi_ext->ref_mv_count[ref_frame_type] > 2 && mbmi->mode == NEARMV) {
uint8_t drl0_ctx =
vp10_drl_ctx(mbmi_ext->ref_mv_stack[ref_frame_type], 1);
vpx_prob drl0_prob = cm->fc->drl_prob0[drl0_ctx];
@@ -1089,7 +1113,7 @@
mode_ctx);
#if CONFIG_REF_MV
- if (mode == NEARMV)
+ if (mode == NEARMV || mode == NEWMV)
write_drl_idx(cm, mbmi, mbmi_ext, w);
#endif
}
@@ -1176,13 +1200,15 @@
#else
if (mode == NEWMV) {
#endif // CONFIG_EXT_INTER
+ int_mv ref_mv;
for (ref = 0; ref < 1 + is_compound; ++ref) {
#if CONFIG_REF_MV
- int nmv_ctx =
- vp10_nmv_ctx(mbmi_ext->ref_mv_count[mbmi->ref_frame[ref]],
- mbmi_ext->ref_mv_stack[mbmi->ref_frame[ref]]);
- const nmv_context *nmvc = &cm->fc->nmvc[nmv_ctx];
+ int nmv_ctx =
+ vp10_nmv_ctx(mbmi_ext->ref_mv_count[mbmi->ref_frame[ref]],
+ mbmi_ext->ref_mv_stack[mbmi->ref_frame[ref]]);
+ const nmv_context *nmvc = &cm->fc->nmvc[nmv_ctx];
#endif
+ ref_mv = mbmi_ext->ref_mvs[mbmi->ref_frame[ref]][0];
#if CONFIG_EXT_INTER
if (mode == NEWFROMNEARMV)
vp10_encode_mv(cpi, w, &mbmi->mv[ref].as_mv,
@@ -1191,8 +1217,8 @@
else
#endif // CONFIG_EXT_INTER
vp10_encode_mv(cpi, w, &mbmi->mv[ref].as_mv,
- &mbmi_ext->ref_mvs[mbmi->ref_frame[ref]][0].as_mv, nmvc,
- allow_hp);
+ &ref_mv.as_mv, nmvc,
+ allow_hp);
}
#if CONFIG_EXT_INTER
} else if (mode == NEAREST_NEWMV || mode == NEAR_NEWMV) {
diff --git a/vp10/encoder/encodeframe.c b/vp10/encoder/encodeframe.c
index 6bb724d..2c47be9 100644
--- a/vp10/encoder/encodeframe.c
+++ b/vp10/encoder/encodeframe.c
@@ -1085,6 +1085,10 @@
const int mi_height = num_8x8_blocks_high_lookup[bsize];
int max_plane;
+#if CONFIG_REF_MV
+ int8_t rf_type;
+#endif
+
#if !CONFIG_SUPERTX
assert(mi->mbmi.sb_type == bsize);
#endif
@@ -1092,6 +1096,23 @@
*mi_addr = *mi;
*x->mbmi_ext = ctx->mbmi_ext;
+#if CONFIG_REF_MV
+ rf_type = vp10_ref_frame_type(mbmi->ref_frame);
+ if (x->mbmi_ext->ref_mv_count[rf_type] > 1 &&
+ mbmi->sb_type >= BLOCK_8X8 &&
+ mbmi->mode == NEWMV) {
+ for (i = 0; i < 1 + has_second_ref(mbmi); ++i) {
+ int_mv this_mv = (i == 0) ?
+ x->mbmi_ext->ref_mv_stack[rf_type][mbmi->ref_mv_idx].this_mv :
+ x->mbmi_ext->ref_mv_stack[rf_type][mbmi->ref_mv_idx].comp_mv;
+ clamp_mv_ref(&this_mv.as_mv, xd->n8_w << 3, xd->n8_h << 3, xd);
+ lower_mv_precision(&this_mv.as_mv, cm->allow_high_precision_mv);
+ x->mbmi_ext->ref_mvs[mbmi->ref_frame[i]][0] = this_mv;
+ mbmi->pred_mv[i] = this_mv;
+ }
+ }
+#endif
+
// If segmentation in use
if (seg->enabled) {
// For in frame complexity AQ copy the segment id from the segment map.
@@ -1231,11 +1252,32 @@
cm->cur_frame->mvs + mi_row * cm->mi_cols + mi_col;
int w, h;
+#if CONFIG_REF_MV
+ int8_t rf_type;
+#endif
+
*mi_addr = *mi;
*x->mbmi_ext = ctx->mbmi_ext;
assert(is_inter_block(mbmi));
assert(mbmi->tx_size == ctx->mic.mbmi.tx_size);
+#if CONFIG_REF_MV
+ rf_type = vp10_ref_frame_type(mbmi->ref_frame);
+ if (x->mbmi_ext->ref_mv_count[rf_type] > 1 &&
+ mbmi->sb_type >= BLOCK_8X8 &&
+ mbmi->mode == NEWMV) {
+ for (i = 0; i < 1 + has_second_ref(mbmi); ++i) {
+ int_mv this_mv = (i == 0) ?
+ x->mbmi_ext->ref_mv_stack[rf_type][mbmi->ref_mv_idx].this_mv :
+ x->mbmi_ext->ref_mv_stack[rf_type][mbmi->ref_mv_idx].comp_mv;
+ clamp_mv_ref(&this_mv.as_mv, xd->n8_w << 3, xd->n8_h << 3, xd);
+ lower_mv_precision(&this_mv.as_mv, cm->allow_high_precision_mv);
+ x->mbmi_ext->ref_mvs[mbmi->ref_frame[i]][0] = this_mv;
+ mbmi->pred_mv[i] = this_mv;
+ }
+ }
+#endif
+
// If segmentation in use
if (seg->enabled && output_enabled) {
// For in frame complexity AQ copy the segment id from the segment map.
diff --git a/vp10/encoder/rdopt.c b/vp10/encoder/rdopt.c
index a49116b..3d92591 100644
--- a/vp10/encoder/rdopt.c
+++ b/vp10/encoder/rdopt.c
@@ -7984,6 +7984,13 @@
rate2 += intra_cost_penalty;
distortion2 = distortion_y + distortion_uv;
} else {
+#if CONFIG_REF_MV
+ int_mv backup_ref_mv[2];
+
+ backup_ref_mv[0] = mbmi_ext->ref_mvs[ref_frame][0];
+ if (comp_pred)
+ backup_ref_mv[1] = mbmi_ext->ref_mvs[second_ref_frame][0];
+#endif
#if CONFIG_EXT_INTER
if (second_ref_frame == INTRA_FRAME) {
mbmi->interintra_mode = best_intra_mode;
@@ -8002,6 +8009,19 @@
#if CONFIG_REF_MV
mbmi->ref_mv_idx = 0;
ref_frame_type = vp10_ref_frame_type(mbmi->ref_frame);
+
+ if (this_mode == NEWMV &&
+ mbmi_ext->ref_mv_count[ref_frame_type] > 1) {
+ int ref;
+ for (ref = 0; ref < 1 + comp_pred; ++ref) {
+ int_mv this_mv = (ref == 0) ?
+ mbmi_ext->ref_mv_stack[ref_frame_type][0].this_mv :
+ mbmi_ext->ref_mv_stack[ref_frame_type][0].comp_mv;
+ clamp_mv_ref(&this_mv.as_mv, xd->n8_w << 3, xd->n8_h << 3, xd);
+ lower_mv_precision(&this_mv.as_mv, cm->allow_high_precision_mv);
+ mbmi_ext->ref_mvs[mbmi->ref_frame[ref]][0] = this_mv;
+ }
+ }
#endif
this_rd = handle_inter_mode(cpi, x, bsize,
&rate2, &distortion2, &skippable,
@@ -8027,20 +8047,38 @@
#if CONFIG_REF_MV
// TODO(jingning): This needs some refactoring to improve code quality
// and reduce redundant steps.
- if (mbmi->mode == NEARMV &&
- mbmi_ext->ref_mv_count[ref_frame_type] > 2) {
+ if ((mbmi->mode == NEARMV &&
+ mbmi_ext->ref_mv_count[ref_frame_type] > 2) ||
+ (mbmi->mode == NEWMV &&
+ mbmi_ext->ref_mv_count[ref_frame_type] > 1)) {
int_mv backup_mv = frame_mv[NEARMV][ref_frame];
- int_mv cur_mv = mbmi_ext->ref_mv_stack[ref_frame][2].this_mv;
MB_MODE_INFO backup_mbmi = *mbmi;
int backup_skip = x->skip;
-
int64_t tmp_ref_rd = this_rd;
int ref_idx;
- int ref_set = VPXMIN(2, mbmi_ext->ref_mv_count[ref_frame_type] - 2);
- uint8_t drl0_ctx =
- vp10_drl_ctx(mbmi_ext->ref_mv_stack[ref_frame_type], 1);
- rate2 += cpi->drl_mode_cost0[drl0_ctx][0];
+ // TODO(jingning): This should be deprecated shortly.
+ int idx_offset = (mbmi->mode == NEARMV) ? 1 : 0;
+
+ int ref_set =
+ VPXMIN(2, mbmi_ext->ref_mv_count[ref_frame_type] - 1 - idx_offset);
+
+ uint8_t drl0_ctx = 0;
+ uint8_t drl_ctx = 0;
+
+ // Dummy
+ int_mv backup_fmv[2];
+ backup_fmv[0] = frame_mv[NEWMV][ref_frame];
+ if (comp_pred)
+ backup_fmv[1] = frame_mv[NEWMV][second_ref_frame];
+
+ if (mbmi->mode == NEARMV) {
+ drl0_ctx = vp10_drl_ctx(mbmi_ext->ref_mv_stack[ref_frame_type], 1);
+ rate2 += cpi->drl_mode_cost0[drl0_ctx][0];
+ } else {
+ drl_ctx = vp10_drl_ctx(mbmi_ext->ref_mv_stack[ref_frame_type], 0);
+ rate2 += cpi->drl_mode_cost0[drl_ctx][0];
+ }
if (this_rd < INT64_MAX) {
if (RDCOST(x->rdmult, x->rddiv, rate_y + rate_uv, distortion2) <
@@ -8066,8 +8104,24 @@
int tmp_skip = 1;
int64_t tmp_dist = 0, tmp_sse = 0;
int dummy_disable_skip = 0;
+ int ref;
+ int_mv cur_mv;
- cur_mv = mbmi_ext->ref_mv_stack[ref_frame][2 + ref_idx].this_mv;
+ mbmi->ref_mv_idx = 1 + ref_idx;
+
+ for (ref = 0; ref < 1 + comp_pred; ++ref) {
+ int_mv this_mv = (ref == 0) ?
+ mbmi_ext->ref_mv_stack[ref_frame_type]
+ [mbmi->ref_mv_idx].this_mv :
+ mbmi_ext->ref_mv_stack[ref_frame_type]
+ [mbmi->ref_mv_idx].comp_mv;
+ clamp_mv_ref(&this_mv.as_mv, xd->n8_w << 3, xd->n8_h << 3, xd);
+ lower_mv_precision(&this_mv.as_mv, cm->allow_high_precision_mv);
+ mbmi_ext->ref_mvs[mbmi->ref_frame[ref]][0] = this_mv;
+ }
+
+ cur_mv = mbmi_ext->ref_mv_stack[ref_frame]
+ [mbmi->ref_mv_idx + idx_offset].this_mv;
lower_mv_precision(&cur_mv.as_mv, cm->allow_high_precision_mv);
clamp_mv2(&cur_mv.as_mv, xd);
@@ -8086,7 +8140,6 @@
#else
int_mv dummy_single_newmv[MAX_REF_FRAMES] = { { 0 } };
#endif
- mbmi->ref_mv_idx = 1 + ref_idx;
frame_mv[NEARMV][ref_frame] = cur_mv;
tmp_alt_rd = handle_inter_mode(cpi, x, bsize,
@@ -8111,12 +8164,23 @@
&tmp_sse, best_rd);
}
- tmp_rate += cpi->drl_mode_cost0[drl0_ctx][1];
+ if (this_mode == NEARMV) {
+ tmp_rate += cpi->drl_mode_cost0[drl0_ctx][1];
+ if (mbmi_ext->ref_mv_count[ref_frame_type] > 3) {
+ uint8_t drl1_ctx =
+ vp10_drl_ctx(mbmi_ext->ref_mv_stack[ref_frame_type], 2);
+ tmp_rate += cpi->drl_mode_cost1[drl1_ctx][ref_idx];
+ }
+ }
- if (mbmi_ext->ref_mv_count[ref_frame_type] > 3) {
- uint8_t drl1_ctx =
- vp10_drl_ctx(mbmi_ext->ref_mv_stack[ref_frame_type], 2);
- tmp_rate += cpi->drl_mode_cost1[drl1_ctx][ref_idx];
+ if (this_mode == NEWMV) {
+ tmp_rate += cpi->drl_mode_cost0[drl_ctx][1];
+
+ if (mbmi_ext->ref_mv_count[ref_frame_type] > 2) {
+ uint8_t this_drl_ctx =
+ vp10_drl_ctx(mbmi_ext->ref_mv_stack[ref_frame_type], 1);
+ tmp_rate += cpi->drl_mode_cost0[this_drl_ctx][ref_idx];
+ }
}
if (tmp_alt_rd < INT64_MAX) {
@@ -8161,12 +8225,18 @@
}
frame_mv[NEARMV][ref_frame] = backup_mv;
+ frame_mv[NEWMV][ref_frame] = backup_fmv[0];
+ if (comp_pred)
+ frame_mv[NEWMV][second_ref_frame] = backup_fmv[1];
#if CONFIG_VAR_TX
for (i = 0; i < MAX_MB_PLANE; ++i)
memcpy(x->blk_skip[i], x->blk_skip_drl[i],
sizeof(uint8_t) * ctx->num_4x4_blk);
#endif
}
+ mbmi_ext->ref_mvs[ref_frame][0] = backup_ref_mv[0];
+ if (comp_pred)
+ mbmi_ext->ref_mvs[second_ref_frame][0] = backup_ref_mv[1];
#endif // CONFIG_REF_MV
if (this_rd == INT64_MAX)
@@ -8475,17 +8545,21 @@
#if CONFIG_REF_MV
const uint8_t rf_type = vp10_ref_frame_type(best_mbmode.ref_frame);
if (!comp_pred_mode) {
- if (best_mbmode.ref_mv_idx > 0 && refs[1] == NONE) {
- int idx = best_mbmode.ref_mv_idx + 1;
- int_mv cur_mv = mbmi_ext->ref_mv_stack[refs[0]][idx].this_mv;
+ int i;
+ int ref_set = (mbmi_ext->ref_mv_count[rf_type] >= 2) ?
+ VPXMIN(2, mbmi_ext->ref_mv_count[rf_type] - 2) : INT_MAX;
+
+ for (i = 0; i <= ref_set && ref_set != INT_MAX; ++i) {
+ int_mv cur_mv = mbmi_ext->ref_mv_stack[rf_type][i + 1].this_mv;
lower_mv_precision(&cur_mv.as_mv, cm->allow_high_precision_mv);
- frame_mv[NEARMV][refs[0]] = cur_mv;
+ if (cur_mv.as_int == best_mbmode.mv[0].as_int) {
+ best_mbmode.mode = NEARMV;
+ best_mbmode.ref_mv_idx = i;
+ }
}
if (frame_mv[NEARESTMV][refs[0]].as_int == best_mbmode.mv[0].as_int)
best_mbmode.mode = NEARESTMV;
- else if (frame_mv[NEARMV][refs[0]].as_int == best_mbmode.mv[0].as_int)
- best_mbmode.mode = NEARMV;
else if (best_mbmode.mv[0].as_int == 0)
best_mbmode.mode = ZEROMV;
} else {
@@ -8493,21 +8567,37 @@
const int allow_hp = cm->allow_high_precision_mv;
int_mv nearestmv[2] = { frame_mv[NEARESTMV][refs[0]],
frame_mv[NEARESTMV][refs[1]] };
-
int_mv nearmv[2] = { frame_mv[NEARMV][refs[0]],
frame_mv[NEARMV][refs[1]] };
+#if CONFIG_EXT_INTER
+ if (mbmi_ext->ref_mv_count[rf_type] > 1) {
+ nearmv[0] = mbmi_ext->ref_mv_stack[rf_type][1].this_mv;
+ nearmv[1] = mbmi_ext->ref_mv_stack[rf_type][1].comp_mv;
+ }
+#else
+ int ref_set = (mbmi_ext->ref_mv_count[rf_type] >= 2) ?
+ VPXMIN(2, mbmi_ext->ref_mv_count[rf_type] - 2) : INT_MAX;
+
+ for (i = 0; i <= ref_set && ref_set != INT_MAX; ++i) {
+ nearmv[0] = mbmi_ext->ref_mv_stack[rf_type][i + 1].this_mv;
+ nearmv[1] = mbmi_ext->ref_mv_stack[rf_type][i + 1].comp_mv;
+ lower_mv_precision(&nearmv[0].as_mv, allow_hp);
+ lower_mv_precision(&nearmv[1].as_mv, allow_hp);
+
+ if (nearmv[0].as_int == best_mbmode.mv[0].as_int &&
+ nearmv[1].as_int == best_mbmode.mv[1].as_int) {
+ best_mbmode.mode = NEARMV;
+ best_mbmode.ref_mv_idx = i;
+ }
+ }
+#endif
+
if (mbmi_ext->ref_mv_count[rf_type] >= 1) {
nearestmv[0] = mbmi_ext->ref_mv_stack[rf_type][0].this_mv;
nearestmv[1] = mbmi_ext->ref_mv_stack[rf_type][0].comp_mv;
}
- if (mbmi_ext->ref_mv_count[rf_type] > 1) {
- int ref_mv_idx = best_mbmode.ref_mv_idx + 1;
- nearmv[0] = mbmi_ext->ref_mv_stack[rf_type][ref_mv_idx].this_mv;
- nearmv[1] = mbmi_ext->ref_mv_stack[rf_type][ref_mv_idx].comp_mv;
- }
-
for (i = 0; i < MAX_MV_REF_CANDIDATES; ++i) {
lower_mv_precision(&nearestmv[i].as_mv, allow_hp);
lower_mv_precision(&nearmv[i].as_mv, allow_hp);
@@ -8527,9 +8617,6 @@
best_mbmode.mode = ZERO_ZEROMV;
#else
best_mbmode.mode = NEARESTMV;
- else if (nearmv[0].as_int == best_mbmode.mv[0].as_int &&
- nearmv[1].as_int == best_mbmode.mv[1].as_int)
- best_mbmode.mode = NEARMV;
else if (best_mbmode.mv[0].as_int == 0 && best_mbmode.mv[1].as_int == 0)
best_mbmode.mode = ZEROMV;
#endif // CONFIG_EXT_INTER