Merge "Use above/left (instead of previous in scan-order) as token context." into experimental

This commit is contained in:
Ronald S. Bultje 2013-03-26 19:16:24 -07:00 committed by Gerrit Code Review
commit c6efbbcfe4
13 changed files with 776 additions and 593 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1886,25 +1886,25 @@ vp9_extra_bit_struct vp9_extra_bits[12] = {
// within the current block.
//
// For now it just returns the previously used context.
int vp9_get_coef_context(int * recent_energy, int token) {
// int token_energy;
// int av_energy;
/*token_energy = ((token != DCT_EOB_TOKEN) ? token : 0);
if (!token_energy) {
if (!(*recent_energy)) {
av_energy = 0;
} else {
av_energy = 1;
}
#define MAX_NEIGHBORS 2
int vp9_get_coef_context(const int *scan, const int *neighbors,
int nb_pad, uint8_t *token_cache, int c, int l) {
int eob = l;
assert(nb_pad == MAX_NEIGHBORS);
if (c == eob - 1) {
return 0;
} else {
av_energy = ((token_energy + *recent_energy + 1) >> 1) + 1;
if (av_energy > DCT_VAL_CATEGORY6)
av_energy = DCT_VAL_CATEGORY6;
int ctx;
c++;
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;
} else {
ctx = token_cache[neighbors[MAX_NEIGHBORS * c + 0]];
}
return vp9_pt_energy_class[ctx];
}
*recent_energy = token_energy;*/
return vp9_pt_energy_class[token];
};
void vp9_default_coef_probs(VP9_COMMON *pc) {
@ -2063,7 +2063,119 @@ void vp9_adjust_default_coef_probs(VP9_COMMON *cm) {
}
#endif
// 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]);
DECLARE_ALIGNED(16, int,
vp9_default_zig_zag1d_32x32_neighbors[1024 * MAX_NEIGHBORS]);
static int find_in_scan(const int *scan, int l, int idx) {
int n, l2 = l * l;
for (n = 0; n < l2; n++) {
int rc = scan[n];
if (rc == idx)
return n;
}
assert(0);
return -1;
}
static void init_scan_neighbors(const int *scan, int l, int *neighbors,
int max_neighbors) {
int l2 = l * l;
int n, i, j;
for (n = 0; n < l2; n++) {
int rc = scan[n];
assert(max_neighbors == MAX_NEIGHBORS);
i = rc / l;
j = rc % l;
if (i > 0 && j > 0) {
// col/row scan is used for adst/dct, and generally means that
// energy decreases to zero much faster in the dimension in
// which ADST is used compared to the direction in which DCT
// is used. Likewise, we find much higher correlation between
// coefficients within the direction in which DCT is used.
// Therefore, if we use ADST/DCT, prefer the DCT neighbor coeff
// as a context. If ADST or DCT is used in both directions, we
// use the combination of the two as a context.
int a = find_in_scan(scan, l, (i - 1) * l + j);
int b = find_in_scan(scan, l, i * l + j - 1);
if (scan == vp9_col_scan_4x4 || scan == vp9_row_scan_4x4) {
neighbors[max_neighbors * n + 0] = MAX(a, b);
neighbors[max_neighbors * n + 1] = -1;
} else {
neighbors[max_neighbors * n + 0] = a;
neighbors[max_neighbors * n + 1] = b;
}
} else if (i > 0) {
neighbors[max_neighbors * n + 0] = find_in_scan(scan, l, (i - 1) * l + j);
neighbors[max_neighbors * n + 1] = -1;
} else if (j > 0) {
neighbors[max_neighbors * n + 0] =
find_in_scan(scan, l, i * l + j - 1);
neighbors[max_neighbors * n + 1] = -1;
} else {
assert(n == 0);
// dc predictor doesn't use previous tokens
neighbors[max_neighbors * n + 0] = -1;
}
assert(neighbors[max_neighbors * n + 0] < n);
}
}
void vp9_init_neighbors() {
init_scan_neighbors(vp9_default_zig_zag1d_4x4, 4,
vp9_default_zig_zag1d_4x4_neighbors, MAX_NEIGHBORS);
init_scan_neighbors(vp9_row_scan_4x4, 4,
vp9_row_scan_4x4_neighbors, MAX_NEIGHBORS);
init_scan_neighbors(vp9_col_scan_4x4, 4,
vp9_col_scan_4x4_neighbors, MAX_NEIGHBORS);
init_scan_neighbors(vp9_default_zig_zag1d_8x8, 8,
vp9_default_zig_zag1d_8x8_neighbors, MAX_NEIGHBORS);
init_scan_neighbors(vp9_default_zig_zag1d_16x16, 16,
vp9_default_zig_zag1d_16x16_neighbors, MAX_NEIGHBORS);
init_scan_neighbors(vp9_default_zig_zag1d_32x32, 32,
vp9_default_zig_zag1d_32x32_neighbors, MAX_NEIGHBORS);
}
const int *vp9_get_coef_neighbors_handle(const int *scan, int *pad) {
if (scan == vp9_default_zig_zag1d_4x4) {
*pad = MAX_NEIGHBORS;
return vp9_default_zig_zag1d_4x4_neighbors;
} else if (scan == vp9_row_scan_4x4) {
*pad = MAX_NEIGHBORS;
return vp9_row_scan_4x4_neighbors;
} else if (scan == vp9_col_scan_4x4) {
*pad = MAX_NEIGHBORS;
return vp9_col_scan_4x4_neighbors;
} else if (scan == vp9_default_zig_zag1d_8x8) {
*pad = MAX_NEIGHBORS;
return vp9_default_zig_zag1d_8x8_neighbors;
} else if (scan == vp9_default_zig_zag1d_16x16) {
*pad = MAX_NEIGHBORS;
return vp9_default_zig_zag1d_16x16_neighbors;
} else if (scan == vp9_default_zig_zag1d_32x32) {
*pad = MAX_NEIGHBORS;
return vp9_default_zig_zag1d_32x32_neighbors;
} else {
assert(0);
return NULL;
}
}
void vp9_coef_tree_initialize() {
vp9_init_neighbors();
init_bit_trees();
vp9_tokens_from_tree(vp9_coef_encodings, vp9_coef_tree);
#if CONFIG_CODE_NONZEROCOUNT
@ -3170,6 +3282,9 @@ void vp9_update_nzc_counts(VP9_COMMON *cm,
static void adapt_coef_probs(vp9_coeff_probs *dst_coef_probs,
vp9_coeff_probs *pre_coef_probs,
int block_types, vp9_coeff_count *coef_counts,
unsigned int (*eob_branch_count)[REF_TYPES]
[COEF_BANDS]
[PREV_COEF_CONTEXTS],
int count_sat, int update_factor) {
int t, i, j, k, l, count;
unsigned int branch_ct[ENTROPY_NODES][2];
@ -3190,6 +3305,8 @@ static void adapt_coef_probs(vp9_coeff_probs *dst_coef_probs,
vp9_tree_probs_from_distribution(vp9_coef_tree,
coef_probs, branch_ct,
coef_counts[i][j][k][l], 0);
branch_ct[0][1] = eob_branch_count[i][j][k][l] - branch_ct[0][0];
coef_probs[0] = get_binary_prob(branch_ct[0][0], branch_ct[0][1]);
for (t = 0; t < entropy_nodes_adapt; ++t) {
count = branch_ct[t][0] + branch_ct[t][1];
count = count > count_sat ? count_sat : count;
@ -3224,15 +3341,19 @@ void vp9_adapt_coef_probs(VP9_COMMON *cm) {
adapt_coef_probs(cm->fc.coef_probs_4x4, cm->fc.pre_coef_probs_4x4,
BLOCK_TYPES, cm->fc.coef_counts_4x4,
cm->fc.eob_branch_counts[TX_4X4],
count_sat, update_factor);
adapt_coef_probs(cm->fc.coef_probs_8x8, cm->fc.pre_coef_probs_8x8,
BLOCK_TYPES, cm->fc.coef_counts_8x8,
cm->fc.eob_branch_counts[TX_8X8],
count_sat, update_factor);
adapt_coef_probs(cm->fc.coef_probs_16x16, cm->fc.pre_coef_probs_16x16,
BLOCK_TYPES, cm->fc.coef_counts_16x16,
cm->fc.eob_branch_counts[TX_16X16],
count_sat, update_factor);
adapt_coef_probs(cm->fc.coef_probs_32x32, cm->fc.pre_coef_probs_32x32,
BLOCK_TYPES, cm->fc.coef_counts_32x32,
cm->fc.eob_branch_counts[TX_32X32],
count_sat, update_factor);
}

View File

@ -139,7 +139,9 @@ static int get_coef_band(TX_SIZE tx_size, int coef_index) {
return 5;
}
}
extern int vp9_get_coef_context(int * recent_energy, int token);
extern int vp9_get_coef_context(const int *scan, const int *neighbors,
int nb_pad, uint8_t *token_cache, int c, int l);
const int *vp9_get_coef_neighbors_handle(const int *scan, int *pad);
#if CONFIG_MODELCOEFPROB
#define COEFPROB_BITS 8

View File

@ -114,6 +114,9 @@ typedef struct frame_contexts {
vp9_coeff_count coef_counts_8x8[BLOCK_TYPES];
vp9_coeff_count coef_counts_16x16[BLOCK_TYPES];
vp9_coeff_count coef_counts_32x32[BLOCK_TYPES];
unsigned int eob_branch_counts[TX_SIZE_MAX_SB][BLOCK_TYPES][REF_TYPES]
[COEF_BANDS][PREV_COEF_CONTEXTS];
#if CONFIG_CODE_NONZEROCOUNT
unsigned int nzc_counts_4x4[MAX_NZC_CONTEXTS][REF_TYPES][BLOCK_TYPES]
[NZC4X4_TOKENS];

View File

@ -1729,6 +1729,7 @@ int vp9_decode_frame(VP9D_COMP *pbi, const unsigned char **p_data_end) {
vp9_zero(pbi->common.fc.coef_counts_8x8);
vp9_zero(pbi->common.fc.coef_counts_16x16);
vp9_zero(pbi->common.fc.coef_counts_32x32);
vp9_zero(pbi->common.fc.eob_branch_counts);
vp9_zero(pbi->common.fc.ymode_counts);
vp9_zero(pbi->common.fc.sb_ymode_counts);
vp9_zero(pbi->common.fc.uv_mode_counts);

View File

@ -66,7 +66,8 @@ static int get_signed(BOOL_DECODER *br, int value_to_sign) {
#define INCREMENT_COUNT(token) \
do { \
coef_counts[type][ref][get_coef_band(txfm_size, c)][pt][token]++; \
pt = vp9_get_coef_context(&recent_energy, token); \
token_cache[c] = token; \
pt = vp9_get_coef_context(scan, nb, pad, token_cache, c, default_eob); \
} while (0)
#if CONFIG_CODE_NONZEROCOUNT
@ -103,8 +104,7 @@ static int decode_coefs(VP9D_COMP *dx, const MACROBLOCKD *xd,
int aidx, lidx;
ENTROPY_CONTEXT above_ec, left_ec;
FRAME_CONTEXT *const fc = &dx->common.fc;
int recent_energy = 0;
int pt, c = 0;
int pt, c = 0, pad, default_eob;
vp9_coeff_probs *coef_probs;
vp9_prob *prob;
vp9_coeff_count *coef_counts;
@ -113,7 +113,8 @@ static int decode_coefs(VP9D_COMP *dx, const MACROBLOCKD *xd,
uint16_t nzc = 0;
uint16_t nzc_expected = xd->mode_info_context->mbmi.nzcs[block_idx];
#endif
const int *scan;
const int *scan, *nb;
uint8_t token_cache[1024];
if (xd->mode_info_context->mbmi.sb_type == BLOCK_SIZE_SB64X64) {
aidx = vp9_block2above_sb64[txfm_size][block_idx];
@ -145,6 +146,7 @@ static int decode_coefs(VP9D_COMP *dx, const MACROBLOCKD *xd,
left_ec = L0[lidx] != 0;
coef_probs = fc->coef_probs_4x4;
coef_counts = fc->coef_counts_4x4;
default_eob = 16;
break;
}
case TX_8X8:
@ -153,6 +155,7 @@ static int decode_coefs(VP9D_COMP *dx, const MACROBLOCKD *xd,
coef_counts = fc->coef_counts_8x8;
above_ec = (A0[aidx] + A0[aidx + 1]) != 0;
left_ec = (L0[lidx] + L0[lidx + 1]) != 0;
default_eob = 64;
break;
case TX_16X16:
scan = vp9_default_zig_zag1d_16x16;
@ -167,6 +170,7 @@ static int decode_coefs(VP9D_COMP *dx, const MACROBLOCKD *xd,
above_ec = (A0[aidx] + A0[aidx + 1] + A0[aidx + 2] + A0[aidx + 3]) != 0;
left_ec = (L0[lidx] + L0[lidx + 1] + L0[lidx + 2] + L0[lidx + 3]) != 0;
}
default_eob = 256;
break;
case TX_32X32:
scan = vp9_default_zig_zag1d_32x32;
@ -191,10 +195,13 @@ static int decode_coefs(VP9D_COMP *dx, const MACROBLOCKD *xd,
left_ec = (L0[lidx] + L0[lidx + 1] + L0[lidx + 2] + L0[lidx + 3] +
L1[lidx] + L1[lidx + 1] + L1[lidx + 2] + L1[lidx + 3]) != 0;
}
default_eob = 1024;
break;
}
VP9_COMBINEENTROPYCONTEXTS(pt, above_ec, left_ec);
nb = vp9_get_coef_neighbors_handle(scan, &pad);
while (1) {
int val;
const uint8_t *cat6 = cat6_prob;
@ -207,6 +214,8 @@ static int decode_coefs(VP9D_COMP *dx, const MACROBLOCKD *xd,
#endif
prob = coef_probs[type][ref][get_coef_band(txfm_size, c)][pt];
#if CONFIG_CODE_NONZEROCOUNT == 0
fc->eob_branch_counts[txfm_size][type][ref]
[get_coef_band(txfm_size, c)][pt]++;
if (!vp9_read(br, prob[EOB_CONTEXT_NODE]))
break;
#endif

View File

@ -1758,6 +1758,9 @@ static void print_prob_tree(vp9_coeff_probs *coef_probs, int block_types) {
static void build_tree_distribution(vp9_coeff_probs *coef_probs,
vp9_coeff_count *coef_counts,
unsigned int (*eob_branch_ct)[REF_TYPES]
[COEF_BANDS]
[PREV_COEF_CONTEXTS],
#ifdef ENTROPY_STATS
VP9_COMP *cpi,
vp9_coeff_accum *context_counters,
@ -1779,10 +1782,18 @@ static void build_tree_distribution(vp9_coeff_probs *coef_probs,
coef_probs[i][j][k][l],
coef_branch_ct[i][j][k][l],
coef_counts[i][j][k][l], 0);
coef_branch_ct[i][j][k][l][0][1] = eob_branch_ct[i][j][k][l] -
coef_branch_ct[i][j][k][l][0][0];
coef_probs[i][j][k][l][0] =
get_binary_prob(coef_branch_ct[i][j][k][l][0][0],
coef_branch_ct[i][j][k][l][0][1]);
#ifdef ENTROPY_STATS
if (!cpi->dummy_packing)
for (t = 0; t < MAX_ENTROPY_TOKENS; ++t)
context_counters[i][j][k][l][t] += coef_counts[i][j][k][l][t];
if (!cpi->dummy_packing) {
for (t = 0; t < MAX_ENTROPY_TOKENS; ++t)
context_counters[i][j][k][l][t] += coef_counts[i][j][k][l][t];
context_counters[i][j][k][l][MAX_ENTROPY_TOKENS] +=
eob_branch_ct[i][j][k][l];
}
#endif
}
}
@ -1793,24 +1804,28 @@ static void build_tree_distribution(vp9_coeff_probs *coef_probs,
static void build_coeff_contexts(VP9_COMP *cpi) {
build_tree_distribution(cpi->frame_coef_probs_4x4,
cpi->coef_counts_4x4,
cpi->common.fc.eob_branch_counts[TX_4X4],
#ifdef ENTROPY_STATS
cpi, context_counters_4x4,
#endif
cpi->frame_branch_ct_4x4, BLOCK_TYPES);
build_tree_distribution(cpi->frame_coef_probs_8x8,
cpi->coef_counts_8x8,
cpi->common.fc.eob_branch_counts[TX_8X8],
#ifdef ENTROPY_STATS
cpi, context_counters_8x8,
#endif
cpi->frame_branch_ct_8x8, BLOCK_TYPES);
build_tree_distribution(cpi->frame_coef_probs_16x16,
cpi->coef_counts_16x16,
cpi->common.fc.eob_branch_counts[TX_16X16],
#ifdef ENTROPY_STATS
cpi, context_counters_16x16,
#endif
cpi->frame_branch_ct_16x16, BLOCK_TYPES);
build_tree_distribution(cpi->frame_coef_probs_32x32,
cpi->coef_counts_32x32,
cpi->common.fc.eob_branch_counts[TX_32X32],
#ifdef ENTROPY_STATS
cpi, context_counters_32x32,
#endif

View File

@ -1276,6 +1276,7 @@ static void encode_frame_internal(VP9_COMP *cpi) {
vp9_zero(cpi->coef_counts_8x8);
vp9_zero(cpi->coef_counts_16x16);
vp9_zero(cpi->coef_counts_32x32);
vp9_zero(cm->fc.eob_branch_counts);
#if CONFIG_CODE_NONZEROCOUNT
vp9_zero(cm->fc.nzc_counts_4x4);
vp9_zero(cm->fc.nzc_counts_8x8);

View File

@ -528,9 +528,16 @@ static const int plane_rd_mult[4] = {
// This function is a place holder for now but may ultimately need
// to scan previous tokens to work out the correct context.
static int trellis_get_coeff_context(int token) {
int recent_energy = 0;
return vp9_get_coef_context(&recent_energy, token);
static int trellis_get_coeff_context(const int *scan,
const int *nb,
int idx, int token,
uint8_t *token_cache,
int pad, int l) {
int bak = token_cache[idx], pt;
token_cache[idx] = token;
pt = vp9_get_coef_context(scan, nb, pad, token_cache, idx + 1, l);
token_cache[idx] = bak;
return pt;
}
static void optimize_b(VP9_COMMON *const cm,
@ -552,9 +559,10 @@ static void optimize_b(VP9_COMMON *const cm,
int rate0, rate1, error0, error1, t0, t1;
int best, band, pt;
int err_mult = plane_rd_mult[type];
int default_eob;
int const *scan;
int default_eob, pad;
int const *scan, *nb;
const int mul = 1 + (tx_size == TX_32X32);
uint8_t token_cache[1024];
#if CONFIG_CODE_NONZEROCOUNT
// TODO(debargha): the dynamic programming approach used in this function
// is not compatible with the true rate cost when nzcs are used. Note
@ -631,6 +639,10 @@ static void optimize_b(VP9_COMMON *const cm,
tokens[eob][0].qc = 0;
*(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;
nb = vp9_get_coef_neighbors_handle(scan, &pad);
for (i = eob; i-- > i0;) {
int base_bits, d2, dx;
#if CONFIG_CODE_NONZEROCOUNT
@ -651,7 +663,8 @@ static void optimize_b(VP9_COMMON *const cm,
/* Consider both possible successor states. */
if (next < default_eob) {
band = get_coef_band(tx_size, i + 1);
pt = trellis_get_coeff_context(t0);
pt = trellis_get_coeff_context(scan, nb, i, t0, token_cache,
pad, default_eob);
rate0 +=
mb->token_costs[tx_size][type][ref][band][pt][tokens[next][0].token];
rate1 +=
@ -710,12 +723,14 @@ static void optimize_b(VP9_COMMON *const cm,
if (next < default_eob) {
band = get_coef_band(tx_size, i + 1);
if (t0 != DCT_EOB_TOKEN) {
pt = trellis_get_coeff_context(t0);
pt = trellis_get_coeff_context(scan, nb, i, t0, token_cache,
pad, default_eob);
rate0 += mb->token_costs[tx_size][type][ref][band][pt][
tokens[next][0].token];
}
if (t1 != DCT_EOB_TOKEN) {
pt = trellis_get_coeff_context(t1);
pt = trellis_get_coeff_context(scan, nb, i, t1, token_cache,
pad, default_eob);
rate1 += mb->token_costs[tx_size][type][ref][band][pt][
tokens[next][1].token];
}

View File

@ -156,21 +156,9 @@ static void fill_token_costs(vp9_coeff_count *c,
for (j = 0; j < REF_TYPES; j++)
for (k = 0; k < COEF_BANDS; k++)
for (l = 0; l < PREV_COEF_CONTEXTS; l++) {
#if CONFIG_CODE_NONZEROCOUNT
// All costs are without the EOB node
vp9_cost_tokens_skip((int *)(c[i][j][k][l]),
p[i][j][k][l],
vp9_coef_tree);
#else
if (l == 0 && k > 0)
vp9_cost_tokens_skip((int *)(c[i][j][k][l]),
p[i][j][k][l],
vp9_coef_tree);
else
vp9_cost_tokens((int *)(c[i][j][k][l]),
p[i][j][k][l],
vp9_coef_tree);
#endif
}
}
@ -448,8 +436,8 @@ static INLINE int cost_coeffs(VP9_COMMON *const cm, MACROBLOCK *mb,
int pt;
const int eob = xd->eobs[ib];
int c = 0;
int cost = 0;
const int *scan;
int cost = 0, pad;
const int *scan, *nb;
const int16_t *qcoeff_ptr = xd->qcoeff + ib * 16;
const int ref = mbmi->ref_frame != INTRA_FRAME;
unsigned int (*token_costs)[PREV_COEF_CONTEXTS][MAX_ENTROPY_TOKENS] =
@ -464,9 +452,12 @@ static INLINE int cost_coeffs(VP9_COMMON *const cm, MACROBLOCK *mb,
int nzc_context = vp9_get_nzc_context(cm, xd, ib);
unsigned int *nzc_cost;
#else
int seg_eob;
const int segment_id = xd->mode_info_context->mbmi.segment_id;
vp9_prob (*coef_probs)[REF_TYPES][COEF_BANDS][PREV_COEF_CONTEXTS]
[ENTROPY_NODES];
#endif
int seg_eob, default_eob;
uint8_t token_cache[1024];
// Check for consistency of tx_size with mode info
if (type == PLANE_TYPE_Y_WITH_DC) {
@ -485,8 +476,9 @@ static INLINE int cost_coeffs(VP9_COMMON *const cm, MACROBLOCK *mb,
#if CONFIG_CODE_NONZEROCOUNT
nzc_cost = mb->nzc_costs_4x4[nzc_context][ref][type];
#else
seg_eob = 16;
coef_probs = cm->fc.coef_probs_4x4;
#endif
seg_eob = 16;
if (tx_type == ADST_DCT) {
scan = vp9_row_scan_4x4;
} else if (tx_type == DCT_ADST) {
@ -503,16 +495,18 @@ static INLINE int cost_coeffs(VP9_COMMON *const cm, MACROBLOCK *mb,
#if CONFIG_CODE_NONZEROCOUNT
nzc_cost = mb->nzc_costs_8x8[nzc_context][ref][type];
#else
seg_eob = 64;
coef_probs = cm->fc.coef_probs_8x8;
#endif
seg_eob = 64;
break;
case TX_16X16:
scan = vp9_default_zig_zag1d_16x16;
#if CONFIG_CODE_NONZEROCOUNT
nzc_cost = mb->nzc_costs_16x16[nzc_context][ref][type];
#else
seg_eob = 256;
coef_probs = cm->fc.coef_probs_16x16;
#endif
seg_eob = 256;
if (type == PLANE_TYPE_UV) {
a_ec = (a[0] + a[1] + a1[0] + a1[1]) != 0;
l_ec = (l[0] + l[1] + l1[0] + l1[1]) != 0;
@ -526,8 +520,9 @@ static INLINE int cost_coeffs(VP9_COMMON *const cm, MACROBLOCK *mb,
#if CONFIG_CODE_NONZEROCOUNT
nzc_cost = mb->nzc_costs_32x32[nzc_context][ref][type];
#else
seg_eob = 1024;
coef_probs = cm->fc.coef_probs_32x32;
#endif
seg_eob = 1024;
if (type == PLANE_TYPE_UV) {
ENTROPY_CONTEXT *a2, *a3, *l2, *l3;
a2 = a1 + sizeof(ENTROPY_CONTEXT_PLANES) / sizeof(ENTROPY_CONTEXT);
@ -551,6 +546,8 @@ static INLINE int cost_coeffs(VP9_COMMON *const cm, MACROBLOCK *mb,
}
VP9_COMBINEENTROPYCONTEXTS(pt, a_ec, l_ec);
nb = vp9_get_coef_neighbors_handle(scan, &pad);
default_eob = seg_eob;
#if CONFIG_CODE_NONZEROCOUNT == 0
if (vp9_segfeature_active(xd, segment_id, SEG_LVL_SKIP))
@ -558,7 +555,6 @@ static INLINE int cost_coeffs(VP9_COMMON *const cm, MACROBLOCK *mb,
#endif
{
int recent_energy = 0;
#if CONFIG_CODE_NONZEROCOUNT
int nzc = 0;
#endif
@ -568,9 +564,16 @@ static INLINE int cost_coeffs(VP9_COMMON *const cm, MACROBLOCK *mb,
#if CONFIG_CODE_NONZEROCOUNT
nzc += (v != 0);
#endif
token_cache[c] = 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 !CONFIG_CODE_NONZEROCOUNT
if (!c || token_cache[c - 1])
cost += vp9_cost_bit(coef_probs[type][ref]
[get_coef_band(tx_size, c)]
[pt][0], 1);
#endif
pt = vp9_get_coef_context(scan, nb, pad, token_cache, c, default_eob);
}
#if CONFIG_CODE_NONZEROCOUNT
cost += nzc_cost[nzc];

View File

@ -109,6 +109,8 @@ static void fill_value_tokens() {
vp9_dct_value_cost_ptr = dct_value_cost + DCT_MAX_VALUE;
}
extern const int *vp9_get_coef_neighbors_handle(const int *scan, int *pad);
static void tokenize_b(VP9_COMP *cpi,
MACROBLOCKD *xd,
const int ib,
@ -119,18 +121,18 @@ static void tokenize_b(VP9_COMP *cpi,
MB_MODE_INFO *mbmi = &xd->mode_info_context->mbmi;
int pt; /* near block/prev token context index */
int c = 0;
int recent_energy = 0;
const int eob = xd->eobs[ib]; /* one beyond last nonzero coeff */
TOKENEXTRA *t = *tp; /* store tokens starting here */
int16_t *qcoeff_ptr = xd->qcoeff + 16 * ib;
int seg_eob;
int seg_eob, default_eob, pad;
const int segment_id = mbmi->segment_id;
const BLOCK_SIZE_TYPE sb_type = mbmi->sb_type;
const int *scan;
const int *scan, *nb;
vp9_coeff_count *counts;
vp9_coeff_probs *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];
#if CONFIG_CODE_NONZEROCOUNT
int zerosleft, nzc = 0;
if (eob == 0)
@ -220,6 +222,8 @@ static void tokenize_b(VP9_COMP *cpi,
}
VP9_COMBINEENTROPYCONTEXTS(pt, a_ec, l_ec);
nb = vp9_get_coef_neighbors_handle(scan, &pad);
default_eob = seg_eob;
if (vp9_segfeature_active(xd, segment_id, SEG_LVL_SKIP))
seg_eob = 0;
@ -252,17 +256,20 @@ static void tokenize_b(VP9_COMP *cpi,
// Skip zero node if there are no zeros left
t->skip_eob_node = 1 + (zerosleft == 0);
#else
t->skip_eob_node = (pt == 0) && (band > 0);
t->skip_eob_node = (c > 0) && (token_cache[c - 1] == 0);
#endif
assert(vp9_coef_encodings[t->Token].Len - t->skip_eob_node > 0);
if (!dry_run) {
++counts[type][ref][band][pt][token];
if (!t->skip_eob_node)
++cpi->common.fc.eob_branch_counts[tx_size][type][ref][band][pt];
}
#if CONFIG_CODE_NONZEROCOUNT
nzc += (v != 0);
#endif
token_cache[c] = token;
pt = vp9_get_coef_context(&recent_energy, token);
pt = vp9_get_coef_context(scan, nb, pad, token_cache, c, default_eob);
++t;
} while (c < eob && ++c < seg_eob);
#if CONFIG_CODE_NONZEROCOUNT
@ -833,7 +840,7 @@ static void print_counter(FILE *f, vp9_coeff_accum *context_counters,
assert(x == (int64_t) y); /* no overflow handling yet */
fprintf(f, "%s %d", Comma(t), y);
} while (++t < MAX_ENTROPY_TOKENS);
} while (++t < 1 + MAX_ENTROPY_TOKENS);
fprintf(f, "}");
} while (++pt < PREV_COEF_CONTEXTS);
fprintf(f, "\n }");
@ -867,13 +874,17 @@ static void print_probs(FILE *f, vp9_coeff_accum *context_counters,
pt = 0;
do {
unsigned int branch_ct[ENTROPY_NODES][2];
unsigned int coef_counts[MAX_ENTROPY_TOKENS];
unsigned int coef_counts[MAX_ENTROPY_TOKENS + 1];
vp9_prob coef_probs[ENTROPY_NODES];
for (t = 0; t < MAX_ENTROPY_TOKENS; ++t)
if (pt >= 3 && band == 0)
break;
for (t = 0; t < MAX_ENTROPY_TOKENS + 1; ++t)
coef_counts[t] = context_counters[type][ref][band][pt][t];
vp9_tree_probs_from_distribution(vp9_coef_tree, coef_probs,
branch_ct, coef_counts, 0);
branch_ct[0][1] = coef_counts[MAX_ENTROPY_TOKENS] - branch_ct[0][0];
coef_probs[0] = get_binary_prob(branch_ct[0][0], branch_ct[0][1]);
fprintf(f, "%s\n {", Comma(pt));
t = 0;
@ -1025,7 +1036,7 @@ static void stuff_b(VP9_COMP *cpi,
#if CONFIG_CODE_NONZEROCOUNT == 0
VP9_COMBINEENTROPYCONTEXTS(pt, a_ec, l_ec);
band = get_coef_band(tx_size, 0);
band = 0;
t->Token = DCT_EOB_TOKEN;
t->context_tree = probs[type][ref][band][pt];
t->skip_eob_node = 0;

View File

@ -29,7 +29,7 @@ typedef struct {
} TOKENEXTRA;
typedef int64_t vp9_coeff_accum[REF_TYPES][COEF_BANDS][PREV_COEF_CONTEXTS]
[MAX_ENTROPY_TOKENS];
[MAX_ENTROPY_TOKENS + 1];
int vp9_mby_is_skippable_4x4(MACROBLOCKD *xd);
int vp9_mbuv_is_skippable_4x4(MACROBLOCKD *xd);

View File

@ -10,6 +10,7 @@
#include "vp9/encoder/vp9_treewriter.h"
#include "vp9/common/vp9_common.h"
static void cost(
int *const C,
@ -35,6 +36,7 @@ void vp9_cost_tokens(int *c, const vp9_prob *p, vp9_tree t) {
}
void vp9_cost_tokens_skip(int *c, const vp9_prob *p, vp9_tree t) {
c[0] = 0;
assert(t[1] > 0 && t[0] <= 0);
c[-t[0]] = vp9_cost_bit(p[0], 0);
cost(c, t, p, 2, 0);
}