Commit c17672a3 authored by Paul Wilkins's avatar Paul Wilkins Committed by Ronald S. Bultje
Browse files

Further changes to coefficient contexts.

This patch alters the balance of context between the
coefficient bands (reflecting the position of coefficients
within a transform blocks) and the energy of the previous
token (or tokens) within a block.

In this case the number of coefficient bands is reduced
but more previous token energy bands are supported.

Some initial rebalancing of the default tables has been
by running multiple derf clips at multiple data rates using
the ENTOPY_STATS macro. Further balancing needs to be
done using larger image formatsd especially in regard to
the bigger transform sizes which are not as well represented
in encodings of smaller image formats.

Change-Id: If9736e95c391e711b04aef6393d26f60f36e1f8a
parent bf0570a7
This diff is collapsed.
......@@ -43,14 +43,18 @@ DECLARE_ALIGNED(16, const uint8_t, vp9_norm[256]) = {
// Unified coefficient band structure used by all block sizes
DECLARE_ALIGNED(16, const int, vp9_coef_bands[32]) = {
0, 1, 2, 3, 5, 4, 4, 5,
5, 3, 6, 6, 6, 6, 6, 7,
7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7
0, 1, 2, 3, 3, 3, 4, 4,
4, 4, 4, 4, 4, 4, 4, 5,
5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5
};
DECLARE_ALIGNED(16, const int, vp9_coef_bands4x4[16]) = {
0, 1, 2, 3, 3, 3, 4, 4,
4, 4, 5, 5, 5, 5, 5, 5
};
DECLARE_ALIGNED(16, const uint8_t, vp9_prev_token_class[MAX_ENTROPY_TOKENS]) = {
0, 1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 0
DECLARE_ALIGNED(16, const uint8_t, vp9_pt_energy_class[MAX_ENTROPY_TOKENS]) = {
0, 1, 2, 3, 3, 4, 4, 5, 5, 5, 5, 5
};
DECLARE_ALIGNED(16, const int, vp9_default_zig_zag1d_4x4[16]) = {
......@@ -231,17 +235,21 @@ int vp9_get_coef_context(int * recent_energy, int token) {
// int token_energy;
// int av_energy;
// Placeholder code for experiments with token energy
// as a coefficient context.
/*token_energy = ((token != DCT_EOB_TOKEN) ? token : 0);
if (token_energy) {
av_energy = (token_energy + *recent_energy + 1) >> 1;
if (!token_energy) {
if (!(*recent_energy)) {
av_energy = 0;
} else {
av_energy = 1;
}
} else {
av_energy = 0;
av_energy = ((token_energy + *recent_energy + 1) >> 1) + 1;
if (av_energy > DCT_VAL_CATEGORY6)
av_energy = DCT_VAL_CATEGORY6;
}
*recent_energy = token_energy;*/
return vp9_prev_token_class[token];
return vp9_pt_energy_class[token];
};
void vp9_default_coef_probs(VP9_COMMON *pc) {
......
......@@ -71,18 +71,16 @@ extern vp9_extra_bit_struct vp9_extra_bits[12]; /* indexed by token value */
#define BLOCK_TYPES_32X32 1
/* Middle dimension is a coarsening of the coefficient's
position within the 4x4 DCT. */
#define COEF_BANDS 8
/* Inside dimension is 3-valued measure of nearby complexity, that is,
the extent to which nearby coefficients are nonzero. For the first
coefficient (DC, unless block type is 0), we look at the (already encoded)
blocks above and to the left of the current block. The context index is
then the number (0,1,or 2) of these blocks having nonzero coefficients.
After decoding a coefficient, the measure is roughly the size of the
most recently decoded coefficient (0 for 0, 1 for 1, 2 for >1).
/* Middle dimension reflects the coefficient position within the transform. */
#define COEF_BANDS 6
/* Inside dimension is measure of nearby complexity, that reflects the energy
of nearby coefficients are nonzero. For the first coefficient (DC, unless
block type is 0), we look at the (already encoded) blocks above and to the
left of the current block. The context index is then the number (0,1,or 2)
of these blocks having nonzero coefficients.
After decoding a coefficient, the measure is determined by the size of the
most recently decoded coefficient.
Note that the intuitive meaning of this measure changes as coefficients
are decoded, e.g., prior to the first token, a zero means that my neighbors
are empty while, after the first token, because of the use of end-of-block,
......@@ -93,7 +91,7 @@ extern vp9_extra_bit_struct vp9_extra_bits[12]; /* indexed by token value */
distinct bands). */
/*# define DC_TOKEN_CONTEXTS 3*/ /* 00, 0!0, !0!0 */
#define PREV_COEF_CONTEXTS 4
#define PREV_COEF_CONTEXTS 6
typedef unsigned int vp9_coeff_count[COEF_BANDS][PREV_COEF_CONTEXTS]
[MAX_ENTROPY_TOKENS];
......@@ -126,11 +124,18 @@ static void vp9_reset_mb_tokens_context(MACROBLOCKD* const xd) {
}
extern const int vp9_coef_bands[32];
static int get_coef_band(int coef_index) {
if (coef_index < 32)
return vp9_coef_bands[coef_index];
else
return 7;
extern const int vp9_coef_bands4x4[16];
static int get_coef_band(TX_SIZE tx_size, int coef_index) {
if (tx_size == TX_4X4) {
return vp9_coef_bands4x4[coef_index];
} else {
if (coef_index < 32)
return vp9_coef_bands[coef_index];
else
return 5;
}
}
extern int vp9_get_coef_context(int * recent_energy, int token);
#endif // VP9_COMMON_VP9_ENTROPY_H_
......@@ -58,9 +58,18 @@ static INLINE vp9_prob clip_prob(int p) {
return (p > 255) ? 255u : (p < 1) ? 1u : p;
}
// int64 is not needed for normal frame level calculations.
// However when outputing entropy stats accumulated over many frames
// or even clips we can overflow int math.
#ifdef ENTROPY_STATS
static INLINE vp9_prob get_prob(int num, int den) {
return (den == 0) ? 128u : clip_prob(((int64_t)num * 256 + (den >> 1)) / den);
}
#else
static INLINE vp9_prob get_prob(int num, int den) {
return (den == 0) ? 128u : clip_prob((num * 256 + (den >> 1)) / den);
}
#endif
static INLINE vp9_prob get_binary_prob(int n0, int n1) {
return get_prob(n0, n0 + n1);
......
......@@ -65,7 +65,7 @@ static int get_signed(BOOL_DECODER *br, int value_to_sign) {
#define INCREMENT_COUNT(token) \
do { \
coef_counts[type][get_coef_band(c)][pt][token]++; \
coef_counts[type][get_coef_band(txfm_size, c)][pt][token]++; \
pt = vp9_get_coef_context(&recent_energy, token); \
} while (0)
......@@ -176,7 +176,7 @@ static int decode_coefs(VP9D_COMP *dx, const MACROBLOCKD *xd,
int val;
const uint8_t *cat6 = cat6_prob;
if (c >= seg_eob) break;
prob = coef_probs[type][get_coef_band(c)][pt];
prob = coef_probs[type][get_coef_band(txfm_size, c)][pt];
if (!vp9_read(br, prob[EOB_CONTEXT_NODE]))
break;
SKIP_START:
......@@ -184,7 +184,7 @@ SKIP_START:
if (!vp9_read(br, prob[ZERO_CONTEXT_NODE])) {
INCREMENT_COUNT(ZERO_TOKEN);
++c;
prob = coef_probs[type][get_coef_band(c)][pt];
prob = coef_probs[type][get_coef_band(txfm_size, c)][pt];
goto SKIP_START;
}
// ONE_CONTEXT_NODE_0_
......@@ -248,7 +248,7 @@ SKIP_START:
}
if (c < seg_eob)
coef_counts[type][get_coef_band(c)][pt][DCT_EOB_TOKEN]++;
coef_counts[type][get_coef_band(txfm_size, c)][pt][DCT_EOB_TOKEN]++;
A0[aidx] = L0[lidx] = (c > 0);
if (txfm_size >= TX_8X8) {
......
......@@ -1277,6 +1277,7 @@ static void update_coef_probs_common(vp9_writer* const bc,
const vp9_prob upd = COEF_UPDATE_PROB;
int s = prev_coef_savings[t];
int u = 0;
if (k >= 3 && j == 0)
continue;
#if defined(SEARCH_NEWP)
......
......@@ -415,7 +415,7 @@ static void optimize_b(MACROBLOCK *mb, int i, PLANE_TYPE type,
t0 = (vp9_dct_value_tokens_ptr + x)->Token;
/* Consider both possible successor states. */
if (next < default_eob) {
band = get_coef_band(i + 1);
band = get_coef_band(tx_size, i + 1);
pt = trellis_get_coeff_context(t0);
rate0 +=
mb->token_costs[tx_size][type][band][pt][tokens[next][0].token];
......@@ -462,7 +462,7 @@ static void optimize_b(MACROBLOCK *mb, int i, PLANE_TYPE type,
t0 = t1 = (vp9_dct_value_tokens_ptr + x)->Token;
}
if (next < default_eob) {
band = get_coef_band(i + 1);
band = get_coef_band(tx_size, i + 1);
if (t0 != DCT_EOB_TOKEN) {
pt = trellis_get_coeff_context(t0);
rate0 += mb->token_costs[tx_size][type][band][pt][
......@@ -497,7 +497,7 @@ static void optimize_b(MACROBLOCK *mb, int i, PLANE_TYPE type,
* add a new trellis node, but we do need to update the costs.
*/
else {
band = get_coef_band(i + 1);
band = get_coef_band(tx_size, i + 1);
t0 = tokens[next][0].token;
t1 = tokens[next][1].token;
/* Update the cost of each path if we're past the EOB token. */
......@@ -514,7 +514,7 @@ static void optimize_b(MACROBLOCK *mb, int i, PLANE_TYPE type,
}
/* Now pick the best path through the whole trellis. */
band = get_coef_band(i + 1);
band = get_coef_band(tx_size, i + 1);
VP9_COMBINEENTROPYCONTEXTS(pt, *a, *l);
rate0 = tokens[next][0].rate;
rate1 = tokens[next][1].rate;
......
......@@ -458,24 +458,24 @@ static INLINE int cost_coeffs(MACROBLOCK *mb,
for (; c < eob; c++) {
int v = qcoeff_ptr[scan[c]];
int t = vp9_dct_value_tokens_ptr[v].Token;
cost += token_costs[get_coef_band(c)][pt][t];
cost += token_costs[get_coef_band(tx_size, c)][pt][t];
cost += vp9_dct_value_cost_ptr[v];
pt = vp9_get_coef_context(&recent_energy, t);
}
if (c < seg_eob)
cost += mb->hybrid_token_costs[tx_size][type][get_coef_band(c)]
cost += mb->hybrid_token_costs[tx_size][type][get_coef_band(tx_size, c)]
[pt][DCT_EOB_TOKEN];
} else {
int recent_energy = 0;
for (; c < eob; c++) {
int v = qcoeff_ptr[scan[c]];
int t = vp9_dct_value_tokens_ptr[v].Token;
cost += token_costs[get_coef_band(c)][pt][t];
cost += token_costs[get_coef_band(tx_size, c)][pt][t];
cost += vp9_dct_value_cost_ptr[v];
pt = vp9_get_coef_context(&recent_energy, t);
}
if (c < seg_eob)
cost += mb->token_costs[tx_size][type][get_coef_band(c)]
cost += mb->token_costs[tx_size][type][get_coef_band(tx_size, c)]
[pt][DCT_EOB_TOKEN];
}
......
......@@ -214,7 +214,7 @@ static void tokenize_b(VP9_COMP *cpi,
seg_eob = 0;
do {
const int band = get_coef_band(c);
const int band = get_coef_band(tx_size, c);
int token;
if (c < eob) {
......@@ -738,7 +738,7 @@ static INLINE void stuff_b(VP9_COMP *cpi,
VP9_COMBINEENTROPYCONTEXTS(pt, a_ec, l_ec);
band = get_coef_band(0);
band = get_coef_band(tx_size, 0);
t->Token = DCT_EOB_TOKEN;
t->context_tree = probs[type][band][pt];
t->skip_eob_node = 0;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment