summaryrefslogtreecommitdiff
path: root/vp9/encoder/vp9_ratectrl.c
diff options
context:
space:
mode:
Diffstat (limited to 'vp9/encoder/vp9_ratectrl.c')
-rw-r--r--vp9/encoder/vp9_ratectrl.c177
1 files changed, 129 insertions, 48 deletions
diff --git a/vp9/encoder/vp9_ratectrl.c b/vp9/encoder/vp9_ratectrl.c
index 342081644..76ec84b5f 100644
--- a/vp9/encoder/vp9_ratectrl.c
+++ b/vp9/encoder/vp9_ratectrl.c
@@ -27,6 +27,11 @@
#include "vp9/encoder/vp9_encodemv.h"
#include "vp9/encoder/vp9_ratectrl.h"
+// Max rate target for 1080P and below encodes under normal circumstances
+// (1920 * 1080 / (16 * 16)) * MAX_MB_RATE bits per MB
+#define MAX_MB_RATE 250
+#define MAXRATE_1080P 2025000
+
#define DEFAULT_KF_BOOST 2000
#define DEFAULT_GF_BOOST 2000
@@ -74,14 +79,13 @@ void vp9_rc_init_minq_luts() {
for (i = 0; i < QINDEX_RANGE; i++) {
const double maxq = vp9_convert_qindex_to_q(i);
-
kf_low_motion_minq[i] = get_minq_index(maxq, 0.000001, -0.0004, 0.15);
kf_high_motion_minq[i] = get_minq_index(maxq, 0.000002, -0.0012, 0.50);
gf_low_motion_minq[i] = get_minq_index(maxq, 0.0000015, -0.0009, 0.32);
gf_high_motion_minq[i] = get_minq_index(maxq, 0.0000021, -0.00125, 0.50);
afq_low_motion_minq[i] = get_minq_index(maxq, 0.0000015, -0.0009, 0.33);
afq_high_motion_minq[i] = get_minq_index(maxq, 0.0000021, -0.00125, 0.55);
- inter_minq[i] = get_minq_index(maxq, 0.00000271, -0.00113, 0.75);
+ inter_minq[i] = get_minq_index(maxq, 0.00000271, -0.00113, 0.55);
}
}
@@ -367,8 +371,8 @@ int vp9_rc_regulate_q(const VP9_COMP *cpi, int target_bits_per_frame,
// Calculate required scaling factor based on target frame size and size of
// frame produced using previous Q.
- target_bits_per_mb =
- ((uint64_t)target_bits_per_frame << BPER_MB_NORMBITS) / cm->MBs;
+ target_bits_per_mb =
+ ((uint64_t)target_bits_per_frame << BPER_MB_NORMBITS) / cm->MBs;
i = active_best_quality;
@@ -565,11 +569,18 @@ static int rc_pick_q_and_bounds_one_pass_cbr(const VP9_COMP *cpi,
#if LIMIT_QRANGE_FOR_ALTREF_AND_KEY
// Limit Q range for the adaptive loop.
- if (cm->frame_type == KEY_FRAME && !rc->this_key_frame_forced) {
- if (!(cm->current_video_frame == 0))
- *top_index = (active_worst_quality + active_best_quality * 3) / 4;
+ if (cm->frame_type == KEY_FRAME &&
+ !rc->this_key_frame_forced &&
+ !(cm->current_video_frame == 0)) {
+ int qdelta = 0;
+ vp9_clear_system_state();
+ qdelta = vp9_compute_qdelta_by_rate(&cpi->rc, cm->frame_type,
+ active_worst_quality, 2.0);
+ *top_index = active_worst_quality + qdelta;
+ *top_index = (*top_index > *bottom_index) ? *top_index : *bottom_index;
}
#endif
+
// Special case code to try and match quality with forced key frames
if (cm->frame_type == KEY_FRAME && rc->this_key_frame_forced) {
q = rc->last_boosted_qindex;
@@ -725,15 +736,26 @@ static int rc_pick_q_and_bounds_one_pass_vbr(const VP9_COMP *cpi,
*bottom_index = active_best_quality;
#if LIMIT_QRANGE_FOR_ALTREF_AND_KEY
- // Limit Q range for the adaptive loop.
- if (cm->frame_type == KEY_FRAME && !rc->this_key_frame_forced) {
- if (!(cm->current_video_frame == 0))
- *top_index = (active_worst_quality + active_best_quality * 3) / 4;
- } else if (!rc->is_src_frame_alt_ref &&
- (cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame)) {
- *top_index = (active_worst_quality + active_best_quality) / 2;
+ {
+ int qdelta = 0;
+ vp9_clear_system_state();
+
+ // Limit Q range for the adaptive loop.
+ if (cm->frame_type == KEY_FRAME &&
+ !rc->this_key_frame_forced &&
+ !(cm->current_video_frame == 0)) {
+ qdelta = vp9_compute_qdelta_by_rate(&cpi->rc, cm->frame_type,
+ active_worst_quality, 2.0);
+ } else if (!rc->is_src_frame_alt_ref &&
+ (cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame)) {
+ qdelta = vp9_compute_qdelta_by_rate(&cpi->rc, cm->frame_type,
+ active_worst_quality, 1.75);
+ }
+ *top_index = active_worst_quality + qdelta;
+ *top_index = (*top_index > *bottom_index) ? *top_index : *bottom_index;
}
#endif
+
if (oxcf->end_usage == USAGE_CONSTANT_QUALITY) {
q = active_best_quality;
// Special case code to try and match quality with forced key frames
@@ -907,13 +929,22 @@ static int rc_pick_q_and_bounds_two_pass(const VP9_COMP *cpi,
*bottom_index = active_best_quality;
#if LIMIT_QRANGE_FOR_ALTREF_AND_KEY
- // Limit Q range for the adaptive loop.
- if (cm->frame_type == KEY_FRAME && !rc->this_key_frame_forced) {
- *top_index = (active_worst_quality + active_best_quality * 3) / 4;
- } else if (!rc->is_src_frame_alt_ref &&
- (oxcf->end_usage != USAGE_STREAM_FROM_SERVER) &&
- (cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame)) {
- *top_index = (active_worst_quality + active_best_quality) / 2;
+ {
+ int qdelta = 0;
+ vp9_clear_system_state();
+
+ // Limit Q range for the adaptive loop.
+ if (cm->frame_type == KEY_FRAME && !rc->this_key_frame_forced) {
+ qdelta = vp9_compute_qdelta_by_rate(&cpi->rc, cm->frame_type,
+ active_worst_quality, 2.0);
+ } else if (!rc->is_src_frame_alt_ref &&
+ (oxcf->end_usage != USAGE_STREAM_FROM_SERVER) &&
+ (cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame)) {
+ qdelta = vp9_compute_qdelta_by_rate(&cpi->rc, cm->frame_type,
+ active_worst_quality, 1.75);
+ }
+ *top_index = active_worst_quality + qdelta;
+ *top_index = (*top_index > *bottom_index) ? *top_index : *bottom_index;
}
#endif
@@ -1065,11 +1096,11 @@ static void update_golden_frame_stats(VP9_COMP *cpi) {
}
void vp9_rc_postencode_update(VP9_COMP *cpi, uint64_t bytes_used) {
- VP9_COMMON *const cm = &cpi->common;
+ const VP9_COMMON *const cm = &cpi->common;
const VP9_CONFIG *const oxcf = &cpi->oxcf;
RATE_CONTROL *const rc = &cpi->rc;
+ const int qindex = cm->base_qindex;
- cm->last_frame_type = cm->frame_type;
// Update rate control heuristics
rc->projected_frame_size = (int)(bytes_used << 3);
@@ -1080,25 +1111,24 @@ void vp9_rc_postencode_update(VP9_COMP *cpi, uint64_t bytes_used) {
// Keep a record of last Q and ambient average Q.
if (cm->frame_type == KEY_FRAME) {
- rc->last_q[KEY_FRAME] = cm->base_qindex;
- rc->avg_frame_qindex[KEY_FRAME] = ROUND_POWER_OF_TWO(
- 3 * rc->avg_frame_qindex[KEY_FRAME] + cm->base_qindex, 2);
+ rc->last_q[KEY_FRAME] = qindex;
+ rc->avg_frame_qindex[KEY_FRAME] =
+ ROUND_POWER_OF_TWO(3 * rc->avg_frame_qindex[KEY_FRAME] + qindex, 2);
} else if (!rc->is_src_frame_alt_ref &&
- (cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame) &&
- !(cpi->use_svc && oxcf->end_usage == USAGE_STREAM_FROM_SERVER)) {
- rc->last_q[2] = cm->base_qindex;
- rc->avg_frame_qindex[2] = ROUND_POWER_OF_TWO(
- 3 * rc->avg_frame_qindex[2] + cm->base_qindex, 2);
+ (cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame) &&
+ !(cpi->use_svc && oxcf->end_usage == USAGE_STREAM_FROM_SERVER)) {
+ rc->last_q[2] = qindex;
+ rc->avg_frame_qindex[2] =
+ ROUND_POWER_OF_TWO(3 * rc->avg_frame_qindex[2] + qindex, 2);
} else {
- rc->last_q[INTER_FRAME] = cm->base_qindex;
- rc->avg_frame_qindex[INTER_FRAME] = ROUND_POWER_OF_TWO(
- 3 * rc->avg_frame_qindex[INTER_FRAME] + cm->base_qindex, 2);
+ rc->last_q[INTER_FRAME] = qindex;
+ rc->avg_frame_qindex[INTER_FRAME] =
+ ROUND_POWER_OF_TWO(3 * rc->avg_frame_qindex[INTER_FRAME] + qindex, 2);
rc->ni_frames++;
- rc->tot_q += vp9_convert_qindex_to_q(cm->base_qindex);
- rc->avg_q = rc->tot_q / (double)rc->ni_frames;
-
+ rc->tot_q += vp9_convert_qindex_to_q(qindex);
+ rc->avg_q = rc->tot_q / rc->ni_frames;
// Calculate the average Q for normal inter frames (not key or GFU frames).
- rc->ni_tot_qi += cm->base_qindex;
+ rc->ni_tot_qi += qindex;
rc->ni_av_qi = rc->ni_tot_qi / rc->ni_frames;
}
@@ -1107,11 +1137,11 @@ void vp9_rc_postencode_update(VP9_COMP *cpi, uint64_t bytes_used) {
// If all mbs in this group are skipped only update if the Q value is
// better than that already stored.
// This is used to help set quality in forced key frames to reduce popping
- if ((cm->base_qindex < rc->last_boosted_qindex) ||
+ if ((qindex < rc->last_boosted_qindex) ||
((cpi->static_mb_pct < 100) &&
((cm->frame_type == KEY_FRAME) || cpi->refresh_alt_ref_frame ||
(cpi->refresh_golden_frame && !rc->is_src_frame_alt_ref)))) {
- rc->last_boosted_qindex = cm->base_qindex;
+ rc->last_boosted_qindex = qindex;
}
update_buffer_level(cpi, rc->projected_frame_size);
@@ -1196,7 +1226,7 @@ void vp9_rc_get_one_pass_vbr_params(VP9_COMP *cpi) {
int target;
if (!cpi->refresh_alt_ref_frame &&
(cm->current_video_frame == 0 ||
- (cm->frame_flags & FRAMEFLAGS_KEY) ||
+ (cpi->frame_flags & FRAMEFLAGS_KEY) ||
rc->frames_to_key == 0 ||
(cpi->oxcf.auto_key && test_for_kf_one_pass(cpi)))) {
cm->frame_type = KEY_FRAME;
@@ -1258,17 +1288,25 @@ static int calc_pframe_target_size_one_pass_cbr(const VP9_COMP *cpi) {
static int calc_iframe_target_size_one_pass_cbr(const VP9_COMP *cpi) {
const RATE_CONTROL *rc = &cpi->rc;
+ const VP9_CONFIG *oxcf = &cpi->oxcf;
+ const SVC *const svc = &cpi->svc;
int target;
-
if (cpi->common.current_video_frame == 0) {
target = ((cpi->oxcf.starting_buffer_level / 2) > INT_MAX)
? INT_MAX : (int)(cpi->oxcf.starting_buffer_level / 2);
} else {
- const int initial_boost = 32;
- int kf_boost = MAX(initial_boost, (int)(2 * cpi->output_framerate - 16));
- if (rc->frames_since_key < cpi->output_framerate / 2) {
+ int kf_boost = 32;
+ double framerate = oxcf->framerate;
+ if (svc->number_temporal_layers > 1 &&
+ oxcf->end_usage == USAGE_STREAM_FROM_SERVER) {
+ // Use the layer framerate for temporal layers CBR mode.
+ const LAYER_CONTEXT *lc = &svc->layer_context[svc->temporal_layer_id];
+ framerate = lc->framerate;
+ }
+ kf_boost = MAX(kf_boost, (int)(2 * framerate - 16));
+ if (rc->frames_since_key < framerate / 2) {
kf_boost = (int)(kf_boost * rc->frames_since_key /
- (cpi->output_framerate / 2));
+ (framerate / 2));
}
target = ((16 + kf_boost) * rc->av_per_frame_bandwidth) >> 4;
}
@@ -1280,7 +1318,7 @@ void vp9_rc_get_svc_params(VP9_COMP *cpi) {
RATE_CONTROL *const rc = &cpi->rc;
int target = rc->av_per_frame_bandwidth;
if ((cm->current_video_frame == 0) ||
- (cm->frame_flags & FRAMEFLAGS_KEY) ||
+ (cpi->frame_flags & FRAMEFLAGS_KEY) ||
(cpi->oxcf.auto_key && (rc->frames_since_key %
cpi->key_frame_frequency == 0))) {
cm->frame_type = KEY_FRAME;
@@ -1304,7 +1342,7 @@ void vp9_rc_get_one_pass_cbr_params(VP9_COMP *cpi) {
RATE_CONTROL *const rc = &cpi->rc;
int target;
if ((cm->current_video_frame == 0 ||
- (cm->frame_flags & FRAMEFLAGS_KEY) ||
+ (cpi->frame_flags & FRAMEFLAGS_KEY) ||
rc->frames_to_key == 0 ||
(cpi->oxcf.auto_key && test_for_kf_one_pass(cpi)))) {
cm->frame_type = KEY_FRAME;
@@ -1366,3 +1404,46 @@ int vp9_compute_qdelta_by_rate(const RATE_CONTROL *rc, FRAME_TYPE frame_type,
return target_index - qindex;
}
+
+void vp9_rc_update_framerate(VP9_COMP *cpi) {
+ const VP9_COMMON *const cm = &cpi->common;
+ const VP9_CONFIG *const oxcf = &cpi->oxcf;
+ RATE_CONTROL *const rc = &cpi->rc;
+ int vbr_max_bits;
+
+ rc->av_per_frame_bandwidth = (int)(oxcf->target_bandwidth / oxcf->framerate);
+ rc->min_frame_bandwidth = (int)(rc->av_per_frame_bandwidth *
+ oxcf->two_pass_vbrmin_section / 100);
+
+ rc->min_frame_bandwidth = MAX(rc->min_frame_bandwidth, FRAME_OVERHEAD_BITS);
+
+ // A maximum bitrate for a frame is defined.
+ // The baseline for this aligns with HW implementations that
+ // can support decode of 1080P content up to a bitrate of MAX_MB_RATE bits
+ // per 16x16 MB (averaged over a frame). However this limit is extended if
+ // a very high rate is given on the command line or the the rate cannnot
+ // be acheived because of a user specificed max q (e.g. when the user
+ // specifies lossless encode.
+ vbr_max_bits = (int)(((int64_t)rc->av_per_frame_bandwidth *
+ oxcf->two_pass_vbrmax_section) / 100);
+ rc->max_frame_bandwidth = MAX(MAX((cm->MBs * MAX_MB_RATE), MAXRATE_1080P),
+ vbr_max_bits);
+
+ // Set Maximum gf/arf interval
+ rc->max_gf_interval = 16;
+
+ // Extended interval for genuinely static scenes
+ rc->static_scene_max_gf_interval = cpi->key_frame_frequency >> 1;
+
+ // Special conditions when alt ref frame enabled in lagged compress mode
+ if (oxcf->play_alternate && oxcf->lag_in_frames) {
+ if (rc->max_gf_interval > oxcf->lag_in_frames - 1)
+ rc->max_gf_interval = oxcf->lag_in_frames - 1;
+
+ if (rc->static_scene_max_gf_interval > oxcf->lag_in_frames - 1)
+ rc->static_scene_max_gf_interval = oxcf->lag_in_frames - 1;
+ }
+
+ if (rc->max_gf_interval > rc->static_scene_max_gf_interval)
+ rc->max_gf_interval = rc->static_scene_max_gf_interval;
+}