Commit 472615c3 authored by Jingning Han's avatar Jingning Han

Generate compound reference motion vector

Use and compare the reference frame vector to find the reference
motion vector candidates for compound mode.

Change-Id: Ie9d1006f5121593a2311fcaeac411a54a705d266
parent d53bc5f9
......@@ -66,6 +66,12 @@ typedef struct {
#define MAX_REF_FRAMES 4
typedef int8_t MV_REFERENCE_FRAME;
#if CONFIG_REF_MV
#define MODE_CTX_REF_FRAMES (MAX_REF_FRAMES + (ALTREF_FRAME - LAST_FRAME))
#else
#define MODE_CTX_REF_FRAMES MAX_REF_FRAMES
#endif
// This structure now relates to 8x8 block regions.
typedef struct {
// Common for both INTER and INTRA blocks
......@@ -196,8 +202,8 @@ typedef struct macroblockd {
const YV12_BUFFER_CONFIG *cur_buf;
#if CONFIG_REF_MV
uint8_t ref_mv_count[MAX_REF_FRAMES];
CANDIDATE_MV ref_mv_stack[MAX_REF_FRAMES][MAX_REF_MV_STACK_SIZE];
uint8_t ref_mv_count[MODE_CTX_REF_FRAMES];
CANDIDATE_MV ref_mv_stack[MODE_CTX_REF_FRAMES][MAX_REF_MV_STACK_SIZE];
uint8_t is_sec_rect;
#endif
......
......@@ -303,7 +303,8 @@ static void setup_ref_mv_list(const AV1_COMMON *cm, const MACROBLOCKD *xd,
nearest_refmv_count = *refmv_count;
if (prev_frame_mvs_base && cm->show_frame && cm->last_show_frame) {
if (prev_frame_mvs_base && cm->show_frame && cm->last_show_frame &&
rf[1] == NONE) {
int ref;
int blk_row, blk_col;
int coll_blk_count = 0;
......@@ -422,10 +423,19 @@ static void setup_ref_mv_list(const AV1_COMMON *cm, const MACROBLOCKD *xd,
}
}
for (idx = 0; idx < AOMMIN(MAX_MV_REF_CANDIDATES, *refmv_count); ++idx) {
mv_ref_list[idx].as_int = ref_mv_stack[idx].this_mv.as_int;
clamp_mv_ref(&mv_ref_list[idx].as_mv,
(xd->n8_w << 3), (xd->n8_h << 3), xd);
if (rf[1] > NONE) {
for (idx = 0; idx < *refmv_count; ++idx) {
clamp_mv_ref(&ref_mv_stack[idx].this_mv.as_mv,
xd->n8_w << 3 , xd->n8_h << 3, xd);
clamp_mv_ref(&ref_mv_stack[idx].comp_mv.as_mv,
xd->n8_w << 3 , xd->n8_h << 3, xd);
}
} else {
for (idx = 0; idx < AOMMIN(MAX_MV_REF_CANDIDATES, *refmv_count); ++idx) {
mv_ref_list[idx].as_int = ref_mv_stack[idx].this_mv.as_int;
clamp_mv_ref(&mv_ref_list[idx].as_mv,
xd->n8_w << 3, xd->n8_h << 3, xd);
}
}
}
#endif
......@@ -611,14 +621,6 @@ void av1_find_mv_refs(const AV1_COMMON *cm, const MACROBLOCKD *xd,
#endif
}
static void lower_mv_precision(MV *mv, int allow_hp) {
const int use_hp = allow_hp && av1_use_mv_hp(mv);
if (!use_hp) {
if (mv->row & 1) mv->row += (mv->row > 0 ? -1 : 1);
if (mv->col & 1) mv->col += (mv->col > 0 ? -1 : 1);
}
}
void av1_find_best_ref_mvs(int allow_hp, int_mv *mvlist, int_mv *nearest_mv,
int_mv *near_mv) {
int i;
......
......@@ -302,6 +302,16 @@ static INLINE int is_inside(const TileInfo *const tile, int mi_col, int mi_row,
mi_col + mi_pos->col >= tile->mi_col_end);
}
static INLINE void lower_mv_precision(MV *mv, int allow_hp) {
const int use_hp = allow_hp && av1_use_mv_hp(mv);
if (!use_hp) {
if (mv->row & 1)
mv->row += (mv->row > 0 ? -1 : 1);
if (mv->col & 1)
mv->col += (mv->col > 0 ? -1 : 1);
}
}
#if CONFIG_REF_MV
static int8_t av1_ref_frame_type(const MV_REFERENCE_FRAME *const rf) {
if (rf[1] > INTRA_FRAME)
......
......@@ -564,9 +564,9 @@ static void read_inter_block_mode_info(AV1Decoder *const pbi,
const BLOCK_SIZE bsize = mbmi->sb_type;
const int allow_hp = cm->allow_high_precision_mv;
int_mv nearestmv[2], nearmv[2];
int_mv ref_mvs[MAX_REF_FRAMES][MAX_MV_REF_CANDIDATES];
int_mv ref_mvs[MODE_CTX_REF_FRAMES][MAX_MV_REF_CANDIDATES];
int ref, is_compound;
int16_t inter_mode_ctx[MAX_REF_FRAMES];
int16_t inter_mode_ctx[MODE_CTX_REF_FRAMES];
int16_t mode_ctx = 0;
MV_REFERENCE_FRAME ref_frame;
......@@ -584,7 +584,7 @@ static void read_inter_block_mode_info(AV1Decoder *const pbi,
av1_setup_pre_planes(xd, ref, ref_buf->buf, mi_row, mi_col, &ref_buf->sf);
}
for (ref_frame = LAST_FRAME; ref_frame < MAX_REF_FRAMES; ++ref_frame) {
for (ref_frame = LAST_FRAME; ref_frame < MODE_CTX_REF_FRAMES; ++ref_frame) {
av1_find_mv_refs(cm, xd, mi, ref_frame,
#if CONFIG_REF_MV
&xd->ref_mv_count[ref_frame],
......@@ -594,11 +594,11 @@ static void read_inter_block_mode_info(AV1Decoder *const pbi,
fpm_sync, (void *)pbi, inter_mode_ctx);
}
mode_ctx = inter_mode_ctx[mbmi->ref_frame[0]];
#if CONFIG_REF_MV
mode_ctx = av1_mode_context_analyzer(inter_mode_ctx,
mbmi->ref_frame, bsize, -1);
#else
mode_ctx = inter_mode_ctx[mbmi->ref_frame[0]];
#endif
if (segfeature_active(&cm->seg, mbmi->segment_id, SEG_LVL_SKIP)) {
......@@ -621,6 +621,35 @@ static void read_inter_block_mode_info(AV1Decoder *const pbi,
}
}
#if CONFIG_REF_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);
if (xd->ref_mv_count[ref_frame_type] == 1 && mbmi->mode == NEARESTMV) {
int i;
nearestmv[0] = xd->ref_mv_stack[ref_frame_type][0].this_mv;
nearestmv[1] = xd->ref_mv_stack[ref_frame_type][0].comp_mv;
for (i = 0; i < MAX_MV_REF_CANDIDATES; ++i)
lower_mv_precision(&nearestmv[i].as_mv, allow_hp);
}
if (xd->ref_mv_count[ref_frame_type] > 1) {
int i;
nearestmv[0] = xd->ref_mv_stack[ref_frame_type][0].this_mv;
nearestmv[1] = xd->ref_mv_stack[ref_frame_type][0].comp_mv;
nearmv[0] = xd->ref_mv_stack[ref_frame_type][1].this_mv;
nearmv[1] = xd->ref_mv_stack[ref_frame_type][1].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);
}
}
}
#endif
mbmi->interp_filter = (cm->interp_filter == SWITCHABLE)
? read_switchable_interp_filter(cm, xd, r)
: cm->interp_filter;
......
......@@ -52,11 +52,11 @@ typedef unsigned int av1_coeff_cost[PLANE_TYPES][REF_TYPES][COEF_BANDS][2]
[COEFF_CONTEXTS][ENTROPY_TOKENS];
typedef struct {
int_mv ref_mvs[MAX_REF_FRAMES][MAX_MV_REF_CANDIDATES];
int16_t mode_context[MAX_REF_FRAMES];
int_mv ref_mvs[MODE_CTX_REF_FRAMES][MAX_MV_REF_CANDIDATES];
int16_t mode_context[MODE_CTX_REF_FRAMES];
#if CONFIG_REF_MV
uint8_t ref_mv_count[MAX_REF_FRAMES];
CANDIDATE_MV ref_mv_stack[MAX_REF_FRAMES][MAX_REF_MV_STACK_SIZE];
uint8_t ref_mv_count[MODE_CTX_REF_FRAMES];
CANDIDATE_MV ref_mv_stack[MODE_CTX_REF_FRAMES][MAX_REF_MV_STACK_SIZE];
#endif
} MB_MODE_INFO_EXT;
......
......@@ -2459,6 +2459,40 @@ static int64_t handle_inter_mode(
mbmi->mv[i].as_int = cur_mv[i].as_int;
}
#if CONFIG_REF_MV
if (this_mode == NEARESTMV && is_comp_pred) {
uint8_t ref_frame_type = av1_ref_frame_type(mbmi->ref_frame);
if (mbmi_ext->ref_mv_count[ref_frame_type] > 0) {
cur_mv[0] = mbmi_ext->ref_mv_stack[ref_frame_type][0].this_mv;
cur_mv[1] = mbmi_ext->ref_mv_stack[ref_frame_type][0].comp_mv;
for (i = 0; i < 2; ++i) {
lower_mv_precision(&cur_mv[i].as_mv, cm->allow_high_precision_mv);
clamp_mv2(&cur_mv[i].as_mv, xd);
if (mv_check_bounds(x, &cur_mv[i].as_mv))
return INT64_MAX;
mbmi->mv[i].as_int = cur_mv[i].as_int;
}
}
}
if (this_mode == NEARMV && is_comp_pred) {
uint8_t ref_frame_type = av1_ref_frame_type(mbmi->ref_frame);
if (mbmi_ext->ref_mv_count[ref_frame_type] > 1) {
cur_mv[0] = mbmi_ext->ref_mv_stack[ref_frame_type][1].this_mv;
cur_mv[1] = mbmi_ext->ref_mv_stack[ref_frame_type][1].comp_mv;
for (i = 0; i < 2; ++i) {
lower_mv_precision(&cur_mv[i].as_mv, cm->allow_high_precision_mv);
clamp_mv2(&cur_mv[i].as_mv, xd);
if (mv_check_bounds(x, &cur_mv[i].as_mv))
return INT64_MAX;
mbmi->mv[i].as_int = cur_mv[i].as_int;
}
}
}
#endif
// do first prediction into the destination buffer. Do the next
// prediction into a temporary buffer. Then keep track of which one
// of these currently holds the best predictor, and use the other
......@@ -2864,10 +2898,10 @@ int av1_active_edge_sb(AV1_COMP *cpi, int mi_row, int mi_col) {
}
void av1_rd_pick_inter_mode_sb(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;
......@@ -2950,6 +2984,19 @@ void av1_rd_pick_inter_mode_sb(AV1_COMP *cpi, TileDataEnc *tile_data,
frame_mv[ZEROMV][ref_frame].as_int = 0;
}
#if CONFIG_REF_MV
for (; ref_frame < MODE_CTX_REF_FRAMES; ++ref_frame) {
MODE_INFO *const mi = xd->mi[0];
int_mv *const candidates = x->mbmi_ext->ref_mvs[ref_frame];
x->mbmi_ext->mode_context[ref_frame] = 0;
av1_find_mv_refs(cm, xd, mi, ref_frame,
&mbmi_ext->ref_mv_count[ref_frame],
mbmi_ext->ref_mv_stack[ref_frame],
candidates, mi_row, mi_col,
NULL, NULL, mbmi_ext->mode_context);
}
#endif
for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) {
if (!(cpi->ref_frame_flags & flag_list[ref_frame])) {
// Skip checking missing references in both single and compound reference
......@@ -3367,7 +3414,49 @@ void av1_rd_pick_inter_mode_sb(AV1_COMP *cpi, TileDataEnc *tile_data,
const MV_REFERENCE_FRAME refs[2] = { best_mbmode.ref_frame[0],
best_mbmode.ref_frame[1] };
int comp_pred_mode = refs[1] > INTRA_FRAME;
#if CONFIG_REF_MV
if (!comp_pred_mode) {
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 {
uint8_t rf_type = av1_ref_frame_type(best_mbmode.ref_frame);
int i;
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 (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) {
nearmv[0] = mbmi_ext->ref_mv_stack[rf_type][1].this_mv;
nearmv[1] = mbmi_ext->ref_mv_stack[rf_type][1].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);
}
if (nearestmv[0].as_int == best_mbmode.mv[0].as_int &&
nearestmv[1].as_int == best_mbmode.mv[1].as_int)
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;
}
#else
if (frame_mv[NEARESTMV][refs[0]].as_int == best_mbmode.mv[0].as_int &&
((comp_pred_mode &&
frame_mv[NEARESTMV][refs[1]].as_int == best_mbmode.mv[1].as_int) ||
......@@ -3382,6 +3471,7 @@ void av1_rd_pick_inter_mode_sb(AV1_COMP *cpi, TileDataEnc *tile_data,
((comp_pred_mode && best_mbmode.mv[1].as_int == 0) ||
!comp_pred_mode))
best_mbmode.mode = ZEROMV;
#endif
}
#if CONFIG_REF_MV
......
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