Some further QIndex issues with extended Q

Resolved or factored out some further issues with Q index.
Put in a 3rd order polynomial instead of less accurate power function
as the best fit on gf and kf boost adjustment.
Added avg_q value to use instead of ni_av_qi.
Compute segment delta Q values based on avg_q.
Fixed bug in adjust_maxq_qrange().

The extended range Q on the derf set, using standard data rates
(which do not extend high enough to get big benefits) still show
a shortfall of between 0.5 and 1% though so there would appear to
be further issues that need to be tracked down.

Change-Id: Icfd49b9f401906ba487ef1bef7d397048295d959
This commit is contained in:
Paul Wilkins 2011-12-06 14:48:52 +00:00
parent 82d99257f2
commit b4ad9b5d50
5 changed files with 130 additions and 38 deletions

View File

@ -898,7 +898,7 @@ static double calc_correction_factor( double err_per_mb,
double correction_factor;
// Adjustment based on actual quantizer to power term.
power_term = (vp8_convert_qindex_to_q(Q) * 0.01) + 0.36;
power_term = (vp8_convert_qindex_to_q(Q) * 0.01) + pt_low;
power_term = (power_term > pt_high) ? pt_high : power_term;
// Adjustments to error term
@ -919,29 +919,29 @@ static double calc_correction_factor( double err_per_mb,
// PGW TODO..
// This code removes direct dependency on QIndex to determin the range
// (now uses the actual quantizer) but has not been tuned.
static double adjust_maxq_qrange(VP8_COMP *cpi, int qindex )
static double adjust_maxq_qrange(VP8_COMP *cpi)
{
int i;
double q = vp8_convert_qindex_to_q(qindex);
double q;
// Set the max corresponding to real q * 2.0
// Set the max corresponding to cpi->avg_q * 2.0
q = cpi->avg_q * 2.0;
cpi->twopass.maxq_max_limit = cpi->worst_quality;
for ( i = qindex; i < cpi->worst_quality; i++ )
for ( i = cpi->best_quality; i <= cpi->worst_quality; i++ )
{
if ( vp8_convert_qindex_to_q(qindex) >= (q * 2.0) )
{
cpi->twopass.maxq_max_limit = i;
}
cpi->twopass.maxq_max_limit = i;
if ( vp8_convert_qindex_to_q(i) >= q )
break;
}
// Set the min corresponding to real q * 0.5
// Set the min corresponding to cpi->avg_q * 0.5
q = cpi->avg_q * 0.5;
cpi->twopass.maxq_min_limit = cpi->best_quality;
for ( i = qindex; i > cpi->best_quality; i-- )
for ( i = cpi->worst_quality; i >= cpi->best_quality; i-- )
{
if ( vp8_convert_qindex_to_q(qindex) <= (q * 0.5) )
{
cpi->twopass.maxq_min_limit = i;
}
cpi->twopass.maxq_min_limit = i;
if ( vp8_convert_qindex_to_q(i) <= q )
break;
}
}
@ -1018,7 +1018,7 @@ static int estimate_max_q(VP8_COMP *cpi,
// Error per MB based correction factor
err_correction_factor =
calc_correction_factor(err_per_mb, 150.0, 0.40, 0.90, Q);
calc_correction_factor(err_per_mb, 150.0, 0.36, 0.90, Q);
bits_per_mb_at_this_q =
vp8_bits_per_mb(INTER_FRAME, Q) + overhead_bits_per_mb;
@ -1054,7 +1054,7 @@ static int estimate_max_q(VP8_COMP *cpi,
((unsigned int)cpi->twopass.total_stats->count >> 8)) &&
(cpi->ni_frames > 150) )
{
adjust_maxq_qrange( cpi, cpi->ni_av_qi );
adjust_maxq_qrange( cpi );
}
return Q;
@ -1120,7 +1120,7 @@ static int estimate_cq( VP8_COMP *cpi,
// Error per MB based correction factor
err_correction_factor =
calc_correction_factor(err_per_mb, 100.0, 0.40, 0.90, Q);
calc_correction_factor(err_per_mb, 100.0, 0.36, 0.90, Q);
bits_per_mb_at_this_q =
vp8_bits_per_mb(INTER_FRAME, Q) + overhead_bits_per_mb;
@ -1181,7 +1181,7 @@ static int estimate_q(VP8_COMP *cpi, double section_err, int section_target_band
// Error per MB based correction factor
err_correction_factor =
calc_correction_factor(err_per_mb, 150.0, 0.40, 0.90, Q);
calc_correction_factor(err_per_mb, 150.0, 0.36, 0.90, Q);
bits_per_mb_at_this_q =
(int)( .5 + ( err_correction_factor *
@ -2329,6 +2329,46 @@ static void assign_std_frame_bits(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame)
cpi->per_frame_bandwidth = target_frame_size; // Per frame bit target for this frame
}
// Make a damped adjustment to the active max q.
int adjust_active_maxq( int old_maxqi, int new_maxqi )
{
int i;
int ret_val = new_maxqi;
double old_q;
double new_q;
double target_q;
old_q = vp8_convert_qindex_to_q( old_maxqi );
new_q = vp8_convert_qindex_to_q( new_maxqi );
target_q = ((old_q * 7.0) + new_q) / 8.0;
if ( target_q > old_q )
{
for ( i = old_maxqi; i <= new_maxqi; i++ )
{
if ( vp8_convert_qindex_to_q( i ) >= target_q )
{
ret_val = i;
break;
}
}
}
else
{
for ( i = old_maxqi; i >= new_maxqi; i-- )
{
if ( vp8_convert_qindex_to_q( i ) <= target_q )
{
ret_val = i;
break;
}
}
}
return ret_val;
}
void vp8_second_pass(VP8_COMP *cpi)
{
int tmp_q;
@ -2480,15 +2520,16 @@ void vp8_second_pass(VP8_COMP *cpi)
(int)(cpi->twopass.bits_left / frames_left),
overhead_bits );
cpi->active_worst_quality = tmp_q;
cpi->ni_av_qi = tmp_q;
cpi->avg_q = vp8_convert_qindex_to_q( tmp_q );
// Limit the maxq value returned subsequently.
// This increases the risk of overspend or underspend if the initial
// estimate for the clip is bad, but helps prevent excessive
// variation in Q, especially near the end of a clip
// where for example a small overspend may cause Q to crash
adjust_maxq_qrange(cpi, tmp_q);
cpi->active_worst_quality = tmp_q;
cpi->ni_av_qi = tmp_q;
adjust_maxq_qrange(cpi);
}
// The last few frames of a clip almost always have to few or too many
@ -2509,14 +2550,9 @@ void vp8_second_pass(VP8_COMP *cpi)
(int)(cpi->twopass.bits_left / frames_left),
overhead_bits );
// Move active_worst_quality but in a damped way
if (tmp_q > cpi->active_worst_quality)
cpi->active_worst_quality ++;
else if (tmp_q < cpi->active_worst_quality)
cpi->active_worst_quality --;
// Make a damped adjustment to active max Q
cpi->active_worst_quality =
((cpi->active_worst_quality * 3) + tmp_q + 2) / 4;
adjust_active_maxq( cpi->active_worst_quality, tmp_q );
}
cpi->twopass.frames_to_key --;

View File

@ -416,13 +416,43 @@ static void segmentation_test_function(VP8_PTR ptr)
}
// Computes a q delta (in "q index" terms) to get from a starting q value
// to a target value
// target q value
static int compute_qdelta( VP8_COMP *cpi, double qstart, double qtarget )
{
int i;
int start_index = cpi->worst_quality;
int target_index = cpi->worst_quality;
int retval = 0;
// Convert the average q value to an index.
for ( i = cpi->best_quality; i < cpi->worst_quality; i++ )
{
start_index = i;
if ( vp8_convert_qindex_to_q(i) >= qstart )
break;
}
// Convert the q target to an index
for ( i = cpi->best_quality; i < cpi->worst_quality; i++ )
{
target_index = i;
if ( vp8_convert_qindex_to_q(i) >= qtarget )
break;
}
return target_index - start_index;
}
//#if CONFIG_SEGFEATURES
static void init_seg_features(VP8_COMP *cpi)
{
VP8_COMMON *cm = &cpi->common;
MACROBLOCKD *xd = &cpi->mb.e_mbd;
int high_q = ((int)vp8_convert_qindex_to_q(cpi->ni_av_qi) > 32);
int high_q = (int)(cpi->avg_q > 32.0);
int qi_delta;
// For now at least dont enable seg features alongside cyclic refresh.
if ( cpi->cyclic_refresh_mode_enabled ||
@ -471,7 +501,8 @@ static void init_seg_features(VP8_COMP *cpi)
xd->update_mb_segmentation_map = 1;
xd->update_mb_segmentation_data = 1;
set_segdata( xd, 1, SEG_LVL_ALT_Q, -(3+(cpi->ni_av_qi >> 3)) );
qi_delta = compute_qdelta( cpi, cpi->avg_q, (cpi->avg_q * 0.875) );
set_segdata( xd, 1, SEG_LVL_ALT_Q, (qi_delta - 2) );
set_segdata( xd, 1, SEG_LVL_ALT_LF, -2 );
enable_segfeature(xd, 1, SEG_LVL_ALT_Q);
@ -495,7 +526,10 @@ static void init_seg_features(VP8_COMP *cpi)
xd->update_mb_segmentation_data = 1;
xd->mb_segement_abs_delta = SEGMENT_DELTADATA;
set_segdata( xd, 1, SEG_LVL_ALT_Q, 5 );
qi_delta = compute_qdelta( cpi, cpi->avg_q,
(cpi->avg_q * 1.125) );
set_segdata( xd, 1, SEG_LVL_ALT_Q, (qi_delta + 2) );
set_segdata( xd, 1, SEG_LVL_ALT_Q, 0 );
enable_segfeature(xd, 1, SEG_LVL_ALT_Q);
set_segdata( xd, 1, SEG_LVL_ALT_LF, -2 );
@ -2242,6 +2276,8 @@ VP8_PTR vp8_create_compressor(VP8_CONFIG *oxcf)
cpi->ni_av_qi = cpi->oxcf.worst_allowed_q;
cpi->ni_tot_qi = 0;
cpi->ni_frames = 0;
cpi->tot_q = 0.0;
cpi->avg_q = vp8_convert_qindex_to_q( cpi->oxcf.worst_allowed_q );
cpi->total_byte_count = 0;
cpi->drop_frame = 0;
@ -4601,6 +4637,8 @@ static void encode_frame_to_data_rate
if ((cm->frame_type != KEY_FRAME) && !cm->refresh_golden_frame && !cm->refresh_alt_ref_frame)
{
cpi->ni_frames++;
cpi->tot_q += vp8_convert_qindex_to_q(Q);
cpi->avg_q = cpi->tot_q / (double)cpi->ni_frames;
// Calculate the average Q for normal inter frames (not key or GFU
// frames).
@ -4732,7 +4770,7 @@ static void encode_frame_to_data_rate
if (cpi->twopass.total_left_stats->coded_error != 0.0)
fprintf(f, "%10d %10d %10d %10d %10d %10d %10d"
"%6.2f %6.2f %6.2f %6.2f %6.2f %6.2f"
"%6.2f %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f"
"%6d %5d %5d %5d %8d %8.2f %10d %10.3f"
"%10.3f %8d\n",
cpi->common.current_video_frame, cpi->this_frame_target,
@ -4749,6 +4787,7 @@ static void encode_frame_to_data_rate
#endif
vp8_convert_qindex_to_q(cpi->active_best_quality),
vp8_convert_qindex_to_q(cpi->active_worst_quality),
cpi->avg_q,
vp8_convert_qindex_to_q(cpi->ni_av_qi),
vp8_convert_qindex_to_q(cpi->cq_target_quality),
cpi->zbin_over_quant,
@ -4763,7 +4802,7 @@ static void encode_frame_to_data_rate
cpi->tot_recode_hits);
else
fprintf(f, "%10d %10d %10d %10d %10d %10d %10d"
"%6.2f %6.2f %6.2f %6.2f %6.2f %6.2f"
"%6.2f %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f"
"%6d %5d %5d %5d %8d %8.2f %10d %10.3f"
"%8d\n",
cpi->common.current_video_frame,
@ -4780,6 +4819,7 @@ static void encode_frame_to_data_rate
#endif
vp8_convert_qindex_to_q(cpi->active_best_quality),
vp8_convert_qindex_to_q(cpi->active_worst_quality),
cpi->avg_q,
vp8_convert_qindex_to_q(cpi->ni_av_qi),
vp8_convert_qindex_to_q(cpi->cq_target_quality),
cpi->zbin_over_quant,

View File

@ -391,6 +391,8 @@ typedef struct VP8_COMP
int ni_tot_qi;
int ni_frames;
int avg_frame_qindex;
double tot_q;
double avg_q;
int zbin_over_quant;
int zbin_mode_boost;

View File

@ -125,12 +125,26 @@ double vp8_convert_qindex_to_q( int qindex )
int vp8_gfboost_qadjust( int qindex )
{
return (50.0 * pow(vp8_convert_qindex_to_q(qindex), 0.25) + 0.5);
int retval;
double q;
q = vp8_convert_qindex_to_q(qindex);
retval = (int)( ( 0.00000828 * q * q * q ) +
( -0.0055 * q * q ) +
( 1.32 * q ) + 79.3 );
return retval;
}
int kfboost_qadjust( int qindex )
{
return (91.0 * pow(vp8_convert_qindex_to_q(qindex), 0.165) + 0.5);
int retval;
double q;
q = vp8_convert_qindex_to_q(qindex);
retval = (int)( ( 0.00000973 * q * q * q ) +
( -0.00613 * q * q ) +
( 1.316 * q ) + 121.2 );
return retval;
}
int vp8_bits_per_mb( FRAME_TYPE frame_type, int qindex )

View File

@ -253,7 +253,7 @@ void vp8_initialize_rd_consts(VP8_COMP *cpi, int QIndex)
#if CONFIG_EXTEND_QRANGE
q = (int)pow(vp8_dc_quant(QIndex,0)>>2, 1.25);
q = q << 2;
cpi->RDMULT *= 16;
cpi->RDMULT = cpi->RDMULT << 4;
#else
q = (int)pow(vp8_dc_quant(QIndex,0), 1.25);
#endif