1 Pass CQ and VBR bug fixes

Issue 291 highlighted  the fact that CQ mode was not working
as expected in 1 pass mode,

This commit fixes that specific problem but in so doing I also
uncovered an overflow issue in the VBR code for 1 pass and
some data values not being correctly initialized.

For some clips (particularly short clips), the resulting
improvement is dramatic.

Change-Id: Ieefd6c6e4776eb8f1b0550dbfdfb72f86b33c960
This commit is contained in:
Paul Wilkins 2011-03-10 16:11:39 +00:00 committed by John Koleszar
parent a0306ea660
commit 2ae91fbef0
2 changed files with 97 additions and 40 deletions

View File

@ -1516,9 +1516,15 @@ void vp8_init_config(VP8_PTR ptr, VP8_CONFIG *oxcf)
else
cpi->oxcf = *oxcf;
// change includes all joint functionality
vp8_change_config(ptr, oxcf);
// Convert target bandwidth from Kbit/s to Bit/s
cpi->oxcf.target_bandwidth *= 1000;
// Initialize active best and worst q and average q values.
cpi->active_worst_quality = cpi->oxcf.worst_allowed_q;
cpi->active_best_quality = cpi->oxcf.best_allowed_q;
cpi->avg_frame_qindex = cpi->oxcf.worst_allowed_q;
// Initialise the starting buffer levels
cpi->oxcf.starting_buffer_level =
rescale(cpi->oxcf.starting_buffer_level,
cpi->oxcf.target_bandwidth, 1000);
@ -1526,10 +1532,6 @@ void vp8_init_config(VP8_PTR ptr, VP8_CONFIG *oxcf)
cpi->buffer_level = cpi->oxcf.starting_buffer_level;
cpi->bits_off_target = cpi->oxcf.starting_buffer_level;
cpi->active_worst_quality = cpi->oxcf.worst_allowed_q;
cpi->active_best_quality = cpi->oxcf.best_allowed_q;
cpi->avg_frame_qindex = cpi->oxcf.worst_allowed_q;
cpi->rolling_target_bits = cpi->av_per_frame_bandwidth;
cpi->rolling_actual_bits = cpi->av_per_frame_bandwidth;
cpi->long_rolling_target_bits = cpi->av_per_frame_bandwidth;
@ -1538,9 +1540,6 @@ void vp8_init_config(VP8_PTR ptr, VP8_CONFIG *oxcf)
cpi->total_actual_bits = 0;
cpi->total_target_vs_actual = 0;
// change includes all joint functionality
vp8_change_config(ptr, oxcf);
#if VP8_TEMPORAL_ALT_REF
cpi->use_weighted_temporal_filter = 0;
@ -1668,7 +1667,8 @@ void vp8_change_config(VP8_PTR ptr, VP8_CONFIG *oxcf)
}
cpi->baseline_gf_interval = cpi->oxcf.alt_freq ? cpi->oxcf.alt_freq : DEFAULT_GF_INTERVAL;
cpi->baseline_gf_interval =
cpi->oxcf.alt_freq ? cpi->oxcf.alt_freq : DEFAULT_GF_INTERVAL;
cpi->ref_frame_flags = VP8_ALT_FLAG | VP8_GOLD_FLAG | VP8_LAST_FLAG;
@ -1679,7 +1679,8 @@ void vp8_change_config(VP8_PTR ptr, VP8_CONFIG *oxcf)
cm->refresh_entropy_probs = 1;
if (cpi->oxcf.token_partitions >= 0 && cpi->oxcf.token_partitions <= 3)
cm->multi_token_partition = (TOKEN_PARTITION) cpi->oxcf.token_partitions;
cm->multi_token_partition =
(TOKEN_PARTITION) cpi->oxcf.token_partitions;
setup_features(cpi);
@ -1700,12 +1701,12 @@ void vp8_change_config(VP8_PTR ptr, VP8_CONFIG *oxcf)
cpi->oxcf.starting_buffer_level = 60000;
cpi->oxcf.optimal_buffer_level = 60000;
cpi->oxcf.maximum_buffer_size = 240000;
}
// Convert target bandwidth from Kbit/s to Bit/s
cpi->oxcf.target_bandwidth *= 1000;
// Set or reset optimal and maximum buffer levels.
if (cpi->oxcf.optimal_buffer_level == 0)
cpi->oxcf.optimal_buffer_level = cpi->oxcf.target_bandwidth / 8;
else
@ -1720,7 +1721,10 @@ void vp8_change_config(VP8_PTR ptr, VP8_CONFIG *oxcf)
rescale(cpi->oxcf.maximum_buffer_size,
cpi->oxcf.target_bandwidth, 1000);
// Set up frame rate and related parameters rate control values.
vp8_new_frame_rate(cpi, cpi->oxcf.frame_rate);
// Set absolute upper and lower quality limits
cpi->worst_quality = cpi->oxcf.worst_allowed_q;
cpi->best_quality = cpi->oxcf.best_allowed_q;
@ -1749,9 +1753,9 @@ void vp8_change_config(VP8_PTR ptr, VP8_CONFIG *oxcf)
cpi->cq_target_quality = cpi->oxcf.cq_level;
// Only allow dropped frames in buffered mode
cpi->drop_frames_allowed = cpi->oxcf.allow_df && cpi->buffered_mode;
cpi->drop_frames_allowed = cpi->oxcf.allow_df && cpi->buffered_mode;
cm->filter_type = (LOOPFILTERTYPE) cpi->filter_type;
cm->filter_type = (LOOPFILTERTYPE) cpi->filter_type;
if (!cm->use_bilinear_mc_filter)
cm->mcomp_filter_type = SIXTAP;
@ -1766,7 +1770,8 @@ void vp8_change_config(VP8_PTR ptr, VP8_CONFIG *oxcf)
cm->horiz_scale = cpi->horiz_scale;
cm->vert_scale = cpi->vert_scale ;
cpi->intra_frame_target = (4 * (cm->Width + cm->Height) / 15) * 1000; // As per VP8
// As per VP8
cpi->intra_frame_target = (4 * (cm->Width + cm->Height) / 15) * 1000;
// VP8 sharpness level mapping 0-7 (vs 0-10 in general VPx dialogs)
if (cpi->oxcf.Sharpness > 7)
@ -1787,8 +1792,10 @@ void vp8_change_config(VP8_PTR ptr, VP8_CONFIG *oxcf)
cm->Height = (vs - 1 + cpi->oxcf.Height * vr) / vs;
}
if (((cm->Width + 15) & 0xfffffff0) != cm->yv12_fb[cm->lst_fb_idx].y_width ||
((cm->Height + 15) & 0xfffffff0) != cm->yv12_fb[cm->lst_fb_idx].y_height ||
if (((cm->Width + 15) & 0xfffffff0) !=
cm->yv12_fb[cm->lst_fb_idx].y_width ||
((cm->Height + 15) & 0xfffffff0) !=
cm->yv12_fb[cm->lst_fb_idx].y_height ||
cm->yv12_fb[cm->lst_fb_idx].y_width == 0)
{
alloc_raw_frame_buffers(cpi);
@ -3637,11 +3644,12 @@ static void encode_frame_to_data_rate
}
}
// If CBR and the buffer is as full then it is reasonable to allow higher quality on the frames
// to prevent bits just going to waste.
// If CBR and the buffer is as full then it is reasonable to allow
// higher quality on the frames to prevent bits just going to waste.
if (cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER)
{
// Note that the use of >= here elliminates the risk of a devide by 0 error in the else if clause
// Note that the use of >= here elliminates the risk of a devide
// by 0 error in the else if clause
if (cpi->buffer_level >= cpi->oxcf.maximum_buffer_size)
cpi->active_best_quality = cpi->best_quality;
@ -3654,6 +3662,20 @@ static void encode_frame_to_data_rate
}
}
}
// Make sure constrained quality mode limits are adhered to for the first
// few frames of one pass encodes
else if (cpi->oxcf.end_usage == USAGE_CONSTRAINED_QUALITY)
{
if ( (cm->frame_type == KEY_FRAME) ||
cm->refresh_golden_frame || cpi->common.refresh_alt_ref_frame )
{
cpi->active_best_quality = cpi->best_quality;
}
else if (cpi->active_best_quality < cpi->cq_target_quality)
{
cpi->active_best_quality = cpi->cq_target_quality;
}
}
// Clip the active best and worst quality values to limits
if (cpi->active_worst_quality > cpi->worst_quality)

