Abstract elements from RATE_CONTROL to PRIMARY_RATE_CONTROL
A structure PRIMARY_RATE_CONTROL is created which contains
all the elements of RATE_CONTROL that do not change during
the encode of a sub-gop. These elements are moved from
cpi->rc (RATE_CONTROL) and now reside in ppi->p_rc (PRIMARY_RATE_CONTROL).
All the relevant initializations have also been moved to their
corresponding primary_* counterparts.
Change-Id: I126f75f7d890a816dcf4678839ea5b8ee1337875
diff --git a/av1/av1_cx_iface.c b/av1/av1_cx_iface.c
index 06ec94e..4917854 100644
--- a/av1/av1_cx_iface.c
+++ b/av1/av1_cx_iface.c
@@ -1355,7 +1355,7 @@
va_list args) {
int *const arg = va_arg(args, int *);
if (arg == NULL) return AOM_CODEC_INVALID_PARAM;
- *arg = ctx->ppi->cpi->rc.baseline_gf_interval;
+ *arg = ctx->ppi->p_rc.baseline_gf_interval;
return AOM_CODEC_OK;
}
@@ -2190,8 +2190,7 @@
static aom_codec_err_t create_context_and_bufferpool(
AV1_PRIMARY *ppi, AV1_COMP **p_cpi, BufferPool **p_buffer_pool,
- AV1EncoderConfig *oxcf, COMPRESSOR_STAGE stage, int num_lap_buffers,
- int lap_lag_in_frames) {
+ AV1EncoderConfig *oxcf, COMPRESSOR_STAGE stage, int lap_lag_in_frames) {
aom_codec_err_t res = AOM_CODEC_OK;
*p_buffer_pool = (BufferPool *)aom_calloc(1, sizeof(BufferPool));
@@ -2203,7 +2202,7 @@
}
#endif
*p_cpi = av1_create_compressor(ppi, oxcf, *p_buffer_pool, stage,
- num_lap_buffers, lap_lag_in_frames);
+ lap_lag_in_frames);
if (*p_cpi == NULL) res = AOM_CODEC_MEM_ERROR;
return res;
@@ -2275,14 +2274,13 @@
res = create_context_and_bufferpool(priv->ppi, &priv->ppi->cpi,
&priv->buffer_pool, &priv->oxcf,
- ENCODE_STAGE, *num_lap_buffers, -1);
+ ENCODE_STAGE, -1);
// Create another compressor if look ahead is enabled
if (res == AOM_CODEC_OK && *num_lap_buffers) {
res = create_context_and_bufferpool(
priv->ppi, &priv->ppi->cpi_lap, &priv->buffer_pool_lap, &priv->oxcf,
- LAP_STAGE, *num_lap_buffers,
- clamp(lap_lag_in_frames, 0, MAX_LAG_BUFFERS));
+ LAP_STAGE, clamp(lap_lag_in_frames, 0, MAX_LAG_BUFFERS));
}
}
}
diff --git a/av1/encoder/aq_cyclicrefresh.c b/av1/encoder/aq_cyclicrefresh.c
index c7abe43..551913e 100644
--- a/av1/encoder/aq_cyclicrefresh.c
+++ b/av1/encoder/aq_cyclicrefresh.c
@@ -257,15 +257,16 @@
void av1_cyclic_refresh_set_golden_update(AV1_COMP *const cpi) {
RATE_CONTROL *const rc = &cpi->rc;
+ PRIMARY_RATE_CONTROL *const p_rc = &cpi->ppi->p_rc;
CYCLIC_REFRESH *const cr = cpi->cyclic_refresh;
// Set minimum gf_interval for GF update to a multiple of the refresh period,
// with some max limit. Depending on past encoding stats, GF flag may be
// reset and update may not occur until next baseline_gf_interval.
if (cr->percent_refresh > 0)
- rc->baseline_gf_interval = AOMMIN(2 * (100 / cr->percent_refresh), 40);
+ p_rc->baseline_gf_interval = AOMMIN(2 * (100 / cr->percent_refresh), 40);
else
- rc->baseline_gf_interval = 20;
- if (rc->avg_frame_low_motion < 40) rc->baseline_gf_interval = 8;
+ p_rc->baseline_gf_interval = 20;
+ if (rc->avg_frame_low_motion < 40) p_rc->baseline_gf_interval = 8;
}
// Update the segmentation map, and related quantities: cyclic refresh map,
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c
index e3e90a6..517bb87 100644
--- a/av1/encoder/encoder.c
+++ b/av1/encoder/encoder.c
@@ -590,6 +590,7 @@
AV1_COMMON *const cm = &cpi->common;
SequenceHeader *const seq_params = &cm->seq_params;
RATE_CONTROL *const rc = &cpi->rc;
+ PRIMARY_RATE_CONTROL *const p_rc = &cpi->ppi->p_rc;
MACROBLOCK *const x = &cpi->td.mb;
AV1LevelParams *const level_params = &cpi->ppi->level_params;
InitialDimensions *const initial_dimensions = &cpi->initial_dimensions;
@@ -683,10 +684,10 @@
seq_params->tier[0]);
}
- if ((has_no_stats_stage(cpi)) && (rc_cfg->mode == AOM_Q)) {
- rc->baseline_gf_interval = FIXED_GF_INTERVAL;
+ if (has_no_stats_stage(cpi) && (rc_cfg->mode == AOM_Q)) {
+ p_rc->baseline_gf_interval = FIXED_GF_INTERVAL;
} else {
- rc->baseline_gf_interval = (MIN_GF_INTERVAL + MAX_GF_INTERVAL) / 2;
+ p_rc->baseline_gf_interval = (MIN_GF_INTERVAL + MAX_GF_INTERVAL) / 2;
}
refresh_frame_flags->golden_frame = false;
@@ -733,12 +734,12 @@
av1_set_high_precision_mv(cpi, 1, 0);
- set_rc_buffer_sizes(rc, rc_cfg);
+ set_rc_buffer_sizes(p_rc, rc_cfg);
// Under a configuration change, where maximum_buffer_size may change,
// keep buffer level clipped to the maximum allowed buffer size.
- rc->bits_off_target = AOMMIN(rc->bits_off_target, rc->maximum_buffer_size);
- rc->buffer_level = AOMMIN(rc->buffer_level, rc->maximum_buffer_size);
+ rc->bits_off_target = AOMMIN(rc->bits_off_target, p_rc->maximum_buffer_size);
+ rc->buffer_level = AOMMIN(rc->buffer_level, p_rc->maximum_buffer_size);
// Set up frame rate and related parameters rate control values.
av1_new_framerate(cpi, cpi->framerate);
@@ -859,12 +860,31 @@
ppi->b_calculate_psnr = CONFIG_INTERNAL_STATS;
ppi->frames_left = oxcf->input_cfg.limit;
+ av1_primary_rc_init(oxcf, &ppi->p_rc);
+
+ // For two pass and lag_in_frames > 33 in LAP.
+ ppi->p_rc.enable_scenecut_detection = ENABLE_SCENECUT_MODE_2;
+ if (ppi->lap_enabled) {
+ if ((num_lap_buffers <
+ (MAX_GF_LENGTH_LAP + SCENE_CUT_KEY_TEST_INTERVAL + 1)) &&
+ num_lap_buffers >= (MAX_GF_LENGTH_LAP + 3)) {
+ /*
+ * For lag in frames >= 19 and <33, enable scenecut
+ * with limited future frame prediction.
+ */
+ ppi->p_rc.enable_scenecut_detection = ENABLE_SCENECUT_MODE_1;
+ } else if (num_lap_buffers < (MAX_GF_LENGTH_LAP + 3)) {
+ // Disable scenecut when lag_in_frames < 19.
+ ppi->p_rc.enable_scenecut_detection = DISABLE_SCENECUT;
+ }
+ }
+
return ppi;
}
AV1_COMP *av1_create_compressor(AV1_PRIMARY *ppi, AV1EncoderConfig *oxcf,
BufferPool *const pool, COMPRESSOR_STAGE stage,
- int num_lap_buffers, int lap_lag_in_frames) {
+ int lap_lag_in_frames) {
AV1_COMP *volatile const cpi = aom_memalign(32, sizeof(AV1_COMP));
AV1_COMMON *volatile const cm = cpi != NULL ? &cpi->common : NULL;
@@ -910,24 +930,8 @@
cpi->oxcf.gf_cfg.lag_in_frames = lap_lag_in_frames;
}
- av1_rc_init(&cpi->oxcf, oxcf->pass, &cpi->rc);
+ av1_rc_init(&cpi->oxcf, oxcf->pass, &cpi->rc, &cpi->ppi->p_rc);
- // For two pass and lag_in_frames > 33 in LAP.
- cpi->rc.enable_scenecut_detection = ENABLE_SCENECUT_MODE_2;
- if (cpi->ppi->lap_enabled) {
- if ((num_lap_buffers <
- (MAX_GF_LENGTH_LAP + SCENE_CUT_KEY_TEST_INTERVAL + 1)) &&
- num_lap_buffers >= (MAX_GF_LENGTH_LAP + 3)) {
- /*
- * For lag in frames >= 19 and <33, enable scenecut
- * with limited future frame prediction.
- */
- cpi->rc.enable_scenecut_detection = ENABLE_SCENECUT_MODE_1;
- } else if (num_lap_buffers < (MAX_GF_LENGTH_LAP + 3)) {
- // Disable scenecut when lag_in_frames < 19.
- cpi->rc.enable_scenecut_detection = DISABLE_SCENECUT;
- }
- }
init_frame_info(&cpi->frame_info, cm);
init_frame_index_set(&cpi->frame_index_set);
@@ -2811,7 +2815,7 @@
// Special case code to reduce pulsing when key frames are forced at a
// fixed interval. Note the reconstruction error if it is the frame before
// the force key frame
- if (cpi->rc.next_key_frame_forced && cpi->rc.frames_to_key == 1) {
+ if (cpi->ppi->p_rc.next_key_frame_forced && cpi->rc.frames_to_key == 1) {
#if CONFIG_AV1_HIGHBITDEPTH
if (seq_params->use_highbitdepth) {
cpi->ambient_err = aom_highbd_get_y_sse(cpi->source, &cm->cur_frame->buf);
diff --git a/av1/encoder/encoder.h b/av1/encoder/encoder.h
index def9de6..6b2c029 100644
--- a/av1/encoder/encoder.h
+++ b/av1/encoder/encoder.h
@@ -2129,6 +2129,11 @@
* Information related to two pass encoding.
*/
TWO_PASS twopass;
+
+ /*!
+ * Rate control related parameters.
+ */
+ PRIMARY_RATE_CONTROL p_rc;
} AV1_PRIMARY;
/*!
@@ -2799,7 +2804,6 @@
struct AV1_COMP *av1_create_compressor(AV1_PRIMARY *ppi, AV1EncoderConfig *oxcf,
BufferPool *const pool,
COMPRESSOR_STAGE stage,
- int num_lap_buffers,
int lap_lag_in_frames);
struct AV1_PRIMARY *av1_create_primary_compressor(
diff --git a/av1/encoder/encoder_utils.c b/av1/encoder/encoder_utils.c
index c6d99e1..4cc9de2 100644
--- a/av1/encoder/encoder_utils.c
+++ b/av1/encoder/encoder_utils.c
@@ -499,20 +499,21 @@
cpi->rd.r0 = (double)intra_cost_base / mc_dep_cost_base;
if (is_frame_tpl_eligible(gf_group, cpi->gf_frame_index)) {
if (cpi->ppi->lap_enabled) {
- double min_boost_factor = sqrt(cpi->rc.baseline_gf_interval);
+ double min_boost_factor = sqrt(cpi->ppi->p_rc.baseline_gf_interval);
const int gfu_boost = get_gfu_boost_from_r0_lap(
min_boost_factor, MAX_GFUBOOST_FACTOR, cpi->rd.r0,
- cpi->rc.num_stats_required_for_gfu_boost);
+ cpi->ppi->p_rc.num_stats_required_for_gfu_boost);
// printf("old boost %d new boost %d\n", cpi->rc.gfu_boost,
// gfu_boost);
- cpi->rc.gfu_boost = combine_prior_with_tpl_boost(
- min_boost_factor, MAX_BOOST_COMBINE_FACTOR, cpi->rc.gfu_boost,
- gfu_boost, cpi->rc.num_stats_used_for_gfu_boost);
+ cpi->ppi->p_rc.gfu_boost = combine_prior_with_tpl_boost(
+ min_boost_factor, MAX_BOOST_COMBINE_FACTOR,
+ cpi->ppi->p_rc.gfu_boost, gfu_boost,
+ cpi->ppi->p_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(
+ cpi->ppi->p_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);
+ cpi->ppi->p_rc.gfu_boost, gfu_boost, cpi->rc.frames_to_key);
}
}
aom_clear_system_state();
@@ -538,8 +539,8 @@
#endif
// Decide q and q bounds.
- *q = av1_rc_pick_q_and_bounds(cpi, &cpi->rc, cm->width, cm->height,
- cpi->gf_frame_index, bottom_index, top_index);
+ *q = av1_rc_pick_q_and_bounds(cpi, cm->width, cm->height, cpi->gf_frame_index,
+ bottom_index, top_index);
// Configure experimental use of segmentation for enhanced coding of
// static regions if indicated.
@@ -1304,7 +1305,7 @@
current_frame->frame_number, cpi->gf_frame_index,
cpi->ppi->gf_group.update_type[cpi->gf_frame_index],
current_frame->order_hint, cm->show_frame, cm->show_existing_frame,
- cpi->rc.source_alt_ref_active, cpi->refresh_frame.alt_ref_frame,
+ cpi->p_rc.source_alt_ref_active, cpi->refresh_frame.alt_ref_frame,
recon_buf->y_stride, recon_buf->uv_stride, cm->width, cm->height);
#if 0
int ref_frame;
diff --git a/av1/encoder/gop_structure.c b/av1/encoder/gop_structure.c
index f768a57..2b35657 100644
--- a/av1/encoder/gop_structure.c
+++ b/av1/encoder/gop_structure.c
@@ -28,10 +28,11 @@
// Set parameters for frames between 'start' and 'end' (excluding both).
static void set_multi_layer_params(const TWO_PASS *twopass,
- GF_GROUP *const gf_group, RATE_CONTROL *rc,
- FRAME_INFO *frame_info, int start, int end,
- int *cur_frame_idx, int *frame_ind,
- int layer_depth) {
+ GF_GROUP *const gf_group,
+ const PRIMARY_RATE_CONTROL *p_rc,
+ RATE_CONTROL *rc, FRAME_INFO *frame_info,
+ int start, int end, int *cur_frame_idx,
+ int *frame_ind, int layer_depth) {
const int num_frames_to_process = end - start;
// Either we are at the last level of the pyramid, or we don't have enough
@@ -45,7 +46,7 @@
gf_group->cur_frame_idx[*frame_ind] = *cur_frame_idx;
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, NULL, NULL, 0);
+ twopass, p_rc, rc, frame_info, start, end - start, 0, NULL, NULL, 0);
gf_group->frame_type[*frame_ind] = INTER_FRAME;
gf_group->refbuf_state[*frame_ind] = REFBUF_UPDATE;
gf_group->max_layer_depth =
@@ -67,11 +68,11 @@
// 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, NULL, NULL, 0);
+ twopass, p_rc, rc, frame_info, m, end - m, m - start, NULL, NULL, 0);
++(*frame_ind);
// Frames displayed before this internal ARF.
- set_multi_layer_params(twopass, gf_group, rc, frame_info, start, m,
+ set_multi_layer_params(twopass, gf_group, p_rc, rc, frame_info, start, m,
cur_frame_idx, frame_ind, layer_depth + 1);
// Overlay for internal ARF.
@@ -86,7 +87,7 @@
++(*cur_frame_idx);
// Frames displayed after this internal ARF.
- set_multi_layer_params(twopass, gf_group, rc, frame_info, m + 1, end,
+ set_multi_layer_params(twopass, gf_group, p_rc, rc, frame_info, m + 1, end,
cur_frame_idx, frame_ind, layer_depth + 1);
}
}
@@ -95,6 +96,7 @@
AV1_COMP *cpi, TWO_PASS *twopass, GF_GROUP *const gf_group,
RATE_CONTROL *rc, FRAME_INFO *const frame_info, int gf_interval,
FRAME_UPDATE_TYPE first_frame_update_type) {
+ PRIMARY_RATE_CONTROL *const p_rc = &cpi->ppi->p_rc;
int frame_index = 0;
int cur_frame_index = 0;
@@ -146,7 +148,7 @@
gf_group->arf_src_offset[frame_index] = gf_interval - cur_frame_index;
gf_group->cur_frame_idx[frame_index] = cur_frame_index;
gf_group->layer_depth[frame_index] = 1;
- gf_group->arf_boost[frame_index] = cpi->rc.gfu_boost;
+ gf_group->arf_boost[frame_index] = cpi->ppi->p_rc.gfu_boost;
gf_group->frame_type[frame_index] = is_fwd_kf ? KEY_FRAME : INTER_FRAME;
gf_group->refbuf_state[frame_index] = REFBUF_UPDATE;
gf_group->max_layer_depth = 1;
@@ -157,9 +159,9 @@
}
// Rest of the frames.
- set_multi_layer_params(twopass, gf_group, rc, frame_info, cur_frame_index,
- gf_interval, &cur_frame_index, &frame_index,
- use_altref + 1);
+ set_multi_layer_params(twopass, gf_group, p_rc, rc, frame_info,
+ cur_frame_index, gf_interval, &cur_frame_index,
+ &frame_index, use_altref + 1);
if (use_altref) {
gf_group->update_type[frame_index] = OVERLAY_UPDATE;
@@ -189,6 +191,7 @@
void av1_gop_setup_structure(AV1_COMP *cpi) {
RATE_CONTROL *const rc = &cpi->rc;
+ PRIMARY_RATE_CONTROL *const p_rc = &cpi->ppi->p_rc;
GF_GROUP *const gf_group = &cpi->ppi->gf_group;
TWO_PASS *const twopass = &cpi->ppi->twopass;
FRAME_INFO *const frame_info = &cpi->frame_info;
@@ -196,10 +199,10 @@
const FRAME_UPDATE_TYPE first_frame_update_type =
key_frame ? KF_UPDATE
: cpi->ppi->gf_state.arf_gf_boost_lst ||
- (rc->baseline_gf_interval == 1)
+ (p_rc->baseline_gf_interval == 1)
? OVERLAY_UPDATE
: GF_UPDATE;
gf_group->size = construct_multi_layer_gf_structure(
- cpi, twopass, gf_group, rc, frame_info, rc->baseline_gf_interval - 1,
+ cpi, twopass, gf_group, rc, frame_info, p_rc->baseline_gf_interval - 1,
first_frame_update_type);
}
diff --git a/av1/encoder/gop_structure.h b/av1/encoder/gop_structure.h
index 56978ab..aeffb40 100644
--- a/av1/encoder/gop_structure.h
+++ b/av1/encoder/gop_structure.h
@@ -66,7 +66,8 @@
int64_t gf_group_bits);
/*!\cond */
-int av1_calc_arf_boost(const TWO_PASS *twopass, const RATE_CONTROL *rc,
+int av1_calc_arf_boost(const TWO_PASS *twopass,
+ const PRIMARY_RATE_CONTROL *p_rc, const RATE_CONTROL *rc,
FRAME_INFO *frame_info, int offset, int f_frames,
int b_frames, int *num_fpstats_used,
int *num_fpstats_required, int project_gfu_boost);
diff --git a/av1/encoder/pass2_strategy.c b/av1/encoder/pass2_strategy.c
index e425a73..7408f1d 100644
--- a/av1/encoder/pass2_strategy.c
+++ b/av1/encoder/pass2_strategy.c
@@ -618,8 +618,8 @@
return AOMMIN(frame_boost, max_boost * boost_q_correction);
}
-static int get_projected_gfu_boost(const RATE_CONTROL *rc, int gfu_boost,
- int frames_to_project,
+static int get_projected_gfu_boost(const PRIMARY_RATE_CONTROL *p_rc,
+ int gfu_boost, int frames_to_project,
int num_stats_used_for_gfu_boost) {
/*
* If frames_to_project is equal to num_stats_used_for_gfu_boost,
@@ -629,7 +629,7 @@
*/
if (num_stats_used_for_gfu_boost >= frames_to_project) return gfu_boost;
- double min_boost_factor = sqrt(rc->baseline_gf_interval);
+ double min_boost_factor = sqrt(p_rc->baseline_gf_interval);
// Get the current tpl factor (number of frames = frames_to_project).
double tpl_factor = av1_get_gfu_boost_projection_factor(
min_boost_factor, MAX_GFUBOOST_FACTOR, frames_to_project);
@@ -644,7 +644,8 @@
#define GF_MAX_BOOST 90.0
#define GF_MIN_BOOST 50
#define MIN_DECAY_FACTOR 0.01
-int av1_calc_arf_boost(const TWO_PASS *twopass, const RATE_CONTROL *rc,
+int av1_calc_arf_boost(const TWO_PASS *twopass,
+ const PRIMARY_RATE_CONTROL *p_rc, const RATE_CONTROL *rc,
FRAME_INFO *frame_info, int offset, int f_frames,
int b_frames, int *num_fpstats_used,
int *num_fpstats_required, int project_gfu_boost) {
@@ -724,7 +725,7 @@
assert(num_fpstats_required != NULL);
assert(num_fpstats_used != NULL);
*num_fpstats_required = f_frames + b_frames;
- arf_boost = get_projected_gfu_boost(rc, arf_boost, *num_fpstats_required,
+ arf_boost = get_projected_gfu_boost(p_rc, arf_boost, *num_fpstats_required,
*num_fpstats_used);
}
@@ -768,6 +769,7 @@
static int64_t calculate_total_gf_group_bits(AV1_COMP *cpi,
double gf_group_err) {
const RATE_CONTROL *const rc = &cpi->rc;
+ const PRIMARY_RATE_CONTROL *const p_rc = &cpi->ppi->p_rc;
const TWO_PASS *const twopass = &cpi->ppi->twopass;
const int max_bits = frame_max_bits(rc, &cpi->oxcf);
int64_t total_group_bits;
@@ -788,8 +790,8 @@
: total_group_bits;
// Clip based on user supplied data rate variability limit.
- if (total_group_bits > (int64_t)max_bits * rc->baseline_gf_interval)
- total_group_bits = (int64_t)max_bits * rc->baseline_gf_interval;
+ if (total_group_bits > (int64_t)max_bits * p_rc->baseline_gf_interval)
+ total_group_bits = (int64_t)max_bits * p_rc->baseline_gf_interval;
return total_group_bits;
}
@@ -836,6 +838,7 @@
int frame_type) {
const AV1_COMMON *const cm = &cpi->common;
const SequenceHeader *const seq_params = &cm->seq_params;
+ PRIMARY_RATE_CONTROL *const p_rc = &cpi->ppi->p_rc;
const int temporal_layer_id = cm->temporal_layer_id;
const int spatial_layer_id = cm->spatial_layer_id;
for (int index = 0; index < seq_params->operating_points_cnt_minus_1 + 1;
@@ -860,18 +863,20 @@
const int level_enforced_max_kf_bits = target_bits_per_frame * 8;
if (bits_assigned > level_enforced_max_kf_bits) {
const int frames = rc->frames_to_key - 1;
- rc->kf_boost = calculate_boost_factor(
+ p_rc->kf_boost = calculate_boost_factor(
frames, level_enforced_max_kf_bits, group_bits);
- bits_assigned = calculate_boost_bits(frames, rc->kf_boost, group_bits);
+ bits_assigned =
+ calculate_boost_bits(frames, p_rc->kf_boost, group_bits);
}
} else if (frame_type == 1) {
// Maximum bits for arf is 4 times the target_bits_per_frame.
const int level_enforced_max_arf_bits = target_bits_per_frame * 4;
if (bits_assigned > level_enforced_max_arf_bits) {
- rc->gfu_boost = calculate_boost_factor(
- rc->baseline_gf_interval, level_enforced_max_arf_bits, group_bits);
- bits_assigned = calculate_boost_bits(rc->baseline_gf_interval,
- rc->gfu_boost, group_bits);
+ p_rc->gfu_boost =
+ calculate_boost_factor(p_rc->baseline_gf_interval,
+ level_enforced_max_arf_bits, group_bits);
+ bits_assigned = calculate_boost_bits(p_rc->baseline_gf_interval,
+ p_rc->gfu_boost, group_bits);
}
} else {
assert(0);
@@ -884,7 +889,9 @@
// Allocate bits to each frame in a GF / ARF group
double layer_fraction[MAX_ARF_LAYERS + 1] = { 1.0, 0.70, 0.55, 0.60,
0.60, 1.0, 1.0 };
-static void allocate_gf_group_bits(GF_GROUP *gf_group, RATE_CONTROL *const rc,
+static void allocate_gf_group_bits(GF_GROUP *gf_group,
+ PRIMARY_RATE_CONTROL *const p_rc,
+ RATE_CONTROL *const rc,
int64_t gf_group_bits, int gf_arf_bits,
int key_frame, int use_arf) {
int64_t total_group_bits = gf_group_bits;
@@ -901,7 +908,7 @@
if (use_arf) total_group_bits -= gf_arf_bits;
int num_frames =
- AOMMAX(1, rc->baseline_gf_interval - (rc->frames_since_key == 0));
+ AOMMAX(1, p_rc->baseline_gf_interval - (rc->frames_since_key == 0));
base_frame_bits = (int)(total_group_bits / num_frames);
// Check the number of frames in each layer in case we have a
@@ -1009,6 +1016,7 @@
EncodeFrameParams *frame_params,
const EncodeFrameInput *frame_input) {
RATE_CONTROL *const rc = &cpi->rc;
+ PRIMARY_RATE_CONTROL *const p_rc = &cpi->ppi->p_rc;
int gop_length_decision_method = cpi->sf.tpl_sf.gop_length_decision_method;
int shorten_gf_interval;
@@ -1016,8 +1024,8 @@
// GF group length is decided based on GF boost and tpl stats of ARFs from
// base layer, (base+1) layer.
shorten_gf_interval =
- (rc->gfu_boost <
- rc->num_stats_used_for_gfu_boost * GF_MIN_BOOST * 1.4) &&
+ (p_rc->gfu_boost <
+ p_rc->num_stats_used_for_gfu_boost * GF_MIN_BOOST * 1.4) &&
!av1_tpl_setup_stats(cpi, 3, frame_params, frame_input);
} else {
int do_complete_tpl = 1;
@@ -1849,12 +1857,13 @@
* \param[in] max_gop_length Maximum length of the GF group
* \param[in] max_intervals Maximum number of intervals to decide
*
- * \return Nothing is returned. Instead, cpi->rc.gf_intervals is
+ * \return Nothing is returned. Instead, cpi->ppi->rc.gf_intervals is
* changed to store the decided GF group lengths.
*/
static void calculate_gf_length(AV1_COMP *cpi, int max_gop_length,
int max_intervals) {
RATE_CONTROL *const rc = &cpi->rc;
+ PRIMARY_RATE_CONTROL *const p_rc = &cpi->ppi->p_rc;
TWO_PASS *const twopass = &cpi->ppi->twopass;
FIRSTPASS_STATS next_frame;
const FIRSTPASS_STATS *const start_pos = twopass->stats_in;
@@ -1869,9 +1878,9 @@
if (has_no_stats_stage(cpi)) {
for (i = 0; i < MAX_NUM_GF_INTERVALS; i++) {
- rc->gf_intervals[i] = AOMMIN(rc->max_gf_interval, max_gop_length);
+ p_rc->gf_intervals[i] = AOMMIN(rc->max_gf_interval, max_gop_length);
}
- rc->cur_gf_index = 0;
+ p_rc->cur_gf_index = 0;
rc->intervals_till_gf_calculate_due = MAX_NUM_GF_INTERVALS;
return;
}
@@ -1893,7 +1902,7 @@
init_gf_stats(&gf_stats);
while (count_cuts < max_intervals + 1) {
// reaches next key frame, break here
- if (i >= rc->frames_to_key + rc->next_is_fwd_key) {
+ if (i >= rc->frames_to_key + p_rc->next_is_fwd_key) {
cut_here = 2;
} else if (i - cur_start >= rc->static_scene_max_gf_interval) {
// reached maximum len, but nothing special yet (almost static)
@@ -1920,10 +1929,10 @@
int ori_last = cur_last;
// The region frame idx does not start from the same frame as cur_start
// and cur_last. Need to offset them.
- int offset = rc->frames_since_key - rc->regions_offset;
- REGIONS *regions = rc->regions;
- int num_regions = rc->num_regions;
- if (cpi->oxcf.kf_cfg.fwd_kf_enabled && rc->next_is_fwd_key) {
+ int offset = rc->frames_since_key - p_rc->regions_offset;
+ REGIONS *regions = p_rc->regions;
+ int num_regions = p_rc->num_regions;
+ if (cpi->oxcf.kf_cfg.fwd_kf_enabled && p_rc->next_is_fwd_key) {
const int frames_left = rc->frames_to_key - i;
const int min_int = AOMMIN(MIN_FWD_KF_INTERVAL, active_min_gf_interval);
if (frames_left < min_int && frames_left > 0) {
@@ -2088,9 +2097,9 @@
// save intervals
rc->intervals_till_gf_calculate_due = count_cuts - 1;
for (int n = 1; n < count_cuts; n++) {
- rc->gf_intervals[n - 1] = cut_pos[n] - cut_pos[n - 1];
+ p_rc->gf_intervals[n - 1] = cut_pos[n] - cut_pos[n - 1];
}
- rc->cur_gf_index = 0;
+ p_rc->cur_gf_index = 0;
twopass->stats_in = start_pos;
}
@@ -2123,6 +2132,7 @@
*/
static void define_gf_group_pass0(AV1_COMP *cpi) {
RATE_CONTROL *const rc = &cpi->rc;
+ PRIMARY_RATE_CONTROL *const p_rc = &cpi->ppi->p_rc;
GF_GROUP *const gf_group = &cpi->ppi->gf_group;
const AV1EncoderConfig *const oxcf = &cpi->oxcf;
const GFConfig *const gf_cfg = &oxcf->gf_cfg;
@@ -2131,28 +2141,28 @@
if (oxcf->q_cfg.aq_mode == CYCLIC_REFRESH_AQ) {
av1_cyclic_refresh_set_golden_update(cpi);
} else {
- rc->baseline_gf_interval = rc->gf_intervals[rc->cur_gf_index];
+ p_rc->baseline_gf_interval = p_rc->gf_intervals[p_rc->cur_gf_index];
rc->intervals_till_gf_calculate_due--;
- rc->cur_gf_index++;
+ p_rc->cur_gf_index++;
}
// correct frames_to_key when lookahead queue is flushing
correct_frames_to_key(cpi);
- if (rc->baseline_gf_interval > rc->frames_to_key)
- rc->baseline_gf_interval = rc->frames_to_key;
+ if (p_rc->baseline_gf_interval > rc->frames_to_key)
+ p_rc->baseline_gf_interval = rc->frames_to_key;
- rc->gfu_boost = DEFAULT_GF_BOOST;
- rc->constrained_gf_group =
- (rc->baseline_gf_interval >= rc->frames_to_key) ? 1 : 0;
+ p_rc->gfu_boost = DEFAULT_GF_BOOST;
+ p_rc->constrained_gf_group =
+ (p_rc->baseline_gf_interval >= rc->frames_to_key) ? 1 : 0;
gf_group->max_layer_depth_allowed = oxcf->gf_cfg.gf_max_pyr_height;
// Rare case when the look-ahead is less than the target GOP length, can't
// generate ARF frame.
- if (rc->baseline_gf_interval > gf_cfg->lag_in_frames ||
+ if (p_rc->baseline_gf_interval > gf_cfg->lag_in_frames ||
!is_altref_enabled(gf_cfg->lag_in_frames, gf_cfg->enable_auto_arf) ||
- rc->baseline_gf_interval < rc->min_gf_interval)
+ p_rc->baseline_gf_interval < rc->min_gf_interval)
gf_group->max_layer_depth_allowed = 0;
// Set up the structure of this Group-Of-Pictures (same as GF_GROUP)
@@ -2184,6 +2194,7 @@
int use_alt_ref,
int is_final_pass) {
RATE_CONTROL *const rc = &cpi->rc;
+ PRIMARY_RATE_CONTROL *const p_rc = &cpi->ppi->p_rc;
TWO_PASS *const twopass = &cpi->ppi->twopass;
// Set the interval until the next gf.
// If forward keyframes are enabled, ensure the final gf group obeys the
@@ -2193,27 +2204,28 @@
twopass->stats_buf_ctx->stats_in_end;
if (cpi->oxcf.kf_cfg.fwd_kf_enabled && use_alt_ref && !is_last_kf &&
- cpi->rc.next_is_fwd_key) {
+ cpi->ppi->p_rc.next_is_fwd_key) {
if (arf_position == rc->frames_to_key + 1) {
- rc->baseline_gf_interval = arf_position;
+ p_rc->baseline_gf_interval = arf_position;
// if the last gf group will be smaller than MIN_FWD_KF_INTERVAL
} else if (rc->frames_to_key + 1 - arf_position <
AOMMAX(MIN_FWD_KF_INTERVAL, rc->min_gf_interval)) {
// if possible, merge the last two gf groups
if (rc->frames_to_key + 1 <= active_max_gf_interval) {
- rc->baseline_gf_interval = rc->frames_to_key + 1;
+ p_rc->baseline_gf_interval = rc->frames_to_key + 1;
if (is_final_pass) rc->intervals_till_gf_calculate_due = 0;
// if merging the last two gf groups creates a group that is too long,
// split them and force the last gf group to be the MIN_FWD_KF_INTERVAL
} else {
- rc->baseline_gf_interval = rc->frames_to_key + 1 - MIN_FWD_KF_INTERVAL;
+ p_rc->baseline_gf_interval =
+ rc->frames_to_key + 1 - MIN_FWD_KF_INTERVAL;
if (is_final_pass) rc->intervals_till_gf_calculate_due = 0;
}
} else {
- rc->baseline_gf_interval = arf_position;
+ p_rc->baseline_gf_interval = arf_position;
}
} else {
- rc->baseline_gf_interval = arf_position;
+ p_rc->baseline_gf_interval = arf_position;
}
}
@@ -2266,6 +2278,7 @@
int is_final_pass) {
AV1_COMMON *const cm = &cpi->common;
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;
@@ -2327,8 +2340,8 @@
AOMMIN(rc->max_gf_interval, max_gop_length);
i = is_intra_only;
- // get the determined gf group length from rc->gf_intervals
- while (i < rc->gf_intervals[rc->cur_gf_index]) {
+ // get the determined gf group length from p_rc->gf_intervals
+ while (i < p_rc->gf_intervals[p_rc->cur_gf_index]) {
// read in the next frame
if (EOF == input_stats(twopass, &next_frame)) break;
// Accumulate error score of frames in this gf group.
@@ -2351,7 +2364,7 @@
i = is_intra_only;
input_stats(twopass, &next_frame);
- while (i < rc->gf_intervals[rc->cur_gf_index]) {
+ while (i < p_rc->gf_intervals[p_rc->cur_gf_index]) {
// read in the next frame
if (EOF == input_stats(twopass, &next_frame)) break;
@@ -2366,7 +2379,7 @@
++i;
}
- i = rc->gf_intervals[rc->cur_gf_index];
+ i = p_rc->gf_intervals[p_rc->cur_gf_index];
// save the errs for the last frame
last_frame_stats.frame_coded_error = next_frame.coded_error;
@@ -2375,11 +2388,11 @@
if (is_final_pass) {
rc->intervals_till_gf_calculate_due--;
- rc->cur_gf_index++;
+ p_rc->cur_gf_index++;
}
// Was the group length constrained by the requirement for a new KF?
- rc->constrained_gf_group = (i >= rc->frames_to_key) ? 1 : 0;
+ p_rc->constrained_gf_group = (i >= rc->frames_to_key) ? 1 : 0;
const int num_mbs = (oxcf->resize_cfg.resize_mode != RESIZE_NONE)
? cpi->initial_mbs
@@ -2406,7 +2419,7 @@
use_alt_ref =
!is_almost_static(gf_stats.zero_motion_accumulator,
twopass->kf_zeromotion_pct, cpi->ppi->lap_enabled) &&
- rc->use_arf_in_this_kf_group && (i < gf_cfg->lag_in_frames) &&
+ p_rc->use_arf_in_this_kf_group && (i < gf_cfg->lag_in_frames) &&
(i >= MIN_GF_INTERVAL);
// TODO(urvang): Improve and use model for VBR, CQ etc as well.
@@ -2415,15 +2428,15 @@
float features[21];
get_features_from_gf_stats(
&gf_stats, &first_frame_stats, &last_frame_stats, num_mbs,
- rc->constrained_gf_group, twopass->kf_zeromotion_pct, i, features);
+ p_rc->constrained_gf_group, twopass->kf_zeromotion_pct, i, features);
// Infer using ML model.
float score;
av1_nn_predict(features, &av1_use_flat_gop_nn_config, 1, &score);
use_alt_ref = (score <= 0.0);
}
} else {
- use_alt_ref =
- rc->use_arf_in_this_kf_group && (i < gf_cfg->lag_in_frames) && (i > 2);
+ use_alt_ref = p_rc->use_arf_in_this_kf_group &&
+ (i < gf_cfg->lag_in_frames) && (i > 2);
}
#define REDUCE_GF_LENGTH_THRESH 4
@@ -2476,35 +2489,35 @@
: 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, ext_len,
- &rc->num_stats_used_for_gfu_boost,
- &rc->num_stats_required_for_gfu_boost, cpi->ppi->lap_enabled);
+ p_rc->gfu_boost = av1_calc_arf_boost(
+ twopass, p_rc, rc, frame_info, alt_offset, forward_frames, ext_len,
+ &p_rc->num_stats_used_for_gfu_boost,
+ &p_rc->num_stats_required_for_gfu_boost, cpi->ppi->lap_enabled);
} else {
reset_fpf_position(twopass, start_pos);
gf_group->max_layer_depth_allowed = 0;
set_baseline_gf_interval(cpi, i, active_max_gf_interval, use_alt_ref,
is_final_pass);
- rc->gfu_boost =
- AOMMIN(MAX_GF_BOOST,
- av1_calc_arf_boost(twopass, rc, frame_info, alt_offset, ext_len,
- 0, &rc->num_stats_used_for_gfu_boost,
- &rc->num_stats_required_for_gfu_boost,
- cpi->ppi->lap_enabled));
+ p_rc->gfu_boost = AOMMIN(
+ MAX_GF_BOOST,
+ av1_calc_arf_boost(twopass, p_rc, rc, frame_info, alt_offset, ext_len,
+ 0, &p_rc->num_stats_used_for_gfu_boost,
+ &p_rc->num_stats_required_for_gfu_boost,
+ cpi->ppi->lap_enabled));
}
#define LAST_ALR_BOOST_FACTOR 0.2f
- rc->arf_boost_factor = 1.0;
+ p_rc->arf_boost_factor = 1.0;
if (use_alt_ref && !is_lossless_requested(rc_cfg)) {
// Reduce the boost of altref in the last gf group
if (rc->frames_to_key - ext_len == REDUCE_GF_LENGTH_BY ||
rc->frames_to_key - ext_len == 0) {
- rc->arf_boost_factor = LAST_ALR_BOOST_FACTOR;
+ p_rc->arf_boost_factor = LAST_ALR_BOOST_FACTOR;
}
}
- rc->frames_till_gf_update_due = rc->baseline_gf_interval;
+ rc->frames_till_gf_update_due = p_rc->baseline_gf_interval;
// Reset the file position.
reset_fpf_position(twopass, start_pos);
@@ -2513,11 +2526,11 @@
// Since we don't have enough stats to know the actual error of the
// gf group, we assume error of each frame to be equal to 1 and set
// the error of the group as baseline_gf_interval.
- gf_stats.gf_group_err = rc->baseline_gf_interval;
+ gf_stats.gf_group_err = p_rc->baseline_gf_interval;
}
// Calculate the bits to be allocated to the gf/arf group as a whole
gf_group_bits = calculate_total_gf_group_bits(cpi, gf_stats.gf_group_err);
- rc->gf_group_bits = gf_group_bits;
+ p_rc->gf_group_bits = gf_group_bits;
#if GROUP_ADAPTIVE_MAXQ
// Calculate an estimate of the maxq needed for the group.
@@ -2525,17 +2538,17 @@
// where there could be significant overshoot than for easier
// sections where we do not wish to risk creating an overshoot
// of the allocated bit budget.
- if ((rc_cfg->mode != AOM_Q) && (rc->baseline_gf_interval > 1) &&
+ if ((rc_cfg->mode != AOM_Q) && (p_rc->baseline_gf_interval > 1) &&
is_final_pass) {
const int vbr_group_bits_per_frame =
- (int)(gf_group_bits / rc->baseline_gf_interval);
+ (int)(gf_group_bits / p_rc->baseline_gf_interval);
const double group_av_err =
- gf_stats.gf_group_raw_error / rc->baseline_gf_interval;
+ gf_stats.gf_group_raw_error / p_rc->baseline_gf_interval;
const double group_av_skip_pct =
- gf_stats.gf_group_skip_pct / rc->baseline_gf_interval;
+ gf_stats.gf_group_skip_pct / p_rc->baseline_gf_interval;
const double group_av_inactive_zone =
((gf_stats.gf_group_inactive_zone_rows * 2) /
- (rc->baseline_gf_interval * (double)cm->mi_params.mb_rows));
+ (p_rc->baseline_gf_interval * (double)cm->mi_params.mb_rows));
int tmp_q;
tmp_q = get_twopass_worst_quality(
@@ -2559,7 +2572,7 @@
if (rc->frames_since_key != 0) {
twopass->section_intra_rating = calculate_section_intra_ratio(
start_pos, twopass->stats_buf_ctx->stats_in_end,
- rc->baseline_gf_interval);
+ p_rc->baseline_gf_interval);
}
av1_gop_bit_allocation(cpi, rc, gf_group, rc->frames_since_key == 0,
@@ -2588,12 +2601,13 @@
void av1_gop_bit_allocation(const AV1_COMP *cpi, RATE_CONTROL *const rc,
GF_GROUP *gf_group, int is_key_frame, int use_arf,
int64_t gf_group_bits) {
+ PRIMARY_RATE_CONTROL *const p_rc = &cpi->ppi->p_rc;
// Calculate the extra bits to be used for boosted frame(s)
#ifdef FIXED_ARF_BITS
int gf_arf_bits = (int)(ARF_BITS_FRACTION * gf_group_bits);
#else
int gf_arf_bits = calculate_boost_bits(
- rc->baseline_gf_interval - (rc->frames_since_key == 0), rc->gfu_boost,
+ p_rc->baseline_gf_interval - (rc->frames_since_key == 0), p_rc->gfu_boost,
gf_group_bits);
#endif
@@ -2601,8 +2615,8 @@
gf_group_bits, 1);
// Allocate bits to each of the frames in the GF group.
- allocate_gf_group_bits(gf_group, rc, gf_group_bits, gf_arf_bits, is_key_frame,
- use_arf);
+ allocate_gf_group_bits(gf_group, p_rc, rc, gf_group_bits, gf_arf_bits,
+ is_key_frame, use_arf);
}
// Minimum % intra coding observed in first pass (1.0 = 100%)
@@ -2777,10 +2791,10 @@
#define MIN_STATIC_KF_BOOST 5400 // Minimum boost for static KF interval
static int detect_app_forced_key(AV1_COMP *cpi) {
- if (cpi->oxcf.kf_cfg.fwd_kf_enabled) cpi->rc.next_is_fwd_key = 1;
+ if (cpi->oxcf.kf_cfg.fwd_kf_enabled) cpi->ppi->p_rc.next_is_fwd_key = 1;
int num_frames_to_app_forced_key = is_forced_keyframe_pending(
cpi->ppi->lookahead, cpi->ppi->lookahead->max_sz, cpi->compressor_stage);
- if (num_frames_to_app_forced_key != -1) cpi->rc.next_is_fwd_key = 0;
+ if (num_frames_to_app_forced_key != -1) cpi->ppi->p_rc.next_is_fwd_key = 0;
return num_frames_to_app_forced_key;
}
@@ -2790,16 +2804,16 @@
* all stats needed for prior boost calculation are available.
* Hence projecting the prior boost is not needed in this cases.
*/
- if (cpi->rc.num_stats_used_for_kf_boost >= cpi->rc.frames_to_key)
- return cpi->rc.kf_boost;
+ if (cpi->ppi->p_rc.num_stats_used_for_kf_boost >= cpi->rc.frames_to_key)
+ return cpi->ppi->p_rc.kf_boost;
// Get the current tpl factor (number of frames = frames_to_key).
double tpl_factor = av1_get_kf_boost_projection_factor(cpi->rc.frames_to_key);
// Get the tpl factor when number of frames = num_stats_used_for_kf_boost.
- double tpl_factor_num_stats =
- av1_get_kf_boost_projection_factor(cpi->rc.num_stats_used_for_kf_boost);
+ double tpl_factor_num_stats = av1_get_kf_boost_projection_factor(
+ cpi->ppi->p_rc.num_stats_used_for_kf_boost);
int projected_kf_boost =
- (int)rint((tpl_factor * cpi->rc.kf_boost) / tpl_factor_num_stats);
+ (int)rint((tpl_factor * cpi->ppi->p_rc.kf_boost) / tpl_factor_num_stats);
return projected_kf_boost;
}
@@ -2821,6 +2835,7 @@
int num_frames_to_detect_scenecut) {
TWO_PASS *const twopass = &cpi->ppi->twopass;
RATE_CONTROL *const rc = &cpi->rc;
+ PRIMARY_RATE_CONTROL *const p_rc = &cpi->ppi->p_rc;
const AV1EncoderConfig *const oxcf = &cpi->oxcf;
const KeyFrameCfg *const kf_cfg = &oxcf->kf_cfg;
double recent_loop_decay[FRAMES_TO_CHECK_DECAY];
@@ -2865,7 +2880,7 @@
input_stats(twopass, this_frame);
// Provided that we are not at the end of the file...
- if ((cpi->rc.enable_scenecut_detection > 0) && kf_cfg->auto_key &&
+ if ((cpi->ppi->p_rc.enable_scenecut_detection > 0) && kf_cfg->auto_key &&
twopass->stats_in < twopass->stats_buf_ctx->stats_in_end) {
double loop_decay_rate;
@@ -2873,7 +2888,7 @@
if (frames_since_key >= kf_cfg->key_freq_min &&
test_candidate_kf(twopass, &last_frame, this_frame, twopass->stats_in,
frames_since_key, oxcf->rc_cfg.mode,
- cpi->rc.enable_scenecut_detection)) {
+ cpi->ppi->p_rc.enable_scenecut_detection)) {
scenecut_detected = 1;
break;
}
@@ -2900,7 +2915,7 @@
// In the case of transition followed by a static scene, the key frame
// could be a good predictor for the following frames, therefore we
// do not use an arf.
- rc->use_arf_in_this_kf_group = 0;
+ p_rc->use_arf_in_this_kf_group = 0;
break;
}
@@ -2919,14 +2934,14 @@
}
if (kf_group_err != NULL)
- rc->num_stats_used_for_kf_boost = num_stats_used_for_kf_boost;
+ p_rc->num_stats_used_for_kf_boost = num_stats_used_for_kf_boost;
if (cpi->ppi->lap_enabled && !scenecut_detected)
frames_to_key = num_frames_to_next_key;
if (!kf_cfg->fwd_kf_enabled || scenecut_detected ||
twopass->stats_in >= twopass->stats_buf_ctx->stats_in_end)
- rc->next_is_fwd_key = 0;
+ p_rc->next_is_fwd_key = 0;
return frames_to_key;
}
@@ -3093,6 +3108,7 @@
*/
static void find_next_key_frame(AV1_COMP *cpi, FIRSTPASS_STATS *this_frame) {
RATE_CONTROL *const rc = &cpi->rc;
+ PRIMARY_RATE_CONTROL *const p_rc = &cpi->ppi->p_rc;
TWO_PASS *const twopass = &cpi->ppi->twopass;
GF_GROUP *const gf_group = &cpi->ppi->gf_group;
FRAME_INFO *const frame_info = &cpi->frame_info;
@@ -3106,7 +3122,7 @@
rc->frames_since_key = 0;
// Use arfs if possible.
- rc->use_arf_in_this_kf_group = is_altref_enabled(
+ p_rc->use_arf_in_this_kf_group = is_altref_enabled(
oxcf->gf_cfg.lag_in_frames, oxcf->gf_cfg.enable_auto_arf);
// Reset the GF group data structures.
@@ -3118,14 +3134,14 @@
if (has_no_stats_stage(cpi)) {
int num_frames_to_app_forced_key = detect_app_forced_key(cpi);
- rc->this_key_frame_forced =
+ p_rc->this_key_frame_forced =
current_frame->frame_number != 0 && rc->frames_to_key == 0;
if (num_frames_to_app_forced_key != -1)
rc->frames_to_key = num_frames_to_app_forced_key;
else
rc->frames_to_key = AOMMAX(1, kf_cfg->key_freq_max);
correct_frames_to_key(cpi);
- rc->kf_boost = DEFAULT_KF_BOOST;
+ p_rc->kf_boost = DEFAULT_KF_BOOST;
gf_group->update_type[0] = KF_UPDATE;
return;
}
@@ -3143,7 +3159,7 @@
int64_t kf_group_bits_clipped = INT64_MAX;
// Is this a forced key frame by interval.
- rc->this_key_frame_forced = rc->next_key_frame_forced;
+ p_rc->this_key_frame_forced = p_rc->next_key_frame_forced;
twopass->kf_group_bits = 0; // Total bits available to kf group
twopass->kf_group_error_left = 0; // Group modified error score.
@@ -3181,23 +3197,24 @@
calculate_modified_err(frame_info, twopass, oxcf, &tmp_frame);
if (EOF == input_stats(twopass, &tmp_frame)) break;
}
- rc->next_key_frame_forced = 1;
+ p_rc->next_key_frame_forced = 1;
} else if ((twopass->stats_in == twopass->stats_buf_ctx->stats_in_end &&
is_stat_consumption_stage_twopass(cpi)) ||
rc->frames_to_key >= kf_cfg->key_freq_max) {
- rc->next_key_frame_forced = 1;
+ p_rc->next_key_frame_forced = 1;
} else {
- rc->next_key_frame_forced = 0;
+ p_rc->next_key_frame_forced = 0;
}
- if (kf_cfg->fwd_kf_enabled) rc->next_is_fwd_key |= rc->next_key_frame_forced;
+ if (kf_cfg->fwd_kf_enabled)
+ p_rc->next_is_fwd_key |= p_rc->next_key_frame_forced;
// Special case for the last key frame of the file.
if (twopass->stats_in >= twopass->stats_buf_ctx->stats_in_end) {
// Accumulate kf group error.
kf_group_err +=
calculate_modified_err(frame_info, twopass, oxcf, this_frame);
- rc->next_is_fwd_key = 0;
+ p_rc->next_is_fwd_key = 0;
}
// Calculate the number of bits that should be assigned to the kf group.
@@ -3258,17 +3275,17 @@
twopass->section_intra_rating = calculate_section_intra_ratio(
start_position, twopass->stats_buf_ctx->stats_in_end, rc->frames_to_key);
- rc->kf_boost = (int)boost_score;
+ p_rc->kf_boost = (int)boost_score;
if (cpi->ppi->lap_enabled) {
if (oxcf->rc_cfg.mode == AOM_Q) {
- rc->kf_boost = get_projected_kf_boost(cpi);
+ p_rc->kf_boost = get_projected_kf_boost(cpi);
} else {
// TODO(any): Explore using average frame stats for AOM_Q as well.
boost_score = get_kf_boost_score(
cpi, kf_raw_err, &zero_motion_accumulator, &sr_accumulator, 1);
reset_fpf_position(twopass, start_position);
- rc->kf_boost += (int)boost_score;
+ p_rc->kf_boost += (int)boost_score;
}
}
@@ -3276,13 +3293,13 @@
// if the kf group is very short.
if ((zero_motion_accumulator > STATIC_KF_GROUP_FLOAT_THRESH) &&
(rc->frames_to_key > 8)) {
- rc->kf_boost = AOMMAX(rc->kf_boost, MIN_STATIC_KF_BOOST);
+ p_rc->kf_boost = AOMMAX(p_rc->kf_boost, MIN_STATIC_KF_BOOST);
} else {
// Apply various clamps for min and max boost
- rc->kf_boost = AOMMAX(rc->kf_boost, (rc->frames_to_key * 3));
- rc->kf_boost = AOMMAX(rc->kf_boost, MIN_KF_BOOST);
+ p_rc->kf_boost = AOMMAX(p_rc->kf_boost, (rc->frames_to_key * 3));
+ p_rc->kf_boost = AOMMAX(p_rc->kf_boost, MIN_KF_BOOST);
#ifdef STRICT_RC
- rc->kf_boost = AOMMIN(rc->kf_boost, MAX_KF_BOOST);
+ p_rc->kf_boost = AOMMIN(p_rc->kf_boost, MAX_KF_BOOST);
#endif
}
@@ -3291,9 +3308,10 @@
// very high, we calculate the bits based on a clipped value of
// frames_to_key.
kf_bits = calculate_boost_bits(
- AOMMIN(rc->frames_to_key, frames_to_key_clipped) - 1, rc->kf_boost,
+ AOMMIN(rc->frames_to_key, frames_to_key_clipped) - 1, p_rc->kf_boost,
AOMMIN(twopass->kf_group_bits, kf_group_bits_clipped));
- // printf("kf boost = %d kf_bits = %d kf_zeromotion_pct = %d\n", rc->kf_boost,
+ // printf("kf boost = %d kf_bits = %d kf_zeromotion_pct = %d\n",
+ // p_rc->kf_boost,
// kf_bits, twopass->kf_zeromotion_pct);
kf_bits = adjust_boost_bits_for_target_level(cpi, rc, kf_bits,
twopass->kf_group_bits, 0);
@@ -3582,6 +3600,7 @@
const EncodeFrameInput *const frame_input,
unsigned int frame_flags) {
RATE_CONTROL *const rc = &cpi->rc;
+ PRIMARY_RATE_CONTROL *const p_rc = &cpi->ppi->p_rc;
TWO_PASS *const twopass = &cpi->ppi->twopass;
GF_GROUP *const gf_group = &cpi->ppi->gf_group;
const AV1EncoderConfig *const oxcf = &cpi->oxcf;
@@ -3684,7 +3703,7 @@
cpi->gf_frame_index == gf_group->size);
const FIRSTPASS_STATS *const start_position = twopass->stats_in;
- if (cpi->ppi->lap_enabled && cpi->rc.enable_scenecut_detection) {
+ if (cpi->ppi->lap_enabled && cpi->ppi->p_rc.enable_scenecut_detection) {
int num_frames_to_detect_scenecut, frames_to_key;
num_frames_to_detect_scenecut = MAX_GF_LENGTH_LAP + 1;
frames_to_key = define_kf_interval(cpi, &this_frame, NULL,
@@ -3705,17 +3724,17 @@
// Identify regions if needed.
// TODO(bohanli): identify regions for all stats available.
if (rc->frames_since_key == 0 || rc->frames_since_key == 1 ||
- (rc->frames_till_regions_update - rc->frames_since_key <
+ (p_rc->frames_till_regions_update - rc->frames_since_key <
rc->frames_to_key &&
- rc->frames_till_regions_update - rc->frames_since_key <
+ p_rc->frames_till_regions_update - rc->frames_since_key <
max_gop_length + 1)) {
// how many frames we can analyze from this frame
- int rest_frames = AOMMIN(rc->frames_to_key + rc->next_is_fwd_key,
+ int rest_frames = AOMMIN(rc->frames_to_key + p_rc->next_is_fwd_key,
MAX_FIRSTPASS_ANALYSIS_FRAMES);
rest_frames = AOMMIN(
rest_frames, (int)(twopass->stats_buf_ctx->stats_in_end -
twopass->stats_in + (rc->frames_since_key == 0)));
- rc->frames_till_regions_update = rest_frames;
+ p_rc->frames_till_regions_update = rest_frames;
if (cpi->ppi->lap_enabled) {
mark_flashes(twopass->stats_buf_ctx->stats_in_start,
@@ -3725,19 +3744,19 @@
estimate_coeff(twopass->stats_buf_ctx->stats_in_start,
twopass->stats_buf_ctx->stats_in_end);
identify_regions(twopass->stats_in, rest_frames,
- (rc->frames_since_key == 0), rc->regions,
- &rc->num_regions);
+ (rc->frames_since_key == 0), p_rc->regions,
+ &p_rc->num_regions);
} else {
identify_regions(twopass->stats_in - (rc->frames_since_key == 0),
- rest_frames, 0, rc->regions, &rc->num_regions);
+ rest_frames, 0, p_rc->regions, &p_rc->num_regions);
}
}
int cur_region_idx =
- find_regions_index(rc->regions, rc->num_regions,
- rc->frames_since_key - rc->regions_offset);
+ find_regions_index(p_rc->regions, p_rc->num_regions,
+ rc->frames_since_key - p_rc->regions_offset);
if ((cur_region_idx >= 0 &&
- rc->regions[cur_region_idx].type == SCENECUT_REGION) ||
+ p_rc->regions[cur_region_idx].type == SCENECUT_REGION) ||
rc->frames_since_key == 0) {
// If we start from a scenecut, then the last GOP's arf boost is not
// needed for this GOP.
@@ -3751,19 +3770,20 @@
if (max_gop_length > 16 && oxcf->algo_cfg.enable_tpl_model &&
cpi->sf.tpl_sf.gop_length_decision_method != 3) {
- int this_idx = rc->frames_since_key + rc->gf_intervals[rc->cur_gf_index] -
- rc->regions_offset - 1;
+ int this_idx = rc->frames_since_key +
+ p_rc->gf_intervals[p_rc->cur_gf_index] -
+ p_rc->regions_offset - 1;
int this_region =
- find_regions_index(rc->regions, rc->num_regions, this_idx);
+ find_regions_index(p_rc->regions, p_rc->num_regions, this_idx);
int next_region =
- find_regions_index(rc->regions, rc->num_regions, this_idx + 1);
+ find_regions_index(p_rc->regions, p_rc->num_regions, this_idx + 1);
int is_last_scenecut =
- (rc->gf_intervals[rc->cur_gf_index] >= rc->frames_to_key ||
- rc->regions[this_region].type == SCENECUT_REGION ||
- rc->regions[next_region].type == SCENECUT_REGION);
- int ori_gf_int = rc->gf_intervals[rc->cur_gf_index];
+ (p_rc->gf_intervals[p_rc->cur_gf_index] >= rc->frames_to_key ||
+ p_rc->regions[this_region].type == SCENECUT_REGION ||
+ p_rc->regions[next_region].type == SCENECUT_REGION);
+ int ori_gf_int = p_rc->gf_intervals[p_rc->cur_gf_index];
- if (rc->gf_intervals[rc->cur_gf_index] > 16) {
+ if (p_rc->gf_intervals[p_rc->cur_gf_index] > 16) {
// The calculate_gf_length function is previously used with
// max_gop_length = 32 with look-ahead gf intervals.
define_gf_group(cpi, &this_frame, frame_params, max_gop_length, 0);
@@ -3775,8 +3795,8 @@
max_gop_length = 16;
calculate_gf_length(cpi, max_gop_length, 1);
if (is_last_scenecut &&
- (ori_gf_int - rc->gf_intervals[rc->cur_gf_index] < 4)) {
- rc->gf_intervals[rc->cur_gf_index] = ori_gf_int;
+ (ori_gf_int - p_rc->gf_intervals[p_rc->cur_gf_index] < 4)) {
+ p_rc->gf_intervals[p_rc->cur_gf_index] = ori_gf_int;
}
}
}
@@ -3789,7 +3809,7 @@
define_gf_group(cpi, &this_frame, frame_params, max_gop_length, 1);
- rc->frames_till_gf_update_due = rc->baseline_gf_interval;
+ rc->frames_till_gf_update_due = p_rc->baseline_gf_interval;
assert(cpi->gf_frame_index == 0);
#if ARF_STATS_OUTPUT
{
@@ -3798,8 +3818,8 @@
++arf_count;
fprintf(fpfile, "%10d %10d %10d %10d %10d\n",
cpi->common.current_frame.frame_number,
- rc->frames_till_gf_update_due, rc->kf_boost, arf_count,
- rc->gfu_boost);
+ p_rc->frames_till_gf_update_due, cpi->ppi->p_rc.kf_boost,
+ arf_count, p_rc->gfu_boost);
fclose(fpfile);
}
@@ -3970,7 +3990,7 @@
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
}
@@ -3984,9 +4004,9 @@
fprintf(fpfile,
"%10d %10d %10d %10" PRId64 " %10" PRId64
" %10d %10d %10d %10.4lf %10.4lf %10.4lf %10.4lf\n",
- cm->current_frame.frame_number, rc->base_frame_target,
- rc->projected_frame_size, rc->total_actual_bits,
- rc->vbr_bits_off_target, rc->rate_error_estimate,
+ cm->current_frame.frame_number, p_rc->base_frame_target,
+ p_rc->projected_frame_size, p_rc->total_actual_bits,
+ p_rc->vbr_bits_off_target, p_rc->rate_error_estimate,
twopass->rolling_arf_group_target_bits,
twopass->rolling_arf_group_actual_bits,
(double)twopass->rolling_arf_group_actual_bits /
@@ -3994,7 +4014,7 @@
twopass->bpm_factor,
av1_convert_qindex_to_q(cpi->common.quant_params.base_qindex,
cm->seq_params.bit_depth),
- av1_convert_qindex_to_q(rc->active_worst_quality,
+ av1_convert_qindex_to_q(p_rc->active_worst_quality,
cm->seq_params.bit_depth));
fclose(fpfile);
}
diff --git a/av1/encoder/ratectrl.c b/av1/encoder/ratectrl.c
index 27499b2..20af42f 100644
--- a/av1/encoder/ratectrl.c
+++ b/av1/encoder/ratectrl.c
@@ -233,11 +233,12 @@
LAYER_IDS_TO_IDX(svc->spatial_layer_id, i, svc->number_temporal_layers);
LAYER_CONTEXT *lc = &svc->layer_context[layer];
RATE_CONTROL *lrc = &lc->rc;
+ PRIMARY_RATE_CONTROL *lp_rc = &lc->p_rc;
lrc->bits_off_target +=
(int)(lc->target_bandwidth / lc->framerate) - encoded_frame_size;
// Clip buffer level to maximum buffer size for the layer.
lrc->bits_off_target =
- AOMMIN(lrc->bits_off_target, lrc->maximum_buffer_size);
+ AOMMIN(lrc->bits_off_target, lp_rc->maximum_buffer_size);
lrc->buffer_level = lrc->bits_off_target;
}
}
@@ -245,6 +246,7 @@
static void update_buffer_level(AV1_COMP *cpi, int encoded_frame_size) {
const AV1_COMMON *const cm = &cpi->common;
RATE_CONTROL *const rc = &cpi->rc;
+ PRIMARY_RATE_CONTROL *const p_rc = &cpi->ppi->p_rc;
// Non-viewable frames are a special case and are treated as pure overhead.
if (!cm->show_frame)
@@ -253,7 +255,7 @@
rc->bits_off_target += rc->avg_frame_bandwidth - encoded_frame_size;
// Clip the buffer level to the maximum specified buffer size.
- rc->bits_off_target = AOMMIN(rc->bits_off_target, rc->maximum_buffer_size);
+ rc->bits_off_target = AOMMIN(rc->bits_off_target, p_rc->maximum_buffer_size);
rc->buffer_level = rc->bits_off_target;
if (cpi->use_svc) update_layer_buffer_level(&cpi->svc, encoded_frame_size);
@@ -285,7 +287,24 @@
return AOMMAX(interval, min_gf_interval);
}
-void av1_rc_init(const AV1EncoderConfig *oxcf, int pass, RATE_CONTROL *rc) {
+void av1_primary_rc_init(const AV1EncoderConfig *oxcf,
+ PRIMARY_RATE_CONTROL *p_rc) {
+ int min_gf_interval = oxcf->gf_cfg.min_gf_interval;
+ int max_gf_interval = oxcf->gf_cfg.max_gf_interval;
+ if (min_gf_interval == 0)
+ min_gf_interval = av1_rc_get_default_min_gf_interval(
+ oxcf->frm_dim_cfg.width, oxcf->frm_dim_cfg.height,
+ oxcf->input_cfg.init_framerate);
+ if (max_gf_interval == 0)
+ max_gf_interval = av1_rc_get_default_max_gf_interval(
+ oxcf->input_cfg.init_framerate, min_gf_interval);
+ p_rc->baseline_gf_interval = (min_gf_interval + max_gf_interval) / 2;
+ p_rc->this_key_frame_forced = 0;
+ p_rc->next_key_frame_forced = 0;
+}
+
+void av1_rc_init(const AV1EncoderConfig *oxcf, int pass, RATE_CONTROL *rc,
+ const PRIMARY_RATE_CONTROL *const p_rc) {
const RateControlCfg *const rc_cfg = &oxcf->rc_cfg;
int i;
@@ -302,8 +321,8 @@
rc->last_q[KEY_FRAME] = rc_cfg->best_allowed_q;
rc->last_q[INTER_FRAME] = rc_cfg->worst_allowed_q;
- rc->buffer_level = rc->starting_buffer_level;
- rc->bits_off_target = rc->starting_buffer_level;
+ rc->buffer_level = p_rc->starting_buffer_level;
+ rc->bits_off_target = p_rc->starting_buffer_level;
rc->rolling_target_bits = rc->avg_frame_bandwidth;
rc->rolling_actual_bits = rc->avg_frame_bandwidth;
@@ -312,8 +331,6 @@
rc->total_target_bits = 0;
rc->frames_since_key = 8; // Sensible default for first frame.
- rc->this_key_frame_forced = 0;
- rc->next_key_frame_forced = 0;
rc->frames_till_gf_update_due = 0;
rc->ni_av_qi = rc_cfg->worst_allowed_q;
@@ -337,7 +354,6 @@
if (rc->max_gf_interval == 0)
rc->max_gf_interval = av1_rc_get_default_max_gf_interval(
oxcf->input_cfg.init_framerate, rc->min_gf_interval);
- rc->baseline_gf_interval = (rc->min_gf_interval + rc->max_gf_interval) / 2;
rc->avg_frame_low_motion = 0;
rc->resize_state = ORIG;
@@ -349,6 +365,7 @@
int av1_rc_drop_frame(AV1_COMP *cpi) {
const AV1EncoderConfig *oxcf = &cpi->oxcf;
RATE_CONTROL *const rc = &cpi->rc;
+ PRIMARY_RATE_CONTROL *const p_rc = &cpi->ppi->p_rc;
if (!oxcf->rc_cfg.drop_frames_water_mark) {
return 0;
@@ -360,7 +377,7 @@
// If buffer is below drop_mark, for now just drop every other frame
// (starting with the next frame) until it increases back over drop_mark.
int drop_mark = (int)(oxcf->rc_cfg.drop_frames_water_mark *
- rc->optimal_buffer_level / 100);
+ p_rc->optimal_buffer_level / 100);
if ((rc->buffer_level > drop_mark) && (rc->decimation_factor > 0)) {
--rc->decimation_factor;
} else if (rc->buffer_level <= drop_mark && rc->decimation_factor == 0) {
@@ -384,6 +401,7 @@
static int adjust_q_cbr(const AV1_COMP *cpi, int q, int active_worst_quality) {
const RATE_CONTROL *const rc = &cpi->rc;
+ const PRIMARY_RATE_CONTROL *const p_rc = &cpi->ppi->p_rc;
const AV1_COMMON *const cm = &cpi->common;
const RefreshFrameFlagsInfo *const refresh_frame_flags = &cpi->refresh_frame;
const int max_delta = 16;
@@ -419,14 +437,14 @@
// only for high Q to avoid excess overshoot.
// Else reduce decrease in Q from previous frame if content change is
// increasing and buffer is below max (so not undershooting).
- if (delta < 0.0 && rc->buffer_level > (rc->optimal_buffer_level >> 2) &&
+ if (delta < 0.0 && rc->buffer_level > (p_rc->optimal_buffer_level >> 2) &&
q > (rc->worst_quality >> 1)) {
double q_adj_factor = 1.0 + 0.5 * tanh(4.0 * delta);
double q_val = av1_convert_qindex_to_q(q, bit_depth);
q += av1_compute_qdelta(rc, q_val, q_val * q_adj_factor, bit_depth);
} else if (rc->q_1_frame - q > 0 && delta > 0.1 &&
- rc->buffer_level < AOMMIN(rc->maximum_buffer_size,
- rc->optimal_buffer_level << 1)) {
+ rc->buffer_level < AOMMIN(p_rc->maximum_buffer_size,
+ p_rc->optimal_buffer_level << 1)) {
q = (3 * q + rc->q_1_frame) >> 2;
}
}
@@ -727,23 +745,23 @@
}
}
-static int get_kf_active_quality(const RATE_CONTROL *const rc, int q,
+static int get_kf_active_quality(const PRIMARY_RATE_CONTROL *const p_rc, int q,
aom_bit_depth_t bit_depth) {
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);
- return get_active_quality(q, rc->kf_boost, kf_low, kf_high,
+ 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(const RATE_CONTROL *const rc, int q,
+static int get_gf_active_quality(const PRIMARY_RATE_CONTROL *const p_rc, int q,
aom_bit_depth_t bit_depth) {
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, rc->gfu_boost, gf_low, gf_high,
+ return get_active_quality(q, p_rc->gfu_boost, gf_low, gf_high,
arfgf_low_motion_minq, arfgf_high_motion_minq);
}
@@ -785,8 +803,9 @@
// (at buffer = critical level).
const AV1_COMMON *const cm = &cpi->common;
const RATE_CONTROL *rc = &cpi->rc;
+ const PRIMARY_RATE_CONTROL *p_rc = &cpi->ppi->p_rc;
// Buffer level below which we push active_worst to worst_quality.
- int64_t critical_level = rc->optimal_buffer_level >> 3;
+ int64_t critical_level = p_rc->optimal_buffer_level >> 3;
int64_t buff_lvl_step = 0;
int adjustment = 0;
int active_worst_quality;
@@ -802,25 +821,26 @@
rc->avg_frame_qindex[KEY_FRAME])
: rc->avg_frame_qindex[INTER_FRAME];
active_worst_quality = AOMMIN(rc->worst_quality, ambient_qp * 5 / 4);
- if (rc->buffer_level > rc->optimal_buffer_level) {
+ if (rc->buffer_level > p_rc->optimal_buffer_level) {
// Adjust down.
// Maximum limit for down adjustment, ~30%.
int max_adjustment_down = active_worst_quality / 3;
if (max_adjustment_down) {
- buff_lvl_step = ((rc->maximum_buffer_size - rc->optimal_buffer_level) /
- max_adjustment_down);
+ buff_lvl_step =
+ ((p_rc->maximum_buffer_size - p_rc->optimal_buffer_level) /
+ max_adjustment_down);
if (buff_lvl_step)
- adjustment = (int)((rc->buffer_level - rc->optimal_buffer_level) /
+ adjustment = (int)((rc->buffer_level - p_rc->optimal_buffer_level) /
buff_lvl_step);
active_worst_quality -= adjustment;
}
} else if (rc->buffer_level > critical_level) {
// Adjust up from ambient Q.
if (critical_level) {
- buff_lvl_step = (rc->optimal_buffer_level - critical_level);
+ buff_lvl_step = (p_rc->optimal_buffer_level - critical_level);
if (buff_lvl_step) {
adjustment = (int)((rc->worst_quality - ambient_qp) *
- (rc->optimal_buffer_level - rc->buffer_level) /
+ (p_rc->optimal_buffer_level - rc->buffer_level) /
buff_lvl_step);
}
active_worst_quality = ambient_qp + adjustment;
@@ -838,6 +858,7 @@
int width, int height) {
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 RefreshFrameFlagsInfo *const refresh_frame_flags = &cpi->refresh_frame;
const CurrentFrame *const current_frame = &cm->current_frame;
int *rtc_minq;
@@ -849,7 +870,7 @@
// Handle the special case for key frames forced when we have reached
// the maximum key frame interval. Here force the Q to a range
// based on the ambient Q to reduce the risk of popping.
- if (rc->this_key_frame_forced) {
+ if (p_rc->this_key_frame_forced) {
int qindex = 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,
@@ -859,8 +880,8 @@
// not first frame of one pass and kf_boost is set
double q_adj_factor = 1.0;
double q_val;
- active_best_quality =
- get_kf_active_quality(rc, rc->avg_frame_qindex[KEY_FRAME], bit_depth);
+ active_best_quality = get_kf_active_quality(
+ p_rc, rc->avg_frame_qindex[KEY_FRAME], bit_depth);
// Allow somewhat lower kf minq with small image formats.
if ((width * height) <= (352 * 288)) {
q_adj_factor -= 0.25;
@@ -883,7 +904,7 @@
rc->avg_frame_qindex[INTER_FRAME] < active_worst_quality) {
q = rc->avg_frame_qindex[INTER_FRAME];
}
- active_best_quality = get_gf_active_quality(rc, q, bit_depth);
+ active_best_quality = get_gf_active_quality(p_rc, q, bit_depth);
} else {
// Use the lower of active_worst_quality and recent/average Q.
FRAME_TYPE frame_type =
@@ -916,6 +937,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 CurrentFrame *const current_frame = &cm->current_frame;
int q;
const int bit_depth = cm->seq_params.bit_depth;
@@ -935,7 +957,7 @@
*bottom_index = active_best_quality;
// Limit Q range for the adaptive loop.
- if (current_frame->frame_type == KEY_FRAME && !rc->this_key_frame_forced &&
+ if (current_frame->frame_type == KEY_FRAME && !p_rc->this_key_frame_forced &&
current_frame->frame_number != 0) {
int qdelta = 0;
aom_clear_system_state();
@@ -947,7 +969,7 @@
}
// Special case code to try and match quality with forced key frames
- if (current_frame->frame_type == KEY_FRAME && rc->this_key_frame_forced) {
+ if (current_frame->frame_type == KEY_FRAME && p_rc->this_key_frame_forced) {
q = rc->last_boosted_qindex;
} else {
q = av1_rc_regulate_q(cpi, rc->this_frame_target, active_best_quality,
@@ -1084,6 +1106,7 @@
int *bottom_index, 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 CurrentFrame *const current_frame = &cm->current_frame;
const AV1EncoderConfig *const oxcf = &cpi->oxcf;
const RefreshFrameFlagsInfo *const refresh_frame_flags = &cpi->refresh_frame;
@@ -1120,7 +1143,7 @@
const int delta_qindex =
av1_compute_qdelta(rc, q_val, q_val * 0.25, bit_depth);
active_best_quality = AOMMAX(qindex + delta_qindex, rc->best_quality);
- } else if (rc->this_key_frame_forced) {
+ } else if (p_rc->this_key_frame_forced) {
const int qindex = rc->last_boosted_qindex;
const double last_boosted_q = av1_convert_qindex_to_q(qindex, bit_depth);
const int delta_qindex = av1_compute_qdelta(
@@ -1129,8 +1152,8 @@
} else { // not first frame of one pass and kf_boost is set
double q_adj_factor = 1.0;
- active_best_quality =
- get_kf_active_quality(rc, rc->avg_frame_qindex[KEY_FRAME], bit_depth);
+ active_best_quality = get_kf_active_quality(
+ p_rc, rc->avg_frame_qindex[KEY_FRAME], bit_depth);
// Allow somewhat lower kf minq with small image formats.
if ((width * height) <= (352 * 288)) {
@@ -1158,7 +1181,7 @@
// For constrained quality dont 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(rc, q, bit_depth);
+ active_best_quality = get_gf_active_quality(p_rc, q, bit_depth);
// Constrained quality use slightly lower active best.
active_best_quality = active_best_quality * 15 / 16;
} else if (rc_mode == AOM_Q) {
@@ -1170,7 +1193,7 @@
: 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(rc, q, bit_depth);
+ active_best_quality = get_gf_active_quality(p_rc, q, bit_depth);
}
} else {
if (rc_mode == AOM_Q) {
@@ -1209,8 +1232,8 @@
{
int qdelta = 0;
aom_clear_system_state();
- if (current_frame->frame_type == KEY_FRAME && !rc->this_key_frame_forced &&
- current_frame->frame_number != 0) {
+ if (current_frame->frame_type == KEY_FRAME &&
+ !p_rc->this_key_frame_forced && current_frame->frame_number != 0) {
qdelta = av1_compute_qdelta_by_rate(
&cpi->rc, current_frame->frame_type, active_worst_quality, 2.0,
cpi->is_screen_content_type, bit_depth);
@@ -1229,7 +1252,7 @@
q = active_best_quality;
// Special case code to try and match quality with forced key frames
} else if ((current_frame->frame_type == KEY_FRAME) &&
- rc->this_key_frame_forced) {
+ p_rc->this_key_frame_forced) {
q = rc->last_boosted_qindex;
} else {
q = av1_rc_regulate_q(cpi, rc->this_frame_target, active_best_quality,
@@ -1274,11 +1297,11 @@
int height, int *bottom_index,
int *top_index) {
const AV1_COMMON *const cm = &cpi->common;
- const RATE_CONTROL *const rc = &cpi->rc;
+ const RATE_CONTROL *const p_rc = &cpi->p_rc;
const AV1EncoderConfig *const oxcf = &cpi->oxcf;
const int cq_level =
- get_active_cq_level(rc, oxcf, frame_is_intra_only(cm), cpi->superres_mode,
- cm->superres_scale_denominator);
+ get_active_cq_level(p_rc, oxcf, frame_is_intra_only(cm),
+ cpi->superres_mode, cm->superres_scale_denominator);
const int bit_depth = cm->seq_params.bit_depth;
const int q = (int)av1_convert_qindex_to_q(cq_level, bit_depth);
(void)width;
@@ -1299,6 +1322,7 @@
int cq_level, int is_fwd_kf) {
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;
int active_best_quality;
int active_worst_quality = *active_worst;
@@ -1319,7 +1343,7 @@
const int delta_qindex = av1_compute_qdelta(
rc, last_boosted_q, last_boosted_q * 0.25, bit_depth);
active_best_quality = AOMMAX(qindex + delta_qindex, rc->best_quality);
- } else if (rc->this_key_frame_forced) {
+ } else if (p_rc->this_key_frame_forced) {
// Handle the special case for key frames forced when we have reached
// the maximum key frame interval. Here force the Q to a range
// based on the ambient Q to reduce the risk of popping.
@@ -1329,7 +1353,7 @@
if (is_stat_consumption_stage_twopass(cpi) &&
cpi->ppi->twopass.last_kfgroup_zeromotion_pct >= STATIC_MOTION_THRESH) {
- qindex = AOMMIN(rc->last_kf_qindex, rc->last_boosted_qindex);
+ qindex = AOMMIN(p_rc->last_kf_qindex, rc->last_boosted_qindex);
active_best_quality = qindex;
last_boosted_q = av1_convert_qindex_to_q(qindex, bit_depth);
delta_qindex = av1_compute_qdelta(rc, last_boosted_q,
@@ -1350,7 +1374,7 @@
// Baseline value derived from cpi->active_worst_quality and kf boost.
active_best_quality =
- get_kf_active_quality(rc, active_worst_quality, bit_depth);
+ get_kf_active_quality(p_rc, active_worst_quality, bit_depth);
if (cpi->is_screen_content_type) {
active_best_quality /= 2;
}
@@ -1399,6 +1423,7 @@
int *active_best) {
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 RefreshFrameFlagsInfo *const refresh_frame_flags = &cpi->refresh_frame;
const int bit_depth = cpi->common.seq_params.bit_depth;
int active_best_quality = *active_best;
@@ -1424,7 +1449,7 @@
aom_clear_system_state();
#ifndef STRICT_RC
// Static forced key frames Q restrictions dealt with elsewhere.
- if (!(frame_is_intra_only(cm)) || !rc->this_key_frame_forced ||
+ if (!(frame_is_intra_only(cm)) || !p_rc->this_key_frame_forced ||
(cpi->ppi->twopass.last_kfgroup_zeromotion_pct < STATIC_MOTION_THRESH)) {
const int qdelta = av1_frame_type_qdelta(cpi, active_worst_quality);
active_worst_quality =
@@ -1470,18 +1495,19 @@
const int active_best_quality) {
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;
int q;
if (cpi->oxcf.rc_cfg.mode == AOM_Q ||
- (frame_is_intra_only(cm) && !rc->this_key_frame_forced &&
+ (frame_is_intra_only(cm) && !p_rc->this_key_frame_forced &&
cpi->ppi->twopass.kf_zeromotion_pct >= STATIC_KF_GROUP_THRESH &&
rc->frames_to_key > 1)) {
q = active_best_quality;
// Special case code to try and match quality with forced key frames.
- } else if (frame_is_intra_only(cm) && rc->this_key_frame_forced) {
+ } else if (frame_is_intra_only(cm) && p_rc->this_key_frame_forced) {
// If static since last kf use better of last boosted and last kf q.
if (cpi->ppi->twopass.last_kfgroup_zeromotion_pct >= STATIC_MOTION_THRESH) {
- q = AOMMIN(rc->last_kf_qindex, rc->last_boosted_qindex);
+ q = AOMMIN(p_rc->last_kf_qindex, rc->last_boosted_qindex);
} else {
q = AOMMIN(rc->last_boosted_qindex,
(active_best_quality + active_worst_quality) / 2);
@@ -1512,6 +1538,7 @@
const AV1_COMMON *const cm = &cpi->common;
const int bit_depth = cm->seq_params.bit_depth;
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;
@@ -1554,15 +1581,15 @@
q = rc->avg_frame_qindex[INTER_FRAME];
}
if (rc_mode == AOM_CQ && q < cq_level) q = cq_level;
- active_best_quality = get_gf_active_quality(rc, q, bit_depth);
+ active_best_quality = get_gf_active_quality(p_rc, q, bit_depth);
// 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 boost = min_boost - active_best_quality;
- active_best_quality = min_boost - (int)(boost * rc->arf_boost_factor);
+ active_best_quality = min_boost - (int)(boost * p_rc->arf_boost_factor);
if (!is_intrl_arf_boost) return active_best_quality;
- if (rc_mode == AOM_Q || rc_mode == AOM_CQ) active_best_quality = rc->arf_q;
+ if (rc_mode == AOM_Q || rc_mode == AOM_CQ) active_best_quality = p_rc->arf_q;
int this_height = gf_group_pyramid_level(gf_group, gf_index);
while (this_height > 1) {
active_best_quality = (active_best_quality + active_worst_quality + 1) / 2;
@@ -1674,9 +1701,9 @@
return q;
}
-int av1_rc_pick_q_and_bounds(const AV1_COMP *cpi, RATE_CONTROL *rc, int width,
- int height, int gf_index, int *bottom_index,
- int *top_index) {
+int av1_rc_pick_q_and_bounds(const AV1_COMP *cpi, int width, int height,
+ int gf_index, int *bottom_index, int *top_index) {
+ PRIMARY_RATE_CONTROL *const p_rc = &cpi->ppi->p_rc;
int q;
// TODO(sarahparker) merge no-stats vbr and altref q computation
// with rc_pick_q_and_bounds().
@@ -1700,7 +1727,7 @@
q = rc_pick_q_and_bounds(cpi, width, height, gf_index, bottom_index,
top_index);
}
- if (gf_group->update_type[gf_index] == ARF_UPDATE) rc->arf_q = q;
+ if (gf_group->update_type[gf_index] == ARF_UPDATE) p_rc->arf_q = q;
return q;
}
@@ -1762,6 +1789,7 @@
const AV1_COMMON *const cm = &cpi->common;
const CurrentFrame *const current_frame = &cm->current_frame;
RATE_CONTROL *const rc = &cpi->rc;
+ PRIMARY_RATE_CONTROL *const p_rc = &cpi->ppi->p_rc;
const GF_GROUP *const gf_group = &cpi->ppi->gf_group;
const RefreshFrameFlagsInfo *const refresh_frame_flags = &cpi->refresh_frame;
@@ -1806,12 +1834,12 @@
// This is used to help set quality in forced key frames to reduce popping
if ((qindex < rc->last_boosted_qindex) ||
(current_frame->frame_type == KEY_FRAME) ||
- (!rc->constrained_gf_group &&
+ (!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;
}
- if (current_frame->frame_type == KEY_FRAME) rc->last_kf_qindex = qindex;
+ if (current_frame->frame_type == KEY_FRAME) p_rc->last_kf_qindex = qindex;
update_buffer_level(cpi, rc->projected_frame_size);
rc->prev_avg_frame_bandwidth = rc->avg_frame_bandwidth;
@@ -2054,20 +2082,21 @@
const AV1_COMP *const cpi, FRAME_UPDATE_TYPE frame_update_type) {
static const int af_ratio = 10;
const RATE_CONTROL *const rc = &cpi->rc;
+ const PRIMARY_RATE_CONTROL *const p_rc = &cpi->ppi->p_rc;
int64_t target;
#if USE_ALTREF_FOR_ONE_PASS
if (frame_update_type == KF_UPDATE || frame_update_type == GF_UPDATE ||
frame_update_type == ARF_UPDATE) {
- target = ((int64_t)rc->avg_frame_bandwidth * rc->baseline_gf_interval *
+ target = ((int64_t)rc->avg_frame_bandwidth * p_rc->baseline_gf_interval *
af_ratio) /
- (rc->baseline_gf_interval + af_ratio - 1);
+ (p_rc->baseline_gf_interval + af_ratio - 1);
} else {
- target = ((int64_t)rc->avg_frame_bandwidth * rc->baseline_gf_interval) /
- (rc->baseline_gf_interval + af_ratio - 1);
+ target = ((int64_t)rc->avg_frame_bandwidth * p_rc->baseline_gf_interval) /
+ (p_rc->baseline_gf_interval + af_ratio - 1);
}
if (target > INT_MAX) target = INT_MAX;
#else
- target = rc->avg_frame_bandwidth;
+ target = p_rc->avg_frame_bandwidth;
#endif
return av1_rc_clamp_pframe_target_size(cpi, (int)target, frame_update_type);
}
@@ -2083,9 +2112,10 @@
const AV1_COMP *cpi, FRAME_UPDATE_TYPE frame_update_type) {
const AV1EncoderConfig *oxcf = &cpi->oxcf;
const RATE_CONTROL *rc = &cpi->rc;
+ const PRIMARY_RATE_CONTROL *p_rc = &cpi->ppi->p_rc;
const RateControlCfg *rc_cfg = &oxcf->rc_cfg;
- const int64_t diff = rc->optimal_buffer_level - rc->buffer_level;
- const int64_t one_pct_bits = 1 + rc->optimal_buffer_level / 100;
+ const int64_t diff = p_rc->optimal_buffer_level - rc->buffer_level;
+ const int64_t one_pct_bits = 1 + p_rc->optimal_buffer_level / 100;
int min_frame_target =
AOMMAX(rc->avg_frame_bandwidth >> 4, FRAME_OVERHEAD_BITS);
int target;
@@ -2093,12 +2123,12 @@
if (rc_cfg->gf_cbr_boost_pct) {
const int af_ratio_pct = rc_cfg->gf_cbr_boost_pct + 100;
if (frame_update_type == GF_UPDATE || frame_update_type == OVERLAY_UPDATE) {
- target =
- (rc->avg_frame_bandwidth * rc->baseline_gf_interval * af_ratio_pct) /
- (rc->baseline_gf_interval * 100 + af_ratio_pct - 100);
+ target = (rc->avg_frame_bandwidth * p_rc->baseline_gf_interval *
+ af_ratio_pct) /
+ (p_rc->baseline_gf_interval * 100 + af_ratio_pct - 100);
} else {
- target = (rc->avg_frame_bandwidth * rc->baseline_gf_interval * 100) /
- (rc->baseline_gf_interval * 100 + af_ratio_pct - 100);
+ target = (rc->avg_frame_bandwidth * p_rc->baseline_gf_interval * 100) /
+ (p_rc->baseline_gf_interval * 100 + af_ratio_pct - 100);
}
} else {
target = rc->avg_frame_bandwidth;
@@ -2135,11 +2165,12 @@
int av1_calc_iframe_target_size_one_pass_cbr(const AV1_COMP *cpi) {
const RATE_CONTROL *rc = &cpi->rc;
+ const PRIMARY_RATE_CONTROL *p_rc = &cpi->ppi->p_rc;
int target;
if (cpi->common.current_frame.frame_number == 0) {
- target = ((rc->starting_buffer_level / 2) > INT_MAX)
+ target = ((p_rc->starting_buffer_level / 2) > INT_MAX)
? INT_MAX
- : (int)(rc->starting_buffer_level / 2);
+ : (int)(p_rc->starting_buffer_level / 2);
} else {
int kf_boost = 32;
double framerate = cpi->framerate;
@@ -2350,6 +2381,7 @@
static int set_gf_interval_update_onepass_rt(AV1_COMP *cpi,
FRAME_TYPE frame_type) {
RATE_CONTROL *const rc = &cpi->rc;
+ PRIMARY_RATE_CONTROL *const p_rc = &cpi->ppi->p_rc;
GF_GROUP *const gf_group = &cpi->ppi->gf_group;
ResizePendingParams *const resize_pending_params =
&cpi->resize_pending_params;
@@ -2366,34 +2398,34 @@
if (cpi->oxcf.q_cfg.aq_mode == CYCLIC_REFRESH_AQ)
av1_cyclic_refresh_set_golden_update(cpi);
else
- rc->baseline_gf_interval = MAX_GF_INTERVAL;
- if (rc->baseline_gf_interval > rc->frames_to_key)
- rc->baseline_gf_interval = rc->frames_to_key;
- rc->gfu_boost = DEFAULT_GF_BOOST_RT;
- rc->constrained_gf_group =
- (rc->baseline_gf_interval >= rc->frames_to_key) ? 1 : 0;
- rc->frames_till_gf_update_due = rc->baseline_gf_interval;
+ p_rc->baseline_gf_interval = MAX_GF_INTERVAL;
+ if (p_rc->baseline_gf_interval > rc->frames_to_key)
+ p_rc->baseline_gf_interval = rc->frames_to_key;
+ p_rc->gfu_boost = DEFAULT_GF_BOOST_RT;
+ p_rc->constrained_gf_group =
+ (p_rc->baseline_gf_interval >= rc->frames_to_key) ? 1 : 0;
+ rc->frames_till_gf_update_due = p_rc->baseline_gf_interval;
cpi->gf_frame_index = 0;
// SVC does not use GF as periodic boost.
// TODO(marpan): Find better way to disable this for SVC.
if (cpi->use_svc) {
SVC *const svc = &cpi->svc;
- rc->baseline_gf_interval = MAX_STATIC_GF_GROUP_LENGTH - 1;
- rc->gfu_boost = 1;
- rc->constrained_gf_group = 0;
- rc->frames_till_gf_update_due = rc->baseline_gf_interval;
+ p_rc->baseline_gf_interval = MAX_STATIC_GF_GROUP_LENGTH - 1;
+ p_rc->gfu_boost = 1;
+ p_rc->constrained_gf_group = 0;
+ rc->frames_till_gf_update_due = p_rc->baseline_gf_interval;
for (int layer = 0;
layer < svc->number_spatial_layers * svc->number_temporal_layers;
++layer) {
LAYER_CONTEXT *const lc = &svc->layer_context[layer];
- lc->rc.baseline_gf_interval = rc->baseline_gf_interval;
- lc->rc.gfu_boost = rc->gfu_boost;
- lc->rc.constrained_gf_group = rc->constrained_gf_group;
+ lc->p_rc.baseline_gf_interval = p_rc->baseline_gf_interval;
+ lc->p_rc.gfu_boost = p_rc->gfu_boost;
+ lc->p_rc.constrained_gf_group = p_rc->constrained_gf_group;
lc->rc.frames_till_gf_update_due = rc->frames_till_gf_update_due;
lc->group_index = 0;
}
}
- gf_group->size = rc->baseline_gf_interval;
+ gf_group->size = p_rc->baseline_gf_interval;
gf_group->update_type[0] =
(frame_type == KEY_FRAME) ? KF_UPDATE : GF_UPDATE;
gf_update = 1;
@@ -2404,6 +2436,7 @@
static void resize_reset_rc(AV1_COMP *cpi, int resize_width, int resize_height,
int prev_width, int prev_height) {
RATE_CONTROL *const rc = &cpi->rc;
+ PRIMARY_RATE_CONTROL *const p_rc = &cpi->ppi->p_rc;
SVC *const svc = &cpi->svc;
double tot_scale_change = 1.0;
int target_bits_per_frame;
@@ -2412,8 +2445,8 @@
tot_scale_change = (double)(resize_width * resize_height) /
(double)(prev_width * prev_height);
// Reset buffer level to optimal, update target size.
- rc->buffer_level = rc->optimal_buffer_level;
- rc->bits_off_target = rc->optimal_buffer_level;
+ rc->buffer_level = p_rc->optimal_buffer_level;
+ rc->bits_off_target = p_rc->optimal_buffer_level;
rc->this_frame_target =
av1_calc_pframe_target_size_one_pass_cbr(cpi, INTER_FRAME);
target_bits_per_frame = rc->this_frame_target;
@@ -2437,8 +2470,8 @@
svc->number_temporal_layers +
tl];
lc->rc.resize_state = rc->resize_state;
- lc->rc.buffer_level = lc->rc.optimal_buffer_level;
- lc->rc.bits_off_target = lc->rc.optimal_buffer_level;
+ lc->rc.buffer_level = lc->p_rc.optimal_buffer_level;
+ lc->rc.bits_off_target = lc->p_rc.optimal_buffer_level;
lc->rc.rate_correction_factors[INTER_FRAME] =
rc->rate_correction_factors[INTER_FRAME];
}
@@ -2470,6 +2503,7 @@
static void dynamic_resize_one_pass_cbr(AV1_COMP *cpi) {
const AV1_COMMON *const cm = &cpi->common;
RATE_CONTROL *const rc = &cpi->rc;
+ PRIMARY_RATE_CONTROL *const p_rc = &cpi->ppi->p_rc;
RESIZE_ACTION resize_action = NO_RESIZE;
const int avg_qp_thr1 = 70;
const int avg_qp_thr2 = 50;
@@ -2492,7 +2526,7 @@
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];
- if (cpi->rc.buffer_level < (int)(30 * rc->optimal_buffer_level / 100))
+ if (cpi->rc.buffer_level < (int)(30 * p_rc->optimal_buffer_level / 100))
++rc->resize_buffer_underflow;
++rc->resize_count;
// Check for resize action every "window" frames.
@@ -2554,6 +2588,7 @@
EncodeFrameParams *const frame_params,
unsigned int frame_flags) {
RATE_CONTROL *const rc = &cpi->rc;
+ PRIMARY_RATE_CONTROL *const p_rc = &cpi->ppi->p_rc;
AV1_COMMON *const cm = &cpi->common;
GF_GROUP *const gf_group = &cpi->ppi->gf_group;
SVC *const svc = &cpi->svc;
@@ -2576,10 +2611,10 @@
svc->current_superframe % cpi->oxcf.kf_cfg.key_freq_max == 0)) ||
(frame_flags & FRAMEFLAGS_KEY)) {
frame_params->frame_type = KEY_FRAME;
- rc->this_key_frame_forced =
+ p_rc->this_key_frame_forced =
cm->current_frame.frame_number != 0 && rc->frames_to_key == 0;
rc->frames_to_key = cpi->oxcf.kf_cfg.key_freq_max;
- rc->kf_boost = DEFAULT_KF_BOOST_RT;
+ p_rc->kf_boost = DEFAULT_KF_BOOST_RT;
gf_group->update_type[cpi->gf_frame_index] = KF_UPDATE;
gf_group->frame_type[cpi->gf_frame_index] = KEY_FRAME;
gf_group->refbuf_state[cpi->gf_frame_index] = REFBUF_RESET;
@@ -2664,6 +2699,7 @@
int av1_encodedframe_overshoot_cbr(AV1_COMP *cpi, int *q) {
AV1_COMMON *const cm = &cpi->common;
RATE_CONTROL *const rc = &cpi->rc;
+ PRIMARY_RATE_CONTROL *const p_rc = &cpi->ppi->p_rc;
SPEED_FEATURES *const sf = &cpi->sf;
int thresh_qp = 7 * (rc->worst_quality >> 3);
// Lower thresh_qp for video (more overshoot at lower Q) to be
@@ -2685,8 +2721,8 @@
// have settled down to a very different (low QP) state, then not adjusting
// them may cause next frame to select low QP and overshoot again.
cpi->rc.avg_frame_qindex[INTER_FRAME] = *q;
- rc->buffer_level = rc->optimal_buffer_level;
- rc->bits_off_target = rc->optimal_buffer_level;
+ rc->buffer_level = p_rc->optimal_buffer_level;
+ rc->bits_off_target = p_rc->optimal_buffer_level;
// Reset rate under/over-shoot flags.
cpi->rc.rc_1_frame = 0;
cpi->rc.rc_2_frame = 0;
diff --git a/av1/encoder/ratectrl.h b/av1/encoder/ratectrl.h
index 544a71c..a1567f0 100644
--- a/av1/encoder/ratectrl.h
+++ b/av1/encoder/ratectrl.h
@@ -129,11 +129,6 @@
int this_frame_target; // Actual frame target after rc adjustment.
/*!
- * Target bit budget for the current GF / ARF group of frame.
- */
- int64_t gf_group_bits;
-
- /*!
* Projected size for current frame
*/
int projected_frame_size;
@@ -159,20 +154,6 @@
int last_boosted_qindex;
/*!
- * Q used for last boosted (non leaf) frame
- */
- int last_kf_qindex;
-
- /*!
- * Boost factor used to calculate the extra bits allocated to ARFs and GFs
- */
- int gfu_boost;
- /*!
- * Boost factor used to calculate the extra bits allocated to the key frame
- */
- int kf_boost;
-
- /*!
* Correction factors used to adjust the q estimate for a given target rate
* in the encode loop.
*/
@@ -193,27 +174,10 @@
*/
int intervals_till_gf_calculate_due;
- /*!
- * Stores the determined gf group lengths for a set of gf groups
- */
- int gf_intervals[MAX_NUM_GF_INTERVALS];
-
- /*!
- * The current group's index into gf_intervals[]
- */
- int cur_gf_index;
-
/*!\cond */
- int num_regions;
- REGIONS regions[MAX_FIRSTPASS_ANALYSIS_FRAMES];
- int regions_offset; // offset of regions from the last keyframe
- int frames_till_regions_update;
-
int min_gf_interval;
int max_gf_interval;
int static_scene_max_gf_interval;
- int baseline_gf_interval;
- int constrained_gf_group;
/*!\endcond */
/*!
* Frames before the next key frame
@@ -221,8 +185,6 @@
int frames_to_key;
/*!\cond */
int frames_since_key;
- int this_key_frame_forced;
- int next_key_frame_forced;
int is_src_frame_alt_ref;
int sframe_due;
@@ -268,18 +230,6 @@
*/
int best_quality;
- /*!
- * Initial buffuer level in ms for CBR / low delay encoding
- */
- int64_t starting_buffer_level;
- /*!
- * Optimum / target buffuer level in ms for CBR / low delay encoding
- */
- int64_t optimal_buffer_level;
- /*!
- * Maximum target buffuer level in ms for CBR / low delay encoding
- */
- int64_t maximum_buffer_size;
/*!\cond */
// rate control history for last frame(1) and the frame before(2).
@@ -291,14 +241,8 @@
int q_1_frame;
int q_2_frame;
- float_t arf_boost_factor;
-
/*!\endcond */
/*!
- * Q index used for ALT frame
- */
- int arf_q;
- /*!
* Proposed maximum alloed Q for current frame
*/
int active_worst_quality;
@@ -308,17 +252,6 @@
int active_best_quality[MAX_ARF_LAYERS + 1];
/*!\cond */
- int base_layer_qp;
-
- // 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;
- int next_is_fwd_key;
- int enable_scenecut_detection;
- int use_arf_in_this_kf_group;
// Track amount of low motion in scene
int avg_frame_low_motion;
@@ -330,13 +263,108 @@
/*!\endcond */
} RATE_CONTROL;
-/*!\cond */
+/*!
+ * \brief Primary Rate Control parameters and status
+ */
+typedef struct {
+ // Sub-gop level Rate targetting variables
+
+ /*!
+ * Target bit budget for the current GF / ARF group of frame.
+ */
+ int64_t gf_group_bits;
+
+ /*!
+ * Boost factor used to calculate the extra bits allocated to the key frame
+ */
+ int kf_boost;
+
+ /*!
+ * Boost factor used to calculate the extra bits allocated to ARFs and GFs
+ */
+ int gfu_boost;
+
+ /*!
+ * Stores the determined gf group lengths for a set of gf groups
+ */
+ int gf_intervals[MAX_NUM_GF_INTERVALS];
+
+ /*!
+ * The current group's index into gf_intervals[]
+ */
+ int cur_gf_index;
+
+ /*!\cond */
+ int num_regions;
+
+ REGIONS regions[MAX_FIRSTPASS_ANALYSIS_FRAMES];
+ int regions_offset; // offset of regions from the last keyframe
+ int frames_till_regions_update;
+
+ int baseline_gf_interval;
+
+ int constrained_gf_group;
+
+ int this_key_frame_forced;
+
+ int next_key_frame_forced;
+ /*!\endcond */
+
+ /*!
+ * Initial buffuer level in ms for CBR / low delay encoding
+ */
+ int64_t starting_buffer_level;
+
+ /*!
+ * Optimum / target buffuer level in ms for CBR / low delay encoding
+ */
+ int64_t optimal_buffer_level;
+
+ /*!
+ * Maximum target buffuer level in ms for CBR / low delay encoding
+ */
+ int64_t maximum_buffer_size;
+
+ /*!
+ * Q index used for ALT frame
+ */
+ int arf_q;
+
+ /*!\cond */
+ float_t arf_boost_factor;
+
+ int base_layer_qp;
+
+ // 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;
+
+ int next_is_fwd_key;
+
+ int enable_scenecut_detection;
+
+ int use_arf_in_this_kf_group;
+ /*!\endcond */
+
+ /*!
+ * Q used for last boosted (non leaf) frame
+ */
+ int last_kf_qindex;
+} PRIMARY_RATE_CONTROL;
struct AV1_COMP;
struct AV1EncoderConfig;
+void av1_primary_rc_init(const struct AV1EncoderConfig *oxcf,
+ PRIMARY_RATE_CONTROL *p_rc);
+
void av1_rc_init(const struct AV1EncoderConfig *oxcf, int pass,
- RATE_CONTROL *rc);
+ RATE_CONTROL *rc, const PRIMARY_RATE_CONTROL *const p_rc);
int av1_estimate_bits_at_q(FRAME_TYPE frame_kind, int q, int mbs,
double correction_factor, aom_bit_depth_t bit_depth,
@@ -414,7 +442,6 @@
*
* \ingroup rate_control
* \param[in] cpi Top level encoder structure
- * \param[in,out] rc Top level rate control structure
* \param[in] width Coded frame width
* \param[in] height Coded frame height
* \param[in] gf_index Index of this frame in the golden frame group
@@ -423,9 +450,8 @@
* \return Returns selected q index to be used for encoding this frame.
* Also, updates \c rc->arf_q.
*/
-int av1_rc_pick_q_and_bounds(const struct AV1_COMP *cpi, RATE_CONTROL *rc,
- int width, int height, int gf_index,
- int *bottom_index, int *top_index);
+int av1_rc_pick_q_and_bounds(const struct AV1_COMP *cpi, int width, int height,
+ int gf_index, int *bottom_index, int *top_index);
/*!\brief Estimates q to achieve a target bits per frame
*
diff --git a/av1/encoder/rc_utils.h b/av1/encoder/rc_utils.h
index 284f55e..6e6adfc 100644
--- a/av1/encoder/rc_utils.h
+++ b/av1/encoder/rc_utils.h
@@ -19,17 +19,17 @@
extern "C" {
#endif
-static AOM_INLINE void set_rc_buffer_sizes(RATE_CONTROL *rc,
+static AOM_INLINE void set_rc_buffer_sizes(PRIMARY_RATE_CONTROL *p_rc,
const RateControlCfg *rc_cfg) {
const int64_t bandwidth = rc_cfg->target_bandwidth;
const int64_t starting = rc_cfg->starting_buffer_level_ms;
const int64_t optimal = rc_cfg->optimal_buffer_level_ms;
const int64_t maximum = rc_cfg->maximum_buffer_size_ms;
- rc->starting_buffer_level = starting * bandwidth / 1000;
- rc->optimal_buffer_level =
+ p_rc->starting_buffer_level = starting * bandwidth / 1000;
+ p_rc->optimal_buffer_level =
(optimal == 0) ? bandwidth / 8 : optimal * bandwidth / 1000;
- rc->maximum_buffer_size =
+ p_rc->maximum_buffer_size =
(maximum == 0) ? bandwidth / 8 : maximum * bandwidth / 1000;
}
@@ -226,6 +226,7 @@
int *const low_cr_seen, const int loop_count) {
AV1_COMMON *const cm = &cpi->common;
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;
*loop = 0;
@@ -263,7 +264,8 @@
&frame_over_shoot_limit);
if (frame_over_shoot_limit == 0) frame_over_shoot_limit = 1;
- if (cm->current_frame.frame_type == KEY_FRAME && rc->this_key_frame_forced &&
+ if (cm->current_frame.frame_type == KEY_FRAME &&
+ p_rc->this_key_frame_forced &&
rc->projected_frame_size < rc->max_frame_bandwidth) {
int64_t kf_err;
const int64_t high_err_target = cpi->ambient_err;
diff --git a/av1/encoder/rd.c b/av1/encoder/rd.c
index 608f8e6..03f85e3 100644
--- a/av1/encoder/rd.c
+++ b/av1/encoder/rd.c
@@ -375,7 +375,7 @@
if (is_stat_consumption_stage(cpi) &&
(cpi->common.current_frame.frame_type != KEY_FRAME)) {
const GF_GROUP *const gf_group = &cpi->ppi->gf_group;
- const int boost_index = AOMMIN(15, (cpi->rc.gfu_boost / 100));
+ const int boost_index = AOMMIN(15, (cpi->ppi->p_rc.gfu_boost / 100));
const int layer_depth =
AOMMIN(gf_group->layer_depth[cpi->gf_frame_index], 6);
diff --git a/av1/encoder/superres_scale.c b/av1/encoder/superres_scale.c
index 11161cd..f035b02 100644
--- a/av1/encoder/superres_scale.c
+++ b/av1/encoder/superres_scale.c
@@ -168,7 +168,7 @@
printf("]\n");
printf("boost = %d\n",
(gf_group->update_type[cpi->gf_frame_index] == KF_UPDATE)
- ? cpi->rc.kf_boost
+ ? cpi->ppi->p_rc.kf_boost
: cpi->rc.gfu_boost);
printf("denom = %d\n", denom);
*/
@@ -223,8 +223,8 @@
// Now decide the use of superres based on 'q'.
int bottom_index, top_index;
const int q = av1_rc_pick_q_and_bounds(
- cpi, &cpi->rc, frm_dim_cfg->width, frm_dim_cfg->height,
- cpi->gf_frame_index, &bottom_index, &top_index);
+ cpi, frm_dim_cfg->width, frm_dim_cfg->height, cpi->gf_frame_index,
+ &bottom_index, &top_index);
const int qthresh = (frame_is_intra_only(&cpi->common))
? superres_cfg->superres_kf_qthresh
@@ -244,8 +244,8 @@
// Now decide the use of superres based on 'q'.
int bottom_index, top_index;
const int q = av1_rc_pick_q_and_bounds(
- cpi, &cpi->rc, frm_dim_cfg->width, frm_dim_cfg->height,
- cpi->gf_frame_index, &bottom_index, &top_index);
+ cpi, frm_dim_cfg->width, frm_dim_cfg->height, cpi->gf_frame_index,
+ &bottom_index, &top_index);
const SUPERRES_AUTO_SEARCH_TYPE sr_search_type =
cpi->sf.hl_sf.superres_auto_search_type;
diff --git a/av1/encoder/svc_layercontext.c b/av1/encoder/svc_layercontext.c
index d538f39..0ad0cf6 100644
--- a/av1/encoder/svc_layercontext.c
+++ b/av1/encoder/svc_layercontext.c
@@ -91,6 +91,7 @@
void av1_update_layer_context_change_config(AV1_COMP *const cpi,
const int64_t target_bandwidth) {
const RATE_CONTROL *const rc = &cpi->rc;
+ const PRIMARY_RATE_CONTROL *const p_rc = &cpi->ppi->p_rc;
SVC *const svc = &cpi->svc;
int layer = 0;
int64_t spatial_layer_target = 0;
@@ -107,17 +108,18 @@
LAYER_CONTEXT *const lc =
&svc->layer_context[sl * svc->number_temporal_layers + tl];
RATE_CONTROL *const lrc = &lc->rc;
+ PRIMARY_RATE_CONTROL *const lp_rc = &lc->p_rc;
lc->spatial_layer_target_bandwidth = spatial_layer_target;
bitrate_alloc = (float)lc->target_bandwidth / target_bandwidth;
- lrc->starting_buffer_level =
- (int64_t)(rc->starting_buffer_level * bitrate_alloc);
- lrc->optimal_buffer_level =
- (int64_t)(rc->optimal_buffer_level * bitrate_alloc);
- lrc->maximum_buffer_size =
- (int64_t)(rc->maximum_buffer_size * bitrate_alloc);
+ lp_rc->starting_buffer_level =
+ (int64_t)(p_rc->starting_buffer_level * bitrate_alloc);
+ lp_rc->optimal_buffer_level =
+ (int64_t)(p_rc->optimal_buffer_level * bitrate_alloc);
+ lp_rc->maximum_buffer_size =
+ (int64_t)(p_rc->maximum_buffer_size * bitrate_alloc);
lrc->bits_off_target =
- AOMMIN(lrc->bits_off_target, lrc->maximum_buffer_size);
- lrc->buffer_level = AOMMIN(lrc->buffer_level, lrc->maximum_buffer_size);
+ AOMMIN(lrc->bits_off_target, lp_rc->maximum_buffer_size);
+ lrc->buffer_level = AOMMIN(lrc->buffer_level, lp_rc->maximum_buffer_size);
lc->framerate = cpi->framerate / lc->framerate_factor;
lrc->avg_frame_bandwidth = (int)(lc->target_bandwidth / lc->framerate);
lrc->max_frame_bandwidth = rc->max_frame_bandwidth;
@@ -172,6 +174,7 @@
const int old_frame_to_key = cpi->rc.frames_to_key;
// Restore layer rate control.
cpi->rc = lc->rc;
+ cpi->ppi->p_rc = lc->p_rc;
cpi->oxcf.rc_cfg.target_bandwidth = lc->target_bandwidth;
cpi->gf_frame_index = 0;
cpi->mv_search_params.max_mv_magnitude = lc->max_mv_magnitude;
@@ -215,6 +218,7 @@
const AV1_COMMON *const cm = &cpi->common;
LAYER_CONTEXT *lc = get_layer_context(cpi);
lc->rc = cpi->rc;
+ lc->p_rc = cpi->ppi->p_rc;
lc->target_bandwidth = (int)cpi->oxcf.rc_cfg.target_bandwidth;
lc->group_index = cpi->gf_frame_index;
lc->max_mv_magnitude = cpi->mv_search_params.max_mv_magnitude;
diff --git a/av1/encoder/svc_layercontext.h b/av1/encoder/svc_layercontext.h
index 44e13d6..5ceaf0f 100644
--- a/av1/encoder/svc_layercontext.h
+++ b/av1/encoder/svc_layercontext.h
@@ -26,6 +26,7 @@
typedef struct {
/*!\cond */
RATE_CONTROL rc;
+ PRIMARY_RATE_CONTROL p_rc;
int framerate_factor;
int64_t layer_target_bitrate;
int scaling_factor_num;
diff --git a/av1/encoder/temporal_filter.c b/av1/encoder/temporal_filter.c
index 29cc43a..4d53b75 100644
--- a/av1/encoder/temporal_filter.c
+++ b/av1/encoder/temporal_filter.c
@@ -1024,7 +1024,7 @@
num_before = AOMMIN(num_frames - 1, max_before);
num_after = 0;
} else {
- num_frames = AOMMIN(num_frames, cpi->rc.gfu_boost / 150);
+ num_frames = AOMMIN(num_frames, cpi->ppi->p_rc.gfu_boost / 150);
num_frames += !(num_frames & 1); // Make the number odd.
// Only use 2 neighbours for the second ARF.
if (is_second_arf) num_frames = AOMMIN(num_frames, 3);
@@ -1252,8 +1252,8 @@
int top_index = 0;
int bottom_index = 0;
const int q = av1_rc_pick_q_and_bounds(
- cpi, &cpi->rc, cpi->oxcf.frm_dim_cfg.width,
- cpi->oxcf.frm_dim_cfg.height, group_idx, &bottom_index, &top_index);
+ cpi, cpi->oxcf.frm_dim_cfg.width, cpi->oxcf.frm_dim_cfg.height,
+ group_idx, &bottom_index, &top_index);
const int ac_q = av1_ac_quant_QTX(q, 0, cpi->common.seq_params.bit_depth);
const float threshold = 0.7f * ac_q * ac_q;
diff --git a/av1/encoder/tpl_model.c b/av1/encoder/tpl_model.c
index 9d4f1d7..a7d8434 100644
--- a/av1/encoder/tpl_model.c
+++ b/av1/encoder/tpl_model.c
@@ -1276,7 +1276,7 @@
TplDepFrame *tpl_frame = &tpl_data->tpl_frame[gf_index];
FRAME_UPDATE_TYPE frame_update_type = gf_group->update_type[gf_index];
int frame_display_index = gf_index == gf_group->size
- ? cpi->rc.baseline_gf_interval
+ ? cpi->ppi->p_rc.baseline_gf_interval
: gf_group->cur_frame_idx[gf_index] +
gf_group->arf_src_offset[gf_index];
@@ -1348,8 +1348,9 @@
if (cpi->rc.frames_since_key == 0) return;
int extend_frame_count = 0;
- int extend_frame_length = AOMMIN(
- MAX_TPL_EXTEND, cpi->rc.frames_to_key - cpi->rc.baseline_gf_interval);
+ int extend_frame_length =
+ AOMMIN(MAX_TPL_EXTEND,
+ cpi->rc.frames_to_key - cpi->ppi->p_rc.baseline_gf_interval);
int frame_display_index = gf_group->cur_frame_idx[gop_length - 1] +
gf_group->arf_src_offset[gop_length - 1] + 1;
@@ -1496,9 +1497,8 @@
cm->show_frame = gf_group->update_type[gf_index] != ARF_UPDATE &&
gf_group->update_type[gf_index] != INTNL_ARF_UPDATE;
- gf_group->q_val[gf_index] =
- av1_rc_pick_q_and_bounds(cpi, &cpi->rc, cm->width, cm->height, gf_index,
- &bottom_index, &top_index);
+ gf_group->q_val[gf_index] = av1_rc_pick_q_and_bounds(
+ cpi, cm->width, cm->height, gf_index, &bottom_index, &top_index);
}
int pframe_qindex;
@@ -1506,7 +1506,7 @@
init_gop_frames_for_tpl(cpi, frame_params, gf_group, gop_eval,
&tpl_gf_group_frames, frame_input, &pframe_qindex);
- cpi->rc.base_layer_qp = pframe_qindex;
+ cpi->ppi->p_rc.base_layer_qp = pframe_qindex;
av1_init_tpl_stats(tpl_data);
diff --git a/doc/dev_guide/av1_encoder.dox b/doc/dev_guide/av1_encoder.dox
index 5d3435c..ea610f1 100644
--- a/doc/dev_guide/av1_encoder.dox
+++ b/doc/dev_guide/av1_encoder.dox
@@ -107,6 +107,7 @@
- \ref AV1_PRIMARY.gf_group (\ref GF_GROUP)
- \ref AV1_PRIMARY.lap_enabled
- \ref AV1_PRIMARY.twopass (\ref TWO_PASS)
+ - \ref AV1_PRIMARY.p_rc (\ref PRIMARY_RATE_CONTROL)
- \ref AV1_COMP
- \ref AV1_COMP.oxcf (\ref AV1EncoderConfig)
@@ -143,10 +144,12 @@
- \ref RateControlCfg.vbrmin_section
- \ref RateControlCfg.vbrmax_section
+- \ref PRIMARY_RATE_CONTROL (Primary Rate control status)
+ - \ref PRIMARY_RATE_CONTROL.gf_intervals[]
+ - \ref PRIMARY_RATE_CONTROL.cur_gf_index
+
- \ref RATE_CONTROL (Rate control status)
- \ref RATE_CONTROL.intervals_till_gf_calculate_due
- - \ref RATE_CONTROL.gf_intervals[]
- - \ref RATE_CONTROL.cur_gf_index
- \ref RATE_CONTROL.frames_till_gf_update_due
- \ref RATE_CONTROL.frames_to_key
@@ -833,9 +836,9 @@
As mentioned, for two-pass encoding, the function \ref
calculate_gf_length() tries to determine the length of as many as
MAX_NUM_GF_INTERVALS groups. The decisions are stored in
-\ref RATE_CONTROL.gf_intervals[]. The variables
+\ref PRIMARY_RATE_CONTROL.gf_intervals[]. The variables
\ref RATE_CONTROL.intervals_till_gf_calculate_due and
-\ref RATE_CONTROL.cur_gf_index help with managing and updating the stored
+\ref PRIMARY_RATE_CONTROL.gf_intervals[] help with managing and updating the stored
decisions. In the function \ref define_gf_group(), the corresponding
stored length decision will be used to define the current GF group.
@@ -859,7 +862,7 @@
\ref RATE_CONTROL.intervals_till_gf_calculate_due is zero. If it is, as
discussed above, \ref calculate_gf_length() is called with original
maximum length. If it is not zero, then the GF group length value stored
-in \ref RATE_CONTROL.gf_intervals[\ref RATE_CONTROL.cur_gf_index] is used
+in \ref PRIMARY_RATE_CONTROL.gf_intervals[\ref PRIMARY_RATE_CONTROL.cur_gf_index] is used
(subject to change as discussed above).
\subsection architecture_enc_gf_structure Defining a GF Group's Structure
@@ -872,7 +875,7 @@
accumulate various stats, using accumulate_this_frame_stats() and
accumulate_next_frame_stats(). The accumulated statistics are then used to
determine the use of the use of ALTREF frame along with other properties of the
-GF group. The values of \ref RATE_CONTROL.cur_gf_index, \ref
+GF group. The values of \ref PRIMARY_RATE_CONTROL.cur_gf_index, \ref
RATE_CONTROL.intervals_till_gf_calculate_due and \ref
RATE_CONTROL.frames_till_gf_update_due are also updated accordingly.