Commit 883f1df7 authored by Jingning Han's avatar Jingning Han
Browse files

Enable dynamic motion vector referencing system

This commit enables the dynamice motion vector referencing system
for inter predicted modes with single reference frame.

Change-Id: Ib3502c746276a859a7b443ec2687b71d4c788dc0
parent 472615c3
......@@ -93,6 +93,9 @@ typedef struct {
MV_REFERENCE_FRAME ref_frame[2];
TX_TYPE tx_type;
#if CONFIG_REF_MV
uint8_t ref_mv_idx;
#endif
// TODO(slavarnway): Delete and use bmi[3].as_mv[] instead.
int_mv mv[2];
/* deringing gain *per-superblock* */
......
......@@ -11,7 +11,8 @@
#include "av1/common/mvref_common.h"
#if CONFIG_REF_MV
static uint8_t add_ref_mv_candidate(const MODE_INFO *const candidate_mi,
static uint8_t add_ref_mv_candidate(const MACROBLOCKD *xd,
const MODE_INFO *const candidate_mi,
const MB_MODE_INFO *const candidate,
const MV_REFERENCE_FRAME rf[2],
uint8_t *refmv_count,
......@@ -26,6 +27,9 @@ static uint8_t add_ref_mv_candidate(const MODE_INFO *const candidate_mi,
if (candidate->ref_frame[ref] == rf[0]) {
int_mv this_refmv =
get_sub_block_mv(candidate_mi, ref, col, block);
clamp_mv_ref(&this_refmv.as_mv,
xd->n8_w << 3, xd->n8_h << 3, xd);
for (index = 0; index < *refmv_count; ++index)
if (ref_mv_stack[index].this_mv.as_int == this_refmv.as_int)
break;
......@@ -47,6 +51,9 @@ static uint8_t add_ref_mv_candidate(const MODE_INFO *const candidate_mi,
int alt_block = 3 - block;
this_refmv =
get_sub_block_mv(candidate_mi, ref, col, alt_block);
clamp_mv_ref(&this_refmv.as_mv,
xd->n8_w << 3, xd->n8_h << 3, xd);
for (index = 0; index < *refmv_count; ++index)
if (ref_mv_stack[index].this_mv.as_int == this_refmv.as_int)
break;
......@@ -75,6 +82,10 @@ static uint8_t add_ref_mv_candidate(const MODE_INFO *const candidate_mi,
get_sub_block_mv(candidate_mi, 1, col, block)
};
for (ref = 0; ref < 2; ++ref)
clamp_mv_ref(&this_refmv[ref].as_mv,
xd->n8_w << 3, xd->n8_h << 3, xd);
for (index = 0; index < *refmv_count; ++index)
if ((ref_mv_stack[index].this_mv.as_int == this_refmv[0].as_int) &&
(ref_mv_stack[index].comp_mv.as_int == this_refmv[1].as_int))
......@@ -99,6 +110,10 @@ static uint8_t add_ref_mv_candidate(const MODE_INFO *const candidate_mi,
this_refmv[0] = get_sub_block_mv(candidate_mi, 0, col, alt_block);
this_refmv[1] = get_sub_block_mv(candidate_mi, 1, col, alt_block);
for (ref = 0; ref < 2; ++ref)
clamp_mv_ref(&this_refmv[ref].as_mv,
xd->n8_w << 3, xd->n8_h << 3, xd);
for (index = 0; index < *refmv_count; ++index)
if (ref_mv_stack[index].this_mv.as_int == this_refmv[0].as_int &&
ref_mv_stack[index].comp_mv.as_int == this_refmv[1].as_int)
......@@ -144,7 +159,7 @@ static uint8_t scan_row_mbmi(const AV1_COMMON *cm, const MACROBLOCKD *xd,
const MB_MODE_INFO *const candidate_mbmi = &candidate_mi->mbmi;
const int len = AOMMIN(xd->n8_w,
num_8x8_blocks_wide_lookup[candidate_mbmi->sb_type]);
newmv_count += add_ref_mv_candidate(candidate_mi, candidate_mbmi, rf,
newmv_count += add_ref_mv_candidate(xd, candidate_mi, candidate_mbmi, rf,
refmv_count, ref_mv_stack, len,
block, mi_pos.col);
i += len;
......@@ -176,7 +191,7 @@ static uint8_t scan_col_mbmi(const AV1_COMMON *cm, const MACROBLOCKD *xd,
const MB_MODE_INFO *const candidate_mbmi = &candidate_mi->mbmi;
const int len = AOMMIN(xd->n8_h,
num_8x8_blocks_high_lookup[candidate_mbmi->sb_type]);
newmv_count += add_ref_mv_candidate(candidate_mi, candidate_mbmi, rf,
newmv_count += add_ref_mv_candidate(xd, candidate_mi, candidate_mbmi, rf,
refmv_count, ref_mv_stack, len,
block, mi_pos.col);
i += len;
......@@ -206,7 +221,7 @@ static uint8_t scan_blk_mbmi(const AV1_COMMON *cm, const MACROBLOCKD *xd,
xd->mi[mi_pos.row * xd->mi_stride + mi_pos.col];
const MB_MODE_INFO *const candidate_mbmi = &candidate_mi->mbmi;
const int len = 1;
newmv_count += add_ref_mv_candidate(candidate_mi, candidate_mbmi, rf,
newmv_count += add_ref_mv_candidate(xd, candidate_mi, candidate_mbmi, rf,
refmv_count, ref_mv_stack, len,
block, mi_pos.col);
} // Analyze a single 8x8 block motion information.
......@@ -612,9 +627,16 @@ void av1_find_mv_refs(const AV1_COMMON *cm, const MACROBLOCKD *xd,
mv_ref_list, -1,
mi_row, mi_col, mode_context);
for (idx = 0; idx < MAX_MV_REF_CANDIDATES; ++idx)
if (mv_ref_list[idx].as_int != 0)
all_zero = 0;
if (*ref_mv_count >= 2) {
for (idx = 0; idx < AOMMIN(3, *ref_mv_count); ++idx) {
if (ref_mv_stack[idx].this_mv.as_int != 0)
all_zero = 0;
}
} else {
for (idx = 0; idx < MAX_MV_REF_CANDIDATES; ++idx)
if (mv_ref_list[idx].as_int != 0)
all_zero = 0;
}
if (all_zero)
mode_context[ref_frame] |= (1 << ALL_ZERO_FLAG_OFFSET);
......
......@@ -597,6 +597,7 @@ static void read_inter_block_mode_info(AV1Decoder *const pbi,
#if CONFIG_REF_MV
mode_ctx = av1_mode_context_analyzer(inter_mode_ctx,
mbmi->ref_frame, bsize, -1);
mbmi->ref_mv_idx = 0;
#else
mode_ctx = inter_mode_ctx[mbmi->ref_frame[0]];
#endif
......@@ -609,9 +610,14 @@ static void read_inter_block_mode_info(AV1Decoder *const pbi,
return;
}
} else {
if (bsize >= BLOCK_8X8)
mbmi->mode =
read_inter_mode(cm, xd, r, mode_ctx);
if (bsize >= BLOCK_8X8) {
mbmi->mode = read_inter_mode(cm, xd, r, mode_ctx);
#if CONFIG_REF_MV
if (mbmi->mode == NEARMV && !is_compound)
if (xd->ref_mv_count[mbmi->ref_frame[0]] > 2)
mbmi->ref_mv_idx = aom_read_bit(r);
#endif
}
}
if (bsize < BLOCK_8X8 || mbmi->mode != ZEROMV) {
......@@ -622,6 +628,12 @@ static void read_inter_block_mode_info(AV1Decoder *const pbi,
}
#if CONFIG_REF_MV
if (mbmi->ref_mv_idx == 1) {
int_mv cur_mv = xd->ref_mv_stack[mbmi->ref_frame[0]][2].this_mv;
lower_mv_precision(&cur_mv.as_mv, cm->allow_high_precision_mv);
nearmv[0] = cur_mv;
}
if (is_compound && bsize >= BLOCK_8X8 && mbmi->mode != NEWMV &&
mbmi->mode != ZEROMV) {
uint8_t ref_frame_type = av1_ref_frame_type(mbmi->ref_frame);
......
......@@ -443,6 +443,11 @@ static void pack_inter_mode_mvs(AV1_COMP *cpi, const MODE_INFO *mi,
if (!segfeature_active(seg, segment_id, SEG_LVL_SKIP)) {
if (bsize >= BLOCK_8X8) {
write_inter_mode(cm, w, mode, mode_ctx);
#if CONFIG_REF_MV
if (mode == NEARMV && mbmi->ref_frame[1] == NONE)
if (mbmi_ext->ref_mv_count[mbmi->ref_frame[0]] > 2)
aom_write_bit(w, mbmi->ref_mv_idx);
#endif
}
}
......
......@@ -2926,6 +2926,11 @@ void av1_rd_pick_inter_mode_sb(AV1_COMP *cpi, TileDataEnc *tile_data,
int64_t best_filter_rd[SWITCHABLE_FILTER_CONTEXTS];
int64_t best_filter_diff[SWITCHABLE_FILTER_CONTEXTS];
MB_MODE_INFO best_mbmode;
#if CONFIG_REF_MV
uint8_t best_ref_mv_idx[MAX_REF_FRAMES] = { 0 };
int rate_skip0 = av1_cost_bit(av1_get_skip_prob(cm, xd), 0);
int rate_skip1 = av1_cost_bit(av1_get_skip_prob(cm, xd), 1);
#endif
int best_mode_skippable = 0;
int midx, best_mode_index = -1;
unsigned int ref_costs_single[MAX_REF_FRAMES], ref_costs_comp[MAX_REF_FRAMES];
......@@ -3104,6 +3109,9 @@ void av1_rd_pick_inter_mode_sb(AV1_COMP *cpi, TileDataEnc *tile_data,
ref_frame = av1_mode_order[mode_index].ref_frame[0];
second_ref_frame = av1_mode_order[mode_index].ref_frame[1];
#if CONFIG_REF_MV
mbmi->ref_mv_idx = 0;
#endif
// Look at the reference frame of the best mode so far and set the
// skip mask to look at a subset of the remaining modes.
if (midx == mode_skip_start && best_mode_index >= 0) {
......@@ -3237,7 +3245,91 @@ void av1_rd_pick_inter_mode_sb(AV1_COMP *cpi, TileDataEnc *tile_data,
&disable_skip, frame_mv, mi_row, mi_col, single_newmv,
single_inter_filter, single_skippable, &total_sse, best_rd,
&mask_filter, filter_cache);
if (this_rd == INT64_MAX) continue;
#if CONFIG_REF_MV
mbmi->ref_mv_idx = 0;
if (!comp_pred && mbmi->mode == NEARMV &&
mbmi_ext->ref_mv_count[ref_frame] > 2) {
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;
int64_t tmp_alt_rd = INT64_MAX, tmp_ref_rd = this_rd;
int tmp_rate = 0, tmp_rate_y = 0, tmp_rate_uv = 0;
int tmp_skip = 1;
int64_t tmp_dist = 0, tmp_sse = 0;
lower_mv_precision(&cur_mv.as_mv, cm->allow_high_precision_mv);
clamp_mv2(&cur_mv.as_mv, xd);
if (!mv_check_bounds(x, &cur_mv.as_mv)) {
int64_t dummy_filter_cache[SWITCHABLE_FILTER_CONTEXTS];
INTERP_FILTER dummy_single_inter_filter[MB_MODE_COUNT]
[MAX_REF_FRAMES];
int dummy_single_skippable[MB_MODE_COUNT][MAX_REF_FRAMES];
int dummy_disable_skip = 0;
int64_t dummy_mask_filter = 0;
int_mv dummy_single_newmv[MAX_REF_FRAMES] = { { 0 } };
frame_mv[NEARMV][ref_frame] = cur_mv;
tmp_alt_rd = handle_inter_mode(cpi, x, bsize,
&tmp_rate, &tmp_dist, &tmp_skip,
&tmp_rate_y, &tmp_rate_uv,
&dummy_disable_skip, frame_mv,
mi_row, mi_col,
dummy_single_newmv,
dummy_single_inter_filter,
dummy_single_skippable,
&tmp_sse, best_rd,
&dummy_mask_filter,
dummy_filter_cache);
}
if (this_rd < INT64_MAX) {
if (RDCOST(x->rdmult, x->rddiv,
rate_y + rate_uv + rate_skip0, distortion2) <
RDCOST(x->rdmult, x->rddiv, rate_skip1, total_sse))
tmp_ref_rd = RDCOST(x->rdmult, x->rddiv,
rate2 + rate_skip0, distortion2);
else
tmp_ref_rd = RDCOST(x->rdmult, x->rddiv,
rate2 + rate_skip1 - rate_y - rate_uv, total_sse);
}
if (tmp_alt_rd < INT64_MAX) {
if (RDCOST(x->rdmult, x->rddiv,
tmp_rate_y + tmp_rate_uv + rate_skip0, tmp_dist) <
RDCOST(x->rdmult, x->rddiv, rate_skip1, tmp_sse))
tmp_alt_rd = RDCOST(x->rdmult, x->rddiv,
tmp_rate + rate_skip0, tmp_dist);
else
tmp_alt_rd = RDCOST(x->rdmult, x->rddiv,
tmp_rate + rate_skip1 - tmp_rate_y - tmp_rate_uv, tmp_sse);
}
if (tmp_ref_rd > tmp_alt_rd) {
rate2 = tmp_rate;
distortion2 = tmp_dist;
skippable = tmp_skip;
rate_y = tmp_rate_y;
rate_uv = tmp_rate_uv;
total_sse = tmp_sse;
this_rd = tmp_alt_rd;
mbmi->ref_mv_idx = 1;
// Indicator of the effective nearmv reference motion vector.
best_ref_mv_idx[ref_frame] = 1;
} else {
*mbmi = backup_mbmi;
}
frame_mv[NEARMV][ref_frame] = backup_mv;
rate2 += av1_cost_bit(128, mbmi->ref_mv_idx);;
}
#endif
if (this_rd == INT64_MAX)
continue;
compmode_cost = av1_cost_bit(comp_mode_p, comp_pred);
......@@ -3260,8 +3352,14 @@ void av1_rd_pick_inter_mode_sb(AV1_COMP *cpi, TileDataEnc *tile_data,
// Cost the skip mb case
rate2 += av1_cost_bit(av1_get_skip_prob(cm, xd), 1);
} else if (ref_frame != INTRA_FRAME && !xd->lossless[mbmi->segment_id]) {
#if CONFIG_REF_MV
if (RDCOST(x->rdmult, x->rddiv,
rate_y + rate_uv + rate_skip0, distortion2) <
RDCOST(x->rdmult, x->rddiv, rate_skip1, total_sse)) {
#else
if (RDCOST(x->rdmult, x->rddiv, rate_y + rate_uv, distortion2) <
RDCOST(x->rdmult, x->rddiv, 0, total_sse)) {
#endif
// Add in the cost of the no skip flag.
rate2 += av1_cost_bit(av1_get_skip_prob(cm, xd), 0);
} else {
......@@ -3416,6 +3514,13 @@ void av1_rd_pick_inter_mode_sb(AV1_COMP *cpi, TileDataEnc *tile_data,
int comp_pred_mode = refs[1] > INTRA_FRAME;
#if CONFIG_REF_MV
if (!comp_pred_mode) {
if (best_ref_mv_idx[refs[0]] == 1) {
int_mv cur_mv =
mbmi_ext->ref_mv_stack[best_mbmode.ref_frame[0]][2].this_mv;
lower_mv_precision(&cur_mv.as_mv, cm->allow_high_precision_mv);
frame_mv[NEARMV][refs[0]] = cur_mv;
}
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)
......@@ -3484,6 +3589,9 @@ void av1_rd_pick_inter_mode_sb(AV1_COMP *cpi, TileDataEnc *tile_data,
if (mode_ctx & (1 << ALL_ZERO_FLAG_OFFSET))
best_mbmode.mode = ZEROMV;
}
if (best_mbmode.mode == NEARMV && best_mbmode.ref_frame[1] == NONE)
best_mbmode.ref_mv_idx = best_ref_mv_idx[best_mbmode.ref_frame[0]];
#endif
if (best_mode_index < 0 || best_rd >= best_rd_so_far) {
......@@ -3659,10 +3767,10 @@ void av1_rd_pick_inter_mode_sb_seg_skip(AV1_COMP *cpi, TileDataEnc *tile_data,
}
void av1_rd_pick_inter_mode_sub8x8(AV1_COMP *cpi, TileDataEnc *tile_data,
MACROBLOCK *x, int mi_row, int mi_col,
RD_COST *rd_cost, BLOCK_SIZE bsize,
PICK_MODE_CONTEXT *ctx,
int64_t best_rd_so_far) {
MACROBLOCK *x, int mi_row, int mi_col,
RD_COST *rd_cost, BLOCK_SIZE bsize,
PICK_MODE_CONTEXT *ctx,
int64_t best_rd_so_far) {
AV1_COMMON *const cm = &cpi->common;
RD_OPT *const rd_opt = &cpi->rd;
SPEED_FEATURES *const sf = &cpi->sf;
......@@ -3751,6 +3859,10 @@ void av1_rd_pick_inter_mode_sub8x8(AV1_COMP *cpi, TileDataEnc *tile_data,
ref_frame = av1_ref_order[ref_index].ref_frame[0];
second_ref_frame = av1_ref_order[ref_index].ref_frame[1];
#if CONFIG_REF_MV
mbmi->ref_mv_idx = 0;
#endif
// Look at the reference frame of the best mode so far and set the
// skip mask to look at a subset of the remaining modes.
if (ref_index > 2 && sf->mode_skip_start < MAX_MODES) {
......
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