Group quantization config in AV1EncoderConfig
This CL groups configuration parameters related to quantization
in AV1EncoderConfig into a new struct QuantizationCfg, removes
redundant variables and adds relevant documentation.
BUG=aomedia:2701
Change-Id: I9c55f16616155bd6e0df02b4d80c82b69f6d9a09
diff --git a/av1/av1_cx_iface.c b/av1/av1_cx_iface.c
index 712a0eb..90684f0 100644
--- a/av1/av1_cx_iface.c
+++ b/av1/av1_cx_iface.c
@@ -726,6 +726,8 @@
RateControlCfg *const rc_cfg = &oxcf->rc_cfg;
+ QuantizationCfg *const q_cfg = &oxcf->q_cfg;
+
const int is_vbr = cfg->rc_end_usage == AOM_VBR;
oxcf->profile = cfg->g_profile;
oxcf->max_threads = (int)cfg->g_threads;
@@ -814,13 +816,30 @@
oxcf->enable_palette = extra_cfg->enable_palette;
oxcf->disable_trellis_quant = extra_cfg->disable_trellis_quant;
oxcf->allow_ref_frame_mvs = extra_cfg->enable_ref_frame_mvs;
- oxcf->using_qm = extra_cfg->enable_qm;
- oxcf->qm_y = extra_cfg->qm_y;
- oxcf->qm_u = extra_cfg->qm_u;
- oxcf->qm_v = extra_cfg->qm_v;
- oxcf->qm_minlevel = extra_cfg->qm_min;
- oxcf->qm_maxlevel = extra_cfg->qm_max;
- oxcf->quant_b_adapt = extra_cfg->quant_b_adapt;
+
+ // Set Quantization related configuration.
+ q_cfg->using_qm = extra_cfg->enable_qm;
+ q_cfg->qm_minlevel = extra_cfg->qm_min;
+ q_cfg->qm_maxlevel = extra_cfg->qm_max;
+ q_cfg->quant_b_adapt = extra_cfg->quant_b_adapt;
+ q_cfg->enable_chroma_deltaq = extra_cfg->enable_chroma_deltaq;
+ q_cfg->aq_mode = extra_cfg->aq_mode;
+ q_cfg->deltaq_mode = extra_cfg->deltaq_mode;
+ q_cfg->use_fixed_qp_offsets =
+ cfg->use_fixed_qp_offsets && (rc_cfg->mode == AOM_Q);
+ for (int i = 0; i < FIXED_QP_OFFSET_COUNT; ++i) {
+ if (q_cfg->use_fixed_qp_offsets) {
+ if (cfg->fixed_qp_offsets[i] >= 0) { // user-provided qp offset
+ q_cfg->fixed_qp_offsets[i] = convert_qp_offset(
+ rc_cfg->cq_level, cfg->fixed_qp_offsets[i], oxcf->bit_depth);
+ } else { // auto-selected qp offset
+ q_cfg->fixed_qp_offsets[i] =
+ get_modeled_qp_offset(rc_cfg->cq_level, i, oxcf->bit_depth);
+ }
+ } else {
+ q_cfg->fixed_qp_offsets[i] = -1.0;
+ }
+ }
// Set cost update frequency configuration.
oxcf->cost_upd_freq.coeff = (COST_UPDATE_TYPE)extra_cfg->coeff_cost_upd_freq;
@@ -1049,12 +1068,8 @@
oxcf->enable_tpl_model =
resize_cfg->resize_mode ? 0 : extra_cfg->enable_tpl_model;
- oxcf->enable_chroma_deltaq = extra_cfg->enable_chroma_deltaq;
- oxcf->aq_mode = extra_cfg->aq_mode;
- oxcf->deltaq_mode = extra_cfg->deltaq_mode;
-
oxcf->deltalf_mode =
- (oxcf->deltaq_mode != NO_DELTA_Q) && extra_cfg->deltalf_mode;
+ (q_cfg->deltaq_mode != NO_DELTA_Q) && extra_cfg->deltalf_mode;
oxcf->save_as_annexb = cfg->save_as_annexb;
@@ -1072,24 +1087,8 @@
sizeof(oxcf->target_seq_level_idx));
oxcf->tier_mask = extra_cfg->tier_mask;
- oxcf->use_fixed_qp_offsets =
- cfg->use_fixed_qp_offsets && (rc_cfg->mode == AOM_Q);
oxcf->vbr_corpus_complexity_lap = extra_cfg->vbr_corpus_complexity_lap;
- for (int i = 0; i < FIXED_QP_OFFSET_COUNT; ++i) {
- if (oxcf->use_fixed_qp_offsets) {
- if (cfg->fixed_qp_offsets[i] >= 0) { // user-provided qp offset
- oxcf->fixed_qp_offsets[i] = convert_qp_offset(
- rc_cfg->cq_level, cfg->fixed_qp_offsets[i], oxcf->bit_depth);
- } else { // auto-selected qp offset
- oxcf->fixed_qp_offsets[i] =
- get_modeled_qp_offset(rc_cfg->cq_level, i, oxcf->bit_depth);
- }
- } else {
- oxcf->fixed_qp_offsets[i] = -1.0;
- }
- }
-
return AOM_CODEC_OK;
}
diff --git a/av1/encoder/encode_strategy.c b/av1/encoder/encode_strategy.c
index c132019..d98fc46 100644
--- a/av1/encoder/encode_strategy.c
+++ b/av1/encoder/encode_strategy.c
@@ -1184,7 +1184,7 @@
frame_params.speed = oxcf->speed;
// Work out some encoding parameters specific to the pass:
- if (has_no_stats_stage(cpi) && oxcf->aq_mode == CYCLIC_REFRESH_AQ) {
+ if (has_no_stats_stage(cpi) && oxcf->q_cfg.aq_mode == CYCLIC_REFRESH_AQ) {
av1_cyclic_refresh_update_parameters(cpi);
} else if (is_stat_generation_stage(cpi)) {
cpi->td.mb.e_mbd.lossless[0] = is_lossless_requested(&oxcf->rc_cfg);
@@ -1267,7 +1267,7 @@
cpi->td.mb.delta_qindex = 0;
if (!frame_params.show_existing_frame) {
- cm->quant_params.using_qmatrix = oxcf->using_qm;
+ cm->quant_params.using_qmatrix = oxcf->q_cfg.using_qm;
#if !CONFIG_REALTIME_ONLY
if (gf_cfg->lag_in_frames > 0 && !is_stat_generation_stage(cpi)) {
if (cpi->gf_group.index == 1 && oxcf->enable_tpl_model) {
diff --git a/av1/encoder/encodeframe.c b/av1/encoder/encodeframe.c
index 7331947..cfc8c20 100644
--- a/av1/encoder/encodeframe.c
+++ b/av1/encoder/encodeframe.c
@@ -296,7 +296,7 @@
if (!is_frame_tpl_eligible((AV1_COMP *)cpi)) return deltaq_rdmult;
if (tpl_idx >= MAX_TPL_FRAME_IDX) return deltaq_rdmult;
if (cpi->superres_mode != AOM_SUPERRES_NONE) return deltaq_rdmult;
- if (cpi->oxcf.aq_mode != NO_AQ) return deltaq_rdmult;
+ if (cpi->oxcf.q_cfg.aq_mode != NO_AQ) return deltaq_rdmult;
const int bsize_base = BLOCK_16X16;
const int num_mi_w = mi_size_wide[bsize_base];
@@ -579,7 +579,7 @@
// If segmentation in use
if (seg->enabled) {
// For in frame complexity AQ copy the segment id from the segment map.
- if (cpi->oxcf.aq_mode == COMPLEXITY_AQ) {
+ if (cpi->oxcf.q_cfg.aq_mode == COMPLEXITY_AQ) {
const uint8_t *const map =
seg->update_map ? cpi->enc_seg.map : cm->last_frame_seg_map;
mi_addr->segment_id =
@@ -588,7 +588,7 @@
}
// Else for cyclic refresh mode update the segment map, set the segment id
// and then update the quantizer.
- if (cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ) {
+ if (cpi->oxcf.q_cfg.aq_mode == CYCLIC_REFRESH_AQ) {
av1_cyclic_refresh_update_segment(cpi, mi_addr, mi_row, mi_col, bsize,
ctx->rd_stats.rate, ctx->rd_stats.dist,
txfm_info->skip_txfm);
@@ -616,7 +616,8 @@
}
}
- if (cpi->oxcf.aq_mode) av1_init_plane_quantizers(cpi, x, mi_addr->segment_id);
+ if (cpi->oxcf.q_cfg.aq_mode)
+ av1_init_plane_quantizers(cpi, x, mi_addr->segment_id);
if (dry_run) return;
@@ -773,7 +774,7 @@
MB_MODE_INFO *mbmi;
struct macroblock_plane *const p = x->plane;
struct macroblockd_plane *const pd = xd->plane;
- const AQ_MODE aq_mode = cpi->oxcf.aq_mode;
+ const AQ_MODE aq_mode = cpi->oxcf.q_cfg.aq_mode;
TxfmSearchInfo *txfm_info = &x->txfm_search_info;
int i;
@@ -2325,7 +2326,7 @@
MB_MODE_INFO *mbmi = xd->mi[0];
struct macroblock_plane *const p = x->plane;
struct macroblockd_plane *const pd = xd->plane;
- const AQ_MODE aq_mode = cpi->oxcf.aq_mode;
+ const AQ_MODE aq_mode = cpi->oxcf.q_cfg.aq_mode;
TxfmSearchInfo *txfm_info = &x->txfm_search_info;
int i;
#if CONFIG_COLLECT_COMPONENT_TIMING
@@ -4500,7 +4501,7 @@
av1_setup_src_planes(x, cpi->source, mi_row, mi_col, num_planes, sb_size);
int current_qindex = cm->quant_params.base_qindex;
- if (cpi->oxcf.deltaq_mode == DELTA_Q_PERCEPTUAL) {
+ if (cpi->oxcf.q_cfg.deltaq_mode == DELTA_Q_PERCEPTUAL) {
if (DELTA_Q_PERCEPTUAL_MODULATION == 1) {
const int block_wavelet_energy_level =
av1_block_wavelet_energy_level(cpi, x, sb_size);
@@ -4513,7 +4514,7 @@
current_qindex =
av1_compute_q_from_energy_level_deltaq_mode(cpi, block_var_level);
}
- } else if (cpi->oxcf.deltaq_mode == DELTA_Q_OBJECTIVE &&
+ } else if (cpi->oxcf.q_cfg.deltaq_mode == DELTA_Q_OBJECTIVE &&
cpi->oxcf.enable_tpl_model) {
// Setup deltaq based on tpl stats
current_qindex = get_q_for_deltaq_objective(cpi, sb_size, mi_row, mi_col);
@@ -4522,7 +4523,7 @@
const int delta_q_res = delta_q_info->delta_q_res;
// Right now aq only works with tpl model. So if tpl is disabled, we set the
// current_qindex to base_qindex.
- if (cpi->oxcf.enable_tpl_model && cpi->oxcf.deltaq_mode != NO_DELTA_Q) {
+ if (cpi->oxcf.enable_tpl_model && cpi->oxcf.q_cfg.deltaq_mode != NO_DELTA_Q) {
current_qindex =
clamp(current_qindex, delta_q_res, 256 - delta_q_info->delta_q_res);
} else {
@@ -4762,8 +4763,8 @@
assert(IMPLIES(cpi->gf_group.size > 0,
cpi->gf_group.index < cpi->gf_group.size));
const int gf_group_index = cpi->gf_group.index;
- if (cpi->oxcf.enable_tpl_model && cpi->oxcf.aq_mode == NO_AQ &&
- cpi->oxcf.deltaq_mode == NO_DELTA_Q && gf_group_index > 0 &&
+ if (cpi->oxcf.enable_tpl_model && cpi->oxcf.q_cfg.aq_mode == NO_AQ &&
+ cpi->oxcf.q_cfg.deltaq_mode == NO_DELTA_Q && gf_group_index > 0 &&
cpi->gf_group.update_type[gf_group_index] == ARF_UPDATE) {
const int dr =
get_rdmult_delta(cpi, sb_size, 0, mi_row, mi_col, orig_rdmult);
@@ -4982,7 +4983,7 @@
if (!is_frame_tpl_eligible(cpi)) return;
if (frame_idx >= MAX_TPL_FRAME_IDX) return;
if (cpi->superres_mode != AOM_SUPERRES_NONE) return;
- if (cpi->oxcf.aq_mode != NO_AQ) return;
+ if (cpi->oxcf.q_cfg.aq_mode != NO_AQ) return;
const int is_overlay = cpi->gf_group.update_type[frame_idx] == OVERLAY_UPDATE;
if (is_overlay) {
@@ -5803,6 +5804,7 @@
MultiThreadInfo *const mt_info = &cpi->mt_info;
AV1EncRowMultiThreadInfo *const enc_row_mt = &mt_info->enc_row_mt;
const AV1EncoderConfig *const oxcf = &cpi->oxcf;
+ const DELTAQ_MODE deltaq_mode = oxcf->q_cfg.deltaq_mode;
int i;
if (!cpi->sf.rt_sf.use_nonrd_pick_mode) {
@@ -5914,20 +5916,20 @@
// Fix delta q resolution for the moment
cm->delta_q_info.delta_q_res = 0;
- if (oxcf->deltaq_mode == DELTA_Q_OBJECTIVE)
+ if (deltaq_mode == DELTA_Q_OBJECTIVE)
cm->delta_q_info.delta_q_res = DEFAULT_DELTA_Q_RES_OBJECTIVE;
- else if (oxcf->deltaq_mode == DELTA_Q_PERCEPTUAL)
+ else if (deltaq_mode == DELTA_Q_PERCEPTUAL)
cm->delta_q_info.delta_q_res = DEFAULT_DELTA_Q_RES_PERCEPTUAL;
// Set delta_q_present_flag before it is used for the first time
cm->delta_q_info.delta_lf_res = DEFAULT_DELTA_LF_RES;
- cm->delta_q_info.delta_q_present_flag = oxcf->deltaq_mode != NO_DELTA_Q;
+ cm->delta_q_info.delta_q_present_flag = deltaq_mode != NO_DELTA_Q;
// Turn off cm->delta_q_info.delta_q_present_flag if objective delta_q is used
// for ineligible frames. That effectively will turn off row_mt usage.
// Note objective delta_q and tpl eligible frames are only altref frames
// currently.
if (cm->delta_q_info.delta_q_present_flag) {
- if (oxcf->deltaq_mode == DELTA_Q_OBJECTIVE && !is_frame_tpl_eligible(cpi))
+ if (deltaq_mode == DELTA_Q_OBJECTIVE && !is_frame_tpl_eligible(cpi))
cm->delta_q_info.delta_q_present_flag = 0;
}
diff --git a/av1/encoder/encodemb.c b/av1/encoder/encodemb.c
index fe774ef..9cda30e 100644
--- a/av1/encoder/encodemb.c
+++ b/av1/encoder/encodemb.c
@@ -393,8 +393,8 @@
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(tx_size, use_trellis, quant_idx, cpi->oxcf.quant_b_adapt,
- &quant_param);
+ av1_setup_quant(tx_size, use_trellis, quant_idx,
+ cpi->oxcf.q_cfg.quant_b_adapt, &quant_param);
av1_setup_qmatrix(&cm->quant_params, xd, plane, tx_size, tx_type,
&quant_param);
av1_xform_quant(x, plane, block, blk_row, blk_col, plane_bsize, &txfm_param,
@@ -437,8 +437,8 @@
// again.
if (p->eobs[block] == 0 && plane == 0) {
#if 0
- if (args->cpi->oxcf.aq_mode == NO_AQ &&
- args->cpi->oxcf.deltaq_mode == NO_DELTA_Q) {
+ if (args->cpi->oxcf.q_cfg.aq_mode == NO_AQ &&
+ args->cpi->oxcf.q_cfg.deltaq_mode == NO_DELTA_Q) {
// TODO(jingning,angiebird,huisu@google.com): enable txk_check when
// enable_optimize_b is true to detect potential RD bug.
const uint8_t disable_txk_check = args->enable_optimize_b;
@@ -584,7 +584,7 @@
QUANT_PARAM quant_param;
av1_setup_xform(cm, x, tx_size, DCT_DCT, &txfm_param);
- av1_setup_quant(tx_size, 0, AV1_XFORM_QUANT_B, cpi->oxcf.quant_b_adapt,
+ av1_setup_quant(tx_size, 0, AV1_XFORM_QUANT_B, cpi->oxcf.q_cfg.quant_b_adapt,
&quant_param);
av1_setup_qmatrix(&cm->quant_params, xd, plane, tx_size, DCT_DCT,
&quant_param);
@@ -727,8 +727,8 @@
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(tx_size, use_trellis, quant_idx, cpi->oxcf.quant_b_adapt,
- &quant_param);
+ av1_setup_quant(tx_size, use_trellis, quant_idx,
+ cpi->oxcf.q_cfg.quant_b_adapt, &quant_param);
av1_setup_qmatrix(&cm->quant_params, xd, plane, tx_size, tx_type,
&quant_param);
@@ -775,8 +775,8 @@
// again.
if (*eob == 0 && plane == 0) {
#if 0
- if (args->cpi->oxcf.aq_mode == NO_AQ
- && args->cpi->oxcf.deltaq_mode == NO_DELTA_Q) {
+ if (args->cpi->oxcf.q_cfg.aq_mode == NO_AQ
+ && args->cpi->oxcf.q_cfg.deltaq_mode == NO_DELTA_Q) {
assert(xd->tx_type_map[blk_row * xd->tx_type_map_stride + blk_col)] ==
DCT_DCT);
}
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c
index e608c15..afdb991 100644
--- a/av1/encoder/encoder.c
+++ b/av1/encoder/encoder.c
@@ -2712,6 +2712,8 @@
// "cm->features.allow_intrabc" and "cpi->is_screen_content_type".
static void determine_sc_tools_with_encoding(AV1_COMP *cpi, const int q_orig) {
AV1_COMMON *const cm = &cpi->common;
+ const AV1EncoderConfig *const oxcf = &cpi->oxcf;
+ const QuantizationCfg *const q_cfg = &oxcf->q_cfg;
// Variables to help determine if we should allow screen content tools.
int projected_size_pass[3] = { 0 };
PSNR_STATS psnr[3];
@@ -2721,8 +2723,8 @@
const int allow_intrabc_orig_decision = cm->features.allow_intrabc;
const int is_screen_content_type_orig_decision = cpi->is_screen_content_type;
// Turn off the encoding trial for forward key frame and superres.
- if (cpi->sf.rt_sf.use_nonrd_pick_mode || cpi->oxcf.kf_cfg.fwd_kf_enabled ||
- cpi->superres_mode != AOM_SUPERRES_NONE || cpi->oxcf.mode == REALTIME ||
+ if (cpi->sf.rt_sf.use_nonrd_pick_mode || oxcf->kf_cfg.fwd_kf_enabled ||
+ cpi->superres_mode != AOM_SUPERRES_NONE || oxcf->mode == REALTIME ||
is_screen_content_type_orig_decision || !is_key_frame) {
return;
}
@@ -2732,7 +2734,7 @@
// for lossless coding.
// Use a high q and a fixed partition to do quick encoding.
const int q_for_screen_content_quick_run =
- is_lossless_requested(&cpi->oxcf.rc_cfg) ? q_orig : AOMMAX(q_orig, 244);
+ is_lossless_requested(&oxcf->rc_cfg) ? q_orig : AOMMAX(q_orig, 244);
const int partition_search_type_orig = cpi->sf.part_sf.partition_search_type;
const BLOCK_SIZE fixed_partition_block_size_orig =
cpi->sf.part_sf.always_this_block_size;
@@ -2767,23 +2769,23 @@
for (int pass = 0; pass < 2; ++pass) {
set_encoding_params_for_screen_content(cpi, pass);
#if CONFIG_TUNE_VMAF
- if (cpi->oxcf.tuning == AOM_TUNE_VMAF_WITH_PREPROCESSING ||
- cpi->oxcf.tuning == AOM_TUNE_VMAF_WITHOUT_PREPROCESSING ||
- cpi->oxcf.tuning == AOM_TUNE_VMAF_MAX_GAIN) {
+ if (oxcf->tuning == AOM_TUNE_VMAF_WITH_PREPROCESSING ||
+ oxcf->tuning == AOM_TUNE_VMAF_WITHOUT_PREPROCESSING ||
+ oxcf->tuning == AOM_TUNE_VMAF_MAX_GAIN) {
av1_set_quantizer(
- cm, cpi->oxcf.qm_minlevel, cpi->oxcf.qm_maxlevel,
+ cm, q_cfg->qm_minlevel, q_cfg->qm_maxlevel,
av1_get_vmaf_base_qindex(cpi, q_for_screen_content_quick_run),
- cpi->oxcf.enable_chroma_deltaq);
+ q_cfg->enable_chroma_deltaq);
} else {
#endif
- av1_set_quantizer(cm, cpi->oxcf.qm_minlevel, cpi->oxcf.qm_maxlevel,
+ av1_set_quantizer(cm, q_cfg->qm_minlevel, q_cfg->qm_maxlevel,
q_for_screen_content_quick_run,
- cpi->oxcf.enable_chroma_deltaq);
+ q_cfg->enable_chroma_deltaq);
#if CONFIG_TUNE_VMAF
}
#endif
- av1_set_speed_features_qindex_dependent(cpi, cpi->oxcf.speed);
- if (cpi->oxcf.deltaq_mode != NO_DELTA_Q)
+ av1_set_speed_features_qindex_dependent(cpi, oxcf->speed);
+ if (q_cfg->deltaq_mode != NO_DELTA_Q)
av1_init_quantizer(&cpi->enc_quant_dequant_params, &cm->quant_params,
cm->seq_params.bit_depth);
@@ -2817,6 +2819,7 @@
*/
static int encode_without_recode(AV1_COMP *cpi) {
AV1_COMMON *const cm = &cpi->common;
+ const QuantizationCfg *const q_cfg = &cpi->oxcf.q_cfg;
int top_index = 0, bottom_index = 0, q = 0;
set_size_independent_vars(cpi);
@@ -2842,10 +2845,10 @@
}
if (!frame_is_intra_only(cm)) scale_references(cpi);
- av1_set_quantizer(cm, cpi->oxcf.qm_minlevel, cpi->oxcf.qm_maxlevel, q,
- cpi->oxcf.enable_chroma_deltaq);
+ av1_set_quantizer(cm, q_cfg->qm_minlevel, q_cfg->qm_maxlevel, q,
+ q_cfg->enable_chroma_deltaq);
av1_set_speed_features_qindex_dependent(cpi, cpi->oxcf.speed);
- if (cpi->oxcf.deltaq_mode != NO_DELTA_Q)
+ if (q_cfg->deltaq_mode != NO_DELTA_Q)
av1_init_quantizer(&cpi->enc_quant_dequant_params, &cm->quant_params,
cm->seq_params.bit_depth);
av1_set_variance_partition_thresholds(cpi, q, 0);
@@ -2857,17 +2860,17 @@
if (cpi->sf.rt_sf.overshoot_detection_cbr == FAST_DETECTION_MAXQ &&
cpi->rc.high_source_sad) {
if (av1_encodedframe_overshoot(cpi, &q)) {
- av1_set_quantizer(cm, cpi->oxcf.qm_minlevel, cpi->oxcf.qm_maxlevel, q,
- cpi->oxcf.enable_chroma_deltaq);
+ av1_set_quantizer(cm, q_cfg->qm_minlevel, q_cfg->qm_maxlevel, q,
+ q_cfg->enable_chroma_deltaq);
av1_set_speed_features_qindex_dependent(cpi, cpi->oxcf.speed);
- if (cpi->oxcf.deltaq_mode != NO_DELTA_Q)
+ if (q_cfg->deltaq_mode != NO_DELTA_Q)
av1_init_quantizer(&cpi->enc_quant_dequant_params, &cm->quant_params,
cm->seq_params.bit_depth);
av1_set_variance_partition_thresholds(cpi, q, 0);
}
}
- if (cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ) {
+ if (q_cfg->aq_mode == CYCLIC_REFRESH_AQ) {
suppress_active_map(cpi);
av1_cyclic_refresh_setup(cpi);
apply_active_map(cpi);
@@ -2897,7 +2900,7 @@
av1_encode_frame(cpi);
// Update some stats from cyclic refresh.
- if (cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ && !frame_is_intra_only(cm))
+ if (q_cfg->aq_mode == CYCLIC_REFRESH_AQ && !frame_is_intra_only(cm))
av1_cyclic_refresh_postencode(cpi);
#if CONFIG_COLLECT_COMPONENT_TIMING
@@ -2933,9 +2936,11 @@
AV1_COMMON *const cm = &cpi->common;
RATE_CONTROL *const rc = &cpi->rc;
GlobalMotionInfo *const gm_info = &cpi->gm_info;
+ const AV1EncoderConfig *const oxcf = &cpi->oxcf;
+ const QuantizationCfg *const q_cfg = &oxcf->q_cfg;
const int allow_recode = (cpi->sf.hl_sf.recode_loop != DISALLOW_RECODE);
// Must allow recode if minimum compression ratio is set.
- assert(IMPLIES(cpi->oxcf.rc_cfg.min_cr > 0, allow_recode));
+ assert(IMPLIES(oxcf->rc_cfg.min_cr > 0, allow_recode));
set_size_independent_vars(cpi);
if (is_stat_consumption_stage_twopass(cpi) &&
@@ -3010,22 +3015,22 @@
scale_references(cpi);
}
#if CONFIG_TUNE_VMAF
- if (cpi->oxcf.tuning == AOM_TUNE_VMAF_WITH_PREPROCESSING ||
- cpi->oxcf.tuning == AOM_TUNE_VMAF_WITHOUT_PREPROCESSING ||
- cpi->oxcf.tuning == AOM_TUNE_VMAF_MAX_GAIN) {
- av1_set_quantizer(cm, cpi->oxcf.qm_minlevel, cpi->oxcf.qm_maxlevel,
+ if (oxcf->tuning == AOM_TUNE_VMAF_WITH_PREPROCESSING ||
+ oxcf->tuning == AOM_TUNE_VMAF_WITHOUT_PREPROCESSING ||
+ oxcf->tuning == AOM_TUNE_VMAF_MAX_GAIN) {
+ av1_set_quantizer(cm, q_cfg->qm_minlevel, q_cfg->qm_maxlevel,
av1_get_vmaf_base_qindex(cpi, q),
- cpi->oxcf.enable_chroma_deltaq);
+ q_cfg->enable_chroma_deltaq);
} else {
#endif
- av1_set_quantizer(cm, cpi->oxcf.qm_minlevel, cpi->oxcf.qm_maxlevel, q,
- cpi->oxcf.enable_chroma_deltaq);
+ av1_set_quantizer(cm, q_cfg->qm_minlevel, q_cfg->qm_maxlevel, q,
+ q_cfg->enable_chroma_deltaq);
#if CONFIG_TUNE_VMAF
}
#endif
- av1_set_speed_features_qindex_dependent(cpi, cpi->oxcf.speed);
+ av1_set_speed_features_qindex_dependent(cpi, oxcf->speed);
- if (cpi->oxcf.deltaq_mode != NO_DELTA_Q)
+ if (q_cfg->deltaq_mode != NO_DELTA_Q)
av1_init_quantizer(&cpi->enc_quant_dequant_params, &cm->quant_params,
cm->seq_params.bit_depth);
@@ -3044,9 +3049,9 @@
av1_setup_frame_contexts(cm);
}
- if (cpi->oxcf.aq_mode == VARIANCE_AQ) {
+ if (q_cfg->aq_mode == VARIANCE_AQ) {
av1_vaq_frame_setup(cpi);
- } else if (cpi->oxcf.aq_mode == COMPLEXITY_AQ) {
+ } else if (q_cfg->aq_mode == COMPLEXITY_AQ) {
av1_setup_in_frame_q_adj(cpi);
}
@@ -3105,8 +3110,8 @@
// to recode.
const int do_dummy_pack =
(cpi->sf.hl_sf.recode_loop >= ALLOW_RECODE_KFARFGF &&
- cpi->oxcf.rc_cfg.mode != AOM_Q) ||
- cpi->oxcf.rc_cfg.min_cr > 0;
+ oxcf->rc_cfg.mode != AOM_Q) ||
+ oxcf->rc_cfg.min_cr > 0;
if (do_dummy_pack) {
finalize_encoded_frame(cpi);
int largest_tile_id = 0; // Output from bitstream: unused here
diff --git a/av1/encoder/encoder.h b/av1/encoder/encoder.h
index 6546b87..0b6b358 100644
--- a/av1/encoder/encoder.h
+++ b/av1/encoder/encoder.h
@@ -543,6 +543,31 @@
bool enable_onesided_comp;
} RefFrameCfg;
+typedef struct {
+ // List of QP offsets for: keyframe, ALTREF, and 3 levels of internal ARFs.
+ // If any of these values are negative, fixed offsets are disabled.
+ // Uses internal q range.
+ double fixed_qp_offsets[FIXED_QP_OFFSET_COUNT];
+ // If true, encoder will use fixed QP offsets, that are either:
+ // - Given by the user, and stored in 'fixed_qp_offsets' array, OR
+ // - Picked automatically from cq_level.
+ int use_fixed_qp_offsets;
+ // Indicates the minimum flatness of the quantization matrix.
+ int qm_minlevel;
+ // Indicates the maximum flatness of the quantization matrix.
+ int qm_maxlevel;
+ // Indicates if adaptive quantize_b should be enabled.
+ int quant_b_adapt;
+ // Indicates the Adaptive Quantization mode to be used.
+ AQ_MODE aq_mode;
+ // Indicates the delta q mode to be used.
+ DELTAQ_MODE deltaq_mode;
+ // Indicates if delta quantization should be enabled in chroma planes.
+ bool enable_chroma_deltaq;
+ // Indicates if encoding with quantization matrices should be enabled.
+ bool using_qm;
+} QuantizationCfg;
+
typedef struct AV1EncoderConfig {
BITSTREAM_PROFILE profile;
aom_bit_depth_t bit_depth; // Codec bit-depth.
@@ -573,23 +598,17 @@
int drop_frames_water_mark;
// controlling quality
- int enable_chroma_deltaq;
- AQ_MODE aq_mode; // Adaptive Quantization mode
- DELTAQ_MODE deltaq_mode;
int deltalf_mode;
int enable_cdef;
int enable_restoration;
int force_video_mode;
int disable_trellis_quant;
- int using_qm;
- int qm_y;
- int qm_u;
- int qm_v;
- int qm_minlevel;
- int qm_maxlevel;
unsigned int vbr_corpus_complexity_lap; // 0 indicates corpus complexity vbr
// mode is disabled
+ // Configuration related to Quantization.
+ QuantizationCfg q_cfg;
+
// Internal frame size scaling.
ResizeCfg resize_cfg;
@@ -690,7 +709,6 @@
unsigned int chroma_subsampling_x;
unsigned int chroma_subsampling_y;
- int quant_b_adapt;
// Configuration related to frequency of cost update.
CostUpdateFreq cost_upd_freq;
@@ -700,14 +718,6 @@
// Bit mask to specify which tier each of the 32 possible operating points
// conforms to.
unsigned int tier_mask;
- // If true, encoder will use fixed QP offsets, that are either:
- // - Given by the user, and stored in 'fixed_qp_offsets' array, OR
- // - Picked automatically from cq_level.
- int use_fixed_qp_offsets;
- // List of QP offsets for: keyframe, ALTREF, and 3 levels of internal ARFs.
- // If any of these values are negative, fixed offsets are disabled.
- // Uses internal q range.
- double fixed_qp_offsets[FIXED_QP_OFFSET_COUNT];
const cfg_options_t *encoder_cfg;
} AV1EncoderConfig;
diff --git a/av1/encoder/encodetxb.c b/av1/encoder/encodetxb.c
index c55863e..1e86128 100644
--- a/av1/encoder/encodetxb.c
+++ b/av1/encoder/encodetxb.c
@@ -1786,11 +1786,11 @@
const int rshift =
(sharpness +
- (cpi->oxcf.aq_mode == VARIANCE_AQ && mbmi->segment_id < 4
+ (cpi->oxcf.q_cfg.aq_mode == VARIANCE_AQ && mbmi->segment_id < 4
? 7 - mbmi->segment_id
: 2) +
- (cpi->oxcf.aq_mode != VARIANCE_AQ &&
- cpi->oxcf.deltaq_mode == DELTA_Q_PERCEPTUAL &&
+ (cpi->oxcf.q_cfg.aq_mode != VARIANCE_AQ &&
+ cpi->oxcf.q_cfg.deltaq_mode == DELTA_Q_PERCEPTUAL &&
cm->delta_q_info.delta_q_present_flag && x->sb_energy_level < 0
? (3 - x->sb_energy_level)
: 0));
diff --git a/av1/encoder/firstpass.c b/av1/encoder/firstpass.c
index 6d5225b..c9128c9 100644
--- a/av1/encoder/firstpass.c
+++ b/av1/encoder/firstpass.c
@@ -1093,8 +1093,9 @@
// Do not use periodic key frames.
cpi->rc.frames_to_key = INT_MAX;
- av1_set_quantizer(cm, cpi->oxcf.qm_minlevel, cpi->oxcf.qm_maxlevel, qindex,
- cpi->oxcf.enable_chroma_deltaq);
+ av1_set_quantizer(cm, cpi->oxcf.q_cfg.qm_minlevel,
+ cpi->oxcf.q_cfg.qm_maxlevel, qindex,
+ cpi->oxcf.q_cfg.enable_chroma_deltaq);
av1_setup_block_planes(xd, seq_params->subsampling_x,
seq_params->subsampling_y, num_planes);
diff --git a/av1/encoder/nonrd_pickmode.c b/av1/encoder/nonrd_pickmode.c
index 3d45e27..e97ded0 100644
--- a/av1/encoder/nonrd_pickmode.c
+++ b/av1/encoder/nonrd_pickmode.c
@@ -470,7 +470,7 @@
else
tx_size = TX_8X8;
- if (cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ &&
+ if (cpi->oxcf.q_cfg.aq_mode == CYCLIC_REFRESH_AQ &&
cyclic_refresh_segment_id_boosted(xd->mi[0]->segment_id))
tx_size = TX_8X8;
else if (tx_size > TX_16X16)
diff --git a/av1/encoder/pass2_strategy.c b/av1/encoder/pass2_strategy.c
index dbcdd99..27abfb2 100644
--- a/av1/encoder/pass2_strategy.c
+++ b/av1/encoder/pass2_strategy.c
@@ -1365,7 +1365,7 @@
const GFConfig *const gf_cfg = &oxcf->gf_cfg;
int target;
- if (oxcf->aq_mode == CYCLIC_REFRESH_AQ) {
+ if (oxcf->q_cfg.aq_mode == CYCLIC_REFRESH_AQ) {
av1_cyclic_refresh_set_golden_update(cpi);
} else {
rc->baseline_gf_interval = rc->gf_intervals[rc->cur_gf_index];
diff --git a/av1/encoder/ratectrl.c b/av1/encoder/ratectrl.c
index 8307750..b0edce3 100644
--- a/av1/encoder/ratectrl.c
+++ b/av1/encoder/ratectrl.c
@@ -502,7 +502,7 @@
// Work out how big we would have expected the frame to be at this Q given
// the current correction factor.
// Stay in double to avoid int overflow when values are large
- if (cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ && cpi->common.seg.enabled) {
+ if (cpi->oxcf.q_cfg.aq_mode == CYCLIC_REFRESH_AQ && cpi->common.seg.enabled) {
projected_size_based_on_q =
av1_cyclic_refresh_estimate_bits_at_q(cpi, rate_correction_factor);
} else {
@@ -574,7 +574,7 @@
const AV1_COMP *cpi,
double correction_factor,
int best_qindex, int worst_qindex) {
- const int use_cyclic_refresh = cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ &&
+ const int use_cyclic_refresh = cpi->oxcf.q_cfg.aq_mode == CYCLIC_REFRESH_AQ &&
cpi->cyclic_refresh->apply_cyclic_refresh;
// Find 'qindex' based on 'desired_bits_per_mb'.
@@ -936,7 +936,7 @@
*
* The q index offsets are fixed in the sense that they are independent of the
* video content. The offsets for each pyramid level are taken from
- * \c oxcf->fixed_qp_offsets array.
+ * \c oxcf->q_cfg.fixed_qp_offsets array.
*
* \ingroup rate_control
* \param[in] oxcf Top level encoder configuration
@@ -955,7 +955,7 @@
const GF_GROUP *const gf_group,
int gf_index, int cq_level,
int bit_depth) {
- assert(oxcf->use_fixed_qp_offsets);
+ assert(oxcf->q_cfg.use_fixed_qp_offsets);
assert(oxcf->rc_cfg.mode == AOM_Q);
const FRAME_UPDATE_TYPE update_type = gf_group->update_type[gf_index];
@@ -977,12 +977,12 @@
return cq_level; // Directly Return worst quality allowed.
}
assert(offset_idx >= 0 && offset_idx < FIXED_QP_OFFSET_COUNT);
- assert(oxcf->fixed_qp_offsets[offset_idx] >= 0);
+ assert(oxcf->q_cfg.fixed_qp_offsets[offset_idx] >= 0);
// Get qindex offset, by first converting to 'q' and then back.
const double q_val_orig = av1_convert_qindex_to_q(cq_level, bit_depth);
const double q_val_target =
- AOMMAX(q_val_orig - oxcf->fixed_qp_offsets[offset_idx], 0.0);
+ AOMMAX(q_val_orig - oxcf->q_cfg.fixed_qp_offsets[offset_idx], 0.0);
const int delta_qindex =
av1_compute_qdelta(rc, q_val_orig, q_val_target, bit_depth);
return AOMMAX(cq_level + delta_qindex, 0);
@@ -1028,7 +1028,7 @@
cm->superres_scale_denominator);
const int bit_depth = cm->seq_params.bit_depth;
- if (oxcf->use_fixed_qp_offsets) {
+ if (oxcf->q_cfg.use_fixed_qp_offsets) {
return get_q_using_fixed_offsets(oxcf, rc, gf_group, gf_index, cq_level,
bit_depth);
}
@@ -1510,7 +1510,7 @@
cm->superres_scale_denominator);
const int bit_depth = cm->seq_params.bit_depth;
- if (oxcf->use_fixed_qp_offsets) {
+ if (oxcf->q_cfg.use_fixed_qp_offsets) {
return get_q_using_fixed_offsets(oxcf, rc, gf_group, gf_group->index,
cq_level, bit_depth);
}
@@ -2255,7 +2255,7 @@
if ((resize_pending || rc->high_source_sad ||
rc->frames_till_gf_update_due == 0) &&
cpi->svc.temporal_layer_id == 0 && cpi->svc.spatial_layer_id == 0) {
- if (cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ)
+ if (cpi->oxcf.q_cfg.aq_mode == CYCLIC_REFRESH_AQ)
av1_cyclic_refresh_set_golden_update(cpi);
else
rc->baseline_gf_interval = MAX_GF_INTERVAL;
diff --git a/av1/encoder/svc_layercontext.c b/av1/encoder/svc_layercontext.c
index 81529a1..b21997f 100644
--- a/av1/encoder/svc_layercontext.c
+++ b/av1/encoder/svc_layercontext.c
@@ -166,7 +166,7 @@
cpi->rc.frames_to_key = old_frame_to_key;
// For spatial-svc, allow cyclic-refresh to be applied on the spatial layers,
// for the base temporal layer.
- if (cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ &&
+ if (cpi->oxcf.q_cfg.aq_mode == CYCLIC_REFRESH_AQ &&
svc->number_spatial_layers > 1 && svc->temporal_layer_id == 0) {
CYCLIC_REFRESH *const cr = cpi->cyclic_refresh;
swap_ptr(&cr->map, &lc->map);
@@ -204,7 +204,7 @@
if (svc->spatial_layer_id == 0) svc->base_framerate = cpi->framerate;
// For spatial-svc, allow cyclic-refresh to be applied on the spatial layers,
// for the base temporal layer.
- if (cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ &&
+ if (cpi->oxcf.q_cfg.aq_mode == CYCLIC_REFRESH_AQ &&
cpi->svc.number_spatial_layers > 1 && svc->temporal_layer_id == 0) {
CYCLIC_REFRESH *const cr = cpi->cyclic_refresh;
signed char *temp = lc->map;
diff --git a/av1/encoder/tpl_model.c b/av1/encoder/tpl_model.c
index a43af38..4d4df7d 100644
--- a/av1/encoder/tpl_model.c
+++ b/av1/encoder/tpl_model.c
@@ -1210,7 +1210,7 @@
if (!is_frame_tpl_eligible(cpi)) return;
if (tpl_idx >= MAX_TPL_FRAME_IDX) return;
if (cpi->superres_mode != AOM_SUPERRES_NONE) return;
- if (cpi->oxcf.aq_mode != NO_AQ) return;
+ if (cpi->oxcf.q_cfg.aq_mode != NO_AQ) return;
const int bsize_base = BLOCK_16X16;
const int num_mi_w = mi_size_wide[bsize_base];
diff --git a/av1/encoder/tx_search.c b/av1/encoder/tx_search.c
index 344d370..7b6a46e 100644
--- a/av1/encoder/tx_search.c
+++ b/av1/encoder/tx_search.c
@@ -1117,7 +1117,7 @@
? (USE_B_QUANT_NO_TRELLIS ? AV1_XFORM_QUANT_B
: AV1_XFORM_QUANT_FP)
: AV1_XFORM_QUANT_FP,
- cpi->oxcf.quant_b_adapt, &quant_param_intra);
+ cpi->oxcf.q_cfg.quant_b_adapt, &quant_param_intra);
av1_setup_qmatrix(&cm->quant_params, xd, plane, tx_size, best_tx_type,
&quant_param_intra);
av1_xform_quant(x, plane, block, blk_row, blk_col, plane_bsize,
@@ -1388,7 +1388,7 @@
QUANT_PARAM quant_param;
TxfmParam txfm_param;
av1_setup_xform(cm, x, tx_size, DCT_DCT, &txfm_param);
- av1_setup_quant(tx_size, 1, AV1_XFORM_QUANT_B, cpi->oxcf.quant_b_adapt,
+ av1_setup_quant(tx_size, 1, AV1_XFORM_QUANT_B, cpi->oxcf.q_cfg.quant_b_adapt,
&quant_param);
int tx_type;
// to ensure we can try ones even outside of ext_tx_set of current block
@@ -1503,7 +1503,7 @@
TxfmParam txfm_param;
QUANT_PARAM quant_param;
av1_setup_xform(cm, x, tx_size, DCT_DCT, &txfm_param);
- av1_setup_quant(tx_size, 1, AV1_XFORM_QUANT_B, cpi->oxcf.quant_b_adapt,
+ av1_setup_quant(tx_size, 1, AV1_XFORM_QUANT_B, cpi->oxcf.q_cfg.quant_b_adapt,
&quant_param);
for (int idx = 0; idx < TX_TYPES; idx++) {
@@ -2264,7 +2264,7 @@
skip_trellis ? (USE_B_QUANT_NO_TRELLIS ? AV1_XFORM_QUANT_B
: AV1_XFORM_QUANT_FP)
: AV1_XFORM_QUANT_FP,
- cpi->oxcf.quant_b_adapt, &quant_param);
+ cpi->oxcf.q_cfg.quant_b_adapt, &quant_param);
// Iterate through all transform type candidates.
for (int idx = 0; idx < TX_TYPES; ++idx) {
@@ -2282,8 +2282,8 @@
av1_xform(x, plane, block, blk_row, blk_col, plane_bsize, &txfm_param);
skip_trellis_based_on_satd[tx_type] = skip_trellis_opt_based_on_satd(
- x, &quant_param, plane, block, tx_size, cpi->oxcf.quant_b_adapt, qstep,
- txfm_params->coeff_opt_satd_threshold, skip_trellis);
+ x, &quant_param, plane, block, tx_size, cpi->oxcf.q_cfg.quant_b_adapt,
+ qstep, txfm_params->coeff_opt_satd_threshold, skip_trellis);
av1_quant(x, plane, block, &txfm_param, &quant_param);
diff --git a/av1/encoder/var_based_part.c b/av1/encoder/var_based_part.c
index 4b94a29..082bc31 100644
--- a/av1/encoder/var_based_part.c
+++ b/av1/encoder/var_based_part.c
@@ -848,7 +848,7 @@
int variance4x4downsample[64];
const int segment_id = xd->mi[0]->segment_id;
- if (cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ && cm->seg.enabled &&
+ if (cpi->oxcf.q_cfg.aq_mode == CYCLIC_REFRESH_AQ && cm->seg.enabled &&
cyclic_refresh_segment_id_boosted(segment_id) &&
cpi->sf.rt_sf.use_nonrd_pick_mode) {
int q = av1_get_qindex(&cm->seg, segment_id, cm->quant_params.base_qindex);