diff --git a/vp10/common/entropymode.c b/vp10/common/entropymode.c index 5c2d51b9a..4d9f773d6 100644 --- a/vp10/common/entropymode.c +++ b/vp10/common/entropymode.c @@ -184,6 +184,10 @@ static const vpx_prob default_refmv_prob[REFMV_MODE_CONTEXTS] = { 220, 220, 200, 200, 180, 128, 30, 220, 30, }; +static const vpx_prob default_drl_prob[DRL_MODE_CONTEXTS] = { + 128, 128, 128, +}; + #if CONFIG_EXT_INTER static const vpx_prob default_new2mv_prob = 180; #endif @@ -1292,6 +1296,8 @@ static void init_mode_probs(FRAME_CONTEXT *fc) { vp10_copy(fc->newmv_prob, default_newmv_prob); vp10_copy(fc->zeromv_prob, default_zeromv_prob); vp10_copy(fc->refmv_prob, default_refmv_prob); + vp10_copy(fc->drl_prob0, default_drl_prob); + vp10_copy(fc->drl_prob1, default_drl_prob); #if CONFIG_EXT_INTER fc->new2mv_prob = default_new2mv_prob; #endif // CONFIG_EXT_INTER @@ -1360,6 +1366,13 @@ void vp10_adapt_inter_frame_probs(VP10_COMMON *cm) { fc->refmv_prob[i] = mode_mv_merge_probs(pre_fc->refmv_prob[i], counts->refmv_mode[i]); + for (i = 0; i < DRL_MODE_CONTEXTS; ++i) + fc->drl_prob0[i] = mode_mv_merge_probs(pre_fc->drl_prob0[i], + counts->drl_mode0[i]); + for (i = 0; i < DRL_MODE_CONTEXTS; ++i) + fc->drl_prob1[i] = mode_mv_merge_probs(pre_fc->drl_prob1[i], + counts->drl_mode1[i]); + #if CONFIG_EXT_INTER fc->new2mv_prob = mode_mv_merge_probs(pre_fc->new2mv_prob, counts->new2mv_mode); diff --git a/vp10/common/entropymode.h b/vp10/common/entropymode.h index fbadc4e07..4b4bdf12f 100644 --- a/vp10/common/entropymode.h +++ b/vp10/common/entropymode.h @@ -68,6 +68,9 @@ typedef struct frame_contexts { vpx_prob newmv_prob[NEWMV_MODE_CONTEXTS]; vpx_prob zeromv_prob[ZEROMV_MODE_CONTEXTS]; vpx_prob refmv_prob[REFMV_MODE_CONTEXTS]; + vpx_prob drl_prob0[DRL_MODE_CONTEXTS]; + vpx_prob drl_prob1[DRL_MODE_CONTEXTS]; + #if CONFIG_EXT_INTER vpx_prob new2mv_prob; #endif // CONFIG_EXT_INTER @@ -121,6 +124,8 @@ typedef struct FRAME_COUNTS { unsigned int newmv_mode[NEWMV_MODE_CONTEXTS][2]; unsigned int zeromv_mode[ZEROMV_MODE_CONTEXTS][2]; unsigned int refmv_mode[REFMV_MODE_CONTEXTS][2]; + unsigned int drl_mode0[DRL_MODE_CONTEXTS][2]; + unsigned int drl_mode1[DRL_MODE_CONTEXTS][2]; #if CONFIG_EXT_INTER unsigned int new2mv_mode[2]; #endif // CONFIG_EXT_INTER diff --git a/vp10/common/enums.h b/vp10/common/enums.h index fdcde99e6..f41b8d945 100644 --- a/vp10/common/enums.h +++ b/vp10/common/enums.h @@ -231,6 +231,7 @@ typedef enum { #define NEWMV_MODE_CONTEXTS 7 #define ZEROMV_MODE_CONTEXTS 2 #define REFMV_MODE_CONTEXTS 9 +#define DRL_MODE_CONTEXTS 3 #define ZEROMV_OFFSET 3 #define REFMV_OFFSET 4 @@ -251,6 +252,7 @@ typedef enum { #define MAX_MV_REF_CANDIDATES 2 #if CONFIG_REF_MV #define MAX_REF_MV_STACK_SIZE 16 +#define REF_CAT_LEVEL 160 #endif #define INTRA_INTER_CONTEXTS 4 diff --git a/vp10/common/mvref_common.c b/vp10/common/mvref_common.c index 53394e94d..1b7fb7d9f 100644 --- a/vp10/common/mvref_common.c +++ b/vp10/common/mvref_common.c @@ -329,6 +329,9 @@ static void setup_ref_mv_list(const VP10_COMMON *cm, const MACROBLOCKD *xd, nearest_refmv_count = *refmv_count; + for (idx = 0; idx < nearest_refmv_count; ++idx) + ref_mv_stack[idx].weight += REF_CAT_LEVEL; + if (prev_frame_mvs_base && cm->show_frame && cm->last_show_frame && rf[1] == NONE) { int ref; diff --git a/vp10/common/mvref_common.h b/vp10/common/mvref_common.h index 3a77147e9..224c5edfa 100644 --- a/vp10/common/mvref_common.h +++ b/vp10/common/mvref_common.h @@ -257,6 +257,24 @@ static INLINE int16_t vp10_mode_context_analyzer( else return mode_context[rf[0]]; } + +static INLINE uint8_t vp10_drl_ctx(const CANDIDATE_MV *ref_mv_stack, + int ref_idx) { + if (ref_mv_stack[ref_idx + 1].weight > REF_CAT_LEVEL && + ref_mv_stack[ref_idx + 2].weight > REF_CAT_LEVEL) + return 0; + + if (ref_mv_stack[ref_idx + 1].weight > REF_CAT_LEVEL && + ref_mv_stack[ref_idx + 2].weight < REF_CAT_LEVEL) + return 1; + + if (ref_mv_stack[ref_idx + 1].weight < REF_CAT_LEVEL && + ref_mv_stack[ref_idx + 2].weight < REF_CAT_LEVEL) + return 2; + + assert(0); + return 0; +} #endif typedef void (*find_mv_refs_sync)(void *const data, int mi_row); diff --git a/vp10/common/thread_common.c b/vp10/common/thread_common.c index bacc53459..6e959edbd 100644 --- a/vp10/common/thread_common.c +++ b/vp10/common/thread_common.c @@ -379,6 +379,15 @@ void vp10_accumulate_frame_counts(VP10_COMMON *cm, FRAME_COUNTS *counts, for (j = 0; j < 2; ++j) cm->counts.refmv_mode[i][j] += counts->refmv_mode[i][j]; + + for (i = 0; i < DRL_MODE_CONTEXTS; ++i) + for (j = 0; j < 2; ++j) + cm->counts.drl_mode0[i][j] += counts->drl_mode0[i][j]; + + for (i = 0; i < DRL_MODE_CONTEXTS; ++i) + for (j = 0; j < 2; ++j) + cm->counts.drl_mode1[i][j] += counts->drl_mode1[i][j]; + #if CONFIG_EXT_INTER for (j = 0; j < 2; ++j) cm->counts.new2mv_mode[j] += counts->new2mv_mode[j]; diff --git a/vp10/decoder/decodeframe.c b/vp10/decoder/decodeframe.c index a26f969cc..ec1a5fb78 100644 --- a/vp10/decoder/decodeframe.c +++ b/vp10/decoder/decodeframe.c @@ -132,6 +132,10 @@ static void read_inter_mode_probs(FRAME_CONTEXT *fc, vpx_reader *r) { vp10_diff_update_prob(r, &fc->zeromv_prob[i]); for (i = 0; i < REFMV_MODE_CONTEXTS; ++i) vp10_diff_update_prob(r, &fc->refmv_prob[i]); + for (i = 0; i < DRL_MODE_CONTEXTS; ++i) + vp10_diff_update_prob(r, &fc->drl_prob0[i]); + for (i = 0; i < DRL_MODE_CONTEXTS; ++i) + vp10_diff_update_prob(r, &fc->drl_prob1[i]); #if CONFIG_EXT_INTER vp10_diff_update_prob(r, &fc->new2mv_prob); #endif // CONFIG_EXT_INTER diff --git a/vp10/decoder/decodemv.c b/vp10/decoder/decodemv.c index 8d26c62de..51bf2b390 100644 --- a/vp10/decoder/decodemv.c +++ b/vp10/decoder/decodemv.c @@ -147,6 +147,45 @@ static PREDICTION_MODE read_inter_mode(VP10_COMMON *cm, MACROBLOCKD *xd, #endif } +#if CONFIG_REF_MV +static void read_drl_idx(const VP10_COMMON *cm, + MACROBLOCKD *xd, + MB_MODE_INFO *mbmi, + vpx_reader *r) { + uint8_t ref_frame_type = vp10_ref_frame_type(mbmi->ref_frame); + mbmi->ref_mv_idx = 0; + + if (xd->ref_mv_count[ref_frame_type] > 2) { + uint8_t drl0_ctx = vp10_drl_ctx(xd->ref_mv_stack[ref_frame_type], 0); + vpx_prob drl0_prob = cm->fc->drl_prob0[drl0_ctx]; + if (vpx_read(r, drl0_prob)) { + mbmi->ref_mv_idx = 1; + if (xd->counts) + ++xd->counts->drl_mode0[drl0_ctx][1]; + if (xd->ref_mv_count[ref_frame_type] > 3) { + uint8_t drl1_ctx = + vp10_drl_ctx(xd->ref_mv_stack[ref_frame_type], 1); + vpx_prob drl1_prob = cm->fc->drl_prob1[drl1_ctx]; + if (vpx_read(r, drl1_prob)) { + mbmi->ref_mv_idx = 2; + if (xd->counts) + ++xd->counts->drl_mode1[drl1_ctx][1]; + + return; + } + + if (xd->counts) + ++xd->counts->drl_mode1[drl1_ctx][0]; + } + return; + } + + if (xd->counts) + ++xd->counts->drl_mode0[drl0_ctx][0]; + } +} +#endif + #if CONFIG_EXT_INTER static PREDICTION_MODE read_inter_compound_mode(VP10_COMMON *cm, MACROBLOCKD *xd, @@ -1056,17 +1095,8 @@ static void read_inter_block_mode_info(VP10Decoder *const pbi, #endif // CONFIG_REF_MV && CONFIG_EXT_INTER r, mode_ctx); #if CONFIG_REF_MV - if (mbmi->mode == NEARMV) { - uint8_t ref_frame_type = vp10_ref_frame_type(mbmi->ref_frame); - if (xd->ref_mv_count[ref_frame_type] > 2) { - if (vpx_read_bit(r)) { - mbmi->ref_mv_idx = 1; - if (xd->ref_mv_count[ref_frame_type] > 3) - if (vpx_read_bit(r)) - mbmi->ref_mv_idx = 2; - } - } - } + if (mbmi->mode == NEARMV) + read_drl_idx(cm, xd, mbmi, r); #endif } } diff --git a/vp10/encoder/bitstream.c b/vp10/encoder/bitstream.c index d4bd12269..a2edade82 100644 --- a/vp10/encoder/bitstream.c +++ b/vp10/encoder/bitstream.c @@ -177,6 +177,28 @@ static void write_inter_mode(VP10_COMMON *cm, #endif } +#if CONFIG_REF_MV +static void write_drl_idx(const VP10_COMMON *cm, + const MB_MODE_INFO *mbmi, + const MB_MODE_INFO_EXT *mbmi_ext, + vpx_writer *w) { + uint8_t ref_frame_type = vp10_ref_frame_type(mbmi->ref_frame); + if (mbmi_ext->ref_mv_count[ref_frame_type] > 2) { + uint8_t drl0_ctx = + vp10_drl_ctx(mbmi_ext->ref_mv_stack[ref_frame_type], 0); + vpx_prob drl0_prob = cm->fc->drl_prob0[drl0_ctx]; + vpx_write(w, mbmi->ref_mv_idx != 0, drl0_prob); + if (mbmi_ext->ref_mv_count[ref_frame_type] > 3 && + mbmi->ref_mv_idx > 0) { + uint8_t drl1_ctx = + vp10_drl_ctx(mbmi_ext->ref_mv_stack[ref_frame_type], 1); + vpx_prob drl1_prob = cm->fc->drl_prob1[drl1_ctx]; + vpx_write(w, mbmi->ref_mv_idx != 1, drl1_prob); + } + } +} +#endif + #if CONFIG_EXT_INTER static void write_inter_compound_mode(VP10_COMMON *cm, vpx_writer *w, PREDICTION_MODE mode, @@ -312,7 +334,12 @@ static void update_inter_mode_probs(VP10_COMMON *cm, vpx_writer *w, for (i = 0; i < REFMV_MODE_CONTEXTS; ++i) vp10_cond_prob_diff_update(w, &cm->fc->refmv_prob[i], counts->refmv_mode[i]); - + for (i = 0; i < DRL_MODE_CONTEXTS; ++i) + vp10_cond_prob_diff_update(w, &cm->fc->drl_prob0[i], + counts->drl_mode0[i]); + for (i = 0; i < DRL_MODE_CONTEXTS; ++i) + vp10_cond_prob_diff_update(w, &cm->fc->drl_prob1[i], + counts->drl_mode1[i]); #if CONFIG_EXT_INTER vp10_cond_prob_diff_update(w, &cm->fc->new2mv_prob, counts->new2mv_mode); #endif // CONFIG_EXT_INTER @@ -994,15 +1021,8 @@ static void pack_inter_mode_mvs(VP10_COMP *cpi, const MODE_INFO *mi, mode_ctx); #if CONFIG_REF_MV - if (mode == NEARMV) { - uint8_t ref_frame_type = vp10_ref_frame_type(mbmi->ref_frame); - if (mbmi_ext->ref_mv_count[ref_frame_type] > 2) { - vpx_write_bit(w, mbmi->ref_mv_idx != 0); - if (mbmi_ext->ref_mv_count[ref_frame_type] > 3 && - mbmi->ref_mv_idx > 0) - vpx_write_bit(w, mbmi->ref_mv_idx != 1); - } - } + if (mode == NEARMV) + write_drl_idx(cm, mbmi, mbmi_ext, w); #endif } } diff --git a/vp10/encoder/encodeframe.c b/vp10/encoder/encodeframe.c index 859ec49c4..b758b3bd8 100644 --- a/vp10/encoder/encodeframe.c +++ b/vp10/encoder/encodeframe.c @@ -1822,6 +1822,28 @@ static void update_stats(VP10_COMMON *cm, ThreadData *td has_second_ref(mbmi), #endif // CONFIG_EXT_INTER mode_ctx); + + if (mode == NEARMV) { + uint8_t ref_frame_type = vp10_ref_frame_type(mbmi->ref_frame); + if (mbmi_ext->ref_mv_count[ref_frame_type] > 2) { + uint8_t drl0_ctx = + vp10_drl_ctx(mbmi_ext->ref_mv_stack[ref_frame_type], 0); + if (mbmi->ref_mv_idx == 0) + ++counts->drl_mode0[drl0_ctx][0]; + else + ++counts->drl_mode0[drl0_ctx][1]; + + if (mbmi_ext->ref_mv_count[ref_frame_type] > 3 && + mbmi->ref_mv_idx > 0) { + uint8_t drl1_ctx = + vp10_drl_ctx(mbmi_ext->ref_mv_stack[ref_frame_type], 1); + if (mbmi->ref_mv_idx == 1) + ++counts->drl_mode1[drl1_ctx][0]; + else + ++counts->drl_mode1[drl1_ctx][1]; + } + } + } #if CONFIG_EXT_INTER } #endif // CONFIG_EXT_INTER diff --git a/vp10/encoder/encoder.h b/vp10/encoder/encoder.h index 940c9a51a..f7c601339 100644 --- a/vp10/encoder/encoder.h +++ b/vp10/encoder/encoder.h @@ -474,6 +474,8 @@ typedef struct VP10_COMP { int newmv_mode_cost[NEWMV_MODE_CONTEXTS][2]; int zeromv_mode_cost[ZEROMV_MODE_CONTEXTS][2]; int refmv_mode_cost[REFMV_MODE_CONTEXTS][2]; + int drl_mode_cost0[DRL_MODE_CONTEXTS][2]; + int drl_mode_cost1[DRL_MODE_CONTEXTS][2]; #if CONFIG_EXT_INTER int new2mv_mode_cost[2]; #endif // CONFIG_EXT_INTER diff --git a/vp10/encoder/rd.c b/vp10/encoder/rd.c index 1aac71908..8498ce9cc 100644 --- a/vp10/encoder/rd.c +++ b/vp10/encoder/rd.c @@ -382,6 +382,16 @@ void vp10_initialize_rd_consts(VP10_COMP *cpi) { cpi->refmv_mode_cost[i][0] = vp10_cost_bit(cm->fc->refmv_prob[i], 0); cpi->refmv_mode_cost[i][1] = vp10_cost_bit(cm->fc->refmv_prob[i], 1); } + + for (i = 0; i < DRL_MODE_CONTEXTS; ++i) { + cpi->drl_mode_cost0[i][0] = vp10_cost_bit(cm->fc->drl_prob0[i], 0); + cpi->drl_mode_cost0[i][1] = vp10_cost_bit(cm->fc->drl_prob0[i], 1); + } + + for (i = 0; i < DRL_MODE_CONTEXTS; ++i) { + cpi->drl_mode_cost1[i][0] = vp10_cost_bit(cm->fc->drl_prob1[i], 0); + cpi->drl_mode_cost1[i][1] = vp10_cost_bit(cm->fc->drl_prob1[i], 1); + } #if CONFIG_EXT_INTER cpi->new2mv_mode_cost[0] = vp10_cost_bit(cm->fc->new2mv_prob, 0); cpi->new2mv_mode_cost[1] = vp10_cost_bit(cm->fc->new2mv_prob, 1); diff --git a/vp10/encoder/rdopt.c b/vp10/encoder/rdopt.c index af360242f..3f617f81a 100644 --- a/vp10/encoder/rdopt.c +++ b/vp10/encoder/rdopt.c @@ -6380,7 +6380,9 @@ void vp10_rd_pick_inter_mode_sb(VP10_COMP *cpi, int ref_idx; int ref_set = VPXMIN(2, mbmi_ext->ref_mv_count[ref_frame_type] - 2); - rate2 += vp10_cost_bit(128, 0); + uint8_t drl0_ctx = + vp10_drl_ctx(mbmi_ext->ref_mv_stack[ref_frame_type], 0); + rate2 += cpi->drl_mode_cost0[drl0_ctx][0]; if (this_rd < INT64_MAX) { if (RDCOST(x->rdmult, x->rddiv, rate_y + rate_uv, distortion2) < @@ -6440,9 +6442,13 @@ void vp10_rd_pick_inter_mode_sb(VP10_COMP *cpi, dummy_filter_cache); } - tmp_rate += vp10_cost_bit(128, 1); - if (mbmi_ext->ref_mv_count[ref_frame_type] > 3) - tmp_rate += vp10_cost_bit(128, ref_idx); + tmp_rate += cpi->drl_mode_cost0[drl0_ctx][1]; + + if (mbmi_ext->ref_mv_count[ref_frame_type] > 3) { + uint8_t drl1_ctx = + vp10_drl_ctx(mbmi_ext->ref_mv_stack[ref_frame_type], 1); + tmp_rate += cpi->drl_mode_cost1[drl1_ctx][ref_idx]; + } if (tmp_alt_rd < INT64_MAX) { if (RDCOST(x->rdmult, x->rddiv,