Further one-pass vbr rate control changes
Some parameter changes and fixes on one-pass rate control. derfraw300 is now only 10% below 2-pass speed 0 rate control. Change-Id: I1940eef8a5a035dc18e71b880d5e00cabd1f01b9
This commit is contained in:
Родитель
ae8bc7a8e1
Коммит
15fb5510a8
|
@ -902,8 +902,8 @@ static double calc_correction_factor(double err_per_mb,
|
|||
return fclamp(pow(error_term, power_term), 0.05, 5.0);
|
||||
}
|
||||
|
||||
static int estimate_max_q(VP9_COMP *cpi, FIRSTPASS_STATS *fpstats,
|
||||
int section_target_bandwitdh) {
|
||||
int vp9_twopass_worst_quality(VP9_COMP *cpi, FIRSTPASS_STATS *fpstats,
|
||||
int section_target_bandwitdh) {
|
||||
int q;
|
||||
const int num_mbs = cpi->common.MBs;
|
||||
int target_norm_bits_per_mb;
|
||||
|
@ -2280,8 +2280,8 @@ void vp9_rc_get_second_pass_params(VP9_COMP *cpi) {
|
|||
// Special case code for first frame.
|
||||
const int section_target_bandwidth = (int)(twopass->bits_left /
|
||||
frames_left);
|
||||
const int tmp_q = estimate_max_q(cpi, &twopass->total_left_stats,
|
||||
section_target_bandwidth);
|
||||
const int tmp_q = vp9_twopass_worst_quality(cpi, &twopass->total_left_stats,
|
||||
section_target_bandwidth);
|
||||
|
||||
rc->active_worst_quality = tmp_q;
|
||||
rc->ni_av_qi = tmp_q;
|
||||
|
|
|
@ -88,6 +88,8 @@ void vp9_end_first_pass(struct VP9_COMP *cpi);
|
|||
void vp9_init_second_pass(struct VP9_COMP *cpi);
|
||||
void vp9_rc_get_second_pass_params(struct VP9_COMP *cpi);
|
||||
void vp9_end_second_pass(struct VP9_COMP *cpi);
|
||||
int vp9_twopass_worst_quality(struct VP9_COMP *cpi, FIRSTPASS_STATS *fpstats,
|
||||
int section_target_bandwitdh);
|
||||
|
||||
// Post encode update of the rate control parameters for 2-pass
|
||||
void vp9_twopass_postencode_update(struct VP9_COMP *cpi,
|
||||
|
|
|
@ -2776,10 +2776,10 @@ static void output_frame_level_debug_stats(VP9_COMP *cpi) {
|
|||
static void encode_without_recode_loop(VP9_COMP *cpi,
|
||||
size_t *size,
|
||||
uint8_t *dest,
|
||||
int *q) {
|
||||
int q) {
|
||||
VP9_COMMON *const cm = &cpi->common;
|
||||
vp9_clear_system_state(); // __asm emms;
|
||||
vp9_set_quantizer(cpi, *q);
|
||||
vp9_set_quantizer(cpi, q);
|
||||
|
||||
// Set up entropy context depending on frame type. The decoder mandates
|
||||
// the use of the default context, index 0, for keyframes and inter
|
||||
|
@ -2813,7 +2813,7 @@ static void encode_without_recode_loop(VP9_COMP *cpi,
|
|||
static void encode_with_recode_loop(VP9_COMP *cpi,
|
||||
size_t *size,
|
||||
uint8_t *dest,
|
||||
int *q,
|
||||
int q,
|
||||
int bottom_index,
|
||||
int top_index) {
|
||||
VP9_COMMON *const cm = &cpi->common;
|
||||
|
@ -2833,7 +2833,7 @@ static void encode_with_recode_loop(VP9_COMP *cpi,
|
|||
do {
|
||||
vp9_clear_system_state(); // __asm emms;
|
||||
|
||||
vp9_set_quantizer(cpi, *q);
|
||||
vp9_set_quantizer(cpi, q);
|
||||
|
||||
if (loop_count == 0) {
|
||||
// Set up entropy context depending on frame type. The decoder mandates
|
||||
|
@ -2890,7 +2890,7 @@ static void encode_with_recode_loop(VP9_COMP *cpi,
|
|||
if ((cm->frame_type == KEY_FRAME) &&
|
||||
cpi->rc.this_key_frame_forced &&
|
||||
(cpi->rc.projected_frame_size < cpi->rc.max_frame_bandwidth)) {
|
||||
int last_q = *q;
|
||||
int last_q = q;
|
||||
int kf_err = vp9_calc_ss_err(cpi->Source, get_frame_new_buffer(cm));
|
||||
|
||||
int high_err_target = cpi->ambient_err;
|
||||
|
@ -2906,32 +2906,32 @@ static void encode_with_recode_loop(VP9_COMP *cpi,
|
|||
(kf_err > low_err_target &&
|
||||
cpi->rc.projected_frame_size <= frame_under_shoot_limit)) {
|
||||
// Lower q_high
|
||||
q_high = *q > q_low ? *q - 1 : q_low;
|
||||
q_high = q > q_low ? q - 1 : q_low;
|
||||
|
||||
// Adjust Q
|
||||
*q = ((*q) * high_err_target) / kf_err;
|
||||
*q = MIN((*q), (q_high + q_low) >> 1);
|
||||
q = (q * high_err_target) / kf_err;
|
||||
q = MIN(q, (q_high + q_low) >> 1);
|
||||
} else if (kf_err < low_err_target &&
|
||||
cpi->rc.projected_frame_size >= frame_under_shoot_limit) {
|
||||
// The key frame is much better than the previous frame
|
||||
// Raise q_low
|
||||
q_low = *q < q_high ? *q + 1 : q_high;
|
||||
q_low = q < q_high ? q + 1 : q_high;
|
||||
|
||||
// Adjust Q
|
||||
*q = ((*q) * low_err_target) / kf_err;
|
||||
*q = MIN((*q), (q_high + q_low + 1) >> 1);
|
||||
q = (q * low_err_target) / kf_err;
|
||||
q = MIN(q, (q_high + q_low + 1) >> 1);
|
||||
}
|
||||
|
||||
// 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 if (recode_loop_test(
|
||||
cpi, frame_over_shoot_limit, frame_under_shoot_limit,
|
||||
*q, MAX(q_high, top_index), bottom_index)) {
|
||||
q, MAX(q_high, top_index), bottom_index)) {
|
||||
// Is the projected frame size out of range and are we allowed
|
||||
// to attempt to recode.
|
||||
int last_q = *q;
|
||||
int last_q = q;
|
||||
int retries = 0;
|
||||
|
||||
// Frame size out of permitted range:
|
||||
|
@ -2944,23 +2944,23 @@ static void encode_with_recode_loop(VP9_COMP *cpi,
|
|||
q_high = cpi->rc.worst_quality;
|
||||
|
||||
// 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) {
|
||||
// Update rate_correction_factor unless
|
||||
vp9_rc_update_rate_correction_factors(cpi, 1);
|
||||
|
||||
*q = (q_high + q_low + 1) / 2;
|
||||
q = (q_high + q_low + 1) / 2;
|
||||
} else {
|
||||
// Update rate_correction_factor unless
|
||||
vp9_rc_update_rate_correction_factors(cpi, 0);
|
||||
|
||||
*q = vp9_rc_regulate_q(cpi, cpi->rc.this_frame_target,
|
||||
q = vp9_rc_regulate_q(cpi, cpi->rc.this_frame_target,
|
||||
bottom_index, MAX(q_high, top_index));
|
||||
|
||||
while (*q < q_low && retries < 10) {
|
||||
while (q < q_low && retries < 10) {
|
||||
vp9_rc_update_rate_correction_factors(cpi, 0);
|
||||
*q = vp9_rc_regulate_q(cpi, cpi->rc.this_frame_target,
|
||||
q = vp9_rc_regulate_q(cpi, cpi->rc.this_frame_target,
|
||||
bottom_index, MAX(q_high, top_index));
|
||||
retries++;
|
||||
}
|
||||
|
@ -2969,27 +2969,27 @@ static void encode_with_recode_loop(VP9_COMP *cpi,
|
|||
overshoot_seen = 1;
|
||||
} else {
|
||||
// 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) {
|
||||
vp9_rc_update_rate_correction_factors(cpi, 1);
|
||||
*q = (q_high + q_low) / 2;
|
||||
q = (q_high + q_low) / 2;
|
||||
} else {
|
||||
vp9_rc_update_rate_correction_factors(cpi, 0);
|
||||
*q = vp9_rc_regulate_q(cpi, cpi->rc.this_frame_target,
|
||||
q = vp9_rc_regulate_q(cpi, cpi->rc.this_frame_target,
|
||||
bottom_index, top_index);
|
||||
// Special case reset for qlow for constrained quality.
|
||||
// This should only trigger where there is very substantial
|
||||
// undershoot on a frame and the auto cq level is above
|
||||
// the user passsed in value.
|
||||
if (cpi->oxcf.end_usage == USAGE_CONSTRAINED_QUALITY &&
|
||||
*q < q_low) {
|
||||
q_low = *q;
|
||||
q < q_low) {
|
||||
q_low = q;
|
||||
}
|
||||
|
||||
while (*q > q_high && retries < 10) {
|
||||
while (q > q_high && retries < 10) {
|
||||
vp9_rc_update_rate_correction_factors(cpi, 0);
|
||||
*q = vp9_rc_regulate_q(cpi, cpi->rc.this_frame_target,
|
||||
q = vp9_rc_regulate_q(cpi, cpi->rc.this_frame_target,
|
||||
bottom_index, top_index);
|
||||
retries++;
|
||||
}
|
||||
|
@ -2999,9 +2999,9 @@ static void encode_with_recode_loop(VP9_COMP *cpi,
|
|||
}
|
||||
|
||||
// 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 {
|
||||
loop = 0;
|
||||
}
|
||||
|
@ -3219,9 +3219,9 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi,
|
|||
}
|
||||
|
||||
if (cpi->sf.recode_loop == DISALLOW_RECODE) {
|
||||
encode_without_recode_loop(cpi, size, dest, &q);
|
||||
encode_without_recode_loop(cpi, size, dest, q);
|
||||
} else {
|
||||
encode_with_recode_loop(cpi, size, dest, &q, bottom_index, top_index);
|
||||
encode_with_recode_loop(cpi, size, dest, q, bottom_index, top_index);
|
||||
}
|
||||
|
||||
// Special case code to reduce pulsing when key frames are forced at a
|
||||
|
|
|
@ -45,7 +45,7 @@ extern "C" {
|
|||
#else
|
||||
#define MIN_GF_INTERVAL 4
|
||||
#endif
|
||||
#define DEFAULT_GF_INTERVAL 11
|
||||
#define DEFAULT_GF_INTERVAL 10
|
||||
#define DEFAULT_KF_BOOST 2000
|
||||
#define DEFAULT_GF_BOOST 2000
|
||||
|
||||
|
|
|
@ -215,7 +215,7 @@ int vp9_rc_clamp_pframe_target_size(const VP9_COMP *const cpi, int target) {
|
|||
rc->av_per_frame_bandwidth >> 5);
|
||||
if (target < min_frame_target)
|
||||
target = min_frame_target;
|
||||
if (cpi->refresh_golden_frame && rc->source_alt_ref_active) {
|
||||
if (cpi->refresh_golden_frame && rc->is_src_frame_alt_ref) {
|
||||
// If there is an active ARF at this location use the minimum
|
||||
// bits on this frame even if it is a constructed arf.
|
||||
// The active maximum quantizer insures that an appropriate
|
||||
|
@ -487,8 +487,7 @@ static int rc_pick_q_and_adjust_q_bounds_one_pass(const VP9_COMP *cpi,
|
|||
double q_adj_factor = 1.0;
|
||||
double q_val;
|
||||
|
||||
// Baseline value derived from cpi->active_worst_quality and kf boost
|
||||
active_best_quality = get_active_quality(active_worst_quality,
|
||||
active_best_quality = get_active_quality(rc->avg_frame_qindex[KEY_FRAME],
|
||||
rc->kf_boost,
|
||||
kf_low, kf_high,
|
||||
kf_low_motion_minq,
|
||||
|
@ -521,7 +520,8 @@ static int rc_pick_q_and_adjust_q_bounds_one_pass(const VP9_COMP *cpi,
|
|||
rc->avg_frame_qindex[INTER_FRAME] < active_worst_quality) {
|
||||
q = rc->avg_frame_qindex[INTER_FRAME];
|
||||
} else {
|
||||
q = active_worst_quality;
|
||||
q = (oxcf->end_usage == USAGE_STREAM_FROM_SERVER) ?
|
||||
active_worst_quality : rc->avg_frame_qindex[KEY_FRAME];
|
||||
}
|
||||
// For constrained quality dont allow Q less than the cq level
|
||||
if (oxcf->end_usage == USAGE_CONSTRAINED_QUALITY) {
|
||||
|
@ -565,10 +565,24 @@ static int rc_pick_q_and_adjust_q_bounds_one_pass(const VP9_COMP *cpi,
|
|||
active_best_quality = cpi->cq_target_quality;
|
||||
} else {
|
||||
// Use the lower of active_worst_quality and recent/average Q.
|
||||
if (rc->avg_frame_qindex[INTER_FRAME] < active_worst_quality)
|
||||
active_best_quality = inter_minq[rc->avg_frame_qindex[INTER_FRAME]];
|
||||
else
|
||||
active_best_quality = inter_minq[active_worst_quality];
|
||||
if (oxcf->end_usage == USAGE_STREAM_FROM_SERVER) {
|
||||
if (cm->current_video_frame > 1) {
|
||||
if (rc->avg_frame_qindex[INTER_FRAME] < active_worst_quality)
|
||||
active_best_quality = inter_minq[rc->avg_frame_qindex[INTER_FRAME]];
|
||||
else
|
||||
active_best_quality = inter_minq[active_worst_quality];
|
||||
} else {
|
||||
if (rc->avg_frame_qindex[KEY_FRAME] < active_worst_quality)
|
||||
active_best_quality = inter_minq[rc->avg_frame_qindex[KEY_FRAME]];
|
||||
else
|
||||
active_best_quality = inter_minq[active_worst_quality];
|
||||
}
|
||||
} else {
|
||||
if (cm->current_video_frame > 1)
|
||||
active_best_quality = inter_minq[rc->avg_frame_qindex[INTER_FRAME]];
|
||||
else
|
||||
active_best_quality = inter_minq[rc->avg_frame_qindex[KEY_FRAME]];
|
||||
}
|
||||
// For the constrained quality mode we don't want
|
||||
// q to fall below the cq level.
|
||||
if ((oxcf->end_usage == USAGE_CONSTRAINED_QUALITY) &&
|
||||
|
@ -1057,7 +1071,7 @@ static int test_for_kf_one_pass(VP9_COMP *cpi) {
|
|||
#define USE_ALTREF_FOR_ONE_PASS 1
|
||||
|
||||
static int calc_pframe_target_size_one_pass_vbr(const VP9_COMP *const cpi) {
|
||||
static const int af_ratio = 5;
|
||||
static const int af_ratio = 10;
|
||||
const RATE_CONTROL *rc = &cpi->rc;
|
||||
int target;
|
||||
#if USE_ALTREF_FOR_ONE_PASS
|
||||
|
@ -1074,12 +1088,42 @@ static int calc_pframe_target_size_one_pass_vbr(const VP9_COMP *const cpi) {
|
|||
}
|
||||
|
||||
static int calc_iframe_target_size_one_pass_vbr(const VP9_COMP *const cpi) {
|
||||
static const int kf_ratio = 12;
|
||||
static const int kf_ratio = 25;
|
||||
const RATE_CONTROL *rc = &cpi->rc;
|
||||
int target = rc->av_per_frame_bandwidth * kf_ratio;
|
||||
return vp9_rc_clamp_iframe_target_size(cpi, target);
|
||||
}
|
||||
|
||||
static int calc_active_worst_quality_one_pass_vbr(const VP9_COMP *cpi) {
|
||||
int active_worst_quality;
|
||||
if (cpi->common.frame_type == KEY_FRAME) {
|
||||
if (cpi->common.current_video_frame == 0) {
|
||||
active_worst_quality = cpi->rc.worst_quality;
|
||||
} else {
|
||||
// Choose active worst quality twice as large as the last q.
|
||||
active_worst_quality = cpi->rc.last_q[KEY_FRAME] * 2;
|
||||
}
|
||||
} else if (!cpi->rc.is_src_frame_alt_ref &&
|
||||
(cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame)) {
|
||||
if (cpi->common.current_video_frame == 1) {
|
||||
active_worst_quality = cpi->rc.last_q[KEY_FRAME] * 5 / 4;
|
||||
} else {
|
||||
// Choose active worst quality twice as large as the last q.
|
||||
active_worst_quality = cpi->rc.last_q[INTER_FRAME];
|
||||
}
|
||||
} else {
|
||||
if (cpi->common.current_video_frame == 1) {
|
||||
active_worst_quality = cpi->rc.last_q[KEY_FRAME] * 2;
|
||||
} else {
|
||||
// Choose active worst quality twice as large as the last q.
|
||||
active_worst_quality = cpi->rc.last_q[INTER_FRAME] * 2;
|
||||
}
|
||||
}
|
||||
if (active_worst_quality > cpi->rc.worst_quality)
|
||||
active_worst_quality = cpi->rc.worst_quality;
|
||||
return active_worst_quality;
|
||||
}
|
||||
|
||||
void vp9_rc_get_one_pass_vbr_params(VP9_COMP *cpi) {
|
||||
VP9_COMMON *const cm = &cpi->common;
|
||||
RATE_CONTROL *const rc = &cpi->rc;
|
||||
|
@ -1095,22 +1139,8 @@ void vp9_rc_get_one_pass_vbr_params(VP9_COMP *cpi) {
|
|||
rc->frames_to_key = cpi->key_frame_frequency;
|
||||
rc->kf_boost = DEFAULT_KF_BOOST;
|
||||
rc->source_alt_ref_active = 0;
|
||||
if (cm->current_video_frame == 0) {
|
||||
rc->active_worst_quality = rc->worst_quality;
|
||||
} else {
|
||||
// Choose active worst quality twice as large as the last q.
|
||||
rc->active_worst_quality = MIN(rc->worst_quality,
|
||||
rc->last_q[KEY_FRAME] * 2);
|
||||
}
|
||||
} else {
|
||||
cm->frame_type = INTER_FRAME;
|
||||
if (cm->current_video_frame == 1) {
|
||||
rc->active_worst_quality = rc->worst_quality;
|
||||
} else {
|
||||
// Choose active worst quality twice as large as the last q.
|
||||
rc->active_worst_quality = MIN(rc->worst_quality,
|
||||
rc->last_q[INTER_FRAME] * 2);
|
||||
}
|
||||
}
|
||||
if (rc->frames_till_gf_update_due == 0) {
|
||||
rc->baseline_gf_interval = DEFAULT_GF_INTERVAL;
|
||||
|
@ -1122,6 +1152,7 @@ void vp9_rc_get_one_pass_vbr_params(VP9_COMP *cpi) {
|
|||
rc->source_alt_ref_pending = USE_ALTREF_FOR_ONE_PASS;
|
||||
rc->gfu_boost = DEFAULT_GF_BOOST;
|
||||
}
|
||||
cpi->rc.active_worst_quality = calc_active_worst_quality_one_pass_vbr(cpi);
|
||||
if (cm->frame_type == KEY_FRAME)
|
||||
target = calc_iframe_target_size_one_pass_vbr(cpi);
|
||||
else
|
||||
|
@ -1140,13 +1171,15 @@ static int calc_active_worst_quality_one_pass_cbr(const VP9_COMP *cpi) {
|
|||
const RATE_CONTROL *rc = &cpi->rc;
|
||||
int active_worst_quality = rc->active_worst_quality;
|
||||
// Maximum limit for down adjustment, ~20%.
|
||||
int max_adjustment_down = active_worst_quality / 5;
|
||||
// Buffer level below which we push active_worst to worst_quality.
|
||||
int critical_level = oxcf->optimal_buffer_level >> 2;
|
||||
int adjustment = 0;
|
||||
int buff_lvl_step = 0;
|
||||
if (cpi->common.frame_type == KEY_FRAME)
|
||||
return rc->worst_quality;
|
||||
if (rc->buffer_level > oxcf->optimal_buffer_level) {
|
||||
// Adjust down.
|
||||
int max_adjustment_down = active_worst_quality / 5;
|
||||
if (max_adjustment_down) {
|
||||
buff_lvl_step = (int)((oxcf->maximum_buffer_size -
|
||||
oxcf->optimal_buffer_level) / max_adjustment_down);
|
||||
|
@ -1229,16 +1262,15 @@ void vp9_rc_get_svc_params(VP9_COMP *cpi) {
|
|||
cpi->rc.source_alt_ref_active = 0;
|
||||
if (cpi->pass == 0 && cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER) {
|
||||
target = calc_iframe_target_size_one_pass_cbr(cpi);
|
||||
cpi->rc.active_worst_quality = cpi->rc.worst_quality;
|
||||
}
|
||||
} else {
|
||||
cm->frame_type = INTER_FRAME;
|
||||
if (cpi->pass == 0 && cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER) {
|
||||
target = calc_pframe_target_size_one_pass_cbr(cpi);
|
||||
cpi->rc.active_worst_quality =
|
||||
calc_active_worst_quality_one_pass_cbr(cpi);
|
||||
}
|
||||
}
|
||||
cpi->rc.active_worst_quality =
|
||||
calc_active_worst_quality_one_pass_cbr(cpi);
|
||||
vp9_rc_set_frame_target(cpi, target);
|
||||
cpi->rc.frames_till_gf_update_due = INT_MAX;
|
||||
cpi->rc.baseline_gf_interval = INT_MAX;
|
||||
|
@ -1259,12 +1291,12 @@ void vp9_rc_get_one_pass_cbr_params(VP9_COMP *cpi) {
|
|||
rc->kf_boost = DEFAULT_KF_BOOST;
|
||||
rc->source_alt_ref_active = 0;
|
||||
target = calc_iframe_target_size_one_pass_cbr(cpi);
|
||||
rc->active_worst_quality = rc->worst_quality;
|
||||
} else {
|
||||
cm->frame_type = INTER_FRAME;
|
||||
target = calc_pframe_target_size_one_pass_cbr(cpi);
|
||||
rc->active_worst_quality = calc_active_worst_quality_one_pass_cbr(cpi);
|
||||
}
|
||||
cpi->rc.active_worst_quality =
|
||||
calc_active_worst_quality_one_pass_cbr(cpi);
|
||||
vp9_rc_set_frame_target(cpi, target);
|
||||
// Don't use gf_update by default in CBR mode.
|
||||
rc->frames_till_gf_update_due = INT_MAX;
|
||||
|
|
Загрузка…
Ссылка в новой задаче