Commit 2fed9c389d for aom
commit 2fed9c389d63e1d0bb20d0e671aa800ceba9c93a
Author: Lin Zheng <linzhen@google.com>
Date: Wed Feb 25 15:34:55 2026 +0000
Tweak the rate control for GOOD mode.
BDRate improvement on PSNR and VMAF/VMAF-NEG.
STATS_CHANGED
Change-Id: I240ea8c626564c0abd43e0efdf538ac5680bba1d
diff --git a/av1/encoder/pass2_strategy.c b/av1/encoder/pass2_strategy.c
index 06905b3f1c..b4b2abf071 100644
--- a/av1/encoder/pass2_strategy.c
+++ b/av1/encoder/pass2_strategy.c
@@ -602,11 +602,15 @@ static double calc_frame_boost(const PRIMARY_RATE_CONTROL *p_rc,
// Increase boost for frames where new data coming into frame (e.g. zoom out).
// Slightly reduce boost if there is a net balance of motion out of the frame
// (zoom in). The range for this_frame_mv_in_out is -1.0 to +1.0.
- if (this_frame_mv_in_out > 0.0)
+ if (this_frame_mv_in_out > 0.0) {
frame_boost += frame_boost * (this_frame_mv_in_out * 2.0);
+ if (!p_rc->accumulate_stats_stage)
+ max_boost += max_boost * (this_frame_mv_in_out * 2.0);
+ }
// In the extreme case the boost is halved.
- else
+ else {
frame_boost += frame_boost * (this_frame_mv_in_out / 2.0);
+ }
return AOMMIN(frame_boost, max_boost * boost_q_correction);
}
@@ -987,21 +991,6 @@ static void allocate_gf_group_bits(GF_GROUP *gf_group,
gf_group->bit_allocation[gf_group_size] = 0;
}
-// Returns true if KF group and GF group both are almost completely static.
-static inline int is_almost_static(double gf_zero_motion, int kf_zero_motion,
- int is_lap_enabled) {
- if (is_lap_enabled) {
- /*
- * when LAP enabled kf_zero_motion is not reliable, so use strict
- * constraint on gf_zero_motion.
- */
- return (gf_zero_motion >= 0.999);
- } else {
- return (gf_zero_motion >= 0.995) &&
- (kf_zero_motion >= STATIC_KF_GROUP_THRESH);
- }
-}
-
#define ARF_ABS_ZOOM_THRESH 4.4
static inline int detect_gf_cut(AV1_COMP *cpi, int frame_index, int cur_start,
int flash_detected, int active_max_gf_interval,
@@ -1041,9 +1030,7 @@ static inline int detect_gf_cut(AV1_COMP *cpi, int frame_index, int cur_start,
// If almost totally static, we will not use the the max GF length later,
// so we can continue for more frames.
- if (((frame_index - cur_start) >= active_max_gf_interval + 1) &&
- !is_almost_static(gf_stats->zero_motion_accumulator,
- twopass->kf_zeromotion_pct, cpi->ppi->lap_enabled)) {
+ if ((frame_index - cur_start) >= active_max_gf_interval + 1) {
return 1;
}
return 0;
@@ -2410,6 +2397,51 @@ static void set_gop_bits_boost(AV1_COMP *cpi, int i, int is_intra_only,
const AV1EncoderConfig *const oxcf = &cpi->oxcf;
const RateControlCfg *const rc_cfg = &oxcf->rc_cfg;
+ TWO_PASS_FRAME stats_in_backup = cpi->twopass_frame;
+ int gfu_boost_sum = 0;
+ int gfu_count = 0;
+ int accumulate_i = 0;
+ p_rc->accumulate_stats_stage = true;
+ if (rc->frames_since_key == 0) {
+ for (int k = 0; k < MAX_NUM_GF_INTERVALS; k++) {
+ if (p_rc->gf_intervals[k] == 0) {
+ break;
+ }
+
+ int new_i = p_rc->gf_intervals[k];
+ int ext_len_new = new_i - (k == 0 ? is_intra_only : 0);
+ if (use_alt_ref) {
+ if (accumulate_i >= rc->frames_to_key) {
+ break;
+ }
+ const int forward_frames =
+ (rc->frames_to_key - accumulate_i - new_i >= ext_len_new)
+ ? ext_len_new
+ : AOMMAX(0, rc->frames_to_key - accumulate_i - new_i);
+ if (k) {
+ cpi->twopass_frame.stats_in += new_i;
+ if (cpi->twopass_frame.stats_in >=
+ twopass->stats_buf_ctx->stats_in_end) {
+ cpi->twopass_frame.stats_in = twopass->stats_buf_ctx->stats_in_end;
+ }
+ }
+ reset_fpf_position(&cpi->twopass_frame, cpi->twopass_frame.stats_in);
+ // Calculate the boost for alt ref.
+ int gfu_boost_tmp = av1_calc_arf_boost(
+ twopass, &cpi->twopass_frame, p_rc, frame_info, alt_offset,
+ forward_frames, ext_len_new, &p_rc->num_stats_used_for_gfu_boost,
+ &p_rc->num_stats_required_for_gfu_boost, cpi->ppi->lap_enabled);
+ gfu_boost_sum += gfu_boost_tmp;
+ }
+ gfu_count++;
+ accumulate_i += new_i;
+ }
+ assert(gfu_count > 0);
+ p_rc->gfu_boost_average = gfu_boost_sum / gfu_count;
+ }
+ cpi->twopass_frame = stats_in_backup;
+ p_rc->accumulate_stats_stage = false;
+
int ext_len = i - is_intra_only;
if (use_alt_ref) {
const int forward_frames = (rc->frames_to_key - i >= ext_len)
@@ -2530,7 +2562,6 @@ static void define_gf_group(AV1_COMP *cpi, EncodeFrameParams *frame_params,
RATE_CONTROL *const rc = &cpi->rc;
PRIMARY_RATE_CONTROL *const p_rc = &cpi->ppi->p_rc;
const AV1EncoderConfig *const oxcf = &cpi->oxcf;
- TWO_PASS *const twopass = &cpi->ppi->twopass;
FIRSTPASS_STATS next_frame;
const FIRSTPASS_STATS *const start_pos = cpi->twopass_frame.stats_in;
GF_GROUP *gf_group = &cpi->ppi->gf_group;
@@ -2595,11 +2626,8 @@ static void define_gf_group(AV1_COMP *cpi, EncodeFrameParams *frame_params,
int use_alt_ref;
if (can_disable_arf) {
- use_alt_ref =
- !is_almost_static(gf_stats.zero_motion_accumulator,
- twopass->kf_zeromotion_pct, cpi->ppi->lap_enabled) &&
- p_rc->use_arf_in_this_kf_group && (i < gf_cfg->lag_in_frames) &&
- (i >= MIN_GF_INTERVAL);
+ use_alt_ref = p_rc->use_arf_in_this_kf_group &&
+ (i < gf_cfg->lag_in_frames) && (i >= MIN_GF_INTERVAL);
} else {
use_alt_ref = p_rc->use_arf_in_this_kf_group &&
(i < gf_cfg->lag_in_frames) && (i > 2);
@@ -4096,7 +4124,6 @@ void av1_get_second_pass_params(AV1_COMP *cpi,
if (rc->intervals_till_gf_calculate_due == 0 || 1) {
calculate_gf_length(cpi, max_gop_length, MAX_NUM_GF_INTERVALS);
}
-
if (max_gop_length > 16 && oxcf->algo_cfg.enable_tpl_model &&
oxcf->gf_cfg.lag_in_frames >= 32 &&
cpi->sf.tpl_sf.gop_length_decision_method != 3) {
diff --git a/av1/encoder/ratectrl.c b/av1/encoder/ratectrl.c
index fe339d4440..6da81c1f03 100644
--- a/av1/encoder/ratectrl.c
+++ b/av1/encoder/ratectrl.c
@@ -41,6 +41,8 @@
#define USE_UNRESTRICTED_Q_IN_CQ_MODE 0
+#define RES_NUM 2
+
// Max rate target for 1080P and below encodes under normal circumstances
// (1920 * 1080 / (16 * 16)) * MAX_MB_RATE bits per MB
#define MAX_MB_RATE 250
@@ -68,36 +70,48 @@
} \
} while (0)
+#define ASSIGN_MINQ_TABLE_2(bit_depth, name, res_idx) \
+ do { \
+ switch (bit_depth) { \
+ case AOM_BITS_8: name = name##_8[res_idx]; break; \
+ case AOM_BITS_10: name = name##_10[res_idx]; break; \
+ case AOM_BITS_12: name = name##_12[res_idx]; break; \
+ default: \
+ assert(0 && \
+ "bit_depth should be AOM_BITS_8, AOM_BITS_10" \
+ " or AOM_BITS_12"); \
+ name = NULL; \
+ } \
+ } while (0)
+
// Tables relating active max Q to active min Q
-static int kf_low_motion_minq_8[QINDEX_RANGE];
-static int kf_high_motion_minq_8[QINDEX_RANGE];
-static int arfgf_low_motion_minq_8[QINDEX_RANGE];
-static int arfgf_high_motion_minq_8[QINDEX_RANGE];
-static int inter_minq_8[QINDEX_RANGE];
+static int kf_low_motion_minq_8[RES_NUM][QINDEX_RANGE];
+static int kf_high_motion_minq_8[RES_NUM][QINDEX_RANGE];
+static int arfgf_low_motion_minq_8[RES_NUM][QINDEX_RANGE];
+static int arfgf_high_motion_minq_8[RES_NUM][QINDEX_RANGE];
+static int inter_minq_8[RES_NUM][QINDEX_RANGE];
static int rtc_minq_8[QINDEX_RANGE];
-static int kf_low_motion_minq_10[QINDEX_RANGE];
-static int kf_high_motion_minq_10[QINDEX_RANGE];
-static int arfgf_low_motion_minq_10[QINDEX_RANGE];
-static int arfgf_high_motion_minq_10[QINDEX_RANGE];
-static int inter_minq_10[QINDEX_RANGE];
+static int kf_low_motion_minq_10[RES_NUM][QINDEX_RANGE];
+static int kf_high_motion_minq_10[RES_NUM][QINDEX_RANGE];
+static int arfgf_low_motion_minq_10[RES_NUM][QINDEX_RANGE];
+static int arfgf_high_motion_minq_10[RES_NUM][QINDEX_RANGE];
+static int inter_minq_10[RES_NUM][QINDEX_RANGE];
static int rtc_minq_10[QINDEX_RANGE];
-static int kf_low_motion_minq_12[QINDEX_RANGE];
-static int kf_high_motion_minq_12[QINDEX_RANGE];
-static int arfgf_low_motion_minq_12[QINDEX_RANGE];
-static int arfgf_high_motion_minq_12[QINDEX_RANGE];
-static int inter_minq_12[QINDEX_RANGE];
+static int kf_low_motion_minq_12[RES_NUM][QINDEX_RANGE];
+static int kf_high_motion_minq_12[RES_NUM][QINDEX_RANGE];
+static int arfgf_low_motion_minq_12[RES_NUM][QINDEX_RANGE];
+static int arfgf_high_motion_minq_12[RES_NUM][QINDEX_RANGE];
+static int inter_minq_12[RES_NUM][QINDEX_RANGE];
static int rtc_minq_12[QINDEX_RANGE];
-static int gf_high = 2400;
-static int gf_low = 300;
-#ifdef STRICT_RC
-static int kf_high = 3200;
-#else
-static int kf_high = 5000;
-#endif
-static int kf_low = 400;
+static int gf_high_1 = 2875;
+static int gf_low_1 = 562;
+static int gf_high_2 = 4994;
+static int gf_low_2 = 100;
+static int kf_high = 8000;
+static int kf_low = 553;
// How many times less pixels there are to encode given the current scaling.
// Temporary replacement for rcf_mult and rate_thresh_mult.
static double resize_rate_factor(const FrameDimensionCfg *const frm_dim_cfg,
@@ -120,18 +134,33 @@ static int get_minq_index(double maxq, double x3, double x2, double x1,
return av1_find_qindex(minqtarget, bit_depth, 0, QINDEX_RANGE - 1);
}
-static void init_minq_luts(int *kf_low_m, int *kf_high_m, int *arfgf_low,
- int *arfgf_high, int *inter, int *rtc,
+static double x1[RES_NUM][5] = {
+ { 0.1771, 0.379, 0.3279, 0.6634, 1.385 },
+ { 0.1917, 0.3760, 0.34570, 0.6916, 1.14820 },
+};
+
+static void init_minq_luts(int kf_low_m[RES_NUM][QINDEX_RANGE],
+ int kf_high_m[RES_NUM][QINDEX_RANGE],
+ int arfgf_low[RES_NUM][QINDEX_RANGE],
+ int arfgf_high[RES_NUM][QINDEX_RANGE],
+ int inter[RES_NUM][QINDEX_RANGE], int *rtc,
aom_bit_depth_t bit_depth) {
int i;
- for (i = 0; i < QINDEX_RANGE; i++) {
- const double maxq = av1_convert_qindex_to_q(i, bit_depth);
- kf_low_m[i] = get_minq_index(maxq, 0.000001, -0.0004, 0.150, bit_depth);
- kf_high_m[i] = get_minq_index(maxq, 0.0000021, -0.00125, 0.45, bit_depth);
- arfgf_low[i] = get_minq_index(maxq, 0.0000015, -0.0009, 0.30, bit_depth);
- arfgf_high[i] = get_minq_index(maxq, 0.0000021, -0.00125, 0.55, bit_depth);
- inter[i] = get_minq_index(maxq, 0.00000271, -0.00113, 0.90, bit_depth);
- rtc[i] = get_minq_index(maxq, 0.00000271, -0.00113, 0.70, bit_depth);
+ for (int res = 0; res < RES_NUM; res++) {
+ for (i = 0; i < QINDEX_RANGE; i++) {
+ const double maxq = av1_convert_qindex_to_q(i, bit_depth);
+ kf_low_m[res][i] =
+ get_minq_index(maxq, 0.000001, -0.0004, x1[res][0], bit_depth);
+ kf_high_m[res][i] =
+ get_minq_index(maxq, 0.0000021, -0.00125, x1[res][1], bit_depth);
+ arfgf_low[res][i] =
+ get_minq_index(maxq, 0.0000015, -0.0009, x1[res][2], bit_depth);
+ arfgf_high[res][i] =
+ get_minq_index(maxq, 0.0000021, -0.00125, x1[res][3], bit_depth);
+ inter[res][i] =
+ get_minq_index(maxq, 0.00000271, -0.00113, x1[res][4], bit_depth);
+ rtc[i] = get_minq_index(maxq, 0.00000271, -0.00113, 0.70, bit_depth);
+ }
}
}
@@ -1123,34 +1152,44 @@ static int get_active_quality(int q, int gfu_boost, int low, int high,
}
}
+static int gfboost_thresh[3] = { 4000, 4000, 3000 };
+
static int get_kf_active_quality(const PRIMARY_RATE_CONTROL *const p_rc, int q,
- aom_bit_depth_t bit_depth) {
+ aom_bit_depth_t bit_depth, const int res_idx) {
int *kf_low_motion_minq;
int *kf_high_motion_minq;
- ASSIGN_MINQ_TABLE(bit_depth, kf_low_motion_minq);
- ASSIGN_MINQ_TABLE(bit_depth, kf_high_motion_minq);
+ ASSIGN_MINQ_TABLE_2(bit_depth, kf_low_motion_minq, res_idx > 1);
+ ASSIGN_MINQ_TABLE_2(bit_depth, kf_high_motion_minq, res_idx > 1);
return get_active_quality(q, p_rc->kf_boost, kf_low, kf_high,
kf_low_motion_minq, kf_high_motion_minq);
}
-static int get_gf_active_quality_no_rc(int gfu_boost, int q,
- aom_bit_depth_t bit_depth) {
+static int get_gf_active_quality_no_rc(const PRIMARY_RATE_CONTROL *const p_rc,
+ int q, aom_bit_depth_t bit_depth,
+ const int res_idx) {
int *arfgf_low_motion_minq;
int *arfgf_high_motion_minq;
- ASSIGN_MINQ_TABLE(bit_depth, arfgf_low_motion_minq);
- ASSIGN_MINQ_TABLE(bit_depth, arfgf_high_motion_minq);
- return get_active_quality(q, gfu_boost, gf_low, gf_high,
+ ASSIGN_MINQ_TABLE_2(bit_depth, arfgf_low_motion_minq, res_idx > 1);
+ ASSIGN_MINQ_TABLE_2(bit_depth, arfgf_high_motion_minq, res_idx > 1);
+
+ int gf_low_local =
+ (p_rc->gfu_boost_average < gfboost_thresh[res_idx]) ? gf_low_1 : gf_low_2;
+ int gf_high_local = (p_rc->gfu_boost_average < gfboost_thresh[res_idx])
+ ? gf_high_1
+ : gf_high_2;
+ return get_active_quality(q, p_rc->gfu_boost, gf_low_local, gf_high_local,
arfgf_low_motion_minq, arfgf_high_motion_minq);
}
static int get_gf_active_quality(const PRIMARY_RATE_CONTROL *const p_rc, int q,
- aom_bit_depth_t bit_depth) {
- return get_gf_active_quality_no_rc(p_rc->gfu_boost, q, bit_depth);
+ aom_bit_depth_t bit_depth, const int res_idx) {
+ return get_gf_active_quality_no_rc(p_rc, q, bit_depth, res_idx);
}
-static int get_gf_high_motion_quality(int q, aom_bit_depth_t bit_depth) {
+static int get_gf_high_motion_quality(int q, aom_bit_depth_t bit_depth,
+ const int res_idx) {
int *arfgf_high_motion_minq;
- ASSIGN_MINQ_TABLE(bit_depth, arfgf_high_motion_minq);
+ ASSIGN_MINQ_TABLE_2(bit_depth, arfgf_high_motion_minq, res_idx > 1);
return arfgf_high_motion_minq[q];
}
@@ -1310,6 +1349,11 @@ static int calc_active_best_quality_no_stats_cbr(const AV1_COMP *cpi,
int active_best_quality = rc->best_quality;
ASSIGN_MINQ_TABLE(bit_depth, rtc_minq);
+ const int is_608p_or_larger = AOMMIN(cm->width, cm->height) >= 608;
+ const int is_480p_or_larger = AOMMIN(cm->width, cm->height) >= 480;
+ // res_idx is 0 for res < 480p, 1 for 480p, 2 for 608p+
+ const int res_idx = is_480p_or_larger + is_608p_or_larger;
+
if (frame_is_intra_only(cm)) {
// Handle the special case for key frames forced when we have reached
// the maximum key frame interval. Here force the Q to a range
@@ -1325,7 +1369,7 @@ static int calc_active_best_quality_no_stats_cbr(const AV1_COMP *cpi,
double q_adj_factor = 1.0;
double q_val;
active_best_quality = get_kf_active_quality(
- p_rc, p_rc->avg_frame_qindex[KEY_FRAME], bit_depth);
+ p_rc, p_rc->avg_frame_qindex[KEY_FRAME], bit_depth, res_idx);
// Allow somewhat lower kf minq with small image formats.
if ((width * height) <= (352 * 288)) {
q_adj_factor -= 0.25;
@@ -1347,7 +1391,7 @@ static int calc_active_best_quality_no_stats_cbr(const AV1_COMP *cpi,
p_rc->avg_frame_qindex[INTER_FRAME] < active_worst_quality) {
q = p_rc->avg_frame_qindex[INTER_FRAME];
}
- active_best_quality = get_gf_active_quality(p_rc, q, bit_depth);
+ active_best_quality = get_gf_active_quality(p_rc, q, bit_depth, res_idx);
} else {
// Use the lower of active_worst_quality and recent/average Q.
FRAME_TYPE frame_type =
@@ -1519,6 +1563,11 @@ static int rc_pick_q_and_bounds_no_stats(const AV1_COMP *cpi, int width,
const RefreshFrameInfo *const refresh_frame = &cpi->refresh_frame;
const enum aom_rc_mode rc_mode = oxcf->rc_cfg.mode;
+ const int is_608p_or_larger = AOMMIN(cm->width, cm->height) >= 608;
+ const int is_480p_or_larger = AOMMIN(cm->width, cm->height) >= 480;
+ // res_idx is 0 for res < 480p, 1 for 480p, 2 for 608p+
+ const int res_idx = is_480p_or_larger + is_608p_or_larger;
+
assert(has_no_stats_stage(cpi));
assert(rc_mode == AOM_VBR ||
(!USE_UNRESTRICTED_Q_IN_CQ_MODE && rc_mode == AOM_CQ) ||
@@ -1533,7 +1582,7 @@ static int rc_pick_q_and_bounds_no_stats(const AV1_COMP *cpi, int width,
int active_worst_quality = calc_active_worst_quality_no_stats_vbr(cpi);
int q;
int *inter_minq;
- ASSIGN_MINQ_TABLE(bit_depth, inter_minq);
+ ASSIGN_MINQ_TABLE_2(bit_depth, inter_minq, res_idx > 1);
if (frame_is_intra_only(cm)) {
if (rc_mode == AOM_Q) {
@@ -1560,7 +1609,7 @@ static int rc_pick_q_and_bounds_no_stats(const AV1_COMP *cpi, int width,
double q_adj_factor = 1.0;
active_best_quality = get_kf_active_quality(
- p_rc, p_rc->avg_frame_qindex[KEY_FRAME], bit_depth);
+ p_rc, p_rc->avg_frame_qindex[KEY_FRAME], bit_depth, res_idx);
// Allow somewhat lower kf minq with small image formats.
if ((width * height) <= (352 * 288)) {
@@ -1587,7 +1636,7 @@ static int rc_pick_q_and_bounds_no_stats(const AV1_COMP *cpi, int width,
// For constrained quality don't allow Q less than the cq level
if (rc_mode == AOM_CQ) {
if (q < cq_level) q = cq_level;
- active_best_quality = get_gf_active_quality(p_rc, q, bit_depth);
+ active_best_quality = get_gf_active_quality(p_rc, q, bit_depth, res_idx);
// Constrained quality use slightly lower active best.
active_best_quality = active_best_quality * 15 / 16;
} else if (rc_mode == AOM_Q) {
@@ -1599,7 +1648,7 @@ static int rc_pick_q_and_bounds_no_stats(const AV1_COMP *cpi, int width,
: av1_compute_qdelta(rc, q_val, q_val * 0.50, bit_depth);
active_best_quality = AOMMAX(qindex + delta_qindex, rc->best_quality);
} else {
- active_best_quality = get_gf_active_quality(p_rc, q, bit_depth);
+ active_best_quality = get_gf_active_quality(p_rc, q, bit_depth, res_idx);
}
} else {
if (rc_mode == AOM_Q) {
@@ -1737,6 +1786,11 @@ static void get_intra_q_and_bounds(const AV1_COMP *cpi, int width, int height,
int active_worst_quality = *active_worst;
const int bit_depth = cm->seq_params->bit_depth;
+ const int is_608p_or_larger = AOMMIN(cm->width, cm->height) >= 608;
+ const int is_480p_or_larger = AOMMIN(cm->width, cm->height) >= 480;
+ // res_idx is 0 for res < 480p, 1 for 480p, 2 for 608p+
+ const int res_idx = is_480p_or_larger + is_608p_or_larger;
+
if (rc->frames_to_key <= 1 && oxcf->rc_cfg.mode == AOM_Q) {
// If the next frame is also a key frame or the current frame is the
// only frame in the sequence in AOM_Q mode, just use the cq_level
@@ -1783,7 +1837,7 @@ static void get_intra_q_and_bounds(const AV1_COMP *cpi, int width, int height,
// Baseline value derived from active_worst_quality and kf boost.
active_best_quality =
- get_kf_active_quality(p_rc, active_worst_quality, bit_depth);
+ get_kf_active_quality(p_rc, active_worst_quality, bit_depth, res_idx);
if (cpi->is_screen_content_type) {
active_best_quality /= 2;
}
@@ -1973,14 +2027,20 @@ static int get_active_best_quality(const AV1_COMP *const cpi,
const RefreshFrameInfo *const refresh_frame = &cpi->refresh_frame;
const GF_GROUP *gf_group = &cpi->ppi->gf_group;
const enum aom_rc_mode rc_mode = oxcf->rc_cfg.mode;
- int *inter_minq;
- ASSIGN_MINQ_TABLE(bit_depth, inter_minq);
int active_best_quality = 0;
FRAME_UPDATE_TYPE update_type = gf_group->update_type[gf_index];
const int is_intrl_arf_boost = update_type == INTNL_ARF_UPDATE;
int is_leaf_frame = !(update_type == ARF_UPDATE || update_type == GF_UPDATE ||
is_intrl_arf_boost);
+ const int is_608p_or_larger = AOMMIN(cm->width, cm->height) >= 608;
+ const int is_480p_or_larger = AOMMIN(cm->width, cm->height) >= 480;
+ // res_idx is 0 for res < 480p, 1 for 480p, 2 for 608p+
+ const int res_idx = is_480p_or_larger + is_608p_or_larger;
+
+ int *inter_minq;
+ ASSIGN_MINQ_TABLE_2(bit_depth, inter_minq, res_idx > 1);
+
// TODO(jingning): Consider to rework this hack that covers issues incurred
// in lightfield setting.
if (cm->tiles.large_scale) {
@@ -2012,10 +2072,10 @@ static int get_active_best_quality(const AV1_COMP *const cpi,
q = p_rc->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);
+ active_best_quality = get_gf_active_quality(p_rc, q, bit_depth, res_idx);
// Constrained quality use slightly lower active best.
if (rc_mode == AOM_CQ) active_best_quality = active_best_quality * 15 / 16;
- const int min_boost = get_gf_high_motion_quality(q, bit_depth);
+ const int min_boost = get_gf_high_motion_quality(q, bit_depth, res_idx);
const int boost = min_boost - active_best_quality;
active_best_quality = min_boost - (int)(boost * p_rc->arf_boost_factor);
if (!is_intrl_arf_boost) return active_best_quality;
diff --git a/av1/encoder/ratectrl.h b/av1/encoder/ratectrl.h
index 4d6ef52bea..e83b7c0e18 100644
--- a/av1/encoder/ratectrl.h
+++ b/av1/encoder/ratectrl.h
@@ -328,6 +328,16 @@ typedef struct {
*/
int gfu_boost;
+ /*!
+ * Average boost factor of ARFs and GFs within a kf interval
+ */
+ int gfu_boost_average;
+
+ /*!
+ * Indicate if it is gfu_boost accumulation stage
+ */
+ bool accumulate_stats_stage;
+
/*!
* Stores the determined gf group lengths for a set of gf groups
*/
diff --git a/av1/encoder/speed_features.c b/av1/encoder/speed_features.c
index 37f0788ab6..7971136335 100644
--- a/av1/encoder/speed_features.c
+++ b/av1/encoder/speed_features.c
@@ -1307,7 +1307,6 @@ static void set_good_speed_features_framesize_independent(
sf->tpl_sf.prune_intra_modes = 1;
sf->tpl_sf.reduce_first_step_size = 6;
sf->tpl_sf.subpel_force_stop = QUARTER_PEL;
- sf->tpl_sf.gop_length_decision_method = 1;
sf->tx_sf.adaptive_txb_search_level = boosted ? 2 : 3;
sf->tx_sf.tx_type_search.use_skip_flag_prediction = 2;
@@ -2194,7 +2193,7 @@ static inline void init_fp_sf(FIRST_PASS_SPEED_FEATURES *fp_sf) {
}
static inline void init_tpl_sf(TPL_SPEED_FEATURES *tpl_sf) {
- tpl_sf->gop_length_decision_method = 0;
+ tpl_sf->gop_length_decision_method = 1;
tpl_sf->prune_intra_modes = 0;
tpl_sf->prune_starting_mv = 0;
tpl_sf->reduce_first_step_size = 0;