View File

@ -842,7 +842,8 @@ void vp8_calc_pframe_target_size(VP8_COMP *cpi)
{
int one_percent_bits = 1 + cpi->oxcf.optimal_buffer_level / 100;
if ((cpi->buffer_level < cpi->oxcf.optimal_buffer_level) || (cpi->bits_off_target < cpi->oxcf.optimal_buffer_level))
if ((cpi->buffer_level < cpi->oxcf.optimal_buffer_level) ||
(cpi->bits_off_target < cpi->oxcf.optimal_buffer_level))
{
int percent_low = 0;
@ -851,9 +852,12 @@ void vp8_calc_pframe_target_size(VP8_COMP *cpi)
// If we are are below the optimal buffer fullness level and adherence
// to buffering contraints is important to the end useage then adjust
// the per frame target.
if ((cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER) && (cpi->buffer_level < cpi->oxcf.optimal_buffer_level))
if ((cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER) &&
(cpi->buffer_level < cpi->oxcf.optimal_buffer_level))
{
percent_low = (cpi->oxcf.optimal_buffer_level - cpi->buffer_level) / one_percent_bits;
percent_low =
(cpi->oxcf.optimal_buffer_level - cpi->buffer_level) /
one_percent_bits;
if (percent_low > 100)
percent_low = 100;
@ -864,7 +868,8 @@ void vp8_calc_pframe_target_size(VP8_COMP *cpi)
else if (cpi->bits_off_target < 0)
{
// Adjust per frame data target downwards to compensate.
percent_low = (int)(100 * -cpi->bits_off_target / (cpi->total_byte_count * 8));
percent_low = (int)(100 * -cpi->bits_off_target /
(cpi->total_byte_count * 8));
if (percent_low > 100)
percent_low = 100;
@ -873,39 +878,60 @@ void vp8_calc_pframe_target_size(VP8_COMP *cpi)
}
// lower the target bandwidth for this frame.
cpi->this_frame_target = (cpi->this_frame_target * (100 - (percent_low / 2))) / 100;
cpi->this_frame_target =
(cpi->this_frame_target * (100 - (percent_low / 2))) / 100;
// Are we using allowing control of active_worst_allowed_q according to buffer level.
// Are we using allowing control of active_worst_allowed_q
// according to buffer level.
if (cpi->auto_worst_q)
{
int critical_buffer_level;
// For streaming applications the most important factor is cpi->buffer_level as this takes
// into account the specified short term buffering constraints. However, hitting the long
// term clip data rate target is also important.
// For streaming applications the most important factor is
// cpi->buffer_level as this takes into account the
// specified short term buffering constraints. However,
// hitting the long term clip data rate target is also
// important.
if (cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER)
{
// Take the smaller of cpi->buffer_level and cpi->bits_off_target
critical_buffer_level = (cpi->buffer_level < cpi->bits_off_target) ? cpi->buffer_level : cpi->bits_off_target;
// Take the smaller of cpi->buffer_level and
// cpi->bits_off_target
critical_buffer_level =
(cpi->buffer_level < cpi->bits_off_target)
? cpi->buffer_level : cpi->bits_off_target;
}
// For local file playback short term buffering contraints are less of an issue
// For local file playback short term buffering contraints
// are less of an issue
else
{
// Consider only how we are doing for the clip as a whole
// Consider only how we are doing for the clip as a
// whole
critical_buffer_level = cpi->bits_off_target;
}
// Set the active worst quality based upon the selected buffer fullness number.
// Set the active worst quality based upon the selected
// buffer fullness number.
if (critical_buffer_level < cpi->oxcf.optimal_buffer_level)
{
if (critical_buffer_level > (cpi->oxcf.optimal_buffer_level / 4))
if ( critical_buffer_level >
(cpi->oxcf.optimal_buffer_level >> 2) )
{
int qadjustment_range = cpi->worst_quality - cpi->ni_av_qi;
int above_base = (critical_buffer_level - (cpi->oxcf.optimal_buffer_level / 4));
INT64 qadjustment_range =
cpi->worst_quality - cpi->ni_av_qi;
INT64 above_base =
(critical_buffer_level -
(cpi->oxcf.optimal_buffer_level >> 2));
// Step active worst quality down from cpi->ni_av_qi when (critical_buffer_level == cpi->optimal_buffer_level)
// to cpi->oxcf.worst_allowed_q when (critical_buffer_level == cpi->optimal_buffer_level/4)
cpi->active_worst_quality = cpi->worst_quality - ((qadjustment_range * above_base) / (cpi->oxcf.optimal_buffer_level * 3 / 4));
// Step active worst quality down from
// cpi->ni_av_qi when (critical_buffer_level ==
// cpi->optimal_buffer_level) to
// cpi->worst_quality when
// (critical_buffer_level ==
// cpi->optimal_buffer_level >> 2)
cpi->active_worst_quality =
cpi->worst_quality -
((qadjustment_range * above_base) /
(cpi->oxcf.optimal_buffer_level*3>>2));
}
else
{
@ -965,6 +991,15 @@ void vp8_calc_pframe_target_size(VP8_COMP *cpi)
// Set the active worst quality
cpi->active_worst_quality = cpi->worst_quality;
}
// Special trap for constrained quality mode
// "active_worst_quality" may never drop below cq level
// for any frame type.
if ( cpi->oxcf.end_usage == USAGE_CONSTRAINED_QUALITY &&
cpi->active_worst_quality < cpi->cq_target_quality)
{
cpi->active_worst_quality = cpi->cq_target_quality;
}
}
// Test to see if we have to drop a frame