Rework base range entropy coding in level map system
Replace the truncated geometric distribution model with the grouped
leaves structure for more efficient probability modeling.
Each group has its own Geometric distribution
This give us 0.2% gain on lowres
Change-Id: If5c73dd429bd5183a8aa81042f8f56937b1d8a6a
diff --git a/av1/encoder/block.h b/av1/encoder/block.h
index 94c2bda..451f3be 100644
--- a/av1/encoder/block.h
+++ b/av1/encoder/block.h
@@ -75,6 +75,9 @@
int dc_sign_cost[DC_SIGN_CONTEXTS][2];
int base_cost[NUM_BASE_LEVELS][COEFF_BASE_CONTEXTS][2];
int lps_cost[LEVEL_CONTEXTS][2];
+#if BR_NODE
+ int br_cost[BASE_RANGE_SETS][LEVEL_CONTEXTS][2];
+#endif
} LV_MAP_COEFF_COST;
typedef struct {
diff --git a/av1/encoder/encodetxb.c b/av1/encoder/encodetxb.c
index 1012668..df25c7e 100644
--- a/av1/encoder/encodetxb.c
+++ b/av1/encoder/encodetxb.c
@@ -231,6 +231,41 @@
// level is above 1.
ctx = get_br_ctx(tcoeff, scan[c], bwl, height);
+
+#if BR_NODE
+ int base_range = level - 1 - NUM_BASE_LEVELS;
+ int br_set_idx = 0;
+ int br_base = 0;
+ int br_offset = 0;
+
+ if (base_range >= COEFF_BASE_RANGE)
+ br_set_idx = BASE_RANGE_SETS;
+ else
+ br_set_idx = coeff_to_br_index[base_range];
+
+ for (idx = 0; idx < BASE_RANGE_SETS; ++idx) {
+ aom_write_symbol(w, idx == br_set_idx,
+ cm->fc->coeff_br_cdf[txs_ctx][plane_type][idx][ctx], 2);
+ if (idx == br_set_idx) {
+ br_base = br_index_to_coeff[br_set_idx];
+ br_offset = base_range - br_base;
+ int extra_bits = (1 << br_extra_bits[idx]) - 1;
+ for (int tok = 0; tok < extra_bits; ++tok) {
+ if (tok == br_offset) {
+ aom_write_symbol(
+ w, 1, cm->fc->coeff_lps_cdf[txs_ctx][plane_type][ctx], 2);
+ break;
+ }
+ aom_write_symbol(w, 0,
+ cm->fc->coeff_lps_cdf[txs_ctx][plane_type][ctx], 2);
+ }
+ // aom_write_literal(w, br_offset, br_extra_bits[idx]);
+ break;
+ }
+ }
+
+ if (br_set_idx < BASE_RANGE_SETS) continue;
+#else // BR_NODE
for (idx = 0; idx < COEFF_BASE_RANGE; ++idx) {
if (level == (idx + 1 + NUM_BASE_LEVELS)) {
#if LV_MAP_PROB
@@ -249,6 +284,7 @@
#endif
}
if (idx < COEFF_BASE_RANGE) continue;
+#endif // BR_NODE
// use 0-th order Golomb code to handle the residual level.
write_golomb(w, level - COEFF_BASE_RANGE - 1 - NUM_BASE_LEVELS);
@@ -428,9 +464,35 @@
if (level > NUM_BASE_LEVELS) {
int idx;
int ctx;
-
ctx = get_br_ctx(qcoeff, scan[c], bwl, height);
+#if BR_NODE
+ int base_range = level - 1 - NUM_BASE_LEVELS;
+ int br_set_idx = base_range < COEFF_BASE_RANGE
+ ? coeff_to_br_index[base_range]
+ : BASE_RANGE_SETS;
+ for (idx = 0; idx < BASE_RANGE_SETS; ++idx) {
+ if (br_set_idx == idx) {
+ int br_base = br_index_to_coeff[br_set_idx];
+ int br_offset = base_range - br_base;
+ int extra_bits = (1 << br_extra_bits[idx]) - 1;
+ cost += coeff_costs->br_cost[idx][ctx][1];
+ for (int tok = 0; tok < extra_bits; ++tok) {
+ if (tok == br_offset) {
+ cost += coeff_costs->lps_cost[ctx][1];
+ break;
+ }
+ cost += coeff_costs->lps_cost[ctx][0];
+ }
+ // cost += extra_bits * av1_cost_bit(128, 1);
+ break;
+ }
+ cost += coeff_costs->br_cost[idx][ctx][0];
+ }
+ if (idx < BASE_RANGE_SETS) continue;
+
+ idx = COEFF_BASE_RANGE;
+#else
for (idx = 0; idx < COEFF_BASE_RANGE; ++idx) {
if (level == (idx + 1 + NUM_BASE_LEVELS)) {
cost += coeff_costs->lps_cost[ctx][1];
@@ -438,7 +500,7 @@
}
cost += coeff_costs->lps_cost[ctx][0];
}
-
+#endif
if (idx >= COEFF_BASE_RANGE) {
// residual cost
int r = level - COEFF_BASE_RANGE - NUM_BASE_LEVELS;
@@ -1681,6 +1743,45 @@
// level is above 1.
ctx = get_br_ctx(tcoeff, scan[c], bwl, height);
+
+#if BR_NODE
+ int base_range = level - 1 - NUM_BASE_LEVELS;
+ int br_set_idx = base_range < COEFF_BASE_RANGE
+ ? coeff_to_br_index[base_range]
+ : BASE_RANGE_SETS;
+
+ for (idx = 0; idx < BASE_RANGE_SETS; ++idx) {
+ if (idx == br_set_idx) {
+ int br_base = br_index_to_coeff[br_set_idx];
+ int br_offset = base_range - br_base;
+ ++td->counts->coeff_br[txsize_ctx][plane_type][idx][ctx][1];
+#if LV_MAP_PROB
+ update_cdf(ec_ctx->coeff_br_cdf[txsize_ctx][plane_type][idx][ctx], 1,
+ 2);
+#endif
+ int extra_bits = (1 << br_extra_bits[idx]) - 1;
+ for (int tok = 0; tok < extra_bits; ++tok) {
+ if (br_offset == tok) {
+ ++td->counts->coeff_lps[txsize_ctx][plane_type][ctx][1];
+#if LV_MAP_PROB
+ update_cdf(ec_ctx->coeff_lps_cdf[txsize_ctx][plane_type][ctx], 1,
+ 2);
+#endif
+ break;
+ }
+ ++td->counts->coeff_lps[txsize_ctx][plane_type][ctx][0];
+#if LV_MAP_PROB
+ update_cdf(ec_ctx->coeff_lps_cdf[txsize_ctx][plane_type][ctx], 0, 2);
+#endif
+ }
+ break;
+ }
+ ++td->counts->coeff_br[txsize_ctx][plane_type][idx][ctx][0];
+#if LV_MAP_PROB
+ update_cdf(ec_ctx->coeff_br_cdf[txsize_ctx][plane_type][idx][ctx], 0, 2);
+#endif
+ }
+#else // BR_NODE
for (idx = 0; idx < COEFF_BASE_RANGE; ++idx) {
if (level == (idx + 1 + NUM_BASE_LEVELS)) {
++td->counts->coeff_lps[txsize_ctx][plane_type][ctx][1];
@@ -1695,7 +1796,7 @@
#endif
}
if (idx < COEFF_BASE_RANGE) continue;
-
+#endif // BR_NODE
// use 0-th order Golomb code to handle the residual level.
}
diff --git a/av1/encoder/encodetxb.h b/av1/encoder/encodetxb.h
index acca0ea..16a1b93 100644
--- a/av1/encoder/encodetxb.h
+++ b/av1/encoder/encodetxb.h
@@ -64,6 +64,9 @@
const aom_prob *coeff_lps;
const aom_prob *eob_flag;
const aom_prob *txb_skip;
+#if BR_NODE
+ const aom_prob *coeff_br;
+#endif
} TxbProbs;
void av1_alloc_txb_buf(AV1_COMP *cpi);
diff --git a/av1/encoder/rd.c b/av1/encoder/rd.c
index 038fe33..a37eb4d 100644
--- a/av1/encoder/rd.c
+++ b/av1/encoder/rd.c
@@ -500,10 +500,18 @@
pcost->base_cost[layer][ctx],
fc->coeff_base_cdf[tx_size][plane][layer][ctx], NULL);
+#if BR_NODE
+ for (int br = 0; br < BASE_RANGE_SETS; ++br)
+ for (int ctx = 0; ctx < LEVEL_CONTEXTS; ++ctx)
+ av1_cost_tokens_from_cdf(pcost->br_cost[br][ctx],
+ fc->coeff_br_cdf[tx_size][plane][br][ctx],
+ NULL);
+#endif // BR_NODE
+
for (int ctx = 0; ctx < LEVEL_CONTEXTS; ++ctx)
av1_cost_tokens_from_cdf(pcost->lps_cost[ctx],
fc->coeff_lps_cdf[tx_size][plane][ctx], NULL);
-#else
+#else // LV_MAP_PROB
for (int ctx = 0; ctx < TXB_SKIP_CONTEXTS; ++ctx)
get_rate_cost(fc->txb_skip[tx_size][ctx], pcost->txb_skip_cost[ctx]);
@@ -523,11 +531,11 @@
for (int ctx = 0; ctx < LEVEL_CONTEXTS; ++ctx)
get_rate_cost(fc->coeff_lps[tx_size][plane][ctx], pcost->lps_cost[ctx]);
-#endif
+#endif // LV_MAP_PROB
}
}
}
-#endif
+#endif // CONFIG_LV_MAP
void av1_fill_token_costs_from_cdf(av1_coeff_cost *cost,
coeff_cdf_model (*cdf)[PLANE_TYPES]) {