From 08f0c7cc9c1e285c33711384834e7a3baf26bd7c Mon Sep 17 00:00:00 2001 From: Deb Mukherjee Date: Tue, 27 Nov 2012 15:51:06 -0800 Subject: [PATCH] New previous coef context experiment Adds an experiment to derive the previous context of a coefficient not just from the previous coefficient in the scan order but from a combination of several neighboring coefficients previously encountered in scan order. A precomputed table of neighbors for each location for each scan type and block size is used. Currently 5 neighbors are used. Results are about 0.2% positive using a strategy where the max coef magnitude from the 5 neigbors is used to derive the context. Change-Id: Ie708b54d8e1898af742846ce2d1e2b0d89fd4ad5 --- configure | 1 + vp9/common/vp9_alloccommon.c | 4 + vp9/common/vp9_entropy.c | 174 ++++++++++++++++++++++++++++++++--- vp9/common/vp9_entropy.h | 31 ++++++- vp9/decoder/vp9_detokenize.c | 34 +++++-- vp9/encoder/vp9_encodemb.c | 33 +++++++ vp9/encoder/vp9_rdopt.c | 54 +++++++++-- vp9/encoder/vp9_tokenize.c | 26 +++++- 8 files changed, 325 insertions(+), 32 deletions(-) diff --git a/configure b/configure index 55add837c..1126ea86e 100755 --- a/configure +++ b/configure @@ -250,6 +250,7 @@ EXPERIMENT_LIST=" tx32x32 dwt32x32hybrid cnvcontext + newcoefcontext " CONFIG_LIST=" external_build diff --git a/vp9/common/vp9_alloccommon.c b/vp9/common/vp9_alloccommon.c index 08882b3a6..bd86db8a8 100644 --- a/vp9/common/vp9_alloccommon.c +++ b/vp9/common/vp9_alloccommon.c @@ -220,4 +220,8 @@ void vp9_initialize_common() { vp9_entropy_mode_init(); vp9_entropy_mv_init(); + +#if CONFIG_NEWCOEFCONTEXT + vp9_init_neighbors(); +#endif } diff --git a/vp9/common/vp9_entropy.c b/vp9/common/vp9_entropy.c index 559757e81..1402c084e 100644 --- a/vp9/common/vp9_entropy.c +++ b/vp9/common/vp9_entropy.c @@ -62,6 +62,7 @@ DECLARE_ALIGNED(16, const int, vp9_col_scan_4x4[16]) = { 2, 6, 10, 14, 3, 7, 11, 15 }; + DECLARE_ALIGNED(16, const int, vp9_row_scan_4x4[16]) = { 0, 1, 2, 3, 4, 5, 6, 7, @@ -69,16 +70,16 @@ DECLARE_ALIGNED(16, const int, vp9_row_scan_4x4[16]) = { 12, 13, 14, 15 }; - DECLARE_ALIGNED(64, const int, vp9_coef_bands_8x8[64]) = { 0, 1, 2, 3, 5, 4, 4, 5, - 5, 3, 6, 3, 5, 4, 6, 6, - 6, 5, 5, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7 - }; + 5, 3, 6, 3, 5, 4, 6, 6, + 6, 5, 5, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7 +}; + DECLARE_ALIGNED(64, const int, vp9_default_zig_zag1d_8x8[64]) = { 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, @@ -118,17 +119,17 @@ DECLARE_ALIGNED(16, const int, vp9_default_zig_zag1d_16x16[256]) = { 25, 10, 11, 26, 41, 56, 71, 86, 101, 116, 131, 146, 161, 176, 192, 177, 162, 147, 132, 117, 102, 87, 72, 57, - 42, 27, 12, 13, 28, 43, 58, 73, + 42, 27, 12, 13, 28, 43, 58, 73, 88, 103, 118, 133, 148, 163, 178, 193, 208, 224, 209, 194, 179, 164, 149, 134, 119, 104, 89, 74, 59, 44, 29, 14, - 15, 30, 45, 60, 75, 90, 105, 120, + 15, 30, 45, 60, 75, 90, 105, 120, 135, 150, 165, 180, 195, 210, 225, 240, 241, 226, 211, 196, 181, 166, 151, 136, 121, 106, 91, 76, 61, 46, 31, 47, - 62, 77, 92, 107, 122, 137, 152, 167, + 62, 77, 92, 107, 122, 137, 152, 167, 182, 197, 212, 227, 242, 243, 228, 213, - 198, 183, 168, 153, 138, 123, 108, 93, + 198, 183, 168, 153, 138, 123, 108, 93, 78, 63, 79, 94, 109, 124, 139, 154, 169, 184, 199, 214, 229, 244, 245, 230, 215, 200, 185, 170, 155, 140, 125, 110, @@ -530,6 +531,152 @@ vp9_extra_bit_struct vp9_extra_bits[12] = { #include "vp9/common/vp9_default_coef_probs.h" +#if CONFIG_NEWCOEFCONTEXT + +// Neighborhood 5-tuples for various scans and blocksizes, +// in {top, left, topleft, topright, bottomleft} order +// for each position in raster scan order. +// -1 indicates the neighbor does not exist. +DECLARE_ALIGNED(16, int, + vp9_default_zig_zag1d_4x4_neighbors[16 * MAX_NEIGHBORS]); +DECLARE_ALIGNED(16, int, + vp9_col_scan_4x4_neighbors[16 * MAX_NEIGHBORS]); +DECLARE_ALIGNED(16, int, + vp9_row_scan_4x4_neighbors[16 * MAX_NEIGHBORS]); +DECLARE_ALIGNED(16, int, + vp9_default_zig_zag1d_8x8_neighbors[64 * MAX_NEIGHBORS]); +DECLARE_ALIGNED(16, int, + vp9_default_zig_zag1d_16x16_neighbors[256 * MAX_NEIGHBORS]); +#if CONFIG_TX32X32 && CONFIG_SUPERBLOCKS +DECLARE_ALIGNED(16, int, + vp9_default_zig_zag1d_32x32_neighbors[1024 * MAX_NEIGHBORS]); +#endif + +static int find_in_scan(const int *scan, int l, int m) { + int i, l2 = l * l; + for (i = 0; i < l2; ++i) { + if (scan[i] == m) + return i; + } + return -1; +} + +static void init_scan_neighbors(const int *scan, int l, int *neighbors) { + int l2 = l * l; + int m, n, i, j, k; + for (n = 0; n < l2; ++n) { + int locn = find_in_scan(scan, l, n); + int z = -1; + i = n / l; + j = n % l; + for (k = 0; k < MAX_NEIGHBORS; ++k) + neighbors[MAX_NEIGHBORS * n + k] = -1; + if (i - 1 >= 0) { + m = (i - 1) * l + j; + if (find_in_scan(scan, l, m) < locn) { + neighbors[MAX_NEIGHBORS * n] = m; + if (m == 0) z = 0; + } + } + if (j - 1 >= 0) { + m = i * l + j - 1; + if (find_in_scan(scan, l, m) < locn) { + neighbors[MAX_NEIGHBORS * n + 1] = m; + if (m == 0) z = 1; + } + } + if (i - 1 >= 0 && j - 1 >= 0) { + m = (i - 1) * l + j - 1; + if (find_in_scan(scan, l, m) < locn) { + neighbors[MAX_NEIGHBORS * n + 2] = m; + if (m == 0) z = 2; + } + } + if (i - 1 >= 0 && j + 1 < l) { + m = (i - 1) * l + j + 1; + if (find_in_scan(scan, l, m) < locn) { + neighbors[MAX_NEIGHBORS * n + 3] = m; + if (m == 0) z = 3; + } + } + if (i + 1 < l && j - 1 >= 0) { + m = (i + 1) * l + j - 1; + if (find_in_scan(scan, l, m) < locn) { + neighbors[MAX_NEIGHBORS * n + 4] = m; + if (m == 0) z = 4; + } + } + if (z != -1) { // zero exists + int v = 0; + for (k = 0; k < MAX_NEIGHBORS; ++k) + v += (neighbors[MAX_NEIGHBORS * n + k] > 0); + if (v) { + neighbors[MAX_NEIGHBORS * n + z] = -1; + } + } + } +} + +void vp9_init_neighbors() { + init_scan_neighbors(vp9_default_zig_zag1d_4x4, 4, + vp9_default_zig_zag1d_4x4_neighbors); + init_scan_neighbors(vp9_row_scan_4x4, 4, + vp9_row_scan_4x4_neighbors); + init_scan_neighbors(vp9_col_scan_4x4, 4, + vp9_col_scan_4x4_neighbors); + init_scan_neighbors(vp9_default_zig_zag1d_8x8, 8, + vp9_default_zig_zag1d_8x8_neighbors); + init_scan_neighbors(vp9_default_zig_zag1d_16x16, 16, + vp9_default_zig_zag1d_16x16_neighbors); +#if CONFIG_TX32X32 && CONFIG_SUPERBLOCKS + init_scan_neighbors(vp9_default_zig_zag1d_32x32, 32, + vp9_default_zig_zag1d_32x32_neighbors); +#endif +} + +const int *vp9_get_coef_neighbors_handle(const int *scan) { + if (scan == vp9_default_zig_zag1d_4x4) { + return vp9_default_zig_zag1d_4x4_neighbors; + } else if (scan == vp9_row_scan_4x4) { + return vp9_row_scan_4x4_neighbors; + } else if (scan == vp9_col_scan_4x4) { + return vp9_col_scan_4x4_neighbors; + } else if (scan == vp9_default_zig_zag1d_8x8) { + return vp9_default_zig_zag1d_8x8_neighbors; + } else if (scan == vp9_default_zig_zag1d_16x16) { + return vp9_default_zig_zag1d_16x16_neighbors; +#if CONFIG_TX32X32 && CONFIG_SUPERBLOCKS + } else if (scan == vp9_default_zig_zag1d_32x32) { + return vp9_default_zig_zag1d_32x32_neighbors; +#endif + } + return vp9_default_zig_zag1d_4x4_neighbors; +} + +int vp9_get_coef_neighbor_context(const short int *qcoeff_ptr, int nodc, + const int *neigbor_handle, int rc) { + static int neighbors_used = MAX_NEIGHBORS; // maximum is MAX_NEIGHBORS + const int *nb = neigbor_handle + rc * MAX_NEIGHBORS; + int i, v, val = 0, n = 0; + for (i = 0; i < neighbors_used; ++i) { + if (nb[i] == -1 || (nb[i] == 0 && nodc)) { + continue; + } + v = abs(qcoeff_ptr[nb[i]]); + val = (v > val ? v : val); + n++; + } + if (n == 0) + return 0; + else if (val <= 1) + return val; + else if (val < 4) + return 2; + else + return 3; +} +#endif /* CONFIG_NEWCOEFCONTEXT */ + void vp9_default_coef_probs(VP9_COMMON *pc) { vpx_memcpy(pc->fc.coef_probs_4x4, default_coef_probs_4x4, sizeof(pc->fc.coef_probs_4x4)); @@ -546,7 +693,6 @@ void vp9_default_coef_probs(VP9_COMMON *pc) { vpx_memcpy(pc->fc.hybrid_coef_probs_16x16, default_hybrid_coef_probs_16x16, sizeof(pc->fc.hybrid_coef_probs_16x16)); - #if CONFIG_TX32X32 && CONFIG_SUPERBLOCKS vpx_memcpy(pc->fc.coef_probs_32x32, default_coef_probs_32x32, sizeof(pc->fc.coef_probs_32x32)); diff --git a/vp9/common/vp9_entropy.h b/vp9/common/vp9_entropy.h index eb8cfe93c..99826015a 100644 --- a/vp9/common/vp9_entropy.h +++ b/vp9/common/vp9_entropy.h @@ -98,7 +98,7 @@ extern DECLARE_ALIGNED(16, const int, vp9_coef_bands_32x32[1024]); distinct bands). */ /*# define DC_TOKEN_CONTEXTS 3*/ /* 00, 0!0, !0!0 */ -#define PREV_COEF_CONTEXTS 4 +#define PREV_COEF_CONTEXTS 4 typedef unsigned int vp9_coeff_count[COEF_BANDS][PREV_COEF_CONTEXTS] [MAX_ENTROPY_TOKENS]; @@ -127,13 +127,36 @@ extern DECLARE_ALIGNED(16, const int, vp9_default_zig_zag1d_32x32[1024]); #endif void vp9_coef_tree_initialize(void); - void vp9_adapt_coef_probs(struct VP9Common *); static void vp9_reset_mb_tokens_context(MACROBLOCKD* const xd) { /* Clear entropy contexts */ - vpx_memset(xd->above_context, 0, sizeof(ENTROPY_CONTEXT_PLANES)); - vpx_memset(xd->left_context, 0, sizeof(ENTROPY_CONTEXT_PLANES)); + vpx_memset(xd->above_context, 0, sizeof(ENTROPY_CONTEXT_PLANES)); + vpx_memset(xd->left_context, 0, sizeof(ENTROPY_CONTEXT_PLANES)); } +#if CONFIG_NEWCOEFCONTEXT + +#define MAX_NEIGHBORS 5 +#define NEWCOEFCONTEXT_BAND_COND(b) ((b) >= 1) +void vp9_init_neighbors(void); + +const int *vp9_get_coef_neighbors_handle(const int *scan); +int vp9_get_coef_neighbor_context(const short int *qcoeff_ptr, int nodc, + const int *neigbor_handle, int rc); +extern DECLARE_ALIGNED(16, int, vp9_default_zig_zag1d_4x4_neighbors[ + 16 * MAX_NEIGHBORS]); +extern DECLARE_ALIGNED(16, int, vp9_row_scan_4x4_neighbors[ + 16 * MAX_NEIGHBORS]); +extern DECLARE_ALIGNED(16, int, vp9_col_scan_4x4_neighbors[ + 16 * MAX_NEIGHBORS]); +extern DECLARE_ALIGNED(16, int, vp9_default_zig_zag1d_8x8_neighbors[ + 64 * MAX_NEIGHBORS]); +extern DECLARE_ALIGNED(16, int, vp9_default_zig_zag1d_16x16_neighbors[ + 256 * MAX_NEIGHBORS]); +#if CONFIG_SUPERBLOCKS && CONFIG_TX32X32 +extern DECLARE_ALIGNED(16, int, vp9_default_zig_zag1d_32x32_neighbors[ + 1024 * MAX_NEIGHBORS]); +#endif +#endif // CONFIG_NEWCOEFCONTEXT #endif // VP9_COMMON_VP9_ENTROPY_H_ diff --git a/vp9/decoder/vp9_detokenize.c b/vp9/decoder/vp9_detokenize.c index 55ce0171a..bdf578b3e 100644 --- a/vp9/decoder/vp9_detokenize.c +++ b/vp9/decoder/vp9_detokenize.c @@ -63,11 +63,24 @@ static int get_signed(BOOL_DECODER *br, int value_to_sign) { return decode_bool(br, 128) ? -value_to_sign : value_to_sign; } -#define INCREMENT_COUNT(token) \ - do { \ +#if CONFIG_NEWCOEFCONTEXT +#define PT pn +#define INCREMENT_COUNT(token) \ + do { \ + coef_counts[type][coef_bands[c]][pn][token]++; \ + pn = pt = vp9_prev_token_class[token]; \ + if (c < seg_eob - 1 && NEWCOEFCONTEXT_BAND_COND(coef_bands[c + 1])) \ + pn = vp9_get_coef_neighbor_context( \ + qcoeff_ptr, nodc, neighbors, scan[c + 1]); \ + } while (0) +#else +#define PT pt +#define INCREMENT_COUNT(token) \ + do { \ coef_counts[type][coef_bands[c]][pt][token]++; \ pt = vp9_prev_token_class[token]; \ } while (0) +#endif /* CONFIG_NEWCOEFCONTEXT */ #define WRITE_COEF_CONTINUE(val, token) \ { \ @@ -92,7 +105,12 @@ static int decode_coefs(VP9D_COMP *dx, const MACROBLOCKD *xd, const int *const scan, TX_SIZE txfm_size, const int *coef_bands) { FRAME_CONTEXT *const fc = &dx->common.fc; - int pt, c = (type == PLANE_TYPE_Y_NO_DC); +#if CONFIG_NEWCOEFCONTEXT + const int *neighbors; + int pn; +#endif + int nodc = (type == PLANE_TYPE_Y_NO_DC); + int pt, c = nodc; vp9_coeff_probs *coef_probs; vp9_prob *prob; vp9_coeff_count *coef_counts; @@ -135,11 +153,15 @@ static int decode_coefs(VP9D_COMP *dx, const MACROBLOCKD *xd, } VP9_COMBINEENTROPYCONTEXTS(pt, *a, *l); +#if CONFIG_NEWCOEFCONTEXT + pn = pt; + neighbors = vp9_get_coef_neighbors_handle(scan); +#endif while (1) { int val; const uint8_t *cat6 = cat6_prob; if (c >= seg_eob) break; - prob = coef_probs[type][coef_bands[c]][pt]; + prob = coef_probs[type][coef_bands[c]][PT]; if (!vp9_read(br, prob[EOB_CONTEXT_NODE])) break; SKIP_START: @@ -147,7 +169,7 @@ SKIP_START: if (!vp9_read(br, prob[ZERO_CONTEXT_NODE])) { INCREMENT_COUNT(ZERO_TOKEN); ++c; - prob = coef_probs[type][coef_bands[c]][pt]; + prob = coef_probs[type][coef_bands[c]][PT]; goto SKIP_START; } // ONE_CONTEXT_NODE_0_ @@ -211,7 +233,7 @@ SKIP_START: } if (c < seg_eob) - coef_counts[type][coef_bands[c]][pt][DCT_EOB_TOKEN]++; + coef_counts[type][coef_bands[c]][PT][DCT_EOB_TOKEN]++; a[0] = l[0] = (c > !type); diff --git a/vp9/encoder/vp9_encodemb.c b/vp9/encoder/vp9_encodemb.c index 66ec31c83..91eea4e51 100644 --- a/vp9/encoder/vp9_encodemb.c +++ b/vp9/encoder/vp9_encodemb.c @@ -380,6 +380,9 @@ static void optimize_b(MACROBLOCK *mb, int i, PLANE_TYPE type, int err_mult = plane_rd_mult[type]; int default_eob; int const *scan, *bands; +#if CONFIG_NEWCOEFCONTEXT + const int *neighbors; +#endif switch (tx_size) { default: @@ -421,6 +424,9 @@ static void optimize_b(MACROBLOCK *mb, int i, PLANE_TYPE type, default_eob = 256; break; } +#if CONFIG_NEWCOEFCONTEXT + neighbors = vp9_get_coef_neighbors_handle(scan); +#endif /* Now set up a Viterbi trellis to evaluate alternative roundings. */ rdmult = mb->rdmult * err_mult; @@ -454,6 +460,11 @@ static void optimize_b(MACROBLOCK *mb, int i, PLANE_TYPE type, if (next < default_eob) { band = bands[i + 1]; pt = vp9_prev_token_class[t0]; +#if CONFIG_NEWCOEFCONTEXT + if (NEWCOEFCONTEXT_BAND_COND(band)) + pt = vp9_get_coef_neighbor_context( + qcoeff_ptr, i0, neighbors, scan[i + 1]); +#endif rate0 += mb->token_costs[tx_size][type][band][pt][tokens[next][0].token]; rate1 += @@ -501,12 +512,34 @@ static void optimize_b(MACROBLOCK *mb, int i, PLANE_TYPE type, if (next < default_eob) { band = bands[i + 1]; if (t0 != DCT_EOB_TOKEN) { +#if CONFIG_NEWCOEFCONTEXT + int tmp = qcoeff_ptr[scan[i]]; + qcoeff_ptr[scan[i]] = x; + if (NEWCOEFCONTEXT_BAND_COND(band)) + pt = vp9_get_coef_neighbor_context( + qcoeff_ptr, i0, neighbors, scan[i + 1]); + else + pt = vp9_prev_token_class[t0]; + qcoeff_ptr[scan[i]] = tmp; +#else pt = vp9_prev_token_class[t0]; +#endif rate0 += mb->token_costs[tx_size][type][band][pt][ tokens[next][0].token]; } if (t1 != DCT_EOB_TOKEN) { +#if CONFIG_NEWCOEFCONTEXT + int tmp = qcoeff_ptr[scan[i]]; + qcoeff_ptr[scan[i]] = x; + if (NEWCOEFCONTEXT_BAND_COND(band)) + pt = vp9_get_coef_neighbor_context( + qcoeff_ptr, i0, neighbors, scan[i + 1]); + else + pt = vp9_prev_token_class[t1]; + qcoeff_ptr[scan[i]] = tmp; +#else pt = vp9_prev_token_class[t1]; +#endif rate1 += mb->token_costs[tx_size][type][band][pt][ tokens[next][1].token]; } diff --git a/vp9/encoder/vp9_rdopt.c b/vp9/encoder/vp9_rdopt.c index 3f9baef75..69bc892bb 100644 --- a/vp9/encoder/vp9_rdopt.c +++ b/vp9/encoder/vp9_rdopt.c @@ -513,29 +513,48 @@ int vp9_uvsse(MACROBLOCK *x) { } +#if CONFIG_NEWCOEFCONTEXT +#define PT pn +#else +#define PT pt +#endif + static int cost_coeffs_2x2(MACROBLOCK *mb, BLOCKD *b, PLANE_TYPE type, ENTROPY_CONTEXT *a, ENTROPY_CONTEXT *l) { - int c = (type == PLANE_TYPE_Y_NO_DC); /* start at coef 0, unless Y with Y2 */ + int nodc = (type == PLANE_TYPE_Y_NO_DC); + int c = nodc; /* start at coef 0, unless Y with Y2 */ int eob = b->eob; int pt; /* surrounding block/prev coef predictor */ int cost = 0; int16_t *qcoeff_ptr = b->qcoeff; +#if CONFIG_NEWCOEFCONTEXT + const int *neighbors = vp9_default_zig_zag1d_4x4_neighbors; + int pn; +#endif VP9_COMBINEENTROPYCONTEXTS(pt, *a, *l); assert(eob <= 4); +#if CONFIG_NEWCOEFCONTEXT + pn = pt; +#endif for (; c < eob; c++) { int v = qcoeff_ptr[vp9_default_zig_zag1d_4x4[c]]; int t = vp9_dct_value_tokens_ptr[v].Token; cost += mb->token_costs[TX_8X8][type][vp9_coef_bands_4x4[c]][pt][t]; cost += vp9_dct_value_cost_ptr[v]; pt = vp9_prev_token_class[t]; +#if CONFIG_NEWCOEFCONTEXT + if (c < 4 - 1) + pn = vp9_get_coef_neighbor_context( + qcoeff_ptr, nodc, neighbors, vp9_default_zig_zag1d_4x4[c + 1]); +#endif } if (c < 4) cost += mb->token_costs[TX_8X8][type][vp9_coef_bands_4x4[c]] - [pt] [DCT_EOB_TOKEN]; + [PT][DCT_EOB_TOKEN]; // is eob first coefficient; pt = (c > !type); *a = *l = pt; @@ -546,7 +565,8 @@ static int cost_coeffs(MACROBLOCK *mb, BLOCKD *b, PLANE_TYPE type, ENTROPY_CONTEXT *a, ENTROPY_CONTEXT *l, TX_SIZE tx_size) { const int eob = b->eob; - int c = (type == PLANE_TYPE_Y_NO_DC); /* start at coef 0, unless Y with Y2 */ + int nodc = (type == PLANE_TYPE_Y_NO_DC); + int c = nodc; /* start at coef 0, unless Y with Y2 */ int cost = 0, default_eob, seg_eob; int pt; /* surrounding block/prev coef predictor */ int const *scan, *band; @@ -555,6 +575,10 @@ static int cost_coeffs(MACROBLOCK *mb, BLOCKD *b, PLANE_TYPE type, MB_MODE_INFO *mbmi = &mb->e_mbd.mode_info_context->mbmi; TX_TYPE tx_type = DCT_DCT; int segment_id = mbmi->segment_id; +#if CONFIG_NEWCOEFCONTEXT + const int *neighbors; + int pn; +#endif scan = vp9_default_zig_zag1d_4x4; band = vp9_coef_bands_4x4; default_eob = 16; @@ -628,17 +652,28 @@ static int cost_coeffs(MACROBLOCK *mb, BLOCKD *b, PLANE_TYPE type, VP9_COMBINEENTROPYCONTEXTS(pt, *a, *l); +#if CONFIG_NEWCOEFCONTEXT + neighbors = vp9_get_coef_neighbors_handle(scan); + pn = pt; +#endif if (tx_type != DCT_DCT) { for (; c < eob; c++) { int v = qcoeff_ptr[scan[c]]; int t = vp9_dct_value_tokens_ptr[v].Token; - cost += mb->hybrid_token_costs[tx_size][type][band[c]][pt][t]; + cost += mb->hybrid_token_costs[tx_size][type][band[c]][PT][t]; cost += vp9_dct_value_cost_ptr[v]; pt = vp9_prev_token_class[t]; +#if CONFIG_NEWCOEFCONTEXT + if (c < seg_eob - 1 && NEWCOEFCONTEXT_BAND_COND(band[c + 1])) + pn = vp9_get_coef_neighbor_context( + qcoeff_ptr, nodc, neighbors, scan[c + 1]); + else + pn = pt; +#endif } if (c < seg_eob) cost += mb->hybrid_token_costs[tx_size][type][band[c]] - [pt][DCT_EOB_TOKEN]; + [PT][DCT_EOB_TOKEN]; } else { for (; c < eob; c++) { int v = qcoeff_ptr[scan[c]]; @@ -646,10 +681,17 @@ static int cost_coeffs(MACROBLOCK *mb, BLOCKD *b, PLANE_TYPE type, cost += mb->token_costs[tx_size][type][band[c]][pt][t]; cost += vp9_dct_value_cost_ptr[v]; pt = vp9_prev_token_class[t]; +#if CONFIG_NEWCOEFCONTEXT + if (c < seg_eob - 1 && NEWCOEFCONTEXT_BAND_COND(band[c + 1])) + pn = vp9_get_coef_neighbor_context( + qcoeff_ptr, nodc, neighbors, scan[c + 1]); + else + pn = pt; +#endif } if (c < seg_eob) cost += mb->token_costs[tx_size][type][band[c]] - [pt][DCT_EOB_TOKEN]; + [PT][DCT_EOB_TOKEN]; } // is eob first coefficient; diff --git a/vp9/encoder/vp9_tokenize.c b/vp9/encoder/vp9_tokenize.c index b0b5e6d5f..58bb251f5 100644 --- a/vp9/encoder/vp9_tokenize.c +++ b/vp9/encoder/vp9_tokenize.c @@ -103,6 +103,13 @@ static void fill_value_tokens() { vp9_dct_value_tokens_ptr = dct_value_tokens + DCT_MAX_VALUE; vp9_dct_value_cost_ptr = dct_value_cost + DCT_MAX_VALUE; } + +#if CONFIG_NEWCOEFCONTEXT +#define PT pn +#else +#define PT pt +#endif + static void tokenize_b(VP9_COMP *cpi, MACROBLOCKD *xd, const int ib, @@ -123,6 +130,10 @@ static void tokenize_b(VP9_COMP *cpi, vp9_coeff_probs *probs; const TX_TYPE tx_type = (type == PLANE_TYPE_Y_WITH_DC) ? get_tx_type(xd, b) : DCT_DCT; +#if CONFIG_NEWCOEFCONTEXT + const int *neighbors; + int pn; +#endif ENTROPY_CONTEXT *const a = (ENTROPY_CONTEXT *)xd->above_context + vp9_block2above[tx_size][ib]; @@ -229,6 +240,10 @@ static void tokenize_b(VP9_COMP *cpi, } VP9_COMBINEENTROPYCONTEXTS(pt, a_ec, l_ec); +#if CONFIG_NEWCOEFCONTEXT + neighbors = vp9_get_coef_neighbors_handle(scan); + pn = pt; +#endif if (vp9_segfeature_active(xd, segment_id, SEG_LVL_EOB)) seg_eob = vp9_get_segdata(xd, segment_id, SEG_LVL_EOB); @@ -249,14 +264,21 @@ static void tokenize_b(VP9_COMP *cpi, } t->Token = token; - t->context_tree = probs[type][band][pt]; + t->context_tree = probs[type][band][PT]; t->skip_eob_node = (pt == 0) && ((band > 0 && type != PLANE_TYPE_Y_NO_DC) || (band > 1 && type == PLANE_TYPE_Y_NO_DC)); assert(vp9_coef_encodings[t->Token].Len - t->skip_eob_node > 0); if (!dry_run) { - ++counts[type][band][pt][token]; + ++counts[type][band][PT][token]; } pt = vp9_prev_token_class[token]; +#if CONFIG_NEWCOEFCONTEXT + if (c < seg_eob - 1 && NEWCOEFCONTEXT_BAND_COND(bands[c + 1])) + pn = vp9_get_coef_neighbor_context( + qcoeff_ptr, (type == PLANE_TYPE_Y_NO_DC), neighbors, scan[c + 1]); + else + pn = pt; +#endif ++t; } while (c < eob && ++c < seg_eob);