Commit 0d085ebc authored by Adrian Grange's avatar Adrian Grange
Browse files

Prepare for dynamic frame resizing in the recode loop

Prepare for the introduction of frame-size change
logic into the recode loop.

Separated the speed dependent features into
separate static and dynamic parts, the latter being
those features that are dependent on the frame size.

Change-Id: Ia693e28c5cf069a1a7bf12e49ecf83e440e1d313
parent 8e112d95
...@@ -1625,7 +1625,8 @@ VP9_COMP *vp9_create_compressor(VP9EncoderConfig *oxcf) { ...@@ -1625,7 +1625,8 @@ VP9_COMP *vp9_create_compressor(VP9EncoderConfig *oxcf) {
} }
} }
vp9_set_speed_features(cpi); vp9_set_speed_features_framesize_independent(cpi);
vp9_set_speed_features_framesize_dependent(cpi);
// Allocate memory to store variances for a frame. // Allocate memory to store variances for a frame.
CHECK_MEM_ERROR(cm, cpi->source_diff_var, CHECK_MEM_ERROR(cm, cpi->source_diff_var,
...@@ -2309,7 +2310,6 @@ static void scale_and_extend_frame(const YV12_BUFFER_CONFIG *src, ...@@ -2309,7 +2310,6 @@ static void scale_and_extend_frame(const YV12_BUFFER_CONFIG *src,
static int recode_loop_test(const VP9_COMP *cpi, static int recode_loop_test(const VP9_COMP *cpi,
int high_limit, int low_limit, int high_limit, int low_limit,
int q, int maxq, int minq) { int q, int maxq, int minq) {
const VP9_COMMON *const cm = &cpi->common;
const RATE_CONTROL *const rc = &cpi->rc; const RATE_CONTROL *const rc = &cpi->rc;
const VP9EncoderConfig *const oxcf = &cpi->oxcf; const VP9EncoderConfig *const oxcf = &cpi->oxcf;
int force_recode = 0; int force_recode = 0;
...@@ -2323,8 +2323,7 @@ static int recode_loop_test(const VP9_COMP *cpi, ...@@ -2323,8 +2323,7 @@ static int recode_loop_test(const VP9_COMP *cpi,
// and the frame is a key frame, golden frame or alt_ref_frame // and the frame is a key frame, golden frame or alt_ref_frame
} else if ((cpi->sf.recode_loop == ALLOW_RECODE) || } else if ((cpi->sf.recode_loop == ALLOW_RECODE) ||
((cpi->sf.recode_loop == ALLOW_RECODE_KFARFGF) && ((cpi->sf.recode_loop == ALLOW_RECODE_KFARFGF) &&
(cm->frame_type == KEY_FRAME || frame_is_kf_gf_arf(cpi))) {
cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame))) {
// General over and under shoot tests // General over and under shoot tests
if ((rc->projected_frame_size > high_limit && q < maxq) || if ((rc->projected_frame_size > high_limit && q < maxq) ||
(rc->projected_frame_size < low_limit && q > minq)) { (rc->projected_frame_size < low_limit && q > minq)) {
...@@ -2505,8 +2504,10 @@ static void release_scaled_references(VP9_COMP *cpi) { ...@@ -2505,8 +2504,10 @@ static void release_scaled_references(VP9_COMP *cpi) {
const int idx = cpi->scaled_ref_idx[i]; const int idx = cpi->scaled_ref_idx[i];
RefCntBuffer *const buf = RefCntBuffer *const buf =
idx != INVALID_REF_BUFFER_IDX ? &cm->frame_bufs[idx] : NULL; idx != INVALID_REF_BUFFER_IDX ? &cm->frame_bufs[idx] : NULL;
if (buf != NULL) if (buf != NULL) {
--buf->ref_count; --buf->ref_count;
cpi->scaled_ref_idx[i] = INVALID_REF_BUFFER_IDX;
}
} }
} }
...@@ -2617,13 +2618,27 @@ static void set_mv_search_params(VP9_COMP *cpi) { ...@@ -2617,13 +2618,27 @@ static void set_mv_search_params(VP9_COMP *cpi) {
} }
} }
static void set_size_independent_vars(VP9_COMP *cpi) {
vp9_set_speed_features_framesize_independent(cpi);
vp9_set_rd_speed_thresholds(cpi);
vp9_set_rd_speed_thresholds_sub8x8(cpi);
cpi->common.interp_filter = cpi->sf.default_interp_filter;
}
static void set_size_dependent_vars(VP9_COMP *cpi, int *q, static void set_size_dependent_vars(VP9_COMP *cpi, int *q,
int *bottom_index, int *top_index) { int *bottom_index, int *top_index) {
VP9_COMMON *const cm = &cpi->common; VP9_COMMON *const cm = &cpi->common;
const VP9EncoderConfig *const oxcf = &cpi->oxcf; const VP9EncoderConfig *const oxcf = &cpi->oxcf;
// Setup variables that depend on the dimensions of the frame. // Setup variables that depend on the dimensions of the frame.
set_mv_search_params(cpi); vp9_set_speed_features_framesize_dependent(cpi);
// Decide q and q bounds.
*q = vp9_rc_pick_q_and_bounds(cpi, bottom_index, top_index);
if (!frame_is_intra_only(cm)) {
vp9_set_high_precision_mv(cpi, (*q) < HIGH_PRECISION_MV_QTHRESH);
}
// Configure experimental use of segmentation for enhanced coding of // Configure experimental use of segmentation for enhanced coding of
// static regions if indicated. // static regions if indicated.
...@@ -2656,19 +2671,6 @@ static void set_size_dependent_vars(VP9_COMP *cpi, int *q, ...@@ -2656,19 +2671,6 @@ static void set_size_dependent_vars(VP9_COMP *cpi, int *q,
vp9_denoise(cpi->Source, cpi->Source, l); vp9_denoise(cpi->Source, cpi->Source, l);
} }
#endif // CONFIG_VP9_POSTPROC #endif // CONFIG_VP9_POSTPROC
vp9_set_speed_features(cpi);
vp9_set_rd_speed_thresholds(cpi);
vp9_set_rd_speed_thresholds_sub8x8(cpi);
// Decide q and q bounds.
*q = vp9_rc_pick_q_and_bounds(cpi, bottom_index, top_index);
if (!frame_is_intra_only(cm)) {
cm->interp_filter = cpi->sf.default_interp_filter;
vp9_set_high_precision_mv(cpi, (*q) < HIGH_PRECISION_MV_QTHRESH);
}
} }
static void init_motion_estimation(VP9_COMP *cpi) { static void init_motion_estimation(VP9_COMP *cpi) {
...@@ -2681,36 +2683,28 @@ static void init_motion_estimation(VP9_COMP *cpi) { ...@@ -2681,36 +2683,28 @@ static void init_motion_estimation(VP9_COMP *cpi) {
} }
} }
extern void vbr_rate_correction(VP9_COMP *cpi,
int * this_frame_target,
const int64_t vbr_bits_off_target);
void set_frame_size(VP9_COMP *cpi) { void set_frame_size(VP9_COMP *cpi) {
int ref_frame; int ref_frame;
VP9_COMMON *const cm = &cpi->common; VP9_COMMON *const cm = &cpi->common;
const RATE_CONTROL *const rc = &cpi->rc;
const VP9EncoderConfig *const oxcf = &cpi->oxcf; const VP9EncoderConfig *const oxcf = &cpi->oxcf;
MACROBLOCKD *const xd = &cpi->mb.e_mbd; MACROBLOCKD *const xd = &cpi->mb.e_mbd;
if ((oxcf->pass == 2) &&
(!cpi->use_svc ||
(is_two_pass_svc(cpi) &&
cpi->svc.encode_empty_frame_state != ENCODING))) {
int target_rate = rc->base_frame_target;
if (oxcf->rc_mode == VPX_VBR)
vbr_rate_correction(cpi, &target_rate, rc->vbr_bits_off_target);
vp9_rc_set_frame_target(cpi, target_rate);
}
if (oxcf->pass == 2 && if (oxcf->pass == 2 &&
cm->current_video_frame == 0 && cm->current_video_frame == 0 &&
oxcf->allow_spatial_resampling && oxcf->resize_mode == RESIZE_FIXED &&
oxcf->rc_mode == VPX_VBR) { oxcf->rc_mode == VPX_VBR) {
// Internal scaling is triggered on the first frame. // Internal scaling is triggered on the first frame.
vp9_set_size_literal(cpi, oxcf->scaled_frame_width, vp9_set_size_literal(cpi, oxcf->scaled_frame_width,
oxcf->scaled_frame_height); oxcf->scaled_frame_height);
} }
if ((oxcf->pass == 2) &&
(!cpi->use_svc ||
(is_two_pass_svc(cpi) &&
cpi->svc.encode_empty_frame_state != ENCODING))) {
vp9_set_target_rate(cpi);
}
// Reset the frame pointers to the current frame size. // Reset the frame pointers to the current frame size.
vp9_realloc_frame_buffer(get_frame_new_buffer(cm), vp9_realloc_frame_buffer(get_frame_new_buffer(cm),
cm->width, cm->height, cm->width, cm->height,
...@@ -2748,9 +2742,8 @@ void set_frame_size(VP9_COMP *cpi) { ...@@ -2748,9 +2742,8 @@ void set_frame_size(VP9_COMP *cpi) {
} }
static void encode_without_recode_loop(VP9_COMP *cpi) { static void encode_without_recode_loop(VP9_COMP *cpi) {
int q;
int bottom_index, top_index; // Dummy.
VP9_COMMON *const cm = &cpi->common; VP9_COMMON *const cm = &cpi->common;
int q, bottom_index, top_index; // Dummy variables.
vp9_clear_system_state(); vp9_clear_system_state();
...@@ -2763,8 +2756,11 @@ static void encode_without_recode_loop(VP9_COMP *cpi) { ...@@ -2763,8 +2756,11 @@ static void encode_without_recode_loop(VP9_COMP *cpi) {
cpi->Last_Source = vp9_scale_if_required(cm, cpi->unscaled_last_source, cpi->Last_Source = vp9_scale_if_required(cm, cpi->unscaled_last_source,
&cpi->scaled_last_source); &cpi->scaled_last_source);
vp9_scale_references(cpi); if (frame_is_intra_only(cm) == 0) {
vp9_scale_references(cpi);
}
set_size_independent_vars(cpi);
set_size_dependent_vars(cpi, &q, &bottom_index, &top_index); set_size_dependent_vars(cpi, &q, &bottom_index, &top_index);
vp9_set_quantizer(cm, q); vp9_set_quantizer(cm, q);
...@@ -2792,8 +2788,6 @@ static void encode_with_recode_loop(VP9_COMP *cpi, ...@@ -2792,8 +2788,6 @@ static void encode_with_recode_loop(VP9_COMP *cpi,
uint8_t *dest) { uint8_t *dest) {
VP9_COMMON *const cm = &cpi->common; VP9_COMMON *const cm = &cpi->common;
RATE_CONTROL *const rc = &cpi->rc; RATE_CONTROL *const rc = &cpi->rc;
int q;
int q_low, q_high;
int bottom_index, top_index; int bottom_index, top_index;
int loop_count = 0; int loop_count = 0;
int loop = 0; int loop = 0;
...@@ -2801,31 +2795,42 @@ static void encode_with_recode_loop(VP9_COMP *cpi, ...@@ -2801,31 +2795,42 @@ static void encode_with_recode_loop(VP9_COMP *cpi,
int undershoot_seen = 0; int undershoot_seen = 0;
int frame_over_shoot_limit; int frame_over_shoot_limit;
int frame_under_shoot_limit; int frame_under_shoot_limit;
int q = 0, q_low = 0, q_high = 0;
int frame_size_changed = 0;
set_size_independent_vars(cpi);
do { do {
vp9_clear_system_state(); vp9_clear_system_state();
if (loop_count == 0) { set_frame_size(cpi);
set_frame_size(cpi);
// Decide frame size bounds if (loop_count == 0 || frame_size_changed != 0) {
vp9_rc_compute_frame_size_bounds(cpi, rc->this_frame_target, set_size_dependent_vars(cpi, &q, &bottom_index, &top_index);
&frame_under_shoot_limit, q_low = bottom_index;
&frame_over_shoot_limit); q_high = top_index;
cpi->Source = vp9_scale_if_required(cm, cpi->un_scaled_source, // TODO(agrange) Scale cpi->max_mv_magnitude if frame-size has changed.
&cpi->scaled_source); set_mv_search_params(cpi);
}
if (cpi->unscaled_last_source != NULL) // Decide frame size bounds
cpi->Last_Source = vp9_scale_if_required(cm, cpi->unscaled_last_source, vp9_rc_compute_frame_size_bounds(cpi, rc->this_frame_target,
&cpi->scaled_last_source); &frame_under_shoot_limit,
&frame_over_shoot_limit);
vp9_scale_references(cpi); cpi->Source = vp9_scale_if_required(cm, cpi->un_scaled_source,
&cpi->scaled_source);
set_size_dependent_vars(cpi, &q, &bottom_index, &top_index); if (cpi->unscaled_last_source != NULL)
cpi->Last_Source = vp9_scale_if_required(cm, cpi->unscaled_last_source,
&cpi->scaled_last_source);
q_low = bottom_index; if (frame_is_intra_only(cm) == 0) {
q_high = top_index; if (loop_count > 0) {
release_scaled_references(cpi);
}
vp9_scale_references(cpi);
} }
vp9_set_quantizer(cm, q); vp9_set_quantizer(cm, q);
...@@ -3272,7 +3277,9 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi, ...@@ -3272,7 +3277,9 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi,
if (cm->seg.update_map) if (cm->seg.update_map)
update_reference_segmentation_map(cpi); update_reference_segmentation_map(cpi);
release_scaled_references(cpi); if (frame_is_intra_only(cm) == 0) {
release_scaled_references(cpi);
}
vp9_update_reference_frames(cpi); vp9_update_reference_frames(cpi);
for (t = TX_4X4; t <= TX_32X32; t++) for (t = TX_4X4; t <= TX_32X32; t++)
...@@ -3744,7 +3751,7 @@ int vp9_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags, ...@@ -3744,7 +3751,7 @@ int vp9_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags,
cm->frame_contexts[cm->frame_context_idx] = *cm->fc; cm->frame_contexts[cm->frame_context_idx] = *cm->fc;
// No frame encoded, or frame was dropped, release scaled references. // No frame encoded, or frame was dropped, release scaled references.
if (*size == 0) { if ((*size == 0) && (frame_is_intra_only(cm) == 0)) {
release_scaled_references(cpi); release_scaled_references(cpi);
} }
......
...@@ -110,6 +110,11 @@ typedef enum { ...@@ -110,6 +110,11 @@ typedef enum {
AQ_MODE_COUNT // This should always be the last member of the enum AQ_MODE_COUNT // This should always be the last member of the enum
} AQ_MODE; } AQ_MODE;
typedef enum {
RESIZE_NONE = 0, // No frame resizing allowed (except for SVC).
RESIZE_FIXED = 1, // All frames are coded at the specified dimension.
RESIZE_DYNAMIC = 2 // Coded size of each frame is determined by the codec.
} RESIZE_TYPE;
typedef struct VP9EncoderConfig { typedef struct VP9EncoderConfig {
BITSTREAM_PROFILE profile; BITSTREAM_PROFILE profile;
...@@ -165,7 +170,7 @@ typedef struct VP9EncoderConfig { ...@@ -165,7 +170,7 @@ typedef struct VP9EncoderConfig {
AQ_MODE aq_mode; // Adaptive Quantization mode AQ_MODE aq_mode; // Adaptive Quantization mode
// Internal frame size scaling. // Internal frame size scaling.
int allow_spatial_resampling; RESIZE_TYPE resize_mode;
int scaled_frame_width; int scaled_frame_width;
int scaled_frame_height; int scaled_frame_height;
...@@ -472,6 +477,12 @@ void vp9_set_svc(VP9_COMP *cpi, int use_svc); ...@@ -472,6 +477,12 @@ void vp9_set_svc(VP9_COMP *cpi, int use_svc);
int vp9_get_quantizer(struct VP9_COMP *cpi); int vp9_get_quantizer(struct VP9_COMP *cpi);
static INLINE int frame_is_kf_gf_arf(const VP9_COMP *cpi) {
return frame_is_intra_only(&cpi->common) ||
cpi->refresh_alt_ref_frame ||
(cpi->refresh_golden_frame && !cpi->rc.is_src_frame_alt_ref);
}
static INLINE int get_ref_frame_idx(const VP9_COMP *cpi, static INLINE int get_ref_frame_idx(const VP9_COMP *cpi,
MV_REFERENCE_FRAME ref_frame) { MV_REFERENCE_FRAME ref_frame) {
if (ref_frame == LAST_FRAME) { if (ref_frame == LAST_FRAME) {
......
...@@ -338,9 +338,9 @@ static unsigned int highbd_get_prediction_error(BLOCK_SIZE bsize, ...@@ -338,9 +338,9 @@ static unsigned int highbd_get_prediction_error(BLOCK_SIZE bsize,
// Refine the motion search range according to the frame dimension // Refine the motion search range according to the frame dimension
// for first pass test. // for first pass test.
static int get_search_range(const VP9_COMMON *cm) { static int get_search_range(const VP9_COMP *cpi) {
int sr = 0; int sr = 0;
const int dim = MIN(cm->width, cm->height); const int dim = MIN(cpi->initial_width, cpi->initial_height);
while ((dim << sr) < MAX_FULL_PEL_VAL) while ((dim << sr) < MAX_FULL_PEL_VAL)
++sr; ++sr;
...@@ -360,7 +360,7 @@ static void first_pass_motion_search(VP9_COMP *cpi, MACROBLOCK *x, ...@@ -360,7 +360,7 @@ static void first_pass_motion_search(VP9_COMP *cpi, MACROBLOCK *x,
int step_param = 3; int step_param = 3;
int further_steps = (MAX_MVSEARCH_STEPS - 1) - step_param; int further_steps = (MAX_MVSEARCH_STEPS - 1) - step_param;
const int sr = get_search_range(&cpi->common); const int sr = get_search_range(cpi);
step_param += sr; step_param += sr;
further_steps -= sr; further_steps -= sr;
...@@ -947,7 +947,8 @@ void vp9_first_pass(VP9_COMP *cpi, const struct lookahead_entry *source) { ...@@ -947,7 +947,8 @@ void vp9_first_pass(VP9_COMP *cpi, const struct lookahead_entry *source) {
// Initial estimate here uses sqrt(mbs) to define the min_err, where the // Initial estimate here uses sqrt(mbs) to define the min_err, where the
// number of mbs is proportional to the image area. // number of mbs is proportional to the image area.
const int num_mbs = const int num_mbs =
cpi->oxcf.allow_spatial_resampling ? cpi->initial_mbs : cpi->common.MBs; cpi->oxcf.resize_mode == RESIZE_FIXED ?
cpi->initial_mbs : cpi->common.MBs;
const double min_err = 200 * sqrt(num_mbs); const double min_err = 200 * sqrt(num_mbs);
intra_factor = intra_factor / (double)num_mbs; intra_factor = intra_factor / (double)num_mbs;
...@@ -1088,7 +1089,8 @@ static int get_twopass_worst_quality(const VP9_COMP *cpi, ...@@ -1088,7 +1089,8 @@ static int get_twopass_worst_quality(const VP9_COMP *cpi,
return rc->worst_quality; // Highest value allowed return rc->worst_quality; // Highest value allowed
} else { } else {
const int num_mbs = const int num_mbs =
cpi->oxcf.allow_spatial_resampling ? cpi->initial_mbs : cpi->common.MBs; cpi->oxcf.resize_mode == RESIZE_FIXED ?
cpi->initial_mbs : cpi->common.MBs;
const double section_err = stats->coded_error / stats->count; const double section_err = stats->coded_error / stats->count;
const double err_per_mb = section_err / num_mbs; const double err_per_mb = section_err / num_mbs;
const double speed_term = 1.0 + 0.04 * oxcf->speed; const double speed_term = 1.0 + 0.04 * oxcf->speed;
...@@ -1206,7 +1208,8 @@ void vp9_init_second_pass(VP9_COMP *cpi) { ...@@ -1206,7 +1208,8 @@ void vp9_init_second_pass(VP9_COMP *cpi) {
static double get_sr_decay_rate(const VP9_COMP *cpi, static double get_sr_decay_rate(const VP9_COMP *cpi,
const FIRSTPASS_STATS *frame) { const FIRSTPASS_STATS *frame) {
const int num_mbs = const int num_mbs =
cpi->oxcf.allow_spatial_resampling ? cpi->initial_mbs : cpi->common.MBs; cpi->oxcf.resize_mode == RESIZE_FIXED ?
cpi->initial_mbs : cpi->common.MBs;
double sr_diff = double sr_diff =
(frame->sr_coded_error - frame->coded_error) / num_mbs; (frame->sr_coded_error - frame->coded_error) / num_mbs;
double sr_decay = 1.0; double sr_decay = 1.0;
...@@ -1333,7 +1336,8 @@ static double calc_frame_boost(VP9_COMP *cpi, ...@@ -1333,7 +1336,8 @@ static double calc_frame_boost(VP9_COMP *cpi,
cpi->common.bit_depth); cpi->common.bit_depth);
const double boost_q_correction = MIN((0.5 + (lq * 0.015)), 1.5); const double boost_q_correction = MIN((0.5 + (lq * 0.015)), 1.5);
const int num_mbs = const int num_mbs =
cpi->oxcf.allow_spatial_resampling ? cpi->initial_mbs : cpi->common.MBs; cpi->oxcf.resize_mode == RESIZE_FIXED ?
cpi->initial_mbs : cpi->common.MBs;
// Underlying boost factor is based on inter error ratio. // Underlying boost factor is based on inter error ratio.
frame_boost = (BASELINE_ERR_PER_MB * num_mbs) / frame_boost = (BASELINE_ERR_PER_MB * num_mbs) /
...@@ -1744,7 +1748,7 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) { ...@@ -1744,7 +1748,7 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) {
// Motion breakout threshold for loop below depends on image size. // Motion breakout threshold for loop below depends on image size.
mv_ratio_accumulator_thresh = mv_ratio_accumulator_thresh =
(cpi->common.height + cpi->common.width) / 4.0; (cpi->initial_height + cpi->initial_width) / 4.0;
// Set a maximum and minimum interval for the GF group. // Set a maximum and minimum interval for the GF group.
// If the image appears almost completely static we can extend beyond this. // If the image appears almost completely static we can extend beyond this.
...@@ -1802,8 +1806,7 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) { ...@@ -1802,8 +1806,7 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) {
// Monitor for static sections. // Monitor for static sections.
zero_motion_accumulator = zero_motion_accumulator =
MIN(zero_motion_accumulator, MIN(zero_motion_accumulator, get_zero_motion_factor(cpi, &next_frame));
get_zero_motion_factor(cpi, &next_frame));
// Break clause to detect very still sections after motion. For example, // Break clause to detect very still sections after motion. For example,
// a static image after a fade or other transition. // a static image after a fade or other transition.
...@@ -2237,36 +2240,6 @@ static void find_next_key_frame(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) { ...@@ -2237,36 +2240,6 @@ static void find_next_key_frame(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) {
twopass->modified_error_left -= kf_group_err; twopass->modified_error_left -= kf_group_err;
} }
#define VBR_PCT_ADJUSTMENT_LIMIT 50
// For VBR...adjustment to the frame target based on error from previous frames
void vbr_rate_correction(VP9_COMP *cpi,
int * this_frame_target,
const int64_t vbr_bits_off_target) {
int max_delta;
double position_factor = 1.0;
// How far through the clip are we.
// This number is used to damp the per frame rate correction.
// Range 0 - 1.0
if (cpi->twopass.total_stats.count) {
position_factor = sqrt((double)cpi->common.current_video_frame /
cpi->twopass.total_stats.count);
}
max_delta = (int)(position_factor *
((*this_frame_target * VBR_PCT_ADJUSTMENT_LIMIT) / 100));
// vbr_bits_off_target > 0 means we have extra bits to spend
if (vbr_bits_off_target > 0) {
*this_frame_target +=
(vbr_bits_off_target > max_delta) ? max_delta
: (int)vbr_bits_off_target;
} else {
*this_frame_target -=
(vbr_bits_off_target < -max_delta) ? max_delta
: (int)-vbr_bits_off_target;
}
}
// Define the reference buffers that will be updated post encode. // Define the reference buffers that will be updated post encode.
void configure_buffer_updates(VP9_COMP *cpi) { void configure_buffer_updates(VP9_COMP *cpi) {
TWO_PASS *const twopass = &cpi->twopass; TWO_PASS *const twopass = &cpi->twopass;
......
...@@ -1575,3 +1575,43 @@ void vp9_rc_update_framerate(VP9_COMP *cpi) { ...@@ -1575,3 +1575,43 @@ void vp9_rc_update_framerate(VP9_COMP *cpi) {
vp9_rc_set_gf_max_interval(cpi, rc); vp9_rc_set_gf_max_interval(cpi, rc);
} }
#define VBR_PCT_ADJUSTMENT_LIMIT 50
// For VBR...adjustment to the frame target based on error from previous frames
static void vbr_rate_correction(VP9_COMP *cpi,
int *this_frame_target,
int64_t vbr_bits_off_target) {
int max_delta;
double position_factor = 1.0;
// How far through the clip are we.
// This number is used to damp the per frame rate correction.
// Range 0 - 1.0
if (cpi->twopass.total_stats.count) {
position_factor = sqrt((double)cpi->common.current_video_frame /
cpi->twopass.total_stats.count);
}
max_delta = (int)(position_factor *
((*this_frame_target * VBR_PCT_ADJUSTMENT_LIMIT) / 100));
// vbr_bits_off_target > 0 means we have extra bits to spend
if (vbr_bits_off_target > 0) {
*this_frame_target +=
(vbr_bits_off_target > max_delta) ? max_delta
: (int)vbr_bits_off_target;
} else {
*this_frame_target -=
(vbr_bits_off_target < -max_delta) ? max_delta
: (int)-vbr_bits_off_target;
}
}
void vp9_set_target_rate(VP9_COMP *cpi) {
RATE_CONTROL *const rc = &cpi->rc;
int target_rate = rc->base_frame_target;
// Correction to rate target based on prior over or under shoot.
if (cpi->oxcf.rc_mode == VPX_VBR)
vbr_rate_correction(cpi, &target_rate, rc->vbr_bits_off_target);
vp9_rc_set_frame_target(cpi, target_rate);
}
...@@ -198,6 +198,8 @@ void vp9_rc_update_framerate(struct VP9_COMP *cpi); ...@@ -198,6 +198,8 @@ void vp9_rc_update_framerate(struct VP9_COMP *cpi);
void vp9_rc_set_gf_max_interval(const struct VP9_COMP *const cpi, void vp9_rc_set_gf_max_interval(const struct VP9_COMP *const cpi,
RATE_CONTROL *const rc); RATE_CONTROL *const rc);
void vp9_set_target_rate(struct VP9_COMP *cpi);
#ifdef __cplusplus #ifdef __cplusplus
} // extern "C" } // extern "C"
#endif #endif
......
...@@ -591,18 +591,13 @@ void vp9_set_rd_speed_thresholds(VP9_COMP *cpi) { ...@@ -591,18 +591,13 @@ void vp9_set_rd_speed_thresholds(VP9_COMP *cpi) {
} }
void vp9_set_rd_speed_thresholds_sub8x8(VP9_COMP *cpi) { void vp9_set_rd_speed_thresholds_sub8x8(VP9_COMP *cpi) {
const SPEED_FEATURES *const sf = &cpi->sf;
RD_OPT *const rd = &cpi->rd;
int i;
static const int thresh_mult[2][MAX_REFS] = static const int thresh_mult[2][MAX_REFS] =
{{2500, 2500, 2500, 4500, 4500, 2500}, {{2500, 2500, 2500, 4500, 4500, 2500},