Commit aeb60057 authored by Jingning Han's avatar Jingning Han

Refactor reference motion vector search process

Unify the reference motion vector candidate search for row, column,
and single block cases. Make it support later extended reference
frame contexts.

Change-Id: I1278a9f1ed8561eccc8460b4edff4b97d438ad9b
parent 3b4479eb
......@@ -38,6 +38,7 @@ typedef struct mv32 {
#if CONFIG_REF_MV
typedef struct candidate_mv {
int_mv this_mv;
int_mv comp_mv;
int weight;
} CANDIDATE_MV;
#endif
......
......@@ -11,33 +11,42 @@
#include "av1/common/mvref_common.h"
#if CONFIG_REF_MV
static uint8_t scan_row_mbmi(const AV1_COMMON *cm, const MACROBLOCKD *xd,
const int mi_row, const int mi_col, int block,
const MV_REFERENCE_FRAME ref_frame,
int row_offset,
CANDIDATE_MV *ref_mv_stack,
uint8_t *refmv_count) {
const TileInfo *const tile = &xd->tile;
int i;
uint8_t newmv_count = 0;
static uint8_t add_ref_mv_candidate(const MODE_INFO *const candidate_mi,
const MB_MODE_INFO *const candidate,
const MV_REFERENCE_FRAME rf[2],
uint8_t *refmv_count,
CANDIDATE_MV *ref_mv_stack,
int len, int block, int col) {
int index = 0, ref;
int newmv_count = 0;
if (rf[1] == NONE) {
// single reference frame
for (ref = 0; ref < 2; ++ref) {
if (candidate->ref_frame[ref] == rf[0]) {
int_mv this_refmv =
get_sub_block_mv(candidate_mi, ref, col, block);
for (index = 0; index < *refmv_count; ++index)
if (ref_mv_stack[index].this_mv.as_int == this_refmv.as_int)
break;
for (i = 0; i < xd->n8_w && *refmv_count < MAX_REF_MV_STACK_SIZE;) {
POSITION mi_pos;
mi_pos.row = row_offset;
mi_pos.col = i;
if (index < *refmv_count)
ref_mv_stack[index].weight += 2 * len;
if (is_inside(tile, mi_col, mi_row, cm->mi_rows, &mi_pos)) {
const MODE_INFO *const candidate_mi =
xd->mi[mi_pos.row * xd->mi_stride + mi_pos.col];
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]);
int index = 0, ref;
// Add a new item to the list.
if (index == *refmv_count) {
ref_mv_stack[index].this_mv = this_refmv;
ref_mv_stack[index].weight = 2 * len;
++(*refmv_count);
if (candidate->mode == NEWMV)
++newmv_count;
}
for (ref = 0; ref < 2; ++ref) {
if (candidate_mbmi->ref_frame[ref] == ref_frame) {
int_mv this_refmv =
get_sub_block_mv(candidate_mi, ref, mi_pos.col, block);
if (candidate_mi->mbmi.sb_type < BLOCK_8X8 && block >= 0) {
int alt_block = 3 - block;
this_refmv =
get_sub_block_mv(candidate_mi, ref, col, alt_block);
for (index = 0; index < *refmv_count; ++index)
if (ref_mv_stack[index].this_mv.as_int == this_refmv.as_int)
break;
......@@ -51,11 +60,93 @@ static uint8_t scan_row_mbmi(const AV1_COMMON *cm, const MACROBLOCKD *xd,
ref_mv_stack[index].weight = len;
++(*refmv_count);
if (candidate_mbmi->mode == NEWMV)
if (candidate->mode == NEWMV)
++newmv_count;
}
}
}
}
} else {
// compound reference frame
if (candidate->ref_frame[0] == rf[0] &&
candidate->ref_frame[1] == rf[1]) {
int_mv this_refmv[2] = {
get_sub_block_mv(candidate_mi, 0, col, block),
get_sub_block_mv(candidate_mi, 1, col, block)
};
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))
break;
if (index < *refmv_count)
ref_mv_stack[index].weight += 2 * len;
// Add a new item to the list.
if (index == *refmv_count) {
ref_mv_stack[index].this_mv = this_refmv[0];
ref_mv_stack[index].comp_mv = this_refmv[1];
ref_mv_stack[index].weight = 2 * len;
++(*refmv_count);
if (candidate->mode == NEWMV)
++newmv_count;
}
if (candidate_mi->mbmi.sb_type < BLOCK_8X8 && block >= 0) {
int alt_block = 3 - block;
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 (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)
break;
if (index < *refmv_count)
ref_mv_stack[index].weight += len;
// Add a new item to the list.
if (index == *refmv_count) {
ref_mv_stack[index].this_mv = this_refmv[0];
ref_mv_stack[index].comp_mv = this_refmv[1];
ref_mv_stack[index].weight = len;
++(*refmv_count);
if (candidate->mode == NEWMV)
++newmv_count;
}
}
}
}
return newmv_count;
}
static uint8_t scan_row_mbmi(const AV1_COMMON *cm, const MACROBLOCKD *xd,
const int mi_row, const int mi_col, int block,
const MV_REFERENCE_FRAME rf[2],
int row_offset,
CANDIDATE_MV *ref_mv_stack,
uint8_t *refmv_count) {
const TileInfo *const tile = &xd->tile;
int i;
uint8_t newmv_count = 0;
for (i = 0; i < xd->n8_w && *refmv_count < MAX_REF_MV_STACK_SIZE;) {
POSITION mi_pos;
mi_pos.row = row_offset;
mi_pos.col = i;
if (is_inside(tile, mi_col, mi_row, cm->mi_rows, &mi_pos)) {
const MODE_INFO *const candidate_mi =
xd->mi[mi_pos.row * xd->mi_stride + mi_pos.col];
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,
refmv_count, ref_mv_stack, len,
block, mi_pos.col);
i += len;
} else {
++i;
......@@ -66,7 +157,7 @@ static uint8_t scan_row_mbmi(const AV1_COMMON *cm, const MACROBLOCKD *xd,
static uint8_t scan_col_mbmi(const AV1_COMMON *cm, const MACROBLOCKD *xd,
const int mi_row, const int mi_col, int block,
const MV_REFERENCE_FRAME ref_frame,
const MV_REFERENCE_FRAME rf[2],
int col_offset,
CANDIDATE_MV *ref_mv_stack,
uint8_t *refmv_count) {
......@@ -85,30 +176,9 @@ 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]);
int index = 0, ref;
for (ref = 0; ref < 2; ++ref) {
if (candidate_mbmi->ref_frame[ref] == ref_frame) {
int_mv this_refmv =
get_sub_block_mv(candidate_mi, ref, mi_pos.col, block);
for (index = 0; index < *refmv_count; ++index)
if (ref_mv_stack[index].this_mv.as_int == this_refmv.as_int)
break;
if (index < *refmv_count)
ref_mv_stack[index].weight += len;
if (index == *refmv_count) {
ref_mv_stack[index].this_mv = this_refmv;
ref_mv_stack[index].weight = len;
++(*refmv_count);
if (candidate_mbmi->mode == NEWMV)
++newmv_count;
}
}
}
newmv_count += add_ref_mv_candidate(candidate_mi, candidate_mbmi, rf,
refmv_count, ref_mv_stack, len,
block, mi_pos.col);
i += len;
} else {
++i;
......@@ -119,7 +189,7 @@ static uint8_t scan_col_mbmi(const AV1_COMMON *cm, const MACROBLOCKD *xd,
static uint8_t scan_blk_mbmi(const AV1_COMMON *cm, const MACROBLOCKD *xd,
const int mi_row, const int mi_col, int block,
const MV_REFERENCE_FRAME ref_frame,
const MV_REFERENCE_FRAME rf[2],
int row_offset, int col_offset,
CANDIDATE_MV *ref_mv_stack,
uint8_t *refmv_count) {
......@@ -136,51 +206,9 @@ 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;
int index = 0, ref;
for (ref = 0; ref < 2; ++ref) {
if (candidate_mbmi->ref_frame[ref] == ref_frame) {
int_mv this_refmv =
get_sub_block_mv(candidate_mi, ref, mi_pos.col, block);
for (index = 0; index < *refmv_count; ++index)
if (ref_mv_stack[index].this_mv.as_int == this_refmv.as_int)
break;
if (index < *refmv_count)
ref_mv_stack[index].weight += len;
if (index == *refmv_count) {
ref_mv_stack[index].this_mv = this_refmv;
ref_mv_stack[index].weight = len;
++(*refmv_count);
if (candidate_mbmi->mode == NEWMV)
++newmv_count;
}
if (candidate_mi->mbmi.sb_type < BLOCK_8X8 && block >= 0) {
int alt_block = 3 - block;
assert(block <= 3);
this_refmv =
get_sub_block_mv(candidate_mi, ref, mi_pos.col, alt_block);
for (index = 0; index < *refmv_count; ++index)
if (ref_mv_stack[index].this_mv.as_int == this_refmv.as_int)
break;
if (index < *refmv_count)
ref_mv_stack[index].weight += len;
// Add a new item to the list.
if (index == *refmv_count) {
ref_mv_stack[index].this_mv = this_refmv;
ref_mv_stack[index].weight = len;
++(*refmv_count);
}
}
} // match reference frame
}
newmv_count += add_ref_mv_candidate(candidate_mi, candidate_mbmi, rf,
refmv_count, ref_mv_stack, len,
block, mi_pos.col);
} // Analyze a single 8x8 block motion information.
return newmv_count;
}
......@@ -255,21 +283,22 @@ static void setup_ref_mv_list(const AV1_COMMON *cm, const MACROBLOCKD *xd,
const int bs = AOMMAX(xd->n8_w, xd->n8_h);
const int has_tr = has_top_right(xd, mi_row, mi_col, bs);
MV_REFERENCE_FRAME rf[2];
av1_set_ref_frame(rf, ref_frame);
mode_context[ref_frame] = 0;
*refmv_count = 0;
// Scan the first above row mode info.
newmv_count += scan_row_mbmi(cm, xd, mi_row, mi_col, block, ref_frame,
newmv_count += scan_row_mbmi(cm, xd, mi_row, mi_col, block, rf,
-1, ref_mv_stack, refmv_count);
// Scan the first left column mode info.
newmv_count += scan_col_mbmi(cm, xd, mi_row, mi_col, block, ref_frame,
newmv_count += scan_col_mbmi(cm, xd, mi_row, mi_col, block, rf,
-1, ref_mv_stack, refmv_count);
// Check top-right boundary
if (has_tr)
newmv_count += scan_blk_mbmi(cm, xd, mi_row, mi_col, block, ref_frame,
newmv_count += scan_blk_mbmi(cm, xd, mi_row, mi_col, block, rf,
-1, 1, ref_mv_stack, refmv_count);
nearest_refmv_count = *refmv_count;
......@@ -307,9 +336,9 @@ static void setup_ref_mv_list(const AV1_COMMON *cm, const MACROBLOCKD *xd,
// Scan the second outer area.
for (idx = 2; idx <= 4; ++idx) {
scan_row_mbmi(cm, xd, mi_row, mi_col, block, ref_frame,
scan_row_mbmi(cm, xd, mi_row, mi_col, block, rf,
-idx, ref_mv_stack, refmv_count);
scan_col_mbmi(cm, xd, mi_row, mi_col, block, ref_frame,
scan_col_mbmi(cm, xd, mi_row, mi_col, block, rf,
-idx, ref_mv_stack, refmv_count);
}
......@@ -612,6 +641,7 @@ void av1_append_sub8x8_mvs_for_idx(AV1_COMMON *cm, MACROBLOCKD *xd, int block,
CANDIDATE_MV tmp_mv;
uint8_t ref_mv_count = 0, idx;
uint8_t above_count = 0, left_count = 0;
MV_REFERENCE_FRAME rf[2] = { mi->mbmi.ref_frame[ref], NONE };
#endif
assert(MAX_MV_REF_CANDIDATES == 2);
......@@ -620,11 +650,11 @@ void av1_append_sub8x8_mvs_for_idx(AV1_COMMON *cm, MACROBLOCKD *xd, int block,
mi_col, NULL, NULL, NULL);
#if CONFIG_REF_MV
scan_blk_mbmi(cm, xd, mi_row, mi_col, block, mi->mbmi.ref_frame[ref],
scan_blk_mbmi(cm, xd, mi_row, mi_col, block, rf,
-1, 0, ref_mv_stack, &ref_mv_count);
above_count = ref_mv_count;
scan_blk_mbmi(cm, xd, mi_row, mi_col, block, mi->mbmi.ref_frame[ref],
scan_blk_mbmi(cm, xd, mi_row, mi_col, block, rf,
0, -1, ref_mv_stack, &ref_mv_count);
left_count = ref_mv_count - above_count;
......
......@@ -303,6 +303,24 @@ static INLINE int is_inside(const TileInfo *const tile, int mi_col, int mi_row,
}
#if CONFIG_REF_MV
static int8_t av1_ref_frame_type(const MV_REFERENCE_FRAME *const rf) {
if (rf[1] > INTRA_FRAME)
return rf[0] + ALTREF_FRAME;
return rf[0];
}
static void av1_set_ref_frame(MV_REFERENCE_FRAME *rf, int8_t ref_frame_type) {
if (ref_frame_type > ALTREF_FRAME) {
rf[0] = ref_frame_type - ALTREF_FRAME;
rf[1] = ALTREF_FRAME;
} else {
rf[0] = ref_frame_type;
rf[1] = NONE;
assert(ref_frame_type > INTRA_FRAME && ref_frame_type < MAX_REF_FRAMES);
}
}
static int16_t av1_mode_context_analyzer(const int16_t *const mode_context,
const MV_REFERENCE_FRAME *const rf,
BLOCK_SIZE bsize, int block) {
......
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