Move optimize_b and quant_idx to QUANT_PARAMS.
Also clean up a bit on the logic of using optimize_b.
Change-Id: I1b05354643cc98a7d89846e334a0e64690b0e31d
diff --git a/av1/encoder/av1_quantize.h b/av1/encoder/av1_quantize.h
index d4fa0b2..4b306d9 100644
--- a/av1/encoder/av1_quantize.h
+++ b/av1/encoder/av1_quantize.h
@@ -31,6 +31,8 @@
const qm_val_t *qmatrix;
const qm_val_t *iqmatrix;
int use_quant_b_adapt;
+ int use_optimize_b;
+ int xform_quant_idx;
} QUANT_PARAM;
typedef void (*AV1_QUANT_FACADE)(const tran_low_t *coeff_ptr, intptr_t n_coeffs,
diff --git a/av1/encoder/encodemb.c b/av1/encoder/encodemb.c
index 143df94..9e87527 100644
--- a/av1/encoder/encodemb.c
+++ b/av1/encoder/encodemb.c
@@ -126,8 +126,7 @@
#endif
void av1_xform_quant(MACROBLOCK *x, int plane, int block, int blk_row,
- int blk_col, BLOCK_SIZE plane_bsize,
- AV1_XFORM_QUANT xform_quant_idx, TxfmParam *txfm_param,
+ int blk_col, BLOCK_SIZE plane_bsize, TxfmParam *txfm_param,
QUANT_PARAM *qparam) {
MACROBLOCKD *const xd = &x->e_mbd;
const struct macroblock_plane *const p = &x->plane[plane];
@@ -146,30 +145,27 @@
av1_fwd_txfm(src_diff, coeff, diff_stride, txfm_param);
- if (xform_quant_idx != AV1_XFORM_QUANT_SKIP_QUANT) {
+ if (qparam->xform_quant_idx != AV1_XFORM_QUANT_SKIP_QUANT) {
const int n_coeffs = av1_get_max_eob(txfm_param->tx_size);
if (LIKELY(!x->skip_block)) {
#if CONFIG_AV1_HIGHBITDEPTH
- quant_func_list[xform_quant_idx][txfm_param->is_hbd](
+ quant_func_list[qparam->xform_quant_idx][txfm_param->is_hbd](
coeff, n_coeffs, p, qcoeff, dqcoeff, eob, scan_order, qparam);
#else
- quant_func_list[xform_quant_idx](coeff, n_coeffs, p, qcoeff, dqcoeff, eob,
- scan_order, qparam);
+ quant_func_list[qparam->xform_quant_idx](
+ coeff, n_coeffs, p, qcoeff, dqcoeff, eob, scan_order, qparam);
#endif
} else {
av1_quantize_skip(n_coeffs, qcoeff, dqcoeff, eob);
}
}
- // NOTE: optimize_b_following is true means av1_optimze_b will be called
- // When the condition of doing optimize_b is changed,
- // this flag need update simultaneously
- const int optimize_b_following =
- (xform_quant_idx != AV1_XFORM_QUANT_FP) || (txfm_param->lossless);
- if (optimize_b_following) {
+ // use_optimize_b is true means av1_optimze_b will be called,
+ // thus cannot update entropy ctx now (performed in optimize_b)
+ if (qparam->use_optimize_b) {
+ p->txb_entropy_ctx[block] = 0;
+ } else {
p->txb_entropy_ctx[block] =
(uint8_t)av1_get_txb_entropy_context(qcoeff, scan_order, *eob);
- } else {
- p->txb_entropy_ctx[block] = 0;
}
return;
}
@@ -188,12 +184,20 @@
txfm_param->bd = xd->bd;
txfm_param->is_hbd = is_cur_buf_hbd(xd);
}
-void av1_setup_quant(const AV1_COMMON *cm, TX_SIZE tx_size,
- QUANT_PARAM *qparam) {
+void av1_setup_quant(const AV1_COMMON *cm, TX_SIZE tx_size, int use_optimize_b,
+ int xform_quant_idx, QUANT_PARAM *qparam) {
qparam->log_scale = av1_get_tx_scale(tx_size);
qparam->tx_size = tx_size;
qparam->use_quant_b_adapt = cm->use_quant_b_adapt;
+
+ // TODO(bohanli): optimize_b and quantization idx has relationship,
+ // but is kind of buried and complicated in different encoding stages.
+ // Should have a unified function to derive quant_idx, rather than
+ // determine and pass in the quant_idx
+ qparam->use_optimize_b = use_optimize_b;
+ qparam->xform_quant_idx = xform_quant_idx;
+
qparam->qmatrix = NULL;
qparam->iqmatrix = NULL;
}
@@ -247,25 +251,25 @@
cm->reduced_tx_set_used);
TxfmParam txfm_param;
QUANT_PARAM quant_param;
+ int use_trellis = (args->enable_optimize_b != NO_TRELLIS_OPT);
+ int quant_idx;
+ if (use_trellis && args->enable_optimize_b != FINAL_PASS_TRELLIS_OPT) {
+ quant_idx = AV1_XFORM_QUANT_FP;
+ } else {
+ quant_idx =
+ USE_B_QUANT_NO_TRELLIS ? AV1_XFORM_QUANT_B : AV1_XFORM_QUANT_FP;
+ }
av1_setup_xform(cm, x, tx_size, tx_type, &txfm_param);
- av1_setup_quant(cm, tx_size, &quant_param);
+ av1_setup_quant(cm, tx_size, use_trellis, quant_idx, &quant_param);
av1_setup_qmatrix(cm, x, plane, tx_size, tx_type, &quant_param);
- if (args->enable_optimize_b != NO_TRELLIS_OPT) {
- av1_xform_quant(x, plane, block, blk_row, blk_col, plane_bsize,
- USE_B_QUANT_NO_TRELLIS && (args->enable_optimize_b ==
- FINAL_PASS_TRELLIS_OPT)
- ? AV1_XFORM_QUANT_B
- : AV1_XFORM_QUANT_FP,
- &txfm_param, &quant_param);
+ av1_xform_quant(x, plane, block, blk_row, blk_col, plane_bsize, &txfm_param,
+ &quant_param);
+
+ if (quant_param.use_optimize_b) {
TXB_CTX txb_ctx;
get_txb_ctx(plane_bsize, tx_size, plane, a, l, &txb_ctx);
av1_optimize_b(args->cpi, x, plane, block, tx_size, tx_type, &txb_ctx,
args->cpi->sf.trellis_eob_fast, &dummy_rate_cost);
- } else {
- av1_xform_quant(
- x, plane, block, blk_row, blk_col, plane_bsize,
- USE_B_QUANT_NO_TRELLIS ? AV1_XFORM_QUANT_B : AV1_XFORM_QUANT_FP,
- &txfm_param, &quant_param);
}
} else {
p->eobs[block] = 0;
@@ -456,11 +460,11 @@
QUANT_PARAM quant_param;
av1_setup_xform(cm, x, tx_size, DCT_DCT, &txfm_param);
- av1_setup_quant(cm, tx_size, &quant_param);
+ av1_setup_quant(cm, tx_size, 0, AV1_XFORM_QUANT_B, &quant_param);
av1_setup_qmatrix(cm, x, plane, tx_size, DCT_DCT, &quant_param);
- av1_xform_quant(x, plane, block, blk_row, blk_col, plane_bsize,
- AV1_XFORM_QUANT_B, &txfm_param, &quant_param);
+ av1_xform_quant(x, plane, block, blk_row, blk_col, plane_bsize, &txfm_param,
+ &quant_param);
if (p->eobs[block] > 0) {
txfm_param.eob = p->eobs[block];
@@ -608,25 +612,26 @@
cm->reduced_tx_set_used);
TxfmParam txfm_param;
QUANT_PARAM quant_param;
+ int use_trellis = args->enable_optimize_b != NO_TRELLIS_OPT;
+ int quant_idx;
+ if (use_trellis && args->enable_optimize_b != FINAL_PASS_TRELLIS_OPT)
+ quant_idx = AV1_XFORM_QUANT_FP;
+ else
+ quant_idx =
+ USE_B_QUANT_NO_TRELLIS ? AV1_XFORM_QUANT_B : AV1_XFORM_QUANT_FP;
+
av1_setup_xform(cm, x, tx_size, tx_type, &txfm_param);
- av1_setup_quant(cm, tx_size, &quant_param);
+ av1_setup_quant(cm, tx_size, use_trellis, quant_idx, &quant_param);
av1_setup_qmatrix(cm, x, plane, tx_size, tx_type, &quant_param);
- if (args->enable_optimize_b != NO_TRELLIS_OPT) {
- av1_xform_quant(x, plane, block, blk_row, blk_col, plane_bsize,
- USE_B_QUANT_NO_TRELLIS && (args->enable_optimize_b ==
- FINAL_PASS_TRELLIS_OPT)
- ? AV1_XFORM_QUANT_B
- : AV1_XFORM_QUANT_FP,
- &txfm_param, &quant_param);
+
+ av1_xform_quant(x, plane, block, blk_row, blk_col, plane_bsize, &txfm_param,
+ &quant_param);
+
+ if (quant_param.use_optimize_b) {
TXB_CTX txb_ctx;
get_txb_ctx(plane_bsize, tx_size, plane, a, l, &txb_ctx);
av1_optimize_b(args->cpi, x, plane, block, tx_size, tx_type, &txb_ctx,
args->cpi->sf.trellis_eob_fast, &dummy_rate_cost);
- } else {
- av1_xform_quant(
- x, plane, block, blk_row, blk_col, plane_bsize,
- USE_B_QUANT_NO_TRELLIS ? AV1_XFORM_QUANT_B : AV1_XFORM_QUANT_FP,
- &txfm_param, &quant_param);
}
}
diff --git a/av1/encoder/encodemb.h b/av1/encoder/encodemb.h
index 0a38859..dc9b190 100644
--- a/av1/encoder/encodemb.h
+++ b/av1/encoder/encodemb.h
@@ -61,14 +61,13 @@
void av1_setup_xform(const AV1_COMMON *cm, MACROBLOCK *x, TX_SIZE tx_size,
TX_TYPE tx_type, TxfmParam *txfm_param);
-void av1_setup_quant(const AV1_COMMON *cm, TX_SIZE tx_size,
- QUANT_PARAM *qparam);
+void av1_setup_quant(const AV1_COMMON *cm, TX_SIZE tx_size, int use_optimize_b,
+ int xform_quant_idx, QUANT_PARAM *qparam);
void av1_setup_qmatrix(const AV1_COMMON *cm, MACROBLOCK *x, int plane,
TX_SIZE tx_size, TX_TYPE tx_type, QUANT_PARAM *qparam);
void av1_xform_quant(MACROBLOCK *x, int plane, int block, int blk_row,
- int blk_col, BLOCK_SIZE plane_bsize,
- AV1_XFORM_QUANT xform_quant_idx, TxfmParam *txfm_param,
+ int blk_col, BLOCK_SIZE plane_bsize, TxfmParam *txfm_param,
QUANT_PARAM *qparam);
int av1_optimize_b(const struct AV1_COMP *cpi, MACROBLOCK *mb, int plane,
diff --git a/av1/encoder/rdopt.c b/av1/encoder/rdopt.c
index c9b7eed..7b8f9e0 100644
--- a/av1/encoder/rdopt.c
+++ b/av1/encoder/rdopt.c
@@ -3314,6 +3314,7 @@
best_eob = intra_txb_rd_info->eob;
best_tx_type = intra_txb_rd_info->tx_type;
perform_block_coeff_opt = intra_txb_rd_info->perform_block_coeff_opt;
+ skip_trellis |= !perform_block_coeff_opt;
update_txk_array(xd, blk_row, blk_col, tx_size, best_tx_type);
goto RECON_INTRA;
}
@@ -3458,13 +3459,18 @@
// larger residuals, R-D optimization may not be effective.
// TODO(any): Experiment with variance and mean based thresholds
perform_block_coeff_opt = (block_mse_q8 <= x->coeff_opt_dist_threshold);
+ skip_trellis |= !perform_block_coeff_opt;
assert(IMPLIES(txk_allowed < TX_TYPES, allowed_tx_mask == 1 << txk_allowed));
TxfmParam txfm_param;
QUANT_PARAM quant_param;
av1_setup_xform(cm, x, tx_size, DCT_DCT, &txfm_param);
- av1_setup_quant(cm, tx_size, &quant_param);
+ av1_setup_quant(cm, tx_size, !skip_trellis,
+ skip_trellis ? (USE_B_QUANT_NO_TRELLIS ? AV1_XFORM_QUANT_B
+ : AV1_XFORM_QUANT_FP)
+ : AV1_XFORM_QUANT_FP,
+ &quant_param);
int use_qm = !(xd->lossless[mbmi->segment_id] || cm->using_qmatrix == 0);
for (int idx = 0; idx < TX_TYPES; ++idx) {
@@ -3477,17 +3483,11 @@
if (plane == 0) xd->tx_type_map[tx_type_map_idx] = tx_type;
RD_STATS this_rd_stats;
av1_invalid_rd_stats(&this_rd_stats);
- if (skip_trellis || (!perform_block_coeff_opt)) {
- av1_xform_quant(
- x, plane, block, blk_row, blk_col, plane_bsize,
- USE_B_QUANT_NO_TRELLIS ? AV1_XFORM_QUANT_B : AV1_XFORM_QUANT_FP,
- &txfm_param, &quant_param);
- rate_cost =
- av1_cost_coeffs(x, plane, block, tx_size, tx_type, txb_ctx,
- use_fast_coef_costing, cm->reduced_tx_set_used);
- } else {
- av1_xform_quant(x, plane, block, blk_row, blk_col, plane_bsize,
- AV1_XFORM_QUANT_FP, &txfm_param, &quant_param);
+
+ av1_xform_quant(x, plane, block, blk_row, blk_col, plane_bsize, &txfm_param,
+ &quant_param);
+
+ if (quant_param.use_optimize_b) {
if (cpi->sf.optimize_b_precheck && best_rd < INT64_MAX &&
eobs_ptr[block] >= 4) {
// Calculate distortion quickly in transform domain.
@@ -3501,7 +3501,12 @@
}
av1_optimize_b(cpi, x, plane, block, tx_size, tx_type, txb_ctx,
cpi->sf.trellis_eob_fast, &rate_cost);
+ } else {
+ rate_cost =
+ av1_cost_coeffs(x, plane, block, tx_size, tx_type, txb_ctx,
+ use_fast_coef_costing, cm->reduced_tx_set_used);
}
+
// If rd cost based on coeff rate is more than best_rd, skip the calculation
// of distortion
int64_t tmp_rd = RDCOST(x->rdmult, rate_cost, 0);
@@ -3660,18 +3665,17 @@
TxfmParam txfm_param_intra;
QUANT_PARAM quant_param_intra;
av1_setup_xform(cm, x, tx_size, best_tx_type, &txfm_param_intra);
- av1_setup_quant(cm, tx_size, &quant_param_intra);
+ av1_setup_quant(cm, tx_size, !skip_trellis,
+ skip_trellis
+ ? (USE_B_QUANT_NO_TRELLIS ? AV1_XFORM_QUANT_B
+ : AV1_XFORM_QUANT_FP)
+ : AV1_XFORM_QUANT_FP,
+ &quant_param_intra);
av1_setup_qmatrix(cm, x, plane, tx_size, best_tx_type,
&quant_param_intra);
- if (skip_trellis || (!perform_block_coeff_opt)) {
- av1_xform_quant(
- x, plane, block, blk_row, blk_col, plane_bsize,
- USE_B_QUANT_NO_TRELLIS ? AV1_XFORM_QUANT_B : AV1_XFORM_QUANT_FP,
- &txfm_param_intra, &quant_param_intra);
- } else {
- av1_xform_quant(x, plane, block, blk_row, blk_col, plane_bsize,
- AV1_XFORM_QUANT_FP, &txfm_param_intra,
- &quant_param_intra);
+ av1_xform_quant(x, plane, block, blk_row, blk_col, plane_bsize,
+ &txfm_param_intra, &quant_param_intra);
+ if (quant_param_intra.use_optimize_b) {
av1_optimize_b(cpi, x, plane, block, tx_size, best_tx_type, txb_ctx,
cpi->sf.trellis_eob_fast, &rate_cost);
}