Decouple encoder side x0 parameter from dq_type
The x0 parameter can now be chosen on the encoder side
independently of the dq offset.
Change-Id: I4a63bae6ae81d5a7f65c53efe1b1ecd713355b01
diff --git a/av1/common/quant_common.c b/av1/common/quant_common.c
index 27c9f8a..12e0f03 100644
--- a/av1/common/quant_common.c
+++ b/av1/common/quant_common.c
@@ -22,111 +22,77 @@
// nominal quantization step. The width is only
// for one side of zero, so the actual width is twice that.
// These are needed only on the encoder side.
-static const uint8_t x0_nuq[QUANT_PROFILES][2] = {
+static const uint8_t x0_nuq[X0_PROFILES][2] = {
{
// lossless
64, 64, // dc, ac
},
- // dq_type = 1
+ // optimize = 1
{
- // Y/intra, dq_type 1, low quality
+ // Y/intra, optimize 1, low quality
64, 64, // dc, ac
},
{
- // Y/intra, dq_type 1, high quality
+ // Y/intra, optimize 1, high quality
64, 64, // dc, ac
},
{
- // UV/intra, dq_type 1, low quality
+ // UV/intra, optimize 1, low quality
64, 64, // dc, ac
},
{
- // UV/intra, dq_type 1, high quality
+ // UV/intra, optimize 1, high quality
64, 64, // dc, ac
},
{
- // Y/inter, dq_type 1, low quality
+ // Y/inter, optimize 1, low quality
64, 64, // dc, ac
},
{
- // Y/inter, dq_type 1, high quality
+ // Y/inter, optimize 1, high quality
64, 64, // dc, ac
},
{
- // UV/inter, dq_type 1, low quality
+ // UV/inter, optimize 1, low quality
64, 64, // dc, ac
},
{
- // UV/inter, dq_type 1, high quality
+ // UV/inter, optimize 1, high quality
64, 64, // dc, ac
},
- // dq_type = 2
+ // optimize = 0
{
- // Y/intra, dq_type 2, low quality
- 72, 72, // dc, ac
- },
- {
- // Y/intra, dq_type 2, high quality
- 72, 72, // dc, ac
- },
- {
- // UV/intra, dq_type 2, low quality
- 72, 72, // dc, ac
- },
- {
- // UV/intra, dq_type 2, high quality
- 72, 72, // dc, ac
- },
- {
- // Y/inter, dq_type 2, low quality
- 72, 72, // dc, ac
- },
- {
- // Y/inter, dq_type 2, high quality
- 72, 72, // dc, ac
- },
- {
- // UV/inter, dq_type 2, low quality
- 72, 72, // dc, ac
- },
- {
- // UV/inter, dq_type 2, high quality
- 72, 72, // dc, ac
- },
-
- // dq_type = 3
- {
- // Y/intra, dq_type 3, low quality
+ // Y/intra, optimize 0, low quality
80, 80, // dc, ac
},
{
- // Y/intra, dq_type 3, high quality
+ // Y/intra, optimize 0, high quality
82, 82, // dc, ac
},
{
- // UV/intra, dq_type 3, low quality
+ // UV/intra, optimize 0, low quality
80, 80, // dc, ac
},
{
- // UV/intra, dq_type 3, high quality
+ // UV/intra, optimize 0, high quality
82, 82, // dc, ac
},
{
- // Y/inter, dq_type 3, low quality
+ // Y/inter, optimize 0, low quality
80, 80, // dc, ac
},
{
- // Y/inter, dq_type 3, high quality
+ // Y/inter, optimize 0, high quality
82, 82, // dc, ac
},
{
- // UV/inter, dq_type 3, low quality
+ // UV/inter, optimize 0, low quality
80, 80, // dc, ac
},
{
- // UV/inter, dq_type 3, high quality
+ // UV/inter, optimize 0, high quality
82, 82, // dc, ac
},
};
@@ -241,27 +207,22 @@
},
};
-static INLINE uint8_t get_nuq_zbin(int is_ac_coeff, int q_profile) {
- return x0_nuq[q_profile][is_ac_coeff];
+// Encoder only
+static INLINE uint8_t get_nuq_zbin(int is_ac_coeff, int x0_profile) {
+ return x0_nuq[x0_profile][is_ac_coeff];
+}
+
+// Encoder only
+void av1_get_cuml_bins_nuq(int q, int is_ac_coeff, tran_low_t *zbin_width,
+ int x0_profile) {
+ const uint8_t zbin = get_nuq_zbin(is_ac_coeff, x0_profile);
+ zbin_width[0] = ROUND_POWER_OF_TWO(zbin * q, 7);
}
static INLINE int8_t quant_to_doff_fixed(int is_ac_coeff, int q_profile) {
return doff_nuq[q_profile][is_ac_coeff];
}
-// get zero bin width
-static INLINE void get_cuml_bins_nuq(int q, int is_ac_coeff,
- tran_low_t *zbin_width, int q_profile) {
- const uint8_t zbin = get_nuq_zbin(is_ac_coeff, q_profile);
- zbin_width[0] = ROUND_POWER_OF_TWO(zbin * q, 7);
-}
-
-void av1_get_cuml_bins_nuq(int q, int is_ac_coeff, tran_low_t *cuml_bins,
- int q_profile) {
- // Get the quantization boundary for the zero bin
- get_cuml_bins_nuq(q, is_ac_coeff, cuml_bins, q_profile);
-}
-
void av1_get_dequant_val_nuq(int q, int is_ac_coeff, tran_low_t *dq,
int q_profile) {
// Get the dequantization offset that will be applied to all non-zero bins.
diff --git a/av1/common/quant_common.h b/av1/common/quant_common.h
index 7cca007..ada7c67 100644
--- a/av1/common/quant_common.h
+++ b/av1/common/quant_common.h
@@ -64,6 +64,9 @@
#define QUANT_RANGES 2
#define NUQ_KNOTS 1
+// Encoder only
+#define X0_PROFILES (2 * 8 + 1)
+
// dequant_val_type_nuq needs space for the 3 possible shift values
// for different tx sizes
typedef tran_low_t dequant_val_type_nuq[NUQ_KNOTS * 3];
@@ -107,6 +110,26 @@
return dq_profile_lookup[dqtype][is_inter][plane_type]
[qindex_to_qrange(qindex)];
}
+
+// Encoder only
+static INLINE int get_x0_profile(int optimize, int qindex, int is_inter,
+ PLANE_TYPE plane_type) {
+ // intra/inter, Y/UV, ctx, qrange
+ static const int x0_profile_lookup[2][REF_TYPES][PLANE_TYPES][QUANT_RANGES] =
+ {
+ {
+ { { 1, 2 }, { 3, 4 } }, // intra: Y, UV
+ { { 5, 6 }, { 7, 8 } }, // inter: Y, UV
+ },
+ {
+ { { 9, 10 }, { 11, 12 } }, // intra: Y, UV
+ { { 13, 14 }, { 15, 16 } }, // inter: Y, UV
+ },
+ };
+ if (!qindex) return 0; // lossless
+ return x0_profile_lookup[!optimize][is_inter][plane_type]
+ [qindex_to_qrange(qindex)];
+}
#endif // CONFIG_NEW_QUANT
#ifdef __cplusplus
diff --git a/av1/encoder/av1_quantize.c b/av1/encoder/av1_quantize.c
index 6711932..9c923e2 100644
--- a/av1/encoder/av1_quantize.c
+++ b/av1/encoder/av1_quantize.c
@@ -711,13 +711,14 @@
const QUANT_PARAM *qparam) {
// obsolete skip_block
const int skip_block = 0;
- int dq = qparam->dq;
+ const int dq = qparam->dq;
+ const int x0 = qparam->x0;
switch (qparam->log_scale) {
case 0:
quantize_nuq(coeff_ptr, n_coeffs, skip_block, p->zbin_QTX, p->quant_QTX,
p->quant_shift_QTX, p->dequant_QTX,
- (const cuml_bins_type_nuq *)p->cuml_bins_nuq[dq],
+ (const cuml_bins_type_nuq *)p->cuml_bins_nuq[x0],
(const dequant_val_type_nuq *)p->dequant_val_nuq_QTX[dq],
qcoeff_ptr, dqcoeff_ptr, eob_ptr, sc->scan);
break;
@@ -725,7 +726,7 @@
quantize_32x32_nuq(
coeff_ptr, n_coeffs, skip_block, p->zbin_QTX, p->quant_QTX,
p->quant_shift_QTX, p->dequant_QTX,
- (const cuml_bins_type_nuq *)p->cuml_bins_nuq[dq],
+ (const cuml_bins_type_nuq *)p->cuml_bins_nuq[x0],
(const dequant_val_type_nuq *)p->dequant_val_nuq_QTX[dq], qcoeff_ptr,
dqcoeff_ptr, eob_ptr, sc->scan);
break;
@@ -734,7 +735,7 @@
quantize_64x64_nuq(
coeff_ptr, n_coeffs, skip_block, p->zbin_QTX, p->quant_QTX,
p->quant_shift_QTX, p->dequant_QTX,
- (const cuml_bins_type_nuq *)p->cuml_bins_nuq[dq],
+ (const cuml_bins_type_nuq *)p->cuml_bins_nuq[x0],
(const dequant_val_type_nuq *)p->dequant_val_nuq_QTX[dq], qcoeff_ptr,
dqcoeff_ptr, eob_ptr, sc->scan);
break;
@@ -750,20 +751,21 @@
const QUANT_PARAM *qparam) {
// obsolete skip_block
const int skip_block = 0;
- int dq = qparam->dq;
+ const int dq = qparam->dq;
+ const int x0 = qparam->x0;
switch (qparam->log_scale) {
case 0:
quantize_fp_nuq(coeff_ptr, n_coeffs, skip_block, p->quant_fp_QTX,
p->dequant_QTX,
- (const cuml_bins_type_nuq *)p->cuml_bins_nuq[dq],
+ (const cuml_bins_type_nuq *)p->cuml_bins_nuq[x0],
(const dequant_val_type_nuq *)p->dequant_val_nuq_QTX[dq],
qcoeff_ptr, dqcoeff_ptr, eob_ptr, sc->scan);
break;
case 1:
quantize_32x32_fp_nuq(
coeff_ptr, n_coeffs, skip_block, p->quant_fp_QTX, p->dequant_QTX,
- (const cuml_bins_type_nuq *)p->cuml_bins_nuq[dq],
+ (const cuml_bins_type_nuq *)p->cuml_bins_nuq[x0],
(const dequant_val_type_nuq *)p->dequant_val_nuq_QTX[dq], qcoeff_ptr,
dqcoeff_ptr, eob_ptr, sc->scan);
break;
@@ -771,7 +773,7 @@
case 2:
quantize_64x64_fp_nuq(
coeff_ptr, n_coeffs, skip_block, p->quant_fp_QTX, p->dequant_QTX,
- (const cuml_bins_type_nuq *)p->cuml_bins_nuq[dq],
+ (const cuml_bins_type_nuq *)p->cuml_bins_nuq[x0],
(const dequant_val_type_nuq *)p->dequant_val_nuq_QTX[dq], qcoeff_ptr,
dqcoeff_ptr, eob_ptr, sc->scan);
break;
@@ -787,27 +789,28 @@
const QUANT_PARAM *qparam) {
// obsolete skip_block
const int skip_block = 0;
- int dq = qparam->dq;
+ const int dq = qparam->dq;
+ const int x0 = qparam->x0;
(void)sc;
switch (qparam->log_scale) {
case 0:
quantize_dc_fp_nuq(coeff_ptr, n_coeffs, skip_block, p->quant_fp_QTX[0],
- p->dequant_QTX[0], p->cuml_bins_nuq[dq][0],
+ p->dequant_QTX[0], p->cuml_bins_nuq[x0][0],
p->dequant_val_nuq_QTX[dq][0], qcoeff_ptr, dqcoeff_ptr,
eob_ptr);
break;
case 1:
quantize_dc_32x32_fp_nuq(
coeff_ptr, n_coeffs, skip_block, p->quant_fp_QTX[0],
- p->dequant_QTX[0], p->cuml_bins_nuq[dq][0],
+ p->dequant_QTX[0], p->cuml_bins_nuq[x0][0],
p->dequant_val_nuq_QTX[dq][0], qcoeff_ptr, dqcoeff_ptr, eob_ptr);
break;
#if CONFIG_TX64X64
case 2:
quantize_dc_64x64_fp_nuq(
coeff_ptr, n_coeffs, skip_block, p->quant_fp_QTX[0],
- p->dequant_QTX[0], p->cuml_bins_nuq[dq][0],
+ p->dequant_QTX[0], p->cuml_bins_nuq[x0][0],
p->dequant_val_nuq_QTX[dq][0], qcoeff_ptr, dqcoeff_ptr, eob_ptr);
break;
#endif // CONFIG_TX64X64
@@ -1338,13 +1341,14 @@
// obsolete skip_block
const int skip_block = 0;
const int dq = qparam->dq;
+ const int x0 = qparam->x0;
switch (qparam->log_scale) {
case 0:
highbd_quantize_nuq(
coeff_ptr, n_coeffs, skip_block, p->zbin_QTX, p->quant_QTX,
p->quant_shift_QTX, p->dequant_QTX,
- (const cuml_bins_type_nuq *)p->cuml_bins_nuq[dq],
+ (const cuml_bins_type_nuq *)p->cuml_bins_nuq[x0],
(const dequant_val_type_nuq *)p->dequant_val_nuq_QTX[dq], qcoeff_ptr,
dqcoeff_ptr, eob_ptr, sc->scan);
break;
@@ -1352,7 +1356,7 @@
highbd_quantize_32x32_nuq(
coeff_ptr, n_coeffs, skip_block, p->zbin_QTX, p->quant_QTX,
p->quant_shift_QTX, p->dequant_QTX,
- (const cuml_bins_type_nuq *)p->cuml_bins_nuq[dq],
+ (const cuml_bins_type_nuq *)p->cuml_bins_nuq[x0],
(const dequant_val_type_nuq *)p->dequant_val_nuq_QTX[dq], qcoeff_ptr,
dqcoeff_ptr, eob_ptr, sc->scan);
break;
@@ -1361,7 +1365,7 @@
highbd_quantize_64x64_nuq(
coeff_ptr, n_coeffs, skip_block, p->zbin_QTX, p->quant_QTX,
p->quant_shift_QTX, p->dequant_QTX,
- (const cuml_bins_type_nuq *)p->cuml_bins_nuq[dq],
+ (const cuml_bins_type_nuq *)p->cuml_bins_nuq[x0],
(const dequant_val_type_nuq *)p->dequant_val_nuq_QTX[dq], qcoeff_ptr,
dqcoeff_ptr, eob_ptr, sc->scan);
break;
@@ -1377,19 +1381,20 @@
// obsolete skip_block
const int skip_block = 0;
const int dq = qparam->dq;
+ const int x0 = qparam->x0;
switch (qparam->log_scale) {
case 0:
highbd_quantize_fp_nuq(
coeff_ptr, n_coeffs, skip_block, p->quant_fp_QTX, p->dequant_QTX,
- (const cuml_bins_type_nuq *)p->cuml_bins_nuq[dq],
+ (const cuml_bins_type_nuq *)p->cuml_bins_nuq[x0],
(const dequant_val_type_nuq *)p->dequant_val_nuq_QTX[dq], qcoeff_ptr,
dqcoeff_ptr, eob_ptr, sc->scan);
break;
case 1:
highbd_quantize_32x32_fp_nuq(
coeff_ptr, n_coeffs, skip_block, p->quant_fp_QTX, p->dequant_QTX,
- (const cuml_bins_type_nuq *)p->cuml_bins_nuq[dq],
+ (const cuml_bins_type_nuq *)p->cuml_bins_nuq[x0],
(const dequant_val_type_nuq *)p->dequant_val_nuq_QTX[dq], qcoeff_ptr,
dqcoeff_ptr, eob_ptr, sc->scan);
break;
@@ -1397,7 +1402,7 @@
case 2:
highbd_quantize_64x64_fp_nuq(
coeff_ptr, n_coeffs, skip_block, p->quant_fp_QTX, p->dequant_QTX,
- (const cuml_bins_type_nuq *)p->cuml_bins_nuq[dq],
+ (const cuml_bins_type_nuq *)p->cuml_bins_nuq[x0],
(const dequant_val_type_nuq *)p->dequant_val_nuq_QTX[dq], qcoeff_ptr,
dqcoeff_ptr, eob_ptr, sc->scan);
break;
@@ -1413,26 +1418,27 @@
// obsolete skip_block
const int skip_block = 0;
const int dq = qparam->dq;
+ const int x0 = qparam->x0;
(void)sc;
switch (qparam->log_scale) {
case 0:
highbd_quantize_dc_fp_nuq(
coeff_ptr, n_coeffs, skip_block, p->quant_fp_QTX[0],
- p->dequant_QTX[0], p->cuml_bins_nuq[dq][0],
+ p->dequant_QTX[0], p->cuml_bins_nuq[x0][0],
p->dequant_val_nuq_QTX[dq][0], qcoeff_ptr, dqcoeff_ptr, eob_ptr);
break;
case 1:
highbd_quantize_dc_32x32_fp_nuq(
coeff_ptr, n_coeffs, skip_block, p->quant_fp_QTX[0],
- p->dequant_QTX[0], p->cuml_bins_nuq[dq][0],
+ p->dequant_QTX[0], p->cuml_bins_nuq[x0][0],
p->dequant_val_nuq_QTX[dq][0], qcoeff_ptr, dqcoeff_ptr, eob_ptr);
break;
#if CONFIG_TX64X64
case 2:
highbd_quantize_dc_64x64_fp_nuq(
coeff_ptr, n_coeffs, skip_block, p->quant_fp_QTX[0],
- p->dequant_QTX[0], p->cuml_bins_nuq[dq][0],
+ p->dequant_QTX[0], p->cuml_bins_nuq[x0][0],
p->dequant_val_nuq_QTX[dq][0], qcoeff_ptr, dqcoeff_ptr, eob_ptr);
break;
#endif // CONFIG_TX64X64
@@ -1534,6 +1540,21 @@
}
#if CONFIG_NEW_QUANT
+ int x0;
+ for (x0 = 0; x0 < X0_PROFILES; x0++) {
+ // DC and AC coefs
+ for (i = 0; i < 2; i++) {
+ const int y_quant = deq->y_dequant_QTX[q][i != 0];
+ const int u_quant = deq->u_dequant_QTX[q][i != 0];
+ const int v_quant = deq->v_dequant_QTX[q][i != 0];
+ av1_get_cuml_bins_nuq(y_quant, i, quants->y_cuml_bins_nuq[x0][q][i],
+ x0);
+ av1_get_cuml_bins_nuq(u_quant, i, quants->u_cuml_bins_nuq[x0][q][i],
+ x0);
+ av1_get_cuml_bins_nuq(v_quant, i, quants->v_cuml_bins_nuq[x0][q][i],
+ x0);
+ }
+ }
int dq;
for (dq = 0; dq < QUANT_PROFILES; dq++) {
// DC and AC coefs
@@ -1547,12 +1568,6 @@
deq->u_dequant_val_nuq_QTX[dq][q][i], dq);
av1_get_dequant_val_nuq(v_quant, i,
deq->v_dequant_val_nuq_QTX[dq][q][i], dq);
- av1_get_cuml_bins_nuq(y_quant, i, quants->y_cuml_bins_nuq[dq][q][i],
- dq);
- av1_get_cuml_bins_nuq(u_quant, i, quants->u_cuml_bins_nuq[dq][q][i],
- dq);
- av1_get_cuml_bins_nuq(v_quant, i, quants->v_cuml_bins_nuq[dq][q][i],
- dq);
}
}
#endif // CONFIG_NEW_QUANT
@@ -1624,9 +1639,6 @@
? NUM_QM_LEVELS - 1
: aom_get_qmlevel(cm->base_qindex, minqm, maxqm);
#endif
-#if CONFIG_NEW_QUANT
- int dq;
-#endif
// Y
x->plane[0].quant_QTX = quants->y_quant[qindex];
@@ -1644,8 +1656,10 @@
#endif
xd->plane[0].dequant_Q3 = cpi->dequants.y_dequant_Q3[qindex];
#if CONFIG_NEW_QUANT
- for (dq = 0; dq < QUANT_PROFILES; dq++) {
- x->plane[0].cuml_bins_nuq[dq] = quants->y_cuml_bins_nuq[dq][qindex];
+ for (int x0 = 0; x0 < X0_PROFILES; x0++) {
+ x->plane[0].cuml_bins_nuq[x0] = quants->y_cuml_bins_nuq[x0][qindex];
+ }
+ for (int dq = 0; dq < QUANT_PROFILES; dq++) {
x->plane[0].dequant_val_nuq_QTX[dq] =
cpi->dequants.y_dequant_val_nuq_QTX[dq][qindex];
}
@@ -1669,8 +1683,10 @@
x->plane[1].dequant_QTX = cpi->dequants.u_dequant_QTX[qindex];
xd->plane[1].dequant_Q3 = cpi->dequants.u_dequant_Q3[qindex];
#if CONFIG_NEW_QUANT
- for (dq = 0; dq < QUANT_PROFILES; dq++) {
- x->plane[1].cuml_bins_nuq[dq] = quants->u_cuml_bins_nuq[dq][qindex];
+ for (int x0 = 0; x0 < X0_PROFILES; x0++) {
+ x->plane[1].cuml_bins_nuq[x0] = quants->u_cuml_bins_nuq[x0][qindex];
+ }
+ for (int dq = 0; dq < QUANT_PROFILES; dq++) {
x->plane[1].dequant_val_nuq_QTX[dq] =
cpi->dequants.u_dequant_val_nuq_QTX[dq][qindex];
}
@@ -1694,8 +1710,10 @@
x->plane[2].dequant_QTX = cpi->dequants.v_dequant_QTX[qindex];
xd->plane[2].dequant_Q3 = cpi->dequants.v_dequant_Q3[qindex];
#if CONFIG_NEW_QUANT
- for (dq = 0; dq < QUANT_PROFILES; dq++) {
- x->plane[2].cuml_bins_nuq[dq] = quants->v_cuml_bins_nuq[dq][qindex];
+ for (int x0 = 0; x0 < X0_PROFILES; x0++) {
+ x->plane[2].cuml_bins_nuq[x0] = quants->v_cuml_bins_nuq[x0][qindex];
+ }
+ for (int dq = 0; dq < QUANT_PROFILES; dq++) {
x->plane[2].dequant_val_nuq_QTX[dq] =
cpi->dequants.v_dequant_val_nuq_QTX[dq][qindex];
}
diff --git a/av1/encoder/av1_quantize.h b/av1/encoder/av1_quantize.h
index f08022f..349ace4 100644
--- a/av1/encoder/av1_quantize.h
+++ b/av1/encoder/av1_quantize.h
@@ -26,6 +26,7 @@
TX_SIZE tx_size;
#if CONFIG_NEW_QUANT
int dq;
+ int x0;
#endif // CONFIG_NEW_QUANT
#if CONFIG_AOM_QM
const qm_val_t *qmatrix;
diff --git a/av1/encoder/block.h b/av1/encoder/block.h
index 7cb8d54..8826a0c 100644
--- a/av1/encoder/block.h
+++ b/av1/encoder/block.h
@@ -52,7 +52,7 @@
const int16_t *round_QTX;
const int16_t *dequant_QTX;
#if CONFIG_NEW_QUANT
- const cuml_bins_type_nuq *cuml_bins_nuq[QUANT_PROFILES];
+ const cuml_bins_type_nuq *cuml_bins_nuq[X0_PROFILES];
const dequant_val_type_nuq *dequant_val_nuq_QTX[QUANT_PROFILES];
#endif // CONFIG_NEW_QUANT
} MACROBLOCK_PLANE;
diff --git a/av1/encoder/encodemb.c b/av1/encoder/encodemb.c
index bc0605e..8459c8c 100644
--- a/av1/encoder/encodemb.c
+++ b/av1/encoder/encodemb.c
@@ -513,6 +513,7 @@
qparam.tx_size = tx_size;
#if CONFIG_NEW_QUANT
qparam.dq = get_dq_profile(cm->dq_type, x->qindex, is_inter, plane_type);
+ qparam.x0 = get_x0_profile(x->optimize, x->qindex, is_inter, plane_type);
#endif // CONFIG_NEW_QUANT
#if CONFIG_AOM_QM
qparam.qmatrix = qmatrix;