FPMT: Abstract previous q related rc members to p_rc
Moved previous frames q related members from RATE_CONTROL
to PRIMARY_RATE_CONTROL. Removed corresponding temporary
variables used for simulation.
Change-Id: I7042b68fbebd41a0ca5009c42156630de333d447
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c
index e734def..d2efe93 100644
--- a/av1/encoder/encoder.c
+++ b/av1/encoder/encoder.c
@@ -4545,8 +4545,8 @@
cur_cpi->rc.frames_since_key = frames_since_key;
cur_cpi->rc.frames_to_key = frames_to_key;
cur_cpi->rc.frames_to_fwd_kf = frames_to_fwd_kf;
+ cur_cpi->rc.active_worst_quality = first_cpi->rc.active_worst_quality;
if (gf_group->update_type[cur_cpi->gf_frame_index] == INTNL_ARF_UPDATE) {
- cur_cpi->rc.active_worst_quality = first_cpi->rc.active_worst_quality;
cur_cpi->common.lf.mode_ref_delta_enabled = 1;
}
cur_cpi->do_frame_data_update = false;
diff --git a/av1/encoder/encoder_utils.c b/av1/encoder/encoder_utils.c
index 66e4117..f0fbc54 100644
--- a/av1/encoder/encoder_utils.c
+++ b/av1/encoder/encoder_utils.c
@@ -310,15 +310,7 @@
const RATE_CONTROL *const rc = &cpi->rc;
struct segmentation *const seg = &cm->seg;
- double avg_q;
-#if CONFIG_FRAME_PARALLEL_ENCODE
- avg_q = (cpi->ppi->gf_group.frame_parallel_level[cpi->gf_frame_index] > 0)
- ? cpi->ppi->p_rc.temp_avg_q
- : cpi->rc.avg_q;
-#else
- avg_q = rc->avg_q;
-#endif
-
+ double avg_q = cpi->ppi->p_rc.avg_q;
int high_q = (int)(avg_q > 48.0);
int qi_delta;
diff --git a/av1/encoder/pass2_strategy.c b/av1/encoder/pass2_strategy.c
index 35c442f..649e176 100644
--- a/av1/encoder/pass2_strategy.c
+++ b/av1/encoder/pass2_strategy.c
@@ -3405,11 +3405,11 @@
rc->active_worst_quality = tmp_q;
rc->ni_av_qi = tmp_q;
- rc->last_q[INTER_FRAME] = tmp_q;
- rc->avg_q = av1_convert_qindex_to_q(tmp_q, cm->seq_params->bit_depth);
+ p_rc->last_q[INTER_FRAME] = tmp_q;
+ p_rc->avg_q = av1_convert_qindex_to_q(tmp_q, cm->seq_params->bit_depth);
p_rc->avg_frame_qindex[INTER_FRAME] = tmp_q;
- rc->last_q[KEY_FRAME] = (tmp_q + cpi->oxcf.rc_cfg.best_allowed_q) / 2;
- p_rc->avg_frame_qindex[KEY_FRAME] = rc->last_q[KEY_FRAME];
+ p_rc->last_q[KEY_FRAME] = (tmp_q + cpi->oxcf.rc_cfg.best_allowed_q) / 2;
+ p_rc->avg_frame_qindex[KEY_FRAME] = p_rc->last_q[KEY_FRAME];
}
if (cpi->twopass_frame.stats_in <
@@ -3889,6 +3889,7 @@
void av1_twopass_postencode_update(AV1_COMP *cpi) {
TWO_PASS *const twopass = &cpi->ppi->twopass;
RATE_CONTROL *const rc = &cpi->rc;
+ PRIMARY_RATE_CONTROL *const p_rc = &cpi->ppi->p_rc;
const RateControlCfg *const rc_cfg = &cpi->oxcf.rc_cfg;
// Increment the stats_in pointer.
@@ -3972,12 +3973,12 @@
cpi->ppi->gf_group.layer_depth[cpi->gf_frame_index];
int i;
for (i = pyramid_level; i <= MAX_ARF_LAYERS; ++i) {
- rc->active_best_quality[i] = cpi->common.quant_params.base_qindex;
+ p_rc->active_best_quality[i] = cpi->common.quant_params.base_qindex;
#if CONFIG_TUNE_VMAF
if (cpi->vmaf_info.original_qindex != -1 &&
(cpi->oxcf.tune_cfg.tuning >= AOM_TUNE_VMAF_WITH_PREPROCESSING &&
cpi->oxcf.tune_cfg.tuning <= AOM_TUNE_VMAF_NEG_MAX_GAIN)) {
- rc->active_best_quality[i] = cpi->vmaf_info.original_qindex;
+ p_rc->active_best_quality[i] = cpi->vmaf_info.original_qindex;
}
#endif
}
@@ -4083,26 +4084,6 @@
}
#if CONFIG_FRAME_PARALLEL_ENCODE
- /* TODO(FPMT): The current update is happening in cpi->rc members,
- * this need to be taken care appropriately in final FPMT implementation
- * to carry these values to subsequent frames.
- *
- * The variable temp_active_best_quality is introduced only for quality
- * simulation purpose, it retains the value previous to the parallel
- * encode frames. The variable is updated based on the update flag.
- *
- * If there exist show_existing_frames between parallel frames, then to
- * retain the temp state do not update it. */
- if (cpi->do_frame_data_update && !show_existing_between_parallel_frames) {
- int i;
- const int pyramid_level =
- cpi->ppi->gf_group.layer_depth[cpi->gf_frame_index];
- if (!rc->is_src_frame_alt_ref) {
- for (i = pyramid_level; i <= MAX_ARF_LAYERS; ++i)
- cpi->ppi->p_rc.temp_active_best_quality[i] = rc->active_best_quality[i];
- }
- }
-
// Update the frame probabilities obtained from parallel encode frames
FrameProbInfo *const frame_probs = &cpi->ppi->frame_probs;
int i, j, loop;
diff --git a/av1/encoder/ratectrl.c b/av1/encoder/ratectrl.c
index 02592aa..64fc56a 100644
--- a/av1/encoder/ratectrl.c
+++ b/av1/encoder/ratectrl.c
@@ -341,6 +341,10 @@
p_rc->avg_frame_qindex[INTER_FRAME] =
(worst_allowed_q + rc_cfg->best_allowed_q) / 2;
}
+ p_rc->avg_q = av1_convert_qindex_to_q(rc_cfg->worst_allowed_q,
+ oxcf->tool_cfg.bit_depth);
+ p_rc->last_q[KEY_FRAME] = rc_cfg->best_allowed_q;
+ p_rc->last_q[INTER_FRAME] = rc_cfg->worst_allowed_q;
}
void av1_rc_init(const AV1EncoderConfig *oxcf, RATE_CONTROL *rc,
@@ -348,9 +352,6 @@
const RateControlCfg *const rc_cfg = &oxcf->rc_cfg;
int i;
- rc->last_q[KEY_FRAME] = rc_cfg->best_allowed_q;
- rc->last_q[INTER_FRAME] = rc_cfg->worst_allowed_q;
-
rc->buffer_level = p_rc->starting_buffer_level;
rc->bits_off_target = p_rc->starting_buffer_level;
@@ -365,8 +366,6 @@
rc->frames_till_gf_update_due = 0;
rc->ni_av_qi = rc_cfg->worst_allowed_q;
rc->ni_tot_qi = 0;
- rc->avg_q = av1_convert_qindex_to_q(rc_cfg->worst_allowed_q,
- oxcf->tool_cfg.bit_depth);
for (i = 0; i < RATE_FACTOR_LEVELS; ++i) {
rc->rate_correction_factors[i] = 0.7;
@@ -873,24 +872,14 @@
static int calc_active_worst_quality_no_stats_vbr(const AV1_COMP *cpi) {
const RATE_CONTROL *const rc = &cpi->rc;
+ const PRIMARY_RATE_CONTROL *const p_rc = &cpi->ppi->p_rc;
const RefreshFrameFlagsInfo *const refresh_frame_flags = &cpi->refresh_frame;
const unsigned int curr_frame = cpi->common.current_frame.frame_number;
int active_worst_quality;
int last_q_key_frame;
int last_q_inter_frame;
-#if CONFIG_FRAME_PARALLEL_ENCODE
- last_q_key_frame =
- (cpi->ppi->gf_group.frame_parallel_level[cpi->gf_frame_index] > 0)
- ? cpi->ppi->p_rc.temp_last_q[KEY_FRAME]
- : cpi->rc.last_q[KEY_FRAME];
- last_q_inter_frame =
- (cpi->ppi->gf_group.frame_parallel_level[cpi->gf_frame_index] > 0)
- ? cpi->ppi->p_rc.temp_last_q[INTER_FRAME]
- : cpi->rc.last_q[INTER_FRAME];
-#else
- last_q_key_frame = rc->last_q[KEY_FRAME];
- last_q_inter_frame = rc->last_q[INTER_FRAME];
-#endif
+ last_q_key_frame = p_rc->last_q[KEY_FRAME];
+ last_q_inter_frame = p_rc->last_q[INTER_FRAME];
if (cpi->common.current_frame.frame_type == KEY_FRAME) {
active_worst_quality =
@@ -986,7 +975,7 @@
// the maximum key frame interval. Here force the Q to a range
// based on the ambient Q to reduce the risk of popping.
if (p_rc->this_key_frame_forced) {
- int qindex = rc->last_boosted_qindex;
+ int qindex = p_rc->last_boosted_qindex;
double last_boosted_q = av1_convert_qindex_to_q(qindex, bit_depth);
int delta_qindex = av1_compute_qdelta(rc, last_boosted_q,
(last_boosted_q * 0.75), bit_depth);
@@ -1084,7 +1073,7 @@
// Special case code to try and match quality with forced key frames
if (current_frame->frame_type == KEY_FRAME && p_rc->this_key_frame_forced) {
- q = rc->last_boosted_qindex;
+ q = p_rc->last_boosted_qindex;
} else {
q = av1_rc_regulate_q(cpi, rc->this_frame_target, active_best_quality,
active_worst_quality, width, height);
@@ -1261,15 +1250,7 @@
av1_compute_qdelta(rc, q_val, q_val * 0.25, bit_depth);
active_best_quality = AOMMAX(qindex + delta_qindex, rc->best_quality);
} else if (p_rc->this_key_frame_forced) {
- int qindex;
-#if CONFIG_FRAME_PARALLEL_ENCODE
- qindex =
- (cpi->ppi->gf_group.frame_parallel_level[cpi->gf_frame_index] > 0)
- ? p_rc->temp_last_boosted_qindex
- : rc->last_boosted_qindex;
-#else
- qindex = rc->last_boosted_qindex;
-#endif
+ int qindex = p_rc->last_boosted_qindex;
const double last_boosted_q = av1_convert_qindex_to_q(qindex, bit_depth);
const int delta_qindex = av1_compute_qdelta(
rc, last_boosted_q, last_boosted_q * 0.75, bit_depth);
@@ -1378,13 +1359,7 @@
// Special case code to try and match quality with forced key frames
} else if ((current_frame->frame_type == KEY_FRAME) &&
p_rc->this_key_frame_forced) {
-#if CONFIG_FRAME_PARALLEL_ENCODE
- q = (cpi->ppi->gf_group.frame_parallel_level[cpi->gf_frame_index] > 0)
- ? p_rc->temp_last_boosted_qindex
- : rc->last_boosted_qindex;
-#else
- q = rc->last_boosted_qindex;
-#endif
+ q = p_rc->last_boosted_qindex;
} else {
q = av1_rc_regulate_q(cpi, rc->this_frame_target, active_best_quality,
active_worst_quality, width, height);
@@ -1469,14 +1444,7 @@
// Handle the special case for forward reference key frames.
// Increase the boost because this keyframe is used as a forward and
// backward reference.
- int qindex;
-#if CONFIG_FRAME_PARALLEL_ENCODE
- qindex = (cpi->ppi->gf_group.frame_parallel_level[cpi->gf_frame_index] > 0)
- ? p_rc->temp_last_boosted_qindex
- : rc->last_boosted_qindex;
-#else
- qindex = rc->last_boosted_qindex;
-#endif
+ int qindex = p_rc->last_boosted_qindex;
const double last_boosted_q = av1_convert_qindex_to_q(qindex, bit_depth);
const int delta_qindex = av1_compute_qdelta(
rc, last_boosted_q, last_boosted_q * 0.25, bit_depth);
@@ -1488,15 +1456,7 @@
double last_boosted_q;
int delta_qindex;
int qindex;
- int last_boosted_qindex;
-#if CONFIG_FRAME_PARALLEL_ENCODE
- last_boosted_qindex =
- (cpi->ppi->gf_group.frame_parallel_level[cpi->gf_frame_index] > 0)
- ? p_rc->temp_last_boosted_qindex
- : rc->last_boosted_qindex;
-#else
- last_boosted_qindex = rc->last_boosted_qindex;
-#endif
+ int last_boosted_qindex = p_rc->last_boosted_qindex;
if (is_stat_consumption_stage_twopass(cpi) &&
cpi->ppi->twopass.last_kfgroup_zeromotion_pct >= STATIC_MOTION_THRESH) {
qindex = AOMMIN(p_rc->last_kf_qindex, last_boosted_qindex);
@@ -1658,15 +1618,7 @@
const RATE_CONTROL *const rc = &cpi->rc;
const PRIMARY_RATE_CONTROL *const p_rc = &cpi->ppi->p_rc;
int q;
- int last_boosted_qindex;
-#if CONFIG_FRAME_PARALLEL_ENCODE
- last_boosted_qindex =
- (cpi->ppi->gf_group.frame_parallel_level[cpi->gf_frame_index] > 0)
- ? p_rc->temp_last_boosted_qindex
- : rc->last_boosted_qindex;
-#else
- last_boosted_qindex = rc->last_boosted_qindex;
-#endif
+ int last_boosted_qindex = p_rc->last_boosted_qindex;
if (cpi->oxcf.rc_cfg.mode == AOM_Q ||
(frame_is_intra_only(cm) && !p_rc->this_key_frame_forced &&
@@ -1869,6 +1821,7 @@
int *top_index) {
const AV1_COMMON *const cm = &cpi->common;
const RATE_CONTROL *const rc = &cpi->rc;
+ const PRIMARY_RATE_CONTROL *const p_rc = &cpi->ppi->p_rc;
const AV1EncoderConfig *const oxcf = &cpi->oxcf;
const RefreshFrameFlagsInfo *const refresh_frame_flags = &cpi->refresh_frame;
const GF_GROUP *gf_group = &cpi->ppi->gf_group;
@@ -1913,16 +1866,7 @@
active_best_quality = get_active_best_quality(cpi, active_worst_quality,
cq_level, gf_index);
} else {
- int local_active_best_quality;
-#if CONFIG_FRAME_PARALLEL_ENCODE
- local_active_best_quality =
- (cpi->ppi->gf_group.frame_parallel_level[cpi->gf_frame_index] > 0)
- ? cpi->ppi->p_rc.temp_active_best_quality[pyramid_level - 1]
- : cpi->rc.active_best_quality[pyramid_level - 1];
-#else
- local_active_best_quality = rc->active_best_quality[pyramid_level - 1];
-#endif
- active_best_quality = local_active_best_quality + 1;
+ active_best_quality = p_rc->active_best_quality[pyramid_level - 1] + 1;
active_best_quality = AOMMIN(active_best_quality, active_worst_quality);
#ifdef STRICT_RC
active_best_quality += (active_worst_quality - active_best_quality) / 16;
@@ -2074,7 +2018,7 @@
// Keep a record of last Q and ambient average Q.
if (current_frame->frame_type == KEY_FRAME) {
- rc->last_q[KEY_FRAME] = qindex;
+ p_rc->last_q[KEY_FRAME] = qindex;
p_rc->avg_frame_qindex[KEY_FRAME] =
ROUND_POWER_OF_TWO(3 * p_rc->avg_frame_qindex[KEY_FRAME] + qindex, 2);
} else {
@@ -2082,12 +2026,12 @@
(!rc->is_src_frame_alt_ref &&
!(refresh_frame_flags->golden_frame || is_intrnl_arf ||
refresh_frame_flags->alt_ref_frame))) {
- rc->last_q[INTER_FRAME] = qindex;
+ p_rc->last_q[INTER_FRAME] = qindex;
p_rc->avg_frame_qindex[INTER_FRAME] = ROUND_POWER_OF_TWO(
3 * p_rc->avg_frame_qindex[INTER_FRAME] + qindex, 2);
p_rc->ni_frames++;
p_rc->tot_q += av1_convert_qindex_to_q(qindex, cm->seq_params->bit_depth);
- rc->avg_q = p_rc->tot_q / p_rc->ni_frames;
+ p_rc->avg_q = p_rc->tot_q / p_rc->ni_frames;
// Calculate the average Q for normal inter frames (not key or GFU
// frames).
rc->ni_tot_qi += qindex;
@@ -2099,12 +2043,12 @@
// If all mbs in this group are skipped only update if the Q value is
// better than that already stored.
// This is used to help set quality in forced key frames to reduce popping
- if ((qindex < rc->last_boosted_qindex) ||
+ if ((qindex < p_rc->last_boosted_qindex) ||
(current_frame->frame_type == KEY_FRAME) ||
(!p_rc->constrained_gf_group &&
(refresh_frame_flags->alt_ref_frame || is_intrnl_arf ||
(refresh_frame_flags->golden_frame && !rc->is_src_frame_alt_ref)))) {
- rc->last_boosted_qindex = qindex;
+ p_rc->last_boosted_qindex = qindex;
}
if (current_frame->frame_type == KEY_FRAME) p_rc->last_kf_qindex = qindex;
@@ -2141,29 +2085,13 @@
#if CONFIG_FRAME_PARALLEL_ENCODE
/* TODO(FPMT): The current update is happening to cpi->rc members,
* this need to be taken care appropriately in final FPMT implementation
- * to carry these values to subsequent frames. The last_q, avg_q and
- * last_boosted_qindex update are accumulated across frames, so the values
- * from all individual parallel frames need to be taken into account after all
- * the parallel frames are encoded.
- *
- * The variables temp_avg_frame_qindex, temp_last_q, temp_avg_q,
- * temp_last_boosted_qindex are introduced only for quality simulation
- * purpose, it retains the value previous to the parallel encode frames. The
- * variables are updated based on the update flag.
- *
- * If there exist show_existing_frames between parallel frames, then to
- * retain the temp state do not update it. */
+ * to carry these values to subsequent frames. */
int show_existing_between_parallel_frames =
(cpi->ppi->gf_group.update_type[cpi->gf_frame_index] ==
INTNL_OVERLAY_UPDATE &&
cpi->ppi->gf_group.frame_parallel_level[cpi->gf_frame_index + 1] == 2);
if (cpi->do_frame_data_update && !show_existing_between_parallel_frames) {
- for (int i = 0; i < FRAME_TYPES; i++) {
- p_rc->temp_last_q[i] = rc->last_q[i];
- }
- p_rc->temp_avg_q = rc->avg_q;
- p_rc->temp_last_boosted_qindex = rc->last_boosted_qindex;
p_rc->temp_total_actual_bits = rc->total_actual_bits;
p_rc->temp_projected_frame_size = rc->projected_frame_size;
for (int i = 0; i < RATE_FACTOR_LEVELS; i++)
@@ -2828,9 +2756,10 @@
// Also check if projected qindex is close to previous qindex, if so
// increase correction factor (to push qindex higher and avoid overshoot).
if (tot_scale_change >= 1.0) {
- if (tot_scale_change < 4.0 && qindex > 130 * rc->last_q[INTER_FRAME] / 100)
+ if (tot_scale_change < 4.0 &&
+ qindex > 130 * p_rc->last_q[INTER_FRAME] / 100)
rc->rate_correction_factors[INTER_NORMAL] *= 0.8;
- if (qindex <= 120 * rc->last_q[INTER_FRAME] / 100)
+ if (qindex <= 120 * p_rc->last_q[INTER_FRAME] / 100)
rc->rate_correction_factors[INTER_NORMAL] *= 2.0;
}
}
@@ -2872,7 +2801,7 @@
// Ignore samples close to key frame, since QP is usually high after key.
if (cpi->rc.frames_since_key > cpi->framerate) {
const int window = AOMMIN(30, (int)(2 * cpi->framerate));
- rc->resize_avg_qp += rc->last_q[INTER_FRAME];
+ rc->resize_avg_qp += p_rc->last_q[INTER_FRAME];
if (cpi->rc.buffer_level < (int)(30 * p_rc->optimal_buffer_level / 100))
++rc->resize_buffer_underflow;
++rc->resize_count;
diff --git a/av1/encoder/ratectrl.h b/av1/encoder/ratectrl.h
index 54135d8..a0badc4 100644
--- a/av1/encoder/ratectrl.h
+++ b/av1/encoder/ratectrl.h
@@ -145,16 +145,6 @@
int sb64_target_rate;
/*!
- * Q used on last encoded frame of the given type.
- */
- int last_q[FRAME_TYPES];
-
- /*!
- * Q used for last boosted (non leaf) frame (GF/KF/ARF)
- */
- int last_boosted_qindex;
-
- /*!
* Correction factors used to adjust the q estimate for a given target rate
* in the encode loop.
*/
@@ -201,7 +191,6 @@
int ni_av_qi;
int ni_tot_qi;
- double avg_q;
int64_t buffer_level;
int64_t bits_off_target;
@@ -245,10 +234,6 @@
* Proposed maximum alloed Q for current frame
*/
int active_worst_quality;
- /*!
- * Proposed minimum allowed Q different layers in a coding pyramid
- */
- int active_best_quality[MAX_ARF_LAYERS + 1];
/*!\cond */
// Track amount of low motion in scene
@@ -368,33 +353,28 @@
*/
int avg_frame_qindex[FRAME_TYPES];
+ /*!
+ * Proposed minimum allowed Q different layers in a coding pyramid
+ */
+ int active_best_quality[MAX_ARF_LAYERS + 1];
+
+ /*!
+ * Q used for last boosted (non leaf) frame (GF/KF/ARF)
+ */
+ int last_boosted_qindex;
+
+ /*!
+ * Average Q value of previous inter frames
+ */
+ double avg_q;
+
+ /*!
+ * Q used on last encoded frame of the given type.
+ */
+ int last_q[FRAME_TYPES];
#if CONFIG_FRAME_PARALLEL_ENCODE
/*!
* Temporary variable used in simulating the delayed update of
- * active_best_quality.
- */
- int temp_active_best_quality[MAX_ARF_LAYERS + 1];
-
- /*!
- * Temporary variable used in simulating the delayed update of
- * last_boosted_qindex.
- */
- int temp_last_boosted_qindex;
-
- /*!
- * Temporary variable used in simulating the delayed update of
- * avg_q.
- */
- double temp_avg_q;
-
- /*!
- * Temporary variable used in simulating the delayed update of
- * last_q.
- */
- int temp_last_q[FRAME_TYPES];
-
- /*!
- * Temporary variable used in simulating the delayed update of
* projected_frame_size.
*/
int temp_projected_frame_size;
diff --git a/av1/encoder/svc_layercontext.c b/av1/encoder/svc_layercontext.c
index d456d9d..9a74950 100644
--- a/av1/encoder/svc_layercontext.c
+++ b/av1/encoder/svc_layercontext.c
@@ -42,7 +42,7 @@
lrc->total_actual_bits = 0;
lrc->ni_tot_qi = 0;
lp_rc->tot_q = 0.0;
- lrc->avg_q = 0.0;
+ lp_rc->avg_q = 0.0;
lp_rc->ni_frames = 0;
lrc->decimation_count = 0;
lrc->decimation_factor = 0;
@@ -52,7 +52,7 @@
lrc->rate_correction_factors[i] = 1.0;
}
lc->target_bandwidth = lc->layer_target_bitrate;
- lrc->last_q[INTER_FRAME] = lrc->worst_quality;
+ lp_rc->last_q[INTER_FRAME] = lrc->worst_quality;
lp_rc->avg_frame_qindex[INTER_FRAME] = lrc->worst_quality;
lp_rc->avg_frame_qindex[KEY_FRAME] = lrc->worst_quality;
lrc->buffer_level =
diff --git a/doc/dev_guide/av1_encoder.dox b/doc/dev_guide/av1_encoder.dox
index a19db95..d035641 100644
--- a/doc/dev_guide/av1_encoder.dox
+++ b/doc/dev_guide/av1_encoder.dox
@@ -656,7 +656,7 @@
As well as \ref RATE_CONTROL.active_worst_quality, the two pass code also
maintains a record of the actual Q value used to encode previous frames
at each level in the current pyramid hierarchy
-(\ref RATE_CONTROL.active_best_quality). The function
+(\ref PRIMARY_RATE_CONTROL.active_best_quality). The function
\ref rc_pick_q_and_bounds(), uses these values to set a permitted Q range
for each frame.