intrabc: Add initial skeleton
Missing features:
* RDOPT (Forced on for certain blocks)
* Any form of border extension
* Non MI sized right and bottom edges
* MV prediction
Present features:
* Force intrabc for some blocks
* Carry intrabc in the bitstream
* Validate DV is causal
* Reconstruct intrabc block assuming border extension is unnecessary
Change-Id: Ib1f6868e89bfacc2a4edfc876485bad1b347263b
diff --git a/av1/decoder/decodeframe.c b/av1/decoder/decodeframe.c
index 91b140d..8d14095 100644
--- a/av1/decoder/decodeframe.c
+++ b/av1/decoder/decodeframe.c
@@ -1728,13 +1728,24 @@
for (ref = 0; ref < 1 + has_second_ref(mbmi); ++ref) {
const MV_REFERENCE_FRAME frame = mbmi->ref_frame[ref];
- RefBuffer *ref_buf = &cm->frame_refs[frame - LAST_FRAME];
+ if (frame < LAST_FRAME) {
+#if CONFIG_INTRABC
+ assert(is_intrabc_block(mbmi));
+ assert(frame == INTRA_FRAME);
+ assert(ref == 0);
+#else
+ assert(0);
+#endif // CONFIG_INTRABC
+ } else {
+ RefBuffer *ref_buf = &cm->frame_refs[frame - LAST_FRAME];
- xd->block_refs[ref] = ref_buf;
- if ((!av1_is_valid_scale(&ref_buf->sf)))
- aom_internal_error(xd->error_info, AOM_CODEC_UNSUP_BITSTREAM,
- "Reference frame has invalid dimensions");
- av1_setup_pre_planes(xd, ref, ref_buf->buf, mi_row, mi_col, &ref_buf->sf);
+ xd->block_refs[ref] = ref_buf;
+ if ((!av1_is_valid_scale(&ref_buf->sf)))
+ aom_internal_error(xd->error_info, AOM_CODEC_UNSUP_BITSTREAM,
+ "Reference frame has invalid dimensions");
+ av1_setup_pre_planes(xd, ref, ref_buf->buf, mi_row, mi_col,
+ &ref_buf->sf);
+ }
}
#if CONFIG_CB4X4
diff --git a/av1/decoder/decodemv.c b/av1/decoder/decodemv.c
index 3a2ab56..24e7cee 100644
--- a/av1/decoder/decodemv.c
+++ b/av1/decoder/decodemv.c
@@ -902,6 +902,32 @@
}
}
+#if CONFIG_INTRABC
+static INLINE void read_mv(aom_reader *r, MV *mv, const MV *ref,
+ nmv_context *ctx, nmv_context_counts *counts,
+ int allow_hp);
+
+static INLINE int is_mv_valid(const MV *mv);
+
+static INLINE int assign_dv(AV1_COMMON *cm, MACROBLOCKD *xd, int_mv *mv,
+ const int_mv *ref_mv, int mi_row, int mi_col,
+ BLOCK_SIZE bsize, aom_reader *r) {
+#if CONFIG_EC_ADAPT
+ FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
+ (void)cm;
+#else
+ FRAME_CONTEXT *ec_ctx = cm->fc;
+#endif
+ FRAME_COUNTS *counts = xd->counts;
+ nmv_context_counts *const dv_counts = counts ? &counts->dv : NULL;
+ 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
+
static void read_intra_frame_mode_info(AV1_COMMON *const cm,
MACROBLOCKD *const xd, int mi_row,
int mi_col, aom_reader *r) {
@@ -942,6 +968,21 @@
mbmi->ref_frame[0] = INTRA_FRAME;
mbmi->ref_frame[1] = NONE_FRAME;
+#if CONFIG_INTRABC
+ 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;
+ mbmi->interp_filter = BILINEAR;
+ 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);
+ return;
+ }
+ }
+#endif // CONFIG_INTRABC
+
#if CONFIG_CB4X4
(void)i;
mbmi->mode =
@@ -2283,6 +2324,10 @@
MV_REF *frame_mvs = cm->cur_frame->mvs + mi_row * cm->mi_cols + mi_col;
int w, h;
+#if CONFIG_INTRABC
+ mi->mbmi.use_intrabc = 0;
+#endif // CONFIG_INTRABC
+
if (frame_is_intra_only(cm)) {
read_intra_frame_mode_info(cm, xd, mi_row, mi_col, r);
#if CONFIG_REF_MV