From ec8864a8bfbdb90995743ea4c1c9974a0f86c606 Mon Sep 17 00:00:00 2001 From: Zoe Liu Date: Fri, 11 Sep 2015 14:57:31 -0700 Subject: [PATCH] Added MACRO for reference frame encoding This CL introduces a few macros plus code cleaning on the encoding of the reference frames. Coding performance remains unchanged. For the encoding of either the compound reference or the single reference case, since each bit has different contexts, the tree structure may not be applied to treat the combined bits as one symbol. It is possible we may explore the sharing of the same context for all the bits to introduce the use of tree structure for the next step. Change-Id: I6916ae53c66be1a0b23e6273811c0139515484df --- vp9/common/vp9_blockd.h | 8 ++++ vp9/common/vp9_entropymode.c | 80 +++++++++++++++++++++-------------- vp9/common/vp9_entropymode.h | 18 ++------ vp9/common/vp9_pred_common.h | 14 +++--- vp9/decoder/vp9_decodeframe.c | 19 +++------ vp9/decoder/vp9_decodemv.c | 22 +++------- vp9/encoder/vp9_bitstream.c | 27 ++++-------- vp9/encoder/vp9_encodeframe.c | 5 +-- 8 files changed, 90 insertions(+), 103 deletions(-) diff --git a/vp9/common/vp9_blockd.h b/vp9/common/vp9_blockd.h index 9d2d3b0ad..82403dad2 100644 --- a/vp9/common/vp9_blockd.h +++ b/vp9/common/vp9_blockd.h @@ -66,6 +66,14 @@ extern "C" { #define COMP_INTER_CONTEXTS 5 #define REF_CONTEXTS 5 +#if CONFIG_MULTI_REF +#define SINGLE_REFS 4 +#define COMP_REFS 3 +#else +#define SINGLE_REFS 3 +#define COMP_REFS 2 +#endif // CONFIG_MULTI_REF + typedef enum { PLANE_TYPE_Y = 0, PLANE_TYPE_UV = 1, diff --git a/vp9/common/vp9_entropymode.c b/vp9/common/vp9_entropymode.c index 6cb0951f7..3f46412db 100644 --- a/vp9/common/vp9_entropymode.c +++ b/vp9/common/vp9_entropymode.c @@ -415,36 +415,60 @@ static const vp9_prob default_comp_inter_p[COMP_INTER_CONTEXTS] = { 239, 183, 119, 96, 41 }; +static const vp9_prob default_single_ref_probs[REF_CONTEXTS][SINGLE_REFS - 1] = +{ #if CONFIG_MULTI_REF -// TODO(zoeliu): To adjust the initial prob values. -static const vp9_prob default_comp_ref_p[REF_CONTEXTS][2] = { - { 33, 16 }, - { 77, 74 }, - { 142, 142 }, - { 172, 170 }, - { 238, 247 } -}; - -static const vp9_prob default_single_ref_p[REF_CONTEXTS][3] = { + // TODO(zoeliu): To adjust the initial prob values. { 33, 16, 16 }, { 77, 74, 74 }, { 142, 142, 142 }, { 172, 170, 170 }, { 238, 247, 247 } -}; #else -static const vp9_prob default_comp_ref_p[REF_CONTEXTS] = { - 50, 126, 123, 221, 226 + { 33, 16 }, + { 77, 74 }, + { 142, 142 }, + { 172, 170 }, + { 238, 247 } +#endif // CONFIG_MULTI_REF }; -static const vp9_prob default_single_ref_p[REF_CONTEXTS][2] = { +static const vp9_prob default_comp_ref_probs[REF_CONTEXTS][COMP_REFS - 1] = { +#if CONFIG_MULTI_REF + // TODO(zoeliu): To adjust the initial prob values. { 33, 16 }, { 77, 74 }, { 142, 142 }, { 172, 170 }, { 238, 247 } +#else + { 50 }, { 126 }, { 123 }, { 221 }, { 226 } +#endif // CONFIG_MULTI_REF }; + +/* +// TODO(zoeliu): Tree structure may be introduced when all bits of the encoding +// of either the compound or the single references share the same contexts. +const vp9_tree_index vp9_comp_ref_tree[TREE_SIZE(COMP_REFS)] = { +#if CONFIG_MULTI_REF + -REF_OFFSET(GOLDEN_FRAME), 2, + -REF_OFFSET(LAST_FRAME), -REF_OFFSET(LAST2_FRAME) +#else + -REF_OFFSET(GOLDEN_FRAME), -REF_OFFSET(LAST_FRAME) #endif // CONFIG_MULTI_REF +}; + +const vp9_tree_index vp9_single_ref_tree[TREE_SIZE(SINGLE_REFS)] = { +#if CONFIG_MULTI_REF + 2, 4, + -REF_OFFSET(ALTREF_FRAME), -REF_OFFSET(GOLDEN_FRAME), + -REF_OFFSET(LAST2_FRAME), -REF_OFFSET(LAST_FRAME) +#else + 2, -REF_OFFSET(LAST_FRAME), + -REF_OFFSET(ALTREF_FRAME), -REF_OFFSET(GOLDEN_FRAME) +#endif // CONFIG_MULTI_REF +}; +*/ static const struct tx_probs default_tx_probs = { #if CONFIG_TX64X64 @@ -1000,8 +1024,8 @@ void vp9_init_mode_probs(FRAME_CONTEXT *fc) { vp9_copy(fc->partition_prob, default_partition_probs); vp9_copy(fc->intra_inter_prob, default_intra_inter_p); vp9_copy(fc->comp_inter_prob, default_comp_inter_p); - vp9_copy(fc->comp_ref_prob, default_comp_ref_p); - vp9_copy(fc->single_ref_prob, default_single_ref_p); + vp9_copy(fc->single_ref_probs, default_single_ref_probs); + vp9_copy(fc->comp_ref_probs, default_comp_ref_probs); fc->tx_probs = default_tx_probs; vp9_copy(fc->skip_probs, default_skip_probs); vp9_copy(fc->inter_mode_probs, default_inter_mode_probs); @@ -1083,25 +1107,19 @@ void vp9_adapt_mode_probs(VP9_COMMON *cm) { for (i = 0; i < COMP_INTER_CONTEXTS; i++) fc->comp_inter_prob[i] = adapt_prob(pre_fc->comp_inter_prob[i], counts->comp_inter[i]); + for (i = 0; i < REF_CONTEXTS; i++) { -#if CONFIG_MULTI_REF - for (j = 0; j < 2; j++) - fc->comp_ref_prob[i][j] = adapt_prob(pre_fc->comp_ref_prob[i][j], - counts->comp_ref[i][j]); -#else - fc->comp_ref_prob[i] = adapt_prob(pre_fc->comp_ref_prob[i], - counts->comp_ref[i]); -#endif // CONFIG_MULTI_REF + for (j = 0; j < (SINGLE_REFS - 1); j++) { + fc->single_ref_probs[i][j] = adapt_prob(pre_fc->single_ref_probs[i][j], + counts->single_ref[i][j]); + } } for (i = 0; i < REF_CONTEXTS; i++) { -#if CONFIG_MULTI_REF - for (j = 0; j < 3; j++) -#else - for (j = 0; j < 2; j++) -#endif // CONFIG_MULTI_REF - fc->single_ref_prob[i][j] = adapt_prob(pre_fc->single_ref_prob[i][j], - counts->single_ref[i][j]); + for (j = 0; j < (COMP_REFS - 1); j++) { + fc->comp_ref_probs[i][j] = adapt_prob(pre_fc->comp_ref_probs[i][j], + counts->comp_ref[i][j]); + } } for (i = 0; i < INTER_MODE_CONTEXTS; i++) diff --git a/vp9/common/vp9_entropymode.h b/vp9/common/vp9_entropymode.h index a7963925c..d8e5f4cae 100644 --- a/vp9/common/vp9_entropymode.h +++ b/vp9/common/vp9_entropymode.h @@ -74,13 +74,8 @@ typedef struct frame_contexts { #endif // CONFIG_NEW_INTER vp9_prob intra_inter_prob[INTRA_INTER_CONTEXTS]; vp9_prob comp_inter_prob[COMP_INTER_CONTEXTS]; -#if CONFIG_MULTI_REF - vp9_prob single_ref_prob[REF_CONTEXTS][3]; - vp9_prob comp_ref_prob[REF_CONTEXTS][2]; -#else - vp9_prob single_ref_prob[REF_CONTEXTS][2]; - vp9_prob comp_ref_prob[REF_CONTEXTS]; -#endif // CONFIG_MULTI_REF + vp9_prob single_ref_probs[REF_CONTEXTS][SINGLE_REFS - 1]; + vp9_prob comp_ref_probs[REF_CONTEXTS][COMP_REFS - 1]; struct tx_probs tx_probs; vp9_prob skip_probs[SKIP_CONTEXTS]; nmv_context nmvc; @@ -159,13 +154,8 @@ typedef struct { #endif // CONFIG_NEW_INTER unsigned int intra_inter[INTRA_INTER_CONTEXTS][2]; unsigned int comp_inter[COMP_INTER_CONTEXTS][2]; -#if CONFIG_MULTI_REF - unsigned int single_ref[REF_CONTEXTS][3][2]; - unsigned int comp_ref[REF_CONTEXTS][2][2]; -#else - unsigned int single_ref[REF_CONTEXTS][2][2]; - unsigned int comp_ref[REF_CONTEXTS][2]; -#endif // CONFIG_MULTI_REF + unsigned int single_ref[REF_CONTEXTS][SINGLE_REFS-1][2]; + unsigned int comp_ref[REF_CONTEXTS][COMP_REFS-1][2]; struct tx_counts tx; unsigned int skip[SKIP_CONTEXTS][2]; nmv_context_counts mv; diff --git a/vp9/common/vp9_pred_common.h b/vp9/common/vp9_pred_common.h index 8c16f744e..b91c4f9f1 100644 --- a/vp9/common/vp9_pred_common.h +++ b/vp9/common/vp9_pred_common.h @@ -127,11 +127,7 @@ int vp9_get_pred_context_comp_ref_p(const VP9_COMMON *cm, static INLINE vp9_prob vp9_get_pred_prob_comp_ref_p(const VP9_COMMON *cm, const MACROBLOCKD *xd) { const int pred_context = vp9_get_pred_context_comp_ref_p(cm, xd); -#if CONFIG_MULTI_REF - return cm->fc.comp_ref_prob[pred_context][0]; -#else - return cm->fc.comp_ref_prob[pred_context]; -#endif // CONFIG_MULTI_REF + return cm->fc.comp_ref_probs[pred_context][0]; } #if CONFIG_MULTI_REF @@ -141,7 +137,7 @@ int vp9_get_pred_context_comp_ref_p1(const VP9_COMMON *cm, static INLINE vp9_prob vp9_get_pred_prob_comp_ref_p1(const VP9_COMMON *cm, const MACROBLOCKD *xd) { const int pred_context = vp9_get_pred_context_comp_ref_p1(cm, xd); - return cm->fc.comp_ref_prob[pred_context][1]; + return cm->fc.comp_ref_probs[pred_context][1]; } #endif // CONFIG_MULTI_REF @@ -149,14 +145,14 @@ int vp9_get_pred_context_single_ref_p1(const MACROBLOCKD *xd); static INLINE vp9_prob vp9_get_pred_prob_single_ref_p1(const VP9_COMMON *cm, const MACROBLOCKD *xd) { - return cm->fc.single_ref_prob[vp9_get_pred_context_single_ref_p1(xd)][0]; + return cm->fc.single_ref_probs[vp9_get_pred_context_single_ref_p1(xd)][0]; } int vp9_get_pred_context_single_ref_p2(const MACROBLOCKD *xd); static INLINE vp9_prob vp9_get_pred_prob_single_ref_p2(const VP9_COMMON *cm, const MACROBLOCKD *xd) { - return cm->fc.single_ref_prob[vp9_get_pred_context_single_ref_p2(xd)][1]; + return cm->fc.single_ref_probs[vp9_get_pred_context_single_ref_p2(xd)][1]; } #if CONFIG_MULTI_REF @@ -164,7 +160,7 @@ int vp9_get_pred_context_single_ref_p3(const MACROBLOCKD *xd); static INLINE vp9_prob vp9_get_pred_prob_single_ref_p3(const VP9_COMMON *cm, const MACROBLOCKD *xd) { - return cm->fc.single_ref_prob[vp9_get_pred_context_single_ref_p3(xd)][2]; + return cm->fc.single_ref_probs[vp9_get_pred_context_single_ref_p3(xd)][2]; } #endif // CONFIG_MULTI_REF diff --git a/vp9/decoder/vp9_decodeframe.c b/vp9/decoder/vp9_decodeframe.c index 606ee4d77..65b8c563c 100644 --- a/vp9/decoder/vp9_decodeframe.c +++ b/vp9/decoder/vp9_decodeframe.c @@ -164,7 +164,7 @@ static REFERENCE_MODE read_frame_reference_mode(const VP9_COMMON *cm, static void read_frame_reference_mode_probs(VP9_COMMON *cm, vp9_reader *r) { FRAME_CONTEXT *const fc = &cm->fc; - int i; + int i, j; if (cm->reference_mode == REFERENCE_MODE_SELECT) for (i = 0; i < COMP_INTER_CONTEXTS; ++i) @@ -172,21 +172,16 @@ static void read_frame_reference_mode_probs(VP9_COMMON *cm, vp9_reader *r) { if (cm->reference_mode != COMPOUND_REFERENCE) for (i = 0; i < REF_CONTEXTS; ++i) { - vp9_diff_update_prob(r, &fc->single_ref_prob[i][0]); - vp9_diff_update_prob(r, &fc->single_ref_prob[i][1]); -#if CONFIG_MULTI_REF - vp9_diff_update_prob(r, &fc->single_ref_prob[i][2]); -#endif // CONFIG_MULTI_REF + for (j = 0; j < (SINGLE_REFS - 1); ++j) { + vp9_diff_update_prob(r, &fc->single_ref_probs[i][j]); + } } if (cm->reference_mode != SINGLE_REFERENCE) for (i = 0; i < REF_CONTEXTS; ++i) { -#if CONFIG_MULTI_REF - vp9_diff_update_prob(r, &fc->comp_ref_prob[i][0]); - vp9_diff_update_prob(r, &fc->comp_ref_prob[i][1]); -#else - vp9_diff_update_prob(r, &fc->comp_ref_prob[i]); -#endif // CONFIG_MULTI_REF + for (j = 0; j < (COMP_REFS - 1); ++j) { + vp9_diff_update_prob(r, &fc->comp_ref_probs[i][j]); + } } } diff --git a/vp9/decoder/vp9_decodemv.c b/vp9/decoder/vp9_decodemv.c index 442aca5cf..1a77f77c2 100644 --- a/vp9/decoder/vp9_decodemv.c +++ b/vp9/decoder/vp9_decodemv.c @@ -767,25 +767,17 @@ static void read_ref_frames(VP9_COMMON *const cm, MACROBLOCKD *const xd, if (mode == COMPOUND_REFERENCE) { const int idx = cm->ref_frame_sign_bias[cm->comp_fixed_ref]; const int ctx = vp9_get_pred_context_comp_ref_p(cm, xd); -#if CONFIG_MULTI_REF - const int bit = vp9_read(r, fc->comp_ref_prob[ctx][0]); -#else - const int bit = vp9_read(r, fc->comp_ref_prob[ctx]); -#endif // CONFIG_MULTI_REF + const int bit = vp9_read(r, fc->comp_ref_probs[ctx][0]); if (!cm->frame_parallel_decoding_mode) -#if CONFIG_MULTI_REF ++counts->comp_ref[ctx][0][bit]; -#else - ++counts->comp_ref[ctx][bit]; -#endif // CONFIG_MULTI_REF ref_frame[idx] = cm->comp_fixed_ref; #if CONFIG_MULTI_REF if (!bit) { const int ctx1 = vp9_get_pred_context_comp_ref_p1(cm, xd); - const int bit1 = vp9_read(r, fc->comp_ref_prob[ctx1][1]); + const int bit1 = vp9_read(r, fc->comp_ref_probs[ctx1][1]); if (!cm->frame_parallel_decoding_mode) ++counts->comp_ref[ctx1][1][bit1]; @@ -800,30 +792,30 @@ static void read_ref_frames(VP9_COMMON *const cm, MACROBLOCKD *const xd, } else if (mode == SINGLE_REFERENCE) { #if CONFIG_MULTI_REF const int ctx0 = vp9_get_pred_context_single_ref_p1(xd); - const int bit0 = vp9_read(r, fc->single_ref_prob[ctx0][0]); + const int bit0 = vp9_read(r, fc->single_ref_probs[ctx0][0]); if (!cm->frame_parallel_decoding_mode) ++counts->single_ref[ctx0][0][bit0]; if (bit0) { const int ctx1 = vp9_get_pred_context_single_ref_p2(xd); - const int bit1 = vp9_read(r, fc->single_ref_prob[ctx1][1]); + const int bit1 = vp9_read(r, fc->single_ref_probs[ctx1][1]); if (!cm->frame_parallel_decoding_mode) ++counts->single_ref[ctx1][1][bit1]; ref_frame[0] = bit1 ? ALTREF_FRAME : GOLDEN_FRAME; } else { const int ctx2 = vp9_get_pred_context_single_ref_p3(xd); - const int bit2 = vp9_read(r, fc->single_ref_prob[ctx2][2]); + const int bit2 = vp9_read(r, fc->single_ref_probs[ctx2][2]); if (!cm->frame_parallel_decoding_mode) ++counts->single_ref[ctx2][2][bit2]; ref_frame[0] = bit2 ? LAST2_FRAME : LAST_FRAME; } #else const int ctx0 = vp9_get_pred_context_single_ref_p1(xd); - const int bit0 = vp9_read(r, fc->single_ref_prob[ctx0][0]); + const int bit0 = vp9_read(r, fc->single_ref_probs[ctx0][0]); if (!cm->frame_parallel_decoding_mode) ++counts->single_ref[ctx0][0][bit0]; if (bit0) { const int ctx1 = vp9_get_pred_context_single_ref_p2(xd); - const int bit1 = vp9_read(r, fc->single_ref_prob[ctx1][1]); + const int bit1 = vp9_read(r, fc->single_ref_probs[ctx1][1]); if (!cm->frame_parallel_decoding_mode) ++counts->single_ref[ctx1][1][bit1]; ref_frame[0] = bit1 ? ALTREF_FRAME : GOLDEN_FRAME; diff --git a/vp9/encoder/vp9_bitstream.c b/vp9/encoder/vp9_bitstream.c index 6b5d907ec..d0e900faf 100644 --- a/vp9/encoder/vp9_bitstream.c +++ b/vp9/encoder/vp9_bitstream.c @@ -2516,7 +2516,7 @@ static size_t write_compressed_header(VP9_COMP *cpi, uint8_t *data) { #endif // CONFIG_SR_MODE if (!frame_is_intra_only(cm)) { - int i; + int i, j; for (i = 0; i < INTER_MODE_CONTEXTS; ++i) { prob_diff_update(vp9_inter_mode_tree, cm->fc.inter_mode_probs[i], cm->counts.inter_mode[i], INTER_MODES, &header_bc); @@ -2551,28 +2551,19 @@ static size_t write_compressed_header(VP9_COMP *cpi, uint8_t *data) { if (cm->reference_mode != COMPOUND_REFERENCE) { for (i = 0; i < REF_CONTEXTS; i++) { - vp9_cond_prob_diff_update(&header_bc, &fc->single_ref_prob[i][0], - cm->counts.single_ref[i][0]); - vp9_cond_prob_diff_update(&header_bc, &fc->single_ref_prob[i][1], - cm->counts.single_ref[i][1]); -#if CONFIG_MULTI_REF - vp9_cond_prob_diff_update(&header_bc, &fc->single_ref_prob[i][2], - cm->counts.single_ref[i][2]); -#endif // CONFIG_MULTI_REF + for (j = 0; j < (SINGLE_REFS - 1); j++) { + vp9_cond_prob_diff_update(&header_bc, &fc->single_ref_probs[i][j], + cm->counts.single_ref[i][j]); + } } } if (cm->reference_mode != SINGLE_REFERENCE) { for (i = 0; i < REF_CONTEXTS; i++) { -#if CONFIG_MULTI_REF - vp9_cond_prob_diff_update(&header_bc, &fc->comp_ref_prob[i][0], - cm->counts.comp_ref[i][0]); - vp9_cond_prob_diff_update(&header_bc, &fc->comp_ref_prob[i][1], - cm->counts.comp_ref[i][1]); -#else - vp9_cond_prob_diff_update(&header_bc, &fc->comp_ref_prob[i], - cm->counts.comp_ref[i]); -#endif // CONFIG_MULTI_REF + for (j = 0; j < (COMP_REFS - 1); j++) { + vp9_cond_prob_diff_update(&header_bc, &fc->comp_ref_probs[i][j], + cm->counts.comp_ref[i][j]); + } } } diff --git a/vp9/encoder/vp9_encodeframe.c b/vp9/encoder/vp9_encodeframe.c index 72cc139f0..0f801a370 100644 --- a/vp9/encoder/vp9_encodeframe.c +++ b/vp9/encoder/vp9_encodeframe.c @@ -1522,16 +1522,13 @@ static void update_stats(VP9_COMMON *cm, const MACROBLOCK *x) { [has_second_ref(mbmi)]++; if (has_second_ref(mbmi)) { -#if CONFIG_MULTI_REF counts->comp_ref[vp9_get_pred_context_comp_ref_p(cm, xd)][0] [ref0 == GOLDEN_FRAME]++; +#if CONFIG_MULTI_REF if (ref0 != GOLDEN_FRAME) { counts->comp_ref[vp9_get_pred_context_comp_ref_p1(cm, xd)][1] [ref0 == LAST_FRAME]++; } -#else - counts->comp_ref[vp9_get_pred_context_comp_ref_p(cm, xd)] - [ref0 == GOLDEN_FRAME]++; #endif // CONFIG_MULTI_REF } else { #if CONFIG_MULTI_REF -- 2.49.0