From a35597fc7f9e96b09eea5ac2863dd2e882ba00ea Mon Sep 17 00:00:00 2001 From: Debargha Mukherjee Date: Wed, 29 Jun 2016 13:18:52 -0700 Subject: [PATCH] Various cosmetics on the new_quant experiment Also extends quant profiles to include quality range. Change-Id: Ia96e45b6425e1d42ca61fc401f63d4fd7214e448 --- vp10/common/blockd.h | 8 -- vp10/common/quant_common.c | 158 +++++++++++++++++++++---------------- vp10/common/quant_common.h | 20 +++-- vp10/decoder/decodeframe.c | 16 ++-- vp10/decoder/detokenize.c | 4 +- vp10/encoder/encodemb.c | 10 +-- vp10/encoder/quantize.c | 32 ++++---- 7 files changed, 133 insertions(+), 115 deletions(-) diff --git a/vp10/common/blockd.h b/vp10/common/blockd.h index 59c8f9c52..27b2cadf8 100644 --- a/vp10/common/blockd.h +++ b/vp10/common/blockd.h @@ -31,14 +31,6 @@ extern "C" { #endif -#if CONFIG_NEW_QUANT -#define QUANT_PROFILES 3 - -static INLINE int get_dq_profile_from_ctx(int q_ctx) { - return VPXMIN(q_ctx, QUANT_PROFILES - 1); -} -#endif // CONFIG_NEW_QUANT - #define MAX_MB_PLANE 3 typedef enum { diff --git a/vp10/common/quant_common.c b/vp10/common/quant_common.c index ba2bd8812..3093ab731 100644 --- a/vp10/common/quant_common.c +++ b/vp10/common/quant_common.c @@ -15,94 +15,112 @@ #include "vp10/common/blockd.h" #if CONFIG_NEW_QUANT + // Bin widths expressed as a fraction over 128 of the quant stepsize, // for the quantization bins 0-4. // So a value x indicates the bin is actually factor x/128 of the // nominal quantization step. For the zero bin, the width is only // for one side of zero, so the actual width is twice that. -// There are four sets of values for 4 different quantizer ranges. // // Functions with nuq correspond to "non uniform quantization" -// TODO(debargha): Optimize these tables -static const uint8_t nuq_knots_lossless[COEF_BANDS][NUQ_KNOTS] = { - {64, 128, 128}, // dc, band 0 - {64, 128, 128}, // band 1 - {64, 128, 128}, // band 2 - {64, 128, 128}, // band 3 - {64, 128, 128}, // band 4 - {64, 128, 128}, // band 5 +// TODO(sarahparker, debargha): Optimize these tables + +typedef struct { + uint8_t knots[NUQ_KNOTS]; // offsets + uint8_t doff; // dequantization +} qprofile_type; + +static const qprofile_type nuq_lossless[COEF_BANDS] = { + {{64, 128, 128}, 0}, // dc, band 0 + {{64, 128, 128}, 0}, // band 1 + {{64, 128, 128}, 0}, // band 2 + {{64, 128, 128}, 0}, // band 3 + {{64, 128, 128}, 0}, // band 4 + {{64, 128, 128}, 0}, // band 5 }; -static const uint8_t nuq_knots[QUANT_PROFILES][COEF_BANDS][NUQ_KNOTS] = { +static const qprofile_type nuq[QUANT_PROFILES][QUANT_RANGES][COEF_BANDS] = { { - {91, 133, 139}, // dc, band 0 - {78, 122, 134}, // band 1 - {83, 127, 139}, // band 2 - {84, 117, 128}, // band 3 - {88, 117, 129}, // band 4 - {93, 122, 134}, // band 5 + { + {{91, 133, 139}, 11}, // dc, band 0 + {{78, 122, 134}, 12}, // band 1 + {{83, 127, 139}, 22}, // band 2 + {{84, 117, 128}, 18}, // band 3 + {{88, 117, 129}, 20}, // band 4 + {{93, 122, 134}, 21} // band 5 + }, { + {{91, 133, 139}, 11}, // dc, band 0 + {{78, 122, 134}, 12}, // band 1 + {{83, 127, 139}, 22}, // band 2 + {{84, 117, 128}, 18}, // band 3 + {{88, 117, 129}, 20}, // band 4 + {{93, 122, 134}, 21} // band 5 + } }, #if QUANT_PROFILES > 1 { - {86, 122, 134}, // dc, band 0 - {78, 122, 134}, // band 1 - {78, 122, 134}, // band 2 - {84, 122, 134}, // band 3 - {88, 122, 134}, // band 4 - {88, 122, 134}, // band 5 + { + {{86, 122, 134}, 6}, // dc, band 0 + {{78, 122, 134}, 15}, // band 1 + {{78, 122, 134}, 17}, // band 2 + {{84, 122, 134}, 22}, // band 3 + {{88, 122, 134}, 23}, // band 4 + {{88, 122, 134}, 23} // band 5 + }, { + {{86, 122, 134}, 6}, // dc, band 0 + {{78, 122, 134}, 15}, // band 1 + {{78, 122, 134}, 17}, // band 2 + {{84, 122, 134}, 22}, // band 3 + {{88, 122, 134}, 23}, // band 4 + {{88, 122, 134}, 23} // band 5 + } }, #if QUANT_PROFILES > 2 { - {86, 122, 134}, // dc, band 0 - {78, 122, 135}, // band 1 - {78, 122, 134}, // band 2 - {84, 122, 133}, // band 3 - {88, 122, 134}, // band 4 - {88, 122, 134}, // band 5 + { + {{86, 122, 134}, 6}, // dc, band 0 + {{78, 122, 135}, 14}, // band 1 + {{78, 122, 134}, 16}, // band 2 + {{84, 122, 133}, 22}, // band 3 + {{88, 122, 134}, 23}, // band 4 + {{88, 122, 134}, 27}, // band 5 + }, { + {{86, 122, 134}, 6}, // dc, band 0 + {{78, 122, 135}, 14}, // band 1 + {{78, 122, 134}, 16}, // band 2 + {{84, 122, 133}, 22}, // band 3 + {{88, 122, 134}, 23}, // band 4 + {{88, 122, 134}, 27}, // band 5 + } } #endif // QUANT_PROFILES > 2 #endif // QUANT_PROFILES > 1 }; -// dequantization offsets -static const uint8_t nuq_doff_lossless[COEF_BANDS] = {0, 0, 0, 0, 0, 0}; - -#if QUANT_PROFILES == 1 -static const uint8_t nuq_doff[QUANT_PROFILES][COEF_BANDS] = { - {11, 12, 22, 18, 20, 21} // dq_off_index = 0 -}; -#elif QUANT_PROFILES == 2 -static const uint8_t nuq_doff[QUANT_PROFILES][COEF_BANDS] = { - {11, 12, 22, 18, 20, 21}, // dq_off_index = 0 - {13, 20, 21, 27, 28, 29} // dq_off_index = 1 -}; -#else // QUANT_PROFILES == 3 -static const uint8_t nuq_doff[QUANT_PROFILES][COEF_BANDS] = { - {11, 12, 22, 18, 20, 21}, // dq_off_index = 0 - {6, 15, 17, 22, 23, 23}, // dq_off_index = 1 - {6, 14, 16, 22, 23, 27} // dq_off_index = 2 -}; -#endif // QUANT_PROFILES == x +static INLINE int qrange_from_qindex(int qindex) { + // return high quality (1) or low quality (0) + return qindex < 140 ? 1 : 0; +} -static const uint8_t *get_nuq_knots(int lossless, int band, int dq_off_index) { - if (lossless) - return nuq_knots_lossless[band]; +static const uint8_t *get_nuq_knots(int qindex, int band, int q_profile) { + if (!qindex) + return nuq_lossless[band].knots; else - return nuq_knots[dq_off_index][band]; + return nuq[q_profile][qrange_from_qindex(qindex)][band].knots; } -static INLINE int16_t quant_to_doff_fixed(int lossless, int band, - int dq_off_index) { - if (lossless) - return nuq_doff_lossless[band]; +static INLINE int16_t quant_to_doff_fixed(int qindex, int band, + int q_profile) { + if (!qindex) + return nuq_lossless[band].doff; else - return nuq_doff[dq_off_index][band]; + return nuq[q_profile][qrange_from_qindex(qindex)][band].doff; } // get cumulative bins -static INLINE void get_cuml_bins_nuq(int q, int lossless, int band, - tran_low_t *cuml_bins, int dq_off_index) { - const uint8_t *knots = get_nuq_knots(lossless, band, dq_off_index); +static INLINE void get_cuml_bins_nuq(int q, int qindex, int band, + tran_low_t *cuml_bins, int q_profile) { + const uint8_t *knots = get_nuq_knots(qindex, band, q_profile); int16_t cuml_knots[NUQ_KNOTS]; int i; cuml_knots[0] = knots[0]; @@ -112,36 +130,36 @@ static INLINE void get_cuml_bins_nuq(int q, int lossless, int band, cuml_bins[i] = ROUND_POWER_OF_TWO(cuml_knots[i] * q, 7); } -void get_dequant_val_nuq(int q, int lossless, int band, - tran_low_t *dq, tran_low_t *cuml_bins, - int dq_off_index) { - const uint8_t *knots = get_nuq_knots(lossless, band, dq_off_index); +void vp10_get_dequant_val_nuq(int q, int qindex, int band, + tran_low_t *dq, tran_low_t *cuml_bins, + int q_profile) { + const uint8_t *knots = get_nuq_knots(qindex, band, q_profile); tran_low_t cuml_bins_[NUQ_KNOTS], *cuml_bins_ptr; tran_low_t doff; int i; cuml_bins_ptr = (cuml_bins ? cuml_bins : cuml_bins_); - get_cuml_bins_nuq(q, lossless, band, cuml_bins_ptr, dq_off_index); + get_cuml_bins_nuq(q, qindex, band, cuml_bins_ptr, q_profile); dq[0] = 0; for (i = 1; i < NUQ_KNOTS; ++i) { - doff = quant_to_doff_fixed(lossless, band, dq_off_index); + doff = quant_to_doff_fixed(qindex, band, q_profile); doff = ROUND_POWER_OF_TWO(doff * knots[i], 7); dq[i] = cuml_bins_ptr[i - 1] + - ROUND_POWER_OF_TWO((knots[i] - doff * 2) * q, 8); + ROUND_POWER_OF_TWO((knots[i] - doff * 2) * q, 8); } - doff = quant_to_doff_fixed(lossless, band, dq_off_index); + doff = quant_to_doff_fixed(qindex, band, q_profile); dq[NUQ_KNOTS] = cuml_bins_ptr[NUQ_KNOTS - 1] + ROUND_POWER_OF_TWO((64 - doff) * q, 7); } -tran_low_t dequant_abscoeff_nuq(int v, int q, const tran_low_t *dq) { +tran_low_t vp10_dequant_abscoeff_nuq(int v, int q, const tran_low_t *dq) { if (v <= NUQ_KNOTS) return dq[v]; else return dq[NUQ_KNOTS] + (v - NUQ_KNOTS) * q; } -tran_low_t dequant_coeff_nuq(int v, int q, const tran_low_t *dq) { - tran_low_t dqmag = dequant_abscoeff_nuq(abs(v), q, dq); +tran_low_t vp10_dequant_coeff_nuq(int v, int q, const tran_low_t *dq) { + tran_low_t dqmag = vp10_dequant_abscoeff_nuq(abs(v), q, dq); return (v < 0 ? -dqmag : dqmag); } #endif // CONFIG_NEW_QUANT diff --git a/vp10/common/quant_common.h b/vp10/common/quant_common.h index c184b00e9..d95579695 100644 --- a/vp10/common/quant_common.h +++ b/vp10/common/quant_common.h @@ -30,14 +30,22 @@ int vp10_get_qindex(const struct segmentation *seg, int segment_id, int base_qindex); #if CONFIG_NEW_QUANT -#define NUQ_KNOTS 3 + +#define QUANT_PROFILES 3 +#define QUANT_RANGES 2 +#define NUQ_KNOTS 3 + typedef tran_low_t dequant_val_type_nuq[NUQ_KNOTS + 1]; typedef tran_low_t cuml_bins_type_nuq[NUQ_KNOTS]; -void get_dequant_val_nuq(int q, int lossless, int band, - tran_low_t *dq, tran_low_t *cuml_bins, - int dq_off_index); -tran_low_t dequant_abscoeff_nuq(int v, int q, const tran_low_t *dq); -tran_low_t dequant_coeff_nuq(int v, int q, const tran_low_t *dq); +void vp10_get_dequant_val_nuq(int q, int qindex, int band, + tran_low_t *dq, tran_low_t *cuml_bins, + int dq_off_index); +tran_low_t vp10_dequant_abscoeff_nuq(int v, int q, const tran_low_t *dq); +tran_low_t vp10_dequant_coeff_nuq(int v, int q, const tran_low_t *dq); + +static INLINE int get_dq_profile_from_ctx(int q_ctx) { + return VPXMIN(q_ctx, QUANT_PROFILES - 1); +} #endif // CONFIG_NEW_QUANT #ifdef __cplusplus diff --git a/vp10/decoder/decodeframe.c b/vp10/decoder/decodeframe.c index 5ba707bca..c414b097f 100644 --- a/vp10/decoder/decodeframe.c +++ b/vp10/decoder/decodeframe.c @@ -2093,11 +2093,11 @@ static void setup_segmentation_dequant(VP10_COMMON *const cm) { #if CONFIG_NEW_QUANT for (dq = 0; dq < QUANT_PROFILES; dq ++) { for (b = 0; b < COEF_BANDS; ++b) { - get_dequant_val_nuq( - cm->y_dequant[i][b != 0], qindex == 0, b, + vp10_get_dequant_val_nuq( + cm->y_dequant[i][b != 0], qindex, b, cm->y_dequant_nuq[i][dq][b], NULL, dq); - get_dequant_val_nuq( - cm->uv_dequant[i][b != 0], qindex == 0, b, + vp10_get_dequant_val_nuq( + cm->uv_dequant[i][b != 0], qindex, b, cm->uv_dequant_nuq[i][dq][b], NULL, dq); } } @@ -2116,11 +2116,11 @@ static void setup_segmentation_dequant(VP10_COMMON *const cm) { #if CONFIG_NEW_QUANT for (dq = 0; dq < QUANT_PROFILES; dq ++) { for (b = 0; b < COEF_BANDS; ++b) { - get_dequant_val_nuq( - cm->y_dequant[0][b != 0], qindex == 0, b, + vp10_get_dequant_val_nuq( + cm->y_dequant[0][b != 0], qindex, b, cm->y_dequant_nuq[0][dq][b], NULL, dq); - get_dequant_val_nuq( - cm->uv_dequant[0][b != 0], qindex == 0, b, + vp10_get_dequant_val_nuq( + cm->uv_dequant[0][b != 0], qindex, b, cm->uv_dequant_nuq[0][dq][b], NULL, dq); } } diff --git a/vp10/decoder/detokenize.c b/vp10/decoder/detokenize.c index 669c9f4d1..cc3b18bb4 100644 --- a/vp10/decoder/detokenize.c +++ b/vp10/decoder/detokenize.c @@ -205,7 +205,7 @@ static int decode_coefs(const MACROBLOCKD *xd, } } #if CONFIG_NEW_QUANT - v = dequant_abscoeff_nuq(val, dqv, dqv_val); + v = vp10_dequant_abscoeff_nuq(val, dqv, dqv_val); v = dq_shift ? ROUND_POWER_OF_TWO(v, dq_shift) : v; #else v = (val * dqv) >> dq_shift; @@ -389,7 +389,7 @@ static int decode_coefs_ans(const MACROBLOCKD *const xd, } break; } #if CONFIG_NEW_QUANT - v = dequant_abscoeff_nuq(val, dqv, dqv_val); + v = vp10_dequant_abscoeff_nuq(val, dqv, dqv_val); v = dq_shift ? ROUND_POWER_OF_TWO(v, dq_shift) : v; #else v = (val * dqv) >> dq_shift; diff --git a/vp10/encoder/encodemb.c b/vp10/encoder/encodemb.c index 65493a094..8fc6fb088 100644 --- a/vp10/encoder/encodemb.c +++ b/vp10/encoder/encodemb.c @@ -207,10 +207,10 @@ int vp10_optimize_b(MACROBLOCK *mb, int plane, int block, } else { #if CONFIG_NEW_QUANT shortcut = ( - (dequant_abscoeff_nuq( + (vp10_dequant_abscoeff_nuq( abs(x), dequant_ptr[rc != 0], dequant_val[band_translate[i]]) > (abs(coeff[rc]) << shift)) && - (dequant_abscoeff_nuq( + (vp10_dequant_abscoeff_nuq( abs(x) - 1, dequant_ptr[rc != 0], dequant_val[band_translate[i]]) < (abs(coeff[rc]) << shift))); #else // CONFIG_NEW_QUANT @@ -280,7 +280,7 @@ int vp10_optimize_b(MACROBLOCK *mb, int plane, int block, } #if CONFIG_NEW_QUANT - dx = dequant_coeff_nuq( + dx = vp10_dequant_coeff_nuq( x, dequant_ptr[rc != 0], dequant_val[band_translate[i]]) - (coeff[rc] << shift); #if CONFIG_VP9_HIGHBITDEPTH @@ -378,8 +378,8 @@ int vp10_optimize_b(MACROBLOCK *mb, int plane, int block, dqcoeff[rc] = tokens[i][best].dqc; #if CONFIG_NEW_QUANT - dqcoeff[rc] = dequant_abscoeff_nuq(abs(x), dequant_ptr[rc != 0], - dequant_val[band_translate[i]]); + dqcoeff[rc] = vp10_dequant_abscoeff_nuq(abs(x), dequant_ptr[rc != 0], + dequant_val[band_translate[i]]); if (shift) dqcoeff[rc] = ROUND_POWER_OF_TWO(dqcoeff[rc], shift); if (x < 0) dqcoeff[rc] = -dqcoeff[rc]; #endif // CONFIG_NEW_QUANT diff --git a/vp10/encoder/quantize.c b/vp10/encoder/quantize.c index 3b2ace6a0..8792db237 100644 --- a/vp10/encoder/quantize.c +++ b/vp10/encoder/quantize.c @@ -48,7 +48,7 @@ static INLINE int quantize_coeff_nuq(const tran_low_t coeffv, } if (q) { *dqcoeff_ptr = - dequant_abscoeff_nuq(q, dequant, dequant_val); + vp10_dequant_abscoeff_nuq(q, dequant, dequant_val); *qcoeff_ptr = (q ^ coeff_sign) - coeff_sign; *dqcoeff_ptr = *qcoeff_ptr < 0 ? -*dqcoeff_ptr : *dqcoeff_ptr; } else { @@ -85,9 +85,9 @@ static INLINE int quantize_coeff_bigtx_nuq(const tran_low_t coeffv, } if (q) { *dqcoeff_ptr = - ROUND_POWER_OF_TWO(dequant_abscoeff_nuq(q, dequant, dequant_val), + ROUND_POWER_OF_TWO(vp10_dequant_abscoeff_nuq(q, dequant, dequant_val), 1 + logsizeby32); - // *dqcoeff_ptr = dequant_abscoeff_nuq(q, dequant, dequant_val) >> + // *dqcoeff_ptr = vp10_dequant_abscoeff_nuq(q, dequant, dequant_val) >> // (1 + logsizeby32); *qcoeff_ptr = (q ^ coeff_sign) - coeff_sign; *dqcoeff_ptr = *qcoeff_ptr < 0 ? -*dqcoeff_ptr : *dqcoeff_ptr; @@ -122,7 +122,7 @@ static INLINE int quantize_coeff_fp_nuq(const tran_low_t coeffv, } if (q) { *dqcoeff_ptr = - dequant_abscoeff_nuq(q, dequant, dequant_val); + vp10_dequant_abscoeff_nuq(q, dequant, dequant_val); *qcoeff_ptr = (q ^ coeff_sign) - coeff_sign; *dqcoeff_ptr = *qcoeff_ptr < 0 ? -*dqcoeff_ptr : *dqcoeff_ptr; } else { @@ -159,9 +159,9 @@ static INLINE int quantize_coeff_bigtx_fp_nuq(const tran_low_t coeffv, } if (q) { *dqcoeff_ptr = - ROUND_POWER_OF_TWO(dequant_abscoeff_nuq(q, dequant, dequant_val), + ROUND_POWER_OF_TWO(vp10_dequant_abscoeff_nuq(q, dequant, dequant_val), 1 + logsizeby32); - // *dqcoeff_ptr = dequant_abscoeff_nuq(q, dequant, dequant_val) >> + // *dqcoeff_ptr = vp10_dequant_abscoeff_nuq(q, dequant, dequant_val) >> // (1 + logsizeby32); *qcoeff_ptr = (q ^ coeff_sign) - coeff_sign; *dqcoeff_ptr = *qcoeff_ptr < 0 ? -*dqcoeff_ptr : *dqcoeff_ptr; @@ -557,7 +557,7 @@ static INLINE int highbd_quantize_coeff_nuq(const tran_low_t coeffv, } if (q) { *dqcoeff_ptr = - dequant_abscoeff_nuq(q, dequant, dequant_val); + vp10_dequant_abscoeff_nuq(q, dequant, dequant_val); *qcoeff_ptr = (q ^ coeff_sign) - coeff_sign; *dqcoeff_ptr = *qcoeff_ptr < 0 ? -*dqcoeff_ptr : *dqcoeff_ptr; } else { @@ -591,7 +591,7 @@ static INLINE int highbd_quantize_coeff_fp_nuq(const tran_low_t coeffv, } if (q) { *dqcoeff_ptr = - dequant_abscoeff_nuq(q, dequant, dequant_val); + vp10_dequant_abscoeff_nuq(q, dequant, dequant_val); *qcoeff_ptr = (q ^ coeff_sign) - coeff_sign; *dqcoeff_ptr = *qcoeff_ptr < 0 ? -*dqcoeff_ptr : *dqcoeff_ptr; } else { @@ -629,7 +629,7 @@ static INLINE int highbd_quantize_coeff_bigtx_fp_nuq( } if (q) { *dqcoeff_ptr = - ROUND_POWER_OF_TWO(dequant_abscoeff_nuq(q, dequant, dequant_val), + ROUND_POWER_OF_TWO(vp10_dequant_abscoeff_nuq(q, dequant, dequant_val), 1 + logsizeby32); *qcoeff_ptr = (q ^ coeff_sign) - coeff_sign; *dqcoeff_ptr = *qcoeff_ptr < 0 ? -*dqcoeff_ptr : *dqcoeff_ptr; @@ -668,7 +668,7 @@ static INLINE int highbd_quantize_coeff_bigtx_nuq(const tran_low_t coeffv, } if (q) { *dqcoeff_ptr = - ROUND_POWER_OF_TWO(dequant_abscoeff_nuq(q, dequant, dequant_val), + ROUND_POWER_OF_TWO(vp10_dequant_abscoeff_nuq(q, dequant, dequant_val), 1 + logsizeby32); *qcoeff_ptr = (q ^ coeff_sign) - coeff_sign; *dqcoeff_ptr = *qcoeff_ptr < 0 ? -*dqcoeff_ptr : *dqcoeff_ptr; @@ -1228,12 +1228,12 @@ void vp10_init_quantizer(VP10_COMP *cpi) { for (i = 0; i < COEF_BANDS; i++) { const int quant = cpi->y_dequant[q][i != 0]; const int uvquant = cpi->uv_dequant[q][i != 0]; - get_dequant_val_nuq(quant, q == 0, i, - cpi->y_dequant_val_nuq[dq][q][i], - quants->y_cuml_bins_nuq[dq][q][i], dq); - get_dequant_val_nuq(uvquant, q == 0, i, - cpi->uv_dequant_val_nuq[dq][q][i], - quants->uv_cuml_bins_nuq[dq][q][i], dq); + vp10_get_dequant_val_nuq(quant, q, i, + cpi->y_dequant_val_nuq[dq][q][i], + quants->y_cuml_bins_nuq[dq][q][i], dq); + vp10_get_dequant_val_nuq(uvquant, q, i, + cpi->uv_dequant_val_nuq[dq][q][i], + quants->uv_cuml_bins_nuq[dq][q][i], dq); } } #endif // CONFIG_NEW_QUANT -- 2.50.1