Commit fdbcf1ffa4 for aom
commit fdbcf1ffa4b37b23c5df29022e59d967a2177962
Author: Frank Galligan <fgalligan@google.com>
Date: Fri Nov 6 11:47:16 2026 -0800
av1: Optimize av1_cost_symbol and txb context
Improve entropy costing and AC transform block context lookups:
- Replace get_prob(p15 << shift, CDF_PROB_TOP) - 128 in av1_cost_symbol
with a direct shift-and-clamp index calculation.
- Add get_lower_levels_ctx_simple for non-DC AC coefficients
(coeff_idx > 0), preserving the 5-neighbor zero shortcut while
skipping coeff_idx == 0 checks and dispatching on tx_class once.
Benchmarking results (incremental vs prev CL / cumulative vs baseline):
- Stock avifenc still-image (Default 1T): -2.04% / -18.42% encode time
- Stock avifenc still-image (Default 8T): -0.13% / -14.14% encode time
- 48-image multi-rate corpus (Full Suite 1T): -1.45% / -18.33% time
- Bit-exact output (1T and 8T)
TAG=agy
CONV=b929a630-a6cd-45a0-979c-1767c30178ee
Change-Id: I9cc3fd30af508ebcca6225404a9aad51bcd4eff2
diff --git a/av1/common/txb_common.h b/av1/common/txb_common.h
index 7b3ee8c431..d4e3fc8a7c 100644
--- a/av1/common/txb_common.h
+++ b/av1/common/txb_common.h
@@ -282,6 +282,43 @@ static AOM_FORCE_INLINE int get_lower_levels_ctx(const uint8_t *levels,
return get_nz_map_ctx_from_stats(stats, coeff_idx, bhl, tx_size, tx_class);
}
+// Specialized variant for AC coefficients (coeff_idx > 0), skipping the
+// redundant coeff_idx == 0 checks and dispatching on tx_class once.
+static AOM_FORCE_INLINE int get_lower_levels_ctx_simple(const uint8_t *levels,
+ int coeff_idx, int bhl,
+ TX_SIZE tx_size,
+ TX_CLASS tx_class) {
+ assert(coeff_idx > 0);
+ assert(bhl >= MIN_TX_SIZE_LOG2 && bhl <= MAX_TX_SIZE_LOG2 - 1);
+ const uint8_t *const nb = levels + get_padded_idx(coeff_idx, bhl);
+ const ptrdiff_t stride = (1 << bhl) + TX_PAD_HOR;
+ if (tx_class == TX_CLASS_2D) {
+ const int offset = av1_nz_map_ctx_offset[tx_size][coeff_idx];
+ if ((nb[1] | nb[2] | nb[stride] | nb[stride + 1] | nb[2 * stride]) == 0)
+ return offset;
+ const int mag = clip_max3[nb[stride]] + clip_max3[nb[1]] +
+ clip_max3[nb[stride + 1]] + clip_max3[nb[2 * stride]] +
+ clip_max3[nb[2]];
+ return offset + AOMMIN((mag + 1) >> 1, 4);
+ } else if (tx_class == TX_CLASS_VERT) {
+ const int offset = nz_map_ctx_offset_1d[coeff_idx & ((1 << bhl) - 1)];
+ if ((nb[stride] | nb[1] | nb[2] | nb[3] | nb[4]) == 0) return offset;
+ const int mag = clip_max3[nb[stride]] + clip_max3[nb[1]] +
+ clip_max3[nb[2]] + clip_max3[nb[3]] + clip_max3[nb[4]];
+ return offset + AOMMIN((mag + 1) >> 1, 4);
+ } else {
+ assert(tx_class == TX_CLASS_HORIZ);
+ const int offset = nz_map_ctx_offset_1d[coeff_idx >> bhl];
+ if ((nb[stride] | nb[1] | nb[2 * stride] | nb[3 * stride] |
+ nb[4 * stride]) == 0)
+ return offset;
+ const int mag = clip_max3[nb[stride]] + clip_max3[nb[1]] +
+ clip_max3[nb[2 * stride]] + clip_max3[nb[3 * stride]] +
+ clip_max3[nb[4 * stride]];
+ return offset + AOMMIN((mag + 1) >> 1, 4);
+ }
+}
+
static inline int get_lower_levels_ctx_general(int is_last, int scan_idx,
int bhl, int width,
const uint8_t *levels,
diff --git a/av1/encoder/cost.h b/av1/encoder/cost.h
index e51e6b8d0a..9ce4b1083d 100644
--- a/av1/encoder/cost.h
+++ b/av1/encoder/cost.h
@@ -36,9 +36,10 @@ static inline int av1_cost_symbol(aom_cdf_prob p15) {
p15 = (aom_cdf_prob)clamp(p15, 1, CDF_PROB_TOP - 1);
assert(0 < p15 && p15 < CDF_PROB_TOP);
const int shift = CDF_PROB_BITS - 1 - get_msb(p15);
- const int prob = get_prob(p15 << shift, CDF_PROB_TOP);
- assert(prob >= 128);
- return av1_prob_cost[prob - 128] + av1_cost_literal(shift);
+ // Since CDF_PROB_TOP == 32768, get_prob(p15 << shift, 32768) - 128 simplifies
+ // to min(((p15 << shift) - 16320) >> 7, 127).
+ const int prob_idx = AOMMIN(((p15 << shift) - 16320) >> 7, 127);
+ return av1_prob_cost[prob_idx] + av1_cost_literal(shift);
}
void av1_cost_tokens_from_cdf(int *costs, const aom_cdf_prob *cdf,
diff --git a/av1/encoder/txb_rdopt.c b/av1/encoder/txb_rdopt.c
index 2a866cb844..02f5615b50 100644
--- a/av1/encoder/txb_rdopt.c
+++ b/av1/encoder/txb_rdopt.c
@@ -101,7 +101,7 @@ static AOM_FORCE_INLINE int update_coeff_simple(
assert(ci > 0);
const tran_low_t qc = qcoeff[ci];
const int coeff_ctx =
- get_lower_levels_ctx(levels, ci, bhl, tx_size, tx_class);
+ get_lower_levels_ctx_simple(levels, ci, bhl, tx_size, tx_class);
if (qc == 0) {
return txb_costs->base_cost[coeff_ctx][0];
} else {