From: Paul Wilkins Date: Mon, 12 Nov 2012 15:09:25 +0000 (+0000) Subject: New inter mode context X-Git-Tag: v1.3.0~1217^2~109^2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=2669f42b0d50bcff236176584caf623585e487b7;p=platform%2Fupstream%2Flibvpx.git New inter mode context This change is a fix / extension of the newbestrefmv experiment. As such it is presented without IFDEF. The change creates a new context for coding inter modes in vp9_find_mv_refs(). This replaces the context that was previously calculated in vp9_find_near_mvs(). The new context is unoptimized and not necessarily any better at this stage (results pending), but eliminates the need for a legacy call to vp9_find_near_mvs(). Based on numbers from Scott, this could help decode speed by several %. In a later patch I will add support for forward update of context (assuming this helps) and refine the context as necessary. Change-Id: I1cd991b82c8df86cc02237a34185e6d67510698a --- diff --git a/vp9/common/blockd.h b/vp9/common/blockd.h index 300c01f..0cfa9dc 100644 --- a/vp9/common/blockd.h +++ b/vp9/common/blockd.h @@ -231,6 +231,8 @@ typedef struct { int_mv mv[2]; // for each reference frame used int_mv ref_mvs[MAX_REF_FRAMES][MAX_MV_REFS]; + int mb_mode_context[MAX_REF_FRAMES]; + SPLITMV_PARTITIONING_TYPE partitioning; unsigned char mb_skip_coeff; /* does this mb has coefficients at all, 1=no coefficients, 0=need decode tokens */ unsigned char need_to_clamp_mvs; diff --git a/vp9/common/entropymode.c b/vp9/common/entropymode.c index 37d09db..d0e83ec 100644 --- a/vp9/common/entropymode.c +++ b/vp9/common/entropymode.c @@ -451,7 +451,7 @@ void vp9_init_mode_contexts(VP9_COMMON *pc) { void vp9_accum_mv_refs(VP9_COMMON *pc, MB_PREDICTION_MODE m, - const int ct[4]) { + const int context) { int (*mv_ref_ct)[4][2]; if (pc->refresh_alt_ref_frame) @@ -460,21 +460,21 @@ void vp9_accum_mv_refs(VP9_COMMON *pc, mv_ref_ct = pc->fc.mv_ref_ct; if (m == ZEROMV) { - ++mv_ref_ct [ct[0]] [0] [0]; + ++mv_ref_ct[context][0][0]; } else { - ++mv_ref_ct [ct[0]] [0] [1]; + ++mv_ref_ct[context][0][1]; if (m == NEARESTMV) { - ++mv_ref_ct [ct[1]] [1] [0]; + ++mv_ref_ct[context][1][0]; } else { - ++mv_ref_ct [ct[1]] [1] [1]; + ++mv_ref_ct[context][1][1]; if (m == NEARMV) { - ++mv_ref_ct [ct[2]] [2] [0]; + ++mv_ref_ct[context][2][0]; } else { - ++mv_ref_ct [ct[2]] [2] [1]; + ++mv_ref_ct[context][2][1]; if (m == NEWMV) { - ++mv_ref_ct [ct[3]] [3] [0]; + ++mv_ref_ct[context][3][0]; } else { - ++mv_ref_ct [ct[3]] [3] [1]; + ++mv_ref_ct[context][3][1]; } } } @@ -496,7 +496,7 @@ void vp9_update_mode_context(VP9_COMMON *pc) { mode_context = pc->fc.mode_context; } - for (j = 0; j < 6; j++) { + for (j = 0; j < INTER_MODE_CONTEXTS; j++) { for (i = 0; i < 4; i++) { int this_prob; int count = mv_ref_ct[j][i][0] + mv_ref_ct[j][i][1]; diff --git a/vp9/common/entropymode.h b/vp9/common/entropymode.h index 0297591..34a2bea 100644 --- a/vp9/common/entropymode.h +++ b/vp9/common/entropymode.h @@ -79,7 +79,7 @@ extern void vp9_update_mode_context(struct VP9Common *pc); extern void vp9_accum_mv_refs(struct VP9Common *pc, MB_PREDICTION_MODE m, - const int ct[4]); + const int context); void vp9_default_bmode_probs(vp9_prob dest[VP9_NKF_BINTRAMODES - 1]); diff --git a/vp9/common/findnearmv.c b/vp9/common/findnearmv.c index 84a377e..8cc0474 100644 --- a/vp9/common/findnearmv.c +++ b/vp9/common/findnearmv.c @@ -31,140 +31,13 @@ static void lower_mv_precision(int_mv *mv, int usehp) } } -/* Predict motion vectors using those from already-decoded nearby blocks. - Note that we only consider one 4x4 subblock from each candidate 16x16 - macroblock. */ - -void vp9_find_near_mvs -( - MACROBLOCKD *xd, - const MODE_INFO *here, - const MODE_INFO *lf_here, - int_mv *nearest, - int_mv *nearby, - int_mv *best_mv, - int cnt[4], - int refframe, - int *ref_frame_sign_bias) { - const MODE_INFO *above = here - xd->mode_info_stride; - const MODE_INFO *left = here - 1; - const MODE_INFO *aboveleft = above - 1; - const MODE_INFO *third = NULL; - int_mv near_mvs[4]; - int_mv *mv = near_mvs; - int *cntx = cnt; - enum {CNT_INTRA, CNT_NEAREST, CNT_NEAR, CNT_SPLITMV}; - - /* Zero accumulators */ - mv[0].as_int = mv[1].as_int = mv[2].as_int = 0; - cnt[0] = cnt[1] = cnt[2] = cnt[3] = 0; - - /* Process above */ - if (above->mbmi.ref_frame != INTRA_FRAME) { - if (above->mbmi.mv[0].as_int) { - ++ mv; - mv->as_int = above->mbmi.mv[0].as_int; - mv_bias(ref_frame_sign_bias[above->mbmi.ref_frame], - refframe, mv, ref_frame_sign_bias); - ++cntx; - } - *cntx += 2; - } - - /* Process left */ - if (left->mbmi.ref_frame != INTRA_FRAME) { - if (left->mbmi.mv[0].as_int) { - int_mv this_mv; - this_mv.as_int = left->mbmi.mv[0].as_int; - mv_bias(ref_frame_sign_bias[left->mbmi.ref_frame], - refframe, &this_mv, ref_frame_sign_bias); - - if (this_mv.as_int != mv->as_int) { - ++ mv; - mv->as_int = this_mv.as_int; - ++ cntx; - } - *cntx += 2; - } else - cnt[CNT_INTRA] += 2; - } - /* Process above left or the one from last frame */ - if (aboveleft->mbmi.ref_frame != INTRA_FRAME || - (lf_here->mbmi.ref_frame == LAST_FRAME && refframe == LAST_FRAME)) { - if (aboveleft->mbmi.mv[0].as_int) { - third = aboveleft; - } else if (lf_here->mbmi.mv[0].as_int) { - third = lf_here; - } - if (third) { - int_mv this_mv; - this_mv.as_int = third->mbmi.mv[0].as_int; - mv_bias(ref_frame_sign_bias[third->mbmi.ref_frame], - refframe, &this_mv, ref_frame_sign_bias); - - if (this_mv.as_int != mv->as_int) { - ++ mv; - mv->as_int = this_mv.as_int; - ++ cntx; - } - *cntx += 1; - } else - cnt[CNT_INTRA] += 1; - } - - /* If we have three distinct MV's ... */ - if (cnt[CNT_SPLITMV]) { - /* See if the third MV can be merged with NEAREST */ - if (mv->as_int == near_mvs[CNT_NEAREST].as_int) - cnt[CNT_NEAREST] += 1; - } - - cnt[CNT_SPLITMV] = ((above->mbmi.mode == SPLITMV) - + (left->mbmi.mode == SPLITMV)) * 2 - + ( - lf_here->mbmi.mode == SPLITMV || - aboveleft->mbmi.mode == SPLITMV); - - /* Swap near and nearest if necessary */ - if (cnt[CNT_NEAR] > cnt[CNT_NEAREST]) { - int tmp; - tmp = cnt[CNT_NEAREST]; - cnt[CNT_NEAREST] = cnt[CNT_NEAR]; - cnt[CNT_NEAR] = tmp; - tmp = near_mvs[CNT_NEAREST].as_int; - near_mvs[CNT_NEAREST].as_int = near_mvs[CNT_NEAR].as_int; - near_mvs[CNT_NEAR].as_int = tmp; - } - - /* Use near_mvs[0] to store the "best" MV */ - if (cnt[CNT_NEAREST] >= cnt[CNT_INTRA]) - near_mvs[CNT_INTRA] = near_mvs[CNT_NEAREST]; - - /* Set up return values */ - best_mv->as_int = near_mvs[0].as_int; - nearest->as_int = near_mvs[CNT_NEAREST].as_int; - nearby->as_int = near_mvs[CNT_NEAR].as_int; - - /* Make sure that the 1/8th bits of the Mvs are zero if high_precision - * is not being used, by truncating the last bit towards 0 - */ - lower_mv_precision(best_mv, xd->allow_high_precision_mv); - lower_mv_precision(nearest, xd->allow_high_precision_mv); - lower_mv_precision(nearby, xd->allow_high_precision_mv); - - // TODO: move clamp outside findnearmv - clamp_mv2(nearest, xd); - clamp_mv2(nearby, xd); - clamp_mv2(best_mv, xd); -} - vp9_prob *vp9_mv_ref_probs(VP9_COMMON *pc, - vp9_prob p[VP9_MVREFS - 1], - const int near_mv_ref_ct[4]) { - p[0] = pc->fc.vp9_mode_contexts[near_mv_ref_ct[0]][0]; - p[1] = pc->fc.vp9_mode_contexts[near_mv_ref_ct[1]][1]; - p[2] = pc->fc.vp9_mode_contexts[near_mv_ref_ct[2]][2]; - p[3] = pc->fc.vp9_mode_contexts[near_mv_ref_ct[3]][3]; + vp9_prob p[4], const int context + ) { + p[0] = pc->fc.vp9_mode_contexts[context][0]; + p[1] = pc->fc.vp9_mode_contexts[context][1]; + p[2] = pc->fc.vp9_mode_contexts[context][2]; + p[3] = pc->fc.vp9_mode_contexts[context][3]; return p; } diff --git a/vp9/common/findnearmv.h b/vp9/common/findnearmv.h index c53575e..64233ec 100644 --- a/vp9/common/findnearmv.h +++ b/vp9/common/findnearmv.h @@ -79,17 +79,9 @@ static unsigned int check_mv_bounds(int_mv *mv, (mv->as_mv.row > mb_to_bottom_edge); } -void vp9_find_near_mvs(MACROBLOCKD *xd, - const MODE_INFO *here, - const MODE_INFO *lfhere, - int_mv *nearest, int_mv *nearby, int_mv *best, - int near_mv_ref_cts[4], - int refframe, - int *ref_frame_sign_bias); - vp9_prob *vp9_mv_ref_probs(VP9_COMMON *pc, vp9_prob p[VP9_MVREFS - 1], - const int near_mv_ref_ct[4]); + const int context); extern const unsigned char vp9_mbsplit_offset[4][16]; diff --git a/vp9/common/modecont.c b/vp9/common/modecont.c index 023d201..ac6719a 100644 --- a/vp9/common/modecont.c +++ b/vp9/common/modecont.c @@ -10,55 +10,20 @@ #include "entropy.h" + const int vp9_default_mode_contexts[6][4] = { - { - /* 0 */ - 7, 1, 1, 183 - }, - { - /* 1 */ - 14, 18, 14, 147 - }, - { - /* 2 */ - 135, 64, 57, 68 - }, - { - /* 3 */ - 60, 56, 128, 65 - }, - { - /* 4 */ - 159, 134, 128, 34 - }, - { - /* 5 */ - 234, 188, 128, 28 - }, + {117, 1, 1, 141}, + {234, 1, 1, 213}, + {128, 90, 22, 145}, + {30, 104, 61, 159}, + {13, 169, 18, 206}, + {15, 76, 24, 166} }; const int vp9_default_mode_contexts_a[6][4] = { - { - /* 0 */ - 4, 1, 1, 143 - }, - { - /* 1 */ - 7, 9, 7, 107 - }, - { - /* 2 */ - 95, 34, 57, 68 - }, - { - /* 3 */ - 95, 56, 128, 65 - }, - { - /* 4 */ - 159, 67, 128, 34 - }, - { - /* 5 */ - 234, 94, 128, 28 - }, + {117, 1, 1, 141}, + {234, 1, 1, 213}, + {128, 90, 22, 145}, + {30, 104, 61, 159}, + {13, 169, 18, 206}, + {15, 76, 24, 166} }; diff --git a/vp9/common/mvref_common.c b/vp9/common/mvref_common.c index 67f2fb0..a412a6c 100644 --- a/vp9/common/mvref_common.c +++ b/vp9/common/mvref_common.c @@ -214,6 +214,7 @@ void vp9_find_mv_refs( int i; MODE_INFO *candidate_mi; + MB_MODE_INFO * mbmi = &xd->mode_info_context->mbmi; int_mv candidate_mvs[MAX_MV_REFS]; int_mv c_refmv; MV_REFERENCE_FRAME c_ref_frame; @@ -328,6 +329,31 @@ void vp9_find_mv_refs( index = (MAX_MV_REFS - 1); } + if (candidate_mvs[0].as_int == 0) { + // 0,0 was best + if (index == 0) { + // No reference candidates + mbmi->mb_mode_context[ref_frame] = 0; + } else if (index == 1) { + // 0,0 was only candidate + mbmi->mb_mode_context[ref_frame] = 1; + } else { + // Other candidates available + mbmi->mb_mode_context[ref_frame] = 2; + } + } else if (candidate_scores[0] >= 32) { + if (candidate_scores[1] >= 16) { + // Strong primary and strong or moderate secondary candidate + mbmi->mb_mode_context[ref_frame] = 3; + } else { + // Strong primary but weak secondary candidate + mbmi->mb_mode_context[ref_frame] = 4; + } + } else { + // Weak or moderate candidates + mbmi->mb_mode_context[ref_frame] = 5; + } + // 0,0 is always a valid reference. for (i = 0; i < index; ++i) if (candidate_mvs[i].as_int == 0) diff --git a/vp9/common/onyxc_int.h b/vp9/common/onyxc_int.h index de81470..516bea3 100644 --- a/vp9/common/onyxc_int.h +++ b/vp9/common/onyxc_int.h @@ -42,6 +42,7 @@ void vp9_initialize_common(void); #define NUM_YV12_BUFFERS 4 #define COMP_PRED_CONTEXTS 2 +#define INTER_MODE_CONTEXTS 6 typedef struct frame_contexts { vp9_prob bmode_prob[VP9_NKF_BINTRAMODES - 1]; @@ -106,11 +107,11 @@ typedef struct frame_contexts { vp9_prob switchable_interp_prob[VP9_SWITCHABLE_FILTERS + 1] [VP9_SWITCHABLE_FILTERS - 1]; - int mode_context[6][4]; - int mode_context_a[6][4]; - int vp9_mode_contexts[6][4]; - int mv_ref_ct[6][4][2]; - int mv_ref_ct_a[6][4][2]; + int mode_context[INTER_MODE_CONTEXTS][4]; + int mode_context_a[INTER_MODE_CONTEXTS][4]; + int vp9_mode_contexts[INTER_MODE_CONTEXTS][4]; + int mv_ref_ct[INTER_MODE_CONTEXTS][4][2]; + int mv_ref_ct_a[INTER_MODE_CONTEXTS][4][2]; } FRAME_CONTEXT; typedef enum { diff --git a/vp9/decoder/decodemv.c b/vp9/decoder/decodemv.c index 7d4d6a7..52032bc 100644 --- a/vp9/decoder/decodemv.c +++ b/vp9/decoder/decodemv.c @@ -720,10 +720,6 @@ static void read_mb_modes_mv(VP9D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi, int recon_y_stride, recon_yoffset; int recon_uv_stride, recon_uvoffset; - vp9_find_near_mvs(xd, mi, - prev_mi, - &nearest, &nearby, &best_mv, rct, - mbmi->ref_frame, cm->ref_frame_sign_bias); { int ref_fb_idx; MV_REFERENCE_FRAME ref_frame = mbmi->ref_frame; @@ -755,9 +751,10 @@ static void read_mb_modes_mv(VP9D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi, recon_y_stride, mbmi->ref_mvs[ref_frame], &best_mv, &nearest, &nearby); - } - vp9_mv_ref_probs(&pbi->common, mv_ref_p, rct); + vp9_mv_ref_probs(&pbi->common, mv_ref_p, + mbmi->mb_mode_context[ref_frame]); + } // Is the segment level mode feature enabled for this segment if (vp9_segfeature_active(xd, mbmi->segment_id, SEG_LVL_MODE)) { @@ -771,7 +768,8 @@ static void read_mb_modes_mv(VP9D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi, #endif mbmi->mode = read_mv_ref(bc, mv_ref_p); - vp9_accum_mv_refs(&pbi->common, mbmi->mode, rct); + vp9_accum_mv_refs(&pbi->common, mbmi->mode, + mbmi->mb_mode_context[mbmi->ref_frame]); } #if CONFIG_PRED_FILTER @@ -825,11 +823,6 @@ static void read_mb_modes_mv(VP9D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi, cm->yv12_fb[second_ref_fb_idx].u_buffer + recon_uvoffset; xd->second_pre.v_buffer = cm->yv12_fb[second_ref_fb_idx].v_buffer + recon_uvoffset; - vp9_find_near_mvs(xd, mi, prev_mi, - &nearest_second, &nearby_second, &best_mv_second, - rct, - mbmi->second_ref_frame, - cm->ref_frame_sign_bias); vp9_find_mv_refs(xd, mi, prev_mi, mbmi->second_ref_frame, diff --git a/vp9/encoder/bitstream.c b/vp9/encoder/bitstream.c index a80532e..d568e78 100644 --- a/vp9/encoder/bitstream.c +++ b/vp9/encoder/bitstream.c @@ -1053,13 +1053,9 @@ static void pack_inter_mode_mvs(VP9_COMP *const cpi, vp9_writer *const bc) { { int_mv n1, n2; - // Only used for context just now and soon to be deprecated. - vp9_find_near_mvs(xd, m, prev_m, &n1, &n2, &best_mv, ct, - rf, cpi->common.ref_frame_sign_bias); - best_mv.as_int = mi->ref_mvs[rf][0].as_int; - vp9_mv_ref_probs(&cpi->common, mv_ref_p, ct); + vp9_mv_ref_probs(&cpi->common, mv_ref_p, mi->mb_mode_context[rf]); #ifdef ENTROPY_STATS accum_mv_refs(mode, ct); @@ -1080,7 +1076,7 @@ static void pack_inter_mode_mvs(VP9_COMP *const cpi, vp9_writer *const bc) { { write_mv_ref(bc, mode, mv_ref_p); } - vp9_accum_mv_refs(&cpi->common, mode, ct); + vp9_accum_mv_refs(&cpi->common, mode, mi->mb_mode_context[rf]); } #if CONFIG_PRED_FILTER @@ -1112,12 +1108,6 @@ static void pack_inter_mode_mvs(VP9_COMP *const cpi, vp9_writer *const bc) { (mode == NEWMV || mode == SPLITMV)) { int_mv n1, n2; - // Only used for context just now and soon to be deprecated. - vp9_find_near_mvs(xd, m, prev_m, - &n1, &n2, &best_second_mv, ct, - mi->second_ref_frame, - cpi->common.ref_frame_sign_bias); - best_second_mv.as_int = mi->ref_mvs[mi->second_ref_frame][0].as_int; } @@ -2287,11 +2277,9 @@ void vp9_pack_bitstream(VP9_COMP *cpi, unsigned char *dest, vp9_update_mode_context(&cpi->common); } - vp9_stop_encode(&residual_bc); *size += residual_bc.pos; - } #ifdef ENTROPY_STATS diff --git a/vp9/encoder/rdopt.c b/vp9/encoder/rdopt.c index 4637db0..2a08ae8 100644 --- a/vp9/encoder/rdopt.c +++ b/vp9/encoder/rdopt.c @@ -1897,7 +1897,7 @@ static int64_t rd_pick_intra_sbuv_mode(VP9_COMP *cpi, int vp9_cost_mv_ref(VP9_COMP *cpi, MB_PREDICTION_MODE m, - const int near_mv_ref_ct[4]) { + const int mode_context) { MACROBLOCKD *xd = &cpi->mb.e_mbd; int segment_id = xd->mode_info_context->mbmi.segment_id; @@ -1911,7 +1911,7 @@ int vp9_cost_mv_ref(VP9_COMP *cpi, vp9_prob p [VP9_MVREFS - 1]; assert(NEARESTMV <= m && m <= SPLITMV); - vp9_mv_ref_probs(pc, p, near_mv_ref_ct); + vp9_mv_ref_probs(pc, p, mode_context); return cost_token(vp9_mv_ref_tree, p, vp9_mv_ref_encoding_array - NEARESTMV + m); } else @@ -2253,7 +2253,8 @@ static void rd_check_segment_txsize(VP9_COMP *cpi, MACROBLOCK *x, // Segmentation method overheads rate = cost_token(vp9_mbsplit_tree, vp9_mbsplit_probs, vp9_mbsplit_encodings + segmentation); - rate += vp9_cost_mv_ref(cpi, SPLITMV, bsi->mdcounts); + rate += vp9_cost_mv_ref(cpi, SPLITMV, + mbmi->mb_mode_context[mbmi->ref_frame]); this_segment_rd += RDCOST(x->rdmult, x->rddiv, rate, 0); br += rate; other_segment_rd = this_segment_rd; @@ -3207,12 +3208,6 @@ static void setup_buffer_inter(VP9_COMP *cpi, MACROBLOCK *x, MACROBLOCKD *const xd = &x->e_mbd; MB_MODE_INFO *const mbmi = &xd->mode_info_context->mbmi; - vp9_find_near_mvs(xd, xd->mode_info_context, - xd->prev_mode_info_context, - &frame_nearest_mv[frame_type], &frame_near_mv[frame_type], - &frame_best_ref_mv[frame_type], frame_mdcounts[frame_type], - frame_type, cpi->common.ref_frame_sign_bias); - y_buffer[frame_type] = yv12->y_buffer + recon_yoffset; u_buffer[frame_type] = yv12->u_buffer + recon_uvoffset; v_buffer[frame_type] = yv12->v_buffer + recon_uvoffset; @@ -3371,7 +3366,8 @@ static int64_t handle_inter_mode(VP9_COMP *cpi, MACROBLOCK *x, * if the first is known */ *compmode_cost = vp9_cost_bit(vp9_get_pred_prob(cm, xd, PRED_COMP), is_comp_pred); - *rate2 += vp9_cost_mv_ref(cpi, this_mode, mdcounts); + *rate2 += vp9_cost_mv_ref(cpi, this_mode, + mbmi->mb_mode_context[mbmi->ref_frame]); if (block_size == BLOCK_16X16) { vp9_build_1st_inter16x16_predictors_mby(xd, xd->predictor, 16, 0);