From: Yue Chen Date: Wed, 20 Jan 2016 00:45:45 +0000 (-0800) Subject: Adding new compound modes to EXT_INTER experiment X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=968bbc7bb2727d22e0616d5701810f5cc308edb8;p=libvpx Adding new compound modes to EXT_INTER experiment Combinations of different mv modes for two reference frames are allowed in compound inter modes. 9 options are enabled, including NEAREST_NEARESTMV, NEAREST_NEARMV, NEAR_NEARESTMV, NEAREST_NEWMV, NEW_NEARESTMV, NEAR_NEWMV, NEW_NEARMV, ZERO_ZEROMV, and NEW_NEWMV. This experiment is mostly deported from the nextgen branch. It is made compatible with other experiments Coding gain of EXT_INTER(derflr/hevcmr/hevchd): 0.533%/0.728%/0.639% Change-Id: Id47e97284e6481b186870afbad33204b7a33dbb0 --- diff --git a/vp10/common/blockd.h b/vp10/common/blockd.h index 8c75c97af..8011456a3 100644 --- a/vp10/common/blockd.h +++ b/vp10/common/blockd.h @@ -49,15 +49,26 @@ typedef enum { static INLINE int is_inter_mode(PREDICTION_MODE mode) { #if CONFIG_EXT_INTER - return mode >= NEARESTMV && mode <= NEWFROMNEARMV; + return mode >= NEARESTMV && mode <= NEW_NEWMV; #else return mode >= NEARESTMV && mode <= NEWMV; #endif // CONFIG_EXT_INTER } #if CONFIG_EXT_INTER +static INLINE int is_inter_singleref_mode(PREDICTION_MODE mode) { + return mode >= NEARESTMV && mode <= NEWFROMNEARMV; +} + +static INLINE int is_inter_compound_mode(PREDICTION_MODE mode) { + return mode >= NEAREST_NEARESTMV && mode <= NEW_NEWMV; +} + static INLINE int have_newmv_in_inter_mode(PREDICTION_MODE mode) { - return (mode == NEWMV || mode == NEWFROMNEARMV); + return (mode == NEWMV || mode == NEWFROMNEARMV || + mode == NEW_NEWMV || + mode == NEAREST_NEWMV || mode == NEW_NEARESTMV || + mode == NEAR_NEWMV || mode == NEW_NEARMV); } #endif // CONFIG_EXT_INTER diff --git a/vp10/common/entropymode.c b/vp10/common/entropymode.c index 579745101..44c10990a 100644 --- a/vp10/common/entropymode.c +++ b/vp10/common/entropymode.c @@ -211,6 +211,19 @@ static const vpx_prob default_inter_mode_probs[INTER_MODE_CONTEXTS] #endif // CONFIG_EXT_INTER }; +#if CONFIG_EXT_INTER +static const vpx_prob default_inter_compound_mode_probs + [INTER_MODE_CONTEXTS][INTER_COMPOUND_MODES - 1] = { + { 2, 173, 68, 192, 192, 128, 180, 180}, // 0 = both zero mv + { 7, 145, 160, 192, 192, 128, 180, 180}, // 1 = 1 zero + 1 predicted + { 7, 166, 126, 192, 192, 128, 180, 180}, // 2 = two predicted mvs + { 7, 94, 132, 192, 192, 128, 180, 180}, // 3 = 1 pred/zero, 1 new + { 8, 64, 64, 192, 192, 128, 180, 180}, // 4 = two new mvs + {17, 81, 52, 192, 192, 128, 180, 180}, // 5 = one intra neighbour + {25, 29, 50, 192, 192, 128, 180, 180}, // 6 = two intra neighbours +}; +#endif // CONFIG_EXT_INTER + /* Array indices are identical to previously-existing INTRAMODECONTEXTNODES. */ const vpx_tree_index vp10_intra_mode_tree[TREE_SIZE(INTRA_MODES)] = { -DC_PRED, 2, /* 0 = DC_NODE */ @@ -235,6 +248,21 @@ const vpx_tree_index vp10_inter_mode_tree[TREE_SIZE(INTER_MODES)] = { #endif // CONFIG_EXT_INTER }; +#if CONFIG_EXT_INTER +const vpx_tree_index vp10_inter_compound_mode_tree + [TREE_SIZE(INTER_COMPOUND_MODES)] = { + -INTER_COMPOUND_OFFSET(ZERO_ZEROMV), 2, + -INTER_COMPOUND_OFFSET(NEAREST_NEARESTMV), 4, + 6, -INTER_COMPOUND_OFFSET(NEW_NEWMV), + 8, 10, + -INTER_COMPOUND_OFFSET(NEAREST_NEARMV), + -INTER_COMPOUND_OFFSET(NEAR_NEARESTMV), + 12, 14, + -INTER_COMPOUND_OFFSET(NEAREST_NEWMV), -INTER_COMPOUND_OFFSET(NEW_NEARESTMV), + -INTER_COMPOUND_OFFSET(NEAR_NEWMV), -INTER_COMPOUND_OFFSET(NEW_NEARMV) +}; +#endif // CONFIG_EXT_INTER + const vpx_tree_index vp10_partition_tree[TREE_SIZE(PARTITION_TYPES)] = { -PARTITION_NONE, 2, -PARTITION_HORZ, 4, @@ -1257,6 +1285,9 @@ static void init_mode_probs(FRAME_CONTEXT *fc) { #endif // CONFIG_EXT_INTER #endif // CONFIG_REF_MV vp10_copy(fc->inter_mode_probs, default_inter_mode_probs); +#if CONFIG_EXT_INTER + vp10_copy(fc->inter_compound_mode_probs, default_inter_compound_mode_probs); +#endif // CONFIG_EXT_INTER #if CONFIG_SUPERTX vp10_copy(fc->supertx_prob, default_supertx_prob); #endif // CONFIG_SUPERTX @@ -1336,6 +1367,14 @@ void vp10_adapt_inter_frame_probs(VP10_COMMON *cm) { } #endif // CONFIG_SUPERTX +#if CONFIG_EXT_INTER + for (i = 0; i < INTER_MODE_CONTEXTS; i++) + vpx_tree_merge_probs(vp10_inter_compound_mode_tree, + pre_fc->inter_compound_mode_probs[i], + counts->inter_compound_mode[i], + fc->inter_compound_mode_probs[i]); +#endif // CONFIG_EXT_INTER + for (i = 0; i < BLOCK_SIZE_GROUPS; i++) vpx_tree_merge_probs(vp10_intra_mode_tree, pre_fc->y_mode_prob[i], counts->y_mode[i], fc->y_mode_prob[i]); diff --git a/vp10/common/entropymode.h b/vp10/common/entropymode.h index ffaa3dfa3..01dcd5266 100644 --- a/vp10/common/entropymode.h +++ b/vp10/common/entropymode.h @@ -26,6 +26,9 @@ extern "C" { #define TX_SIZE_CONTEXTS 2 #define INTER_OFFSET(mode) ((mode) - NEARESTMV) +#if CONFIG_EXT_INTER +#define INTER_COMPOUND_OFFSET(mode) ((mode) - NEAREST_NEARESTMV) +#endif // CONFIG_EXT_INTER #define PALETTE_COLOR_CONTEXTS 16 #define PALETTE_MAX_SIZE 8 @@ -71,6 +74,10 @@ typedef struct frame_contexts { #endif vpx_prob inter_mode_probs[INTER_MODE_CONTEXTS][INTER_MODES - 1]; +#if CONFIG_EXT_INTER + vpx_prob inter_compound_mode_probs[INTER_MODE_CONTEXTS] + [INTER_COMPOUND_MODES - 1]; +#endif // CONFIG_EXT_INTER vpx_prob intra_inter_prob[INTRA_INTER_CONTEXTS]; vpx_prob comp_inter_prob[COMP_INTER_CONTEXTS]; vpx_prob single_ref_prob[REF_CONTEXTS][SINGLE_REFS-1]; @@ -119,6 +126,9 @@ typedef struct FRAME_COUNTS { #endif unsigned int inter_mode[INTER_MODE_CONTEXTS][INTER_MODES]; +#if CONFIG_EXT_INTER + unsigned int inter_compound_mode[INTER_MODE_CONTEXTS][INTER_COMPOUND_MODES]; +#endif // CONFIG_EXT_INTER unsigned int intra_inter[INTRA_INTER_CONTEXTS][2]; unsigned int comp_inter[COMP_INTER_CONTEXTS][2]; unsigned int single_ref[REF_CONTEXTS][SINGLE_REFS-1][2]; @@ -162,6 +172,10 @@ extern const vpx_prob vp10_default_palette_uv_color_prob extern const vpx_tree_index vp10_intra_mode_tree[TREE_SIZE(INTRA_MODES)]; extern const vpx_tree_index vp10_inter_mode_tree[TREE_SIZE(INTER_MODES)]; +#if CONFIG_EXT_INTER +extern const vpx_tree_index vp10_inter_compound_mode_tree + [TREE_SIZE(INTER_COMPOUND_MODES)]; +#endif // CONFIG_EXT_INTER extern const vpx_tree_index vp10_partition_tree[TREE_SIZE(PARTITION_TYPES)]; extern const vpx_tree_index vp10_switchable_interp_tree [TREE_SIZE(SWITCHABLE_FILTERS)]; diff --git a/vp10/common/enums.h b/vp10/common/enums.h index 5b4d1c5ec..fdcde99e6 100644 --- a/vp10/common/enums.h +++ b/vp10/common/enums.h @@ -179,7 +179,16 @@ typedef enum { #define NEWMV 13 #if CONFIG_EXT_INTER #define NEWFROMNEARMV 14 -#define MB_MODE_COUNT 15 +#define NEAREST_NEARESTMV 15 +#define NEAREST_NEARMV 16 +#define NEAR_NEARESTMV 17 +#define NEAREST_NEWMV 18 +#define NEW_NEARESTMV 19 +#define NEAR_NEWMV 20 +#define NEW_NEARMV 21 +#define ZERO_ZEROMV 22 +#define NEW_NEWMV 23 +#define MB_MODE_COUNT 24 #else #define MB_MODE_COUNT 14 #endif // CONFIG_EXT_INTER @@ -212,6 +221,10 @@ typedef enum { #define INTER_MODES (1 + NEWMV - NEARESTMV) #endif // CONFIG_EXT_INTER +#if CONFIG_EXT_INTER +#define INTER_COMPOUND_MODES (1 + NEW_NEWMV - NEAREST_NEARESTMV) +#endif // CONFIG_EXT_INTER + #define SKIP_CONTEXTS 3 #if CONFIG_REF_MV diff --git a/vp10/common/loopfilter.c b/vp10/common/loopfilter.c index 380312e6c..a4845339d 100644 --- a/vp10/common/loopfilter.c +++ b/vp10/common/loopfilter.c @@ -210,7 +210,8 @@ static const int mode_lf_lut[MB_MODE_COUNT] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // INTRA_MODES 1, 1, 0, 1 // INTER_MODES (ZEROMV == 0) #if CONFIG_EXT_INTER - , 1 // NEWFROMNEARMV mode + , 1, // NEWFROMNEARMV mode + 1, 1, 1, 1, 1, 1, 1, 0, 1 // INTER_COMPOUND_MODES (ZERO_ZEROMV == 0) #endif // CONFIG_EXT_INTER }; diff --git a/vp10/common/mvref_common.c b/vp10/common/mvref_common.c index 89cd8bbb8..53394e94d 100644 --- a/vp10/common/mvref_common.c +++ b/vp10/common/mvref_common.c @@ -41,7 +41,11 @@ static uint8_t add_ref_mv_candidate(const MODE_INFO *const candidate_mi, ref_mv_stack[index].weight = 2 * weight; ++(*refmv_count); +#if CONFIG_EXT_INTER + if (candidate->mode == NEWMV || candidate->mode == NEWFROMNEARMV) +#else if (candidate->mode == NEWMV) +#endif // CONFIG_EXT_INTER ++newmv_count; } @@ -62,7 +66,11 @@ static uint8_t add_ref_mv_candidate(const MODE_INFO *const candidate_mi, ref_mv_stack[index].weight = weight; ++(*refmv_count); +#if CONFIG_EXT_INTER + if (candidate->mode == NEWMV || candidate->mode == NEWFROMNEARMV) +#else if (candidate->mode == NEWMV) +#endif // CONFIG_EXT_INTER ++newmv_count; } } @@ -92,7 +100,11 @@ static uint8_t add_ref_mv_candidate(const MODE_INFO *const candidate_mi, ref_mv_stack[index].weight = 2 * weight; ++(*refmv_count); +#if CONFIG_EXT_INTER + if (candidate->mode == NEW_NEWMV) +#else if (candidate->mode == NEWMV) +#endif // CONFIG_EXT_INTER ++newmv_count; } @@ -116,7 +128,11 @@ static uint8_t add_ref_mv_candidate(const MODE_INFO *const candidate_mi, ref_mv_stack[index].weight = weight; ++(*refmv_count); +#if CONFIG_EXT_INTER + if (candidate->mode == NEW_NEWMV) +#else if (candidate->mode == NEWMV) +#endif // CONFIG_EXT_INTER ++newmv_count; } } @@ -664,6 +680,9 @@ void vp10_find_mv_refs(const VP10_COMMON *cm, const MACROBLOCKD *xd, #if CONFIG_REF_MV uint8_t *ref_mv_count, CANDIDATE_MV *ref_mv_stack, +#if CONFIG_EXT_INTER + int16_t *compound_mode_context, +#endif // CONFIG_EXT_INTER #endif int_mv *mv_ref_list, int mi_row, int mi_col, @@ -674,7 +693,12 @@ void vp10_find_mv_refs(const VP10_COMMON *cm, const MACROBLOCKD *xd, #endif #if CONFIG_EXT_INTER vp10_update_mv_context(cm, xd, mi, ref_frame, mv_ref_list, -1, - mi_row, mi_col, mode_context); + mi_row, mi_col, +#if CONFIG_REF_MV + compound_mode_context); +#else + mode_context); +#endif // CONFIG_REF_MV find_mv_refs_idx(cm, xd, mi, ref_frame, mv_ref_list, -1, mi_row, mi_col, sync, data, NULL); #else diff --git a/vp10/common/mvref_common.h b/vp10/common/mvref_common.h index c1ddc959b..4187247e7 100644 --- a/vp10/common/mvref_common.h +++ b/vp10/common/mvref_common.h @@ -57,6 +57,15 @@ static const int mode_2_counter[MB_MODE_COUNT] = { 1, // NEWMV #if CONFIG_EXT_INTER 1, // NEWFROMNEARMV + 0, // NEAREST_NEARESTMV + 0, // NEAREST_NEARMV + 0, // NEAR_NEARESTMV + 1, // NEAREST_NEWMV + 1, // NEW_NEARESTMV + 1, // NEAR_NEWMV + 1, // NEW_NEARMV + 3, // ZERO_ZEROMV + 1, // NEW_NEWMV #endif // CONFIG_EXT_INTER }; @@ -255,6 +264,9 @@ void vp10_find_mv_refs(const VP10_COMMON *cm, const MACROBLOCKD *xd, #if CONFIG_REF_MV uint8_t *ref_mv_count, CANDIDATE_MV *ref_mv_stack, +#if CONFIG_EXT_INTER + int16_t *compound_mode_context, +#endif // CONFIG_EXT_INTER #endif int_mv *mv_ref_list, int mi_row, int mi_col, find_mv_refs_sync sync, void *const data, diff --git a/vp10/common/thread_common.c b/vp10/common/thread_common.c index c9cc34346..be8b9d1ea 100644 --- a/vp10/common/thread_common.c +++ b/vp10/common/thread_common.c @@ -389,6 +389,13 @@ void vp10_accumulate_frame_counts(VP10_COMMON *cm, FRAME_COUNTS *counts, for (j = 0; j < INTER_MODES; j++) cm->counts.inter_mode[i][j] += counts->inter_mode[i][j]; +#if CONFIG_EXT_INTER + for (i = 0; i < INTER_MODE_CONTEXTS; i++) + for (j = 0; j < INTER_COMPOUND_MODES; j++) + cm->counts.inter_compound_mode[i][j] += + counts->inter_compound_mode[i][j]; +#endif // CONFIG_EXT_INTER + for (i = 0; i < INTRA_INTER_CONTEXTS; i++) for (j = 0; j < 2; j++) cm->counts.intra_inter[i][j] += counts->intra_inter[i][j]; diff --git a/vp10/decoder/decodeframe.c b/vp10/decoder/decodeframe.c index 33e8332ea..0ed16f12f 100644 --- a/vp10/decoder/decodeframe.c +++ b/vp10/decoder/decodeframe.c @@ -143,6 +143,19 @@ static void read_inter_mode_probs(FRAME_CONTEXT *fc, vpx_reader *r) { #endif } +#if CONFIG_EXT_INTER +static void read_inter_compound_mode_probs(FRAME_CONTEXT *fc, vpx_reader *r) { + int i, j; + if (vpx_read(r, GROUP_DIFF_UPDATE_PROB)) { + for (j = 0; j < INTER_MODE_CONTEXTS; ++j) { + for (i = 0; i < INTER_COMPOUND_MODES - 1; ++i) { + vp10_diff_update_prob(r, &fc->inter_compound_mode_probs[j][i]); + } + } + } +} +#endif // CONFIG_EXT_INTER + static REFERENCE_MODE read_frame_reference_mode(const VP10_COMMON *cm, struct vpx_read_bit_buffer *rb) { if (is_compound_reference_allowed(cm)) { @@ -3259,6 +3272,10 @@ static int read_compressed_header(VP10Decoder *pbi, const uint8_t *data, read_inter_mode_probs(fc, &r); +#if CONFIG_EXT_INTER + read_inter_compound_mode_probs(fc, &r); +#endif // CONFIG_EXT_INTER + if (cm->interp_filter == SWITCHABLE) read_switchable_interp_probs(fc, &r); @@ -3308,6 +3325,11 @@ static void debug_check_frame_counts(const VP10_COMMON *const cm) { sizeof(cm->counts.switchable_interp))); assert(!memcmp(cm->counts.inter_mode, zero_counts.inter_mode, sizeof(cm->counts.inter_mode))); +#if CONFIG_EXT_INTER + assert(!memcmp(cm->counts.inter_compound_mode, + zero_counts.inter_compound_mode, + sizeof(cm->counts.inter_compound_mode))); +#endif // CONFIG_EXT_INTER assert(!memcmp(cm->counts.intra_inter, zero_counts.intra_inter, sizeof(cm->counts.intra_inter))); assert(!memcmp(cm->counts.comp_inter, zero_counts.comp_inter, diff --git a/vp10/decoder/decodemv.c b/vp10/decoder/decodemv.c index d7c3faf0e..8f6d51080 100644 --- a/vp10/decoder/decodemv.c +++ b/vp10/decoder/decodemv.c @@ -147,6 +147,22 @@ static PREDICTION_MODE read_inter_mode(VP10_COMMON *cm, MACROBLOCKD *xd, #endif } +#if CONFIG_EXT_INTER +static PREDICTION_MODE read_inter_compound_mode(VP10_COMMON *cm, + MACROBLOCKD *xd, + vpx_reader *r, int16_t ctx) { + const int mode = vpx_read_tree(r, vp10_inter_compound_mode_tree, + cm->fc->inter_compound_mode_probs[ctx]); + FRAME_COUNTS *counts = xd->counts; + + if (counts) + ++counts->inter_compound_mode[ctx][mode]; + + assert(is_inter_compound_mode(NEAREST_NEARESTMV + mode)); + return NEAREST_NEARESTMV + mode; +} +#endif // CONFIG_EXT_INTER + static int read_segment_id(vpx_reader *r, const struct segmentation_probs *segp) { return vpx_read_tree(r, vp10_segment_tree, segp->tree_probs); @@ -826,6 +842,83 @@ static INLINE int assign_mv(VP10_COMMON *cm, MACROBLOCKD *xd, mv[1].as_int = 0; break; } +#if CONFIG_EXT_INTER + case NEW_NEWMV: { + FRAME_COUNTS *counts = xd->counts; + nmv_context_counts *const mv_counts = counts ? &counts->mv : NULL; + assert(is_compound); + for (i = 0; i < 2; ++i) { + read_mv(r, &mv[i].as_mv, &ref_mv[i].as_mv, &cm->fc->nmvc, mv_counts, + allow_hp); + ret = ret && is_mv_valid(&mv[i].as_mv); + } + break; + } + case NEAREST_NEARESTMV: { + assert(is_compound); + mv[0].as_int = nearest_mv[0].as_int; + mv[1].as_int = nearest_mv[1].as_int; + break; + } + case NEAREST_NEARMV: { + assert(is_compound); + mv[0].as_int = nearest_mv[0].as_int; + mv[1].as_int = near_mv[1].as_int; + break; + } + case NEAR_NEARESTMV: { + assert(is_compound); + mv[0].as_int = near_mv[0].as_int; + mv[1].as_int = nearest_mv[1].as_int; + break; + } + case NEW_NEARESTMV: { + FRAME_COUNTS *counts = xd->counts; + nmv_context_counts *const mv_counts = counts ? &counts->mv : NULL; + assert(is_compound); + read_mv(r, &mv[0].as_mv, &ref_mv[0].as_mv, &cm->fc->nmvc, mv_counts, + allow_hp); + ret = ret && is_mv_valid(&mv[0].as_mv); + mv[1].as_int = nearest_mv[1].as_int; + break; + } + case NEAREST_NEWMV: { + FRAME_COUNTS *counts = xd->counts; + nmv_context_counts *const mv_counts = counts ? &counts->mv : NULL; + assert(is_compound); + mv[0].as_int = nearest_mv[0].as_int; + read_mv(r, &mv[1].as_mv, &ref_mv[1].as_mv, &cm->fc->nmvc, mv_counts, + allow_hp); + ret = ret && is_mv_valid(&mv[1].as_mv); + break; + } + case NEAR_NEWMV: { + FRAME_COUNTS *counts = xd->counts; + nmv_context_counts *const mv_counts = counts ? &counts->mv : NULL; + assert(is_compound); + mv[0].as_int = near_mv[0].as_int; + read_mv(r, &mv[1].as_mv, &ref_mv[1].as_mv, &cm->fc->nmvc, mv_counts, + allow_hp); + ret = ret && is_mv_valid(&mv[1].as_mv); + break; + } + case NEW_NEARMV: { + FRAME_COUNTS *counts = xd->counts; + nmv_context_counts *const mv_counts = counts ? &counts->mv : NULL; + assert(is_compound); + read_mv(r, &mv[0].as_mv, &ref_mv[0].as_mv, &cm->fc->nmvc, mv_counts, + allow_hp); + ret = ret && is_mv_valid(&mv[0].as_mv); + mv[1].as_int = near_mv[1].as_int; + break; + } + case ZERO_ZEROMV: { + assert(is_compound); + mv[0].as_int = 0; + mv[1].as_int = 0; + break; + } +#endif // CONFIG_EXT_INTER default: { return 0; } @@ -868,6 +961,9 @@ static void read_inter_block_mode_info(VP10Decoder *const pbi, #endif // CONFIG_EXT_INTER int ref, is_compound; int16_t inter_mode_ctx[MODE_CTX_REF_FRAMES]; +#if CONFIG_REF_MV && CONFIG_EXT_INTER + int16_t compound_inter_mode_ctx[MODE_CTX_REF_FRAMES]; +#endif // CONFIG_REF_MV && CONFIG_EXT_INTER int16_t mode_ctx = 0; MV_REFERENCE_FRAME ref_frame; @@ -891,12 +987,20 @@ static void read_inter_block_mode_info(VP10Decoder *const pbi, #if CONFIG_REF_MV &xd->ref_mv_count[ref_frame], xd->ref_mv_stack[ref_frame], +#if CONFIG_EXT_INTER + compound_inter_mode_ctx, +#endif // CONFIG_EXT_INTER #endif ref_mvs[ref_frame], mi_row, mi_col, fpm_sync, (void *)pbi, inter_mode_ctx); } #if CONFIG_REF_MV +#if CONFIG_EXT_INTER + if (is_compound) + mode_ctx = compound_inter_mode_ctx[mbmi->ref_frame[0]]; + else +#endif // CONFIG_EXT_INTER mode_ctx = vp10_mode_context_analyzer(inter_mode_ctx, mbmi->ref_frame, bsize, -1); #else @@ -912,14 +1016,28 @@ static void read_inter_block_mode_info(VP10Decoder *const pbi, } } else { if (bsize >= BLOCK_8X8) +#if CONFIG_EXT_INTER + { + if (is_compound) + mbmi->mode = read_inter_compound_mode(cm, xd, r, mode_ctx); + else +#endif // CONFIG_EXT_INTER mbmi->mode = read_inter_mode(cm, xd, #if CONFIG_REF_MV && CONFIG_EXT_INTER mbmi, #endif // CONFIG_REF_MV && CONFIG_EXT_INTER r, mode_ctx); +#if CONFIG_EXT_INTER + } +#endif // CONFIG_EXT_INTER } +#if CONFIG_EXT_INTER + if (bsize < BLOCK_8X8 || + (mbmi->mode != ZEROMV && mbmi->mode != ZERO_ZEROMV)) { +#else if (bsize < BLOCK_8X8 || mbmi->mode != ZEROMV) { +#endif // CONFIG_EXT_INTER for (ref = 0; ref < 1 + is_compound; ++ref) { vp10_find_best_ref_mvs(allow_hp, ref_mvs[mbmi->ref_frame[ref]], &nearestmv[ref], &nearmv[ref]); @@ -927,19 +1045,52 @@ static void read_inter_block_mode_info(VP10Decoder *const pbi, } #if CONFIG_REF_MV +#if CONFIG_EXT_INTER + if (is_compound && bsize >= BLOCK_8X8 && mbmi->mode != ZERO_ZEROMV) { +#else if (is_compound && bsize >= BLOCK_8X8 && mbmi->mode != NEWMV && mbmi->mode != ZEROMV) { +#endif // CONFIG_EXT_INTER uint8_t ref_frame_type = vp10_ref_frame_type(mbmi->ref_frame); +#if CONFIG_EXT_INTER + if (xd->ref_mv_count[ref_frame_type] > 0) { +#else if (xd->ref_mv_count[ref_frame_type] == 1 && mbmi->mode == NEARESTMV) { +#endif // CONFIG_EXT_INTER int i; +#if CONFIG_EXT_INTER + if (mbmi->mode == NEAREST_NEARESTMV) { +#endif // CONFIG_EXT_INTER nearestmv[0] = xd->ref_mv_stack[ref_frame_type][0].this_mv; nearestmv[1] = xd->ref_mv_stack[ref_frame_type][0].comp_mv; for (i = 0; i < MAX_MV_REF_CANDIDATES; ++i) lower_mv_precision(&nearestmv[i].as_mv, allow_hp); +#if CONFIG_EXT_INTER + } else if (mbmi->mode == NEAREST_NEWMV || mbmi->mode == NEAREST_NEARMV) { + nearestmv[0] = xd->ref_mv_stack[ref_frame_type][0].this_mv; + lower_mv_precision(&nearestmv[0].as_mv, allow_hp); + } else if (mbmi->mode == NEW_NEARESTMV || mbmi->mode == NEAR_NEARESTMV) { + nearestmv[1] = xd->ref_mv_stack[ref_frame_type][0].comp_mv; + lower_mv_precision(&nearestmv[1].as_mv, allow_hp); + } +#endif // CONFIG_EXT_INTER } +#if CONFIG_EXT_INTER + if (xd->ref_mv_count[ref_frame_type] > 1) { + if (mbmi->mode == NEAR_NEWMV || mbmi->mode == NEAR_NEARESTMV) { + nearmv[0] = xd->ref_mv_stack[ref_frame_type][1].this_mv; + lower_mv_precision(&nearmv[0].as_mv, allow_hp); + } + + if (mbmi->mode == NEW_NEARMV || mbmi->mode == NEAREST_NEARMV) { + nearmv[1] = xd->ref_mv_stack[ref_frame_type][1].comp_mv; + lower_mv_precision(&nearmv[1].as_mv, allow_hp); + } + } +#else if (xd->ref_mv_count[ref_frame_type] > 1) { int i; nearestmv[0] = xd->ref_mv_stack[ref_frame_type][0].this_mv; @@ -952,6 +1103,7 @@ static void read_inter_block_mode_info(VP10Decoder *const pbi, lower_mv_precision(&nearmv[i].as_mv, allow_hp); } } +#endif // CONFIG_EXT_INTER } #endif @@ -975,9 +1127,17 @@ static void read_inter_block_mode_info(VP10Decoder *const pbi, int_mv block[2]; const int j = idy * 2 + idx; #if CONFIG_REF_MV +#if CONFIG_EXT_INTER + if (!is_compound) +#endif // CONFIG_EXT_INTER mode_ctx = vp10_mode_context_analyzer(inter_mode_ctx, mbmi->ref_frame, bsize, j); #endif +#if CONFIG_EXT_INTER + if (is_compound) + b_mode = read_inter_compound_mode(cm, xd, r, mode_ctx); + else +#endif // CONFIG_EXT_INTER b_mode = read_inter_mode(cm, xd, #if CONFIG_REF_MV && CONFIG_EXT_INTER mbmi, @@ -987,7 +1147,7 @@ static void read_inter_block_mode_info(VP10Decoder *const pbi, #if CONFIG_EXT_INTER mv_idx = (b_mode == NEWFROMNEARMV) ? 1 : 0; - if (b_mode != ZEROMV) { + if (b_mode != ZEROMV && b_mode != ZERO_ZEROMV) { #else if (b_mode == NEARESTMV || b_mode == NEARMV) { #endif // CONFIG_EXT_INTER @@ -1000,7 +1160,7 @@ static void read_inter_block_mode_info(VP10Decoder *const pbi, #endif // CONFIG_EXT_INTER vp10_append_sub8x8_mvs_for_idx(cm, xd, j, ref, mi_row, mi_col, #if CONFIG_EXT_INTER - mv_ref_list, + mv_ref_list, #endif // CONFIG_EXT_INTER &nearest_sub8x8[ref], &near_sub8x8[ref]); diff --git a/vp10/encoder/bitstream.c b/vp10/encoder/bitstream.c index 098c86a50..48c256496 100644 --- a/vp10/encoder/bitstream.c +++ b/vp10/encoder/bitstream.c @@ -55,6 +55,13 @@ static const struct vp10_token inter_mode_encodings[INTER_MODES] = {{2, 2}, {6, 3}, {0, 1}, {7, 3}}; #endif // CONFIG_EXT_INTER #endif +#if CONFIG_EXT_INTER +static const struct vp10_token inter_compound_mode_encodings + [INTER_COMPOUND_MODES] = { + {2, 2}, {24, 5}, {25, 5}, {52, 6}, {53, 6}, + {54, 6}, {55, 6}, {0, 1}, {7, 3} +}; +#endif // CONFIG_EXT_INTER static const struct vp10_token palette_size_encodings[] = { {0, 1}, {2, 2}, {6, 3}, {14, 4}, {30, 5}, {62, 6}, {63, 6}, }; @@ -173,6 +180,19 @@ static void write_inter_mode(VP10_COMMON *cm, #endif } +#if CONFIG_EXT_INTER +static void write_inter_compound_mode(VP10_COMMON *cm, vpx_writer *w, + PREDICTION_MODE mode, + const int16_t mode_ctx) { + const vpx_prob *const inter_compound_probs = + cm->fc->inter_compound_mode_probs[mode_ctx]; + + assert(is_inter_compound_mode(mode)); + vp10_write_token(w, vp10_inter_compound_mode_tree, inter_compound_probs, + &inter_compound_mode_encodings[INTER_COMPOUND_OFFSET(mode)]); +} +#endif // CONFIG_EXT_INTER + static void encode_unsigned_max(struct vpx_write_bit_buffer *wb, int data, int max) { vpx_wb_write_literal(wb, data, get_unsigned_bits(max)); @@ -302,6 +322,32 @@ static void update_inter_mode_probs(VP10_COMMON *cm, vpx_writer *w, } #endif +#if CONFIG_EXT_INTER +static void update_inter_compound_mode_probs(VP10_COMMON *cm, vpx_writer *w) { + const int savings_thresh = vp10_cost_one(GROUP_DIFF_UPDATE_PROB) - + vp10_cost_zero(GROUP_DIFF_UPDATE_PROB); + int i; + int savings = 0; + int do_update = 0; + for (i = 0; i < INTER_MODE_CONTEXTS; ++i) { + savings += prob_diff_update_savings(vp10_inter_compound_mode_tree, + cm->fc->inter_compound_mode_probs[i], + cm->counts.inter_compound_mode[i], + INTER_COMPOUND_MODES); + } + do_update = savings > savings_thresh; + vpx_write(w, do_update, GROUP_DIFF_UPDATE_PROB); + if (do_update) { + for (i = 0; i < INTER_MODE_CONTEXTS; ++i) { + prob_diff_update(vp10_inter_compound_mode_tree, + cm->fc->inter_compound_mode_probs[i], + cm->counts.inter_compound_mode[i], + INTER_COMPOUND_MODES, w); + } + } +} +#endif // CONFIG_EXT_INTER + static int write_skip(const VP10_COMMON *cm, const MACROBLOCKD *xd, int segment_id, const MODE_INFO *mi, vpx_writer *w) { if (segfeature_active(&cm->seg, segment_id, SEG_LVL_SKIP)) { @@ -793,8 +839,6 @@ static void write_switchable_interp_filter(VP10_COMP *cpi, const int ctx = vp10_get_pred_context_switchable_interp(xd); #if CONFIG_EXT_INTERP if (!vp10_is_interp_needed(xd)) { - // if (mbmi->interp_filter != EIGHTTAP) - // printf("Error [%d]\n", mbmi->sb_type); assert(mbmi->interp_filter == EIGHTTAP); return; } @@ -919,6 +963,11 @@ static void pack_inter_mode_mvs(VP10_COMP *cpi, const MODE_INFO *mi, write_ref_frames(cm, xd, w); #if CONFIG_REF_MV +#if CONFIG_EXT_INTER + if (is_compound) + mode_ctx = mbmi_ext->compound_mode_context[mbmi->ref_frame[0]]; + else +#endif // CONFIG_EXT_INTER mode_ctx = vp10_mode_context_analyzer(mbmi_ext->mode_context, mbmi->ref_frame, bsize, -1); #endif @@ -926,6 +975,11 @@ static void pack_inter_mode_mvs(VP10_COMP *cpi, const MODE_INFO *mi, // If segment skip is not enabled code the mode. if (!segfeature_active(seg, segment_id, SEG_LVL_SKIP)) { if (bsize >= BLOCK_8X8) { +#if CONFIG_EXT_INTER + if (is_inter_compound_mode(mode)) + write_inter_compound_mode(cm, w, mode, mode_ctx); + else if (is_inter_singleref_mode(mode)) +#endif // CONFIG_EXT_INTER write_inter_mode(cm, w, mode, #if CONFIG_REF_MV && CONFIG_EXT_INTER has_second_ref(mbmi), @@ -947,9 +1001,17 @@ static void pack_inter_mode_mvs(VP10_COMP *cpi, const MODE_INFO *mi, const int j = idy * 2 + idx; const PREDICTION_MODE b_mode = mi->bmi[j].as_mode; #if CONFIG_REF_MV +#if CONFIG_EXT_INTER + if (!is_compound) +#endif // CONFIG_EXT_INTER mode_ctx = vp10_mode_context_analyzer(mbmi_ext->mode_context, mbmi->ref_frame, bsize, j); #endif +#if CONFIG_EXT_INTER + if (is_inter_compound_mode(b_mode)) + write_inter_compound_mode(cm, w, b_mode, mode_ctx); + else if (is_inter_singleref_mode(b_mode)) +#endif // CONFIG_EXT_INTER write_inter_mode(cm, w, b_mode, #if CONFIG_REF_MV && CONFIG_EXT_INTER has_second_ref(mbmi), @@ -957,7 +1019,8 @@ static void pack_inter_mode_mvs(VP10_COMP *cpi, const MODE_INFO *mi, mode_ctx); #if CONFIG_EXT_INTER - if (b_mode == NEWMV || b_mode == NEWFROMNEARMV) { + if (b_mode == NEWMV || b_mode == NEWFROMNEARMV || + b_mode == NEW_NEWMV) { #else if (b_mode == NEWMV) { #endif // CONFIG_EXT_INTER @@ -970,11 +1033,20 @@ static void pack_inter_mode_mvs(VP10_COMP *cpi, const MODE_INFO *mi, #endif // CONFIG_EXT_INTER nmvc, allow_hp); } +#if CONFIG_EXT_INTER + else if (b_mode == NEAREST_NEWMV || b_mode == NEAR_NEWMV) { + vp10_encode_mv(cpi, w, &mi->bmi[j].as_mv[1].as_mv, + &mi->bmi[j].ref_mv[1].as_mv, nmvc, allow_hp); + } else if (b_mode == NEW_NEARESTMV || b_mode == NEW_NEARMV) { + vp10_encode_mv(cpi, w, &mi->bmi[j].as_mv[0].as_mv, + &mi->bmi[j].ref_mv[0].as_mv, nmvc, allow_hp); + } +#endif // CONFIG_EXT_INTER } } } else { #if CONFIG_EXT_INTER - if (mode == NEWMV || mode == NEWFROMNEARMV) { + if (mode == NEWMV || mode == NEWFROMNEARMV || mode == NEW_NEWMV) { #else if (mode == NEWMV) { #endif // CONFIG_EXT_INTER @@ -992,6 +1064,14 @@ static void pack_inter_mode_mvs(VP10_COMP *cpi, const MODE_INFO *mi, allow_hp); #if CONFIG_EXT_INTER } + } else if (mode == NEAREST_NEWMV || mode == NEAR_NEWMV) { + vp10_encode_mv(cpi, w, &mbmi->mv[1].as_mv, + &mbmi_ext->ref_mvs[mbmi->ref_frame[1]][0].as_mv, nmvc, + allow_hp); + } else if (mode == NEW_NEARESTMV || mode == NEW_NEARMV) { + vp10_encode_mv(cpi, w, &mbmi->mv[0].as_mv, + &mbmi_ext->ref_mvs[mbmi->ref_frame[0]][0].as_mv, nmvc, + allow_hp); #endif // CONFIG_EXT_INTER } } @@ -2212,6 +2292,10 @@ static size_t write_compressed_header(VP10_COMP *cpi, uint8_t *data) { counts->inter_mode[i], INTER_MODES, &header_bc); #endif +#if CONFIG_EXT_INTER + update_inter_compound_mode_probs(cm, &header_bc); +#endif // CONFIG_EXT_INTER + if (cm->interp_filter == SWITCHABLE) update_switchable_interp_probs(cm, &header_bc, counts); diff --git a/vp10/encoder/block.h b/vp10/encoder/block.h index 597f0d7d6..3e322decd 100644 --- a/vp10/encoder/block.h +++ b/vp10/encoder/block.h @@ -56,6 +56,9 @@ typedef struct { #if CONFIG_REF_MV uint8_t ref_mv_count[MODE_CTX_REF_FRAMES]; CANDIDATE_MV ref_mv_stack[MODE_CTX_REF_FRAMES][MAX_REF_MV_STACK_SIZE]; +#if CONFIG_EXT_INTER + int16_t compound_mode_context[MODE_CTX_REF_FRAMES]; +#endif // CONFIG_EXT_INTER #endif } MB_MODE_INFO_EXT; diff --git a/vp10/encoder/denoiser.c b/vp10/encoder/denoiser.c index 43647b0f4..e87667653 100644 --- a/vp10/encoder/denoiser.c +++ b/vp10/encoder/denoiser.c @@ -230,9 +230,19 @@ static VP9_DENOISER_DECISION perform_motion_compensation(VP9_DENOISER *denoiser, frame = ctx->best_zeromv_reference_frame; mbmi->ref_frame[0] = ctx->best_zeromv_reference_frame; +#if CONFIG_EXT_INTER + if (has_second_ref(mbmi)) + mbmi->mode = ZERO_ZEROMV; + else +#endif // CONFIG_EXT_INTER mbmi->mode = ZEROMV; mbmi->mv[0].as_int = 0; +#if CONFIG_EXT_INTER + if (has_second_ref(mbmi)) + ctx->best_sse_inter_mode = ZERO_ZEROMV; + else +#endif // CONFIG_EXT_INTER ctx->best_sse_inter_mode = ZEROMV; ctx->best_sse_mv.as_int = 0; ctx->newmv_sse = ctx->zeromv_sse; diff --git a/vp10/encoder/encodeframe.c b/vp10/encoder/encodeframe.c index 52926e35e..8c75287f4 100644 --- a/vp10/encoder/encodeframe.c +++ b/vp10/encoder/encodeframe.c @@ -1796,6 +1796,12 @@ static void update_stats(VP10_COMMON *cm, ThreadData *td if (bsize >= BLOCK_8X8) { const PREDICTION_MODE mode = mbmi->mode; #if CONFIG_REF_MV +#if CONFIG_EXT_INTER + if (has_second_ref(mbmi)) { + mode_ctx = mbmi_ext->compound_mode_context[mbmi->ref_frame[0]]; + ++counts->inter_compound_mode[mode_ctx][INTER_COMPOUND_OFFSET(mode)]; + } else { +#endif // CONFIG_EXT_INTER mode_ctx = vp10_mode_context_analyzer(mbmi_ext->mode_context, mbmi->ref_frame, bsize, -1); update_inter_mode_stats(counts, mode, @@ -1803,8 +1809,15 @@ static void update_stats(VP10_COMMON *cm, ThreadData *td has_second_ref(mbmi), #endif // CONFIG_EXT_INTER mode_ctx); - +#if CONFIG_EXT_INTER + } +#endif // CONFIG_EXT_INTER #else +#if CONFIG_EXT_INTER + if (is_inter_compound_mode(mode)) + ++counts->inter_compound_mode[mode_ctx][INTER_COMPOUND_OFFSET(mode)]; + else +#endif // CONFIG_EXT_INTER ++counts->inter_mode[mode_ctx][INTER_OFFSET(mode)]; #endif } else { @@ -1816,6 +1829,13 @@ 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 +#if CONFIG_EXT_INTER + if (has_second_ref(mbmi)) { + mode_ctx = mbmi_ext->compound_mode_context[mbmi->ref_frame[0]]; + ++counts->inter_compound_mode[mode_ctx] + [INTER_COMPOUND_OFFSET(b_mode)]; + } else { +#endif // CONFIG_EXT_INTER mode_ctx = vp10_mode_context_analyzer(mbmi_ext->mode_context, mbmi->ref_frame, bsize, j); update_inter_mode_stats(counts, b_mode, @@ -1823,7 +1843,16 @@ static void update_stats(VP10_COMMON *cm, ThreadData *td has_second_ref(mbmi), #endif // CONFIG_EXT_INTER mode_ctx); +#if CONFIG_EXT_INTER + } +#endif // CONFIG_EXT_INTER #else +#if CONFIG_EXT_INTER + if (is_inter_compound_mode(b_mode)) + ++counts->inter_compound_mode[mode_ctx] + [INTER_COMPOUND_OFFSET(b_mode)]; + else +#endif // CONFIG_EXT_INTER ++counts->inter_mode[mode_ctx][INTER_OFFSET(b_mode)]; #endif } diff --git a/vp10/encoder/encodemv.c b/vp10/encoder/encodemv.c index 0184bae9d..4124c4ac2 100644 --- a/vp10/encoder/encodemv.c +++ b/vp10/encoder/encodemv.c @@ -232,13 +232,23 @@ static void inc_mvs(const MB_MODE_INFO *mbmi, const MB_MODE_INFO_EXT *mbmi_ext, PREDICTION_MODE mode = mbmi->mode; int mv_idx = (mode == NEWFROMNEARMV); - if (mode == NEWMV || mode == NEWFROMNEARMV) { + if (mode == NEWMV || mode == NEWFROMNEARMV || mode == NEW_NEWMV) { for (i = 0; i < 1 + has_second_ref(mbmi); ++i) { const MV *ref = &mbmi_ext->ref_mvs[mbmi->ref_frame[i]][mv_idx].as_mv; const MV diff = {mvs[i].as_mv.row - ref->row, mvs[i].as_mv.col - ref->col}; vp10_inc_mv(&diff, counts, vp10_use_mv_hp(ref)); } + } else if (mode == NEAREST_NEWMV || mode == NEAR_NEWMV) { + const MV *ref = &mbmi_ext->ref_mvs[mbmi->ref_frame[1]][0].as_mv; + const MV diff = {mvs[1].as_mv.row - ref->row, + mvs[1].as_mv.col - ref->col}; + vp10_inc_mv(&diff, counts, vp10_use_mv_hp(ref)); + } else if (mode == NEW_NEARESTMV || mode == NEW_NEARMV) { + const MV *ref = &mbmi_ext->ref_mvs[mbmi->ref_frame[0]][0].as_mv; + const MV diff = {mvs[0].as_mv.row - ref->row, + mvs[0].as_mv.col - ref->col}; + vp10_inc_mv(&diff, counts, vp10_use_mv_hp(ref)); } } @@ -249,13 +259,23 @@ static void inc_mvs_sub8x8(const MODE_INFO *mi, int i; PREDICTION_MODE mode = mi->bmi[block].as_mode; - if (mode == NEWMV || mode == NEWFROMNEARMV) { + if (mode == NEWMV || mode == NEWFROMNEARMV || mode == NEW_NEWMV) { for (i = 0; i < 1 + has_second_ref(&mi->mbmi); ++i) { const MV *ref = &mi->bmi[block].ref_mv[i].as_mv; const MV diff = {mvs[i].as_mv.row - ref->row, mvs[i].as_mv.col - ref->col}; vp10_inc_mv(&diff, counts, vp10_use_mv_hp(ref)); } + } else if (mode == NEAREST_NEWMV || mode == NEAR_NEWMV) { + const MV *ref = &mi->bmi[block].ref_mv[1].as_mv; + const MV diff = {mvs[1].as_mv.row - ref->row, + mvs[1].as_mv.col - ref->col}; + vp10_inc_mv(&diff, counts, vp10_use_mv_hp(ref)); + } else if (mode == NEW_NEARESTMV || mode == NEW_NEARMV) { + const MV *ref = &mi->bmi[block].ref_mv[0].as_mv; + const MV diff = {mvs[0].as_mv.row - ref->row, + mvs[0].as_mv.col - ref->col}; + vp10_inc_mv(&diff, counts, vp10_use_mv_hp(ref)); } } #else diff --git a/vp10/encoder/encoder.h b/vp10/encoder/encoder.h index 797abacaf..d5c432f8d 100644 --- a/vp10/encoder/encoder.h +++ b/vp10/encoder/encoder.h @@ -482,6 +482,10 @@ typedef struct VP10_COMP { #endif unsigned int inter_mode_cost[INTER_MODE_CONTEXTS][INTER_MODES]; +#if CONFIG_EXT_INTER + unsigned int inter_compound_mode_cost[INTER_MODE_CONTEXTS] + [INTER_COMPOUND_MODES]; +#endif // CONFIG_EXT_INTER int intra_uv_mode_cost[INTRA_MODES][INTRA_MODES]; int y_mode_costs[INTRA_MODES][INTRA_MODES][INTRA_MODES]; int switchable_interp_costs[SWITCHABLE_FILTER_CONTEXTS][SWITCHABLE_FILTERS]; diff --git a/vp10/encoder/mbgraph.c b/vp10/encoder/mbgraph.c index ed0f53909..ab1e60f0e 100644 --- a/vp10/encoder/mbgraph.c +++ b/vp10/encoder/mbgraph.c @@ -67,6 +67,11 @@ static unsigned int do_16x16_motion_iteration(VP10_COMP *cpi, &distortion, &sse, NULL, 0, 0); } +#if CONFIG_EXT_INTER + if (has_second_ref(&xd->mi[0]->mbmi)) + xd->mi[0]->mbmi.mode = NEW_NEWMV; + else +#endif // CONFIG_EXT_INTER xd->mi[0]->mbmi.mode = NEWMV; xd->mi[0]->mbmi.mv[0].as_mv = *dst_mv; diff --git a/vp10/encoder/rd.c b/vp10/encoder/rd.c index d67f7c388..9dede8ee1 100644 --- a/vp10/encoder/rd.c +++ b/vp10/encoder/rd.c @@ -386,6 +386,12 @@ void vp10_initialize_rd_consts(VP10_COMP *cpi) { vp10_cost_tokens((int *)cpi->inter_mode_cost[i], cm->fc->inter_mode_probs[i], vp10_inter_mode_tree); #endif +#if CONFIG_EXT_INTER + for (i = 0; i < INTER_MODE_CONTEXTS; ++i) + vp10_cost_tokens((int *)cpi->inter_compound_mode_cost[i], + cm->fc->inter_compound_mode_probs[i], + vp10_inter_compound_mode_tree); +#endif // CONFIG_EXT_INTER } } @@ -692,11 +698,11 @@ void vp10_set_rd_speed_thresholds(VP10_COMP *cpi) { #if CONFIG_EXT_INTER rd->thresh_mult[THR_NEWFROMNEARMV] += 1000; -#if CONFIG_EXT_REF +#if CONFIG_EXT_REFS rd->thresh_mult[THR_NEWFROMNEARL2] += 1000; rd->thresh_mult[THR_NEWFROMNEARL3] += 1000; rd->thresh_mult[THR_NEWFROMNEARL4] += 1000; -#endif // CONFIG_EXT_REF +#endif // CONFIG_EXT_REFS rd->thresh_mult[THR_NEWFROMNEARG] += 1000; rd->thresh_mult[THR_NEWFROMNEARA] += 1000; #endif // CONFIG_EXT_INTER @@ -712,6 +718,59 @@ void vp10_set_rd_speed_thresholds(VP10_COMP *cpi) { rd->thresh_mult[THR_TM] += 1000; +#if CONFIG_EXT_INTER + rd->thresh_mult[THR_COMP_NEAREST_NEARESTLA] += 1000; + rd->thresh_mult[THR_COMP_NEAREST_NEARESTGA] += 1000; + rd->thresh_mult[THR_COMP_NEAREST_NEARLA] += 1200; + rd->thresh_mult[THR_COMP_NEAREST_NEARGA] += 1200; + rd->thresh_mult[THR_COMP_NEAR_NEARESTLA] += 1200; + rd->thresh_mult[THR_COMP_NEAR_NEARESTGA] += 1200; + rd->thresh_mult[THR_COMP_NEAREST_NEWLA] += 1500; + rd->thresh_mult[THR_COMP_NEAREST_NEWGA] += 1500; + rd->thresh_mult[THR_COMP_NEW_NEARESTLA] += 1500; + rd->thresh_mult[THR_COMP_NEW_NEARESTGA] += 1500; + rd->thresh_mult[THR_COMP_NEAR_NEWLA] += 1700; + rd->thresh_mult[THR_COMP_NEAR_NEWGA] += 1700; + rd->thresh_mult[THR_COMP_NEW_NEARLA] += 1700; + rd->thresh_mult[THR_COMP_NEW_NEARGA] += 1700; + rd->thresh_mult[THR_COMP_NEW_NEWLA] += 2000; + rd->thresh_mult[THR_COMP_NEW_NEWGA] += 2000; + rd->thresh_mult[THR_COMP_ZERO_ZEROLA] += 2500; + rd->thresh_mult[THR_COMP_ZERO_ZEROGA] += 2500; + +#if CONFIG_EXT_REFS + rd->thresh_mult[THR_COMP_NEAREST_NEARESTL2A] += 1000; + rd->thresh_mult[THR_COMP_NEAREST_NEARL2A] += 1200; + rd->thresh_mult[THR_COMP_NEAR_NEARESTL2A] += 1200; + rd->thresh_mult[THR_COMP_NEAREST_NEWL2A] += 1500; + rd->thresh_mult[THR_COMP_NEW_NEARESTL2A] += 1500; + rd->thresh_mult[THR_COMP_NEAR_NEWL2A] += 1700; + rd->thresh_mult[THR_COMP_NEW_NEARL2A] += 1700; + rd->thresh_mult[THR_COMP_NEW_NEWL2A] += 2000; + rd->thresh_mult[THR_COMP_ZERO_ZEROL2A] += 2500; + + rd->thresh_mult[THR_COMP_NEAREST_NEARESTL3A] += 1000; + rd->thresh_mult[THR_COMP_NEAREST_NEARL3A] += 1200; + rd->thresh_mult[THR_COMP_NEAR_NEARESTL3A] += 1200; + rd->thresh_mult[THR_COMP_NEAREST_NEWL3A] += 1500; + rd->thresh_mult[THR_COMP_NEW_NEARESTL3A] += 1500; + rd->thresh_mult[THR_COMP_NEAR_NEWL3A] += 1700; + rd->thresh_mult[THR_COMP_NEW_NEARL3A] += 1700; + rd->thresh_mult[THR_COMP_NEW_NEWL3A] += 2000; + rd->thresh_mult[THR_COMP_ZERO_ZEROL3A] += 2500; + + rd->thresh_mult[THR_COMP_NEAREST_NEARESTL4A] += 1000; + rd->thresh_mult[THR_COMP_NEAREST_NEARL4A] += 1200; + rd->thresh_mult[THR_COMP_NEAR_NEARESTL4A] += 1200; + rd->thresh_mult[THR_COMP_NEAREST_NEWL4A] += 1500; + rd->thresh_mult[THR_COMP_NEW_NEARESTL4A] += 1500; + rd->thresh_mult[THR_COMP_NEAR_NEWL4A] += 1700; + rd->thresh_mult[THR_COMP_NEW_NEARL4A] += 1700; + rd->thresh_mult[THR_COMP_NEW_NEWL4A] += 2000; + rd->thresh_mult[THR_COMP_ZERO_ZEROL4A] += 2500; + +#endif // CONFIG_EXT_REFS +#else rd->thresh_mult[THR_COMP_NEARESTLA] += 1000; #if CONFIG_EXT_REFS rd->thresh_mult[THR_COMP_NEARESTL2A] += 1000; @@ -740,6 +799,7 @@ void vp10_set_rd_speed_thresholds(VP10_COMP *cpi) { rd->thresh_mult[THR_COMP_ZEROL4A] += 2500; #endif // CONFIG_EXT_REFS rd->thresh_mult[THR_COMP_ZEROGA] += 2500; +#endif // CONFIG_EXT_INTER rd->thresh_mult[THR_H_PRED] += 2000; rd->thresh_mult[THR_V_PRED] += 2000; diff --git a/vp10/encoder/rd.h b/vp10/encoder/rd.h index 2b6106d95..2303c2005 100644 --- a/vp10/encoder/rd.h +++ b/vp10/encoder/rd.h @@ -39,13 +39,13 @@ extern "C" { #if CONFIG_EXT_REFS #if CONFIG_EXT_INTER -#define MAX_MODES 60 +#define MAX_MODES 85 #else #define MAX_MODES 54 #endif // CONFIG_EXT_INTER #else #if CONFIG_EXT_INTER -#define MAX_MODES 33 +#define MAX_MODES 43 #else #define MAX_MODES 30 #endif // CONFIG_EXT_INTER @@ -94,11 +94,11 @@ typedef enum { #if CONFIG_EXT_INTER THR_NEWFROMNEARMV, -#if CONFIG_EXT_REF +#if CONFIG_EXT_REFS THR_NEWFROMNEARL2, THR_NEWFROMNEARL3, THR_NEWFROMNEARL4, -#endif // CONFIG_EXT_REF +#endif // CONFIG_EXT_REFS THR_NEWFROMNEARA, THR_NEWFROMNEARG, #endif // CONFIG_EXT_INTER @@ -112,6 +112,15 @@ typedef enum { THR_ZEROG, THR_ZEROA, +#if CONFIG_EXT_INTER + THR_COMP_NEAREST_NEARESTLA, +#if CONFIG_EXT_REFS + THR_COMP_NEAREST_NEARESTL2A, + THR_COMP_NEAREST_NEARESTL3A, + THR_COMP_NEAREST_NEARESTL4A, +#endif // CONFIG_EXT_REFS + THR_COMP_NEAREST_NEARESTGA, +#else // CONFIG_EXT_INTER THR_COMP_NEARESTLA, #if CONFIG_EXT_REFS THR_COMP_NEARESTL2A, @@ -119,9 +128,57 @@ typedef enum { THR_COMP_NEARESTL4A, #endif // CONFIG_EXT_REFS THR_COMP_NEARESTGA, +#endif // CONFIG_EXT_INTER THR_TM, +#if CONFIG_EXT_INTER + THR_COMP_NEAR_NEARESTLA, + THR_COMP_NEAR_NEARESTGA, + THR_COMP_NEAREST_NEARLA, + THR_COMP_NEAREST_NEARGA, + THR_COMP_NEW_NEARESTLA, + THR_COMP_NEW_NEARESTGA, + THR_COMP_NEAREST_NEWLA, + THR_COMP_NEAREST_NEWGA, + THR_COMP_NEW_NEARLA, + THR_COMP_NEW_NEARGA, + THR_COMP_NEAR_NEWLA, + THR_COMP_NEAR_NEWGA, + THR_COMP_NEW_NEWLA, + THR_COMP_NEW_NEWGA, + THR_COMP_ZERO_ZEROLA, + THR_COMP_ZERO_ZEROGA, + +#if CONFIG_EXT_REFS + THR_COMP_NEAR_NEARESTL2A, + THR_COMP_NEAREST_NEARL2A, + THR_COMP_NEW_NEARESTL2A, + THR_COMP_NEAREST_NEWL2A, + THR_COMP_NEW_NEARL2A, + THR_COMP_NEAR_NEWL2A, + THR_COMP_NEW_NEWL2A, + THR_COMP_ZERO_ZEROL2A, + + THR_COMP_NEAR_NEARESTL3A, + THR_COMP_NEAREST_NEARL3A, + THR_COMP_NEW_NEARESTL3A, + THR_COMP_NEAREST_NEWL3A, + THR_COMP_NEW_NEARL3A, + THR_COMP_NEAR_NEWL3A, + THR_COMP_NEW_NEWL3A, + THR_COMP_ZERO_ZEROL3A, + + THR_COMP_NEAR_NEARESTL4A, + THR_COMP_NEAREST_NEARL4A, + THR_COMP_NEW_NEARESTL4A, + THR_COMP_NEAREST_NEWL4A, + THR_COMP_NEW_NEARL4A, + THR_COMP_NEAR_NEWL4A, + THR_COMP_NEW_NEWL4A, + THR_COMP_ZERO_ZEROL4A, +#endif // CONFIG_EXT_REFS +#else THR_COMP_NEARLA, THR_COMP_NEWLA, #if CONFIG_EXT_REFS @@ -142,6 +199,7 @@ typedef enum { THR_COMP_ZEROL4A, #endif // CONFIG_EXT_REFS THR_COMP_ZEROGA, +#endif // CONFIG_EXT_INTER THR_H_PRED, THR_V_PRED, diff --git a/vp10/encoder/rdopt.c b/vp10/encoder/rdopt.c index ec67dca29..0ec4af138 100644 --- a/vp10/encoder/rdopt.c +++ b/vp10/encoder/rdopt.c @@ -148,11 +148,11 @@ static const MODE_DEFINITION vp10_mode_order[MAX_MODES] = { #if CONFIG_EXT_INTER {NEWFROMNEARMV, {LAST_FRAME, NONE}}, -#if CONFIG_EXT_REF +#if CONFIG_EXT_REFS {NEWFROMNEARMV, {LAST2_FRAME, NONE}}, {NEWFROMNEARMV, {LAST3_FRAME, NONE}}, {NEWFROMNEARMV, {LAST4_FRAME, NONE}}, -#endif // CONFIG_EXT_REF +#endif // CONFIG_EXT_REFS {NEWFROMNEARMV, {ALTREF_FRAME, NONE}}, {NEWFROMNEARMV, {GOLDEN_FRAME, NONE}}, #endif // CONFIG_EXT_INTER @@ -166,6 +166,15 @@ static const MODE_DEFINITION vp10_mode_order[MAX_MODES] = { {ZEROMV, {GOLDEN_FRAME, NONE}}, {ZEROMV, {ALTREF_FRAME, NONE}}, +#if CONFIG_EXT_INTER + {NEAREST_NEARESTMV, {LAST_FRAME, ALTREF_FRAME}}, +#if CONFIG_EXT_REFS + {NEAREST_NEARESTMV, {LAST2_FRAME, ALTREF_FRAME}}, + {NEAREST_NEARESTMV, {LAST3_FRAME, ALTREF_FRAME}}, + {NEAREST_NEARESTMV, {LAST4_FRAME, ALTREF_FRAME}}, +#endif // CONFIG_EXT_REFS + {NEAREST_NEARESTMV, {GOLDEN_FRAME, ALTREF_FRAME}}, +#else // CONFIG_EXT_INTER {NEARESTMV, {LAST_FRAME, ALTREF_FRAME}}, #if CONFIG_EXT_REFS {NEARESTMV, {LAST2_FRAME, ALTREF_FRAME}}, @@ -173,9 +182,56 @@ static const MODE_DEFINITION vp10_mode_order[MAX_MODES] = { {NEARESTMV, {LAST4_FRAME, ALTREF_FRAME}}, #endif // CONFIG_EXT_REFS {NEARESTMV, {GOLDEN_FRAME, ALTREF_FRAME}}, +#endif // CONFIG_EXT_INTER {TM_PRED, {INTRA_FRAME, NONE}}, +#if CONFIG_EXT_INTER + {NEAR_NEARESTMV, {LAST_FRAME, ALTREF_FRAME}}, + {NEAR_NEARESTMV, {GOLDEN_FRAME, ALTREF_FRAME}}, + {NEAREST_NEARMV, {LAST_FRAME, ALTREF_FRAME}}, + {NEAREST_NEARMV, {GOLDEN_FRAME, ALTREF_FRAME}}, + {NEW_NEARESTMV, {LAST_FRAME, ALTREF_FRAME}}, + {NEW_NEARESTMV, {GOLDEN_FRAME, ALTREF_FRAME}}, + {NEAREST_NEWMV, {LAST_FRAME, ALTREF_FRAME}}, + {NEAREST_NEWMV, {GOLDEN_FRAME, ALTREF_FRAME}}, + {NEW_NEARMV, {LAST_FRAME, ALTREF_FRAME}}, + {NEW_NEARMV, {GOLDEN_FRAME, ALTREF_FRAME}}, + {NEAR_NEWMV, {LAST_FRAME, ALTREF_FRAME}}, + {NEAR_NEWMV, {GOLDEN_FRAME, ALTREF_FRAME}}, + {NEW_NEWMV, {LAST_FRAME, ALTREF_FRAME}}, + {NEW_NEWMV, {GOLDEN_FRAME, ALTREF_FRAME}}, + {ZERO_ZEROMV, {LAST_FRAME, ALTREF_FRAME}}, + {ZERO_ZEROMV, {GOLDEN_FRAME, ALTREF_FRAME}}, +#if CONFIG_EXT_REFS + {NEAR_NEARESTMV, {LAST2_FRAME, ALTREF_FRAME}}, + {NEAREST_NEARMV, {LAST2_FRAME, ALTREF_FRAME}}, + {NEW_NEARESTMV, {LAST2_FRAME, ALTREF_FRAME}}, + {NEAREST_NEWMV, {LAST2_FRAME, ALTREF_FRAME}}, + {NEW_NEARMV, {LAST2_FRAME, ALTREF_FRAME}}, + {NEAR_NEWMV, {LAST2_FRAME, ALTREF_FRAME}}, + {NEW_NEWMV, {LAST2_FRAME, ALTREF_FRAME}}, + {ZERO_ZEROMV, {LAST2_FRAME, ALTREF_FRAME}}, + + {NEAR_NEARESTMV, {LAST3_FRAME, ALTREF_FRAME}}, + {NEAREST_NEARMV, {LAST3_FRAME, ALTREF_FRAME}}, + {NEW_NEARESTMV, {LAST3_FRAME, ALTREF_FRAME}}, + {NEAREST_NEWMV, {LAST3_FRAME, ALTREF_FRAME}}, + {NEW_NEARMV, {LAST3_FRAME, ALTREF_FRAME}}, + {NEAR_NEWMV, {LAST3_FRAME, ALTREF_FRAME}}, + {NEW_NEWMV, {LAST3_FRAME, ALTREF_FRAME}}, + {ZERO_ZEROMV, {LAST3_FRAME, ALTREF_FRAME}}, + + {NEAR_NEARESTMV, {LAST4_FRAME, ALTREF_FRAME}}, + {NEAREST_NEARMV, {LAST4_FRAME, ALTREF_FRAME}}, + {NEW_NEARESTMV, {LAST4_FRAME, ALTREF_FRAME}}, + {NEAREST_NEWMV, {LAST4_FRAME, ALTREF_FRAME}}, + {NEW_NEARMV, {LAST4_FRAME, ALTREF_FRAME}}, + {NEAR_NEWMV, {LAST4_FRAME, ALTREF_FRAME}}, + {NEW_NEWMV, {LAST4_FRAME, ALTREF_FRAME}}, + {ZERO_ZEROMV, {LAST4_FRAME, ALTREF_FRAME}}, +#endif // CONFIG_EXT_REFS +#else {NEARMV, {LAST_FRAME, ALTREF_FRAME}}, {NEWMV, {LAST_FRAME, ALTREF_FRAME}}, #if CONFIG_EXT_REFS @@ -196,6 +252,7 @@ static const MODE_DEFINITION vp10_mode_order[MAX_MODES] = { {ZEROMV, {LAST4_FRAME, ALTREF_FRAME}}, #endif // CONFIG_EXT_REFS {ZEROMV, {GOLDEN_FRAME, ALTREF_FRAME}}, +#endif // CONFIG_EXT_INTER {H_PRED, {INTRA_FRAME, NONE}}, {V_PRED, {INTRA_FRAME, NONE}}, @@ -3150,13 +3207,22 @@ static int cost_mv_ref(const VP10_COMP *cpi, PREDICTION_MODE mode, int16_t mode_context) { #if CONFIG_REF_MV int mode_cost = 0; +#if CONFIG_EXT_INTER + int16_t mode_ctx = is_compound ? mode_context : + (mode_context & NEWMV_CTX_MASK); +#else int16_t mode_ctx = mode_context & NEWMV_CTX_MASK; +#endif // CONFIG_EXT_INTER int16_t is_all_zero_mv = mode_context & (1 << ALL_ZERO_FLAG_OFFSET); assert(is_inter_mode(mode)); #if CONFIG_EXT_INTER - if (mode == NEWMV || mode == NEWFROMNEARMV) { + if (is_compound) { + return cpi->inter_compound_mode_cost[mode_context] + [INTER_COMPOUND_OFFSET(mode)]; + } else { + if (mode == NEWMV || mode == NEWFROMNEARMV) { #else if (mode == NEWMV) { #endif // CONFIG_EXT_INTER @@ -3191,9 +3257,21 @@ static int cost_mv_ref(const VP10_COMP *cpi, PREDICTION_MODE mode, return mode_cost; } } +#if CONFIG_EXT_INTER + } +#endif // CONFIG_EXT_INTER #else assert(is_inter_mode(mode)); +#if CONFIG_EXT_INTER + if (is_inter_compound_mode(mode)) { + return cpi->inter_compound_mode_cost[mode_context] + [INTER_COMPOUND_OFFSET(mode)]; + } else { +#endif // CONFIG_EXT_INTER return cpi->inter_mode_cost[mode_context][INTER_OFFSET(mode)]; +#if CONFIG_EXT_INTER + } +#endif // CONFIG_EXT_INTER #endif } @@ -3221,7 +3299,6 @@ static int set_and_cost_bmi_mvs(VP10_COMP *cpi, MACROBLOCK *x, MACROBLOCKD *xd, case NEWMV: #if CONFIG_EXT_INTER case NEWFROMNEARMV: - if (!is_compound) { #endif // CONFIG_EXT_INTER this_mv[0].as_int = seg_mvs[mbmi->ref_frame[0]].as_int; #if CONFIG_EXT_INTER @@ -3231,36 +3308,13 @@ static int set_and_cost_bmi_mvs(VP10_COMP *cpi, MACROBLOCK *x, MACROBLOCKD *xd, #endif // CONFIG_EXT_INTER thismvcost += vp10_mv_bit_cost(&this_mv[0].as_mv, &best_ref_mv[0]->as_mv, mvjcost, mvcost, MV_COST_WEIGHT_SUB); -#if CONFIG_EXT_INTER - } else { - if (compound_seg_newmvs[0].as_int == INVALID_MV || - compound_seg_newmvs[1].as_int == INVALID_MV) { - this_mv[0].as_int = seg_mvs[mbmi->ref_frame[0]].as_int; - this_mv[1].as_int = seg_mvs[mbmi->ref_frame[1]].as_int; - } else { - this_mv[0].as_int = compound_seg_newmvs[0].as_int; - this_mv[1].as_int = compound_seg_newmvs[1].as_int; - } - if (!cpi->common.allow_high_precision_mv || - !vp10_use_mv_hp(&best_ref_mv[0]->as_mv)) - lower_mv_precision(&this_mv[0].as_mv, 0); - if (!cpi->common.allow_high_precision_mv || - !vp10_use_mv_hp(&best_ref_mv[1]->as_mv)) - lower_mv_precision(&this_mv[1].as_mv, 0); - thismvcost += vp10_mv_bit_cost(&this_mv[0].as_mv, - &best_ref_mv[0]->as_mv, - mvjcost, mvcost, MV_COST_WEIGHT_SUB); - thismvcost += vp10_mv_bit_cost(&this_mv[1].as_mv, - &best_ref_mv[1]->as_mv, - mvjcost, mvcost, MV_COST_WEIGHT_SUB); - } -#else +#if !CONFIG_EXT_INTER if (is_compound) { this_mv[1].as_int = seg_mvs[mbmi->ref_frame[1]].as_int; thismvcost += vp10_mv_bit_cost(&this_mv[1].as_mv, &best_ref_mv[1]->as_mv, mvjcost, mvcost, MV_COST_WEIGHT_SUB); } -#endif // CONFIG_EXT_INTER +#endif // !CONFIG_EXT_INTER break; case NEARMV: case NEARESTMV: @@ -3273,6 +3327,60 @@ static int set_and_cost_bmi_mvs(VP10_COMP *cpi, MACROBLOCK *x, MACROBLOCKD *xd, if (is_compound) this_mv[1].as_int = 0; break; +#if CONFIG_EXT_INTER + case NEW_NEWMV: + if (compound_seg_newmvs[0].as_int == INVALID_MV || + compound_seg_newmvs[1].as_int == INVALID_MV) { + this_mv[0].as_int = seg_mvs[mbmi->ref_frame[0]].as_int; + this_mv[1].as_int = seg_mvs[mbmi->ref_frame[1]].as_int; + } else { + this_mv[0].as_int = compound_seg_newmvs[0].as_int; + this_mv[1].as_int = compound_seg_newmvs[1].as_int; + } + if (!cpi->common.allow_high_precision_mv || + !vp10_use_mv_hp(&best_ref_mv[0]->as_mv)) + lower_mv_precision(&this_mv[0].as_mv, 0); + if (!cpi->common.allow_high_precision_mv || + !vp10_use_mv_hp(&best_ref_mv[1]->as_mv)) + lower_mv_precision(&this_mv[1].as_mv, 0); + thismvcost += vp10_mv_bit_cost(&this_mv[0].as_mv, + &best_ref_mv[0]->as_mv, + mvjcost, mvcost, MV_COST_WEIGHT_SUB); + thismvcost += vp10_mv_bit_cost(&this_mv[1].as_mv, + &best_ref_mv[1]->as_mv, + mvjcost, mvcost, MV_COST_WEIGHT_SUB); + break; + case NEW_NEARMV: + case NEW_NEARESTMV: + this_mv[0].as_int = seg_mvs[mbmi->ref_frame[0]].as_int; + if (!cpi->common.allow_high_precision_mv || + !vp10_use_mv_hp(&best_ref_mv[0]->as_mv)) + lower_mv_precision(&this_mv[0].as_mv, 0); + thismvcost += vp10_mv_bit_cost(&this_mv[0].as_mv, &best_ref_mv[0]->as_mv, + mvjcost, mvcost, MV_COST_WEIGHT_SUB); + this_mv[1].as_int = frame_mv[mode][mbmi->ref_frame[1]].as_int; + break; + case NEAR_NEWMV: + case NEAREST_NEWMV: + this_mv[0].as_int = frame_mv[mode][mbmi->ref_frame[0]].as_int; + this_mv[1].as_int = seg_mvs[mbmi->ref_frame[1]].as_int; + if (!cpi->common.allow_high_precision_mv || + !vp10_use_mv_hp(&best_ref_mv[1]->as_mv)) + lower_mv_precision(&this_mv[1].as_mv, 0); + thismvcost += vp10_mv_bit_cost(&this_mv[1].as_mv, &best_ref_mv[1]->as_mv, + mvjcost, mvcost, MV_COST_WEIGHT_SUB); + break; + case NEAREST_NEARMV: + case NEAR_NEARESTMV: + case NEAREST_NEARESTMV: + this_mv[0].as_int = frame_mv[mode][mbmi->ref_frame[0]].as_int; + this_mv[1].as_int = frame_mv[mode][mbmi->ref_frame[1]].as_int; + break; + case ZERO_ZEROMV: + this_mv[0].as_int = 0; + this_mv[1].as_int = 0; + break; +#endif // CONFIG_EXT_INTER default: break; } @@ -3288,6 +3396,11 @@ 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 +#if CONFIG_EXT_INTER + if (is_compound) + mode_ctx = mbmi_ext->compound_mode_context[mbmi->ref_frame[0]]; + else +#endif // CONFIG_EXT_INTER mode_ctx = vp10_mode_context_analyzer(mbmi_ext->mode_context, mbmi->ref_frame, mbmi->sb_type, i); #endif @@ -3441,7 +3554,11 @@ typedef struct { int64_t sse; int segment_yrate; PREDICTION_MODE modes[4]; +#if CONFIG_EXT_INTER + SEG_RDSTAT rdstat[4][INTER_MODES + INTER_COMPOUND_MODES]; +#else SEG_RDSTAT rdstat[4][INTER_MODES]; +#endif // CONFIG_EXT_INTER int mvthresh; } BEST_SEG_INFO; @@ -3480,6 +3597,9 @@ static INLINE void mi_buf_restore(MACROBLOCK *x, struct buf_2d orig_src, // 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 int16_t mode_context[MAX_REF_FRAMES], +#if CONFIG_REF_MV && CONFIG_EXT_INTER + const int16_t compound_mode_context[MAX_REF_FRAMES], +#endif // CONFIG_REF_MV && CONFIG_EXT_INTER int_mv frame_mv[MB_MODE_COUNT][MAX_REF_FRAMES], int this_mode, const MV_REFERENCE_FRAME ref_frames[2], const BLOCK_SIZE bsize, int block) { @@ -3527,6 +3647,56 @@ static int check_best_zero_mv( } } } +#if CONFIG_EXT_INTER + else if ((this_mode == NEAREST_NEARESTMV || this_mode == NEAREST_NEARMV || + this_mode == NEAR_NEARESTMV || this_mode == ZERO_ZEROMV) && + frame_mv[this_mode][ref_frames[0]].as_int == 0 && + frame_mv[this_mode][ref_frames[1]].as_int == 0) { +#if CONFIG_REF_MV + int16_t rfc = compound_mode_context[ref_frames[0]]; + int c1 = cost_mv_ref(cpi, NEAREST_NEARMV, 1, rfc); + int c2 = cost_mv_ref(cpi, NEAREST_NEARESTMV, 1, rfc); + int c3 = cost_mv_ref(cpi, ZERO_ZEROMV, 1, rfc); + int c4 = cost_mv_ref(cpi, NEAR_NEARESTMV, 1, rfc); +#else + int16_t rfc = mode_context[ref_frames[0]]; + int c1 = cost_mv_ref(cpi, NEAREST_NEARMV, rfc); + int c2 = cost_mv_ref(cpi, NEAREST_NEARESTMV, rfc); + int c3 = cost_mv_ref(cpi, ZERO_ZEROMV, rfc); + int c4 = cost_mv_ref(cpi, NEAR_NEARESTMV, rfc); +#endif + + if (this_mode == NEAREST_NEARMV) { + if (c1 > c3) return 0; + } else if (this_mode == NEAREST_NEARESTMV) { + if (c2 > c3) return 0; + } else if (this_mode == NEAR_NEARESTMV) { + if (c4 > c3) return 0; + } else { + assert(this_mode == ZERO_ZEROMV); + if (ref_frames[1] == NONE) { + if ((c3 >= c2 && + frame_mv[NEAREST_NEARESTMV][ref_frames[0]].as_int == 0) || + (c3 >= c1 && + frame_mv[NEAREST_NEARMV][ref_frames[0]].as_int == 0) || + (c3 >= c4 && + frame_mv[NEAR_NEARESTMV][ref_frames[0]].as_int == 0)) + return 0; + } else { + if ((c3 >= c2 && + frame_mv[NEAREST_NEARESTMV][ref_frames[0]].as_int == 0 && + frame_mv[NEAREST_NEARESTMV][ref_frames[1]].as_int == 0) || + (c3 >= c1 && + frame_mv[NEAREST_NEARMV][ref_frames[0]].as_int == 0 && + frame_mv[NEAREST_NEARMV][ref_frames[1]].as_int == 0) || + (c3 >= c4 && + frame_mv[NEAR_NEARESTMV][ref_frames[0]].as_int == 0 && + frame_mv[NEAR_NEARESTMV][ref_frames[1]].as_int == 0)) + return 0; + } + } + } +#endif // CONFIG_EXT_INTER return 1; } @@ -3827,13 +3997,40 @@ static int64_t rd_pick_best_sub8x8_mode(VP10_COMP *cpi, MACROBLOCK *x, mv_ref_list[1].as_int = frame_mv[NEARMV][frame].as_int; vp10_find_best_ref_mvs(cm->allow_high_precision_mv, mv_ref_list, &ref_mvs_sub8x8[0][ref], &ref_mvs_sub8x8[1][ref]); + + if (has_second_rf) { + frame_mv[ZERO_ZEROMV][frame].as_int = 0; + frame_mv[NEAREST_NEARESTMV][frame].as_int = + frame_mv[NEARESTMV][frame].as_int; + + if (ref == 0) { + frame_mv[NEAREST_NEARMV][frame].as_int = + frame_mv[NEARESTMV][frame].as_int; + frame_mv[NEAR_NEARESTMV][frame].as_int = + frame_mv[NEARMV][frame].as_int; + frame_mv[NEAREST_NEWMV][frame].as_int = + frame_mv[NEARESTMV][frame].as_int; + frame_mv[NEAR_NEWMV][frame].as_int = + frame_mv[NEARMV][frame].as_int; + } else if (ref == 1) { + frame_mv[NEAREST_NEARMV][frame].as_int = + frame_mv[NEARMV][frame].as_int; + frame_mv[NEAR_NEARESTMV][frame].as_int = + frame_mv[NEARESTMV][frame].as_int; + frame_mv[NEW_NEARESTMV][frame].as_int = + frame_mv[NEARESTMV][frame].as_int; + frame_mv[NEW_NEARMV][frame].as_int = + frame_mv[NEARMV][frame].as_int; + } + } #endif // CONFIG_EXT_INTER } // search for the best motion vector on this segment #if CONFIG_EXT_INTER - for (this_mode = NEARESTMV; - this_mode <= (has_second_rf ? NEWMV : NEWFROMNEARMV); ++this_mode) { + for (this_mode = (has_second_rf ? NEAREST_NEARESTMV : NEARESTMV); + this_mode <= (has_second_rf ? NEW_NEWMV : NEWFROMNEARMV); + ++this_mode) { #else for (this_mode = NEARESTMV; this_mode <= NEWMV; ++this_mode) { #endif // CONFIG_EXT_INTER @@ -3843,6 +4040,7 @@ static int64_t rd_pick_best_sub8x8_mode(VP10_COMP *cpi, MACROBLOCK *x, mode_idx = INTER_OFFSET(this_mode); #if CONFIG_EXT_INTER mv_idx = (this_mode == NEWFROMNEARMV) ? 1 : 0; + for (ref = 0; ref < 1 + has_second_rf; ++ref) bsi->ref_mv[ref]->as_int = ref_mvs_sub8x8[mv_idx][ref].as_int; #endif // CONFIG_EXT_INTER @@ -3850,7 +4048,11 @@ static int64_t rd_pick_best_sub8x8_mode(VP10_COMP *cpi, MACROBLOCK *x, if (!(inter_mode_mask & (1 << this_mode))) continue; - if (!check_best_zero_mv(cpi, mbmi_ext->mode_context, frame_mv, + if (!check_best_zero_mv(cpi, mbmi_ext->mode_context, +#if CONFIG_REF_MV && CONFIG_EXT_INTER + mbmi_ext->compound_mode_context, +#endif // CONFIG_REF_MV && CONFIG_EXT_INTER + frame_mv, this_mode, mbmi->ref_frame, bsize, i)) continue; @@ -3977,7 +4179,12 @@ static int64_t rd_pick_best_sub8x8_mode(VP10_COMP *cpi, MACROBLOCK *x, continue; } - if (has_second_rf && this_mode == NEWMV && + if (has_second_rf && +#if CONFIG_EXT_INTER + this_mode == NEW_NEWMV && +#else + this_mode == NEWMV && +#endif // CONFIG_EXT_INTER mbmi->interp_filter == EIGHTTAP) { // adjust src pointers mi_buf_shift(x, i); @@ -4133,7 +4340,11 @@ static int64_t rd_pick_best_sub8x8_mode(VP10_COMP *cpi, MACROBLOCK *x, if (best_rd == INT64_MAX) { int iy, midx; for (iy = i + 1; iy < 4; ++iy) +#if CONFIG_EXT_INTER + for (midx = 0; midx < INTER_MODES + INTER_COMPOUND_MODES; ++midx) +#else for (midx = 0; midx < INTER_MODES; ++midx) +#endif // CONFIG_EXT_INTER bsi->rdstat[iy][midx].brdcost = INT64_MAX; bsi->segment_rd = INT64_MAX; return INT64_MAX; @@ -4168,7 +4379,11 @@ static int64_t rd_pick_best_sub8x8_mode(VP10_COMP *cpi, MACROBLOCK *x, if (this_segment_rd > bsi->segment_rd) { int iy, midx; for (iy = i + 1; iy < 4; ++iy) +#if CONFIG_EXT_INTER + for (midx = 0; midx < INTER_MODES + INTER_COMPOUND_MODES; ++midx) +#else for (midx = 0; midx < INTER_MODES; ++midx) +#endif // CONFIG_EXT_INTER bsi->rdstat[iy][midx].brdcost = INT64_MAX; bsi->segment_rd = INT64_MAX; return INT64_MAX; @@ -4400,6 +4615,9 @@ static void setup_buffer_inter( #if CONFIG_REF_MV &mbmi_ext->ref_mv_count[ref_frame], mbmi_ext->ref_mv_stack[ref_frame], +#if CONFIG_EXT_INTER + mbmi_ext->compound_mode_context, +#endif // CONFIG_EXT_INTER #endif candidates, mi_row, mi_col, NULL, NULL, mbmi_ext->mode_context); @@ -4630,6 +4848,9 @@ static int64_t handle_inter_mode(VP10_COMP *cpi, MACROBLOCK *x, #if CONFIG_EXT_INTER int mv_idx = (this_mode == NEWFROMNEARMV) ? 1 : 0; int_mv single_newmv[MAX_REF_FRAMES]; +#if CONFIG_REF_MV + uint8_t ref_frame_type = vp10_ref_frame_type(mbmi->ref_frame); +#endif #endif // CONFIG_EXT_INTER #if CONFIG_VP9_HIGHBITDEPTH DECLARE_ALIGNED(16, uint16_t, tmp_buf16[MAX_MB_PLANE * 64 * 64]); @@ -4659,6 +4880,11 @@ 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 CONFIG_EXT_INTER + if (is_comp_pred) + mode_ctx = mbmi_ext->compound_mode_context[refs[0]]; + else +#endif // CONFIG_EXT_INTER mode_ctx = vp10_mode_context_analyzer(mbmi_ext->mode_context, mbmi->ref_frame, bsize, -1); #endif @@ -4679,7 +4905,8 @@ static int64_t handle_inter_mode(VP10_COMP *cpi, MACROBLOCK *x, lf = xd->mi[-1]->mbmi.interp_filter; #if CONFIG_EXT_INTER - if ((this_mode != NEWMV && this_mode != NEWFROMNEARMV) || (af == lf)) + if ((this_mode != NEWMV && this_mode != NEWFROMNEARMV && + this_mode != NEW_NEWMV) || (af == lf)) #else if ((this_mode != NEWMV) || (af == lf)) #endif // CONFIG_EXT_INTER @@ -4692,9 +4919,64 @@ static int64_t handle_inter_mode(VP10_COMP *cpi, MACROBLOCK *x, return INT64_MAX; if (cpi->sf.adaptive_mode_search) { +#if CONFIG_EXT_INTER + switch (this_mode) { + case NEAREST_NEARESTMV: + if (single_filter[NEARESTMV][refs[0]] == + single_filter[NEARESTMV][refs[1]]) + best_filter = single_filter[NEARESTMV][refs[0]]; + break; + case NEAREST_NEARMV: + if (single_filter[NEARESTMV][refs[0]] == + single_filter[NEARMV][refs[1]]) + best_filter = single_filter[NEARESTMV][refs[0]]; + break; + case NEAR_NEARESTMV: + if (single_filter[NEARMV][refs[0]] == + single_filter[NEARESTMV][refs[1]]) + best_filter = single_filter[NEARMV][refs[0]]; + break; + case ZERO_ZEROMV: + if (single_filter[ZEROMV][refs[0]] == + single_filter[ZEROMV][refs[1]]) + best_filter = single_filter[ZEROMV][refs[0]]; + break; + case NEW_NEWMV: + if (single_filter[NEWMV][refs[0]] == + single_filter[NEWMV][refs[1]]) + best_filter = single_filter[NEWMV][refs[0]]; + break; + case NEAREST_NEWMV: + if (single_filter[NEARESTMV][refs[0]] == + single_filter[NEWMV][refs[1]]) + best_filter = single_filter[NEARESTMV][refs[0]]; + break; + case NEAR_NEWMV: + if (single_filter[NEARMV][refs[0]] == + single_filter[NEWMV][refs[1]]) + best_filter = single_filter[NEARMV][refs[0]]; + break; + case NEW_NEARESTMV: + if (single_filter[NEWMV][refs[0]] == + single_filter[NEARESTMV][refs[1]]) + best_filter = single_filter[NEWMV][refs[0]]; + break; + case NEW_NEARMV: + if (single_filter[NEWMV][refs[0]] == + single_filter[NEARMV][refs[1]]) + best_filter = single_filter[NEWMV][refs[0]]; + break; + default: + if (single_filter[this_mode][refs[0]] == + single_filter[this_mode][refs[1]]) + best_filter = single_filter[this_mode][refs[0]]; + break; + } +#else if (single_filter[this_mode][refs[0]] == single_filter[this_mode][refs[1]]) best_filter = single_filter[this_mode][refs[0]]; +#endif // CONFIG_EXT_INTER } } @@ -4708,9 +4990,38 @@ static int64_t handle_inter_mode(VP10_COMP *cpi, MACROBLOCK *x, #if CONFIG_EXT_INTER for (i = 0; i < 2; ++i) { single_newmv[refs[i]].as_int = - single_newmvs[mv_idx][refs[i]].as_int; + single_newmvs[mv_idx][refs[i]].as_int; } -#endif // CONFIG_EXT_INTER + + if (this_mode == NEW_NEWMV) { + frame_mv[refs[0]].as_int = single_newmv[refs[0]].as_int; + frame_mv[refs[1]].as_int = single_newmv[refs[1]].as_int; + + if (cpi->sf.comp_inter_joint_search_thresh <= bsize) { + joint_motion_search(cpi, x, bsize, frame_mv, + mi_row, mi_col, NULL, single_newmv, &rate_mv); + } else { + rate_mv = vp10_mv_bit_cost(&frame_mv[refs[0]].as_mv, + &x->mbmi_ext->ref_mvs[refs[0]][0].as_mv, + x->nmvjointcost, x->mvcost, + MV_COST_WEIGHT); + rate_mv += vp10_mv_bit_cost(&frame_mv[refs[1]].as_mv, + &x->mbmi_ext->ref_mvs[refs[1]][0].as_mv, + x->nmvjointcost, x->mvcost, + MV_COST_WEIGHT); + } + } else if (this_mode == NEAREST_NEWMV || this_mode == NEAR_NEWMV) { + frame_mv[refs[1]].as_int = single_newmv[refs[1]].as_int; + rate_mv = vp10_mv_bit_cost(&frame_mv[refs[1]].as_mv, + &x->mbmi_ext->ref_mvs[refs[1]][0].as_mv, + x->nmvjointcost, x->mvcost, MV_COST_WEIGHT); + } else { + frame_mv[refs[0]].as_int = single_newmv[refs[0]].as_int; + rate_mv = vp10_mv_bit_cost(&frame_mv[refs[0]].as_mv, + &x->mbmi_ext->ref_mvs[refs[0]][0].as_mv, + x->nmvjointcost, x->mvcost, MV_COST_WEIGHT); + } +#else // Initialize mv using single prediction mode result. frame_mv[refs[0]].as_int = single_newmv[refs[0]].as_int; frame_mv[refs[1]].as_int = single_newmv[refs[1]].as_int; @@ -4718,9 +5029,6 @@ static int64_t handle_inter_mode(VP10_COMP *cpi, MACROBLOCK *x, if (cpi->sf.comp_inter_joint_search_thresh <= bsize) { joint_motion_search(cpi, x, bsize, frame_mv, mi_row, mi_col, -#if CONFIG_EXT_INTER - NULL, -#endif // CONFIG_EXT_INTER single_newmv, &rate_mv); } else { rate_mv = vp10_mv_bit_cost(&frame_mv[refs[0]].as_mv, @@ -4730,6 +5038,7 @@ static int64_t handle_inter_mode(VP10_COMP *cpi, MACROBLOCK *x, &x->mbmi_ext->ref_mvs[refs[1]][0].as_mv, x->nmvjointcost, x->mvcost, MV_COST_WEIGHT); } +#endif // CONFIG_EXT_INTER *rate2 += rate_mv; } else { int_mv tmp_mv; @@ -4777,8 +5086,12 @@ static int64_t handle_inter_mode(VP10_COMP *cpi, MACROBLOCK *x, } #if CONFIG_REF_MV +#if CONFIG_EXT_INTER + if (this_mode == NEAREST_NEARESTMV) { +#else if (this_mode == NEARESTMV && is_comp_pred) { uint8_t ref_frame_type = vp10_ref_frame_type(mbmi->ref_frame); +#endif // CONFIG_EXT_INTER if (mbmi_ext->ref_mv_count[ref_frame_type] > 0) { cur_mv[0] = mbmi_ext->ref_mv_stack[ref_frame_type][0].this_mv; cur_mv[1] = mbmi_ext->ref_mv_stack[ref_frame_type][0].comp_mv; @@ -4793,6 +5106,51 @@ static int64_t handle_inter_mode(VP10_COMP *cpi, MACROBLOCK *x, } } +#if CONFIG_EXT_INTER + if (mbmi_ext->ref_mv_count[ref_frame_type] > 0) { + if (this_mode == NEAREST_NEWMV || this_mode == NEAREST_NEARMV) { + cur_mv[0] = mbmi_ext->ref_mv_stack[ref_frame_type][0].this_mv; + + lower_mv_precision(&cur_mv[0].as_mv, cm->allow_high_precision_mv); + clamp_mv2(&cur_mv[0].as_mv, xd); + if (mv_check_bounds(x, &cur_mv[0].as_mv)) + return INT64_MAX; + mbmi->mv[0].as_int = cur_mv[0].as_int; + } + + if (this_mode == NEW_NEARESTMV || this_mode == NEAR_NEARESTMV) { + cur_mv[1] = mbmi_ext->ref_mv_stack[ref_frame_type][0].comp_mv; + + lower_mv_precision(&cur_mv[1].as_mv, cm->allow_high_precision_mv); + clamp_mv2(&cur_mv[1].as_mv, xd); + if (mv_check_bounds(x, &cur_mv[1].as_mv)) + return INT64_MAX; + mbmi->mv[1].as_int = cur_mv[1].as_int; + } + } + + if (mbmi_ext->ref_mv_count[ref_frame_type] > 1) { + if (this_mode == NEAR_NEWMV || this_mode == NEAR_NEARESTMV) { + cur_mv[0] = mbmi_ext->ref_mv_stack[ref_frame_type][1].this_mv; + + lower_mv_precision(&cur_mv[0].as_mv, cm->allow_high_precision_mv); + clamp_mv2(&cur_mv[0].as_mv, xd); + if (mv_check_bounds(x, &cur_mv[0].as_mv)) + return INT64_MAX; + mbmi->mv[0].as_int = cur_mv[0].as_int; + } + + if (this_mode == NEW_NEARMV || this_mode == NEAREST_NEARMV) { + cur_mv[1] = mbmi_ext->ref_mv_stack[ref_frame_type][1].comp_mv; + + lower_mv_precision(&cur_mv[1].as_mv, cm->allow_high_precision_mv); + clamp_mv2(&cur_mv[1].as_mv, xd); + if (mv_check_bounds(x, &cur_mv[1].as_mv)) + return INT64_MAX; + mbmi->mv[1].as_int = cur_mv[1].as_int; + } + } +#else if (this_mode == NEARMV && is_comp_pred) { uint8_t ref_frame_type = vp10_ref_frame_type(mbmi->ref_frame); if (mbmi_ext->ref_mv_count[ref_frame_type] > 1) { @@ -4808,6 +5166,7 @@ static int64_t handle_inter_mode(VP10_COMP *cpi, MACROBLOCK *x, } } } +#endif // CONFIG_EXT_INTER #endif // do first prediction into the destination buffer. Do the next @@ -4845,7 +5204,11 @@ static int64_t handle_inter_mode(VP10_COMP *cpi, MACROBLOCK *x, } if (RDCOST(x->rdmult, x->rddiv, *rate2, 0) > ref_best_rd && +#if CONFIG_EXT_INTER + mbmi->mode != NEARESTMV && mbmi->mode != NEAREST_NEARESTMV) +#else mbmi->mode != NEARESTMV) +#endif // CONFIG_EXT_INTER return INT64_MAX; pred_exists = 0; @@ -4994,9 +5357,64 @@ static int64_t handle_inter_mode(VP10_COMP *cpi, MACROBLOCK *x, if (cpi->sf.adaptive_mode_search) if (is_comp_pred) +#if CONFIG_EXT_INTER + switch (this_mode) { + case NEAREST_NEARESTMV: + if (single_skippable[NEARESTMV][refs[0]] && + single_skippable[NEARESTMV][refs[1]]) + memset(skip_txfm, SKIP_TXFM_AC_DC, sizeof(skip_txfm)); + break; + case ZERO_ZEROMV: + if (single_skippable[ZEROMV][refs[0]] && + single_skippable[ZEROMV][refs[1]]) + memset(skip_txfm, SKIP_TXFM_AC_DC, sizeof(skip_txfm)); + break; + case NEW_NEWMV: + if (single_skippable[NEWMV][refs[0]] && + single_skippable[NEWMV][refs[1]]) + memset(skip_txfm, SKIP_TXFM_AC_DC, sizeof(skip_txfm)); + break; + case NEAREST_NEWMV: + if (single_skippable[NEARESTMV][refs[0]] && + single_skippable[NEWMV][refs[1]]) + memset(skip_txfm, SKIP_TXFM_AC_DC, sizeof(skip_txfm)); + break; + case NEAR_NEWMV: + if (single_skippable[NEARMV][refs[0]] && + single_skippable[NEWMV][refs[1]]) + memset(skip_txfm, SKIP_TXFM_AC_DC, sizeof(skip_txfm)); + break; + case NEW_NEARESTMV: + if (single_skippable[NEWMV][refs[0]] && + single_skippable[NEARESTMV][refs[1]]) + memset(skip_txfm, SKIP_TXFM_AC_DC, sizeof(skip_txfm)); + break; + case NEW_NEARMV: + if (single_skippable[NEWMV][refs[0]] && + single_skippable[NEARMV][refs[1]]) + memset(skip_txfm, SKIP_TXFM_AC_DC, sizeof(skip_txfm)); + break; + case NEAREST_NEARMV: + if (single_skippable[NEARESTMV][refs[0]] && + single_skippable[NEARMV][refs[1]]) + memset(skip_txfm, SKIP_TXFM_AC_DC, sizeof(skip_txfm)); + break; + case NEAR_NEARESTMV: + if (single_skippable[NEARMV][refs[0]] && + single_skippable[NEARESTMV][refs[1]]) + memset(skip_txfm, SKIP_TXFM_AC_DC, sizeof(skip_txfm)); + break; + default: + if (single_skippable[this_mode][refs[0]] && + single_skippable[this_mode][refs[1]]) + memset(skip_txfm, SKIP_TXFM_AC_DC, sizeof(skip_txfm)); + break; + } +#else if (single_skippable[this_mode][refs[0]] && single_skippable[this_mode][refs[1]]) memset(skip_txfm, SKIP_TXFM_AC_DC, sizeof(skip_txfm)); +#endif // CONFIG_EXT_INTER if (cpi->sf.use_rd_breakout && ref_best_rd < INT64_MAX) { // if current pred_error modeled rd is substantially more than the best @@ -5387,6 +5805,9 @@ 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 CONFIG_REF_MV && CONFIG_EXT_INTER + x->mbmi_ext->compound_mode_context[ref_frame] = 0; +#endif // CONFIG_REF_MV && CONFIG_EXT_INTER 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, @@ -5396,6 +5817,8 @@ void vp10_rd_pick_inter_mode_sb(VP10_COMP *cpi, frame_mv[ZEROMV][ref_frame].as_int = 0; #if CONFIG_EXT_INTER frame_mv[NEWFROMNEARMV][ref_frame].as_int = INVALID_MV; + frame_mv[NEW_NEWMV][ref_frame].as_int = INVALID_MV; + frame_mv[ZERO_ZEROMV][ref_frame].as_int = 0; #endif // CONFIG_EXT_INTER } @@ -5408,6 +5831,9 @@ void vp10_rd_pick_inter_mode_sb(VP10_COMP *cpi, #if CONFIG_REF_MV &mbmi_ext->ref_mv_count[ref_frame], mbmi_ext->ref_mv_stack[ref_frame], +#if CONFIG_EXT_INTER + mbmi_ext->compound_mode_context, +#endif // CONFIG_EXT_INTER #endif candidates, mi_row, mi_col, NULL, NULL, mbmi_ext->mode_context); @@ -5462,6 +5888,14 @@ void vp10_rd_pick_inter_mode_sb(VP10_COMP *cpi, mode_skip_mask[ALTREF_FRAME] |= (1 << NEARMV); if (frame_mv[NEARESTMV][ALTREF_FRAME].as_int != 0) mode_skip_mask[ALTREF_FRAME] |= (1 << NEARESTMV); +#if CONFIG_EXT_INTER + if (frame_mv[NEAREST_NEARESTMV][ALTREF_FRAME].as_int != 0) + mode_skip_mask[ALTREF_FRAME] |= (1 << NEAREST_NEARESTMV); + if (frame_mv[NEAREST_NEARMV][ALTREF_FRAME].as_int != 0) + mode_skip_mask[ALTREF_FRAME] |= (1 << NEAREST_NEARMV); + if (frame_mv[NEAR_NEARESTMV][ALTREF_FRAME].as_int != 0) + mode_skip_mask[ALTREF_FRAME] |= (1 << NEAR_NEARESTMV); +#endif // CONFIG_EXT_INTER } } @@ -5531,6 +5965,50 @@ void vp10_rd_pick_inter_mode_sb(VP10_COMP *cpi, ref_frame = vp10_mode_order[mode_index].ref_frame[0]; second_ref_frame = vp10_mode_order[mode_index].ref_frame[1]; +#if CONFIG_EXT_INTER + if (this_mode == NEAREST_NEARESTMV) { + frame_mv[NEAREST_NEARESTMV][ref_frame].as_int = + frame_mv[NEARESTMV][ref_frame].as_int; + frame_mv[NEAREST_NEARESTMV][second_ref_frame].as_int = + frame_mv[NEARESTMV][second_ref_frame].as_int; + } else if (this_mode == NEAREST_NEARMV) { + frame_mv[NEAREST_NEARMV][ref_frame].as_int = + frame_mv[NEARESTMV][ref_frame].as_int; + frame_mv[NEAREST_NEARMV][second_ref_frame].as_int = + frame_mv[NEARMV][second_ref_frame].as_int; + } else if (this_mode == NEAR_NEARESTMV) { + frame_mv[NEAR_NEARESTMV][ref_frame].as_int = + frame_mv[NEARMV][ref_frame].as_int; + frame_mv[NEAR_NEARESTMV][second_ref_frame].as_int = + frame_mv[NEARESTMV][second_ref_frame].as_int; + } else if (this_mode == NEAREST_NEWMV) { + frame_mv[NEAREST_NEWMV][ref_frame].as_int = + frame_mv[NEARESTMV][ref_frame].as_int; + frame_mv[NEAREST_NEWMV][second_ref_frame].as_int = + frame_mv[NEWMV][second_ref_frame].as_int; + } else if (this_mode == NEW_NEARESTMV) { + frame_mv[NEW_NEARESTMV][ref_frame].as_int = + frame_mv[NEWMV][ref_frame].as_int; + frame_mv[NEW_NEARESTMV][second_ref_frame].as_int = + frame_mv[NEARESTMV][second_ref_frame].as_int; + } else if (this_mode == NEAR_NEWMV) { + frame_mv[NEAR_NEWMV][ref_frame].as_int = + frame_mv[NEARMV][ref_frame].as_int; + frame_mv[NEAR_NEWMV][second_ref_frame].as_int = + frame_mv[NEWMV][second_ref_frame].as_int; + } else if (this_mode == NEW_NEARMV) { + frame_mv[NEW_NEARMV][ref_frame].as_int = + frame_mv[NEWMV][ref_frame].as_int; + frame_mv[NEW_NEARMV][second_ref_frame].as_int = + frame_mv[NEARMV][second_ref_frame].as_int; + } else if (this_mode == NEW_NEWMV) { + frame_mv[NEW_NEWMV][ref_frame].as_int = + frame_mv[NEWMV][ref_frame].as_int; + frame_mv[NEW_NEWMV][second_ref_frame].as_int = + frame_mv[NEWMV][second_ref_frame].as_int; + } +#endif // CONFIG_EXT_INTER + // Look at the reference frame of the best mode so far and set the // skip mask to look at a subset of the remaining modes. if (midx == mode_skip_start && best_mode_index >= 0) { @@ -5635,7 +6113,11 @@ 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, + if (!check_best_zero_mv(cpi, mbmi_ext->mode_context, +#if CONFIG_REF_MV && CONFIG_EXT_INTER + mbmi_ext->compound_mode_context, +#endif // CONFIG_REF_MV && CONFIG_EXT_INTER + frame_mv, this_mode, ref_frames, bsize, -1)) continue; } @@ -6008,6 +6490,7 @@ void vp10_rd_pick_inter_mode_sb(VP10_COMP *cpi, if (best_mbmode.mode == NEWMV #if CONFIG_EXT_INTER || best_mbmode.mode == NEWFROMNEARMV + || best_mbmode.mode == NEW_NEWMV #endif // CONFIG_EXT_INTER ) { const MV_REFERENCE_FRAME refs[2] = {best_mbmode.ref_frame[0], @@ -6048,14 +6531,29 @@ void vp10_rd_pick_inter_mode_sb(VP10_COMP *cpi, if (nearestmv[0].as_int == best_mbmode.mv[0].as_int && nearestmv[1].as_int == best_mbmode.mv[1].as_int) +#if CONFIG_EXT_INTER + best_mbmode.mode = NEAREST_NEARESTMV; + else if (nearestmv[0].as_int == best_mbmode.mv[0].as_int && + nearmv[1].as_int == best_mbmode.mv[1].as_int) + best_mbmode.mode = NEAREST_NEARMV; + else if (nearmv[0].as_int == best_mbmode.mv[0].as_int && + nearestmv[1].as_int == best_mbmode.mv[1].as_int) + best_mbmode.mode = NEAR_NEARESTMV; + else if (best_mbmode.mv[0].as_int == 0 && best_mbmode.mv[1].as_int == 0) + best_mbmode.mode = ZERO_ZEROMV; +#else best_mbmode.mode = NEARESTMV; else if (nearmv[0].as_int == best_mbmode.mv[0].as_int && nearmv[1].as_int == best_mbmode.mv[1].as_int) best_mbmode.mode = NEARMV; else if (best_mbmode.mv[0].as_int == 0 && best_mbmode.mv[1].as_int == 0) best_mbmode.mode = ZEROMV; +#endif // CONFIG_EXT_INTER } #else +#if CONFIG_EXT_INTER + if (!comp_pred_mode) { +#endif // CONFIG_EXT_INTER if (frame_mv[NEARESTMV][refs[0]].as_int == best_mbmode.mv[0].as_int && ((comp_pred_mode && frame_mv[NEARESTMV][refs[1]].as_int == best_mbmode.mv[1].as_int) || !comp_pred_mode)) @@ -6067,16 +6565,46 @@ void vp10_rd_pick_inter_mode_sb(VP10_COMP *cpi, else if (best_mbmode.mv[0].as_int == 0 && ((comp_pred_mode && best_mbmode.mv[1].as_int == 0) || !comp_pred_mode)) best_mbmode.mode = ZEROMV; +#if CONFIG_EXT_INTER + } else { + const MV_REFERENCE_FRAME refs[2] = {best_mbmode.ref_frame[0], + best_mbmode.ref_frame[1]}; + + if (frame_mv[NEAREST_NEARESTMV][refs[0]].as_int == + best_mbmode.mv[0].as_int && + frame_mv[NEAREST_NEARESTMV][refs[1]].as_int == + best_mbmode.mv[1].as_int) + best_mbmode.mode = NEAREST_NEARESTMV; + else if (frame_mv[NEAREST_NEARMV][refs[0]].as_int == + best_mbmode.mv[0].as_int && + frame_mv[NEAREST_NEARMV][refs[1]].as_int == + best_mbmode.mv[1].as_int) + best_mbmode.mode = NEAREST_NEARMV; + else if (frame_mv[NEAR_NEARESTMV][refs[0]].as_int == + best_mbmode.mv[0].as_int && + frame_mv[NEAR_NEARESTMV][refs[1]].as_int == + best_mbmode.mv[1].as_int) + best_mbmode.mode = NEAR_NEARESTMV; + else if (best_mbmode.mv[0].as_int == 0 && best_mbmode.mv[1].as_int == 0) + best_mbmode.mode = ZERO_ZEROMV; + } +#endif // CONFIG_EXT_INTER #endif } #if CONFIG_REF_MV if (best_mbmode.ref_frame[0] > INTRA_FRAME && best_mbmode.mv[0].as_int == 0 && +#if CONFIG_EXT_INTER + best_mbmode.ref_frame[1] == NONE) { +#else (best_mbmode.ref_frame[1] == NONE || best_mbmode.mv[1].as_int == 0)) { +#endif // CONFIG_EXT_INTER int16_t mode_ctx = mbmi_ext->mode_context[best_mbmode.ref_frame[0]]; +#if !CONFIG_EXT_INTER if (best_mbmode.ref_frame[1] > NONE) mode_ctx &= (mbmi_ext->mode_context[best_mbmode.ref_frame[1]] | 0x00ff); +#endif // !CONFIG_EXT_INTER if (mode_ctx & (1 << ALL_ZERO_FLAG_OFFSET)) best_mbmode.mode = ZEROMV; @@ -6381,6 +6909,9 @@ void vp10_rd_pick_inter_mode_sub8x8(struct VP10_COMP *cpi, for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ref_frame++) { x->mbmi_ext->mode_context[ref_frame] = 0; +#if CONFIG_REF_MV && CONFIG_EXT_INTER + x->mbmi_ext->compound_mode_context[ref_frame] = 0; +#endif // CONFIG_REF_MV && CONFIG_EXT_INTER 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], diff --git a/vp10/encoder/speed_features.h b/vp10/encoder/speed_features.h index a48a76c31..170e53742 100644 --- a/vp10/encoder/speed_features.h +++ b/vp10/encoder/speed_features.h @@ -35,16 +35,40 @@ enum { enum { INTER_ALL = (1 << NEARESTMV) | (1 << NEARMV) | (1 << ZEROMV) | - (1 << NEWMV) | (1 << NEWFROMNEARMV), - INTER_NEAREST = (1 << NEARESTMV), - INTER_NEAREST_NEW = (1 << NEARESTMV) | (1 << NEWMV) | (1 << NEWFROMNEARMV), - INTER_NEAREST_ZERO = (1 << NEARESTMV) | (1 << ZEROMV), + (1 << NEWMV) | (1 << NEWFROMNEARMV) | + (1 << NEAREST_NEARESTMV) | (1 << ZERO_ZEROMV) | (1 << NEAREST_NEARMV) | + (1 << NEAR_NEARESTMV) | (1 << NEW_NEWMV) | (1 << NEAREST_NEWMV) | + (1 << NEAR_NEWMV) | (1 << NEW_NEARMV) | (1 << NEW_NEARESTMV), + INTER_NEAREST = (1 << NEARESTMV) | (1 << NEAREST_NEARESTMV) | + (1 << NEAREST_NEARMV) | (1 << NEAR_NEARESTMV) | + (1 << NEW_NEARESTMV) | (1 << NEAREST_NEWMV), + INTER_NEAREST_NEW = (1 << NEARESTMV) | (1 << NEWMV) | (1 << NEWFROMNEARMV) | + (1 << NEAREST_NEARESTMV) | (1 << NEW_NEWMV) | + (1 << NEAR_NEARESTMV) | (1 << NEAREST_NEARMV) | + (1 << NEW_NEARESTMV) | (1 << NEAREST_NEWMV) | + (1 << NEW_NEARMV) | (1 << NEAR_NEWMV), + INTER_NEAREST_ZERO = (1 << NEARESTMV) | (1 << ZEROMV) | + (1 << NEAREST_NEARESTMV) | (1 << ZERO_ZEROMV) | + (1 << NEAREST_NEARMV) | (1 << NEAR_NEARESTMV) | + (1 << NEAREST_NEWMV) | (1 << NEW_NEARESTMV), INTER_NEAREST_NEW_ZERO = - (1 << NEARESTMV) | (1 << ZEROMV) | (1 << NEWMV) | (1 << NEWFROMNEARMV), + (1 << NEARESTMV) | (1 << ZEROMV) | (1 << NEWMV) | (1 << NEWFROMNEARMV) | + (1 << NEAREST_NEARESTMV) | (1 << ZERO_ZEROMV) | (1 << NEW_NEWMV) | + (1 << NEAREST_NEARMV) | (1 << NEAR_NEARESTMV) | + (1 << NEW_NEARESTMV) | (1 << NEAREST_NEWMV) | + (1 << NEW_NEARMV) | (1 << NEAR_NEWMV), INTER_NEAREST_NEAR_NEW = - (1 << NEARESTMV) | (1 << NEARMV) | (1 << NEWMV) | (1 << NEWFROMNEARMV), + (1 << NEARESTMV) | (1 << NEARMV) | (1 << NEWMV) | (1 << NEWFROMNEARMV) | + (1 << NEAREST_NEARESTMV) | (1 << NEW_NEWMV) | + (1 << NEAREST_NEARMV) | (1 << NEAR_NEARESTMV) | + (1 << NEW_NEARESTMV) | (1 << NEAREST_NEWMV) | + (1 << NEW_NEARMV) | (1 << NEAR_NEWMV), INTER_NEAREST_NEAR_ZERO = - (1 << NEARESTMV) | (1 << NEARMV) | (1 << ZEROMV) + (1 << NEARESTMV) | (1 << NEARMV) | (1 << ZEROMV) | + (1 << NEAREST_NEARESTMV) | (1 << ZERO_ZEROMV) | + (1 << NEAREST_NEARMV) | (1 << NEAR_NEARESTMV) | + (1 << NEAREST_NEWMV) | (1 << NEW_NEARESTMV) | + (1 << NEW_NEARMV) | (1 << NEAR_NEWMV) }; #else enum {