From: Jingning Han Date: Wed, 9 Dec 2015 17:07:39 +0000 (-0800) Subject: Enable context analyzer for inter mode entropy coding X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=387a10e3dcae530c83af31be95e8aef5064b0f5b;p=libvpx Enable context analyzer for inter mode entropy coding It allows the codec to account for certain corner cases when processing inter prediction mode entropy coding. Change-Id: Ied451f4fff26ba579f6556554b8381ff2ccd0003 --- diff --git a/vp10/common/entropymode.c b/vp10/common/entropymode.c index 02287ec7a..0048c7ca4 100644 --- a/vp10/common/entropymode.c +++ b/vp10/common/entropymode.c @@ -181,7 +181,7 @@ static const vpx_prob default_zeromv_prob[ZEROMV_MODE_CONTEXTS] = { }; static const vpx_prob default_refmv_prob[REFMV_MODE_CONTEXTS] = { - 220, 220, 200, 200, 180, 128, 1, 250, + 220, 220, 200, 200, 180, 128, 30, 220, 30, }; #endif diff --git a/vp10/common/enums.h b/vp10/common/enums.h index c283222ea..44de0a227 100644 --- a/vp10/common/enums.h +++ b/vp10/common/enums.h @@ -207,7 +207,7 @@ typedef enum { #if CONFIG_REF_MV #define NEWMV_MODE_CONTEXTS 7 #define ZEROMV_MODE_CONTEXTS 2 -#define REFMV_MODE_CONTEXTS 8 +#define REFMV_MODE_CONTEXTS 9 #define ZEROMV_OFFSET 3 #define REFMV_OFFSET 4 @@ -219,6 +219,7 @@ typedef enum { #define ALL_ZERO_FLAG_OFFSET 8 #define SKIP_NEARESTMV_OFFSET 9 #define SKIP_NEARMV_OFFSET 10 +#define SKIP_NEARESTMV_SUB8X8_OFFSET 11 #endif #define INTER_MODE_CONTEXTS 7 diff --git a/vp10/common/mvref_common.c b/vp10/common/mvref_common.c index c62e8acc0..319ef4a7e 100644 --- a/vp10/common/mvref_common.c +++ b/vp10/common/mvref_common.c @@ -216,7 +216,7 @@ static int has_top_right(const MACROBLOCKD *xd, } static void handle_sec_rect_block(const MB_MODE_INFO * const candidate, - uint8_t *refmv_count, + uint8_t refmv_count, CANDIDATE_MV *ref_mv_stack, MV_REFERENCE_FRAME ref_frame, int16_t *mode_context) { @@ -224,7 +224,7 @@ static void handle_sec_rect_block(const MB_MODE_INFO * const candidate, for (rf = 0; rf < 2; ++rf) { if (candidate->ref_frame[rf] == ref_frame) { - const int list_range = VPXMIN(*refmv_count, MAX_MV_REF_CANDIDATES); + const int list_range = VPXMIN(refmv_count, MAX_MV_REF_CANDIDATES); const int_mv pred_mv = candidate->mv[rf]; for (idx = 0; idx < list_range; ++idx) @@ -232,15 +232,10 @@ static void handle_sec_rect_block(const MB_MODE_INFO * const candidate, break; if (idx < list_range) { - mode_context[ref_frame] &= ~(0x0f << REFMV_OFFSET); - - if (idx == 0) { + if (idx == 0) mode_context[ref_frame] |= (1 << SKIP_NEARESTMV_OFFSET); - mode_context[ref_frame] |= (6 << REFMV_OFFSET); - } else if (idx == 1) { + else if (idx == 1) mode_context[ref_frame] |= (1 << SKIP_NEARMV_OFFSET); - mode_context[ref_frame] |= (7 << REFMV_OFFSET); - } } } } @@ -417,14 +412,14 @@ static void setup_ref_mv_list(const VP10_COMMON *cm, const MACROBLOCKD *xd, if (xd->n8_w < xd->n8_h) { const MODE_INFO *const candidate_mi = xd->mi[-1]; const MB_MODE_INFO *const candidate = &candidate_mi->mbmi; - handle_sec_rect_block(candidate, refmv_count, ref_mv_stack, + handle_sec_rect_block(candidate, nearest_refmv_count, ref_mv_stack, ref_frame, mode_context); } if (xd->n8_w > xd->n8_h) { const MODE_INFO *const candidate_mi = xd->mi[-xd->mi_stride]; const MB_MODE_INFO *const candidate = &candidate_mi->mbmi; - handle_sec_rect_block(candidate, refmv_count, ref_mv_stack, + handle_sec_rect_block(candidate, nearest_refmv_count, ref_mv_stack, ref_frame, mode_context); } } diff --git a/vp10/common/mvref_common.h b/vp10/common/mvref_common.h index c5b40c313..396846906 100644 --- a/vp10/common/mvref_common.h +++ b/vp10/common/mvref_common.h @@ -195,6 +195,29 @@ static INLINE int is_inside(const TileInfo *const tile, mi_col + mi_pos->col >= tile->mi_col_end); } +#if CONFIG_REF_MV +static int16_t vp10_mode_context_analyzer(const int16_t *const mode_context, + const MV_REFERENCE_FRAME *const rf, + BLOCK_SIZE bsize, int block) { + int16_t mode_ctx = 0; + if (block >= 0) { + mode_ctx = mode_context[rf[0]] & 0x00ff; + + if (block > 0 && bsize < BLOCK_8X8 && bsize > BLOCK_4X4) + mode_ctx |= (1 << SKIP_NEARESTMV_SUB8X8_OFFSET); + + return mode_ctx; + } + + if (rf[1] > INTRA_FRAME) + return mode_context[rf[0]] & (mode_context[rf[1]] | 0x00ff); + else if (rf[0] != ALTREF_FRAME) + return mode_context[rf[0]] & ~(mode_context[ALTREF_FRAME] & 0xfe00); + else + return mode_context[rf[0]]; +} +#endif + typedef void (*find_mv_refs_sync)(void *const data, int mi_row); void vp10_find_mv_refs(const VP10_COMMON *cm, const MACROBLOCKD *xd, MODE_INFO *mi, MV_REFERENCE_FRAME ref_frame, diff --git a/vp10/decoder/decodemv.c b/vp10/decoder/decodemv.c index f41085a3d..f4386e488 100644 --- a/vp10/decoder/decodemv.c +++ b/vp10/decoder/decodemv.c @@ -92,6 +92,14 @@ static PREDICTION_MODE read_inter_mode(VP10_COMMON *cm, MACROBLOCKD *xd, ++counts->zeromv_mode[mode_ctx][1]; mode_ctx = (ctx >> REFMV_OFFSET) & REFMV_CTX_MASK; + + if (ctx & (1 << SKIP_NEARESTMV_OFFSET)) + mode_ctx = 6; + if (ctx & (1 << SKIP_NEARMV_OFFSET)) + mode_ctx = 7; + if (ctx & (1 << SKIP_NEARESTMV_SUB8X8_OFFSET)) + mode_ctx = 8; + mode_prob = cm->fc->refmv_prob[mode_ctx]; if (vpx_read(r, mode_prob) == 0) { @@ -820,12 +828,13 @@ static void read_inter_block_mode_info(VP10Decoder *const pbi, int ref, is_compound; int16_t inter_mode_ctx[MAX_REF_FRAMES]; int16_t mode_ctx = 0; + MV_REFERENCE_FRAME ref_frame; read_ref_frames(cm, xd, r, mbmi->segment_id, mbmi->ref_frame); is_compound = has_second_ref(mbmi); for (ref = 0; ref < 1 + is_compound; ++ref) { - const MV_REFERENCE_FRAME frame = mbmi->ref_frame[ref]; + MV_REFERENCE_FRAME frame = mbmi->ref_frame[ref]; RefBuffer *ref_buf = &cm->frame_refs[frame - LAST_FRAME]; xd->block_refs[ref] = ref_buf; @@ -834,22 +843,23 @@ static void read_inter_block_mode_info(VP10Decoder *const pbi, "Reference frame has invalid dimensions"); vp10_setup_pre_planes(xd, ref, ref_buf->buf, mi_row, mi_col, &ref_buf->sf); - vp10_find_mv_refs(cm, xd, mi, frame, + } + + for (ref_frame = LAST_FRAME; ref_frame < MAX_REF_FRAMES; ++ref_frame) { + vp10_find_mv_refs(cm, xd, mi, ref_frame, #if CONFIG_REF_MV - &xd->ref_mv_count[frame], - xd->ref_mv_stack[frame], + &xd->ref_mv_count[ref_frame], + xd->ref_mv_stack[ref_frame], #endif - ref_mvs[frame], + ref_mvs[ref_frame], mi_row, mi_col, fpm_sync, (void *)pbi, inter_mode_ctx); } mode_ctx = inter_mode_ctx[mbmi->ref_frame[0]]; #if CONFIG_REF_MV - if (mbmi->ref_frame[1] > NONE) - mode_ctx &= (inter_mode_ctx[mbmi->ref_frame[1]] | 0x00ff); - if (bsize < BLOCK_8X8) - mode_ctx &= 0x00ff; + mode_ctx = vp10_mode_context_analyzer(inter_mode_ctx, + mbmi->ref_frame, bsize, -1); #endif if (segfeature_active(&cm->seg, mbmi->segment_id, SEG_LVL_SKIP)) { @@ -887,6 +897,10 @@ static void read_inter_block_mode_info(VP10Decoder *const pbi, for (idx = 0; idx < 2; idx += num_4x4_w) { int_mv block[2]; const int j = idy * 2 + idx; +#if CONFIG_REF_MV + mode_ctx = vp10_mode_context_analyzer(inter_mode_ctx, mbmi->ref_frame, + bsize, j); +#endif b_mode = read_inter_mode(cm, xd, r, mode_ctx); if (b_mode == NEARESTMV || b_mode == NEARMV) { diff --git a/vp10/encoder/bitstream.c b/vp10/encoder/bitstream.c index 11fa85480..4c0c6af22 100644 --- a/vp10/encoder/bitstream.c +++ b/vp10/encoder/bitstream.c @@ -131,8 +131,17 @@ static void write_inter_mode(VP10_COMMON *cm, vpx_write(w, mode != ZEROMV, zeromv_prob); if (mode != ZEROMV) { - const int16_t refmv_ctx = (mode_ctx >> REFMV_OFFSET) & REFMV_CTX_MASK; - const vpx_prob refmv_prob = cm->fc->refmv_prob[refmv_ctx]; + int16_t refmv_ctx = (mode_ctx >> REFMV_OFFSET) & REFMV_CTX_MASK; + vpx_prob refmv_prob; + + if (mode_ctx & (1 << SKIP_NEARESTMV_OFFSET)) + refmv_ctx = 6; + if (mode_ctx & (1 << SKIP_NEARMV_OFFSET)) + refmv_ctx = 7; + if (mode_ctx & (1 << SKIP_NEARESTMV_SUB8X8_OFFSET)) + refmv_ctx = 8; + + refmv_prob = cm->fc->refmv_prob[refmv_ctx]; vpx_write(w, mode != NEARESTMV, refmv_prob); } } @@ -776,10 +785,8 @@ static void pack_inter_mode_mvs(VP10_COMP *cpi, const MODE_INFO *mi, write_ref_frames(cm, xd, w); #if CONFIG_REF_MV - if (mbmi->ref_frame[1] > NONE) - mode_ctx &= (mbmi_ext->mode_context[mbmi->ref_frame[1]] | 0x00ff); - if (bsize < BLOCK_8X8) - mode_ctx &= 0x00ff; + mode_ctx = vp10_mode_context_analyzer(mbmi_ext->mode_context, + mbmi->ref_frame, bsize, -1); #endif // If segment skip is not enabled code the mode. @@ -801,6 +808,10 @@ static void pack_inter_mode_mvs(VP10_COMP *cpi, const MODE_INFO *mi, for (idx = 0; idx < 2; idx += num_4x4_w) { const int j = idy * 2 + idx; const PREDICTION_MODE b_mode = mi->bmi[j].as_mode; +#if CONFIG_REF_MV + mode_ctx = vp10_mode_context_analyzer(mbmi_ext->mode_context, + mbmi->ref_frame, bsize, j); +#endif write_inter_mode(cm, w, b_mode, mode_ctx); if (b_mode == NEWMV) { for (ref = 0; ref < 1 + is_compound; ++ref) diff --git a/vp10/encoder/encodeframe.c b/vp10/encoder/encodeframe.c index 1e4ed4b41..e516a5f9f 100644 --- a/vp10/encoder/encodeframe.c +++ b/vp10/encoder/encodeframe.c @@ -1687,6 +1687,14 @@ static void update_inter_mode_stats(FRAME_COUNTS *counts, } else { ++counts->zeromv_mode[mode_ctx][1]; mode_ctx = (mode_context >> REFMV_OFFSET) & REFMV_CTX_MASK; + + if (mode_context & (1 << SKIP_NEARESTMV_OFFSET)) + mode_ctx = 6; + if (mode_context & (1 << SKIP_NEARMV_OFFSET)) + mode_ctx = 7; + if (mode_context & (1 << SKIP_NEARESTMV_SUB8X8_OFFSET)) + mode_ctx = 8; + ++counts->refmv_mode[mode_ctx][mode != NEARESTMV]; } } @@ -1779,8 +1787,8 @@ static void update_stats(VP10_COMMON *cm, ThreadData *td if (bsize >= BLOCK_8X8) { const PREDICTION_MODE mode = mbmi->mode; #if CONFIG_REF_MV - if (mbmi->ref_frame[1] > NONE) - mode_ctx &= (mbmi_ext->mode_context[mbmi->ref_frame[1]] | 0x00ff); + mode_ctx = vp10_mode_context_analyzer(mbmi_ext->mode_context, + mbmi->ref_frame, bsize, -1); update_inter_mode_stats(counts, mode, mode_ctx); #else ++counts->inter_mode[mode_ctx][INTER_OFFSET(mode)]; @@ -1794,7 +1802,8 @@ static void update_stats(VP10_COMMON *cm, ThreadData *td const int j = idy * 2 + idx; const PREDICTION_MODE b_mode = mi->bmi[j].as_mode; #if CONFIG_REF_MV - mode_ctx &= 0x00ff; + mode_ctx = vp10_mode_context_analyzer(mbmi_ext->mode_context, + mbmi->ref_frame, bsize, j); update_inter_mode_stats(counts, b_mode, mode_ctx); #else ++counts->inter_mode[mode_ctx][INTER_OFFSET(b_mode)]; diff --git a/vp10/encoder/encoder.c b/vp10/encoder/encoder.c index a3982e3ce..6d0fd197f 100644 --- a/vp10/encoder/encoder.c +++ b/vp10/encoder/encoder.c @@ -3340,7 +3340,6 @@ static void encode_with_recode_loop(VP10_COMP *cpi, // update_base_skip_probs(cpi); vpx_clear_system_state(); - // Dummy pack of the bitstream using up to date stats to get an // accurate estimate of output frame size to determine if we need // to recode. diff --git a/vp10/encoder/rdopt.c b/vp10/encoder/rdopt.c index bd7be7f38..d457199cc 100644 --- a/vp10/encoder/rdopt.c +++ b/vp10/encoder/rdopt.c @@ -3099,6 +3099,14 @@ static int cost_mv_ref(const VP10_COMP *cpi, PREDICTION_MODE mode, } else { mode_cost += cpi->zeromv_mode_cost[mode_ctx][1]; mode_ctx = (mode_context >> REFMV_OFFSET) & REFMV_CTX_MASK; + + if (mode_context & (1 << SKIP_NEARESTMV_OFFSET)) + mode_ctx = 6; + if (mode_context & (1 << SKIP_NEARMV_OFFSET)) + mode_ctx = 7; + if (mode_context & (1 << SKIP_NEARESTMV_SUB8X8_OFFSET)) + mode_ctx = 8; + mode_cost += cpi->refmv_mode_cost[mode_ctx][mode != NEARESTMV]; return mode_cost; } @@ -3163,7 +3171,8 @@ static int set_and_cost_bmi_mvs(VP10_COMP *cpi, MACROBLOCK *x, MACROBLOCKD *xd, memmove(&mic->bmi[i + idy * 2 + idx], &mic->bmi[i], sizeof(mic->bmi[i])); #if CONFIG_REF_MV - mode_ctx &= 0x00ff; + mode_ctx = vp10_mode_context_analyzer(mbmi_ext->mode_context, + mbmi->ref_frame, mbmi->sb_type, i); #endif return cost_mv_ref(cpi, mode, mode_ctx) + thismvcost; } @@ -3348,14 +3357,15 @@ static INLINE void mi_buf_restore(MACROBLOCK *x, struct buf_2d orig_src, static int check_best_zero_mv( const VP10_COMP *cpi, const int16_t mode_context[MAX_REF_FRAMES], int_mv frame_mv[MB_MODE_COUNT][MAX_REF_FRAMES], int this_mode, - const MV_REFERENCE_FRAME ref_frames[2]) { + const MV_REFERENCE_FRAME ref_frames[2], + const BLOCK_SIZE bsize, int block) { if ((this_mode == NEARMV || this_mode == NEARESTMV || this_mode == ZEROMV) && frame_mv[this_mode][ref_frames[0]].as_int == 0 && (ref_frames[1] == NONE || frame_mv[this_mode][ref_frames[1]].as_int == 0)) { #if CONFIG_REF_MV - int16_t rfc = (ref_frames[1] == NONE) ? mode_context[ref_frames[0]] : - mode_context[ref_frames[0]] & (mode_context[ref_frames[1]] | 0x00ff); + int16_t rfc = vp10_mode_context_analyzer(mode_context, + ref_frames, bsize, block); #else int16_t rfc = mode_context[ref_frames[0]]; #endif @@ -3363,6 +3373,11 @@ static int check_best_zero_mv( int c2 = cost_mv_ref(cpi, NEARESTMV, rfc); int c3 = cost_mv_ref(cpi, ZEROMV, rfc); +#if !CONFIG_REF_MV + (void)bsize; + (void)block; +#endif + if (this_mode == NEARMV) { if (c1 > c3) return 0; } else if (this_mode == NEARESTMV) { @@ -3656,7 +3671,7 @@ static int64_t rd_pick_best_sub8x8_mode(VP10_COMP *cpi, MACROBLOCK *x, continue; if (!check_best_zero_mv(cpi, mbmi_ext->mode_context, frame_mv, - this_mode, mbmi->ref_frame)) + this_mode, mbmi->ref_frame, bsize, i)) continue; memcpy(orig_pre, pd->pre, sizeof(orig_pre)); @@ -4261,8 +4276,6 @@ static void single_motion_search(VP10_COMP *cpi, MACROBLOCK *x, } } - - static INLINE void restore_dst_buf(MACROBLOCKD *xd, uint8_t *orig_dst[MAX_MB_PLANE], int orig_dst_stride[MAX_MB_PLANE]) { @@ -4360,8 +4373,8 @@ static int64_t handle_inter_mode(VP10_COMP *cpi, MACROBLOCK *x, int16_t mode_ctx = mbmi_ext->mode_context[refs[0]]; #if CONFIG_REF_MV - if (refs[1] > NONE) - mode_ctx &= (mbmi_ext->mode_context[refs[1]] | 0x00ff); + mode_ctx = vp10_mode_context_analyzer(mbmi_ext->mode_context, + mbmi->ref_frame, bsize, -1); #endif #if CONFIG_VP9_HIGHBITDEPTH @@ -5012,6 +5025,7 @@ void vp10_rd_pick_inter_mode_sb(VP10_COMP *cpi, for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) { x->pred_mv_sad[ref_frame] = INT_MAX; + x->mbmi_ext->mode_context[ref_frame] = 0; if (cpi->ref_frame_flags & flag_list[ref_frame]) { assert(get_ref_frame_buffer(cpi, ref_frame) != NULL); setup_buffer_inter(cpi, x, ref_frame, bsize, mi_row, mi_col, @@ -5243,7 +5257,7 @@ void vp10_rd_pick_inter_mode_sb(VP10_COMP *cpi, } else { const MV_REFERENCE_FRAME ref_frames[2] = {ref_frame, second_ref_frame}; if (!check_best_zero_mv(cpi, mbmi_ext->mode_context, frame_mv, - this_mode, ref_frames)) + this_mode, ref_frames, bsize, -1)) continue; } @@ -5923,6 +5937,7 @@ void vp10_rd_pick_inter_mode_sub8x8(struct VP10_COMP *cpi, #endif for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ref_frame++) { + x->mbmi_ext->mode_context[ref_frame] = 0; if (cpi->ref_frame_flags & flag_list[ref_frame]) { setup_buffer_inter(cpi, x, ref_frame, bsize, mi_row, mi_col, frame_mv[NEARESTMV], frame_mv[NEARMV],