diff --git a/vp8/encoder/firstpass.c b/vp8/encoder/firstpass.c index bdddc2219..3295cea22 100644 --- a/vp8/encoder/firstpass.c +++ b/vp8/encoder/firstpass.c @@ -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 --; diff --git a/vp8/encoder/onyx_if.c b/vp8/encoder/onyx_if.c index 4a6b7617d..126a2db5e 100644 --- a/vp8/encoder/onyx_if.c +++ b/vp8/encoder/onyx_if.c @@ -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, diff --git a/vp8/encoder/onyx_int.h b/vp8/encoder/onyx_int.h index 160f22d05..38025cad5 100644 --- a/vp8/encoder/onyx_int.h +++ b/vp8/encoder/onyx_int.h @@ -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; diff --git a/vp8/encoder/ratectrl.c b/vp8/encoder/ratectrl.c index de6ccaf0f..2ab16ed11 100644 --- a/vp8/encoder/ratectrl.c +++ b/vp8/encoder/ratectrl.c @@ -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 ) diff --git a/vp8/encoder/rdopt.c b/vp8/encoder/rdopt.c index 00a395845..8be284965 100644 --- a/vp8/encoder/rdopt.c +++ b/vp8/encoder/rdopt.c @@ -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