intrabc: Add a DV prediction scheme derived from ref_mv
wikipedia_420.y4m
PSNR: -1.5035 PSNR-HVS: -1.2607 SSIM: -1.1581
Change-Id: I6e6c4bd9671427b99299df39ff0f42af7daf8ce7
diff --git a/av1/common/mvref_common.c b/av1/common/mvref_common.c
index db36b64..d558111 100644
--- a/av1/common/mvref_common.c
+++ b/av1/common/mvref_common.c
@@ -586,6 +586,9 @@
? cm->prev_frame->mvs + mi_row * cm->mi_cols + mi_col
: NULL;
#endif
+#if CONFIG_INTRABC
+ assert(IMPLIES(ref_frame == INTRA_FRAME, cm->use_prev_frame_mvs == 0));
+#endif
const TileInfo *const tile = &xd->tile;
const BLOCK_SIZE bsize = mi->mbmi.sb_type;
const int bw = block_size_wide[AOMMAX(bsize, BLOCK_8X8)];
diff --git a/av1/common/mvref_common.h b/av1/common/mvref_common.h
index b4747c6..7ed836e 100644
--- a/av1/common/mvref_common.h
+++ b/av1/common/mvref_common.h
@@ -267,8 +267,12 @@
} else {
rf[0] = ref_frame_type;
rf[1] = NONE_FRAME;
- assert(ref_frame_type > INTRA_FRAME &&
- ref_frame_type < TOTAL_REFS_PER_FRAME);
+#if CONFIG_INTRABC
+ assert(ref_frame_type > NONE_FRAME);
+#else
+ assert(ref_frame_type > INTRA_FRAME);
+#endif
+ assert(ref_frame_type < TOTAL_REFS_PER_FRAME);
}
}
diff --git a/av1/decoder/decodemv.c b/av1/decoder/decodemv.c
index af226fa..d155435 100644
--- a/av1/decoder/decodemv.c
+++ b/av1/decoder/decodemv.c
@@ -1045,7 +1045,6 @@
read_mv(r, &mv->as_mv, &ref_mv->as_mv, &ec_ctx->ndvc, dv_counts, 0);
int valid = is_mv_valid(&mv->as_mv) &&
is_dv_valid(mv->as_mv, &xd->tile, mi_row, mi_col, bsize);
- // TODO(aconverse@google.com): additional validation
return valid;
}
#endif // CONFIG_INTRABC
@@ -1103,14 +1102,29 @@
if (bsize >= BLOCK_8X8 && cm->allow_screen_content_tools) {
mbmi->use_intrabc = aom_read(r, INTRABC_PROB, ACCT_STR);
if (mbmi->use_intrabc) {
- int_mv dv_ref;
mbmi->mode = mbmi->uv_mode = DC_PRED;
#if CONFIG_DUAL_FILTER
for (int idx = 0; idx < 4; ++idx) mbmi->interp_filter[idx] = BILINEAR;
#else
mbmi->interp_filter = BILINEAR;
#endif
- av1_find_ref_dv(&dv_ref, mi_row, mi_col);
+
+ int16_t inter_mode_ctx[MODE_CTX_REF_FRAMES];
+ int_mv ref_mvs[MAX_MV_REF_CANDIDATES] = {};
+
+ av1_find_mv_refs(cm, xd, mi, INTRA_FRAME, &xd->ref_mv_count[INTRA_FRAME],
+ xd->ref_mv_stack[INTRA_FRAME],
+#if CONFIG_EXT_INTER
+ compound_inter_mode_ctx,
+#endif // CONFIG_EXT_INTER
+ ref_mvs, mi_row, mi_col, NULL, NULL, inter_mode_ctx);
+
+ int_mv nearestmv, nearmv;
+ av1_find_best_ref_mvs(0, ref_mvs, &nearestmv, &nearmv);
+
+ int_mv dv_ref = nearestmv.as_int == 0 ? nearmv : nearestmv;
+ if (dv_ref.as_int == 0) av1_find_ref_dv(&dv_ref, mi_row, mi_col);
+
xd->corrupted |=
!assign_dv(cm, xd, &mbmi->mv[0], &dv_ref, mi_row, mi_col, bsize, r);
#if CONFIG_EXT_TX && !CONFIG_TXK_SEL
diff --git a/av1/encoder/bitstream.c b/av1/encoder/bitstream.c
index 52d95d7..4be8557 100644
--- a/av1/encoder/bitstream.c
+++ b/av1/encoder/bitstream.c
@@ -2144,6 +2144,9 @@
#else
const MACROBLOCKD *xd,
#endif // CONFIG_DELTA_Q
+#if CONFIG_INTRABC
+ const MB_MODE_INFO_EXT *mbmi_ext,
+#endif // CONFIG_INTRABC
const int mi_row, const int mi_col,
aom_writer *w) {
const struct segmentation *const seg = &cm->seg;
@@ -2215,8 +2218,7 @@
if (use_intrabc) {
assert(mbmi->mode == DC_PRED);
assert(mbmi->uv_mode == DC_PRED);
- int_mv dv_ref;
- av1_find_ref_dv(&dv_ref, mi_row, mi_col);
+ int_mv dv_ref = mbmi_ext->ref_mvs[INTRA_FRAME][0];
av1_encode_dv(w, &mbmi->mv[0].as_mv, &dv_ref.as_mv, &ec_ctx->ndvc);
#if CONFIG_EXT_TX && !CONFIG_TXK_SEL
av1_write_tx_type(cm, xd,
@@ -2365,7 +2367,11 @@
cm->mi_rows, cm->mi_cols);
if (frame_is_intra_only(cm)) {
- write_mb_modes_kf(cm, xd, mi_row, mi_col, w);
+ write_mb_modes_kf(cm, xd,
+#if CONFIG_INTRABC
+ cpi->td.mb.mbmi_ext,
+#endif // CONFIG_INTRABC
+ mi_row, mi_col, w);
} else {
#if CONFIG_VAR_TX
xd->above_txfm_context = cm->above_txfm_context + mi_col;
diff --git a/av1/encoder/rdopt.c b/av1/encoder/rdopt.c
index 61c3404..28c9138 100644
--- a/av1/encoder/rdopt.c
+++ b/av1/encoder/rdopt.c
@@ -9065,11 +9065,25 @@
const int h = block_size_high[bsize];
const int sb_row = mi_row / MAX_MIB_SIZE;
- int_mv dv_ref;
- av1_find_ref_dv(&dv_ref, mi_row, mi_col);
+ MB_MODE_INFO_EXT *const mbmi_ext = x->mbmi_ext;
+ MV_REFERENCE_FRAME ref_frame = INTRA_FRAME;
+ int_mv *const candidates = x->mbmi_ext->ref_mvs[ref_frame];
+ av1_find_mv_refs(cm, xd, mi, ref_frame, &mbmi_ext->ref_mv_count[ref_frame],
+ mbmi_ext->ref_mv_stack[ref_frame],
+#if CONFIG_EXT_INTER
+ mbmi_ext->compound_mode_context,
+#endif // CONFIG_EXT_INTER
+ candidates, mi_row, mi_col, NULL, NULL,
+ mbmi_ext->mode_context);
+
+ int_mv nearestmv, nearmv;
+ av1_find_best_ref_mvs(0, candidates, &nearestmv, &nearmv);
+
+ int_mv dv_ref = nearestmv.as_int == 0 ? nearmv : nearestmv;
+ if (dv_ref.as_int == 0) av1_find_ref_dv(&dv_ref, mi_row, mi_col);
+ mbmi_ext->ref_mvs[INTRA_FRAME][0] = dv_ref;
const MvLimits tmp_mv_limits = x->mv_limits;
-
// TODO(aconverse@google.com): Handle same row DV.
x->mv_limits.col_min = (tile->mi_col_start - mi_col) * MI_SIZE;
x->mv_limits.col_max = (tile->mi_col_end - mi_col) * MI_SIZE - w;
@@ -9198,6 +9212,7 @@
xd->mi[0]->mbmi.ref_frame[1] = NONE_FRAME;
#if CONFIG_INTRABC
xd->mi[0]->mbmi.use_intrabc = 0;
+ xd->mi[0]->mbmi.mv[0].as_int = 0;
#endif // CONFIG_INTRABC
const int64_t intra_yrd =