From: Jingning Han Date: Mon, 7 Dec 2015 23:54:59 +0000 (-0800) Subject: Enable adaptive prediction mode coding X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=aa5d53eb17937adcc6645843de24b6ee28a9132d;p=libvpx Enable adaptive prediction mode coding This commit allows the codec to analyze the reference motion vector candidate list and adaptively reduce the size of inter prediction mode set. Change-Id: Ied6a403843b860d66f26ed485c1825c05c71bdfc --- diff --git a/vp10/common/blockd.h b/vp10/common/blockd.h index 8858d573f..ec11f0a0f 100644 --- a/vp10/common/blockd.h +++ b/vp10/common/blockd.h @@ -257,6 +257,7 @@ typedef struct macroblockd { #if CONFIG_REF_MV uint8_t ref_mv_count[MAX_REF_FRAMES]; CANDIDATE_MV ref_mv_stack[MAX_REF_FRAMES][MAX_REF_MV_STACK_SIZE]; + uint8_t is_sec_rect; #endif #if CONFIG_VP9_HIGHBITDEPTH diff --git a/vp10/common/entropymode.c b/vp10/common/entropymode.c index 9dec0ba07..aa3e10b60 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, + 220, 220, 200, 200, 180, 128, 1, 250, }; #endif diff --git a/vp10/common/enums.h b/vp10/common/enums.h index cde29458e..980514c4a 100644 --- a/vp10/common/enums.h +++ b/vp10/common/enums.h @@ -206,13 +206,18 @@ typedef enum { #if CONFIG_REF_MV #define NEWMV_MODE_CONTEXTS 7 #define ZEROMV_MODE_CONTEXTS 2 -#define REFMV_MODE_CONTEXTS 6 +#define REFMV_MODE_CONTEXTS 8 #define ZEROMV_OFFSET 3 #define REFMV_OFFSET 4 #define NEWMV_CTX_MASK ((1 << ZEROMV_OFFSET) - 1) #define ZEROMV_CTX_MASK ((1 << (REFMV_OFFSET - ZEROMV_OFFSET)) - 1) +#define REFMV_CTX_MASK ((1 << (8 - REFMV_OFFSET)) - 1) + +#define ALL_ZERO_FLAG_OFFSET 8 +#define SKIP_NEARESTMV_OFFSET 9 +#define SKIP_NEARMV_OFFSET 10 #endif #define INTER_MODE_CONTEXTS 7 diff --git a/vp10/common/mvref_common.c b/vp10/common/mvref_common.c index 86bb980d7..c62e8acc0 100644 --- a/vp10/common/mvref_common.c +++ b/vp10/common/mvref_common.c @@ -189,7 +189,6 @@ static uint8_t scan_blk_mbmi(const VP10_COMMON *cm, const MACROBLOCKD *xd, static int has_top_right(const MACROBLOCKD *xd, int mi_row, int mi_col, int bs) { - int is_second_rect = 0; int has_tr = !((mi_row & bs) & (bs * 2 - 1)) || !((mi_col & bs) & (bs * 2 - 1)); @@ -205,31 +204,55 @@ static int has_top_right(const MACROBLOCKD *xd, if ((mi_row & 0x07) > 0) has_tr = 0; - if (xd->n8_w < xd->n8_h) { - if (mi_col & (xd->n8_h - 1)) - is_second_rect = 1; - - if (!is_second_rect) + if (xd->n8_w < xd->n8_h) + if (!xd->is_sec_rect) has_tr = 1; - } - if (xd->n8_w > xd->n8_h) { - if (mi_row & (xd->n8_w - 1)) - is_second_rect = 1; - - if (is_second_rect) + if (xd->n8_w > xd->n8_h) + if (xd->is_sec_rect) has_tr = 0; - } + return has_tr; } +static void handle_sec_rect_block(const MB_MODE_INFO * const candidate, + uint8_t *refmv_count, + CANDIDATE_MV *ref_mv_stack, + MV_REFERENCE_FRAME ref_frame, + int16_t *mode_context) { + int rf, idx; + + 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_mv pred_mv = candidate->mv[rf]; + for (idx = 0; idx < list_range; ++idx) + if (pred_mv.as_int == ref_mv_stack[idx].this_mv.as_int) + break; + + if (idx < list_range) { + mode_context[ref_frame] &= ~(0x0f << REFMV_OFFSET); + + if (idx == 0) { + mode_context[ref_frame] |= (1 << SKIP_NEARESTMV_OFFSET); + mode_context[ref_frame] |= (6 << REFMV_OFFSET); + } else if (idx == 1) { + mode_context[ref_frame] |= (1 << SKIP_NEARMV_OFFSET); + mode_context[ref_frame] |= (7 << REFMV_OFFSET); + } + } + } + } +} + static void setup_ref_mv_list(const VP10_COMMON *cm, const MACROBLOCKD *xd, MV_REFERENCE_FRAME ref_frame, uint8_t *refmv_count, CANDIDATE_MV *ref_mv_stack, int_mv *mv_ref_list, int block, int mi_row, int mi_col, - uint8_t *mode_context) { + int16_t *mode_context) { int idx, nearest_refmv_count = 0; uint8_t newmv_count = 0; @@ -389,6 +412,23 @@ static void setup_ref_mv_list(const VP10_COMMON *cm, const MACROBLOCKD *xd, len = nr_len; } + // TODO(jingning): Clean-up needed. + if (xd->is_sec_rect) { + 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, + 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, + ref_frame, mode_context); + } + } + for (idx = 0; idx < VPXMIN(MAX_MV_REF_CANDIDATES, *refmv_count); ++idx) { mv_ref_list[idx].as_int = ref_mv_stack[idx].this_mv.as_int; clamp_mv_ref(&mv_ref_list[idx].as_mv, @@ -404,7 +444,7 @@ static void find_mv_refs_idx(const VP10_COMMON *cm, const MACROBLOCKD *xd, int_mv *mv_ref_list, int block, int mi_row, int mi_col, find_mv_refs_sync sync, void *const data, - uint8_t *mode_context) { + int16_t *mode_context) { const int *ref_sign_bias = cm->ref_frame_sign_bias; int i, refmv_count = 0; const POSITION *const mv_ref_search = mv_ref_blocks[mi->mbmi.sb_type]; @@ -541,13 +581,23 @@ void vp10_find_mv_refs(const VP10_COMMON *cm, const MACROBLOCKD *xd, int_mv *mv_ref_list, int mi_row, int mi_col, find_mv_refs_sync sync, void *const data, - uint8_t *mode_context) { + int16_t *mode_context) { +#if CONFIG_REF_MV + int idx, all_zero = 1; +#endif find_mv_refs_idx(cm, xd, mi, ref_frame, mv_ref_list, -1, mi_row, mi_col, sync, data, mode_context); #if CONFIG_REF_MV setup_ref_mv_list(cm, xd, ref_frame, ref_mv_count, ref_mv_stack, mv_ref_list, -1, mi_row, mi_col, mode_context); + + for (idx = 0; idx < MAX_MV_REF_CANDIDATES; ++idx) + if (mv_ref_list[idx].as_int != 0) + all_zero = 0; + + if (all_zero) + mode_context[ref_frame] |= (1 << ALL_ZERO_FLAG_OFFSET); #endif } diff --git a/vp10/common/mvref_common.h b/vp10/common/mvref_common.h index 5950e1853..c5b40c313 100644 --- a/vp10/common/mvref_common.h +++ b/vp10/common/mvref_common.h @@ -204,7 +204,7 @@ void vp10_find_mv_refs(const VP10_COMMON *cm, const MACROBLOCKD *xd, #endif int_mv *mv_ref_list, int mi_row, int mi_col, find_mv_refs_sync sync, void *const data, - uint8_t *mode_context); + int16_t *mode_context); // check a list of motion vectors by sad score using a number rows of pixels // above and a number cols of pixels in the left to select the one with best diff --git a/vp10/common/onyxc_int.h b/vp10/common/onyxc_int.h index 4c98d1fd4..9b7a729be 100644 --- a/vp10/common/onyxc_int.h +++ b/vp10/common/onyxc_int.h @@ -460,6 +460,16 @@ static INLINE void set_mi_row_col(MACROBLOCKD *xd, const TileInfo *const tile, xd->n8_h = bh; xd->n8_w = bw; +#if CONFIG_REF_MV + xd->is_sec_rect = 0; + if (xd->n8_w < xd->n8_h) + if (mi_col & (xd->n8_h - 1)) + xd->is_sec_rect = 1; + + if (xd->n8_w > xd->n8_h) + if (mi_row & (xd->n8_w - 1)) + xd->is_sec_rect = 1; +#endif } static INLINE const vpx_prob *get_y_mode_probs(const VP10_COMMON *cm, diff --git a/vp10/decoder/decodemv.c b/vp10/decoder/decodemv.c index abb2217d0..392388a20 100644 --- a/vp10/decoder/decodemv.c +++ b/vp10/decoder/decodemv.c @@ -63,10 +63,10 @@ static PREDICTION_MODE read_intra_mode_uv(VP10_COMMON *cm, MACROBLOCKD *xd, } static PREDICTION_MODE read_inter_mode(VP10_COMMON *cm, MACROBLOCKD *xd, - vpx_reader *r, uint8_t ctx) { + vpx_reader *r, int16_t ctx) { #if CONFIG_REF_MV FRAME_COUNTS *counts = xd->counts; - uint8_t mode_ctx = ctx & NEWMV_CTX_MASK; + int16_t mode_ctx = ctx & NEWMV_CTX_MASK; vpx_prob mode_prob = cm->fc->newmv_prob[mode_ctx]; if (vpx_read(r, mode_prob) == 0) { @@ -77,10 +77,10 @@ static PREDICTION_MODE read_inter_mode(VP10_COMMON *cm, MACROBLOCKD *xd, if (counts) ++counts->newmv_mode[mode_ctx][1]; - mode_ctx = (ctx >> ZEROMV_OFFSET) & ZEROMV_CTX_MASK; + if (ctx & (1 << ALL_ZERO_FLAG_OFFSET)) + return ZEROMV; - if (mode_ctx > 1) - assert(0); + mode_ctx = (ctx >> ZEROMV_OFFSET) & ZEROMV_CTX_MASK; mode_prob = cm->fc->zeromv_prob[mode_ctx]; if (vpx_read(r, mode_prob) == 0) { @@ -91,11 +91,13 @@ static PREDICTION_MODE read_inter_mode(VP10_COMMON *cm, MACROBLOCKD *xd, if (counts) ++counts->zeromv_mode[mode_ctx][1]; - mode_ctx = (ctx >> REFMV_OFFSET); + mode_ctx = (ctx >> REFMV_OFFSET) & REFMV_CTX_MASK; mode_prob = cm->fc->refmv_prob[mode_ctx]; + if (vpx_read(r, mode_prob) == 0) { if (counts) ++counts->refmv_mode[mode_ctx][0]; + return NEARESTMV; } else { if (counts) @@ -814,7 +816,8 @@ static void read_inter_block_mode_info(VP10Decoder *const pbi, int_mv nearestmv[2], nearmv[2]; int_mv ref_mvs[MAX_REF_FRAMES][MAX_MV_REF_CANDIDATES]; int ref, is_compound; - uint8_t inter_mode_ctx[MAX_REF_FRAMES]; + int16_t inter_mode_ctx[MAX_REF_FRAMES]; + int16_t mode_ctx = 0; read_ref_frames(cm, xd, r, mbmi->segment_id, mbmi->ref_frame); is_compound = has_second_ref(mbmi); @@ -838,6 +841,15 @@ static void read_inter_block_mode_info(VP10Decoder *const pbi, 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; +#endif + if (segfeature_active(&cm->seg, mbmi->segment_id, SEG_LVL_SKIP)) { mbmi->mode = ZEROMV; if (bsize < BLOCK_8X8) { @@ -847,8 +859,7 @@ static void read_inter_block_mode_info(VP10Decoder *const pbi, } } else { if (bsize >= BLOCK_8X8) - mbmi->mode = read_inter_mode(cm, xd, r, - inter_mode_ctx[mbmi->ref_frame[0]]); + mbmi->mode = read_inter_mode(cm, xd, r, mode_ctx); } if (bsize < BLOCK_8X8 || mbmi->mode != ZEROMV) { @@ -874,7 +885,7 @@ 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; - b_mode = read_inter_mode(cm, xd, r, inter_mode_ctx[mbmi->ref_frame[0]]); + b_mode = read_inter_mode(cm, xd, r, mode_ctx); if (b_mode == NEARESTMV || b_mode == NEARMV) { for (ref = 0; ref < 1 + is_compound; ++ref) diff --git a/vp10/encoder/bitstream.c b/vp10/encoder/bitstream.c index 2bac77dcb..61a364339 100644 --- a/vp10/encoder/bitstream.c +++ b/vp10/encoder/bitstream.c @@ -103,19 +103,25 @@ static void write_intra_mode(vpx_writer *w, PREDICTION_MODE mode, static void write_inter_mode(VP10_COMMON *cm, vpx_writer *w, PREDICTION_MODE mode, - const uint8_t mode_ctx) { + const int16_t mode_ctx) { #if CONFIG_REF_MV - const uint8_t newmv_ctx = mode_ctx & NEWMV_CTX_MASK; + const int16_t newmv_ctx = mode_ctx & NEWMV_CTX_MASK; const vpx_prob newmv_prob = cm->fc->newmv_prob[newmv_ctx]; vpx_write(w, mode != NEWMV, newmv_prob); if (mode != NEWMV) { - const uint8_t zeromv_ctx = (mode_ctx >> ZEROMV_OFFSET) & ZEROMV_CTX_MASK; + const int16_t zeromv_ctx = (mode_ctx >> ZEROMV_OFFSET) & ZEROMV_CTX_MASK; const vpx_prob zeromv_prob = cm->fc->zeromv_prob[zeromv_ctx]; + + if (mode_ctx & (1 << ALL_ZERO_FLAG_OFFSET)) { + assert(mode == ZEROMV); + return; + } + vpx_write(w, mode != ZEROMV, zeromv_prob); if (mode != ZEROMV) { - const uint8_t refmv_ctx = (mode_ctx >> REFMV_OFFSET); + const int16_t refmv_ctx = (mode_ctx >> REFMV_OFFSET) & REFMV_CTX_MASK; const vpx_prob refmv_prob = cm->fc->refmv_prob[refmv_ctx]; vpx_write(w, mode != NEARESTMV, refmv_prob); } @@ -714,9 +720,16 @@ static void pack_inter_mode_mvs(VP10_COMP *cpi, const MODE_INFO *mi, write_ext_intra_mode_info(cm, mbmi, w); #endif // CONFIG_EXT_INTRA } else { - const int mode_ctx = mbmi_ext->mode_context[mbmi->ref_frame[0]]; + int16_t mode_ctx = mbmi_ext->mode_context[mbmi->ref_frame[0]]; 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; +#endif + // If segment skip is not enabled code the mode. if (!segfeature_active(seg, segment_id, SEG_LVL_SKIP)) { if (bsize >= BLOCK_8X8) { diff --git a/vp10/encoder/block.h b/vp10/encoder/block.h index 62de0bc37..1d5779b59 100644 --- a/vp10/encoder/block.h +++ b/vp10/encoder/block.h @@ -52,7 +52,7 @@ typedef unsigned int vp10_coeff_cost[PLANE_TYPES][REF_TYPES][COEF_BANDS][2] typedef struct { int_mv ref_mvs[MAX_REF_FRAMES][MAX_MV_REF_CANDIDATES]; - uint8_t mode_context[MAX_REF_FRAMES]; + int16_t mode_context[MAX_REF_FRAMES]; #if CONFIG_REF_MV uint8_t ref_mv_count[MAX_REF_FRAMES]; CANDIDATE_MV ref_mv_stack[MAX_REF_FRAMES][MAX_REF_MV_STACK_SIZE]; diff --git a/vp10/encoder/encodeframe.c b/vp10/encoder/encodeframe.c index 34eac8912..a2f6cdb2d 100644 --- a/vp10/encoder/encodeframe.c +++ b/vp10/encoder/encodeframe.c @@ -1260,20 +1260,25 @@ static void rd_pick_sb_modes(VP10_COMP *cpi, #if CONFIG_REF_MV static void update_inter_mode_stats(FRAME_COUNTS *counts, PREDICTION_MODE mode, - uint8_t mode_context) { - uint8_t mode_ctx = mode_context & NEWMV_CTX_MASK; + int16_t mode_context) { + int16_t mode_ctx = mode_context & NEWMV_CTX_MASK; if (mode == NEWMV) { ++counts->newmv_mode[mode_ctx][0]; return; } else { ++counts->newmv_mode[mode_ctx][1]; + + if (mode_context & (1 << ALL_ZERO_FLAG_OFFSET)) { + return; + } + mode_ctx = (mode_context >> ZEROMV_OFFSET) & ZEROMV_CTX_MASK; if (mode == ZEROMV) { ++counts->zeromv_mode[mode_ctx][0]; return; } else { ++counts->zeromv_mode[mode_ctx][1]; - mode_ctx = (mode_context >> REFMV_OFFSET); + mode_ctx = (mode_context >> REFMV_OFFSET) & REFMV_CTX_MASK; ++counts->refmv_mode[mode_ctx][mode != NEARESTMV]; } } @@ -1355,10 +1360,12 @@ static void update_stats(VP10_COMMON *cm, ThreadData *td) { } if (inter_block && !segfeature_active(&cm->seg, mbmi->segment_id, SEG_LVL_SKIP)) { - const int mode_ctx = mbmi_ext->mode_context[mbmi->ref_frame[0]]; + int16_t mode_ctx = mbmi_ext->mode_context[mbmi->ref_frame[0]]; 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); update_inter_mode_stats(counts, mode, mode_ctx); #else ++counts->inter_mode[mode_ctx][INTER_OFFSET(mode)]; @@ -1372,6 +1379,7 @@ 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; update_inter_mode_stats(counts, b_mode, mode_ctx); #else ++counts->inter_mode[mode_ctx][INTER_OFFSET(b_mode)]; diff --git a/vp10/encoder/rdopt.c b/vp10/encoder/rdopt.c index 813e13e0b..ed9673e84 100644 --- a/vp10/encoder/rdopt.c +++ b/vp10/encoder/rdopt.c @@ -3025,10 +3025,11 @@ static void choose_intra_uv_mode(VP10_COMP *cpi, MACROBLOCK *const x, } static int cost_mv_ref(const VP10_COMP *cpi, PREDICTION_MODE mode, - uint8_t mode_context) { + int16_t mode_context) { #if CONFIG_REF_MV int mode_cost = 0; - uint8_t mode_ctx = mode_context & NEWMV_CTX_MASK; + int16_t mode_ctx = mode_context & NEWMV_CTX_MASK; + int16_t is_all_zero_mv = mode_context & (1 << ALL_ZERO_FLAG_OFFSET); assert(is_inter_mode(mode)); @@ -3038,12 +3039,16 @@ static int cost_mv_ref(const VP10_COMP *cpi, PREDICTION_MODE mode, } else { mode_cost = cpi->newmv_mode_cost[mode_ctx][1]; mode_ctx = (mode_context >> ZEROMV_OFFSET) & ZEROMV_CTX_MASK; + + if (is_all_zero_mv) + return mode_cost; + if (mode == ZEROMV) { mode_cost += cpi->zeromv_mode_cost[mode_ctx][0]; return mode_cost; } else { mode_cost += cpi->zeromv_mode_cost[mode_ctx][1]; - mode_ctx = (mode_context >> REFMV_OFFSET); + mode_ctx = (mode_context >> REFMV_OFFSET) & REFMV_CTX_MASK; mode_cost += cpi->refmv_mode_cost[mode_ctx][mode != NEARESTMV]; return mode_cost; } @@ -3069,6 +3074,7 @@ static int set_and_cost_bmi_mvs(VP10_COMP *cpi, MACROBLOCK *x, MACROBLOCKD *xd, const int num_4x4_blocks_wide = num_4x4_blocks_wide_lookup[mbmi->sb_type]; const int num_4x4_blocks_high = num_4x4_blocks_high_lookup[mbmi->sb_type]; const int is_compound = has_second_ref(mbmi); + int mode_ctx = mbmi_ext->mode_context[mbmi->ref_frame[0]]; switch (mode) { case NEWMV: @@ -3106,8 +3112,10 @@ static int set_and_cost_bmi_mvs(VP10_COMP *cpi, MACROBLOCK *x, MACROBLOCKD *xd, for (idx = 0; idx < num_4x4_blocks_wide; ++idx) memmove(&mic->bmi[i + idy * 2 + idx], &mic->bmi[i], sizeof(mic->bmi[i])); - return cost_mv_ref(cpi, mode, mbmi_ext->mode_context[mbmi->ref_frame[0]]) + - thismvcost; +#if CONFIG_REF_MV + mode_ctx &= 0x00ff; +#endif + return cost_mv_ref(cpi, mode, mode_ctx) + thismvcost; } static int64_t encode_inter_mb_segment(VP10_COMP *cpi, @@ -3288,14 +3296,19 @@ static INLINE void mi_buf_restore(MACROBLOCK *x, struct buf_2d orig_src, // Check if NEARESTMV/NEARMV/ZEROMV is the cheapest way encode zero motion. // TODO(aconverse): Find out if this is still productive then clean up or remove static int check_best_zero_mv( - const VP10_COMP *cpi, const uint8_t mode_context[MAX_REF_FRAMES], + 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]) { 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)) { - int rfc = mode_context[ref_frames[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); +#else + int16_t rfc = mode_context[ref_frames[0]]; +#endif int c1 = cost_mv_ref(cpi, NEARMV, rfc); int c2 = cost_mv_ref(cpi, NEARESTMV, rfc); int c3 = cost_mv_ref(cpi, ZEROMV, rfc); @@ -4315,6 +4328,12 @@ static int64_t handle_inter_mode(VP10_COMP *cpi, MACROBLOCK *x, int skip_txfm_sb = 0; int64_t skip_sse_sb = INT64_MAX; int64_t distortion_y = 0, distortion_uv = 0; + 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); +#endif #if CONFIG_VP9_HIGHBITDEPTH if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) { @@ -4419,12 +4438,10 @@ static int64_t handle_inter_mode(VP10_COMP *cpi, MACROBLOCK *x, // initiation of a motion field. if (discount_newmv_test(cpi, this_mode, frame_mv[refs[0]], mode_mv, refs[0])) { - *rate2 += VPXMIN(cost_mv_ref(cpi, this_mode, - mbmi_ext->mode_context[refs[0]]), - cost_mv_ref(cpi, NEARESTMV, - mbmi_ext->mode_context[refs[0]])); + *rate2 += VPXMIN(cost_mv_ref(cpi, this_mode, mode_ctx), + cost_mv_ref(cpi, NEARESTMV, mode_ctx)); } else { - *rate2 += cost_mv_ref(cpi, this_mode, mbmi_ext->mode_context[refs[0]]); + *rate2 += cost_mv_ref(cpi, this_mode, mode_ctx); } if (RDCOST(x->rdmult, x->rddiv, *rate2, 0) > ref_best_rd && @@ -5573,6 +5590,19 @@ void vp10_rd_pick_inter_mode_sb(VP10_COMP *cpi, best_mbmode.mode = ZEROMV; } +#if CONFIG_REF_MV + if (best_mbmode.ref_frame[0] > INTRA_FRAME && + best_mbmode.mv[0].as_int == 0 && + (best_mbmode.ref_frame[1] == NONE || best_mbmode.mv[1].as_int == 0)) { + int16_t mode_ctx = mbmi_ext->mode_context[best_mbmode.ref_frame[0]]; + if (best_mbmode.ref_frame[1] > NONE) + mode_ctx &= (mbmi_ext->mode_context[best_mbmode.ref_frame[1]] | 0x00ff); + + if (mode_ctx & (1 << ALL_ZERO_FLAG_OFFSET)) + best_mbmode.mode = ZEROMV; + } +#endif + if (best_mode_index < 0 || best_rd >= best_rd_so_far) { rd_cost->rate = INT_MAX; rd_cost->rdcost = INT64_MAX;