NEW_TOKENSET: do not code impossible values. In the last position, No-EOB values and zero are all not possible. AWCY, objective-1-fast: -0.08% all metrics AWCY, screen content: PSNR YCbCr: -0.42% -0.42% -0.43% PSNRHVS: -0.40% SSIM: -0.41% MSSSIM: -0.41% CIEDE2000: -0.42% Change-Id: Iad012abfd2a48a2c9ff27512f92b27235a5a8a4a
diff --git a/av1/common/entropy.h b/av1/common/entropy.h index e310863..1b44662 100644 --- a/av1/common/entropy.h +++ b/av1/common/entropy.h
@@ -49,6 +49,9 @@ #define CATEGORY6_TOKEN 10 // 67+ Extra Bits 14+1 #define EOB_TOKEN 11 // EOB Extra Bits 0+0 #if CONFIG_NEW_TOKENSET +#define NO_EOB 0 // Not an end-of-block +#define EARLY_EOB 1 // End of block before the last position +#define LAST_EOB 2 // End of block in the last position (implicit) #define BLOCK_Z_TOKEN 255 // block zero #define ONE_TOKEN_EOB 1 #define ONE_TOKEN_NEOB 2
diff --git a/av1/decoder/detokenize.c b/av1/decoder/detokenize.c index 4750d10..bc8f9c4 100644 --- a/av1/decoder/detokenize.c +++ b/av1/decoder/detokenize.c
@@ -167,6 +167,7 @@ while (c < max_eob) { int more_data; int comb_token; + int last_pos = (c + 1 == max_eob); #if CONFIG_NEW_QUANT dqv_val = &dq_val[band][0]; @@ -174,7 +175,8 @@ cdf_head = &coef_head_cdfs[band][ctx]; cdf_tail = &coef_tail_cdfs[band][ctx]; - comb_token = aom_read_symbol(r, *cdf_head, 6, ACCT_STR); + comb_token = last_pos ? (aom_read_bit(r, ACCT_STR) + 1) * 2 + : aom_read_symbol(r, *cdf_head, 6, ACCT_STR); if (c == 0) { if (counts) ++blockz_count[comb_token != 0]; if (comb_token == 0) return 0; @@ -191,7 +193,7 @@ *max_scan_line = AOMMAX(*max_scan_line, scan[c]); - if (token) { + if (token && !last_pos) { if (counts) ++eob_branch_count[band][ctx]; if (!more_data) { if (counts) ++coef_counts[band][ctx][EOB_MODEL_TOKEN];
diff --git a/av1/encoder/bitstream.c b/av1/encoder/bitstream.c index 00ae1fd..c5c656c 100644 --- a/av1/encoder/bitstream.c +++ b/av1/encoder/bitstream.c
@@ -839,9 +839,13 @@ p++; continue; } - int comb_symb = 2 * AOMMIN(token, TWO_TOKEN) - p->is_eob + 1; - - aom_write_symbol(w, comb_symb, *p->head_cdf, 6); + if (p->eob_val == LAST_EOB) { + // Just code a flag indicating whether the value is >1 or 1. + aom_write_bit(w, token != ONE_TOKEN); + } else { + int comb_symb = 2 * AOMMIN(token, TWO_TOKEN) - p->eob_val + 1; + aom_write_symbol(w, comb_symb, *p->head_cdf, 6); + } if (token > ONE_TOKEN) { aom_write_symbol(w, token - TWO_TOKEN, *p->tail_cdf, CATEGORY6_TOKEN + 1 - 2);
diff --git a/av1/encoder/tokenize.c b/av1/encoder/tokenize.c index e22cf3a..d214ad3 100644 --- a/av1/encoder/tokenize.c +++ b/av1/encoder/tokenize.c
@@ -364,12 +364,12 @@ static INLINE void add_token(TOKENEXTRA **t, aom_cdf_prob (*tail_cdf)[CDF_SIZE(ENTROPY_TOKENS)], aom_cdf_prob (*head_cdf)[CDF_SIZE(ENTROPY_TOKENS)], - int is_eob, int32_t extra, uint8_t token) { + int eob_val, int32_t extra, uint8_t token) { (*t)->token = token; (*t)->extra = extra; (*t)->tail_cdf = tail_cdf; (*t)->head_cdf = head_cdf; - (*t)->is_eob = is_eob; + (*t)->eob_val = eob_val; (*t)++; } @@ -390,13 +390,13 @@ (*t)++; ++counts[token]; } +#endif static INLINE int get_tx_eob(const struct segmentation *seg, int segment_id, TX_SIZE tx_size) { const int eob_max = tx_size_2d[tx_size]; return segfeature_active(seg, segment_id, SEG_LVL_SKIP) ? 0 : eob_max; } -#endif #endif // !CONFIG_PVQ #if CONFIG_PALETTE @@ -509,13 +509,11 @@ const int eob = p->eobs[block]; const PLANE_TYPE type = pd->plane_type; const tran_low_t *qcoeff = BLOCK_OFFSET(p->qcoeff, block); -#if !CONFIG_NEW_TOKENSET #if CONFIG_SUPERTX const int segment_id = AOMMIN(mbmi->segment_id, mbmi->segment_id_supertx); #else const int segment_id = mbmi->segment_id; #endif // CONFIG_SUEPRTX -#endif // !CONFIG_NEW_TOKENSET const int16_t *scan, *nb; const int block_raster_idx = av1_block_index_to_raster_order(tx_size, block); const TX_TYPE tx_type = get_tx_type(type, xd, block_raster_idx, tx_size); @@ -548,15 +546,15 @@ ec_ctx->coef_tail_cdfs[txsize_sqr_map[tx_size]][type][ref]; unsigned int(*const blockz_count)[2] = td->counts->blockz_count[txsize_sqr_map[tx_size]][type][ref]; - int is_eob; + int eob_val; #else #if CONFIG_EC_MULTISYMBOL aom_cdf_prob(*const coef_cdfs)[COEFF_CONTEXTS][CDF_SIZE(ENTROPY_TOKENS)] = ec_ctx->coef_cdfs[txsize_sqr_map[tx_size]][type][ref]; #endif int skip_eob = 0; - const int seg_eob = get_tx_eob(&cpi->common.seg, segment_id, tx_size); #endif + const int seg_eob = get_tx_eob(&cpi->common.seg, segment_id, tx_size); unsigned int(*const eob_branch)[COEFF_CONTEXTS] = td->counts->eob_branch[txsize_sqr_map[tx_size]][type][ref]; const uint8_t *const band = get_band_translate(tx_size); @@ -585,16 +583,19 @@ ++counts[band[c]][pt][ZERO_TOKEN]; token_cache[scan[c]] = 0; } else { - is_eob = (c + 1 == eob); + eob_val = + (c + 1 == eob) ? (c + 1 == seg_eob ? LAST_EOB : EARLY_EOB) : NO_EOB; av1_get_token_extra(v, &token, &extra); add_token(&t, &coef_tail_cdfs[band[c]][pt], &coef_head_cdfs[band[c]][pt], - is_eob, extra, (uint8_t)token); + eob_val, extra, (uint8_t)token); - ++counts[band[c]][pt][token]; - ++eob_branch[band[c]][pt]; - counts[band[c]][pt][EOB_TOKEN] += is_eob; + if (eob_val != LAST_EOB) { + ++counts[band[c]][pt][token]; + ++eob_branch[band[c]][pt]; + counts[band[c]][pt][EOB_TOKEN] += eob_val != NO_EOB; + } token_cache[scan[c]] = av1_pt_energy_class[token]; }
diff --git a/av1/encoder/tokenize.h b/av1/encoder/tokenize.h index 46d3eff..02aa04f 100644 --- a/av1/encoder/tokenize.h +++ b/av1/encoder/tokenize.h
@@ -38,7 +38,7 @@ #if CONFIG_NEW_TOKENSET aom_cdf_prob (*tail_cdf)[CDF_SIZE(ENTROPY_TOKENS)]; aom_cdf_prob (*head_cdf)[CDF_SIZE(ENTROPY_TOKENS)]; - int is_eob; + int eob_val; #elif CONFIG_EC_MULTISYMBOL aom_cdf_prob (*token_cdf)[CDF_SIZE(ENTROPY_TOKENS)]; #endif