From: Jingning Han Date: Sat, 12 Dec 2015 06:39:40 +0000 (-0800) Subject: Refactor ref mv stack system X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=253a200d3ba09f7803b86e16e10713374fdc7648;p=libvpx 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 --- diff --git a/vp10/common/blockd.h b/vp10/common/blockd.h index 66e29d41b..7b951486b 100644 --- a/vp10/common/blockd.h +++ b/vp10/common/blockd.h @@ -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]; diff --git a/vp10/common/mv.h b/vp10/common/mv.h index 289c591ed..904d372f9 100644 --- a/vp10/common/mv.h +++ b/vp10/common/mv.h @@ -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 diff --git a/vp10/common/mvref_common.c b/vp10/common/mvref_common.c index 319ef4a7e..cd1ea38b6 100644 --- a/vp10/common/mvref_common.c +++ b/vp10/common/mvref_common.c @@ -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; diff --git a/vp10/common/mvref_common.h b/vp10/common/mvref_common.h index 396846906..1f388c19e 100644 --- a/vp10/common/mvref_common.h +++ b/vp10/common/mvref_common.h @@ -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) {