summaryrefslogtreecommitdiff
path: root/vp9
diff options
context:
space:
mode:
Diffstat (limited to 'vp9')
-rw-r--r--vp9/common/vp9_blockd.h9
-rw-r--r--vp9/common/vp9_coefupdateprobs.h4
-rw-r--r--vp9/common/vp9_default_coef_probs.h83
-rw-r--r--vp9/common/vp9_entropy.c153
-rw-r--r--vp9/common/vp9_entropy.h56
-rw-r--r--vp9/common/vp9_onyxc_int.h22
-rw-r--r--vp9/decoder/vp9_decodframe.c65
-rw-r--r--vp9/decoder/vp9_detokenize.c129
-rw-r--r--vp9/encoder/vp9_bitstream.c311
-rw-r--r--vp9/encoder/vp9_encodeframe.c8
-rw-r--r--vp9/encoder/vp9_encodemb.c10
-rw-r--r--vp9/encoder/vp9_onyx_if.c28
-rw-r--r--vp9/encoder/vp9_onyx_int.h6
-rw-r--r--vp9/encoder/vp9_ratectrl.c12
-rw-r--r--vp9/encoder/vp9_rdopt.c140
-rw-r--r--vp9/encoder/vp9_tokenize.c167
-rw-r--r--vp9/encoder/vp9_tokenize.h3
17 files changed, 1142 insertions, 64 deletions
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_
diff --git a/vp9/decoder/vp9_decodframe.c b/vp9/decoder/vp9_decodframe.c
index fdd40db46..8b3b3b10b 100644
--- a/vp9/decoder/vp9_decodframe.c
+++ b/vp9/decoder/vp9_decodframe.c
@@ -995,6 +995,54 @@ static void init_frame(VP9D_COMP *pbi) {
xd->corrupted = 0;
}
+#if CONFIG_CODE_ZEROGROUP
+static void read_zpc_probs_common(VP9_COMMON *cm,
+ vp9_reader* bc,
+ TX_SIZE tx_size) {
+ int r, b, p, n;
+ vp9_zpc_probs *zpc_probs;
+ vp9_prob upd = ZPC_UPDATE_PROB;
+ if (!get_zpc_used(tx_size)) return;
+ if (!vp9_read_bit(bc)) return;
+
+ if (tx_size == TX_32X32) {
+ zpc_probs = &cm->fc.zpc_probs_32x32;
+ } else if (tx_size == TX_16X16) {
+ zpc_probs = &cm->fc.zpc_probs_16x16;
+ } else if (tx_size == TX_8X8) {
+ zpc_probs = &cm->fc.zpc_probs_8x8;
+ } else {
+ zpc_probs = &cm->fc.zpc_probs_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 *q = &(*zpc_probs)[r][b][p][n];
+#if USE_ZPC_EXTRA == 0
+ if (n == 1) continue;
+#endif
+ if (vp9_read(bc, upd)) {
+ *q = read_prob_diff_update(bc, *q);
+ }
+ }
+ }
+ }
+ }
+}
+
+static void read_zpc_probs(VP9_COMMON *cm,
+ vp9_reader* bc) {
+ read_zpc_probs_common(cm, bc, TX_4X4);
+ if (cm->txfm_mode != ONLY_4X4)
+ read_zpc_probs_common(cm, bc, TX_8X8);
+ if (cm->txfm_mode > ALLOW_8X8)
+ read_zpc_probs_common(cm, bc, TX_16X16);
+ if (cm->txfm_mode > ALLOW_16X16)
+ read_zpc_probs_common(cm, bc, TX_32X32);
+}
+#endif // CONFIG_CODE_ZEROGROUP
+
#if CONFIG_CODE_NONZEROCOUNT
static void read_nzc_probs_common(VP9_COMMON *cm,
vp9_reader *rd,
@@ -1404,6 +1452,17 @@ static void update_frame_context(VP9D_COMP *pbi) {
vp9_zero(fc->nzc_counts_32x32);
vp9_zero(fc->nzc_pcat_counts);
#endif
+#if CONFIG_CODE_ZEROGROUP
+ vp9_copy(fc->pre_zpc_probs_4x4, fc->zpc_probs_4x4);
+ vp9_copy(fc->pre_zpc_probs_8x8, fc->zpc_probs_8x8);
+ vp9_copy(fc->pre_zpc_probs_16x16, fc->zpc_probs_16x16);
+ vp9_copy(fc->pre_zpc_probs_32x32, fc->zpc_probs_32x32);
+
+ vp9_zero(fc->zpc_counts_4x4);
+ vp9_zero(fc->zpc_counts_8x8);
+ vp9_zero(fc->zpc_counts_16x16);
+ vp9_zero(fc->zpc_counts_32x32);
+#endif
}
static void decode_tiles(VP9D_COMP *pbi,
@@ -1660,6 +1719,9 @@ int vp9_decode_frame(VP9D_COMP *pbi, const uint8_t **p_data_end) {
#if CONFIG_CODE_NONZEROCOUNT
read_nzc_probs(&pbi->common, &header_bc);
#endif
+#if CONFIG_CODE_ZEROGROUP
+ read_zpc_probs(&pbi->common, &header_bc);
+#endif
// Initialize xd pointers. Any reference should do for xd->pre, so use 0.
vpx_memcpy(&xd->pre, &pc->yv12_fb[pc->active_ref_idx[0]],
@@ -1712,6 +1774,9 @@ int vp9_decode_frame(VP9D_COMP *pbi, const uint8_t **p_data_end) {
#if CONFIG_CODE_NONZEROCOUNT
vp9_adapt_nzc_probs(pc);
#endif
+#if CONFIG_CODE_ZEROGROUP
+ vp9_adapt_zpc_probs(pc);
+#endif
}
if (pc->frame_type != KEY_FRAME) {
diff --git a/vp9/decoder/vp9_detokenize.c b/vp9/decoder/vp9_detokenize.c
index b3a6927c2..7cfc7dc65 100644
--- a/vp9/decoder/vp9_detokenize.c
+++ b/vp9/decoder/vp9_detokenize.c
@@ -60,14 +60,28 @@ static const vp9_prob cat6_prob[15] = {
DECLARE_ALIGNED(16, extern const uint8_t, vp9_norm[256]);
+#if CONFIG_CODE_ZEROGROUP
+#define ZEROGROUP_ADVANCE() \
+ do { \
+ token_cache[scan[c]] = ZERO_TOKEN; \
+ is_last_zero[o] = 1; \
+ c++; \
+ } while (0)
+#define INCREMENT_COUNT(token) \
+ do { \
+ coef_counts[type][ref][get_coef_band(scan, txfm_size, c)] \
+ [pt][token]++; \
+ token_cache[scan[c]] = token; \
+ is_last_zero[o] = (token == ZERO_TOKEN); \
+ } while (0)
+#else
#define INCREMENT_COUNT(token) \
do { \
coef_counts[type][ref][get_coef_band(scan, txfm_size, c)] \
[pt][token]++; \
- token_cache[c] = token; \
- pt = vp9_get_coef_context(scan, nb, pad, token_cache, \
- c + 1, default_eob); \
+ token_cache[scan[c]] = token; \
} while (0)
+#endif
#if CONFIG_CODE_NONZEROCOUNT
#define WRITE_COEF_CONTINUE(val, token) \
@@ -88,6 +102,12 @@ DECLARE_ALIGNED(16, extern const uint8_t, vp9_norm[256]);
}
#endif // CONFIG_CODE_NONZEROCOUNT
+#define WRITE_COEF_ONE() \
+{ \
+ qcoeff_ptr[scan[c]] = vp9_read_and_apply_sign(br, 1); \
+ INCREMENT_COUNT(ONE_TOKEN); \
+}
+
#define ADJUST_COEF(prob, bits_count) \
do { \
if (vp9_read(r, prob)) \
@@ -108,6 +128,16 @@ static int decode_coefs(VP9D_COMP *dx, const MACROBLOCKD *xd,
vp9_prob *prob;
vp9_coeff_count *coef_counts;
const int ref = xd->mode_info_context->mbmi.ref_frame != INTRA_FRAME;
+ TX_TYPE tx_type = DCT_DCT;
+#if CONFIG_CODE_ZEROGROUP
+ int is_eoo[3] = {0, 0, 0};
+ int is_last_zero[3] = {0, 0, 0};
+ int o, rc;
+ vp9_zpc_probs *zpc_probs;
+ vp9_zpc_count *zpc_count;
+ vp9_prob *zprobs;
+ int eoo = 0, use_eoo;
+#endif
#if CONFIG_CODE_NONZEROCOUNT
const int nzc_used = get_nzc_used(txfm_size);
uint16_t nzc = 0;
@@ -116,6 +146,9 @@ static int decode_coefs(VP9D_COMP *dx, const MACROBLOCKD *xd,
#endif
const int *scan, *nb;
uint8_t token_cache[1024];
+#if CONFIG_CODE_ZEROGROUP
+ vpx_memset(token_cache, UNKNOWN_TOKEN, sizeof(token_cache));
+#endif
if (xd->mode_info_context->mbmi.sb_type == BLOCK_SIZE_SB64X64) {
aidx = vp9_block2above_sb64[txfm_size][block_idx];
@@ -147,8 +180,8 @@ static int decode_coefs(VP9D_COMP *dx, const MACROBLOCKD *xd,
switch (txfm_size) {
default:
case TX_4X4: {
- const TX_TYPE tx_type = (type == PLANE_TYPE_Y_WITH_DC) ?
- get_tx_type_4x4(xd, block_idx) : DCT_DCT;
+ tx_type = (type == PLANE_TYPE_Y_WITH_DC) ?
+ get_tx_type_4x4(xd, block_idx) : DCT_DCT;
switch (tx_type) {
default:
scan = vp9_default_zig_zag1d_4x4;
@@ -165,6 +198,10 @@ static int decode_coefs(VP9D_COMP *dx, const MACROBLOCKD *xd,
coef_probs = fc->coef_probs_4x4;
coef_counts = fc->coef_counts_4x4;
default_eob = 16;
+#if CONFIG_CODE_ZEROGROUP
+ zpc_probs = &(fc->zpc_probs_4x4);
+ zpc_count = &(fc->zpc_counts_4x4);
+#endif
break;
}
case TX_8X8: {
@@ -172,8 +209,8 @@ static int decode_coefs(VP9D_COMP *dx, const MACROBLOCKD *xd,
const int sz = 3 + mb_width_log2(sb_type);
const int x = block_idx & ((1 << sz) - 1);
const int y = block_idx - x;
- const TX_TYPE tx_type = (type == PLANE_TYPE_Y_WITH_DC) ?
- get_tx_type_8x8(xd, y + (x >> 1)) : DCT_DCT;
+ tx_type = (type == PLANE_TYPE_Y_WITH_DC) ?
+ get_tx_type_8x8(xd, y + (x >> 1)) : DCT_DCT;
switch (tx_type) {
default:
scan = vp9_default_zig_zag1d_8x8;
@@ -190,6 +227,10 @@ static int decode_coefs(VP9D_COMP *dx, const MACROBLOCKD *xd,
above_ec = (A0[aidx] + A0[aidx + 1]) != 0;
left_ec = (L0[lidx] + L0[lidx + 1]) != 0;
default_eob = 64;
+#if CONFIG_CODE_ZEROGROUP
+ zpc_probs = &(fc->zpc_probs_8x8);
+ zpc_count = &(fc->zpc_counts_8x8);
+#endif
break;
}
case TX_16X16: {
@@ -197,8 +238,8 @@ static int decode_coefs(VP9D_COMP *dx, const MACROBLOCKD *xd,
const int sz = 4 + mb_width_log2(sb_type);
const int x = block_idx & ((1 << sz) - 1);
const int y = block_idx - x;
- const TX_TYPE tx_type = (type == PLANE_TYPE_Y_WITH_DC) ?
- get_tx_type_16x16(xd, y + (x >> 2)) : DCT_DCT;
+ tx_type = (type == PLANE_TYPE_Y_WITH_DC) ?
+ get_tx_type_16x16(xd, y + (x >> 2)) : DCT_DCT;
switch (tx_type) {
default:
scan = vp9_default_zig_zag1d_16x16;
@@ -222,6 +263,10 @@ static int decode_coefs(VP9D_COMP *dx, const MACROBLOCKD *xd,
left_ec = (L0[lidx] + L0[lidx + 1] + L0[lidx + 2] + L0[lidx + 3]) != 0;
}
default_eob = 256;
+#if CONFIG_CODE_ZEROGROUP
+ zpc_probs = &(fc->zpc_probs_16x16);
+ zpc_count = &(fc->zpc_counts_16x16);
+#endif
break;
}
case TX_32X32:
@@ -248,6 +293,10 @@ static int decode_coefs(VP9D_COMP *dx, const MACROBLOCKD *xd,
L1[lidx] + L1[lidx + 1] + L1[lidx + 2] + L1[lidx + 3]) != 0;
}
default_eob = 1024;
+#if CONFIG_CODE_ZEROGROUP
+ zpc_probs = &fc->zpc_probs_32x32;
+ zpc_count = &fc->zpc_counts_32x32;
+#endif
break;
}
@@ -256,35 +305,85 @@ static int decode_coefs(VP9D_COMP *dx, const MACROBLOCKD *xd,
while (1) {
int val;
+ int band;
const uint8_t *cat6 = cat6_prob;
-
if (c >= seg_eob)
break;
#if CONFIG_CODE_NONZEROCOUNT
if (nzc_used && nzc == nzc_expected)
break;
#endif
- prob = coef_probs[type][ref][get_coef_band(scan, txfm_size, c)][pt];
- fc->eob_branch_counts[txfm_size][type][ref]
- [get_coef_band(scan, txfm_size, c)][pt]++;
+ if (c)
+ pt = vp9_get_coef_context(scan, nb, pad, token_cache,
+ c, default_eob);
+ band = get_coef_band(scan, txfm_size, c);
+ prob = coef_probs[type][ref][band][pt];
+ fc->eob_branch_counts[txfm_size][type][ref][band][pt]++;
#if CONFIG_CODE_NONZEROCOUNT
- if (!nzc_used)
+ if (!nzc_used) {
#endif
if (!vp9_read(r, prob[EOB_CONTEXT_NODE]))
break;
+#if CONFIG_CODE_ZEROGROUP
+ rc = scan[c];
+ o = vp9_get_orientation(rc, txfm_size);
+ if (token_cache[rc] == ZERO_TOKEN || is_eoo[o]) {
+ coef_counts[type][ref][band][pt][ZERO_TOKEN]++;
+ ZEROGROUP_ADVANCE();
+ goto SKIP_START;
+ }
+#endif
+#if CONFIG_CODE_NONZEROCOUNT
+ }
+#endif
+
SKIP_START:
if (c >= seg_eob)
break;
#if CONFIG_CODE_NONZEROCOUNT
if (nzc_used && nzc == nzc_expected)
break;
+#endif
+ if (c)
+ pt = vp9_get_coef_context(scan, nb, pad, token_cache,
+ c, default_eob);
+ band = get_coef_band(scan, txfm_size, c);
+ prob = coef_probs[type][ref][band][pt];
+#if CONFIG_CODE_ZEROGROUP
+ rc = scan[c];
+ o = vp9_get_orientation(rc, txfm_size);
+ if (token_cache[rc] == ZERO_TOKEN || is_eoo[o]) {
+ ZEROGROUP_ADVANCE();
+ goto SKIP_START;
+ }
+ zprobs = (*zpc_probs)[ref]
+ [coef_to_zpc_band(band)]
+ [coef_to_zpc_ptok(pt)];
+#endif
+#if CONFIG_CODE_NONZEROCOUNT
// decode zero node only if there are zeros left
if (!nzc_used || seg_eob - nzc_expected - c + nzc > 0)
#endif
if (!vp9_read(r, prob[ZERO_CONTEXT_NODE])) {
+#if CONFIG_CODE_ZEROGROUP
+ eoo = 0;
+#if USE_ZPC_EOORIENT == 1
+ use_eoo = vp9_use_eoo(c, seg_eob, scan, txfm_size, is_last_zero, is_eoo);
+#else
+ use_eoo = 0;
+#endif
+ if (use_eoo) {
+ eoo = !vp9_read(r, zprobs[0]);
+ ++(*zpc_count)[ref]
+ [coef_to_zpc_band(band)]
+ [coef_to_zpc_ptok(pt)][0][!eoo];
+ if (eoo) {
+ is_eoo[o] = 1;
+ }
+ }
+#endif
INCREMENT_COUNT(ZERO_TOKEN);
++c;
- prob = coef_probs[type][ref][get_coef_band(scan, txfm_size, c)][pt];
goto SKIP_START;
}
// ONE_CONTEXT_NODE_0_
diff --git a/vp9/encoder/vp9_bitstream.c b/vp9/encoder/vp9_bitstream.c
index 95e05fd55..b12e28816 100644
--- a/vp9/encoder/vp9_bitstream.c
+++ b/vp9/encoder/vp9_bitstream.c
@@ -67,6 +67,17 @@ void update_nzcstats(VP9_COMMON *const cm);
void print_nzcstats();
#endif
#endif
+#if CONFIG_CODE_ZEROGROUP
+#ifdef ZPC_STATS
+vp9_zpc_count zpc_stats_4x4;
+vp9_zpc_count zpc_stats_8x8;
+vp9_zpc_count zpc_stats_16x16;
+vp9_zpc_count zpc_stats_32x32;
+void init_zpcstats();
+void update_zpcstats(VP9_COMMON *const cm);
+void print_zpcstats();
+#endif
+#endif
#ifdef MODE_STATS
int count_mb_seg[4] = { 0, 0, 0, 0 };
@@ -427,24 +438,42 @@ static void pack_mb_tokens(vp9_writer* const bc,
const unsigned char *pp = p->context_tree;
int v = a->value;
int n = a->len;
+ int ncount = n;
if (t == EOSB_TOKEN)
{
++p;
break;
}
+ assert(pp != 0);
+#if CONFIG_CODE_ZEROGROUP
+ if (t == ZPC_ISOLATED || t == ZPC_EOORIENT) {
+ assert((p - 1)->token == ZERO_TOKEN);
+ encode_bool(bc, t == ZPC_ISOLATED, *pp);
+ ++p;
+ continue;
+ } else if (p->skip_coef_val) {
+ assert(p->skip_eob_node == 0);
+ assert(t == DCT_EOB_TOKEN || t == ZERO_TOKEN);
+ encode_bool(bc, t == ZERO_TOKEN, *pp);
+ ++p;
+ continue;
+ }
+#endif
/* skip one or two nodes */
if (p->skip_eob_node) {
n -= p->skip_eob_node;
i = 2 * p->skip_eob_node;
+ ncount -= p->skip_eob_node;
}
do {
const int bb = (v >> --n) & 1;
vp9_write(bc, bb, pp[i >> 1]);
i = vp9_coef_tree[i + bb];
- } while (n);
+ ncount--;
+ } while (n && ncount);
if (b->base_val) {
@@ -1541,6 +1570,150 @@ void print_nzcstats() {
#endif // CONFIG_CODE_NONZEROCOUNT
+#if CONFIG_CODE_ZEROGROUP
+#ifdef ZPC_STATS
+void init_zpcstats() {
+ vp9_zero(zpc_stats_4x4);
+ vp9_zero(zpc_stats_8x8);
+ vp9_zero(zpc_stats_16x16);
+ vp9_zero(zpc_stats_32x32);
+}
+
+void update_zpcstats(VP9_COMMON *const cm) {
+ int r, b, p, n;
+ 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) {
+ zpc_stats_4x4[r][b][p][n][0] += cm->fc.zpc_counts_4x4[r][b][p][n][0];
+ zpc_stats_4x4[r][b][p][n][1] += cm->fc.zpc_counts_4x4[r][b][p][n][1];
+ zpc_stats_8x8[r][b][p][n][0] += cm->fc.zpc_counts_8x8[r][b][p][n][0];
+ zpc_stats_8x8[r][b][p][n][1] += cm->fc.zpc_counts_8x8[r][b][p][n][1];
+ zpc_stats_16x16[r][b][p][n][0] +=
+ cm->fc.zpc_counts_16x16[r][b][p][n][0];
+ zpc_stats_16x16[r][b][p][n][1] +=
+ cm->fc.zpc_counts_16x16[r][b][p][n][1];
+ zpc_stats_32x32[r][b][p][n][0] +=
+ cm->fc.zpc_counts_32x32[r][b][p][n][0];
+ zpc_stats_32x32[r][b][p][n][1] +=
+ cm->fc.zpc_counts_32x32[r][b][p][n][1];
+ }
+ }
+ }
+ }
+}
+
+void print_zpcstats() {
+ int r, b, p, n;
+ FILE *f;
+
+ printf(
+ "static const unsigned int default_zpc_probs_4x4[REF_TYPES]\n"
+ " [ZPC_BANDS]\n"
+ " [ZPC_PTOKS]\n"
+ " [ZPC_NODES] = {\n");
+ for (r = 0; r < REF_TYPES; ++r) {
+ printf(" {\n");
+ for (b = 0; b < ZPC_BANDS; ++b) {
+ printf(" {\n");
+ for (p = 0; p < ZPC_PTOKS; ++p) {
+ printf(" {");
+ for (n = 0; n < ZPC_NODES; ++n) {
+ vp9_prob prob = get_binary_prob(zpc_stats_4x4[r][b][p][n][0],
+ zpc_stats_4x4[r][b][p][n][1]);
+ printf(" %-3d [%d/%d],", prob, zpc_stats_4x4[r][b][p][n][0],
+ zpc_stats_4x4[r][b][p][n][1]);
+ }
+ printf(" },\n");
+ }
+ printf(" },\n");
+ }
+ printf(" },\n");
+ }
+ printf("};\n");
+ printf(
+ "static const unsigned int default_zpc_probs_8x8[REF_TYPES]\n"
+ " [ZPC_BANDS]\n"
+ " [ZPC_PTOKS]\n"
+ " [ZPC_NODES] = {\n");
+ for (r = 0; r < REF_TYPES; ++r) {
+ printf(" {\n");
+ for (b = 0; b < ZPC_BANDS; ++b) {
+ printf(" {\n");
+ for (p = 0; p < ZPC_PTOKS; ++p) {
+ printf(" {");
+ for (n = 0; n < ZPC_NODES; ++n) {
+ vp9_prob prob = get_binary_prob(zpc_stats_8x8[r][b][p][n][0],
+ zpc_stats_8x8[r][b][p][n][1]);
+ printf(" %-3d [%d/%d],", prob, zpc_stats_8x8[r][b][p][n][0],
+ zpc_stats_8x8[r][b][p][n][1]);
+ }
+ printf(" },\n");
+ }
+ printf(" },\n");
+ }
+ printf(" },\n");
+ }
+ printf("};\n");
+ printf(
+ "static const unsigned int default_zpc_probs_16x16[REF_TYPES]\n"
+ " [ZPC_BANDS]\n"
+ " [ZPC_PTOKS]\n"
+ " [ZPC_NODES] = {\n");
+ for (r = 0; r < REF_TYPES; ++r) {
+ printf(" {\n");
+ for (b = 0; b < ZPC_BANDS; ++b) {
+ printf(" {\n");
+ for (p = 0; p < ZPC_PTOKS; ++p) {
+ printf(" {");
+ for (n = 0; n < ZPC_NODES; ++n) {
+ vp9_prob prob = get_binary_prob(zpc_stats_16x16[r][b][p][n][0],
+ zpc_stats_16x16[r][b][p][n][1]);
+ printf(" %-3d [%d/%d],", prob, zpc_stats_16x16[r][b][p][n][0],
+ zpc_stats_16x16[r][b][p][n][1]);
+ }
+ printf(" },\n");
+ }
+ printf(" },\n");
+ }
+ printf(" },\n");
+ }
+ printf("};\n");
+ printf(
+ "static const unsigned int default_zpc_probs_32x32[REF_TYPES]\n"
+ " [ZPC_BANDS]\n"
+ " [ZPC_PTOKS]\n"
+ " [ZPC_NODES] = {\n");
+ for (r = 0; r < REF_TYPES; ++r) {
+ printf(" {\n");
+ for (b = 0; b < ZPC_BANDS; ++b) {
+ printf(" {\n");
+ for (p = 0; p < ZPC_PTOKS; ++p) {
+ printf(" {");
+ for (n = 0; n < ZPC_NODES; ++n) {
+ vp9_prob prob = get_binary_prob(zpc_stats_32x32[r][b][p][n][0],
+ zpc_stats_32x32[r][b][p][n][1]);
+ printf(" %-3d [%d/%d],", prob, zpc_stats_32x32[r][b][p][n][0],
+ zpc_stats_32x32[r][b][p][n][1]);
+ }
+ printf(" },\n");
+ }
+ printf(" },\n");
+ }
+ printf(" },\n");
+ }
+ printf("};\n");
+
+ f = fopen("zpcstats.bin", "wb");
+ fwrite(zpc_stats_4x4, sizeof(zpc_stats_4x4), 1, f);
+ fwrite(zpc_stats_8x8, sizeof(zpc_stats_8x8), 1, f);
+ fwrite(zpc_stats_16x16, sizeof(zpc_stats_16x16), 1, f);
+ fwrite(zpc_stats_32x32, sizeof(zpc_stats_32x32), 1, f);
+ fclose(f);
+}
+#endif
+#endif // CONFIG_CODE_ZEROGROUP
+
static void write_modes_b(VP9_COMP *cpi, MODE_INFO *m, vp9_writer *bc,
TOKENEXTRA **tok, TOKENEXTRA *tok_end,
int mb_row, int mb_col) {
@@ -1779,6 +1952,129 @@ static void build_coeff_contexts(VP9_COMP *cpi) {
cpi->frame_branch_ct_32x32, BLOCK_TYPES);
}
+#if CONFIG_CODE_ZEROGROUP
+static void update_zpc_probs_common(VP9_COMP* cpi,
+ vp9_writer* const bc,
+ TX_SIZE tx_size) {
+ int r, b, p, n;
+ VP9_COMMON *const cm = &cpi->common;
+ int update[2] = {0, 0};
+ int savings = 0;
+ vp9_zpc_probs newprobs;
+ vp9_zpc_probs *zpc_probs;
+ vp9_zpc_count *zpc_counts;
+ vp9_prob upd = ZPC_UPDATE_PROB;
+
+ if (!get_zpc_used(tx_size)) return;
+ if (tx_size == TX_32X32) {
+ zpc_probs = &cm->fc.zpc_probs_32x32;
+ zpc_counts = &cm->fc.zpc_counts_32x32;
+ } else if (tx_size == TX_16X16) {
+ zpc_probs = &cm->fc.zpc_probs_16x16;
+ zpc_counts = &cm->fc.zpc_counts_16x16;
+ } else if (tx_size == TX_8X8) {
+ zpc_probs = &cm->fc.zpc_probs_8x8;
+ zpc_counts = &cm->fc.zpc_counts_8x8;
+ } else {
+ zpc_probs = &cm->fc.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) {
+ newprobs[r][b][p][n] = get_binary_prob((*zpc_counts)[r][b][p][n][0],
+ (*zpc_counts)[r][b][p][n][1]);
+ }
+ }
+ }
+ }
+ 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 newp = newprobs[r][b][p][n];
+ vp9_prob oldp = (*zpc_probs)[r][b][p][n];
+ int s, u = 0;
+#if USE_ZPC_EXTRA == 0
+ if (n == 1) continue;
+#endif
+#if defined(SEARCH_NEWP)
+ s = prob_diff_update_savings_search((*zpc_counts)[r][b][p][n],
+ oldp, &newp, upd);
+ if (s > 0 && newp != oldp)
+ u = 1;
+ if (u)
+ savings += s - (int)(vp9_cost_zero(upd));
+ else
+ savings -= (int)(vp9_cost_zero(upd));
+#else
+ s = prob_update_savings((*zpc_counts)[r][b][p][n],
+ oldp, newp, upd);
+ if (s > 0)
+ u = 1;
+ if (u)
+ savings += s;
+#endif
+ update[u]++;
+ }
+ }
+ }
+ }
+ if (update[1] == 0 || savings < 0) {
+ vp9_write_bit(bc, 0);
+ return;
+ }
+ vp9_write_bit(bc, 1);
+ 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 newp = newprobs[r][b][p][n];
+ vp9_prob *oldp = &(*zpc_probs)[r][b][p][n];
+ int s, u = 0;
+#if USE_ZPC_EXTRA == 0
+ if (n == 1) continue;
+#endif
+#if defined(SEARCH_NEWP)
+ s = prob_diff_update_savings_search((*zpc_counts)[r][b][p][n],
+ *oldp, &newp, upd);
+ if (s > 0 && newp != *oldp)
+ u = 1;
+#else
+ s = prob_update_savings((*zpc_counts)[r][b][p][n],
+ *oldp, newp, upd);
+ if (s > 0)
+ u = 1;
+#endif
+ vp9_write(bc, u, upd);
+ if (u) {
+ /* send/use new probability */
+ write_prob_diff_update(bc, newp, *oldp);
+ *oldp = newp;
+ }
+ }
+ }
+ }
+ }
+}
+
+static void update_zpc_probs(VP9_COMP* cpi,
+ vp9_writer* const bc) {
+ update_zpc_probs_common(cpi, bc, TX_4X4);
+ if (cpi->common.txfm_mode != ONLY_4X4)
+ update_zpc_probs_common(cpi, bc, TX_8X8);
+ if (cpi->common.txfm_mode > ALLOW_8X8)
+ update_zpc_probs_common(cpi, bc, TX_16X16);
+ if (cpi->common.txfm_mode > ALLOW_16X16)
+ update_zpc_probs_common(cpi, bc, TX_32X32);
+#ifdef ZPC_STATS
+ if (!cpi->dummy_packing)
+ update_zpcstats(&cpi->common);
+#endif
+}
+#endif // CONFIG_CODE_ZEROGROUP
+
#if CONFIG_CODE_NONZEROCOUNT
static void update_nzc_probs_common(VP9_COMP* cpi,
vp9_writer* const bc,
@@ -2691,6 +2987,16 @@ void vp9_pack_bitstream(VP9_COMP *cpi, unsigned char *dest,
vp9_zero(cpi->common.fc.nzc_pcat_counts);
*/
#endif
+#if CONFIG_CODE_ZEROGROUP
+ vp9_copy(cpi->common.fc.pre_zpc_probs_4x4,
+ cpi->common.fc.zpc_probs_4x4);
+ vp9_copy(cpi->common.fc.pre_zpc_probs_8x8,
+ cpi->common.fc.zpc_probs_8x8);
+ vp9_copy(cpi->common.fc.pre_zpc_probs_16x16,
+ cpi->common.fc.zpc_probs_16x16);
+ vp9_copy(cpi->common.fc.pre_zpc_probs_32x32,
+ cpi->common.fc.zpc_probs_32x32);
+#endif
vp9_copy(cpi->common.fc.pre_sb_ymode_prob, cpi->common.fc.sb_ymode_prob);
vp9_copy(cpi->common.fc.pre_ymode_prob, cpi->common.fc.ymode_prob);
vp9_copy(cpi->common.fc.pre_uv_mode_prob, cpi->common.fc.uv_mode_prob);
@@ -2711,6 +3017,9 @@ void vp9_pack_bitstream(VP9_COMP *cpi, unsigned char *dest,
#if CONFIG_CODE_NONZEROCOUNT
update_nzc_probs(cpi, &header_bc);
#endif
+#if CONFIG_CODE_ZEROGROUP
+ update_zpc_probs(cpi, &header_bc);
+#endif
#ifdef ENTROPY_STATS
active_section = 2;
diff --git a/vp9/encoder/vp9_encodeframe.c b/vp9/encoder/vp9_encodeframe.c
index e9612b988..dbd06a06c 100644
--- a/vp9/encoder/vp9_encodeframe.c
+++ b/vp9/encoder/vp9_encodeframe.c
@@ -1345,6 +1345,12 @@ static void encode_frame_internal(VP9_COMP *cpi) {
vp9_zero(cm->fc.nzc_counts_32x32);
vp9_zero(cm->fc.nzc_pcat_counts);
#endif
+#if CONFIG_CODE_ZEROGROUP
+ vp9_zero(cm->fc.zpc_counts_4x4);
+ vp9_zero(cm->fc.zpc_counts_8x8);
+ vp9_zero(cm->fc.zpc_counts_16x16);
+ vp9_zero(cm->fc.zpc_counts_32x32);
+#endif
cpi->mb.e_mbd.lossless = (cm->base_qindex == 0 &&
cm->y_dc_delta_q == 0 &&
@@ -1397,6 +1403,8 @@ static void encode_frame_internal(VP9_COMP *cpi) {
encode_sb_row(cpi, mb_row, &tp, &totalrate);
}
cpi->tok_count[tile_col] = (unsigned int)(tp - tp_old);
+ assert(tp - cpi->tok <=
+ get_token_alloc(cm->mb_rows, cm->mb_cols));
}
}
}
diff --git a/vp9/encoder/vp9_encodemb.c b/vp9/encoder/vp9_encodemb.c
index ea19fbfa8..cf2625db4 100644
--- a/vp9/encoder/vp9_encodemb.c
+++ b/vp9/encoder/vp9_encodemb.c
@@ -295,10 +295,10 @@ static int trellis_get_coeff_context(const int *scan,
int idx, int token,
uint8_t *token_cache,
int pad, int l) {
- int bak = token_cache[idx], pt;
- token_cache[idx] = token;
+ int bak = token_cache[scan[idx]], pt;
+ token_cache[scan[idx]] = token;
pt = vp9_get_coef_context(scan, nb, pad, token_cache, idx + 1, l);
- token_cache[idx] = bak;
+ token_cache[scan[idx]] = bak;
return pt;
}
@@ -430,7 +430,7 @@ static void optimize_b(VP9_COMMON *const cm,
*(tokens[eob] + 1) = *(tokens[eob] + 0);
next = eob;
for (i = 0; i < eob; i++)
- token_cache[i] = vp9_dct_value_tokens_ptr[qcoeff_ptr[scan[i]]].token;
+ token_cache[scan[i]] = vp9_dct_value_tokens_ptr[qcoeff_ptr[scan[i]]].token;
nb = vp9_get_coef_neighbors_handle(scan, &pad);
for (i = eob; i-- > i0;) {
@@ -590,6 +590,8 @@ static void optimize_b(VP9_COMMON *const cm,
final_nzc_exp = (best ? nzc1 : nzc0);
#endif
final_eob = i0 - 1;
+ vpx_memset(qcoeff_ptr, 0, sizeof(*qcoeff_ptr) * (16 << (tx_size * 2)));
+ vpx_memset(dqcoeff_ptr, 0, sizeof(*dqcoeff_ptr) * (16 << (tx_size * 2)));
for (i = next; i < eob; i = next) {
x = tokens[i][best].qc;
if (x) {
diff --git a/vp9/encoder/vp9_onyx_if.c b/vp9/encoder/vp9_onyx_if.c
index 66ed1da72..1c308af39 100644
--- a/vp9/encoder/vp9_onyx_if.c
+++ b/vp9/encoder/vp9_onyx_if.c
@@ -120,6 +120,12 @@ extern void init_nzcstats();
extern void print_nzcstats();
#endif
#endif
+#if CONFIG_CODE_ZEROGROUP
+#ifdef ZPC_STATS
+extern void init_zpcstats();
+extern void print_zpcstats();
+#endif
+#endif
#ifdef SPEEDSTATS
unsigned int frames_at_speed[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
@@ -895,7 +901,7 @@ void vp9_alloc_compressor_data(VP9_COMP *cpi) {
vpx_free(cpi->tok);
{
- unsigned int tokens = cm->mb_rows * cm->mb_cols * (24 * 16 + 1);
+ unsigned int tokens = get_token_alloc(cm->mb_rows, cm->mb_cols);
CHECK_MEM_ERROR(cpi->tok, vpx_calloc(tokens, sizeof(*cpi->tok)));
}
@@ -1438,6 +1444,11 @@ VP9_PTR vp9_create_compressor(VP9_CONFIG *oxcf) {
init_nzcstats();
#endif
#endif
+#if CONFIG_CODE_ZEROGROUP
+#ifdef ZPC_STATS
+ init_zpcstats();
+#endif
+#endif
/*Initialize the feed-forward activity masking.*/
cpi->activity_avg = 90 << 12;
@@ -1650,6 +1661,12 @@ VP9_PTR vp9_create_compressor(VP9_CONFIG *oxcf) {
vp9_zero(cm->fc.nzc_counts_32x32);
vp9_zero(cm->fc.nzc_pcat_counts);
#endif
+#if CONFIG_CODE_ZEROGROUP
+ vp9_zero(cm->fc.zpc_counts_4x4);
+ vp9_zero(cm->fc.zpc_counts_8x8);
+ vp9_zero(cm->fc.zpc_counts_16x16);
+ vp9_zero(cm->fc.zpc_counts_32x32);
+#endif
return (VP9_PTR) cpi;
}
@@ -1683,6 +1700,12 @@ void vp9_remove_compressor(VP9_PTR *ptr) {
print_nzcstats();
#endif
#endif
+#if CONFIG_CODE_ZEROGROUP
+#ifdef ZPC_STATS
+ if (cpi->pass != 1)
+ print_zpcstats();
+#endif
+#endif
#if CONFIG_INTERNAL_STATS
@@ -3304,6 +3327,9 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi,
#if CONFIG_CODE_NONZEROCOUNT
vp9_adapt_nzc_probs(&cpi->common);
#endif
+#if CONFIG_CODE_ZEROGROUP
+ vp9_adapt_zpc_probs(&cpi->common);
+#endif
}
if (cpi->common.frame_type != KEY_FRAME) {
vp9_copy(cpi->common.fc.sb_ymode_counts, cpi->sb_ymode_count);
diff --git a/vp9/encoder/vp9_onyx_int.h b/vp9/encoder/vp9_onyx_int.h
index 6d309c84d..a6cfe9367 100644
--- a/vp9/encoder/vp9_onyx_int.h
+++ b/vp9/encoder/vp9_onyx_int.h
@@ -126,6 +126,12 @@ typedef struct {
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
} CODING_CONTEXT;
typedef struct {
diff --git a/vp9/encoder/vp9_ratectrl.c b/vp9/encoder/vp9_ratectrl.c
index 96d857fe7..30889d3e8 100644
--- a/vp9/encoder/vp9_ratectrl.c
+++ b/vp9/encoder/vp9_ratectrl.c
@@ -179,6 +179,12 @@ void vp9_save_coding_context(VP9_COMP *cpi) {
vp9_copy(cc->nzc_probs_32x32, cm->fc.nzc_probs_32x32);
vp9_copy(cc->nzc_pcat_probs, cm->fc.nzc_pcat_probs);
#endif
+#if CONFIG_CODE_ZEROGROUP
+ vp9_copy(cc->zpc_probs_4x4, cm->fc.zpc_probs_4x4);
+ vp9_copy(cc->zpc_probs_8x8, cm->fc.zpc_probs_8x8);
+ vp9_copy(cc->zpc_probs_16x16, cm->fc.zpc_probs_16x16);
+ vp9_copy(cc->zpc_probs_32x32, cm->fc.zpc_probs_32x32);
+#endif
}
void vp9_restore_coding_context(VP9_COMP *cpi) {
@@ -242,6 +248,12 @@ void vp9_restore_coding_context(VP9_COMP *cpi) {
vp9_copy(cm->fc.nzc_probs_32x32, cc->nzc_probs_32x32);
vp9_copy(cm->fc.nzc_pcat_probs, cc->nzc_pcat_probs);
#endif
+#if CONFIG_CODE_ZEROGROUP
+ vp9_copy(cm->fc.zpc_probs_4x4, cc->zpc_probs_4x4);
+ vp9_copy(cm->fc.zpc_probs_8x8, cc->zpc_probs_8x8);
+ vp9_copy(cm->fc.zpc_probs_16x16, cc->zpc_probs_16x16);
+ vp9_copy(cm->fc.zpc_probs_32x32, cc->zpc_probs_32x32);
+#endif
}
void vp9_setup_key_frame(VP9_COMP *cpi) {
diff --git a/vp9/encoder/vp9_rdopt.c b/vp9/encoder/vp9_rdopt.c
index 0f6d7132f..c3cf31818 100644
--- a/vp9/encoder/vp9_rdopt.c
+++ b/vp9/encoder/vp9_rdopt.c
@@ -374,18 +374,32 @@ static INLINE int cost_coeffs(VP9_COMMON *const cm, MACROBLOCK *mb,
sizeof(ENTROPY_CONTEXT_PLANES)/sizeof(ENTROPY_CONTEXT);
ENTROPY_CONTEXT *const l1 = l +
sizeof(ENTROPY_CONTEXT_PLANES)/sizeof(ENTROPY_CONTEXT);
+ TX_TYPE tx_type = DCT_DCT;
#if CONFIG_CODE_NONZEROCOUNT
const int nzc_used = get_nzc_used(tx_size);
int nzc_context = vp9_get_nzc_context(cm, xd, ib);
unsigned int *nzc_cost;
#endif
+#if CONFIG_CODE_ZEROGROUP
+ int last_nz_pos[3] = {-1, -1, -1}; // Encoder only
+ int is_eoo_list[3] = {0, 0, 0};
+ int is_eoo_negative[3] = {0, 0, 0};
+ int is_last_zero[3] = {0, 0, 0};
+ int o, rc, skip_coef_val;
+ vp9_zpc_probs *zpc_probs;
+ uint8_t token_cache_full[1024];
+#endif
const int segment_id = xd->mode_info_context->mbmi.segment_id;
vp9_prob (*coef_probs)[REF_TYPES][COEF_BANDS][PREV_COEF_CONTEXTS]
[ENTROPY_NODES];
int seg_eob, default_eob;
uint8_t token_cache[1024];
+#if CONFIG_CODE_ZEROGROUP
+ vpx_memset(token_cache, UNKNOWN_TOKEN, sizeof(token_cache));
+#endif
+
// Check for consistency of tx_size with mode info
assert((!type && !pb_idx.plane) || (type && pb_idx.plane));
if (type == PLANE_TYPE_Y_WITH_DC) {
@@ -397,8 +411,8 @@ static INLINE int cost_coeffs(VP9_COMMON *const cm, MACROBLOCK *mb,
switch (tx_size) {
case TX_4X4: {
- const TX_TYPE tx_type = (type == PLANE_TYPE_Y_WITH_DC) ?
- get_tx_type_4x4(xd, ib) : DCT_DCT;
+ tx_type = (type == PLANE_TYPE_Y_WITH_DC) ?
+ get_tx_type_4x4(xd, ib) : DCT_DCT;
a_ec = *a;
l_ec = *l;
#if CONFIG_CODE_NONZEROCOUNT
@@ -413,14 +427,17 @@ static INLINE int cost_coeffs(VP9_COMMON *const cm, MACROBLOCK *mb,
} else {
scan = vp9_default_zig_zag1d_4x4;
}
+#if CONFIG_CODE_ZEROGROUP
+ zpc_probs = &cm->fc.zpc_probs_4x4;
+#endif
break;
}
case TX_8X8: {
const BLOCK_SIZE_TYPE sb_type = xd->mode_info_context->mbmi.sb_type;
const int sz = 3 + mb_width_log2(sb_type);
const int x = ib & ((1 << sz) - 1), y = ib - x;
- const TX_TYPE tx_type = (type == PLANE_TYPE_Y_WITH_DC) ?
- get_tx_type_8x8(xd, y + (x >> 1)) : DCT_DCT;
+ TX_TYPE tx_type = (type == PLANE_TYPE_Y_WITH_DC) ?
+ get_tx_type_8x8(xd, y + (x >> 1)) : DCT_DCT;
a_ec = (a[0] + a[1]) != 0;
l_ec = (l[0] + l[1]) != 0;
if (tx_type == ADST_DCT) {
@@ -435,14 +452,17 @@ static INLINE int cost_coeffs(VP9_COMMON *const cm, MACROBLOCK *mb,
#endif
coef_probs = cm->fc.coef_probs_8x8;
seg_eob = 64;
+#if CONFIG_CODE_ZEROGROUP
+ zpc_probs = &cm->fc.zpc_probs_8x8;
+#endif
break;
}
case TX_16X16: {
const BLOCK_SIZE_TYPE sb_type = xd->mode_info_context->mbmi.sb_type;
const int sz = 4 + mb_width_log2(sb_type);
const int x = ib & ((1 << sz) - 1), y = ib - x;
- const TX_TYPE tx_type = (type == PLANE_TYPE_Y_WITH_DC) ?
- get_tx_type_16x16(xd, y + (x >> 2)) : DCT_DCT;
+ TX_TYPE tx_type = (type == PLANE_TYPE_Y_WITH_DC) ?
+ get_tx_type_16x16(xd, y + (x >> 2)) : DCT_DCT;
if (tx_type == ADST_DCT) {
scan = vp9_row_scan_16x16;
} else if (tx_type == DCT_ADST) {
@@ -462,6 +482,9 @@ static INLINE int cost_coeffs(VP9_COMMON *const cm, MACROBLOCK *mb,
a_ec = (a[0] + a[1] + a[2] + a[3]) != 0;
l_ec = (l[0] + l[1] + l[2] + l[3]) != 0;
}
+#if CONFIG_CODE_ZEROGROUP
+ zpc_probs = &cm->fc.zpc_probs_16x16;
+#endif
break;
}
case TX_32X32:
@@ -487,6 +510,9 @@ static INLINE int cost_coeffs(VP9_COMMON *const cm, MACROBLOCK *mb,
l_ec = (l[0] + l[1] + l[2] + l[3] +
l1[0] + l1[1] + l1[2] + l1[3]) != 0;
}
+#if CONFIG_CODE_ZEROGROUP
+ zpc_probs = &cm->fc.zpc_probs_32x32;
+#endif
break;
default:
abort();
@@ -508,36 +534,116 @@ static INLINE int cost_coeffs(VP9_COMMON *const cm, MACROBLOCK *mb,
if (eob < seg_eob)
assert(qcoeff_ptr[scan[eob]] == 0);
+#if CONFIG_CODE_ZEROGROUP
+ vpx_memset(token_cache_full, ZERO_TOKEN, sizeof(token_cache_full));
+ for (c = 0; c < eob; ++c) {
+ rc = scan[c];
+ token_cache_full[rc] = vp9_dct_value_tokens_ptr[qcoeff_ptr[rc]].token;
+ o = vp9_get_orientation(rc, tx_size);
+ if (qcoeff_ptr[rc] != 0)
+ last_nz_pos[o] = c;
+ }
+#endif
{
#if CONFIG_CODE_NONZEROCOUNT
int nzc = 0;
#endif
- for (; c < eob; c++) {
+ for (c = 0; c < eob; c++) {
int v = qcoeff_ptr[scan[c]];
int t = vp9_dct_value_tokens_ptr[v].token;
+ int band = get_coef_band(scan, tx_size, c);
#if CONFIG_CODE_NONZEROCOUNT
nzc += (v != 0);
#endif
- token_cache[c] = t;
- cost += token_costs[get_coef_band(scan, tx_size, c)][pt][t];
- cost += vp9_dct_value_cost_ptr[v];
-#if !CONFIG_CODE_NONZEROCOUNT
- if (!c || token_cache[c - 1])
- cost += vp9_cost_bit(coef_probs[type][ref]
- [get_coef_band(scan, tx_size, c)]
- [pt][0], 1);
+ if (c)
+ pt = vp9_get_coef_context(scan, nb, pad, token_cache, c, default_eob);
+#if CONFIG_CODE_ZEROGROUP
+ rc = scan[c];
+ o = vp9_get_orientation(rc, tx_size);
+ skip_coef_val = (token_cache[rc] == ZERO_TOKEN || is_eoo_list[o]);
+ if (!skip_coef_val) {
+ cost += token_costs[band][pt][t] + vp9_dct_value_cost_ptr[v];
+ } else {
+ assert(v == 0);
+ }
+#else
+ cost += token_costs[band][pt][t] + vp9_dct_value_cost_ptr[v];
+#endif
+#if CONFIG_CODE_NONZEROCOUNT
+ if (!nzc_used)
+#endif
+ if (!c || token_cache[scan[c - 1]])
+ cost += vp9_cost_bit(coef_probs[type][ref][band][pt][0], 1);
+ token_cache[scan[c]] = t;
+#if CONFIG_CODE_ZEROGROUP
+ if (t == ZERO_TOKEN && !skip_coef_val) {
+ int eoo = 0, use_eoo;
+#if USE_ZPC_EOORIENT == 1
+ use_eoo = vp9_use_eoo(c, seg_eob, scan, tx_size,
+ is_last_zero, is_eoo_list);
+#else
+ use_eoo = 0;
+#endif
+ if (use_eoo) {
+ eoo = vp9_is_eoo(c, eob, scan, tx_size, qcoeff_ptr, last_nz_pos);
+ if (eoo && is_eoo_negative[o]) eoo = 0;
+ if (eoo) {
+ int c_;
+ int savings = 0;
+ int zsaved = 0;
+ savings = vp9_cost_bit((*zpc_probs)[ref]
+ [coef_to_zpc_band(band)]
+ [coef_to_zpc_ptok(pt)][0], 1) -
+ vp9_cost_bit((*zpc_probs)[ref]
+ [coef_to_zpc_band(band)]
+ [coef_to_zpc_ptok(pt)][0], 0);
+ for (c_ = c + 1; c_ < eob; ++c_) {
+ if (o == vp9_get_orientation(scan[c_], tx_size)) {
+ int pt_ = vp9_get_coef_context(scan, nb, pad,
+ token_cache_full, c_,
+ default_eob);
+ int band_ = get_coef_band(scan, tx_size, c_);
+ assert(token_cache_full[scan[c_]] == ZERO_TOKEN);
+ if (!c_ || token_cache_full[scan[c_ - 1]])
+ savings += vp9_cost_bit(
+ coef_probs[type][ref][band_][pt_][0], 1);
+ savings += vp9_cost_bit(
+ coef_probs[type][ref][band_][pt_][1], 0);
+ zsaved++;
+ }
+ }
+ if (savings < 0) {
+ // if (zsaved < ZPC_ZEROSSAVED_EOO) {
+ eoo = 0;
+ is_eoo_negative[o] = 1;
+ }
+ }
+ }
+ if (use_eoo) {
+ cost += vp9_cost_bit((*zpc_probs)[ref]
+ [coef_to_zpc_band(band)]
+ [coef_to_zpc_ptok(pt)][0], !eoo);
+ if (eoo) {
+ assert(is_eoo_list[o] == 0);
+ is_eoo_list[o] = 1;
+ }
+ }
+ }
+ is_last_zero[o] = (t == ZERO_TOKEN);
#endif
- pt = vp9_get_coef_context(scan, nb, pad, token_cache, c + 1, default_eob);
}
#if CONFIG_CODE_NONZEROCOUNT
if (nzc_used)
cost += nzc_cost[nzc];
else
#endif
- if (c < seg_eob)
+ if (c < seg_eob) {
+ if (c)
+ pt = vp9_get_coef_context(scan, nb, pad, token_cache, c, default_eob);
cost += mb->token_costs[tx_size][type][ref]
[get_coef_band(scan, tx_size, c)]
[pt][DCT_EOB_TOKEN];
+ }
}
// is eob first coefficient;
diff --git a/vp9/encoder/vp9_tokenize.c b/vp9/encoder/vp9_tokenize.c
index 398b4bbe6..dd9efe6db 100644
--- a/vp9/encoder/vp9_tokenize.c
+++ b/vp9/encoder/vp9_tokenize.c
@@ -121,7 +121,7 @@ static void tokenize_b(VP9_COMP *cpi,
int dry_run) {
MB_MODE_INFO *mbmi = &xd->mode_info_context->mbmi;
int pt; /* near block/prev token context index */
- int c = 0;
+ int c = 0, rc = 0;
TOKENEXTRA *t = *tp; /* store tokens starting here */
const struct plane_block_idx pb_idx = plane_block_idx(y_blocks, ib);
const int eob = xd->plane[pb_idx.plane].eobs[pb_idx.block];
@@ -132,16 +132,30 @@ static void tokenize_b(VP9_COMP *cpi,
const BLOCK_SIZE_TYPE sb_type = mbmi->sb_type;
const int *scan, *nb;
vp9_coeff_count *counts;
- vp9_coeff_probs *probs;
+ vp9_coeff_probs *coef_probs;
const int ref = mbmi->ref_frame != INTRA_FRAME;
ENTROPY_CONTEXT *a, *l, *a1, *l1, *a2, *l2, *a3, *l3, a_ec, l_ec;
uint8_t token_cache[1024];
+ TX_TYPE tx_type = DCT_DCT;
+#if CONFIG_CODE_ZEROGROUP
+ int last_nz_pos[3] = {-1, -1, -1}; // Encoder only
+ int is_eoo_list[3] = {0, 0, 0};
+ int is_last_zero[3] = {0, 0, 0};
+ int is_eoo_negative[3] = {0, 0, 0};
+ int o;
+ vp9_zpc_probs *zpc_probs;
+ vp9_zpc_count *zpc_count;
+ uint8_t token_cache_full[1024];
+#endif
#if CONFIG_CODE_NONZEROCOUNT
const int nzc_used = get_nzc_used(tx_size);
int zerosleft = 0, nzc = 0;
if (eob == 0)
assert(xd->nzcs[ib] == 0);
#endif
+#if CONFIG_CODE_ZEROGROUP
+ vpx_memset(token_cache, UNKNOWN_TOKEN, sizeof(token_cache));
+#endif
assert((!type && !pb_idx.plane) || (type && pb_idx.plane));
if (sb_type == BLOCK_SIZE_SB64X64) {
@@ -206,8 +220,8 @@ static void tokenize_b(VP9_COMP *cpi,
switch (tx_size) {
default:
case TX_4X4: {
- const TX_TYPE tx_type = (type == PLANE_TYPE_Y_WITH_DC) ?
- get_tx_type_4x4(xd, ib) : DCT_DCT;
+ tx_type = (type == PLANE_TYPE_Y_WITH_DC) ?
+ get_tx_type_4x4(xd, ib) : DCT_DCT;
a_ec = *a;
l_ec = *l;
seg_eob = 16;
@@ -220,14 +234,18 @@ static void tokenize_b(VP9_COMP *cpi,
}
}
counts = cpi->coef_counts_4x4;
- probs = cpi->common.fc.coef_probs_4x4;
+ coef_probs = cpi->common.fc.coef_probs_4x4;
+#if CONFIG_CODE_ZEROGROUP
+ zpc_count = &cpi->common.fc.zpc_counts_4x4;
+ zpc_probs = &cpi->common.fc.zpc_probs_4x4;
+#endif
break;
}
case TX_8X8: {
const int sz = 3 + mb_width_log2(sb_type);
const int x = ib & ((1 << sz) - 1), y = ib - x;
- const TX_TYPE tx_type = (type == PLANE_TYPE_Y_WITH_DC) ?
- get_tx_type_8x8(xd, y + (x >> 1)) : DCT_DCT;
+ tx_type = (type == PLANE_TYPE_Y_WITH_DC) ?
+ get_tx_type_8x8(xd, y + (x >> 1)) : DCT_DCT;
a_ec = (a[0] + a[1]) != 0;
l_ec = (l[0] + l[1]) != 0;
seg_eob = 64;
@@ -240,14 +258,18 @@ static void tokenize_b(VP9_COMP *cpi,
}
}
counts = cpi->coef_counts_8x8;
- probs = cpi->common.fc.coef_probs_8x8;
+ coef_probs = cpi->common.fc.coef_probs_8x8;
+#if CONFIG_CODE_ZEROGROUP
+ zpc_count = &cpi->common.fc.zpc_counts_8x8;
+ zpc_probs = &cpi->common.fc.zpc_probs_8x8;
+#endif
break;
}
case TX_16X16: {
const int sz = 4 + mb_width_log2(sb_type);
const int x = ib & ((1 << sz) - 1), y = ib - x;
- const TX_TYPE tx_type = (type == PLANE_TYPE_Y_WITH_DC) ?
- get_tx_type_16x16(xd, y + (x >> 2)) : DCT_DCT;
+ tx_type = (type == PLANE_TYPE_Y_WITH_DC) ?
+ get_tx_type_16x16(xd, y + (x >> 2)) : DCT_DCT;
if (type != PLANE_TYPE_UV) {
a_ec = (a[0] + a[1] + a[2] + a[3]) != 0;
l_ec = (l[0] + l[1] + l[2] + l[3]) != 0;
@@ -265,7 +287,11 @@ static void tokenize_b(VP9_COMP *cpi,
}
}
counts = cpi->coef_counts_16x16;
- probs = cpi->common.fc.coef_probs_16x16;
+ coef_probs = cpi->common.fc.coef_probs_16x16;
+#if CONFIG_CODE_ZEROGROUP
+ zpc_count = &cpi->common.fc.zpc_counts_16x16;
+ zpc_probs = &cpi->common.fc.zpc_probs_16x16;
+#endif
break;
}
case TX_32X32:
@@ -283,7 +309,11 @@ static void tokenize_b(VP9_COMP *cpi,
seg_eob = 1024;
scan = vp9_default_zig_zag1d_32x32;
counts = cpi->coef_counts_32x32;
- probs = cpi->common.fc.coef_probs_32x32;
+ coef_probs = cpi->common.fc.coef_probs_32x32;
+#if CONFIG_CODE_ZEROGROUP
+ zpc_count = &cpi->common.fc.zpc_counts_32x32;
+ zpc_probs = &cpi->common.fc.zpc_probs_32x32;
+#endif
break;
}
@@ -294,16 +324,30 @@ static void tokenize_b(VP9_COMP *cpi,
if (vp9_segfeature_active(xd, segment_id, SEG_LVL_SKIP))
seg_eob = 0;
+#if CONFIG_CODE_ZEROGROUP
+ vpx_memset(token_cache_full, ZERO_TOKEN, sizeof(token_cache_full));
+ for (c = 0; c < eob; ++c) {
+ rc = scan[c];
+ token_cache_full[rc] = vp9_dct_value_tokens_ptr[qcoeff_ptr[rc]].token;
+ o = vp9_get_orientation(rc, tx_size);
+ if (qcoeff_ptr[rc] != 0) {
+ last_nz_pos[o] = c;
+ }
+ }
+#endif
+ c = 0;
do {
const int band = get_coef_band(scan, tx_size, c);
int token;
int v = 0;
+ rc = scan[c];
+ if (c)
+ pt = vp9_get_coef_context(scan, nb, pad, token_cache, c, default_eob);
#if CONFIG_CODE_NONZEROCOUNT
if (nzc_used)
zerosleft = seg_eob - xd->nzcs[ib] - c + nzc;
#endif
if (c < eob) {
- const int rc = scan[c];
v = qcoeff_ptr[rc];
assert(-DCT_MAX_VALUE <= v && v < DCT_MAX_VALUE);
@@ -319,15 +363,29 @@ static void tokenize_b(VP9_COMP *cpi,
}
t->token = token;
- t->context_tree = probs[type][ref][band][pt];
+ t->context_tree = coef_probs[type][ref][band][pt];
#if CONFIG_CODE_NONZEROCOUNT
// Skip zero node if there are no zeros left
if (nzc_used)
t->skip_eob_node = 1 + (zerosleft == 0);
else
#endif
- t->skip_eob_node = (c > 0) && (token_cache[c - 1] == 0);
+ t->skip_eob_node = (c > 0) && (token_cache[scan[c - 1]] == 0);
assert(vp9_coef_encodings[t->token].len - t->skip_eob_node > 0);
+#if CONFIG_CODE_ZEROGROUP
+ o = vp9_get_orientation(rc, tx_size);
+ t->skip_coef_val = (token_cache[rc] == ZERO_TOKEN || is_eoo_list[o]);
+ if (t->skip_coef_val) {
+ assert(v == 0);
+ }
+ // No need to transmit any token
+ if (t->skip_eob_node && t->skip_coef_val) {
+ assert(token == ZERO_TOKEN);
+ is_last_zero[o] = 1;
+ token_cache[scan[c]] = ZERO_TOKEN;
+ continue;
+ }
+#endif
if (!dry_run) {
++counts[type][ref][band][pt][token];
if (!t->skip_eob_node)
@@ -336,13 +394,79 @@ static void tokenize_b(VP9_COMP *cpi,
#if CONFIG_CODE_NONZEROCOUNT
nzc += (v != 0);
#endif
- token_cache[c] = token;
-
- pt = vp9_get_coef_context(scan, nb, pad, token_cache, c + 1, default_eob);
+ token_cache[scan[c]] = token;
+#if CONFIG_CODE_ZEROGROUP
+ if (token == ZERO_TOKEN && !t->skip_coef_val) {
+ int eoo = 0, use_eoo;
+#if USE_ZPC_EOORIENT == 1
+ use_eoo = vp9_use_eoo(c, seg_eob, scan, tx_size,
+ is_last_zero, is_eoo_list);
+#else
+ use_eoo = 0;
+#endif
+ if (use_eoo) {
+ eoo = vp9_is_eoo(c, eob, scan, tx_size, qcoeff_ptr, last_nz_pos);
+ if (eoo && is_eoo_negative[o]) eoo = 0;
+ if (eoo) {
+ int c_;
+ int savings = 0;
+ int zsaved = 0;
+ savings =
+ vp9_cost_bit((*zpc_probs)[ref]
+ [coef_to_zpc_band(band)]
+ [coef_to_zpc_ptok(pt)][0], 1) -
+ vp9_cost_bit((*zpc_probs)[ref]
+ [coef_to_zpc_band(band)]
+ [coef_to_zpc_ptok(pt)][0], 0);
+ for (c_ = c + 1; c_ < eob; ++c_) {
+ if (o == vp9_get_orientation(scan[c_], tx_size)) {
+ int pt_ = vp9_get_coef_context(scan, nb, pad, token_cache_full,
+ c_, default_eob);
+ int band_ = get_coef_band(scan, tx_size, c_);
+ assert(token_cache_full[scan[c_]] == ZERO_TOKEN);
+ if (!c_ || token_cache_full[scan[c_ - 1]])
+ savings +=
+ vp9_cost_bit(coef_probs[type][ref][band_][pt_][0], 1);
+ savings += vp9_cost_bit(coef_probs[type][ref][band_][pt_][1], 0);
+ zsaved++;
+ }
+ }
+ /*
+ if (!dry_run)
+ if (savings > 0)
+ printf("savings %d zsaved %d (%d, %d)\n",
+ savings, zsaved, tx_size, band);
+ */
+ if (savings < 0) {
+ eoo = 0;
+ is_eoo_negative[o] = 1;
+ }
+ }
+ }
+ if (use_eoo) {
+ t++;
+ t->skip_eob_node = t->skip_coef_val = 0;
+ // transmit the eoo symbol
+ t->token = !eoo ? ZPC_ISOLATED : ZPC_EOORIENT;
+ t->context_tree = &((*zpc_probs)[ref]
+ [coef_to_zpc_band(band)]
+ [coef_to_zpc_ptok(pt)][0]);
+ if (!dry_run)
+ (*zpc_count)[ref]
+ [coef_to_zpc_band(band)]
+ [coef_to_zpc_ptok(pt)][0][!eoo]++;
+ if (eoo) {
+ assert(is_eoo_list[o] == 0);
+ is_eoo_list[o] = 1;
+ }
+ }
+ }
+ is_last_zero[o] = (token == ZERO_TOKEN);
+#endif
++t;
- } while (c < eob && ++c < seg_eob);
+} while (c < eob && ++c < seg_eob);
#if CONFIG_CODE_NONZEROCOUNT
- assert(nzc == xd->nzcs[ib]);
+assert(nzc == xd->nzcs[ib]);
#endif
*tp = t;
@@ -812,6 +936,9 @@ static void stuff_b(VP9_COMP *cpi,
t->token = DCT_EOB_TOKEN;
t->context_tree = probs[type][ref][band][pt];
t->skip_eob_node = 0;
+#if CONFIG_CODE_ZEROGROUP
+ t->skip_coef_val = 0;
+#endif
++t;
*tp = t;
if (!dry_run) {
diff --git a/vp9/encoder/vp9_tokenize.h b/vp9/encoder/vp9_tokenize.h
index 82d798e47..da1c817a2 100644
--- a/vp9/encoder/vp9_tokenize.h
+++ b/vp9/encoder/vp9_tokenize.h
@@ -26,6 +26,9 @@ typedef struct {
int16_t extra;
uint8_t token;
uint8_t skip_eob_node;
+#if CONFIG_CODE_ZEROGROUP
+ uint8_t skip_coef_val;
+#endif
} TOKENEXTRA;
typedef int64_t vp9_coeff_accum[REF_TYPES][COEF_BANDS][PREV_COEF_CONTEXTS]