Commit 23ebacdb authored by Adrian Grange's avatar Adrian Grange
Browse files

Auto-adaptive encoder frame resizing logic

Note: This feature is still in development.

Add an option for the encoder to decide the resolution
at which to encode each frame.

Each KF/GF/ARF goup is tested to see if it would be
better encoded at a lower resolution. At present, each
KF/GF/ARF is coded first at full-size and if the coded
size exceeds a threshold (twice target data rate) at
the maximum active Q then the entire group is encoded
at lower resolution.

This feature is enabled in vpxenc by setting:
  --resize-allowed=1

In addition, if the vpxenc command line also specifies
valid frame dimensions using:
  --resize-width=XXXX & --resize_height=YYYY
then *all* frames will be encoded at this resolution.

Change-Id: I13f341e0a82512f9e84e144e0f3b5aed8a65402b
parent 84b813aa
...@@ -2307,26 +2307,43 @@ static void scale_and_extend_frame(const YV12_BUFFER_CONFIG *src, ...@@ -2307,26 +2307,43 @@ static void scale_and_extend_frame(const YV12_BUFFER_CONFIG *src,
vp9_extend_frame_borders(dst); vp9_extend_frame_borders(dst);
} }
static int scale_down(VP9_COMP *cpi, int q) {
RATE_CONTROL *const rc = &cpi->rc;
GF_GROUP *const gf_group = &cpi->twopass.gf_group;
int scale = 0;
assert(frame_is_kf_gf_arf(cpi));
if (rc->frame_size_selector == UNSCALED &&
q >= rc->rf_level_maxq[gf_group->rf_level[gf_group->index]]) {
const int max_size_thresh = (int)(rate_thresh_mult[SCALE_STEP1]
* MAX(rc->this_frame_target, rc->avg_frame_bandwidth));
scale = rc->projected_frame_size > max_size_thresh ? 1 : 0;
}
return scale;
}
// Function to test for conditions that indicate we should loop // Function to test for conditions that indicate we should loop
// back and recode a frame. // back and recode a frame.
static int recode_loop_test(const VP9_COMP *cpi, static int recode_loop_test(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 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;
const int frame_is_kfgfarf = frame_is_kf_gf_arf(cpi);
int force_recode = 0; int force_recode = 0;
// Special case trap if maximum allowed frame size exceeded. if ((cpi->sf.recode_loop == ALLOW_RECODE) ||
if (rc->projected_frame_size > rc->max_frame_bandwidth) { (frame_is_kfgfarf &&
force_recode = 1; (cpi->sf.recode_loop == ALLOW_RECODE_KFARFGF))) {
if (frame_is_kfgfarf &&
// Is frame recode allowed. (oxcf->resize_mode == RESIZE_DYNAMIC) &&
// Yes if either recode mode 1 is selected or mode 2 is selected scale_down(cpi, q)) {
// and the frame is a key frame, golden frame or alt_ref_frame // Code this group at a lower resolution.
} else if ((cpi->sf.recode_loop == ALLOW_RECODE) || cpi->resize_pending = 1;
((cpi->sf.recode_loop == ALLOW_RECODE_KFARFGF) && return 1;
frame_is_kf_gf_arf(cpi))) { }
// General over and under shoot tests
// TODO(agrange) high_limit could be greater than the scale-down threshold.
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)) {
force_recode = 1; force_recode = 1;
...@@ -2557,13 +2574,15 @@ static void output_frame_level_debug_stats(VP9_COMP *cpi) { ...@@ -2557,13 +2574,15 @@ static void output_frame_level_debug_stats(VP9_COMP *cpi) {
recon_err = vp9_get_y_sse(cpi->Source, get_frame_new_buffer(cm)); recon_err = vp9_get_y_sse(cpi->Source, get_frame_new_buffer(cm));
if (cpi->twopass.total_left_stats.coded_error != 0.0) if (cpi->twopass.total_left_stats.coded_error != 0.0)
fprintf(f, "%10u %10d %10d %10d %10d" fprintf(f, "%10u %dx%d %10d %10d %10d %10d"
"%10"PRId64" %10"PRId64" %10"PRId64" %10"PRId64" %10d " "%10"PRId64" %10"PRId64" %10"PRId64" %10"PRId64" %10d "
"%7.2lf %7.2lf %7.2lf %7.2lf %7.2lf" "%7.2lf %7.2lf %7.2lf %7.2lf %7.2lf"
"%6d %6d %5d %5d %5d " "%6d %6d %5d %5d %5d "
"%10"PRId64" %10.3lf" "%10"PRId64" %10.3lf"
"%10lf %8u %10"PRId64" %10d %10d\n", "%10lf %8u %10"PRId64" %10d %10d\n",
cpi->common.current_video_frame, cpi->rc.this_frame_target, cpi->common.current_video_frame,
cm->width, cm->height,
cpi->rc.this_frame_target,
cpi->rc.projected_frame_size, cpi->rc.projected_frame_size,
cpi->rc.projected_frame_size / cpi->common.MBs, cpi->rc.projected_frame_size / cpi->common.MBs,
(cpi->rc.projected_frame_size - cpi->rc.this_frame_target), (cpi->rc.projected_frame_size - cpi->rc.this_frame_target),
...@@ -2699,14 +2718,17 @@ static void init_motion_estimation(VP9_COMP *cpi) { ...@@ -2699,14 +2718,17 @@ static void init_motion_estimation(VP9_COMP *cpi) {
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 VP9EncoderConfig *const oxcf = &cpi->oxcf; VP9EncoderConfig *const oxcf = &cpi->oxcf;
MACROBLOCKD *const xd = &cpi->td.mb.e_mbd; MACROBLOCKD *const xd = &cpi->td.mb.e_mbd;
if (oxcf->pass == 2 && if (oxcf->pass == 2 &&
cm->current_video_frame == 0 && oxcf->rc_mode == VPX_VBR &&
oxcf->resize_mode == RESIZE_FIXED && ((oxcf->resize_mode == RESIZE_FIXED && cm->current_video_frame == 0) ||
oxcf->rc_mode == VPX_VBR) { (oxcf->resize_mode == RESIZE_DYNAMIC && cpi->resize_pending))) {
// Internal scaling is triggered on the first frame. calculate_coded_size(
cpi, &oxcf->scaled_frame_width, &oxcf->scaled_frame_height);
// There has been a change in frame size.
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);
} }
...@@ -2757,7 +2779,7 @@ void set_frame_size(VP9_COMP *cpi) { ...@@ -2757,7 +2779,7 @@ 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) {
VP9_COMMON *const cm = &cpi->common; VP9_COMMON *const cm = &cpi->common;
int q, bottom_index, top_index; // Dummy variables. int q = 0, bottom_index = 0, top_index = 0; // Dummy variables.
vp9_clear_system_state(); vp9_clear_system_state();
...@@ -2804,13 +2826,13 @@ static void encode_with_recode_loop(VP9_COMP *cpi, ...@@ -2804,13 +2826,13 @@ static void encode_with_recode_loop(VP9_COMP *cpi,
RATE_CONTROL *const rc = &cpi->rc; RATE_CONTROL *const rc = &cpi->rc;
int bottom_index, top_index; int bottom_index, top_index;
int loop_count = 0; int loop_count = 0;
int loop_at_this_size = 0;
int loop = 0; int loop = 0;
int overshoot_seen = 0; int overshoot_seen = 0;
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 q = 0, q_low = 0, q_high = 0;
int frame_size_changed = 0;
set_size_independent_vars(cpi); set_size_independent_vars(cpi);
...@@ -2819,19 +2841,31 @@ static void encode_with_recode_loop(VP9_COMP *cpi, ...@@ -2819,19 +2841,31 @@ static void encode_with_recode_loop(VP9_COMP *cpi,
set_frame_size(cpi); set_frame_size(cpi);
if (loop_count == 0 || frame_size_changed != 0) { if (loop_count == 0 || cpi->resize_pending != 0) {
set_size_dependent_vars(cpi, &q, &bottom_index, &top_index); set_size_dependent_vars(cpi, &q, &bottom_index, &top_index);
q_low = bottom_index;
q_high = top_index;
// TODO(agrange) Scale cpi->max_mv_magnitude if frame-size has changed. // TODO(agrange) Scale cpi->max_mv_magnitude if frame-size has changed.
set_mv_search_params(cpi); set_mv_search_params(cpi);
// Reset the loop state for new frame size.
overshoot_seen = 0;
undershoot_seen = 0;
// Reconfiguration for change in frame size has concluded.
cpi->resize_pending = 0;
q_low = bottom_index;
q_high = top_index;
loop_at_this_size = 0;
} }
// Decide frame size bounds // Decide frame size bounds first time through.
vp9_rc_compute_frame_size_bounds(cpi, rc->this_frame_target, if (loop_count == 0) {
&frame_under_shoot_limit, vp9_rc_compute_frame_size_bounds(cpi, rc->this_frame_target,
&frame_over_shoot_limit); &frame_under_shoot_limit,
&frame_over_shoot_limit);
}
cpi->Source = vp9_scale_if_required(cm, cpi->un_scaled_source, cpi->Source = vp9_scale_if_required(cm, cpi->un_scaled_source,
&cpi->scaled_source); &cpi->scaled_source);
...@@ -2944,6 +2978,20 @@ static void encode_with_recode_loop(VP9_COMP *cpi, ...@@ -2944,6 +2978,20 @@ static void encode_with_recode_loop(VP9_COMP *cpi,
int last_q = q; int last_q = q;
int retries = 0; int retries = 0;
if (cpi->resize_pending == 1) {
// Change in frame size so go back around the recode loop.
cpi->rc.frame_size_selector =
SCALE_STEP1 - cpi->rc.frame_size_selector;
cpi->rc.next_frame_size_selector = cpi->rc.frame_size_selector;
#if CONFIG_INTERNAL_STATS
++cpi->tot_recode_hits;
#endif
++loop_count;
loop = 1;
continue;
}
// Frame size out of permitted range: // Frame size out of permitted range:
// Update correction factor & compute new Q to try... // Update correction factor & compute new Q to try...
...@@ -2956,7 +3004,7 @@ static void encode_with_recode_loop(VP9_COMP *cpi, ...@@ -2956,7 +3004,7 @@ static void encode_with_recode_loop(VP9_COMP *cpi,
// Raise Qlow as to at least the current value // Raise Qlow as to at least the current value
q_low = q < q_high ? q + 1 : q_high; q_low = q < q_high ? q + 1 : q_high;
if (undershoot_seen || loop_count > 1) { if (undershoot_seen || loop_at_this_size > 1) {
// Update rate_correction_factor unless // Update rate_correction_factor unless
vp9_rc_update_rate_correction_factors(cpi); vp9_rc_update_rate_correction_factors(cpi);
...@@ -2981,7 +3029,7 @@ static void encode_with_recode_loop(VP9_COMP *cpi, ...@@ -2981,7 +3029,7 @@ static void encode_with_recode_loop(VP9_COMP *cpi,
// Frame is too small // Frame is too small
q_high = q > q_low ? q - 1 : q_low; q_high = q > q_low ? q - 1 : q_low;
if (overshoot_seen || loop_count > 1) { if (overshoot_seen || loop_at_this_size > 1) {
vp9_rc_update_rate_correction_factors(cpi); vp9_rc_update_rate_correction_factors(cpi);
q = (q_high + q_low) / 2; q = (q_high + q_low) / 2;
} else { } else {
...@@ -3011,7 +3059,7 @@ static void encode_with_recode_loop(VP9_COMP *cpi, ...@@ -3011,7 +3059,7 @@ static void encode_with_recode_loop(VP9_COMP *cpi,
// Clamp Q to upper and lower limits: // Clamp Q to upper and lower limits:
q = clamp(q, q_low, q_high); q = clamp(q, q_low, q_high);
loop = q != last_q; loop = (q != last_q);
} else { } else {
loop = 0; loop = 0;
} }
...@@ -3023,10 +3071,11 @@ static void encode_with_recode_loop(VP9_COMP *cpi, ...@@ -3023,10 +3071,11 @@ static void encode_with_recode_loop(VP9_COMP *cpi,
loop = 0; loop = 0;
if (loop) { if (loop) {
loop_count++; ++loop_count;
++loop_at_this_size;
#if CONFIG_INTERNAL_STATS #if CONFIG_INTERNAL_STATS
cpi->tot_recode_hits++; ++cpi->tot_recode_hits;
#endif #endif
} }
} while (loop); } while (loop);
......
...@@ -448,6 +448,8 @@ typedef struct VP9_COMP { ...@@ -448,6 +448,8 @@ typedef struct VP9_COMP {
VP9_DENOISER denoiser; VP9_DENOISER denoiser;
#endif #endif
int resize_pending;
// Multi-threading // Multi-threading
int num_workers; int num_workers;
VP9Worker *workers; VP9Worker *workers;
...@@ -593,6 +595,8 @@ static INLINE int *cond_cost_list(const struct VP9_COMP *cpi, int *cost_list) { ...@@ -593,6 +595,8 @@ static INLINE int *cond_cost_list(const struct VP9_COMP *cpi, int *cost_list) {
return cpi->sf.mv.subpel_search_method != SUBPEL_TREE ? cost_list : NULL; return cpi->sf.mv.subpel_search_method != SUBPEL_TREE ? cost_list : NULL;
} }
void vp9_new_framerate(VP9_COMP *cpi, double framerate);
#ifdef __cplusplus #ifdef __cplusplus
} // extern "C" } // extern "C"
#endif #endif
......
...@@ -1134,7 +1134,38 @@ static int get_twopass_worst_quality(const VP9_COMP *cpi, ...@@ -1134,7 +1134,38 @@ static int get_twopass_worst_quality(const VP9_COMP *cpi,
} }
} }
extern void vp9_new_framerate(VP9_COMP *cpi, double framerate); static void setup_rf_level_maxq(VP9_COMP *cpi) {
int i;
RATE_CONTROL *const rc = &cpi->rc;
for (i = INTER_NORMAL; i < RATE_FACTOR_LEVELS; ++i) {
int qdelta = vp9_frame_type_qdelta(cpi, i, rc->worst_quality);
rc->rf_level_maxq[i] = MAX(rc->worst_quality + qdelta, rc->best_quality);
}
}
void vp9_init_subsampling(VP9_COMP *cpi) {
const VP9_COMMON *const cm = &cpi->common;
RATE_CONTROL *const rc = &cpi->rc;
const int w = cm->width;
const int h = cm->height;
int i;
for (i = 0; i < FRAME_SCALE_STEPS; ++i) {
// Note: Frames with odd-sized dimensions may result from this scaling.
rc->frame_width[i] = (w * 16) / frame_scale_factor[i];
rc->frame_height[i] = (h * 16) / frame_scale_factor[i];
}
setup_rf_level_maxq(cpi);
}
void calculate_coded_size(VP9_COMP *cpi,
int *scaled_frame_width,
int *scaled_frame_height) {
RATE_CONTROL *const rc = &cpi->rc;
*scaled_frame_width = rc->frame_width[rc->frame_size_selector];
*scaled_frame_height = rc->frame_height[rc->frame_size_selector];
}
void vp9_init_second_pass(VP9_COMP *cpi) { void vp9_init_second_pass(VP9_COMP *cpi) {
SVC *const svc = &cpi->svc; SVC *const svc = &cpi->svc;
...@@ -1204,6 +1235,10 @@ void vp9_init_second_pass(VP9_COMP *cpi) { ...@@ -1204,6 +1235,10 @@ void vp9_init_second_pass(VP9_COMP *cpi) {
// Static sequence monitor variables. // Static sequence monitor variables.
twopass->kf_zeromotion_pct = 100; twopass->kf_zeromotion_pct = 100;
twopass->last_kfgroup_zeromotion_pct = 100; twopass->last_kfgroup_zeromotion_pct = 100;
if (oxcf->resize_mode != RESIZE_NONE) {
vp9_init_subsampling(cpi);
}
} }
#define SR_DIFF_PART 0.0015 #define SR_DIFF_PART 0.0015
...@@ -1696,8 +1731,9 @@ static void allocate_gf_group_bits(VP9_COMP *cpi, int64_t gf_group_bits, ...@@ -1696,8 +1731,9 @@ static void allocate_gf_group_bits(VP9_COMP *cpi, int64_t gf_group_bits,
// Analyse and define a gf/arf group. // Analyse and define a gf/arf group.
static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) { static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) {
VP9_COMMON *const cm = &cpi->common;
RATE_CONTROL *const rc = &cpi->rc; RATE_CONTROL *const rc = &cpi->rc;
const VP9EncoderConfig *const oxcf = &cpi->oxcf; VP9EncoderConfig *const oxcf = &cpi->oxcf;
TWO_PASS *const twopass = &cpi->twopass; TWO_PASS *const twopass = &cpi->twopass;
FIRSTPASS_STATS next_frame; FIRSTPASS_STATS next_frame;
const FIRSTPASS_STATS *const start_pos = twopass->stats_in; const FIRSTPASS_STATS *const start_pos = twopass->stats_in;
...@@ -1733,10 +1769,11 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) { ...@@ -1733,10 +1769,11 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) {
int64_t gf_group_bits; int64_t gf_group_bits;
double gf_group_error_left; double gf_group_error_left;
int gf_arf_bits; int gf_arf_bits;
int is_key_frame = frame_is_intra_only(cm);
// Reset the GF group data structures unless this is a key // Reset the GF group data structures unless this is a key
// frame in which case it will already have been done. // frame in which case it will already have been done.
if (cpi->common.frame_type != KEY_FRAME) { if (is_key_frame == 0) {
vp9_zero(twopass->gf_group); vp9_zero(twopass->gf_group);
} }
...@@ -1752,7 +1789,7 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) { ...@@ -1752,7 +1789,7 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) {
// If this is a key frame or the overlay from a previous arf then // If this is a key frame or the overlay from a previous arf then
// the error score / cost of this frame has already been accounted for. // the error score / cost of this frame has already been accounted for.
if (cpi->common.frame_type == KEY_FRAME || rc->source_alt_ref_active) { if (is_key_frame || rc->source_alt_ref_active) {
gf_group_err -= gf_first_frame_err; gf_group_err -= gf_first_frame_err;
#if GROUP_ADAPTIVE_MAXQ #if GROUP_ADAPTIVE_MAXQ
gf_group_raw_error -= this_frame->coded_error; gf_group_raw_error -= this_frame->coded_error;
...@@ -1864,7 +1901,7 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) { ...@@ -1864,7 +1901,7 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) {
rc->constrained_gf_group = (i >= rc->frames_to_key) ? 1 : 0; rc->constrained_gf_group = (i >= rc->frames_to_key) ? 1 : 0;
// Set the interval until the next gf. // Set the interval until the next gf.
if (cpi->common.frame_type == KEY_FRAME || rc->source_alt_ref_active) if (is_key_frame || rc->source_alt_ref_active)
rc->baseline_gf_interval = i - 1; rc->baseline_gf_interval = i - 1;
else else
rc->baseline_gf_interval = i; rc->baseline_gf_interval = i;
...@@ -1927,9 +1964,9 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) { ...@@ -1927,9 +1964,9 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) {
get_twopass_worst_quality(cpi, group_av_err, vbr_group_bits_per_frame, get_twopass_worst_quality(cpi, group_av_err, vbr_group_bits_per_frame,
twopass->kfgroup_inter_fraction); twopass->kfgroup_inter_fraction);
if (tmp_q < twopass->baseline_worst_quality) { if (tmp_q < twopass->baseline_active_worst_quality) {
twopass->active_worst_quality = twopass->active_worst_quality =
(tmp_q + twopass->baseline_worst_quality + 1) / 2; (tmp_q + twopass->baseline_active_worst_quality + 1) / 2;
} else { } else {
twopass->active_worst_quality = tmp_q; twopass->active_worst_quality = tmp_q;
} }
...@@ -1951,7 +1988,7 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) { ...@@ -1951,7 +1988,7 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) {
// also a key frame in which case it has already been accounted for. // also a key frame in which case it has already been accounted for.
if (rc->source_alt_ref_pending) { if (rc->source_alt_ref_pending) {
gf_group_error_left = gf_group_err - mod_frame_err; gf_group_error_left = gf_group_err - mod_frame_err;
} else if (cpi->common.frame_type != KEY_FRAME) { } else if (is_key_frame == 0) {
gf_group_error_left = gf_group_err - gf_first_frame_err; gf_group_error_left = gf_group_err - gf_first_frame_err;
} else { } else {
gf_group_error_left = gf_group_err; gf_group_error_left = gf_group_err;
...@@ -1969,6 +2006,11 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) { ...@@ -1969,6 +2006,11 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) {
calculate_section_intra_ratio(start_pos, twopass->stats_in_end, calculate_section_intra_ratio(start_pos, twopass->stats_in_end,
rc->baseline_gf_interval); rc->baseline_gf_interval);
} }
if (oxcf->resize_mode == RESIZE_DYNAMIC) {
// Default to starting GF groups at normal frame size.
cpi->rc.next_frame_size_selector = UNSCALED;
}
} }
// TODO(PGW) Re-examine the use of II ration in this code in the light of# // TODO(PGW) Re-examine the use of II ration in this code in the light of#
...@@ -2293,6 +2335,11 @@ static void find_next_key_frame(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) { ...@@ -2293,6 +2335,11 @@ static void find_next_key_frame(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) {
// The count of bits left is adjusted elsewhere based on real coded frame // The count of bits left is adjusted elsewhere based on real coded frame
// sizes. // sizes.
twopass->modified_error_left -= kf_group_err; twopass->modified_error_left -= kf_group_err;
if (oxcf->resize_mode == RESIZE_DYNAMIC) {
// Default to normal-sized frame on keyframes.
cpi->rc.next_frame_size_selector = UNSCALED;
}
} }
// Define the reference buffers that will be updated post encode. // Define the reference buffers that will be updated post encode.
...@@ -2433,7 +2480,7 @@ void vp9_rc_get_second_pass_params(VP9_COMP *cpi) { ...@@ -2433,7 +2480,7 @@ void vp9_rc_get_second_pass_params(VP9_COMP *cpi) {
section_target_bandwidth, DEFAULT_GRP_WEIGHT); section_target_bandwidth, DEFAULT_GRP_WEIGHT);
twopass->active_worst_quality = tmp_q; twopass->active_worst_quality = tmp_q;
twopass->baseline_worst_quality = tmp_q; twopass->baseline_active_worst_quality = tmp_q;
rc->ni_av_qi = tmp_q; rc->ni_av_qi = tmp_q;
rc->last_q[INTER_FRAME] = tmp_q; rc->last_q[INTER_FRAME] = tmp_q;
rc->avg_q = vp9_convert_qindex_to_q(tmp_q, cm->bit_depth); rc->avg_q = vp9_convert_qindex_to_q(tmp_q, cm->bit_depth);
......
...@@ -118,8 +118,8 @@ typedef struct { ...@@ -118,8 +118,8 @@ typedef struct {
int kf_zeromotion_pct; int kf_zeromotion_pct;
int last_kfgroup_zeromotion_pct; int last_kfgroup_zeromotion_pct;
int gf_zeromotion_pct; int gf_zeromotion_pct;
int baseline_worst_quality;
int active_worst_quality; int active_worst_quality;
int baseline_active_worst_quality;
int extend_minq; int extend_minq;
int extend_maxq; int extend_maxq;
...@@ -138,6 +138,13 @@ void vp9_rc_get_second_pass_params(struct VP9_COMP *cpi); ...@@ -138,6 +138,13 @@ void vp9_rc_get_second_pass_params(struct VP9_COMP *cpi);
// Post encode update of the rate control parameters for 2-pass // Post encode update of the rate control parameters for 2-pass
void vp9_twopass_postencode_update(struct VP9_COMP *cpi); void vp9_twopass_postencode_update(struct VP9_COMP *cpi);
void vp9_init_subsampling(struct VP9_COMP *cpi);
void calculate_coded_size(struct VP9_COMP *cpi,
int *scaled_frame_width,
int *scaled_frame_height);
#ifdef __cplusplus #ifdef __cplusplus
} // extern "C" } // extern "C"
#endif #endif
......
...@@ -360,26 +360,32 @@ int vp9_rc_drop_frame(VP9_COMP *cpi) { ...@@ -360,26 +360,32 @@ int vp9_rc_drop_frame(VP9_COMP *cpi) {
static double get_rate_correction_factor(const VP9_COMP *cpi) { static double get_rate_correction_factor(const VP9_COMP *cpi) {
const RATE_CONTROL *const rc = &cpi->rc; const RATE_CONTROL *const rc = &cpi->rc;
double rcf;
if (cpi->common.frame_type == KEY_FRAME) { if (cpi->common.frame_type == KEY_FRAME) {
return rc->rate_correction_factors[KF_STD]; rcf = rc->rate_correction_factors[KF_STD];
} else if (cpi->oxcf.pass == 2) { } else if (cpi->oxcf.pass == 2) {
RATE_FACTOR_LEVEL rf_lvl = RATE_FACTOR_LEVEL rf_lvl =
cpi->twopass.gf_group.rf_level[cpi->twopass.gf_group.index]; cpi->twopass.gf_group.rf_level[cpi->twopass.gf_group.index];
return rc->rate_correction_factors[rf_lvl]; rcf = rc->rate_correction_factors[rf_lvl];
} else { } else {
if ((cpi->refresh_alt_ref_frame || cpi->refresh_golden_frame) && if ((cpi->refresh_alt_ref_frame || cpi->refresh_golden_frame) &&
!rc->is_src_frame_alt_ref && !cpi->use_svc && !rc->is_src_frame_alt_ref && !cpi->use_svc &&
(cpi->oxcf.rc_mode != VPX_CBR || cpi->oxcf.gf_cbr_boost_pct > 20)) (cpi->oxcf.rc_mode != VPX_CBR || cpi->oxcf.gf_cbr_boost_pct > 20))
return rc->rate_correction_factors[GF_ARF_STD]; rcf = rc->rate_correction_factors[GF_ARF_STD];
else else
return rc->rate_correction_factors[INTER_NORMAL]; rcf = rc->rate_correction_factors[INTER_NORMAL];
} }
rcf *= rcf_mult[rc->frame_size_selector];
return rcf > MAX_BPB_FACTOR ? MAX_BPB_FACTOR : rcf;
} }
static void set_rate_correction_factor(VP9_COMP *cpi, double factor) { static void set_rate_correction_factor(VP9_COMP *cpi, double factor) {
RATE_CONTROL *const rc = &cpi->rc; RATE_CONTROL *const rc = &cpi->rc;
// Normalize RCF to account for the size-dependent scaling factor.
factor /= rcf_mult[cpi->rc.frame_size_selector];
if (cpi->common.frame_type == KEY_FRAME) { if (cpi->common.frame_type == KEY_FRAME) {
rc->rate_correction_factors[KF_STD] = factor; rc->rate_correction_factors[KF_STD] = factor;
} else if (cpi->oxcf.pass == 2) { } else if (cpi->oxcf.pass == 2) {
...@@ -911,6 +917,23 @@ static int rc_pick_q_and_bounds_one_pass_vbr(const VP9_COMP *cpi, ...@@ -911,6 +917,23 @@ static int rc_pick_q_and_bounds_one_pass_vbr(const VP9_COMP *cpi,
return q; return q;
} }