FPMT SIMULATION: Delay avg_frame_qindex update
This patch introduces temp_avg_frame_qindex variable
which retains the avg_frame_qindex value previous to
the parallel frames. The temp_avg_frame_qindex updates
are enabled based on do_frame_update_flag. The changes
are done only in AOM_Q path and is used for quality
simulation purpose.
Change-Id: I7ec08db5b6b723a0ff9d1c2200f8a2293c5cae31
diff --git a/av1/encoder/aq_cyclicrefresh.c b/av1/encoder/aq_cyclicrefresh.c
index f78d90c..40b8c25 100644
--- a/av1/encoder/aq_cyclicrefresh.c
+++ b/av1/encoder/aq_cyclicrefresh.c
@@ -398,11 +398,20 @@
int qp_thresh = AOMMIN(20, rc->best_quality << 1);
int qp_max_thresh = 118 * MAXQ >> 7;
cr->apply_cyclic_refresh = 1;
+ int avg_frame_qindex_inter_frame;
+#if CONFIG_FRAME_PARALLEL_ENCODE
+ avg_frame_qindex_inter_frame =
+ (cpi->ppi->gf_group.frame_parallel_level[cpi->gf_frame_index] > 0)
+ ? cpi->ppi->temp_avg_frame_qindex[INTER_FRAME]
+ : rc->avg_frame_qindex[INTER_FRAME];
+#else
+ avg_frame_qindex_inter_frame = rc->avg_frame_qindex[INTER_FRAME];
+#endif // CONFIG_FRAME_PARALLEL_ENCODE
if (frame_is_intra_only(cm) || is_lossless_requested(&cpi->oxcf.rc_cfg) ||
cpi->svc.temporal_layer_id > 0 ||
- rc->avg_frame_qindex[INTER_FRAME] < qp_thresh ||
+ avg_frame_qindex_inter_frame < qp_thresh ||
(rc->frames_since_key > 20 &&
- rc->avg_frame_qindex[INTER_FRAME] > qp_max_thresh) ||
+ avg_frame_qindex_inter_frame > qp_max_thresh) ||
(rc->avg_frame_low_motion < 45 && rc->frames_since_key > 40)) {
cr->apply_cyclic_refresh = 0;
return;
diff --git a/av1/encoder/encoder.h b/av1/encoder/encoder.h
index f3aac06..89c1ac1 100644
--- a/av1/encoder/encoder.h
+++ b/av1/encoder/encoder.h
@@ -2179,6 +2179,12 @@
* Temporary variable simulating the delayed frame_probability update.
*/
FrameProbInfo temp_frame_probs;
+
+ /*!
+ * Temporary variable used in simulating the delayed update of
+ * avg_frame_qindex.
+ */
+ int temp_avg_frame_qindex[FRAME_TYPES];
#endif // CONFIG_FRAME_PARALLEL_ENCODE
/*!
* Encode stage top level structure
diff --git a/av1/encoder/ratectrl.c b/av1/encoder/ratectrl.c
index f34d460..7a5c529 100644
--- a/av1/encoder/ratectrl.c
+++ b/av1/encoder/ratectrl.c
@@ -1175,10 +1175,25 @@
// Use the lower of active_worst_quality and recent
// average Q as basis for GF/ARF best Q limit unless last frame was
// a key frame.
+ int avg_frame_qindex_inter_frame;
+ int avg_frame_qindex_key_frame;
+#if CONFIG_FRAME_PARALLEL_ENCODE
+ avg_frame_qindex_inter_frame =
+ (cpi->ppi->gf_group.frame_parallel_level[cpi->gf_frame_index] > 0)
+ ? cpi->ppi->temp_avg_frame_qindex[INTER_FRAME]
+ : cpi->rc.avg_frame_qindex[INTER_FRAME];
+ avg_frame_qindex_key_frame =
+ (cpi->ppi->gf_group.frame_parallel_level[cpi->gf_frame_index] > 0)
+ ? cpi->ppi->temp_avg_frame_qindex[KEY_FRAME]
+ : cpi->rc.avg_frame_qindex[KEY_FRAME];
+#else
+ avg_frame_qindex_inter_frame = rc->avg_frame_qindex[INTER_FRAME];
+ avg_frame_qindex_key_frame = rc->avg_frame_qindex[KEY_FRAME];
+#endif
q = (rc->frames_since_key > 1 &&
- rc->avg_frame_qindex[INTER_FRAME] < active_worst_quality)
- ? rc->avg_frame_qindex[INTER_FRAME]
- : rc->avg_frame_qindex[KEY_FRAME];
+ avg_frame_qindex_inter_frame < active_worst_quality)
+ ? avg_frame_qindex_inter_frame
+ : avg_frame_qindex_key_frame;
// For constrained quality dont allow Q less than the cq level
if (rc_mode == AOM_CQ) {
if (q < cq_level) q = cq_level;
@@ -1545,6 +1560,7 @@
const GF_GROUP *gf_group = &cpi->ppi->gf_group;
const enum aom_rc_mode rc_mode = oxcf->rc_cfg.mode;
int *inter_minq;
+ int avg_frame_qindex_inter_frame;
ASSIGN_MINQ_TABLE(bit_depth, inter_minq);
int active_best_quality = 0;
const int is_intrl_arf_boost =
@@ -1575,12 +1591,22 @@
// Determine active_best_quality for frames that are not leaf or overlay.
int q = active_worst_quality;
+#if CONFIG_FRAME_PARALLEL_ENCODE
+ // For quality simulation purpose - for parallel frames use previous
+ // avg_frame_qindex
+ avg_frame_qindex_inter_frame =
+ (cpi->ppi->gf_group.frame_parallel_level[cpi->gf_frame_index] > 0)
+ ? cpi->ppi->temp_avg_frame_qindex[INTER_FRAME]
+ : rc->avg_frame_qindex[INTER_FRAME];
+#else
+ avg_frame_qindex_inter_frame = rc->avg_frame_qindex[INTER_FRAME];
+#endif // CONFIG_FRAME_PARALLEL_ENCODE
// Use the lower of active_worst_quality and recent
// average Q as basis for GF/ARF best Q limit unless last frame was
// a key frame.
if (rc->frames_since_key > 1 &&
- rc->avg_frame_qindex[INTER_FRAME] < active_worst_quality) {
- q = rc->avg_frame_qindex[INTER_FRAME];
+ avg_frame_qindex_inter_frame < active_worst_quality) {
+ q = avg_frame_qindex_inter_frame;
}
if (rc_mode == AOM_CQ && q < cq_level) q = cq_level;
active_best_quality = get_gf_active_quality(p_rc, q, bit_depth);
@@ -1878,7 +1904,23 @@
rc->ni_av_qi = rc->ni_tot_qi / rc->ni_frames;
}
}
-
+#if CONFIG_FRAME_PARALLEL_ENCODE
+ /* TODO(FPMT): The current update is happening in cpi->rc.avg_frame_qindex,
+ * this need to be taken care appropriately in final FPMT implementation
+ * to carry these values to subsequent frames. The avg_frame_qindex update
+ * is 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 variable temp_avg_frame_qindex 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 (cpi->do_frame_data_update && !rc->is_src_frame_alt_ref) {
+ for (int index = 0; index < FRAME_TYPES; index++)
+ cpi->ppi->temp_avg_frame_qindex[index] = rc->avg_frame_qindex[index];
+ }
+#endif // CONFIG_FRAME_PARALLEL_ENCODE
// Keep record of last boosted (KF/GF/ARF) Q value.
// If the current frame is coded at a lower Q then we also update it.
// If all mbs in this group are skipped only update if the Q value is
diff --git a/av1/encoder/temporal_filter.c b/av1/encoder/temporal_filter.c
index d58c960..6833ac8 100644
--- a/av1/encoder/temporal_filter.c
+++ b/av1/encoder/temporal_filter.c
@@ -754,8 +754,17 @@
int av1_get_q(const AV1_COMP *cpi) {
const GF_GROUP *gf_group = &cpi->ppi->gf_group;
const FRAME_TYPE frame_type = gf_group->frame_type[cpi->gf_frame_index];
- const int q = (int)av1_convert_qindex_to_q(
- cpi->rc.avg_frame_qindex[frame_type], cpi->common.seq_params->bit_depth);
+ int avg_frame_qindex;
+#if CONFIG_FRAME_PARALLEL_ENCODE
+ avg_frame_qindex =
+ (cpi->ppi->gf_group.frame_parallel_level[cpi->gf_frame_index] > 0)
+ ? cpi->ppi->temp_avg_frame_qindex[frame_type]
+ : cpi->rc.avg_frame_qindex[frame_type];
+#else
+ avg_frame_qindex = cpi->rc.avg_frame_qindex[frame_type];
+#endif // CONFIG_FRAME_PARALLEL_ENCODE
+ const int q = (int)av1_convert_qindex_to_q(avg_frame_qindex,
+ cpi->common.seq_params->bit_depth);
return q;
}