Further rate control cleanups

Includes various cleanups.
Streamlines the interfaces so that all rate control state
updates happen in the vp9_rc_postencode_update() function.
This will hopefully make it easier to support multiple
rate control schemes.
Removes some unnecessary code, which in rare cases can casue
a difference in the constrained quality mode output, but
other than that there is no bitstream change yet.

Change-Id: I3198cc37249932feea1e3691c0b2650e7b0c22fc
This commit is contained in:
Deb Mukherjee 2013-12-03 17:05:19 -08:00
parent e7922a5b70
commit 52d273674b
5 changed files with 184 additions and 222 deletions

View File

@ -2170,21 +2170,6 @@ void vp9_second_pass(VP9_COMP *cpi) {
(int)(cpi->twopass.bits_left / frames_left);
cpi->twopass.est_max_qcorrection_factor = 1.0;
// Set a cq_level in constrained quality mode.
// Commenting this code out for now since it does not seem to be
// working well.
/*
if (cpi->oxcf.end_usage == USAGE_CONSTRAINED_QUALITY) {
int est_cq = estimate_cq(cpi, &cpi->twopass.total_left_stats,
section_target_bandwidth);
if (est_cq > cpi->cq_target_quality)
cpi->cq_target_quality = est_cq;
else
cpi->cq_target_quality = cpi->oxcf.cq_level;
}
*/
// guess at maxq needed in 2nd pass
cpi->twopass.maxq_max_limit = cpi->rc.worst_quality;
cpi->twopass.maxq_min_limit = cpi->rc.best_quality;

View File

@ -143,8 +143,9 @@ static INLINE void Scale2Ratio(int mode, int *hr, int *hs) {
}
}
static void set_mvcost(VP9_COMP *cpi) {
static void set_high_precision_mv(VP9_COMP *cpi, int allow_high_precision_mv) {
MACROBLOCK *const mb = &cpi->mb;
cpi->common.allow_high_precision_mv = allow_high_precision_mv;
if (cpi->common.allow_high_precision_mv) {
mb->mvcost = mb->nmvcost_hp;
mb->mvsadcost = mb->nmvsadcost_hp;
@ -234,7 +235,7 @@ static void dealloc_compressor_data(VP9_COMP *cpi) {
// Computes a q delta (in "q index" terms) to get from a starting q value
// to a target value
// target q value
int vp9_compute_qdelta(VP9_COMP *cpi, double qstart, double qtarget) {
int vp9_compute_qdelta(const VP9_COMP *cpi, double qstart, double qtarget) {
int i;
int start_index = cpi->rc.worst_quality;
int target_index = cpi->rc.worst_quality;
@ -1115,8 +1116,8 @@ static void init_config(VP9_PTR ptr, VP9_CONFIG *oxcf) {
vp9_change_config(ptr, oxcf);
// Initialize active best and worst q and average q values.
cpi->rc.active_worst_quality = cpi->oxcf.worst_allowed_q;
cpi->rc.active_best_quality = cpi->oxcf.best_allowed_q;
cpi->rc.active_worst_quality = cpi->oxcf.worst_allowed_q;
cpi->rc.avg_frame_qindex = cpi->oxcf.worst_allowed_q;
// Initialise the starting buffer levels
@ -1205,8 +1206,7 @@ void vp9_change_config(VP9_PTR ptr, VP9_CONFIG *oxcf) {
cm->reset_frame_context = 0;
setup_features(cm);
cpi->common.allow_high_precision_mv = 0; // Default mv precision
set_mvcost(cpi);
set_high_precision_mv(cpi, 0);
{
int i;
@ -1253,12 +1253,8 @@ void vp9_change_config(VP9_PTR ptr, VP9_CONFIG *oxcf) {
// active values should only be modified if out of new range
cpi->rc.active_worst_quality = clamp(cpi->rc.active_worst_quality,
cpi->oxcf.best_allowed_q,
cpi->oxcf.worst_allowed_q);
cpi->rc.active_best_quality = clamp(cpi->rc.active_best_quality,
cpi->oxcf.best_allowed_q,
cpi->oxcf.worst_allowed_q);
cpi->rc.best_quality,
cpi->rc.worst_quality);
cpi->cq_target_quality = cpi->oxcf.cq_level;
@ -2369,16 +2365,6 @@ static int find_fp_qindex() {
return i;
}
static void Pass1Encode(VP9_COMP *cpi, unsigned long *size, unsigned char *dest,
unsigned int *frame_flags) {
(void) size;
(void) dest;
(void) frame_flags;
vp9_set_quantizer(cpi, find_fp_qindex());
vp9_first_pass(cpi);
}
#define WRITE_RECON_BUFFER 0
#if WRITE_RECON_BUFFER
void write_cx_frame_to_file(YV12_BUFFER_CONFIG *frame, int this_frame) {
@ -2470,16 +2456,9 @@ static int recode_loop_test(VP9_COMP *cpi,
cpi->rc.projected_frame_size <
((cpi->rc.this_frame_target * 7) >> 3)) {
force_recode = 1;
} else if (q > cpi->oxcf.cq_level &&
cpi->rc.projected_frame_size < cpi->rc.min_frame_bandwidth &&
cpi->rc.active_best_quality > cpi->oxcf.cq_level) {
// Severe undershoot and between auto and user cq level
force_recode = 1;
cpi->rc.active_best_quality = cpi->oxcf.cq_level;
}
}
}
return force_recode;
}
@ -2639,7 +2618,7 @@ static void output_frame_level_debug_stats(VP9_COMP *cpi) {
if (cpi->twopass.total_left_stats.coded_error != 0.0)
fprintf(f, "%10d %10d %10d %10d %10d %10d %10d %10d %10d"
"%7.2f %7.2f %7.2f %7.2f %7.2f %7.2f %7.2f"
"%7.2f %7.2f %7.2f %7.2f %7.2f %7.2f"
"%6d %6d %5d %5d %5d %8.2f %10d %10.3f"
"%10.3f %8d %10d %10d %10d\n",
cpi->common.current_video_frame, cpi->rc.this_frame_target,
@ -2650,7 +2629,6 @@ static void output_frame_level_debug_stats(VP9_COMP *cpi) {
(int)cpi->rc.total_actual_bits, cm->base_qindex,
vp9_convert_qindex_to_q(cm->base_qindex),
(double)vp9_dc_quant(cm->base_qindex, 0) / 4.0,
vp9_convert_qindex_to_q(cpi->rc.active_best_quality),
vp9_convert_qindex_to_q(cpi->rc.active_worst_quality), cpi->rc.avg_q,
vp9_convert_qindex_to_q(cpi->rc.ni_av_qi),
vp9_convert_qindex_to_q(cpi->cq_target_quality),
@ -2699,6 +2677,7 @@ static void encode_with_recode_loop(VP9_COMP *cpi,
int overshoot_seen = 0;
int undershoot_seen = 0;
int q_low = bottom_index, q_high = top_index;
do {
vp9_clear_system_state(); // __asm emms;
@ -2816,11 +2795,13 @@ static void encode_with_recode_loop(VP9_COMP *cpi,
// 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, top_index);
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, top_index);
retries++;
}
}
@ -2831,18 +2812,12 @@ static void encode_with_recode_loop(VP9_COMP *cpi,
q_high = *q > q_low ? *q - 1 : q_low;
if (overshoot_seen || loop_count > 1) {
// Update rate_correction_factor unless
// cpi->rc.active_worst_quality has changed.
vp9_rc_update_rate_correction_factors(cpi, 1);
*q = (q_high + q_low) / 2;
} else {
// Update rate_correction_factor unless
// cpi->rc.active_worst_quality has changed.
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
@ -2854,7 +2829,8 @@ static void encode_with_recode_loop(VP9_COMP *cpi,
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++;
}
}
@ -2893,8 +2869,8 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi,
int q;
int frame_over_shoot_limit;
int frame_under_shoot_limit;
int top_index;
int top_index_prop;
int bottom_index;
SPEED_FEATURES *const sf = &cpi->sf;
@ -3008,45 +2984,8 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi,
vp9_clear_system_state();
// Decide how big to make the frame.
vp9_rc_pick_frame_size_and_bounds(cpi,
&frame_under_shoot_limit,
&frame_over_shoot_limit);
q = vp9_rc_pick_q_and_adjust_q_bounds(cpi,
&bottom_index,
&top_index);
#if CONFIG_MULTIPLE_ARF
// Force the quantizer determined by the coding order pattern.
if (cpi->multi_arf_enabled && (cm->frame_type != KEY_FRAME) &&
cpi->oxcf.end_usage != USAGE_CONSTANT_QUALITY) {
double new_q;
double current_q = vp9_convert_qindex_to_q(cpi->rc.active_worst_quality);
int level = cpi->this_frame_weight;
assert(level >= 0);
// Set quantizer steps at 10% increments.
new_q = current_q * (1.0 - (0.2 * (cpi->max_arf_level - level)));
q = cpi->rc.active_worst_quality +
vp9_compute_qdelta(cpi, current_q, new_q);
bottom_index = q;
top_index = q;
printf("frame:%d q:%d\n", cm->current_video_frame, q);
}
#endif
vp9_zero(cpi->rd_tx_select_threshes);
if (!frame_is_intra_only(cm)) {
cm->mcomp_filter_type = DEFAULT_INTERP_FILTER;
/* TODO: Decide this more intelligently */
cm->allow_high_precision_mv = q < HIGH_PRECISION_MV_QTHRESH;
set_mvcost(cpi);
}
#if CONFIG_VP9_POSTPROC
if (cpi->oxcf.noise_sensitivity > 0) {
int l = 0;
@ -3076,6 +3015,26 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi,
vp9_write_yuv_frame(cpi->Source);
#endif
// Decide how big to make the frame.
vp9_rc_pick_frame_size_target(cpi);
// Decide frame size bounds
vp9_rc_compute_frame_size_bounds(cpi, cpi->rc.this_frame_target,
&frame_under_shoot_limit,
&frame_over_shoot_limit);
// Decide q and q bounds
q = vp9_rc_pick_q_and_adjust_q_bounds(cpi,
&bottom_index,
&top_index,
&top_index_prop);
if (!frame_is_intra_only(cm)) {
cm->mcomp_filter_type = DEFAULT_INTERP_FILTER;
/* TODO: Decide this more intelligently */
set_high_precision_mv(cpi, (q < HIGH_PRECISION_MV_QTHRESH));
}
encode_with_recode_loop(cpi,
size,
dest,
@ -3161,7 +3120,7 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi,
* needed in motion search besides loopfilter */
cm->last_frame_type = cm->frame_type;
vp9_rc_postencode_update(cpi, *size, q);
vp9_rc_postencode_update(cpi, *size, top_index_prop);
#if 0
output_frame_level_debug_stats(cpi);
@ -3282,6 +3241,21 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi,
cm->prev_mi_grid_visible = cm->prev_mi_grid_base + cm->mode_info_stride + 1;
}
static void Pass0Encode(VP9_COMP *cpi, unsigned long *size, unsigned char *dest,
unsigned int *frame_flags) {
encode_frame_to_data_rate(cpi, size, dest, frame_flags);
}
static void Pass1Encode(VP9_COMP *cpi, unsigned long *size, unsigned char *dest,
unsigned int *frame_flags) {
(void) size;
(void) dest;
(void) frame_flags;
vp9_set_quantizer(cpi, find_fp_qindex());
vp9_first_pass(cpi);
}
static void Pass2Encode(VP9_COMP *cpi, unsigned long *size,
unsigned char *dest, unsigned int *frame_flags) {
cpi->enable_encode_breakout = 1;
@ -3293,27 +3267,6 @@ static void Pass2Encode(VP9_COMP *cpi, unsigned long *size,
// vp9_print_modes_and_motion_vectors(&cpi->common, "encode.stt");
vp9_twopass_postencode_update(cpi, *size);
/*
#ifdef DISABLE_RC_LONG_TERM_MEM
cpi->twopass.bits_left -= cpi->rc.this_frame_target;
#else
cpi->twopass.bits_left -= 8 * *size;
#endif
if (!cpi->refresh_alt_ref_frame) {
double lower_bounds_min_rate = FRAME_OVERHEAD_BITS * cpi->oxcf.framerate;
double two_pass_min_rate = (double)(cpi->oxcf.target_bandwidth
* cpi->oxcf.two_pass_vbrmin_section
/ 100);
if (two_pass_min_rate < lower_bounds_min_rate)
two_pass_min_rate = lower_bounds_min_rate;
cpi->twopass.bits_left += (int64_t)(two_pass_min_rate
/ cpi->oxcf.framerate);
}
*/
}
static void check_initial_width(VP9_COMP *cpi, YV12_BUFFER_CONFIG *sd) {
@ -3386,8 +3339,7 @@ int vp9_get_compressed_data(VP9_PTR ptr, unsigned int *frame_flags,
cpi->source = NULL;
cpi->common.allow_high_precision_mv = ALTREF_HIGH_PRECISION_MV;
set_mvcost(cpi);
set_high_precision_mv(cpi, ALTREF_HIGH_PRECISION_MV);
// Should we code an alternate reference frame.
if (cpi->oxcf.play_alternate && cpi->source_alt_ref_pending) {
@ -3627,7 +3579,8 @@ int vp9_get_compressed_data(VP9_PTR ptr, unsigned int *frame_flags,
} else if (cpi->pass == 2) {
Pass2Encode(cpi, size, dest, frame_flags);
} else {
encode_frame_to_data_rate(cpi, size, dest, frame_flags);
// One pass encode
Pass0Encode(cpi, size, dest, frame_flags);
}
if (cm->refresh_frame_context)

View File

@ -338,7 +338,7 @@ typedef struct {
int worst_quality;
int active_worst_quality;
int best_quality;
int active_best_quality;
// int active_best_quality;
} RATE_CONTROL;
typedef struct VP9_COMP {
@ -695,7 +695,7 @@ int vp9_calc_ss_err(YV12_BUFFER_CONFIG *source, YV12_BUFFER_CONFIG *dest);
void vp9_alloc_compressor_data(VP9_COMP *cpi);
int vp9_compute_qdelta(VP9_COMP *cpi, double qstart, double qtarget);
int vp9_compute_qdelta(const VP9_COMP *cpi, double qstart, double qtarget);
static int get_token_alloc(int mb_rows, int mb_cols) {
return mb_rows * mb_cols * (48 * 16 + 4);

View File

@ -45,6 +45,10 @@ static int gf_high_motion_minq[QINDEX_RANGE];
static int inter_minq[QINDEX_RANGE];
static int afq_low_motion_minq[QINDEX_RANGE];
static int afq_high_motion_minq[QINDEX_RANGE];
static int gf_high = 2000;
static int gf_low = 400;
static int kf_high = 5000;
static int kf_low = 400;
// Functions to compute the active minq lookup table entries based on a
// formulaic approach to facilitate easier adjustment of the Q tables.
@ -84,7 +88,7 @@ void vp9_rc_init_minq_luts(void) {
kf_high_motion_minq[i] = calculate_minq_index(maxq,
0.000002,
-0.0012,
0.5,
0.50,
0.0);
gf_low_motion_minq[i] = calculate_minq_index(maxq,
@ -97,11 +101,6 @@ void vp9_rc_init_minq_luts(void) {
-0.00125,
0.50,
0.0);
inter_minq[i] = calculate_minq_index(maxq,
0.00000271,
-0.00113,
0.75,
0.0);
afq_low_motion_minq[i] = calculate_minq_index(maxq,
0.0000015,
-0.0009,
@ -112,6 +111,11 @@ void vp9_rc_init_minq_luts(void) {
-0.00125,
0.55,
0.0);
inter_minq[i] = calculate_minq_index(maxq,
0.00000271,
-0.00113,
0.75,
0.0);
}
}
@ -285,7 +289,6 @@ static void calc_pframe_target_size(VP9_COMP *cpi) {
}
}
void vp9_rc_update_rate_correction_factors(VP9_COMP *cpi, int damp_var) {
const int q = cpi->common.base_qindex;
int correction_factor = 100;
@ -333,7 +336,6 @@ void vp9_rc_update_rate_correction_factors(VP9_COMP *cpi, int damp_var) {
break;
}
// if ( (correction_factor > 102) && (Q < cpi->rc.active_worst_quality) )
if (correction_factor > 102) {
// We are not already at the worst allowable quality
correction_factor =
@ -367,8 +369,9 @@ void vp9_rc_update_rate_correction_factors(VP9_COMP *cpi, int damp_var) {
}
int vp9_rc_regulate_q(const VP9_COMP *cpi, int target_bits_per_frame) {
int q = cpi->rc.active_worst_quality;
int vp9_rc_regulate_q(const VP9_COMP *cpi, int target_bits_per_frame,
int active_best_quality, int active_worst_quality) {
int q = active_worst_quality;
int i;
int last_error = INT_MAX;
@ -396,7 +399,7 @@ int vp9_rc_regulate_q(const VP9_COMP *cpi, int target_bits_per_frame) {
target_bits_per_mb =
(target_bits_per_frame << BPER_MB_NORMBITS) / cpi->common.MBs;
i = cpi->rc.active_best_quality;
i = active_best_quality;
do {
bits_per_mb_at_this_q = (int)vp9_rc_bits_per_mb(cpi->common.frame_type, i,
@ -412,7 +415,7 @@ int vp9_rc_regulate_q(const VP9_COMP *cpi, int target_bits_per_frame) {
} else {
last_error = bits_per_mb_at_this_q - target_bits_per_mb;
}
} while (++i <= cpi->rc.active_worst_quality);
} while (++i <= active_worst_quality);
return q;
}
@ -438,14 +441,17 @@ static int get_active_quality(int q,
return active_best_quality;
}
int vp9_rc_pick_q_and_adjust_q_bounds(VP9_COMP *cpi,
int vp9_rc_pick_q_and_adjust_q_bounds(const VP9_COMP *cpi,
int *bottom_index,
int *top_index) {
// Set an active best quality and if necessary active worst quality
int q = cpi->rc.active_worst_quality;
VP9_COMMON *const cm = &cpi->common;
int *top_index,
int *top_index_prop) {
const VP9_COMMON *const cm = &cpi->common;
int active_best_quality;
int active_worst_quality = cpi->rc.active_worst_quality;
int q;
if (frame_is_intra_only(cm)) {
active_best_quality = cpi->rc.best_quality;
#if !CONFIG_MULTIPLE_ARF
// Handle the special case for key frames forced when we have75 reached
// the maximum key frame interval. Here force the Q to a range
@ -457,25 +463,19 @@ int vp9_rc_pick_q_and_adjust_q_bounds(VP9_COMP *cpi,
delta_qindex = vp9_compute_qdelta(cpi, last_boosted_q,
(last_boosted_q * 0.75));
cpi->rc.active_best_quality = MAX(qindex + delta_qindex,
cpi->rc.best_quality);
} else if (cpi->pass == 0 && cpi->common.current_video_frame == 0) {
// If this is the first (key) frame in 1-pass, active best/worst is
// the user best/worst-allowed, and leave the top_index to active_worst.
cpi->rc.active_best_quality = cpi->oxcf.best_allowed_q;
cpi->rc.active_worst_quality = cpi->oxcf.worst_allowed_q;
} else {
int high = 5000;
int low = 400;
active_best_quality = MAX(qindex + delta_qindex,
cpi->rc.best_quality);
} else if (!(cpi->pass == 0 && cpi->common.current_video_frame == 0)) {
// not first frame of one pass
double q_adj_factor = 1.0;
double q_val;
// Baseline value derived from cpi->active_worst_quality and kf boost
cpi->rc.active_best_quality = get_active_quality(q, cpi->rc.kf_boost,
low, high,
kf_low_motion_minq,
kf_high_motion_minq);
active_best_quality = get_active_quality(active_worst_quality,
cpi->rc.kf_boost,
kf_low, kf_high,
kf_low_motion_minq,
kf_high_motion_minq);
// Allow somewhat lower kf minq with small image formats.
if ((cm->width * cm->height) <= (352 * 288)) {
@ -487,124 +487,128 @@ int vp9_rc_pick_q_and_adjust_q_bounds(VP9_COMP *cpi,
// Convert the adjustment factor to a qindex delta
// on active_best_quality.
q_val = vp9_convert_qindex_to_q(cpi->rc.active_best_quality);
cpi->rc.active_best_quality +=
q_val = vp9_convert_qindex_to_q(active_best_quality);
active_best_quality +=
vp9_compute_qdelta(cpi, q_val, (q_val * q_adj_factor));
}
#else
double current_q;
// Force the KF quantizer to be 30% of the active_worst_quality.
current_q = vp9_convert_qindex_to_q(cpi->rc.active_worst_quality);
cpi->rc.active_best_quality = cpi->rc.active_worst_quality
current_q = vp9_convert_qindex_to_q(active_worst_quality);
active_best_quality = active_worst_quality
+ vp9_compute_qdelta(cpi, current_q, current_q * 0.3);
#endif
} else if (!cpi->is_src_frame_alt_ref &&
(cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame)) {
int high = 2000;
int low = 400;
// Use the lower of cpi->rc.active_worst_quality and recent
// Use the lower of active_worst_quality and recent
// average Q as basis for GF/ARF best Q limit unless last frame was
// a key frame.
if (cpi->frames_since_key > 1 &&
cpi->rc.avg_frame_qindex < cpi->rc.active_worst_quality) {
cpi->rc.avg_frame_qindex < active_worst_quality) {
q = cpi->rc.avg_frame_qindex;
} else {
q = active_worst_quality;
}
// For constrained quality dont allow Q less than the cq level
if (cpi->oxcf.end_usage == USAGE_CONSTRAINED_QUALITY) {
if (q < cpi->cq_target_quality)
q = cpi->cq_target_quality;
if (cpi->frames_since_key > 1) {
cpi->rc.active_best_quality = get_active_quality(q, cpi->rc.gfu_boost,
low, high,
afq_low_motion_minq,
afq_high_motion_minq);
active_best_quality = get_active_quality(q, cpi->rc.gfu_boost,
gf_low, gf_high,
afq_low_motion_minq,
afq_high_motion_minq);
} else {
cpi->rc.active_best_quality = get_active_quality(q, cpi->rc.gfu_boost,
low, high,
gf_low_motion_minq,
gf_high_motion_minq);
active_best_quality = get_active_quality(q, cpi->rc.gfu_boost,
gf_low, gf_high,
gf_low_motion_minq,
gf_high_motion_minq);
}
// Constrained quality use slightly lower active best.
cpi->rc.active_best_quality = cpi->rc.active_best_quality * 15 / 16;
active_best_quality = active_best_quality * 15 / 16;
} else if (cpi->oxcf.end_usage == USAGE_CONSTANT_QUALITY) {
if (!cpi->refresh_alt_ref_frame) {
cpi->rc.active_best_quality = cpi->cq_target_quality;
active_best_quality = cpi->cq_target_quality;
} else {
if (cpi->frames_since_key > 1) {
cpi->rc.active_best_quality = get_active_quality(
q, cpi->rc.gfu_boost, low, high,
active_best_quality = get_active_quality(
q, cpi->rc.gfu_boost, gf_low, gf_high,
afq_low_motion_minq, afq_high_motion_minq);
} else {
cpi->rc.active_best_quality = get_active_quality(
q, cpi->rc.gfu_boost, low, high,
active_best_quality = get_active_quality(
q, cpi->rc.gfu_boost, gf_low, gf_high,
gf_low_motion_minq, gf_high_motion_minq);
}
}
} else {
cpi->rc.active_best_quality = get_active_quality(
q, cpi->rc.gfu_boost, low, high,
gf_low_motion_minq, gf_high_motion_minq);
active_best_quality = get_active_quality(
q, cpi->rc.gfu_boost, gf_low, gf_high,
gf_low_motion_minq, gf_high_motion_minq);
}
} else {
if (cpi->oxcf.end_usage == USAGE_CONSTANT_QUALITY) {
cpi->rc.active_best_quality = cpi->cq_target_quality;
active_best_quality = cpi->cq_target_quality;
} else {
cpi->rc.active_best_quality = inter_minq[q];
// 1-pass: for now, use the average Q for the active_best, if its lower
// than active_worst.
if (cpi->pass == 0 && (cpi->rc.avg_frame_qindex < q))
cpi->rc.active_best_quality = inter_minq[cpi->rc.avg_frame_qindex];
if (cpi->pass == 0 &&
cpi->rc.avg_frame_qindex < active_worst_quality)
// 1-pass: for now, use the average Q for the active_best, if its lower
// than active_worst.
active_best_quality = inter_minq[cpi->rc.avg_frame_qindex];
else
active_best_quality = inter_minq[active_worst_quality];
// For the constrained quality mode we don't want
// q to fall below the cq level.
if ((cpi->oxcf.end_usage == USAGE_CONSTRAINED_QUALITY) &&
(cpi->rc.active_best_quality < cpi->cq_target_quality)) {
(active_best_quality < cpi->cq_target_quality)) {
// If we are strongly undershooting the target rate in the last
// frames then use the user passed in cq value not the auto
// cq value.
if (cpi->rc.rolling_actual_bits < cpi->rc.min_frame_bandwidth)
cpi->rc.active_best_quality = cpi->oxcf.cq_level;
active_best_quality = cpi->oxcf.cq_level;
else
cpi->rc.active_best_quality = cpi->cq_target_quality;
active_best_quality = cpi->cq_target_quality;
}
}
}
// Clip the active best and worst quality values to limits
if (cpi->rc.active_worst_quality > cpi->rc.worst_quality)
cpi->rc.active_worst_quality = cpi->rc.worst_quality;
if (active_worst_quality > cpi->rc.worst_quality)
active_worst_quality = cpi->rc.worst_quality;
if (cpi->rc.active_best_quality < cpi->rc.best_quality)
cpi->rc.active_best_quality = cpi->rc.best_quality;
if (active_best_quality < cpi->rc.best_quality)
active_best_quality = cpi->rc.best_quality;
if (cpi->rc.active_best_quality > cpi->rc.worst_quality)
cpi->rc.active_best_quality = cpi->rc.worst_quality;
if (active_best_quality > cpi->rc.worst_quality)
active_best_quality = cpi->rc.worst_quality;
if (cpi->rc.active_worst_quality < cpi->rc.active_best_quality)
cpi->rc.active_worst_quality = cpi->rc.active_best_quality;
if (active_worst_quality < active_best_quality)
active_worst_quality = active_best_quality;
*top_index = cpi->rc.active_worst_quality;
*bottom_index = cpi->rc.active_best_quality;
*top_index_prop = active_worst_quality;
*top_index = active_worst_quality;
*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 && !cpi->this_key_frame_forced) {
if (!(cpi->pass == 0 && cpi->common.current_video_frame == 0)) {
*top_index = active_worst_quality;
*top_index =
(cpi->rc.active_worst_quality + cpi->rc.active_best_quality * 3) / 4;
(active_worst_quality + active_best_quality * 3) / 4;
}
} else if (!cpi->is_src_frame_alt_ref &&
(cpi->oxcf.end_usage != USAGE_STREAM_FROM_SERVER) &&
(cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame)) {
*top_index =
(cpi->rc.active_worst_quality + cpi->rc.active_best_quality) / 2;
(active_worst_quality + active_best_quality) / 2;
}
#endif
if (cpi->oxcf.end_usage == USAGE_CONSTANT_QUALITY) {
q = cpi->rc.active_best_quality;
q = active_best_quality;
// Special case code to try and match quality with forced key frames
} else if ((cm->frame_type == KEY_FRAME) && cpi->this_key_frame_forced) {
q = cpi->rc.last_boosted_qindex;
@ -614,17 +618,35 @@ int vp9_rc_pick_q_and_adjust_q_bounds(VP9_COMP *cpi,
// 1-pass: for now, use per-frame-bw for target size of frame, scaled
// by |x| for key frame.
int scale = (cm->frame_type == KEY_FRAME) ? 5 : 1;
q = vp9_rc_regulate_q(cpi, scale * cpi->rc.av_per_frame_bandwidth);
q = vp9_rc_regulate_q(cpi, scale * cpi->rc.av_per_frame_bandwidth,
active_best_quality, active_worst_quality);
} else {
q = vp9_rc_regulate_q(cpi, cpi->rc.this_frame_target);
q = vp9_rc_regulate_q(cpi, cpi->rc.this_frame_target,
active_best_quality, active_worst_quality);
}
if (q > *top_index)
q = *top_index;
}
#if CONFIG_MULTIPLE_ARF
// Force the quantizer determined by the coding order pattern.
if (cpi->multi_arf_enabled && (cm->frame_type != KEY_FRAME) &&
cpi->oxcf.end_usage != USAGE_CONSTANT_QUALITY) {
double new_q;
double current_q = vp9_convert_qindex_to_q(active_worst_quality);
int level = cpi->this_frame_weight;
assert(level >= 0);
new_q = current_q * (1.0 - (0.2 * (cpi->max_arf_level - level)));
q = active_worst_quality +
vp9_compute_qdelta(cpi, current_q, new_q);
*bottom_index = q;
*top_index = q;
printf("frame:%d q:%d\n", cm->current_video_frame, q);
}
#endif
return q;
}
static int estimate_keyframe_frequency(VP9_COMP *cpi) {
int i;
@ -680,8 +702,7 @@ static void adjust_key_frame_context(VP9_COMP *cpi) {
cpi->rc.key_frame_count++;
}
static void compute_frame_size_bounds(const VP9_COMP *cpi,
void vp9_rc_compute_frame_size_bounds(const VP9_COMP *cpi,
int this_frame_target,
int *frame_under_shoot_limit,
int *frame_over_shoot_limit) {
@ -720,9 +741,7 @@ static void compute_frame_size_bounds(const VP9_COMP *cpi,
}
// return of 0 means drop frame
int vp9_rc_pick_frame_size_and_bounds(VP9_COMP *cpi,
int *frame_under_shoot_limit,
int *frame_over_shoot_limit) {
int vp9_rc_pick_frame_size_target(VP9_COMP *cpi) {
VP9_COMMON *cm = &cpi->common;
if (cm->frame_type == KEY_FRAME)
@ -733,13 +752,11 @@ int vp9_rc_pick_frame_size_and_bounds(VP9_COMP *cpi,
// Target rate per SB64 (including partial SB64s.
cpi->rc.sb64_target_rate = ((int64_t)cpi->rc.this_frame_target * 64 * 64) /
(cpi->common.width * cpi->common.height);
compute_frame_size_bounds(cpi, cpi->rc.this_frame_target,
frame_under_shoot_limit, frame_over_shoot_limit);
return 1;
}
void vp9_rc_postencode_update(VP9_COMP *cpi, uint64_t bytes_used, int q) {
void vp9_rc_postencode_update(VP9_COMP *cpi, uint64_t bytes_used,
int worst_q) {
VP9_COMMON *const cm = &cpi->common;
// Update rate control heuristics
cpi->rc.projected_frame_size = (bytes_used << 3);
@ -750,6 +767,7 @@ void vp9_rc_postencode_update(VP9_COMP *cpi, uint64_t bytes_used, int q) {
cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER) ? 2 : 0);
cpi->rc.last_q[cm->frame_type] = cm->base_qindex;
cpi->rc.active_worst_quality = worst_q;
// Keep record of last boosted (KF/KF/ARF) Q value.
// If the current frame is coded at a lower Q then we also update it.
@ -777,11 +795,11 @@ void vp9_rc_postencode_update(VP9_COMP *cpi, uint64_t bytes_used, int q) {
if (cm->frame_type != KEY_FRAME &&
!cpi->refresh_golden_frame && !cpi->refresh_alt_ref_frame) {
cpi->rc.ni_frames++;
cpi->rc.tot_q += vp9_convert_qindex_to_q(q);
cpi->rc.tot_q += vp9_convert_qindex_to_q(cm->base_qindex);
cpi->rc.avg_q = cpi->rc.tot_q / (double)cpi->rc.ni_frames;
// Calculate the average Q for normal inter frames (not key or GFU frames).
cpi->rc.ni_tot_qi += q;
cpi->rc.ni_tot_qi += cm->base_qindex;
cpi->rc.ni_av_qi = cpi->rc.ni_tot_qi / cpi->rc.ni_frames;
}

View File

@ -31,23 +31,29 @@ void vp9_rc_update_rate_correction_factors(VP9_COMP *cpi, int damp_var);
void vp9_rc_init_minq_luts(void);
// return of 0 means drop frame
// Changes rc.this_frame_target and rc.sb64_rate_target
int vp9_rc_pick_frame_size_and_bounds(VP9_COMP *cpi,
// Changes only rc.this_frame_target and rc.sb64_rate_target
int vp9_rc_pick_frame_size_target(VP9_COMP *cpi);
void vp9_rc_compute_frame_size_bounds(const VP9_COMP *cpi,
int this_frame_target,
int *frame_under_shoot_limit,
int *frame_over_shoot_limit);
// Picks q and q bounds given the target for bits
int vp9_rc_pick_q_and_adjust_q_bounds(VP9_COMP *cpi,
int * bottom_index,
int * top_index);
int vp9_rc_pick_q_and_adjust_q_bounds(const VP9_COMP *cpi,
int *bottom_index,
int *top_index,
int *top_index_prop);
// Estimates q to achieve a target bits per frame
int vp9_rc_regulate_q(const VP9_COMP *cpi, int target_bits_per_frame);
int vp9_rc_regulate_q(const VP9_COMP *cpi, int target_bits_per_frame,
int active_best_quality, int active_worst_quality);
// Post encode update of the rate control parameters based
// on bytes used and q used for the frame
void vp9_rc_postencode_update(VP9_COMP *cpi,
uint64_t bytes_used,
int q_used);
int worst_q);
// estimates bits per mb for a given qindex and correction factor
int vp9_rc_bits_per_mb(FRAME_TYPE frame_type, int qindex,