vp10: skip unreachable cat6 token extrabits.
We have historically added new bits to cat6 whenever we added a new transform size (or bitdepth, for that matter). However, we have always coded these new bits regardless of the actual transform size, which means that for smaller transforms, we code bits that cannot possibly be set. The coding (quality) impact of this is negligible, but the bigger issue is that this allows creating bitstreams with coefficient values that are nonsensible and can cause int overflows, which then de facto become part of the bitstream spec. By not coding these bits, we remove this possibility. See issue 1065. Change-Id: Ib3186eca2df6a7a15ddc60c8b55af182aadd964d
This commit is contained in:
@@ -163,26 +163,33 @@ static int decode_coefs(const MACROBLOCKD *xd,
|
|||||||
case CATEGORY5_TOKEN:
|
case CATEGORY5_TOKEN:
|
||||||
val = CAT5_MIN_VAL + read_coeff(cat5_prob, 5, r);
|
val = CAT5_MIN_VAL + read_coeff(cat5_prob, 5, r);
|
||||||
break;
|
break;
|
||||||
case CATEGORY6_TOKEN:
|
case CATEGORY6_TOKEN: {
|
||||||
|
#if CONFIG_MISC_FIXES
|
||||||
|
const int skip_bits = TX_SIZES - 1 - tx_size;
|
||||||
|
#else
|
||||||
|
const int skip_bits = 0;
|
||||||
|
#endif
|
||||||
|
const uint8_t *cat6p = cat6_prob + skip_bits;
|
||||||
#if CONFIG_VP9_HIGHBITDEPTH
|
#if CONFIG_VP9_HIGHBITDEPTH
|
||||||
switch (xd->bd) {
|
switch (xd->bd) {
|
||||||
case VPX_BITS_8:
|
case VPX_BITS_8:
|
||||||
val = CAT6_MIN_VAL + read_coeff(cat6_prob, 14, r);
|
val = CAT6_MIN_VAL + read_coeff(cat6p, 14 - skip_bits, r);
|
||||||
break;
|
break;
|
||||||
case VPX_BITS_10:
|
case VPX_BITS_10:
|
||||||
val = CAT6_MIN_VAL + read_coeff(cat6_prob, 16, r);
|
val = CAT6_MIN_VAL + read_coeff(cat6p, 16 - skip_bits, r);
|
||||||
break;
|
break;
|
||||||
case VPX_BITS_12:
|
case VPX_BITS_12:
|
||||||
val = CAT6_MIN_VAL + read_coeff(cat6_prob, 18, r);
|
val = CAT6_MIN_VAL + read_coeff(cat6p, 18 - skip_bits, r);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
assert(0);
|
assert(0);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
val = CAT6_MIN_VAL + read_coeff(cat6_prob, 14, r);
|
val = CAT6_MIN_VAL + read_coeff(cat6p, 14 - skip_bits, r);
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
v = (val * dqv) >> dq_shift;
|
v = (val * dqv) >> dq_shift;
|
||||||
|
@@ -122,8 +122,11 @@ static void update_switchable_interp_probs(VP10_COMMON *cm, vpx_writer *w,
|
|||||||
|
|
||||||
static void pack_mb_tokens(vpx_writer *w,
|
static void pack_mb_tokens(vpx_writer *w,
|
||||||
TOKENEXTRA **tp, const TOKENEXTRA *const stop,
|
TOKENEXTRA **tp, const TOKENEXTRA *const stop,
|
||||||
vpx_bit_depth_t bit_depth) {
|
vpx_bit_depth_t bit_depth, const TX_SIZE tx) {
|
||||||
TOKENEXTRA *p = *tp;
|
TOKENEXTRA *p = *tp;
|
||||||
|
#if !CONFIG_MISC_FIXES
|
||||||
|
(void) tx;
|
||||||
|
#endif
|
||||||
|
|
||||||
while (p < stop && p->token != EOSB_TOKEN) {
|
while (p < stop && p->token != EOSB_TOKEN) {
|
||||||
const int t = p->token;
|
const int t = p->token;
|
||||||
@@ -171,6 +174,12 @@ static void pack_mb_tokens(vpx_writer *w,
|
|||||||
|
|
||||||
if (b->base_val) {
|
if (b->base_val) {
|
||||||
const int e = p->extra, l = b->len;
|
const int e = p->extra, l = b->len;
|
||||||
|
#if CONFIG_MISC_FIXES
|
||||||
|
int skip_bits =
|
||||||
|
(b->base_val == CAT6_MIN_VAL) ? TX_SIZES - 1 - tx : 0;
|
||||||
|
#else
|
||||||
|
int skip_bits = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (l) {
|
if (l) {
|
||||||
const unsigned char *pb = b->prob;
|
const unsigned char *pb = b->prob;
|
||||||
@@ -180,7 +189,12 @@ static void pack_mb_tokens(vpx_writer *w,
|
|||||||
|
|
||||||
do {
|
do {
|
||||||
const int bb = (v >> --n) & 1;
|
const int bb = (v >> --n) & 1;
|
||||||
vpx_write(w, bb, pb[i >> 1]);
|
if (skip_bits) {
|
||||||
|
skip_bits--;
|
||||||
|
assert(!bb);
|
||||||
|
} else {
|
||||||
|
vpx_write(w, bb, pb[i >> 1]);
|
||||||
|
}
|
||||||
i = b->tree[i + bb];
|
i = b->tree[i + bb];
|
||||||
} while (n);
|
} while (n);
|
||||||
}
|
}
|
||||||
@@ -190,7 +204,7 @@ static void pack_mb_tokens(vpx_writer *w,
|
|||||||
++p;
|
++p;
|
||||||
}
|
}
|
||||||
|
|
||||||
*tp = p + (p->token == EOSB_TOKEN);
|
*tp = p;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void write_segment_id(vpx_writer *w, const struct segmentation *seg,
|
static void write_segment_id(vpx_writer *w, const struct segmentation *seg,
|
||||||
@@ -382,6 +396,7 @@ static void write_modes_b(VP10_COMP *cpi, const TileInfo *const tile,
|
|||||||
const VP10_COMMON *const cm = &cpi->common;
|
const VP10_COMMON *const cm = &cpi->common;
|
||||||
MACROBLOCKD *const xd = &cpi->td.mb.e_mbd;
|
MACROBLOCKD *const xd = &cpi->td.mb.e_mbd;
|
||||||
MODE_INFO *m;
|
MODE_INFO *m;
|
||||||
|
int plane;
|
||||||
|
|
||||||
xd->mi = cm->mi_grid_visible + (mi_row * cm->mi_stride + mi_col);
|
xd->mi = cm->mi_grid_visible + (mi_row * cm->mi_stride + mi_col);
|
||||||
m = xd->mi[0];
|
m = xd->mi[0];
|
||||||
@@ -398,8 +413,16 @@ static void write_modes_b(VP10_COMP *cpi, const TileInfo *const tile,
|
|||||||
pack_inter_mode_mvs(cpi, m, w);
|
pack_inter_mode_mvs(cpi, m, w);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(*tok < tok_end);
|
if (!m->mbmi.skip) {
|
||||||
pack_mb_tokens(w, tok, tok_end, cm->bit_depth);
|
assert(*tok < tok_end);
|
||||||
|
for (plane = 0; plane < MAX_MB_PLANE; ++plane) {
|
||||||
|
TX_SIZE tx = plane ? get_uv_tx_size(&m->mbmi, &xd->plane[plane])
|
||||||
|
: m->mbmi.tx_size;
|
||||||
|
pack_mb_tokens(w, tok, tok_end, cm->bit_depth, tx);
|
||||||
|
assert(*tok < tok_end && (*tok)->token == EOSB_TOKEN);
|
||||||
|
(*tok)++;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void write_partition(const VP10_COMMON *const cm,
|
static void write_partition(const VP10_COMMON *const cm,
|
||||||
|
@@ -1356,9 +1356,6 @@ static void encode_b(VP10_COMP *cpi, const TileInfo *const tile,
|
|||||||
|
|
||||||
if (output_enabled) {
|
if (output_enabled) {
|
||||||
update_stats(&cpi->common, td);
|
update_stats(&cpi->common, td);
|
||||||
|
|
||||||
(*tp)->token = EOSB_TOKEN;
|
|
||||||
(*tp)++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -628,8 +628,16 @@ void vp10_tokenize_sb(VP10_COMP *cpi, ThreadData *td, TOKENEXTRA **t,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!dry_run) {
|
if (!dry_run) {
|
||||||
|
int plane;
|
||||||
|
|
||||||
td->counts->skip[ctx][0] += skip_inc;
|
td->counts->skip[ctx][0] += skip_inc;
|
||||||
vp10_foreach_transformed_block(xd, bsize, tokenize_b, &arg);
|
|
||||||
|
for (plane = 0; plane < MAX_MB_PLANE; ++plane) {
|
||||||
|
vp10_foreach_transformed_block_in_plane(xd, bsize, plane, tokenize_b,
|
||||||
|
&arg);
|
||||||
|
(*t)->token = EOSB_TOKEN;
|
||||||
|
(*t)++;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
vp10_foreach_transformed_block(xd, bsize, set_entropy_context_b, &arg);
|
vp10_foreach_transformed_block(xd, bsize, set_entropy_context_b, &arg);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user