FPMT SIMULATION: Handle recode for parallel frames
Introduce frame_level_rate_correction_factors specific
to the frame, in order to track the corrected rate within
the parallel frames. This variable is initialised with
rate_correction_factor previous to the parallel frames.
Change-Id: I751976922685fd182976b0e74608da98c6e4d756
diff --git a/av1/encoder/encode_strategy.c b/av1/encoder/encode_strategy.c
index 81d5b19..d4d927e 100644
--- a/av1/encoder/encode_strategy.c
+++ b/av1/encoder/encode_strategy.c
@@ -1474,6 +1474,16 @@
#if CONFIG_COLLECT_COMPONENT_TIMING
start_timing(cpi, av1_get_second_pass_params_time);
#endif
+
+#if CONFIG_FRAME_PARALLEL_ENCODE
+ // Initialise frame_level_rate_correction_factors with value previous
+ // to the parallel frames.
+ if (cpi->ppi->gf_group.frame_parallel_level[cpi->gf_frame_index] > 0) {
+ for (int i = 0; i < RATE_FACTOR_LEVELS; i++)
+ cpi->rc.frame_level_rate_correction_factors[i] =
+ cpi->ppi->p_rc.temp_rate_correction_factors[i];
+ }
+#endif
av1_get_second_pass_params(cpi, &frame_params, &frame_input, *frame_flags);
#if CONFIG_COLLECT_COMPONENT_TIMING
end_timing(cpi, av1_get_second_pass_params_time);
diff --git a/av1/encoder/ratectrl.c b/av1/encoder/ratectrl.c
index cfb027f..2c6d2a0 100644
--- a/av1/encoder/ratectrl.c
+++ b/av1/encoder/ratectrl.c
@@ -527,15 +527,15 @@
#if CONFIG_FRAME_PARALLEL_ENCODE
rate_correction_factors_kfstd =
(cpi->ppi->gf_group.frame_parallel_level[cpi->gf_frame_index] > 0)
- ? cpi->ppi->p_rc.temp_rate_correction_factors[KF_STD]
+ ? rc->frame_level_rate_correction_factors[KF_STD]
: rc->rate_correction_factors[KF_STD];
rate_correction_factors_gfarfstd =
(cpi->ppi->gf_group.frame_parallel_level[cpi->gf_frame_index] > 0)
- ? cpi->ppi->p_rc.temp_rate_correction_factors[GF_ARF_STD]
+ ? rc->frame_level_rate_correction_factors[GF_ARF_STD]
: rc->rate_correction_factors[GF_ARF_STD];
rate_correction_factors_internormal =
(cpi->ppi->gf_group.frame_parallel_level[cpi->gf_frame_index] > 0)
- ? cpi->ppi->p_rc.temp_rate_correction_factors[INTER_NORMAL]
+ ? rc->frame_level_rate_correction_factors[INTER_NORMAL]
: rc->rate_correction_factors[INTER_NORMAL];
#else
rate_correction_factors_kfstd = rc->rate_correction_factors[KF_STD];
@@ -553,7 +553,7 @@
#if CONFIG_FRAME_PARALLEL_ENCODE
rate_correction_factors_rflvl =
(cpi->ppi->gf_group.frame_parallel_level[cpi->gf_frame_index] > 0)
- ? cpi->ppi->p_rc.temp_rate_correction_factors[rf_lvl]
+ ? rc->frame_level_rate_correction_factors[rf_lvl]
: rc->rate_correction_factors[rf_lvl];
#else
rate_correction_factors_rflvl = rc->rate_correction_factors[rf_lvl];
@@ -588,11 +588,14 @@
* \return None but updates the rate correction factor for the
* current frame type in cpi->rc.
*/
-static void set_rate_correction_factor(AV1_COMP *cpi, double factor, int width,
- int height) {
+static void set_rate_correction_factor(AV1_COMP *cpi,
+#if CONFIG_FRAME_PARALLEL_ENCODE
+ int is_encode_stage,
+#endif
+ double factor, int width, int height) {
RATE_CONTROL *const rc = &cpi->rc;
const RefreshFrameFlagsInfo *const refresh_frame_flags = &cpi->refresh_frame;
-
+ int update_default_rcf = 1;
// Normalize RCF to account for the size-dependent scaling factor.
factor /= resize_rate_factor(&cpi->oxcf.frm_dim_cfg, width, height);
@@ -603,21 +606,40 @@
} else if (is_stat_consumption_stage(cpi)) {
const RATE_FACTOR_LEVEL rf_lvl =
get_rate_factor_level(&cpi->ppi->gf_group, cpi->gf_frame_index);
- rc->rate_correction_factors[rf_lvl] = factor;
+#if CONFIG_FRAME_PARALLEL_ENCODE
+ if (is_encode_stage &&
+ cpi->ppi->gf_group.frame_parallel_level[cpi->gf_frame_index] > 0) {
+ rc->frame_level_rate_correction_factors[rf_lvl] = factor;
+ update_default_rcf = 0;
+ }
+#endif
+ if (update_default_rcf) rc->rate_correction_factors[rf_lvl] = factor;
} else {
if ((refresh_frame_flags->alt_ref_frame ||
refresh_frame_flags->golden_frame) &&
!rc->is_src_frame_alt_ref && !cpi->ppi->use_svc &&
(cpi->oxcf.rc_cfg.mode != AOM_CBR ||
- cpi->oxcf.rc_cfg.gf_cbr_boost_pct > 20))
+ cpi->oxcf.rc_cfg.gf_cbr_boost_pct > 20)) {
rc->rate_correction_factors[GF_ARF_STD] = factor;
- else
- rc->rate_correction_factors[INTER_NORMAL] = factor;
+ } else {
+#if CONFIG_FRAME_PARALLEL_ENCODE
+ if (is_encode_stage &&
+ cpi->ppi->gf_group.frame_parallel_level[cpi->gf_frame_index] > 0) {
+ rc->frame_level_rate_correction_factors[INTER_NORMAL] = factor;
+ update_default_rcf = 0;
+ }
+#endif
+ if (update_default_rcf)
+ rc->rate_correction_factors[INTER_NORMAL] = factor;
+ }
}
}
-void av1_rc_update_rate_correction_factors(AV1_COMP *cpi, int width,
- int height) {
+void av1_rc_update_rate_correction_factors(AV1_COMP *cpi,
+#if CONFIG_FRAME_PARALLEL_ENCODE
+ int is_encode_stage,
+#endif
+ int width, int height) {
const AV1_COMMON *const cm = &cpi->common;
int correction_factor = 100;
double rate_correction_factor =
@@ -688,7 +710,11 @@
rate_correction_factor = MIN_BPB_FACTOR;
}
- set_rate_correction_factor(cpi, rate_correction_factor, width, height);
+ set_rate_correction_factor(cpi,
+#if CONFIG_FRAME_PARALLEL_ENCODE
+ is_encode_stage,
+#endif
+ rate_correction_factor, width, height);
}
// Calculate rate for the given 'q'.
@@ -2084,7 +2110,11 @@
rc->projected_frame_size = (int)(bytes_used << 3);
// Post encode loop adjustment of Q prediction.
- av1_rc_update_rate_correction_factors(cpi, cm->width, cm->height);
+ av1_rc_update_rate_correction_factors(cpi,
+#if CONFIG_FRAME_PARALLEL_ENCODE
+ 0,
+#endif
+ cm->width, cm->height);
// Keep a record of last Q and ambient average Q.
if (current_frame->frame_type == KEY_FRAME) {
diff --git a/av1/encoder/ratectrl.h b/av1/encoder/ratectrl.h
index 96279de..a6273df 100644
--- a/av1/encoder/ratectrl.h
+++ b/av1/encoder/ratectrl.h
@@ -263,6 +263,7 @@
int resize_count;
#if CONFIG_FRAME_PARALLEL_ENCODE
int frame_level_fast_extra_bits;
+ double frame_level_rate_correction_factors[RATE_FACTOR_LEVELS];
#endif
/*!\endcond */
} RATE_CONTROL;
@@ -512,8 +513,11 @@
*
* \return None but updates the relevant rate correction factor in cpi->rc
*/
-void av1_rc_update_rate_correction_factors(struct AV1_COMP *cpi, int width,
- int height);
+void av1_rc_update_rate_correction_factors(struct AV1_COMP *cpi,
+#if CONFIG_FRAME_PARALLEL_ENCODE
+ int is_encode_stage,
+#endif
+ int width, int height);
/*!\cond */
// Decide if we should drop this frame: For 1-pass CBR.
diff --git a/av1/encoder/rc_utils.h b/av1/encoder/rc_utils.h
index 0a9d02d..ef2bfb1 100644
--- a/av1/encoder/rc_utils.h
+++ b/av1/encoder/rc_utils.h
@@ -181,13 +181,21 @@
return factor;
}
-static AOM_INLINE int get_regulated_q_overshoot(AV1_COMP *const cpi, int q_low,
- int q_high, int top_index,
+static AOM_INLINE int get_regulated_q_overshoot(AV1_COMP *const cpi,
+#if CONFIG_FRAME_PARALLEL_ENCODE
+ int is_encode_stage,
+#endif
+ int q_low, int q_high,
+ int top_index,
int bottom_index) {
const AV1_COMMON *const cm = &cpi->common;
const RATE_CONTROL *const rc = &cpi->rc;
- av1_rc_update_rate_correction_factors(cpi, cm->width, cm->height);
+ av1_rc_update_rate_correction_factors(cpi,
+#if CONFIG_FRAME_PARALLEL_ENCODE
+ is_encode_stage,
+#endif
+ cm->width, cm->height);
int q_regulated =
av1_rc_regulate_q(cpi, rc->this_frame_target, bottom_index,
@@ -195,7 +203,11 @@
int retries = 0;
while (q_regulated < q_low && retries < 10) {
- av1_rc_update_rate_correction_factors(cpi, cm->width, cm->height);
+ av1_rc_update_rate_correction_factors(cpi,
+#if CONFIG_FRAME_PARALLEL_ENCODE
+ is_encode_stage,
+#endif
+ cm->width, cm->height);
q_regulated =
av1_rc_regulate_q(cpi, rc->this_frame_target, bottom_index,
AOMMAX(q_high, top_index), cm->width, cm->height);
@@ -205,18 +217,29 @@
}
static AOM_INLINE int get_regulated_q_undershoot(AV1_COMP *const cpi,
+#if CONFIG_FRAME_PARALLEL_ENCODE
+ int is_encode_stage,
+#endif
int q_high, int top_index,
int bottom_index) {
const AV1_COMMON *const cm = &cpi->common;
const RATE_CONTROL *const rc = &cpi->rc;
- av1_rc_update_rate_correction_factors(cpi, cm->width, cm->height);
+ av1_rc_update_rate_correction_factors(cpi,
+#if CONFIG_FRAME_PARALLEL_ENCODE
+ is_encode_stage,
+#endif
+ cm->width, cm->height);
int q_regulated = av1_rc_regulate_q(cpi, rc->this_frame_target, bottom_index,
top_index, cm->width, cm->height);
int retries = 0;
while (q_regulated > q_high && retries < 10) {
- av1_rc_update_rate_correction_factors(cpi, cm->width, cm->height);
+ av1_rc_update_rate_correction_factors(cpi,
+#if CONFIG_FRAME_PARALLEL_ENCODE
+ is_encode_stage,
+#endif
+ cm->width, cm->height);
q_regulated = av1_rc_regulate_q(cpi, rc->this_frame_target, bottom_index,
top_index, cm->width, cm->height);
retries++;
@@ -365,19 +388,31 @@
if (*undershoot_seen || loop_count > 2 ||
(loop_count == 2 && !frame_is_intra_only(cm))) {
- av1_rc_update_rate_correction_factors(cpi, cm->width, cm->height);
+ av1_rc_update_rate_correction_factors(cpi,
+#if CONFIG_FRAME_PARALLEL_ENCODE
+ 1,
+#endif
+ cm->width, cm->height);
*q = (*q_high + *q_low + 1) / 2;
} else if (loop_count == 2 && frame_is_intra_only(cm)) {
const int q_mid = (*q_high + *q_low + 1) / 2;
- const int q_regulated = get_regulated_q_overshoot(
- cpi, *q_low, *q_high, top_index, bottom_index);
+ const int q_regulated =
+ get_regulated_q_overshoot(cpi,
+#if CONFIG_FRAME_PARALLEL_ENCODE
+ 1,
+#endif
+ *q_low, *q_high, top_index, bottom_index);
// Get 'q' in-between 'q_mid' and 'q_regulated' for a smooth
// transition between loop_count < 2 and loop_count > 2.
*q = (q_mid + q_regulated + 1) / 2;
} else {
- *q = get_regulated_q_overshoot(cpi, *q_low, *q_high, top_index,
- bottom_index);
+ *q =
+ get_regulated_q_overshoot(cpi,
+#if CONFIG_FRAME_PARALLEL_ENCODE
+ 1,
+#endif
+ *q_low, *q_high, top_index, bottom_index);
}
*overshoot_seen = 1;
@@ -387,12 +422,20 @@
if (*overshoot_seen || loop_count > 2 ||
(loop_count == 2 && !frame_is_intra_only(cm))) {
- av1_rc_update_rate_correction_factors(cpi, cm->width, cm->height);
+ av1_rc_update_rate_correction_factors(cpi,
+#if CONFIG_FRAME_PARALLEL_ENCODE
+ 1,
+#endif
+ cm->width, cm->height);
*q = (*q_high + *q_low) / 2;
} else if (loop_count == 2 && frame_is_intra_only(cm)) {
const int q_mid = (*q_high + *q_low) / 2;
const int q_regulated =
- get_regulated_q_undershoot(cpi, *q_high, top_index, bottom_index);
+ get_regulated_q_undershoot(cpi,
+#if CONFIG_FRAME_PARALLEL_ENCODE
+ 1,
+#endif
+ *q_high, top_index, bottom_index);
// Get 'q' in-between 'q_mid' and 'q_regulated' for a smooth
// transition between loop_count < 2 and loop_count > 2.
*q = (q_mid + q_regulated) / 2;
@@ -405,7 +448,11 @@
*q_low = *q;
}
} else {
- *q = get_regulated_q_undershoot(cpi, *q_high, top_index, bottom_index);
+ *q = get_regulated_q_undershoot(cpi,
+#if CONFIG_FRAME_PARALLEL_ENCODE
+ 1,
+#endif
+ *q_high, top_index, bottom_index);
// Special case reset for qlow for constrained quality.
// This should only trigger where there is very substantial