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.c95
1 files changed, 43 insertions, 52 deletions
diff --git a/vp9/encoder/vp9_ratectrl.c b/vp9/encoder/vp9_ratectrl.c
index 4d2d43a11..3ebf98c0f 100644
--- a/vp9/encoder/vp9_ratectrl.c
+++ b/vp9/encoder/vp9_ratectrl.c
@@ -211,19 +211,16 @@ static int estimate_bits_at_q(int frame_kind, int q, int mbs,
static void calc_iframe_target_size(VP9_COMP *cpi) {
- // boost defaults to half second
+ const VP9_CONFIG *oxcf = &cpi->oxcf;
+ RATE_CONTROL *const rc = &cpi->rc;
int target;
- // Clear down mmx registers to allow floating point in what follows
vp9_clear_system_state(); // __asm emms;
- // New Two pass RC
- target = cpi->rc.per_frame_bandwidth;
-
// For 1-pass.
if (cpi->pass == 0) {
if (cpi->common.current_video_frame == 0) {
- target = cpi->oxcf.starting_buffer_level / 2;
+ target = oxcf->starting_buffer_level / 2;
} else {
// TODO(marpan): Add in adjustment based on Q.
// If this keyframe was forced, use a more recent Q estimate.
@@ -235,47 +232,49 @@ static void calc_iframe_target_size(VP9_COMP *cpi) {
// Adjustment up based on q: need to fix.
// kf_boost = kf_boost * kfboost_qadjust(Q) / 100;
// Frame separation adjustment (down).
- if (cpi->rc.frames_since_key < cpi->output_framerate / 2) {
- kf_boost = (int)(kf_boost * cpi->rc.frames_since_key /
- (cpi->output_framerate / 2));
+ if (rc->frames_since_key < cpi->output_framerate / 2) {
+ kf_boost = (int)(kf_boost * rc->frames_since_key /
+ (cpi->output_framerate / 2));
}
kf_boost = (kf_boost < 16) ? 16 : kf_boost;
- target = ((16 + kf_boost) * cpi->rc.per_frame_bandwidth) >> 4;
+ target = ((16 + kf_boost) * rc->per_frame_bandwidth) >> 4;
}
- cpi->rc.active_worst_quality = cpi->rc.worst_quality;
+ rc->active_worst_quality = rc->worst_quality;
+ } else {
+ target = rc->per_frame_bandwidth;
}
- if (cpi->oxcf.rc_max_intra_bitrate_pct) {
- int max_rate = cpi->rc.per_frame_bandwidth
- * cpi->oxcf.rc_max_intra_bitrate_pct / 100;
-
- if (target > max_rate)
- target = max_rate;
+ if (oxcf->rc_max_intra_bitrate_pct) {
+ const int max_rate = rc->per_frame_bandwidth *
+ oxcf->rc_max_intra_bitrate_pct / 100;
+ target = MIN(target, max_rate);
}
- cpi->rc.this_frame_target = target;
+ rc->this_frame_target = target;
}
// Update the buffer level: leaky bucket model.
void vp9_update_buffer_level(VP9_COMP *const cpi, int encoded_frame_size) {
- VP9_COMMON *const cm = &cpi->common;
+ const VP9_COMMON *const cm = &cpi->common;
+ const VP9_CONFIG *oxcf = &cpi->oxcf;
RATE_CONTROL *const rc = &cpi->rc;
+
// Non-viewable frames are a special case and are treated as pure overhead.
if (!cm->show_frame) {
rc->bits_off_target -= encoded_frame_size;
} else {
rc->bits_off_target += rc->av_per_frame_bandwidth - encoded_frame_size;
}
+
// Clip the buffer level to the maximum specified buffer size.
- if (rc->bits_off_target > cpi->oxcf.maximum_buffer_size) {
- rc->bits_off_target = cpi->oxcf.maximum_buffer_size;
- }
- rc->buffer_level = rc->bits_off_target;
+ rc->buffer_level = MIN(rc->bits_off_target, oxcf->maximum_buffer_size);
}
int vp9_drop_frame(VP9_COMP *const cpi) {
+ const VP9_CONFIG *oxcf = &cpi->oxcf;
RATE_CONTROL *const rc = &cpi->rc;
- if (!cpi->oxcf.drop_frames_water_mark) {
+
+ if (!oxcf->drop_frames_water_mark) {
return 0;
} else {
if (rc->buffer_level < 0) {
@@ -284,8 +283,8 @@ int vp9_drop_frame(VP9_COMP *const cpi) {
} else {
// 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)(cpi->oxcf.drop_frames_water_mark *
- cpi->oxcf.optimal_buffer_level / 100);
+ int drop_mark = (int)(oxcf->drop_frames_water_mark *
+ oxcf->optimal_buffer_level / 100);
if ((rc->buffer_level > drop_mark) &&
(rc->decimation_factor > 0)) {
--rc->decimation_factor;
@@ -310,14 +309,14 @@ int vp9_drop_frame(VP9_COMP *const cpi) {
}
// Adjust active_worst_quality level based on buffer level.
-static int adjust_active_worst_quality_from_buffer_level(const VP9_COMP *cpi) {
+static int adjust_active_worst_quality_from_buffer_level(const VP9_CONFIG *oxcf,
+ const RATE_CONTROL *rc) {
// Adjust active_worst_quality: If buffer is above the optimal/target level,
// bring active_worst_quality down depending on fullness over buffer.
// If buffer is below the optimal level, let the active_worst_quality go from
// ambient Q (at buffer = optimal level) to worst_quality level
// (at buffer = critical level).
- const RATE_CONTROL *const rc = &cpi->rc;
- const VP9_CONFIG *const oxcf = &cpi->oxcf;
+
int active_worst_quality = rc->active_worst_quality;
// Maximum limit for down adjustment, ~20%.
int max_adjustment_down = active_worst_quality / 5;
@@ -354,31 +353,23 @@ static int adjust_active_worst_quality_from_buffer_level(const VP9_COMP *cpi) {
}
// Adjust target frame size with respect to the buffering constraints:
-static int target_size_from_buffer_level(const VP9_COMP *cpi) {
- const RATE_CONTROL *const rc = &cpi->rc;
- const VP9_CONFIG *const oxcf = &cpi->oxcf;
- int this_frame_target = cpi->rc.this_frame_target;
- int percent_low = 0;
- int percent_high = 0;
- int one_percent_bits = (int)(1 + oxcf->optimal_buffer_level / 100);
- if (rc->buffer_level < oxcf->optimal_buffer_level) {
- percent_low = (int)((oxcf->optimal_buffer_level - rc->buffer_level) /
- one_percent_bits);
- if (percent_low > oxcf->under_shoot_pct)
- percent_low = oxcf->under_shoot_pct;
+static int target_size_from_buffer_level(const VP9_CONFIG *oxcf,
+ const RATE_CONTROL *rc) {
+ int target = rc->this_frame_target;
+ const int64_t diff = oxcf->optimal_buffer_level - rc->buffer_level;
+ const int one_pct_bits = 1 + oxcf->optimal_buffer_level / 100;
+ if (diff > 0) {
// Lower the target bandwidth for this frame.
- this_frame_target -= (this_frame_target * percent_low) / 200;
- } else if (rc->buffer_level > oxcf->optimal_buffer_level) {
- percent_high = (int)((rc->buffer_level - oxcf->optimal_buffer_level) /
- one_percent_bits);
- if (percent_high > oxcf->over_shoot_pct)
- percent_high = oxcf->over_shoot_pct;
-
+ const int pct_low = MIN(diff / one_pct_bits, oxcf->under_shoot_pct);
+ target -= (target * pct_low) / 200;
+ } else if (diff < 0) {
// Increase the target bandwidth for this frame.
- this_frame_target += (this_frame_target * percent_high) / 200;
+ const int pct_high = MIN(-diff / one_pct_bits, oxcf->over_shoot_pct);
+ target += (target * pct_high) / 200;
}
- return this_frame_target;
+
+ return target;
}
static void calc_pframe_target_size(VP9_COMP *const cpi) {
@@ -400,10 +391,10 @@ static void calc_pframe_target_size(VP9_COMP *const cpi) {
// For now, use: cpi->rc.av_per_frame_bandwidth / 16:
min_frame_target = MAX(rc->av_per_frame_bandwidth >> 4,
FRAME_OVERHEAD_BITS);
- rc->this_frame_target = target_size_from_buffer_level(cpi);
+ rc->this_frame_target = target_size_from_buffer_level(oxcf, rc);
// Adjust qp-max based on buffer level.
rc->active_worst_quality =
- adjust_active_worst_quality_from_buffer_level(cpi);
+ adjust_active_worst_quality_from_buffer_level(oxcf, rc);
}
}