Correct tpl boost combination with gfu_boost in LAP
As all stats may not be available for a lower lag_in_frames,
using frames_to_key in process_tpl_stats_frame would be incorrect
in case of LAP. Using number of stats actually used, for projection
and combination of gfu_boost in LAP.
STATS_CHANGED
Change-Id: I3825a6329f1b6671f90c59597895d7d0667dbaa1
(cherry picked from commit 28742ee3c7331274da2827fa65d3852c6853650e)
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c
index 04e2bb3..42bf1e7 100644
--- a/av1/encoder/encoder.c
+++ b/av1/encoder/encoder.c
@@ -4012,6 +4012,26 @@
}
#if !CONFIG_REALTIME_ONLY
+#define MAX_GFUBOOST_FACTOR 10.0
+#define MIN_GFUBOOST_FACTOR 4.0
+static double get_gfu_boost_projection_factor(double min_factor,
+ double max_factor,
+ int frame_count) {
+ double factor = sqrt((double)frame_count);
+ factor = AOMMIN(factor, max_factor);
+ factor = AOMMAX(factor, min_factor);
+ factor = (200.0 + 10.0 * factor);
+ return factor;
+}
+
+static int get_gfu_boost_from_r0_lap(double min_factor, double max_factor,
+ double r0, int frames_to_key) {
+ double factor =
+ get_gfu_boost_projection_factor(min_factor, max_factor, frames_to_key);
+ const int boost = (int)rint(factor / r0);
+ return boost;
+}
+
static double get_kf_boost_projection_factor(int frame_count) {
double factor = sqrt((double)frame_count);
factor = AOMMIN(factor, 10.0);
@@ -4026,6 +4046,31 @@
return boost;
}
+static int get_projected_prior_gfu_boost(AV1_COMP *cpi) {
+ int num_stats_used_for_gfu_boost = cpi->rc.num_stats_used_for_gfu_boost;
+ int frames_to_project = cpi->rc.num_stats_required_for_gfu_boost;
+
+ /*
+ * If frames_to_project is equal to num_stats_used_for_gfu_boost,
+ * it means that gfu_boost was calculated over frames_to_project to
+ * begin with(ie; all stats required were available), hence return
+ * the original boost.
+ */
+ if (num_stats_used_for_gfu_boost >= frames_to_project)
+ return cpi->rc.gfu_boost;
+
+ double min_boost_factor = sqrt(cpi->rc.baseline_gf_interval);
+ // Get the current tpl factor (number of frames = frames_to_project).
+ double tpl_factor = get_gfu_boost_projection_factor(
+ min_boost_factor, MAX_GFUBOOST_FACTOR, frames_to_project);
+ // Get the tpl factor when number of frames = num_stats_used_for_prior_boost.
+ double tpl_factor_num_stats = get_gfu_boost_projection_factor(
+ min_boost_factor, MAX_GFUBOOST_FACTOR, num_stats_used_for_gfu_boost);
+ int projected_gfu_boost =
+ (int)rint((tpl_factor * cpi->rc.gfu_boost) / tpl_factor_num_stats);
+ return projected_gfu_boost;
+}
+
static int get_projected_prior_boost(AV1_COMP *cpi) {
/*
* If num_stats_used_for_kf_boost >= frames_to_key, then
@@ -4046,13 +4091,18 @@
}
#endif
-int combine_prior_with_tpl_boost(int prior_boost, int tpl_boost,
+#define MIN_BOOST_COMBINE_FACTOR 4.0
+#define MAX_BOOST_COMBINE_FACTOR 12.0
+int combine_prior_with_tpl_boost(double min_factor, double max_factor,
+ int prior_boost, int tpl_boost,
int frames_to_key) {
double factor = sqrt((double)frames_to_key);
- factor = AOMMIN(factor, 12.0);
- factor = AOMMAX(factor, 4.0);
- factor -= 4.0;
- int boost = (int)((factor * prior_boost + (8.0 - factor) * tpl_boost) / 8.0);
+ double range = max_factor - min_factor;
+ factor = AOMMIN(factor, max_factor);
+ factor = AOMMAX(factor, min_factor);
+ factor -= min_factor;
+ int boost =
+ (int)((factor * prior_boost + (range - factor) * tpl_boost) / range);
return boost;
}
@@ -4102,9 +4152,23 @@
cpi->rd.r0 = (double)intra_cost_base / mc_dep_cost_base;
if (is_frame_arf_and_tpl_eligible(gf_group)) {
cpi->rd.arf_r0 = cpi->rd.r0;
- const int gfu_boost = (int)(200.0 / cpi->rd.r0);
- cpi->rc.gfu_boost = combine_prior_with_tpl_boost(
- cpi->rc.gfu_boost, gfu_boost, cpi->rc.frames_to_key);
+ if (cpi->lap_enabled) {
+ double min_boost_factor = sqrt(cpi->rc.baseline_gf_interval);
+ const int gfu_boost = get_gfu_boost_from_r0_lap(
+ min_boost_factor, MAX_GFUBOOST_FACTOR, cpi->rd.arf_r0,
+ cpi->rc.num_stats_required_for_gfu_boost);
+ const int prior_boost = get_projected_prior_gfu_boost(cpi);
+ // printf("old boost %d new boost %d\n", prior_boost,
+ // gfu_boost);
+ cpi->rc.gfu_boost = combine_prior_with_tpl_boost(
+ min_boost_factor, MAX_BOOST_COMBINE_FACTOR, prior_boost,
+ gfu_boost, cpi->rc.num_stats_used_for_gfu_boost);
+ } else {
+ const int gfu_boost = (int)(200.0 / cpi->rd.r0);
+ cpi->rc.gfu_boost = combine_prior_with_tpl_boost(
+ MIN_BOOST_COMBINE_FACTOR, MAX_BOOST_COMBINE_FACTOR,
+ cpi->rc.gfu_boost, gfu_boost, cpi->rc.frames_to_key);
+ }
} else if (frame_is_intra_only(cm)) {
// TODO(debargha): Turn off q adjustment for kf temporarily to
// reduce impact on speed of encoding. Need to investigate how
@@ -4115,10 +4179,12 @@
if (cpi->lap_enabled) {
const int projected_prior_boost = get_projected_prior_boost(cpi);
cpi->rc.kf_boost = combine_prior_with_tpl_boost(
+ MIN_BOOST_COMBINE_FACTOR, MAX_BOOST_COMBINE_FACTOR,
projected_prior_boost, kf_boost,
cpi->rc.num_stats_used_for_kf_boost);
} else {
cpi->rc.kf_boost = combine_prior_with_tpl_boost(
+ MIN_BOOST_COMBINE_FACTOR, MAX_BOOST_COMBINE_FACTOR,
cpi->rc.kf_boost, kf_boost, cpi->rc.frames_to_key);
}
}
diff --git a/av1/encoder/gop_structure.c b/av1/encoder/gop_structure.c
index 6889c83..210e894 100644
--- a/av1/encoder/gop_structure.c
+++ b/av1/encoder/gop_structure.c
@@ -47,8 +47,8 @@
gf_group->cur_frame_idx[*frame_ind] = *cur_frame_idx;
gf_group->frame_disp_idx[*frame_ind] = start;
gf_group->layer_depth[*frame_ind] = MAX_ARF_LAYERS;
- gf_group->arf_boost[*frame_ind] =
- av1_calc_arf_boost(twopass, rc, frame_info, start, end - start, 0);
+ gf_group->arf_boost[*frame_ind] = av1_calc_arf_boost(
+ twopass, rc, frame_info, start, end - start, 0, NULL);
gf_group->max_layer_depth =
AOMMAX(gf_group->max_layer_depth, layer_depth);
++(*frame_ind);
@@ -64,8 +64,8 @@
gf_group->layer_depth[*frame_ind] = layer_depth;
// Get the boost factor for intermediate ARF frames.
- gf_group->arf_boost[*frame_ind] =
- av1_calc_arf_boost(twopass, rc, frame_info, m, end - m, m - start);
+ gf_group->arf_boost[*frame_ind] = av1_calc_arf_boost(
+ twopass, rc, frame_info, m, end - m, m - start, NULL);
++(*frame_ind);
// Frames displayed before this internal ARF.
diff --git a/av1/encoder/gop_structure.h b/av1/encoder/gop_structure.h
index 4637930..e76ba21 100644
--- a/av1/encoder/gop_structure.h
+++ b/av1/encoder/gop_structure.h
@@ -34,7 +34,7 @@
int av1_calc_arf_boost(const TWO_PASS *twopass, const RATE_CONTROL *rc,
FRAME_INFO *frame_info, int offset, int f_frames,
- int b_frames);
+ int b_frames, int *num_fpstats_used);
#ifdef __cplusplus
} // extern "C"
#endif
diff --git a/av1/encoder/pass2_strategy.c b/av1/encoder/pass2_strategy.c
index 67d19e8..195f578 100644
--- a/av1/encoder/pass2_strategy.c
+++ b/av1/encoder/pass2_strategy.c
@@ -461,7 +461,7 @@
#define MIN_DECAY_FACTOR 0.01
int av1_calc_arf_boost(const TWO_PASS *twopass, const RATE_CONTROL *rc,
FRAME_INFO *frame_info, int offset, int f_frames,
- int b_frames) {
+ int b_frames, int *num_fpstats_used) {
int i;
double boost_score = (double)NORMAL_BOOST;
double mv_ratio_accumulator = 0.0;
@@ -471,6 +471,7 @@
double abs_mv_in_out_accumulator = 0.0;
int arf_boost;
int flash_detected = 0;
+ if (num_fpstats_used) *num_fpstats_used = 0;
// Search forward from the proposed arf/next gf position.
for (i = 0; i < f_frames; ++i) {
@@ -498,6 +499,7 @@
boost_score += decay_accumulator *
calc_frame_boost(rc, frame_info, this_frame,
this_frame_mv_in_out, GF_MAX_BOOST);
+ if (num_fpstats_used) (*num_fpstats_used)++;
}
arf_boost = (int)boost_score;
@@ -536,6 +538,7 @@
boost_score += decay_accumulator *
calc_frame_boost(rc, frame_info, this_frame,
this_frame_mv_in_out, GF_MAX_BOOST);
+ if (num_fpstats_used) (*num_fpstats_used)++;
}
arf_boost += (int)boost_score;
@@ -1582,15 +1585,19 @@
: AOMMAX(0, rc->frames_to_key - i);
// Calculate the boost for alt ref.
- rc->gfu_boost = av1_calc_arf_boost(twopass, rc, frame_info, alt_offset,
- forward_frames, (i - 1));
+ rc->gfu_boost =
+ av1_calc_arf_boost(twopass, rc, frame_info, alt_offset, forward_frames,
+ (i - 1), &rc->num_stats_used_for_gfu_boost);
+ rc->num_stats_required_for_gfu_boost = (forward_frames + i - 1);
rc->source_alt_ref_pending = 1;
gf_group->max_layer_depth_allowed = cpi->oxcf.gf_max_pyr_height;
} else {
reset_fpf_position(twopass, start_pos);
- rc->gfu_boost = AOMMIN(
- MAX_GF_BOOST,
- av1_calc_arf_boost(twopass, rc, frame_info, alt_offset, (i - 1), 0));
+ rc->gfu_boost =
+ AOMMIN(MAX_GF_BOOST,
+ av1_calc_arf_boost(twopass, rc, frame_info, alt_offset, (i - 1),
+ 0, &rc->num_stats_used_for_gfu_boost));
+ rc->num_stats_required_for_gfu_boost = (i - 1);
rc->source_alt_ref_pending = 0;
gf_group->max_layer_depth_allowed = 0;
}
diff --git a/av1/encoder/ratectrl.h b/av1/encoder/ratectrl.h
index 038eac8..05f11fb 100644
--- a/av1/encoder/ratectrl.h
+++ b/av1/encoder/ratectrl.h
@@ -175,6 +175,10 @@
// Total number of stats used only for kf_boost calculation.
int num_stats_used_for_kf_boost;
+ // Total number of stats used only for gfu_boost calculation.
+ int num_stats_used_for_gfu_boost;
+ // Total number of stats required by gfu_boost calculation.
+ int num_stats_required_for_gfu_boost;
} RATE_CONTROL;
struct AV1_COMP;