From 70d9f116fd90f130ec7798b16c2083c9e3853050 Mon Sep 17 00:00:00 2001 From: Deb Mukherjee Date: Thu, 28 Mar 2013 10:42:23 -0700 Subject: End of orientation zero group experiment Adds an experiment that codes an end-of-orientation symbol for every eligible zero encountered in scan order. This cleans out various other sub-experiments that were part of the origiinal patch, which will be later included if found useful. Results are slightly positive on all sets (0.1 - 0.2% range). Change-Id: I57765c605fefc7fb9d1b57f1b356843602abefaf --- vp9/common/vp9_blockd.h | 9 ++- vp9/common/vp9_coefupdateprobs.h | 4 + vp9/common/vp9_default_coef_probs.h | 83 +++++++++++++++++++ vp9/common/vp9_entropy.c | 153 +++++++++++++++++++++++++++++++++++- vp9/common/vp9_entropy.h | 56 +++++++++++++ vp9/common/vp9_onyxc_int.h | 22 ++++++ 6 files changed, 321 insertions(+), 6 deletions(-) (limited to 'vp9/common') diff --git a/vp9/common/vp9_blockd.h b/vp9/common/vp9_blockd.h index aa48958b0..b1915d18a 100644 --- a/vp9/common/vp9_blockd.h +++ b/vp9/common/vp9_blockd.h @@ -767,7 +767,7 @@ struct plane_block_idx { // TODO(jkoleszar): returning a struct so it can be used in a const context, // expect to refactor this further later. static INLINE struct plane_block_idx plane_block_idx(int y_blocks, - int b_idx) { + int b_idx) { const int v_offset = y_blocks * 5 / 4; struct plane_block_idx res; @@ -939,6 +939,9 @@ static INLINE void foreach_predicted_block_uv( } } - - +#if CONFIG_CODE_ZEROGROUP +static int get_zpc_used(TX_SIZE tx_size) { + return (tx_size >= TX_16X16); +} +#endif #endif // VP9_COMMON_VP9_BLOCKD_H_ diff --git a/vp9/common/vp9_coefupdateprobs.h b/vp9/common/vp9_coefupdateprobs.h index b4d892df9..a13f9b290 100644 --- a/vp9/common/vp9_coefupdateprobs.h +++ b/vp9/common/vp9_coefupdateprobs.h @@ -26,6 +26,10 @@ static const vp9_prob vp9_coef_update_prob[ENTROPY_NODES] = { #define NZC_UPDATE_PROB_PCAT 252 #endif +#if CONFIG_CODE_ZEROGROUP +#define ZPC_UPDATE_PROB 248 +#endif + #if CONFIG_MODELCOEFPROB #define COEF_MODEL_UPDATE_PROB 16 #endif diff --git a/vp9/common/vp9_default_coef_probs.h b/vp9/common/vp9_default_coef_probs.h index 5a781fb0a..9e105bd5c 100644 --- a/vp9/common/vp9_default_coef_probs.h +++ b/vp9/common/vp9_default_coef_probs.h @@ -995,3 +995,86 @@ static const vp9_prob default_nzc_pcat_probs[MAX_NZC_CONTEXTS] }; #endif // CONFIG_CODE_NONZEROCOUNT + +#if CONFIG_CODE_ZEROGROUP + +// There are two probs: the first is the prob(0) of the isolated zero bit, +// the second is the prob(0) of the end of orientation symbol [if 0 that +// indicates a zerotree root]. +static const vp9_zpc_probs default_zpc_probs_4x4 = { + { /* Intra */ + { /* Coeff Band 0 */ + { 1, }, { 1, }, { 1, }, + }, { /* Coeff Band 1 */ + { 1, }, { 1, }, { 1, }, + }, { /* Coeff Band 2 */ + { 1, }, { 1, }, { 1, }, + } + }, { /* Inter */ + { /* Coeff Band 0 */ + { 1, }, { 1, }, { 1, }, + }, { /* Coeff Band 1 */ + { 1, }, { 1, }, { 1, }, + }, { /* Coeff Band 2 */ + { 1, }, { 1, }, { 1, }, + } + } +}; +static const vp9_zpc_probs default_zpc_probs_8x8 = { + { /* Intra */ + { /* ZPC Band 0 */ + { 4, }, { 2, }, { 1, }, + }, { /* ZPC Band 1 */ + { 4, }, { 2, }, { 1, }, + }, { /* ZPC Band 2 */ + { 4, }, { 2, }, { 1, }, + } + }, { /* Inter */ + { /* ZPC Band 0 */ + { 4, }, { 2, }, { 1, }, + }, { /* ZPC Band 1 */ + { 4, }, { 2, }, { 1, }, + }, { /* ZPC Band 2 */ + { 4, }, { 2, }, { 1, }, + } + } +}; +static const vp9_zpc_probs default_zpc_probs_16x16 = { + { /* Intra */ + { /* ZPC Band 0 */ + { 57, }, { 30, }, { 13, }, + }, { /* ZPC Band 1 */ + { 46, }, { 23, }, { 4, }, + }, { /* ZPC Band 1 */ + { 36, }, { 11, }, { 2, }, + }, + }, { /* Inter */ + { /* ZPC Band 0 */ + { 45, }, { 21 }, { 10, }, + }, { /* ZPC Band 1 */ + { 24, }, { 14, }, { 3, }, + }, { /* ZPC Band 2 */ + { 16, }, { 6, }, { 1, }, + }, + }, +}; +static const vp9_zpc_probs default_zpc_probs_32x32 = { + { /* Intra */ + { /* ZPC Band 0 */ + { 132, }, { 60, }, { 19, }, + }, { /* ZPC Band 1 */ + { 64, }, { 32, }, { 8, }, + }, { /* ZPC Band 2 */ + { 25, }, { 11, }, { 1, }, + }, + }, { /* Inter */ + { /* ZPC Band 0 */ + { 134, }, { 39, }, { 25, }, + }, { /* ZPC Band 1 */ + { 64, }, { 24, }, { 12, }, + }, { /* ZPC Band 2 */ + { 21, }, { 10, }, { 1, }, + }, + }, +}; +#endif // CONFIG_CODE_ZEROGROUP diff --git a/vp9/common/vp9_entropy.c b/vp9/common/vp9_entropy.c index 5b3ddfbc2..cfd6a3cd1 100644 --- a/vp9/common/vp9_entropy.c +++ b/vp9/common/vp9_entropy.c @@ -1344,10 +1344,10 @@ int vp9_get_coef_context(const int *scan, const int *neighbors, int ctx; assert(neighbors[MAX_NEIGHBORS * c + 0] >= 0); if (neighbors[MAX_NEIGHBORS * c + 1] >= 0) { - ctx = (1 + token_cache[neighbors[MAX_NEIGHBORS * c + 0]] + - token_cache[neighbors[MAX_NEIGHBORS * c + 1]]) >> 1; + ctx = (1 + token_cache[scan[neighbors[MAX_NEIGHBORS * c + 0]]] + + token_cache[scan[neighbors[MAX_NEIGHBORS * c + 1]]]) >> 1; } else { - ctx = token_cache[neighbors[MAX_NEIGHBORS * c + 0]]; + ctx = token_cache[scan[neighbors[MAX_NEIGHBORS * c + 0]]]; } return vp9_pt_energy_class[ctx]; } @@ -1447,6 +1447,16 @@ void vp9_default_coef_probs(VP9_COMMON *pc) { vpx_memcpy(pc->fc.coef_probs_32x32, default_coef_probs_32x32, sizeof(pc->fc.coef_probs_32x32)); #endif +#if CONFIG_CODE_ZEROGROUP + vpx_memcpy(pc->fc.zpc_probs_4x4, default_zpc_probs_4x4, + sizeof(pc->fc.zpc_probs_4x4)); + vpx_memcpy(pc->fc.zpc_probs_8x8, default_zpc_probs_8x8, + sizeof(pc->fc.zpc_probs_8x8)); + vpx_memcpy(pc->fc.zpc_probs_16x16, default_zpc_probs_16x16, + sizeof(pc->fc.zpc_probs_16x16)); + vpx_memcpy(pc->fc.zpc_probs_32x32, default_zpc_probs_32x32, + sizeof(pc->fc.zpc_probs_32x32)); +#endif } // Neighborhood 5-tuples for various scans and blocksizes, @@ -2901,3 +2911,140 @@ void vp9_adapt_nzc_probs(VP9_COMMON *cm) { adapt_nzc_pcat(cm, count_sat, update_factor); } #endif // CONFIG_CODE_NONZEROCOUNT + +#if CONFIG_CODE_ZEROGROUP +OrientationType vp9_get_orientation(int rc, TX_SIZE tx_size) { + int i = rc >> (tx_size + 2); + int j = rc & ((4 << tx_size) - 1); + if (i > 2 * j) + return VERTICAL; + else if (j > 2 * i) + return HORIZONTAL; + else + return DIAGONAL; + /* + if (i == 0 && j == 0) return DIAGONAL; + while (i > 1 || j > 1) { + i >>= 1; + j >>= 1; + } + if (i == 0 && j == 1) + return HORIZONTAL; // horizontal + else if (i == 1 && j == 1) + return DIAGONAL; // diagonal + else if (i == 1 && j == 0) + return VERTICAL; // vertical + assert(0); + */ +} + +int vp9_use_eoo(int c, int seg_eob, const int *scan, + TX_SIZE tx_size, int *is_last_zero, int *is_eoo) { + // NOTE: returning 0 from this function will turn off eoo symbols + // For instance we can experiment with turning eoo off for smaller blocks + // and/or lower bands + int o = vp9_get_orientation(scan[c], tx_size); + int band = get_coef_band(scan, tx_size, c); + int use_eoo = (!is_last_zero[o] && + !is_eoo[o] && + band <= ZPC_EOO_BAND_UPPER && + band >= ZPC_EOO_BAND_LOWER && + get_zpc_used(tx_size) && + seg_eob - c > (ZPC_USEEOO_THRESH << tx_size) && + is_eoo[0] + is_eoo[1] + is_eoo[2] < 2); + return use_eoo; +} + +int vp9_is_eoo(int c, int eob, const int *scan, TX_SIZE tx_size, + const int16_t *qcoeff_ptr, int *last_nz_pos) { + int rc = scan[c]; + int o = vp9_get_orientation(rc, tx_size); + int eoo = c > last_nz_pos[o]; + return eoo; +} + +static void adapt_zpc_probs_common(VP9_COMMON *cm, + TX_SIZE tx_size, + int count_sat, + int update_factor) { + int r, b, p, n; + int count, factor; + vp9_zpc_probs *zpc_probs; + vp9_zpc_probs *pre_zpc_probs; + vp9_zpc_count *zpc_counts; + if (!get_zpc_used(tx_size)) return; + if (tx_size == TX_32X32) { + zpc_probs = &cm->fc.zpc_probs_32x32; + pre_zpc_probs = &cm->fc.pre_zpc_probs_32x32; + zpc_counts = &cm->fc.zpc_counts_32x32; + } else if (tx_size == TX_16X16) { + zpc_probs = &cm->fc.zpc_probs_16x16; + pre_zpc_probs = &cm->fc.pre_zpc_probs_16x16; + zpc_counts = &cm->fc.zpc_counts_16x16; + } else if (tx_size == TX_8X8) { + zpc_probs = &cm->fc.zpc_probs_8x8; + pre_zpc_probs = &cm->fc.pre_zpc_probs_8x8; + zpc_counts = &cm->fc.zpc_counts_8x8; + } else { + zpc_probs = &cm->fc.zpc_probs_4x4; + pre_zpc_probs = &cm->fc.pre_zpc_probs_4x4; + zpc_counts = &cm->fc.zpc_counts_4x4; + } + for (r = 0; r < REF_TYPES; ++r) { + for (b = 0; b < ZPC_BANDS; ++b) { + for (p = 0; p < ZPC_PTOKS; ++p) { + for (n = 0; n < ZPC_NODES; ++n) { + vp9_prob prob = get_binary_prob((*zpc_counts)[r][b][p][n][0], + (*zpc_counts)[r][b][p][n][1]); + count = (*zpc_counts)[r][b][p][n][0] + (*zpc_counts)[r][b][p][n][1]; + count = count > count_sat ? count_sat : count; + factor = (update_factor * count / count_sat); + (*zpc_probs)[r][b][p][n] = weighted_prob( + (*pre_zpc_probs)[r][b][p][n], prob, factor); + } + } + } + } +} + +// #define ZPC_COUNT_TESTING +void vp9_adapt_zpc_probs(VP9_COMMON *cm) { + int count_sat; + int update_factor; /* denominator 256 */ +#ifdef NZC_COUNT_TESTING + int r, b, p, n; + printf("\n"); + for (r = 0; r < REF_TYPES; ++r) { + printf("{"); + for (b = 0; b < ZPC_BANDS; ++b) { + printf(" {"); + for (p = 0; p < ZPC_PTOKS; ++p) { + printf(" {"); + for (n = 0; n < ZPC_NODES; ++n) { + printf(" %d,", cm->fc.zpc_counts_16x16[r][b][p][n]); + } + printf("},\n"); + } + printf(" },\n"); + } + printf("},\n"); + } +#endif + + if (cm->frame_type == KEY_FRAME) { + update_factor = COEF_MAX_UPDATE_FACTOR_KEY; + count_sat = COEF_COUNT_SAT_KEY; + } else if (cm->last_frame_type == KEY_FRAME) { + update_factor = COEF_MAX_UPDATE_FACTOR_AFTER_KEY; /* adapt quickly */ + count_sat = COEF_COUNT_SAT_AFTER_KEY; + } else { + update_factor = COEF_MAX_UPDATE_FACTOR; + count_sat = COEF_COUNT_SAT; + } + + adapt_zpc_probs_common(cm, TX_4X4, count_sat, update_factor); + adapt_zpc_probs_common(cm, TX_8X8, count_sat, update_factor); + adapt_zpc_probs_common(cm, TX_16X16, count_sat, update_factor); + adapt_zpc_probs_common(cm, TX_32X32, count_sat, update_factor); +} +#endif // CONFIG_CODE_ZEROGROUP diff --git a/vp9/common/vp9_entropy.h b/vp9/common/vp9_entropy.h index 3cae94649..6b24ffc94 100644 --- a/vp9/common/vp9_entropy.h +++ b/vp9/common/vp9_entropy.h @@ -250,6 +250,62 @@ extern const int vp9_basenzcvalue[NZC32X32_TOKENS]; #endif // CONFIG_CODE_NONZEROCOUNT +#if CONFIG_CODE_ZEROGROUP + +#define ZPC_STATS + +typedef enum { + HORIZONTAL = 0, + DIAGONAL, + VERTICAL, +} OrientationType; + +/* Note EOB should become part of this symbol eventually, + * but holding off on this for now because that is a major + * change in the rest of the codebase */ + +#define ZPC_ISOLATED (MAX_ENTROPY_TOKENS + 0) /* Isolated zero */ + +/* ZPC_EOORIENT: All remaining coefficients in the same orientation are 0. + * In other words all remaining coeffs in the current subband, and all + * children of the current subband are zero. Subbands are defined by + * dyadic partitioning in the coeff domain */ +#define ZPC_EOORIENT (MAX_ENTROPY_TOKENS + 1) /* End of Orientation */ + +/* Band limits over which the eoo bit is sent */ +#define ZPC_EOO_BAND_LOWER 0 +#define ZPC_EOO_BAND_UPPER 5 + +#define USE_ZPC_EOORIENT 1 /* 0: not used */ + /* 1: used */ +#define ZPC_NODES 1 + +#define UNKNOWN_TOKEN 255 /* Not signalled, encoder only */ + +#define ZPC_BANDS 3 /* context bands for izr */ +#define ZPC_PTOKS 3 /* context pt for zpcs */ + +#define coef_to_zpc_band(b) ((b) >> 1) +#define coef_to_zpc_ptok(p) ((p) > 2 ? 2 : (p)) + +typedef vp9_prob vp9_zpc_probs[REF_TYPES][ZPC_BANDS] + [ZPC_PTOKS][ZPC_NODES]; +typedef unsigned int vp9_zpc_count[REF_TYPES][ZPC_BANDS] + [ZPC_PTOKS][ZPC_NODES][2]; + +OrientationType vp9_get_orientation(int rc, TX_SIZE tx_size); +int vp9_use_eoo(int c, int eob, const int *scan, TX_SIZE tx_size, + int *is_last_zero, int *is_eoo); +int vp9_is_eoo(int c, int eob, const int *scan, TX_SIZE tx_size, + const int16_t *qcoeff_ptr, int *last_nz_pos); + +#define ZPC_USEEOO_THRESH 4 +#define ZPC_ZEROSSAVED_EOO 7 /* encoder only */ + +void vp9_adapt_zpc_probs(struct VP9Common *cm); + +#endif // CONFIG_CODE_ZEROGROUP + #include "vp9/common/vp9_coefupdateprobs.h" #endif // VP9_COMMON_VP9_ENTROPY_H_ diff --git a/vp9/common/vp9_onyxc_int.h b/vp9/common/vp9_onyxc_int.h index 13ec8657f..eb2a2c682 100644 --- a/vp9/common/vp9_onyxc_int.h +++ b/vp9/common/vp9_onyxc_int.h @@ -86,6 +86,12 @@ typedef struct frame_contexts { vp9_prob nzc_pcat_probs[MAX_NZC_CONTEXTS] [NZC_TOKENS_EXTRA][NZC_BITS_EXTRA]; #endif +#if CONFIG_CODE_ZEROGROUP + vp9_zpc_probs zpc_probs_4x4; + vp9_zpc_probs zpc_probs_8x8; + vp9_zpc_probs zpc_probs_16x16; + vp9_zpc_probs zpc_probs_32x32; +#endif nmv_context nmvc; nmv_context pre_nmvc; @@ -122,6 +128,12 @@ typedef struct frame_contexts { vp9_prob pre_nzc_pcat_probs[MAX_NZC_CONTEXTS] [NZC_TOKENS_EXTRA][NZC_BITS_EXTRA]; #endif +#if CONFIG_CODE_ZEROGROUP + vp9_zpc_probs pre_zpc_probs_4x4; + vp9_zpc_probs pre_zpc_probs_8x8; + vp9_zpc_probs pre_zpc_probs_16x16; + vp9_zpc_probs pre_zpc_probs_32x32; +#endif vp9_coeff_count coef_counts_4x4[BLOCK_TYPES]; vp9_coeff_count coef_counts_8x8[BLOCK_TYPES]; @@ -142,6 +154,12 @@ typedef struct frame_contexts { unsigned int nzc_pcat_counts[MAX_NZC_CONTEXTS] [NZC_TOKENS_EXTRA][NZC_BITS_EXTRA][2]; #endif +#if CONFIG_CODE_ZEROGROUP + vp9_zpc_count zpc_counts_4x4; + vp9_zpc_count zpc_counts_8x8; + vp9_zpc_count zpc_counts_16x16; + vp9_zpc_count zpc_counts_32x32; +#endif nmv_context_counts NMVcount; vp9_prob switchable_interp_prob[VP9_SWITCHABLE_FILTERS + 1] @@ -377,4 +395,8 @@ static int get_mb_row(const MACROBLOCKD *xd) { static int get_mb_col(const MACROBLOCKD *xd) { return ((-xd->mb_to_left_edge) >> 7); } + +static int get_token_alloc(int mb_rows, int mb_cols) { + return mb_rows * mb_cols * (24 * 16 + 4); +} #endif // VP9_COMMON_VP9_ONYXC_INT_H_ -- cgit v1.2.3