Commit 253a200d authored by Jingning Han's avatar Jingning Han
Browse files

Refactor ref mv stack system

This commit re-works the reference motion vector stack process
and make it support extended context set. It unifies reference
motion vector checking process for row and column scan, as well as
for single block scan.

Change-Id: I68c05cde93cf8b0ca2ef4d1523399f405bd0a337
parent 387a10e3
......@@ -83,6 +83,10 @@ typedef struct {
typedef int8_t MV_REFERENCE_FRAME;
#if CONFIG_REF_MV
#define MODE_CTX_REF_FRAMES (MAX_REF_FRAMES + (ALTREF_FRAME - LAST_FRAME))
#endif
typedef struct {
// Number of base colors for Y (0) and UV (1)
uint8_t palette_size[2];
......
......@@ -37,6 +37,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
......
......@@ -12,34 +12,43 @@
#include "vp10/common/mvref_common.h"
#if CONFIG_REF_MV
static uint8_t scan_row_mbmi(const VP10_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) {
const int weight = len;
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 * weight;
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 = &candidate_mi->mbmi;
const int len = VPXMIN(xd->n8_w,
num_8x8_blocks_wide_lookup[candidate->sb_type]);
const int weight = len;
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 * weight;
++(*refmv_count);
for (ref = 0; ref < 2; ++ref) {
if (candidate->ref_frame[ref] == ref_frame) {
int_mv this_refmv =
get_sub_block_mv(candidate_mi, ref, mi_pos.col, block);
if (candidate->mode == NEWMV)
++newmv_count;
}
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;
......@@ -58,6 +67,89 @@ static uint8_t scan_row_mbmi(const VP10_COMMON *cm, const MACROBLOCKD *xd,
}
}
}
}
} 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 * weight;
// 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 * weight;
++(*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 += weight;
// 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 = weight;
++(*refmv_count);
if (candidate->mode == NEWMV)
++newmv_count;
}
}
}
}
return newmv_count;
}
static uint8_t scan_row_mbmi(const VP10_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 = &candidate_mi->mbmi;
const int len = VPXMIN(xd->n8_w,
num_8x8_blocks_wide_lookup[candidate->sb_type]);
newmv_count += add_ref_mv_candidate(candidate_mi, candidate, rf,
refmv_count, ref_mv_stack, len,
block, mi_pos.col);
i += len;
} else {
++i;
......@@ -69,7 +161,7 @@ static uint8_t scan_row_mbmi(const VP10_COMMON *cm, const MACROBLOCKD *xd,
static uint8_t scan_col_mbmi(const VP10_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) {
......@@ -88,30 +180,10 @@ static uint8_t scan_col_mbmi(const VP10_COMMON *cm, const MACROBLOCKD *xd,
const MB_MODE_INFO *const candidate = &candidate_mi->mbmi;
const int len = VPXMIN(xd->n8_h,
num_8x8_blocks_high_lookup[candidate->sb_type]);
const int weight = len;
int index = 0, ref;
for (ref = 0; ref < 2; ++ref) {
if (candidate->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 += weight;
if (index == *refmv_count) {
ref_mv_stack[index].this_mv = this_refmv;
ref_mv_stack[index].weight = weight;
++(*refmv_count);
if (candidate->mode == NEWMV)
++newmv_count;
}
}
}
newmv_count += add_ref_mv_candidate(candidate_mi, candidate, rf,
refmv_count, ref_mv_stack, len,
block, mi_pos.col);
i += len;
} else {
++i;
......@@ -123,7 +195,7 @@ static uint8_t scan_col_mbmi(const VP10_COMMON *cm, const MACROBLOCKD *xd,
static uint8_t scan_blk_mbmi(const VP10_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) {
......@@ -140,49 +212,10 @@ static uint8_t scan_blk_mbmi(const VP10_COMMON *cm, const MACROBLOCKD *xd,
xd->mi[mi_pos.row * xd->mi_stride + mi_pos.col];
const MB_MODE_INFO *const candidate = &candidate_mi->mbmi;
const int len = 1;
const int weight = len;
int index = 0, ref;
for (ref = 0; ref < 2; ++ref) {
if (candidate->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 += weight;
if (index == *refmv_count) {
ref_mv_stack[index].this_mv = this_refmv;
ref_mv_stack[index].weight = weight;
++(*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 =
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 += weight;
// Add a new item to the list.
if (index == *refmv_count) {
ref_mv_stack[index].this_mv = this_refmv;
ref_mv_stack[index].weight = weight;
++(*refmv_count);
}
}
}
}
newmv_count += add_ref_mv_candidate(candidate_mi, candidate, rf,
refmv_count, ref_mv_stack, len,
block, mi_pos.col);
} // Analyze a single 8x8 block motion information.
return newmv_count;
}
......@@ -260,19 +293,22 @@ static void setup_ref_mv_list(const VP10_COMMON *cm, const MACROBLOCKD *xd,
int bs = VPXMAX(xd->n8_w, xd->n8_h);
int has_tr = has_top_right(xd, mi_row, mi_col, bs);
MV_REFERENCE_FRAME rf[2];
vp10_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;
......@@ -301,12 +337,12 @@ static void setup_ref_mv_list(const VP10_COMMON *cm, const MACROBLOCKD *xd,
break;
if (idx < *refmv_count)
ref_mv_stack[idx].weight += 1;
ref_mv_stack[idx].weight += 2;
if (idx == *refmv_count &&
*refmv_count < MAX_REF_MV_STACK_SIZE) {
ref_mv_stack[idx].this_mv.as_int = prev_frame_mvs->mv[ref].as_int;
ref_mv_stack[idx].weight = 1;
ref_mv_stack[idx].weight = 2;
++(*refmv_count);
if (abs(ref_mv_stack[idx].this_mv.as_mv.row) >= 8 ||
......@@ -327,22 +363,22 @@ static void setup_ref_mv_list(const VP10_COMMON *cm, const MACROBLOCKD *xd,
// -1, -1, ref_mv_stack, refmv_count);
// Scan the second outer area.
scan_row_mbmi(cm, xd, mi_row, mi_col, block, ref_frame,
scan_row_mbmi(cm, xd, mi_row, mi_col, block, rf,
-2, 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,
-2, ref_mv_stack, refmv_count);
// Scan the third outer area.
scan_row_mbmi(cm, xd, mi_row, mi_col, block, ref_frame,
scan_row_mbmi(cm, xd, mi_row, mi_col, block, rf,
-3, 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,
-3, ref_mv_stack, refmv_count);
// Scan the fourth outer area.
scan_row_mbmi(cm, xd, mi_row, mi_col, block, ref_frame,
scan_row_mbmi(cm, xd, mi_row, mi_col, block, rf,
-4, ref_mv_stack, refmv_count);
// Scan the third left row mode info.
scan_col_mbmi(cm, xd, mi_row, mi_col, block, ref_frame,
scan_col_mbmi(cm, xd, mi_row, mi_col, block, rf,
-4, ref_mv_stack, refmv_count);
switch (nearest_refmv_count) {
......@@ -630,6 +666,7 @@ void vp10_append_sub8x8_mvs_for_idx(VP10_COMMON *cm, MACROBLOCKD *xd,
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);
......@@ -638,11 +675,11 @@ void vp10_append_sub8x8_mvs_for_idx(VP10_COMMON *cm, MACROBLOCKD *xd,
mi_row, 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;
......
......@@ -196,6 +196,24 @@ static INLINE int is_inside(const TileInfo *const tile,
}
#if CONFIG_REF_MV
static int8_t vp10_ref_frame_type(const MV_REFERENCE_FRAME *const rf) {
if (rf[1] > INTRA_FRAME)
return rf[0] + ALTREF_FRAME;
return rf[0];
}
static void vp10_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 vp10_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