Enable motion field estimation in DRL Enable the use of motion field estimation in the dynamic motion vector referencing system. With default experiments on, it improves the compression performance: lowres 1.2% midres 1.5% Change-Id: Ifc5b15a7239b5c3212ea50f326ab99d372034658
diff --git a/av1/common/alloccommon.c b/av1/common/alloccommon.c index 69b2197..0db9ff6 100644 --- a/av1/common/alloccommon.c +++ b/av1/common/alloccommon.c
@@ -85,6 +85,10 @@ } aom_free(pool->frame_bufs[i].mvs); pool->frame_bufs[i].mvs = NULL; +#if CONFIG_MFMV + aom_free(pool->frame_bufs[i].tpl_mvs); + pool->frame_bufs[i].tpl_mvs = NULL; +#endif aom_free_frame_buffer(&pool->frame_bufs[i].buf); #if CONFIG_HASH_ME av1_hash_table_destroy(&pool->frame_bufs[i].hash_table);
diff --git a/av1/common/mv.h b/av1/common/mv.h index ab35880..59b9ad9 100644 --- a/av1/common/mv.h +++ b/av1/common/mv.h
@@ -20,6 +20,8 @@ extern "C" { #endif +#define INVALID_MV 0x80008000 + typedef struct mv { int16_t row; int16_t col;
diff --git a/av1/common/mvref_common.c b/av1/common/mvref_common.c index 8f6232e..14f37d0 100644 --- a/av1/common/mvref_common.c +++ b/av1/common/mvref_common.c
@@ -306,6 +306,114 @@ return has_tr; } +#if CONFIG_MFMV +static int add_tpl_ref_mv(const AV1_COMMON *cm, + const MV_REF *prev_frame_mvs_base, + const MACROBLOCKD *xd, int mi_row, int mi_col, + MV_REFERENCE_FRAME ref_frame, int blk_row, + int blk_col, uint8_t *refmv_count, + CANDIDATE_MV *ref_mv_stack, int16_t *mode_context) { + const TPL_MV_REF *prev_frame_mvs = cm->cur_frame->tpl_mvs + + (mi_row + blk_row) * cm->mi_stride + + (mi_col + blk_col); + (void)prev_frame_mvs_base; + POSITION mi_pos; + int idx; + int coll_blk_count = 0; + const int weight_unit = 1; // mi_size_wide[BLOCK_8X8]; + +#if CONFIG_MV_COMPRESS + mi_pos.row = (mi_row & 0x01) ? blk_row : blk_row + 1; + mi_pos.col = (mi_col & 0x01) ? blk_col : blk_col + 1; +#else + mi_pos.row = blk_row; + mi_pos.col = blk_col; +#endif + + if (!is_inside(&xd->tile, mi_col, mi_row, cm->mi_rows, cm, &mi_pos)) + return coll_blk_count; + + MV_REFERENCE_FRAME rf[2]; + av1_set_ref_frame(rf, ref_frame); + + if (rf[1] == NONE_FRAME) { + for (int i = 0; i < MFMV_STACK_SIZE; ++i) { + if (prev_frame_mvs->mfmv[ref_frame - LAST_FRAME][i].as_int != + INVALID_MV) { + int_mv this_refmv = prev_frame_mvs->mfmv[ref_frame - LAST_FRAME][i]; + lower_mv_precision(&this_refmv.as_mv, cm->allow_high_precision_mv); + + if (abs(this_refmv.as_mv.row) >= 16 || abs(this_refmv.as_mv.col) >= 16) + mode_context[ref_frame] |= (1 << ZEROMV_OFFSET); + + for (idx = 0; idx < *refmv_count; ++idx) + if (abs(this_refmv.as_mv.row - ref_mv_stack[idx].this_mv.as_mv.row) < + 4 && + abs(this_refmv.as_mv.col - ref_mv_stack[idx].this_mv.as_mv.col) < + 4) + break; + + if (idx < *refmv_count) ref_mv_stack[idx].weight += 2 * weight_unit; + + if (idx == *refmv_count && *refmv_count < MAX_REF_MV_STACK_SIZE) { + ref_mv_stack[idx].this_mv.as_int = this_refmv.as_int; + // TODO(jingning): Hard coded context number. Need to make it better + // sense. + ref_mv_stack[idx].pred_diff[0] = 1; + ref_mv_stack[idx].weight = 2 * weight_unit; + ++(*refmv_count); + } + + ++coll_blk_count; + } + } + } else { + // Process compound inter mode + for (int i = 0; i < MFMV_STACK_SIZE; ++i) { + if (prev_frame_mvs->mfmv[rf[0] - LAST_FRAME][i].as_int != INVALID_MV && + prev_frame_mvs->mfmv[rf[1] - LAST_FRAME][i].as_int != INVALID_MV) { + int_mv this_refmv = prev_frame_mvs->mfmv[rf[0] - LAST_FRAME][i]; + int_mv comp_refmv = prev_frame_mvs->mfmv[rf[1] - LAST_FRAME][i]; + lower_mv_precision(&this_refmv.as_mv, cm->allow_high_precision_mv); + lower_mv_precision(&comp_refmv.as_mv, cm->allow_high_precision_mv); + + if (abs(this_refmv.as_mv.row) >= 16 || + abs(this_refmv.as_mv.col) >= 16 || + abs(comp_refmv.as_mv.row) >= 16 || abs(comp_refmv.as_mv.col) >= 16) + mode_context[ref_frame] |= (1 << ZEROMV_OFFSET); + + for (idx = 0; idx < *refmv_count; ++idx) + if (abs(this_refmv.as_mv.row - ref_mv_stack[idx].this_mv.as_mv.row) < + 4 && + abs(this_refmv.as_mv.col - ref_mv_stack[idx].this_mv.as_mv.col) < + 4 && + abs(comp_refmv.as_mv.row - ref_mv_stack[idx].comp_mv.as_mv.row) < + 4 && + abs(comp_refmv.as_mv.col - ref_mv_stack[idx].comp_mv.as_mv.col) < + 4) + break; + + if (idx < *refmv_count) ref_mv_stack[idx].weight += 2 * weight_unit; + + if (idx == *refmv_count && *refmv_count < MAX_REF_MV_STACK_SIZE) { + ref_mv_stack[idx].this_mv.as_int = this_refmv.as_int; + ref_mv_stack[idx].comp_mv.as_int = comp_refmv.as_int; + // TODO(jingning): Hard coded context number. Need to make it better + // sense. + ref_mv_stack[idx].pred_diff[0] = 1; + ref_mv_stack[idx].pred_diff[1] = 1; + ref_mv_stack[idx].weight = 2 * weight_unit; + ++(*refmv_count); + } + + ++coll_blk_count; + } + } + } + + return coll_blk_count; +} +#else static int add_col_ref_mv(const AV1_COMMON *cm, const MV_REF *prev_frame_mvs_base, const MACROBLOCKD *xd, int mi_row, int mi_col, @@ -356,6 +464,7 @@ return coll_blk_count; } +#endif static void setup_ref_mv_list(const AV1_COMMON *cm, const MACROBLOCKD *xd, MV_REFERENCE_FRAME ref_frame, @@ -430,6 +539,37 @@ for (idx = 0; idx < nearest_refmv_count; ++idx) ref_mv_stack[idx].weight += REF_CAT_LEVEL; + +#if CONFIG_MFMV + int blk_row, blk_col; + int coll_blk_count = 0; + + int tpl_sample_pos[9][2] = { + { -1, xd->n8_w }, { 0, xd->n8_w }, { xd->n8_h, xd->n8_w }, + { xd->n8_h, 0 }, { xd->n8_h, -1 }, { xd->n8_h, -2 }, + { -2, xd->n8_w }, { xd->n8_h, 2 }, { 1, xd->n8_w + 2 }, + }; + int i; + + for (blk_row = 0; blk_row < xd->n8_h; ++blk_row) { + for (blk_col = 0; blk_col < xd->n8_w; ++blk_col) { + coll_blk_count += add_tpl_ref_mv(cm, prev_frame_mvs_base, xd, mi_row, + mi_col, ref_frame, blk_row, blk_col, + refmv_count, ref_mv_stack, mode_context); + } + } + + if (coll_blk_count == 0) mode_context[ref_frame] |= (1 << ZEROMV_OFFSET); + + for (i = 0; i < 9; ++i) { + blk_row = tpl_sample_pos[i][0]; + blk_col = tpl_sample_pos[i][1]; + coll_blk_count += add_tpl_ref_mv(cm, prev_frame_mvs_base, xd, mi_row, + mi_col, ref_frame, blk_row, blk_col, + refmv_count, ref_mv_stack, mode_context); + } + +#else #if CONFIG_TEMPMV_SIGNALING if (cm->use_prev_frame_mvs && rf[1] == NONE_FRAME) #else @@ -478,6 +618,7 @@ } else { mode_context[ref_frame] |= (1 << ZEROMV_OFFSET); } +#endif // Scan the second outer area. scan_blk_mbmi(cm, xd, mi_row, mi_col, block, rf, -1, -1, ref_mv_stack, @@ -919,7 +1060,6 @@ zero, so sets the ALL_ZERO flag. * This leads to an encode/decode mismatch. */ - for (idx = 0; idx < AOMMIN(3, *ref_mv_count); ++idx) { if (ref_mv_stack[idx].this_mv.as_int != zeromv[0].as_int) all_zero = 0; if (ref_frame > ALTREF_FRAME) @@ -1072,7 +1212,409 @@ cm->buffer_pool->frame_bufs[bwd_buf_idx].cur_frame_offset; #endif } + +INLINE void get_mv_projection(MV *output, MV ref, int num, int den) { + output->row = (int16_t)(ref.row * (double)num / den); + output->col = (int16_t)(ref.col * (double)num / den); +} + +INLINE void get_block_position(AV1_COMMON *cm, int *mi_r, int *mi_c, + int blk_row, int blk_col, MV mv, int sign_bias) { + int row = (sign_bias == 1) ? blk_row - (mv.row >> (3 + MI_SIZE_LOG2)) + : blk_row + (mv.row >> (3 + MI_SIZE_LOG2)); + int col = (sign_bias == 1) ? blk_col - (mv.col >> (3 + MI_SIZE_LOG2)) + : blk_col + (mv.col >> (3 + MI_SIZE_LOG2)); + + row = AOMMIN(row, cm->mi_rows); + row = AOMMAX(row, 0); + col = AOMMIN(col, cm->mi_cols); + col = AOMMAX(col, 0); + + *mi_r = row; + *mi_c = col; +} + +INLINE uint32_t mv_sign_reverse(int_mv ref) { + int_mv this_mv; + this_mv.as_mv.row = -ref.as_mv.row; + this_mv.as_mv.col = -ref.as_mv.col; + + return this_mv.as_int; +} + +void av1_setup_motion_field(AV1_COMMON *cm) { + int cur_frame_index = cm->cur_frame->cur_frame_offset; + int lst_frame_index = 0, alt_frame_index = 0, gld_frame_index = 0; +#if CONFIG_EXT_REFS + int lst2_frame_index = 0, lst3_frame_index = 0, bwd_frame_index = 0; #endif + TPL_MV_REF *tpl_mvs_base = cm->cur_frame->tpl_mvs; + + for (int ref_frame = 0; ref_frame < INTER_REFS_PER_FRAME; ++ref_frame) { + int size = (cm->mi_rows + 16) * cm->mi_stride; + for (int idx = 0; idx < size; ++idx) { + for (int i = 0; i < MFMV_STACK_SIZE; ++i) + tpl_mvs_base[idx].mfmv[ref_frame][i].as_int = INVALID_MV; + } + } + + int alt_buf_idx = cm->frame_refs[ALTREF_FRAME - LAST_FRAME].idx; + int lst_buf_idx = cm->frame_refs[LAST_FRAME - LAST_FRAME].idx; + int gld_buf_idx = cm->frame_refs[GOLDEN_FRAME - LAST_FRAME].idx; +#if CONFIG_EXT_REFS + int lst2_buf_idx = cm->frame_refs[LAST2_FRAME - LAST_FRAME].idx; + int lst3_buf_idx = cm->frame_refs[LAST3_FRAME - LAST_FRAME].idx; + int bwd_buf_idx = cm->frame_refs[BWDREF_FRAME - LAST_FRAME].idx; +#endif + + if (alt_buf_idx >= 0) + alt_frame_index = cm->buffer_pool->frame_bufs[alt_buf_idx].cur_frame_offset; + + if (lst_buf_idx >= 0) + lst_frame_index = cm->buffer_pool->frame_bufs[lst_buf_idx].cur_frame_offset; + + if (gld_buf_idx >= 0) + gld_frame_index = cm->buffer_pool->frame_bufs[gld_buf_idx].cur_frame_offset; + +#if CONFIG_EXT_REFS + if (lst2_buf_idx >= 0) + lst2_frame_index = + cm->buffer_pool->frame_bufs[lst2_buf_idx].cur_frame_offset; + + if (lst3_buf_idx >= 0) + lst3_frame_index = + cm->buffer_pool->frame_bufs[lst3_buf_idx].cur_frame_offset; + + if (bwd_buf_idx >= 0) + bwd_frame_index = cm->buffer_pool->frame_bufs[bwd_buf_idx].cur_frame_offset; +#endif + + if (alt_frame_index < cur_frame_index) return; + + // ====================== + // Process last frame + // ====================== + if (lst_buf_idx >= 0) { + MV_REF *mv_ref_base = cm->buffer_pool->frame_bufs[lst_buf_idx].mvs; + const int lst_frame_idx = + cm->buffer_pool->frame_bufs[lst_buf_idx].lst_frame_offset; + const int alt_frame_idx = + cm->buffer_pool->frame_bufs[lst_buf_idx].alt_frame_offset; + const int gld_frame_idx = + cm->buffer_pool->frame_bufs[lst_buf_idx].gld_frame_offset; +#if CONFIG_EXT_REFS + const int lst2_frame_idx = + cm->buffer_pool->frame_bufs[lst_buf_idx].lst2_frame_offset; + const int lst3_frame_idx = + cm->buffer_pool->frame_bufs[lst_buf_idx].lst3_frame_offset; + const int bwd_frame_idx = + cm->buffer_pool->frame_bufs[lst_buf_idx].bwd_frame_offset; +#endif + + int alt_offset = AOMMAX(1, alt_frame_idx - lst_frame_index); + int lst_offset = AOMMAX(1, lst_frame_index - lst_frame_idx); + int gld_offset = AOMMAX(1, lst_frame_index - gld_frame_idx); + int cur_to_lst = cur_frame_index - lst_frame_index; + int cur_to_alt = alt_frame_index - cur_frame_index; + int cur_to_gld = cur_frame_index - gld_frame_index; + +#if CONFIG_EXT_REFS + int bwd_offset = AOMMAX(1, bwd_frame_idx - lst_frame_index); + int lst2_offset = AOMMAX(1, lst_frame_index - lst2_frame_idx); + int lst3_offset = AOMMAX(1, lst_frame_index - lst3_frame_idx); + int cur_to_lst2 = cur_frame_index - lst2_frame_index; + int cur_to_lst3 = cur_frame_index - lst3_frame_index; + int cur_to_bwd = bwd_frame_index - cur_frame_index; +#endif + + const int is_lst_overlay = (alt_frame_idx == gld_frame_index); + // clang-format off + const int ref_frame_offset_buffer[TOTAL_REFS_PER_FRAME] = { +#if CONFIG_EXT_REFS + 0, lst_offset, lst2_offset, lst3_offset, gld_offset, + bwd_offset, alt_offset +#else + 0, lst_offset, gld_offset, alt_offset +#endif + }; + // clang-format on + + for (int blk_row = 0; blk_row < cm->mi_rows && !is_lst_overlay; ++blk_row) { + for (int blk_col = 0; blk_col < cm->mi_cols; ++blk_col) { + MV_REF *mv_ref = &mv_ref_base[blk_row * cm->mi_cols + blk_col]; + MV fwd_mv = mv_ref->mv[0].as_mv; + MV_REFERENCE_FRAME ref_frame[2] = { mv_ref->ref_frame[0], + mv_ref->ref_frame[1] }; + + // Derive motion vectors toward last reference frame. + if (ref_frame[0] <= GOLDEN_FRAME && ref_frame[0] > INTRA_FRAME) { + int_mv this_mv; + int mi_r, mi_c; + + const int ref_frame_offset = ref_frame_offset_buffer[ref_frame[0]]; + + get_mv_projection(&this_mv.as_mv, fwd_mv, cur_to_lst, + ref_frame_offset); + get_block_position(cm, &mi_r, &mi_c, blk_row, blk_col, this_mv.as_mv, + 1); + int mi_offset = mi_r * cm->mi_stride + mi_c; + tpl_mvs_base[mi_offset].mfmv[FWD_RF_OFFSET(LAST_FRAME)][0].as_int = + this_mv.as_int; + +#if CONFIG_EXT_REFS + get_mv_projection(&this_mv.as_mv, fwd_mv, cur_to_lst2, + ref_frame_offset); + tpl_mvs_base[mi_offset].mfmv[FWD_RF_OFFSET(LAST2_FRAME)][0].as_int = + this_mv.as_int; + + get_mv_projection(&this_mv.as_mv, fwd_mv, cur_to_lst3, + ref_frame_offset); + tpl_mvs_base[mi_offset].mfmv[FWD_RF_OFFSET(LAST3_FRAME)][0].as_int = + this_mv.as_int; +#endif + get_mv_projection(&this_mv.as_mv, fwd_mv, cur_to_gld, + ref_frame_offset); + tpl_mvs_base[mi_offset].mfmv[FWD_RF_OFFSET(GOLDEN_FRAME)][0].as_int = + this_mv.as_int; + } + + for (int idx = 0; idx < 2; ++idx) { + if (ref_frame[idx] <= GOLDEN_FRAME) continue; + + int_mv this_mv; + int mi_r, mi_c; + fwd_mv = mv_ref->mv[idx].as_mv; + + const int ref_frame_offset = ref_frame_offset_buffer[ref_frame[idx]]; + + get_mv_projection(&this_mv.as_mv, fwd_mv, cur_to_lst, + ref_frame_offset); + get_block_position(cm, &mi_r, &mi_c, blk_row, blk_col, this_mv.as_mv, + 0); + + int mi_offset = mi_r * cm->mi_stride + mi_c; + get_mv_projection(&this_mv.as_mv, fwd_mv, cur_to_alt, + ref_frame_offset); + tpl_mvs_base[mi_offset].mfmv[FWD_RF_OFFSET(ALTREF_FRAME)][0].as_int = + this_mv.as_int; + +#if CONFIG_EXT_REFS + get_mv_projection(&this_mv.as_mv, fwd_mv, cur_to_bwd, + ref_frame_offset); + tpl_mvs_base[mi_offset].mfmv[FWD_RF_OFFSET(BWDREF_FRAME)][0].as_int = + this_mv.as_int; +#endif + } + } + } + } + + // ======================= + // Process ARF frame + // ======================= + if (alt_buf_idx >= 0) { + MV_REF *mv_ref_base = cm->buffer_pool->frame_bufs[alt_buf_idx].mvs; + const int lst_frame_idx = + cm->buffer_pool->frame_bufs[alt_buf_idx].lst_frame_offset; + const int gld_frame_idx = + cm->buffer_pool->frame_bufs[alt_buf_idx].gld_frame_offset; +#if CONFIG_EXT_REFS + const int lst2_frame_idx = + cm->buffer_pool->frame_bufs[alt_buf_idx].lst2_frame_offset; + const int lst3_frame_idx = + cm->buffer_pool->frame_bufs[alt_buf_idx].lst3_frame_offset; + const int bwd_frame_idx = + cm->buffer_pool->frame_bufs[alt_buf_idx].bwd_frame_offset; +#endif + + int lst_offset = AOMMAX(1, alt_frame_index - lst_frame_idx); + int gld_offset = AOMMAX(1, alt_frame_index - gld_frame_idx); + int cur_to_alt = alt_frame_index - cur_frame_index; + int cur_to_lst = cur_frame_index - lst_frame_index; + +#if CONFIG_EXT_REFS + int bwd_offset = AOMMAX(1, alt_frame_index - bwd_frame_idx); + int lst2_offset = AOMMAX(1, alt_frame_index - lst2_frame_idx); + int lst3_offset = AOMMAX(1, alt_frame_index - lst3_frame_idx); + int cur_to_lst2 = cur_frame_index - lst2_frame_index; + int cur_to_lst3 = cur_frame_index - lst3_frame_index; + int cur_to_gld = cur_frame_index - gld_frame_index; + int cur_to_bwd = bwd_frame_index - cur_frame_index; +#endif + const int ref_stamp = FWD_RF_OFFSET(ALTREF_FRAME); + // clang-format off + const int ref_frame_offset_buffer[TOTAL_REFS_PER_FRAME] = { +#if CONFIG_EXT_REFS + 0, lst_offset, lst2_offset, lst3_offset, gld_offset, + bwd_offset, 0, +#else + 0, lst_offset, gld_offset, 0, +#endif + }; + // clang-format on + + for (int blk_row = 0; blk_row < cm->mi_rows; ++blk_row) { + for (int blk_col = 0; blk_col < cm->mi_cols; ++blk_col) { + MV_REF *mv_ref = &mv_ref_base[blk_row * cm->mi_cols + blk_col]; + MV fwd_mv = mv_ref->mv[0].as_mv; + MV_REFERENCE_FRAME ref_frame[2] = { mv_ref->ref_frame[0], + mv_ref->ref_frame[1] }; + + const int ref_frame_offset = ref_frame_offset_buffer[ref_frame[0]]; + + if (ref_frame[0] <= GOLDEN_FRAME && ref_frame[0] > INTRA_FRAME) { + int_mv this_mv; + int mi_r, mi_c; + + get_mv_projection(&this_mv.as_mv, fwd_mv, cur_to_alt, + ref_frame_offset); + get_block_position(cm, &mi_r, &mi_c, blk_row, blk_col, this_mv.as_mv, + 0); + + int mi_offset = mi_r * cm->mi_stride + mi_c; + tpl_mvs_base[mi_offset] + .mfmv[FWD_RF_OFFSET(ALTREF_FRAME)][ref_stamp] + .as_int = mv_sign_reverse(this_mv); + + get_mv_projection(&this_mv.as_mv, fwd_mv, cur_to_lst, + ref_frame_offset); + tpl_mvs_base[mi_offset] + .mfmv[FWD_RF_OFFSET(LAST_FRAME)][ref_stamp] + .as_int = this_mv.as_int; + +#if CONFIG_EXT_REFS + get_mv_projection(&this_mv.as_mv, fwd_mv, cur_to_bwd, + ref_frame_offset); + tpl_mvs_base[mi_offset] + .mfmv[FWD_RF_OFFSET(BWDREF_FRAME)][ref_stamp] + .as_int = mv_sign_reverse(this_mv); + + if (ref_frame[0] >= LAST2_FRAME) { + get_mv_projection(&this_mv.as_mv, fwd_mv, cur_to_lst2, + ref_frame_offset); + tpl_mvs_base[mi_offset] + .mfmv[FWD_RF_OFFSET(LAST2_FRAME)][ref_stamp] + .as_int = this_mv.as_int; + } + + if (ref_frame[0] >= LAST3_FRAME) { + get_mv_projection(&this_mv.as_mv, fwd_mv, cur_to_lst3, + ref_frame_offset); + tpl_mvs_base[mi_offset] + .mfmv[FWD_RF_OFFSET(LAST3_FRAME)][ref_stamp] + .as_int = this_mv.as_int; + } +#endif + if (ref_frame[0] >= GOLDEN_FRAME) { + get_mv_projection(&this_mv.as_mv, fwd_mv, cur_to_gld, + ref_frame_offset); + tpl_mvs_base[mi_offset] + .mfmv[FWD_RF_OFFSET(GOLDEN_FRAME)][ref_stamp] + .as_int = this_mv.as_int; + } + } + } + } + } + +// ========================================== +// Process BWD reference frame +// ========================================== +#if CONFIG_EXT_REFS + if (bwd_buf_idx >= 0) { + MV_REF *mv_ref_base = cm->buffer_pool->frame_bufs[bwd_buf_idx].mvs; + const int lst_frame_idx = + cm->buffer_pool->frame_bufs[bwd_buf_idx].lst_frame_offset; + const int gld_frame_idx = + cm->buffer_pool->frame_bufs[bwd_buf_idx].gld_frame_offset; + const int lst2_frame_idx = + cm->buffer_pool->frame_bufs[bwd_buf_idx].lst2_frame_offset; + const int lst3_frame_idx = + cm->buffer_pool->frame_bufs[bwd_buf_idx].lst3_frame_offset; + const int bwd_frame_idx = + cm->buffer_pool->frame_bufs[bwd_buf_idx].bwd_frame_offset; + const int alt_frame_idx = + cm->buffer_pool->frame_bufs[bwd_buf_idx].alt_frame_offset; + + int lst_offset = AOMMAX(1, bwd_frame_index - lst_frame_idx); + int gld_offset = AOMMAX(1, bwd_frame_index - gld_frame_idx); + int cur_to_lst = cur_frame_index - lst_frame_index; + + int lst2_offset = AOMMAX(1, bwd_frame_index - lst2_frame_idx); + int lst3_offset = AOMMAX(1, bwd_frame_index - lst3_frame_idx); + int bwd_offset = AOMMAX(1, bwd_frame_idx - bwd_frame_index); + int alt_offset = AOMMAX(1, alt_frame_idx - bwd_frame_index); + int cur_to_lst2 = cur_frame_index - lst2_frame_index; + int cur_to_lst3 = cur_frame_index - lst3_frame_index; + int cur_to_gld = cur_frame_index - gld_frame_index; + int cur_to_bwd = bwd_frame_index - cur_frame_index; + + const int ref_stamp = FWD_RF_OFFSET(BWDREF_FRAME); + const int ref_frame_offset_buffer[TOTAL_REFS_PER_FRAME] = { + 0, lst_offset, lst2_offset, lst3_offset, + gld_offset, bwd_offset, alt_offset, + }; + + for (int blk_row = 0; blk_row < cm->mi_rows; ++blk_row) { + for (int blk_col = 0; blk_col < cm->mi_cols; ++blk_col) { + MV_REF *mv_ref = &mv_ref_base[blk_row * cm->mi_cols + blk_col]; + MV fwd_mv = mv_ref->mv[0].as_mv; + MV_REFERENCE_FRAME ref_frame[2] = { mv_ref->ref_frame[0], + mv_ref->ref_frame[1] }; + + const int ref_frame_offset = ref_frame_offset_buffer[ref_frame[0]]; + + if (ref_frame[0] <= GOLDEN_FRAME && ref_frame[0] > INTRA_FRAME) { + int_mv this_mv; + int mi_r, mi_c; + + get_mv_projection(&this_mv.as_mv, fwd_mv, cur_to_bwd, + ref_frame_offset); + get_block_position(cm, &mi_r, &mi_c, blk_row, blk_col, this_mv.as_mv, + 0); + int mi_offset = mi_r * cm->mi_stride + mi_c; + + tpl_mvs_base[mi_offset] + .mfmv[FWD_RF_OFFSET(BWDREF_FRAME)][ref_stamp] + .as_int = mv_sign_reverse(this_mv); + + // Project the motion vector onto last reference frame + get_mv_projection(&this_mv.as_mv, fwd_mv, cur_to_lst, + ref_frame_offset); + tpl_mvs_base[mi_offset] + .mfmv[FWD_RF_OFFSET(LAST_FRAME)][ref_stamp] + .as_int = this_mv.as_int; + + if (ref_frame[0] >= LAST2_FRAME) { + get_mv_projection(&this_mv.as_mv, fwd_mv, cur_to_lst2, + ref_frame_offset); + tpl_mvs_base[mi_offset] + .mfmv[FWD_RF_OFFSET(LAST2_FRAME)][ref_stamp] + .as_int = this_mv.as_int; + } + + if (ref_frame[0] >= LAST3_FRAME) { + get_mv_projection(&this_mv.as_mv, fwd_mv, cur_to_lst3, + ref_frame_offset); + tpl_mvs_base[mi_offset] + .mfmv[FWD_RF_OFFSET(LAST3_FRAME)][ref_stamp] + .as_int = this_mv.as_int; + } + + if (ref_frame[0] >= GOLDEN_FRAME) { + get_mv_projection(&this_mv.as_mv, fwd_mv, cur_to_gld, + ref_frame_offset); + tpl_mvs_base[mi_offset] + .mfmv[FWD_RF_OFFSET(GOLDEN_FRAME)][ref_stamp] + .as_int = this_mv.as_int; + } + } + } + } + } +#endif +} +#endif // CONFIG_MFMV #if CONFIG_WARPED_MOTION #if WARPED_MOTION_SORT_SAMPLES
diff --git a/av1/common/mvref_common.h b/av1/common/mvref_common.h index 05d7584..4d33597 100644 --- a/av1/common/mvref_common.h +++ b/av1/common/mvref_common.h
@@ -381,6 +381,7 @@ #if CONFIG_MFMV void av1_setup_frame_buf_refs(AV1_COMMON *cm); +void av1_setup_motion_field(AV1_COMMON *cm); #endif typedef void (*find_mv_refs_sync)(void *const data, int mi_row);
diff --git a/av1/common/onyxc_int.h b/av1/common/onyxc_int.h index e077556..e966a12 100644 --- a/av1/common/onyxc_int.h +++ b/av1/common/onyxc_int.h
@@ -111,6 +111,14 @@ REFRESH_FRAME_CONTEXT_BACKWARD, } REFRESH_FRAME_CONTEXT_MODE; +#if CONFIG_MFMV +#define MFMV_STACK_SIZE INTER_REFS_PER_FRAME + +typedef struct { + int_mv mfmv[INTER_REFS_PER_FRAME][MFMV_STACK_SIZE]; +} TPL_MV_REF; +#endif + typedef struct { int_mv mv[2]; int_mv pred_mv[2]; @@ -125,14 +133,13 @@ int lst_frame_offset; int alt_frame_offset; int gld_frame_offset; - #if CONFIG_EXT_REFS int lst2_frame_offset; int lst3_frame_offset; int bwd_frame_offset; #endif + TPL_MV_REF *tpl_mvs; #endif - MV_REF *mvs; int mi_rows; int mi_cols; @@ -587,6 +594,14 @@ CHECK_MEM_ERROR( cm, buf->mvs, (MV_REF *)aom_calloc(cm->mi_rows * cm->mi_cols, sizeof(*buf->mvs))); + +#if CONFIG_MFMV + aom_free(buf->tpl_mvs); + CHECK_MEM_ERROR( + cm, buf->tpl_mvs, + (TPL_MV_REF *)aom_calloc((cm->mi_rows + MAX_MIB_SIZE) * cm->mi_stride, + sizeof(*buf->tpl_mvs))); +#endif } }
diff --git a/av1/decoder/decodeframe.c b/av1/decoder/decodeframe.c index 18663cc..7af5c0e 100644 --- a/av1/decoder/decodeframe.c +++ b/av1/decoder/decodeframe.c
@@ -5287,6 +5287,7 @@ #if CONFIG_MFMV av1_setup_frame_buf_refs(cm); + av1_setup_motion_field(cm); #endif av1_setup_block_planes(xd, cm->subsampling_x, cm->subsampling_y);
diff --git a/av1/encoder/encodeframe.c b/av1/encoder/encodeframe.c index 64f40ac..2fa1dc5 100644 --- a/av1/encoder/encodeframe.c +++ b/av1/encoder/encodeframe.c
@@ -5314,6 +5314,7 @@ cm->frame_offset = cm->current_video_frame; } av1_setup_frame_buf_refs(cm); + av1_setup_motion_field(cm); #endif {
diff --git a/av1/encoder/rd.h b/av1/encoder/rd.h index 98f39bd..2cfd8f2 100644 --- a/av1/encoder/rd.h +++ b/av1/encoder/rd.h
@@ -43,8 +43,6 @@ #define MV_COST_WEIGHT 108 #define MV_COST_WEIGHT_SUB 120 -#define INVALID_MV 0x80008000 - #define RD_THRESH_MAX_FACT 64 #define RD_THRESH_INC 1