From: Paul Wilkins Date: Wed, 23 Nov 2011 17:18:31 +0000 (+0000) Subject: Two pass rate control code changes. X-Git-Tag: v1.3.0~1217^2~380^2~143 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=ee2051f6500cf2a576a50f966c5e43df42430f86;p=libvpx Two pass rate control code changes. This comitt brings accross changes from the public branch commit number Icf74d13af77437c08602571dc7a97e747cce5066. The main puurpose of this comit relates to CQ mode but it also includes some refactoring of the two pass code which I hope will make tuning the experimental branch for the new quantizer range a little less painfull. Change-Id: I278e989436a928fc1fe7761068960048f9d7a376 --- diff --git a/vp8/encoder/firstpass.c b/vp8/encoder/firstpass.c index 35adb9d10..4f3b75ce2 100644 --- a/vp8/encoder/firstpass.c +++ b/vp8/encoder/firstpass.c @@ -146,7 +146,7 @@ static void output_stats(const VP8_COMP *cpi, fprintf(fpfile, "%12.0f %12.0f %12.0f %12.4f %12.4f %12.4f %12.4f" " %12.4f %12.4f %12.4f %12.4f %12.4f %12.4f %12.4f %12.4f" - " %12.0f %12.4f\n", + " %12.0f %12.0f %12.4f\n", stats->frame, stats->intra_error, stats->coded_error, @@ -162,6 +162,7 @@ static void output_stats(const VP8_COMP *cpi, stats->MVrv, stats->MVcv, stats->mv_in_out_count, + stats->new_mv_count, stats->count, stats->duration); fclose(fpfile); @@ -186,6 +187,7 @@ static void zero_stats(FIRSTPASS_STATS *section) section->MVrv = 0.0; section->MVcv = 0.0; section->mv_in_out_count = 0.0; + section->new_mv_count = 0.0; section->count = 0.0; section->duration = 1.0; } @@ -207,10 +209,33 @@ static void accumulate_stats(FIRSTPASS_STATS *section, FIRSTPASS_STATS *frame) section->MVrv += frame->MVrv; section->MVcv += frame->MVcv; section->mv_in_out_count += frame->mv_in_out_count; + section->new_mv_count += frame->new_mv_count; section->count += frame->count; section->duration += frame->duration; } +static void subtract_stats(FIRSTPASS_STATS *section, FIRSTPASS_STATS *frame) +{ + section->frame -= frame->frame; + section->intra_error -= frame->intra_error; + section->coded_error -= frame->coded_error; + section->ssim_weighted_pred_err -= frame->ssim_weighted_pred_err; + section->pcnt_inter -= frame->pcnt_inter; + section->pcnt_motion -= frame->pcnt_motion; + section->pcnt_second_ref -= frame->pcnt_second_ref; + section->pcnt_neutral -= frame->pcnt_neutral; + section->MVr -= frame->MVr; + section->mvr_abs -= frame->mvr_abs; + section->MVc -= frame->MVc; + section->mvc_abs -= frame->mvc_abs; + section->MVrv -= frame->MVrv; + section->MVcv -= frame->MVcv; + section->mv_in_out_count -= frame->mv_in_out_count; + section->new_mv_count -= frame->new_mv_count; + section->count -= frame->count; + section->duration -= frame->duration; +} + static void avg_stats(FIRSTPASS_STATS *section) { if (section->count < 1.0) @@ -236,49 +261,16 @@ static void avg_stats(FIRSTPASS_STATS *section) // Calculate a modified Error used in distributing bits between easier and harder frames static double calculate_modified_err(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame) { - double av_err = cpi->twopass.total_stats->ssim_weighted_pred_err; + double av_err = ( cpi->twopass.total_stats->ssim_weighted_pred_err / + cpi->twopass.total_stats->count ); double this_err = this_frame->ssim_weighted_pred_err; double modified_err; - //double relative_next_iiratio; - //double next_iiratio; - //double sum_iiratio; - //int i; - - //FIRSTPASS_STATS next_frame; - //FIRSTPASS_STATS *start_pos; - - /*start_pos = cpi->twopass.stats_in; - sum_iiratio = 0.0; - i = 0; - while ( (i < 1) && input_stats(cpi,&next_frame) != EOF ) - { - - next_iiratio = next_frame.intra_error / DOUBLE_DIVIDE_CHECK(next_frame.coded_error); - next_iiratio = ( next_iiratio < 1.0 ) ? 1.0 : (next_iiratio > 20.0) ? 20.0 : next_iiratio; - sum_iiratio += next_iiratio; - i++; - } - if ( i > 0 ) - { - relative_next_iiratio = sum_iiratio / DOUBLE_DIVIDE_CHECK(cpi->twopass.avg_iiratio * (double)i); - } - else - { - relative_next_iiratio = 1.0; - } - reset_fpf_position(cpi, start_pos);*/ - if (this_err > av_err) modified_err = av_err * pow((this_err / DOUBLE_DIVIDE_CHECK(av_err)), POW1); else modified_err = av_err * pow((this_err / DOUBLE_DIVIDE_CHECK(av_err)), POW2); - /* - relative_next_iiratio = pow(relative_next_iiratio,0.25); - modified_err = modified_err * relative_next_iiratio; - */ - return modified_err; } @@ -510,8 +502,9 @@ void vp8_first_pass(VP8_COMP *cpi) int second_ref_count = 0; int intrapenalty = 256; int neutral_count = 0; - + int new_mv_count = 0; int sum_in_vectors = 0; + uint32_t lastmv_as_int = 0; int_mv zero_ref_mv; @@ -542,7 +535,7 @@ void vp8_first_pass(VP8_COMP *cpi) //if ( 0 ) { int flag[2] = {1, 1}; - vp8_initialize_rd_consts(cpi, cm->base_qindex+cm->y1dc_delta_q); + vp8_initialize_rd_consts(cpi, vp8_dc_quant(cm->base_qindex, cm->y1dc_delta_q)); vpx_memcpy(cm->fc.mvc, vp8_default_mv_context, sizeof(vp8_default_mv_context)); vp8_build_component_cost_table(cpi->mb.mvcost, (const MV_CONTEXT *) cm->fc.mvc, flag); } @@ -691,6 +684,11 @@ void vp8_first_pass(VP8_COMP *cpi) { mvcount++; + // Was it different from the last non zero vector + if ( d->bmi.mv.as_int != lastmv_as_int ) + new_mv_count++; + lastmv_as_int = d->bmi.mv.as_int; + // Does the Row vector point inwards or outwards if (mb_row < cm->mb_rows / 2) { @@ -788,6 +786,7 @@ void vp8_first_pass(VP8_COMP *cpi) fps.MVrv = ((double)sum_mvrs - (fps.MVr * fps.MVr / (double)mvcount)) / (double)mvcount; fps.MVcv = ((double)sum_mvcs - (fps.MVc * fps.MVc / (double)mvcount)) / (double)mvcount; fps.mv_in_out_count = (double)sum_in_vectors / (double)(mvcount * 2); + fps.new_mv_count = new_mv_count; fps.pcnt_motion = 1.0 * (double)mvcount / cpi->common.MBs; } @@ -844,42 +843,117 @@ void vp8_first_pass(VP8_COMP *cpi) } -#define BASE_ERRPERMB 150 -static int estimate_max_q(VP8_COMP *cpi, double section_err, int section_target_bandwitdh) +// Estimate a cost per mb attributable to overheads such as the coding of +// modes and motion vectors. +// Currently simplistic in its assumptions for testing. +// + + +double bitcost( double prob ) +{ + return -(log( prob ) / log( 2.0 )); +} +static long long estimate_modemvcost(VP8_COMP *cpi, + FIRSTPASS_STATS * fpstats) +{ + int mv_cost; + int mode_cost; + + double av_pct_inter = fpstats->pcnt_inter / fpstats->count; + double av_pct_motion = fpstats->pcnt_motion / fpstats->count; + double av_intra = (1.0 - av_pct_inter); + + double zz_cost; + double motion_cost; + double intra_cost; + + zz_cost = bitcost(av_pct_inter - av_pct_motion); + motion_cost = bitcost(av_pct_motion); + intra_cost = bitcost(av_intra); + + // Estimate of extra bits per mv overhead for mbs + // << 9 is the normalization to the (bits * 512) used in vp8_bits_per_mb + mv_cost = ((int)(fpstats->new_mv_count / fpstats->count) * 8) << 9; + + // Crude estimate of overhead cost from modes + // << 9 is the normalization to (bits * 512) used in vp8_bits_per_mb + mode_cost = + (int)( ( ((av_pct_inter - av_pct_motion) * zz_cost) + + (av_pct_motion * motion_cost) + + (av_intra * intra_cost) ) * cpi->common.MBs ) << 9; + + return mv_cost + mode_cost; +} + +static double calc_correction_factor( double err_per_mb, + double err_devisor, + double pt_low, + double pt_high, + int Q ) +{ + double power_term; + double error_term = err_per_mb / err_devisor; + double correction_factor; + + // Adjustment based on Q to power term. + power_term = pt_low + (Q * 0.01); + power_term = (power_term > pt_high) ? pt_high : power_term; + + // Adjustments to error term + // TBD + + // Calculate correction factor + correction_factor = pow(error_term, power_term); + + // Clip range + correction_factor = + (correction_factor < 0.05) + ? 0.05 : (correction_factor > 5.0) ? 5.0 : correction_factor; + + return correction_factor; +} + +static int estimate_max_q(VP8_COMP *cpi, + FIRSTPASS_STATS * fpstats, + int section_target_bandwitdh, + int overhead_bits ) { int Q; int num_mbs = cpi->common.MBs; int target_norm_bits_per_mb; + double section_err = (fpstats->coded_error / fpstats->count); double err_per_mb = section_err / num_mbs; - double correction_factor; + double err_correction_factor; double corr_high; double speed_correction = 1.0; - double pow_highq = 0.90; - double pow_lowq = 0.40; + double inter_pct = (fpstats->pcnt_inter / fpstats->count); + double intra_pct = 1.0 - inter_pct; + int overhead_bits_per_mb; if (section_target_bandwitdh <= 0) return cpi->twopass.maxq_max_limit; // Highest value allowed - target_norm_bits_per_mb = (section_target_bandwitdh < (1 << 20)) ? (512 * section_target_bandwitdh) / num_mbs : 512 * (section_target_bandwitdh / num_mbs); + target_norm_bits_per_mb = + (section_target_bandwitdh < (1 << 20)) + ? (512 * section_target_bandwitdh) / num_mbs + : 512 * (section_target_bandwitdh / num_mbs); - // Calculate a corrective factor based on a rolling ratio of bits spent vs target bits - if ((cpi->rolling_target_bits > 0) && (cpi->active_worst_quality < cpi->worst_quality)) + // Calculate a corrective factor based on a rolling ratio of bits spent + // vs target bits + if ((cpi->rolling_target_bits > 0) && + (cpi->active_worst_quality < cpi->worst_quality)) { double rolling_ratio; - rolling_ratio = (double)cpi->rolling_actual_bits / (double)cpi->rolling_target_bits; + rolling_ratio = (double)cpi->rolling_actual_bits / + (double)cpi->rolling_target_bits; - //if ( cpi->twopass.est_max_qcorrection_factor > rolling_ratio ) if (rolling_ratio < 0.95) - //cpi->twopass.est_max_qcorrection_factor *= adjustment_rate; cpi->twopass.est_max_qcorrection_factor -= 0.005; - //else if ( cpi->twopass.est_max_qcorrection_factor < rolling_ratio ) else if (rolling_ratio > 1.05) cpi->twopass.est_max_qcorrection_factor += 0.005; - //cpi->twopass.est_max_qcorrection_factor /= adjustment_rate; - cpi->twopass.est_max_qcorrection_factor = (cpi->twopass.est_max_qcorrection_factor < 0.1) ? 0.1 @@ -887,7 +961,8 @@ static int estimate_max_q(VP8_COMP *cpi, double section_err, int section_target_ ? 10.0 : cpi->twopass.est_max_qcorrection_factor; } - // Corrections for higher compression speed settings (reduced compression expected) + // Corrections for higher compression speed settings + // (reduced compression expected) if ((cpi->compressor_speed == 3) || (cpi->compressor_speed == 1)) { if (cpi->oxcf.cpu_used <= 5) @@ -896,10 +971,10 @@ static int estimate_max_q(VP8_COMP *cpi, double section_err, int section_target_ speed_correction = 1.25; } - // Correction factor used for Q values >= 20 - corr_high = pow(err_per_mb / BASE_ERRPERMB, pow_highq); - corr_high = (corr_high < 0.05) - ? 0.05 : (corr_high > 5.0) ? 5.0 : corr_high; + // Estimate of overhead bits per mb + // Correction to overhead bits for min allowed Q. + overhead_bits_per_mb = overhead_bits / num_mbs; + overhead_bits_per_mb *= pow( 0.98, (double)cpi->twopass.maxq_min_limit ); // Try and pick a max Q that will be high enough to encode the // content at the given rate. @@ -907,18 +982,22 @@ static int estimate_max_q(VP8_COMP *cpi, double section_err, int section_target_ { int bits_per_mb_at_this_q; - if (Q < 50) - { - correction_factor = pow(err_per_mb / BASE_ERRPERMB, (pow_lowq + Q * 0.01)); - correction_factor = (correction_factor < 0.05) ? 0.05 : (correction_factor > 5.0) ? 5.0 : correction_factor; - } - else - correction_factor = corr_high; + // Error per MB based correction factor + err_correction_factor = + calc_correction_factor(err_per_mb, 150.0, 0.40, 0.90, Q); + + bits_per_mb_at_this_q = + vp8_bits_per_mb(INTER_FRAME, Q) + overhead_bits_per_mb; - bits_per_mb_at_this_q = (int)(.5 + correction_factor + bits_per_mb_at_this_q = (int)(.5 + err_correction_factor * speed_correction * cpi->twopass.est_max_qcorrection_factor * cpi->twopass.section_max_qfactor - * (double)vp8_bits_per_mb(INTER_FRAME,Q) / 1.0); + * (double)bits_per_mb_at_this_q); + + // Mode and motion overhead + // As Q rises in real encode loop rd code will force overhead down + // We make a crude adjustment for this here as *.98 per Q step. + overhead_bits_per_mb = (int)((double)overhead_bits_per_mb * 0.98); if (bits_per_mb_at_this_q <= target_norm_bits_per_mb) break; @@ -927,10 +1006,8 @@ static int estimate_max_q(VP8_COMP *cpi, double section_err, int section_target_ // Restriction on active max q for constrained quality mode. if ( (cpi->oxcf.end_usage == USAGE_CONSTRAINED_QUALITY) && (Q < cpi->cq_target_quality) ) - //(Q < cpi->oxcf.cq_level;) ) { Q = cpi->cq_target_quality; - //Q = cpi->oxcf.cq_level; } // Adjust maxq_min_limit and maxq_max_limit limits based on @@ -948,6 +1025,97 @@ static int estimate_max_q(VP8_COMP *cpi, double section_err, int section_target_ return Q; } + +// For cq mode estimate a cq level that matches the observed +// complexity and data rate. +static int estimate_cq( VP8_COMP *cpi, + FIRSTPASS_STATS * fpstats, + int section_target_bandwitdh, + int overhead_bits ) +{ + int Q; + int num_mbs = cpi->common.MBs; + int target_norm_bits_per_mb; + + double section_err = (fpstats->coded_error / fpstats->count); + double err_per_mb = section_err / num_mbs; + double err_correction_factor; + double corr_high; + double speed_correction = 1.0; + double clip_iiratio; + double clip_iifactor; + double inter_pct = (fpstats->pcnt_inter / fpstats->count); + double intra_pct = 1.0 - inter_pct; + int overhead_bits_per_mb; + + if (0) + { + FILE *f = fopen("epmp.stt", "a"); + fprintf(f, "%10.2f\n", err_per_mb ); + fclose(f); + } + + target_norm_bits_per_mb = (section_target_bandwitdh < (1 << 20)) + ? (512 * section_target_bandwitdh) / num_mbs + : 512 * (section_target_bandwitdh / num_mbs); + + // Estimate of overhead bits per mb + overhead_bits_per_mb = overhead_bits / num_mbs; + + // Corrections for higher compression speed settings + // (reduced compression expected) + if ((cpi->compressor_speed == 3) || (cpi->compressor_speed == 1)) + { + if (cpi->oxcf.cpu_used <= 5) + speed_correction = 1.04 + (cpi->oxcf.cpu_used * 0.04); + else + speed_correction = 1.25; + } + + // II ratio correction factor for clip as a whole + clip_iiratio = cpi->twopass.total_stats->intra_error / + DOUBLE_DIVIDE_CHECK(cpi->twopass.total_stats->coded_error); + clip_iifactor = 1.0 - ((clip_iiratio - 10.0) * 0.025); + if (clip_iifactor < 0.80) + clip_iifactor = 0.80; + + // Try and pick a Q that can encode the content at the given rate. + for (Q = 0; Q < MAXQ; Q++) + { + int bits_per_mb_at_this_q; + + // Error per MB based correction factor + err_correction_factor = + calc_correction_factor(err_per_mb, 100.0, 0.40, 0.90, Q); + + bits_per_mb_at_this_q = + vp8_bits_per_mb(INTER_FRAME, Q) + overhead_bits_per_mb; + + bits_per_mb_at_this_q = + (int)( .5 + err_correction_factor * + speed_correction * + clip_iifactor * + (double)bits_per_mb_at_this_q); + + // Mode and motion overhead + // As Q rises in real encode loop rd code will force overhead down + // We make a crude adjustment for this here as *.98 per Q step. + overhead_bits_per_mb = (int)((double)overhead_bits_per_mb * 0.98); + + if (bits_per_mb_at_this_q <= target_norm_bits_per_mb) + break; + } + + // Clip value to range "best allowed to (worst allowed - 1)" + Q = cq_level[Q]; + if ( Q >= cpi->worst_quality ) + Q = cpi->worst_quality - 1; + if ( Q < cpi->best_quality ) + Q = cpi->best_quality; + + return Q; +} + static int estimate_q(VP8_COMP *cpi, double section_err, int section_target_bandwitdh) { int Q; @@ -955,11 +1123,9 @@ static int estimate_q(VP8_COMP *cpi, double section_err, int section_target_band int target_norm_bits_per_mb; double err_per_mb = section_err / num_mbs; - double correction_factor; + double err_correction_factor; double corr_high; double speed_correction = 1.0; - double pow_highq = 0.90; - double pow_lowq = 0.40; target_norm_bits_per_mb = (section_target_bandwitdh < (1 << 20)) ? (512 * section_target_bandwitdh) / num_mbs : 512 * (section_target_bandwitdh / num_mbs); @@ -972,28 +1138,20 @@ static int estimate_q(VP8_COMP *cpi, double section_err, int section_target_band speed_correction = 1.25; } - // Correction factor used for Q values >= 20 - corr_high = pow(err_per_mb / BASE_ERRPERMB, pow_highq); - corr_high = (corr_high < 0.05) ? 0.05 : (corr_high > 5.0) ? 5.0 : corr_high; - // Try and pick a Q that can encode the content at the given rate. for (Q = 0; Q < MAXQ; Q++) { int bits_per_mb_at_this_q; - if (Q < 50) - { - correction_factor = pow(err_per_mb / BASE_ERRPERMB, (pow_lowq + Q * 0.01)); - correction_factor = (correction_factor < 0.05) ? 0.05 : (correction_factor > 5.0) ? 5.0 : correction_factor; - } - else - correction_factor = corr_high; + // Error per MB based correction factor + err_correction_factor = + calc_correction_factor(err_per_mb, 150.0, 0.40, 0.90, Q); bits_per_mb_at_this_q = - (int)(.5 + correction_factor * - speed_correction * - cpi->twopass.est_max_qcorrection_factor * - (double)vp8_bits_per_mb(INTER_FRAME,Q) / 1.0); + (int)( .5 + ( err_correction_factor * + speed_correction * + cpi->twopass.est_max_qcorrection_factor * + (double)vp8_bits_per_mb(INTER_FRAME, Q) / 1.0 ) ); if (bits_per_mb_at_this_q <= target_norm_bits_per_mb) break; @@ -1056,26 +1214,17 @@ static int estimate_kf_group_q(VP8_COMP *cpi, double section_err, int section_ta // Combine the various factors calculated above combined_correction_factor = speed_correction * iiratio_correction_factor * current_spend_ratio; - // Correction factor used for Q values >= 20 - corr_high = pow(err_per_mb / BASE_ERRPERMB, pow_highq); - corr_high = (corr_high < 0.05) ? 0.05 : (corr_high > 5.0) ? 5.0 : corr_high; - // Try and pick a Q that should be high enough to encode the content at the given rate. for (Q = 0; Q < MAXQ; Q++) { - // Q values < 20 treated as a special case - if (Q < 20) - { - err_correction_factor = pow(err_per_mb / BASE_ERRPERMB, (pow_lowq + Q * 0.01)); - err_correction_factor = (err_correction_factor < 0.05) ? 0.05 : (err_correction_factor > 5.0) ? 5.0 : err_correction_factor; - } - else - err_correction_factor = corr_high; + // Error per MB based correction factor + err_correction_factor = + calc_correction_factor(err_per_mb, 150.0, pow_lowq, pow_highq, Q); bits_per_mb_at_this_q = - (int)(.5 + err_correction_factor * - combined_correction_factor * - (double)vp8_bits_per_mb(INTER_FRAME,Q) ); + (int)(.5 + ( err_correction_factor * + combined_correction_factor * + (double)vp8_bits_per_mb(INTER_FRAME, Q)) ); if (bits_per_mb_at_this_q <= target_norm_bits_per_mb) break; @@ -1102,77 +1251,6 @@ static int estimate_kf_group_q(VP8_COMP *cpi, double section_err, int section_ta return Q; } -// For cq mode estimate a cq level that matches the observed -// complexity and data rate. -static int estimate_cq(VP8_COMP *cpi, double section_err, int section_target_bandwitdh) -{ - int Q; - int num_mbs = cpi->common.MBs; - int target_norm_bits_per_mb; - - double err_per_mb = section_err / num_mbs; - double correction_factor; - double corr_high; - double speed_correction = 1.0; - double pow_highq = 0.90; - double pow_lowq = 0.40; - double clip_iiratio; - double clip_iifactor; - - target_norm_bits_per_mb = (section_target_bandwitdh < (1 << 20)) - ? (512 * section_target_bandwitdh) / num_mbs - : 512 * (section_target_bandwitdh / num_mbs); - - // Corrections for higher compression speed settings - // (reduced compression expected) - if ((cpi->compressor_speed == 3) || (cpi->compressor_speed == 1)) - { - if (cpi->oxcf.cpu_used <= 5) - speed_correction = 1.04 + (cpi->oxcf.cpu_used * 0.04); - else - speed_correction = 1.25; - } - // II ratio correction factor for clip as a whole - clip_iiratio = cpi->twopass.total_stats->intra_error / - DOUBLE_DIVIDE_CHECK(cpi->twopass.total_stats->coded_error); - clip_iifactor = 1.0 - ((clip_iiratio - 10.0) * 0.025); - if (clip_iifactor < 0.80) - clip_iifactor = 0.80; - - // Correction factor used for Q values >= 20 - corr_high = pow(err_per_mb / BASE_ERRPERMB, pow_highq); - corr_high = (corr_high < 0.05) ? 0.05 : (corr_high > 5.0) ? 5.0 : corr_high; - - // Try and pick a Q that can encode the content at the given rate. - for (Q = 0; Q < MAXQ; Q++) - { - int bits_per_mb_at_this_q; - - if (Q < 50) - { - correction_factor = - pow( err_per_mb / BASE_ERRPERMB, (pow_lowq + Q * 0.01)); - - correction_factor = (correction_factor < 0.05) ? 0.05 - : (correction_factor > 5.0) ? 5.0 - : correction_factor; - } - else - correction_factor = corr_high; - - bits_per_mb_at_this_q = - (int)( .5 + correction_factor * - speed_correction * - clip_iifactor * - (double)vp8_bits_per_mb(INTER_FRAME,Q) / 1.0); - - if (bits_per_mb_at_this_q <= target_norm_bits_per_mb) - break; - } - - return cq_level[Q]; -} - extern void vp8_new_frame_rate(VP8_COMP *cpi, double framerate); void vp8_init_second_pass(VP8_COMP *cpi) @@ -1183,19 +1261,13 @@ void vp8_init_second_pass(VP8_COMP *cpi) double two_pass_min_rate = (double)(cpi->oxcf.target_bandwidth * cpi->oxcf.two_pass_vbrmin_section / 100); zero_stats(cpi->twopass.total_stats); + zero_stats(cpi->twopass.total_left_stats); if (!cpi->twopass.stats_in_end) return; *cpi->twopass.total_stats = *cpi->twopass.stats_in_end; - - cpi->twopass.total_error_left = cpi->twopass.total_stats->ssim_weighted_pred_err; - cpi->twopass.total_intra_error_left = cpi->twopass.total_stats->intra_error; - cpi->twopass.total_coded_error_left = cpi->twopass.total_stats->coded_error; - cpi->twopass.start_tot_err_left = cpi->twopass.total_error_left; - - //cpi->twopass.bits_left = (int64_t)(cpi->twopass.total_stats->count * cpi->oxcf.target_bandwidth / DOUBLE_DIVIDE_CHECK((double)cpi->oxcf.frame_rate)); - //cpi->twopass.bits_left -= (int64_t)(cpi->twopass.total_stats->count * two_pass_min_rate / DOUBLE_DIVIDE_CHECK((double)cpi->oxcf.frame_rate)); + *cpi->twopass.total_left_stats = *cpi->twopass.total_stats; // each frame can have a different duration, as the frame rate in the source // isn't guaranteed to be constant. The frame rate prior to the first frame @@ -1207,7 +1279,6 @@ void vp8_init_second_pass(VP8_COMP *cpi) cpi->output_frame_rate = cpi->oxcf.frame_rate; cpi->twopass.bits_left = (int64_t)(cpi->twopass.total_stats->duration * cpi->oxcf.target_bandwidth / 10000000.0) ; cpi->twopass.bits_left -= (int64_t)(cpi->twopass.total_stats->duration * two_pass_min_rate / 10000000.0); - cpi->twopass.clip_bits_total = cpi->twopass.bits_left; // Calculate a minimum intra value to be used in determining the IIratio // scores used in the second pass. We have this minimum to make sure @@ -1216,8 +1287,6 @@ void vp8_init_second_pass(VP8_COMP *cpi) cpi->twopass.kf_intra_err_min = KF_MB_INTRA_MIN * cpi->common.MBs; cpi->twopass.gf_intra_err_min = GF_MB_INTRA_MIN * cpi->common.MBs; - avg_stats(cpi->twopass.total_stats); - // Scan the first pass file and calculate an average Intra / Inter error score ratio for the sequence { double sum_iiratio = 0.0; @@ -2238,6 +2307,8 @@ void vp8_second_pass(VP8_COMP *cpi) FIRSTPASS_STATS *start_pos; + int overhead_bits; + if (!cpi->twopass.stats_in) { return ; @@ -2337,20 +2408,26 @@ void vp8_second_pass(VP8_COMP *cpi) if (cpi->target_bandwidth < 0) cpi->target_bandwidth = 0; + + // Account for mv, mode and other overheads. + overhead_bits = estimate_modemvcost( + cpi, cpi->twopass.total_left_stats ); + + // Special case code for first frame. if (cpi->common.current_video_frame == 0) { cpi->twopass.est_max_qcorrection_factor = 1.0; - // Experimental code to try and set a cq_level in constrained - // quality mode. + // Set a cq_level in constrained quality mode. if ( cpi->oxcf.end_usage == USAGE_CONSTRAINED_QUALITY ) { int est_cq; est_cq = estimate_cq( cpi, - (cpi->twopass.total_coded_error_left / frames_left), - (int)(cpi->twopass.bits_left / frames_left)); + cpi->twopass.total_left_stats, + (int)(cpi->twopass.bits_left / frames_left), + overhead_bits ); cpi->cq_target_quality = cpi->oxcf.cq_level; if ( est_cq > cpi->cq_target_quality ) @@ -2360,9 +2437,12 @@ void vp8_second_pass(VP8_COMP *cpi) // guess at maxq needed in 2nd pass cpi->twopass.maxq_max_limit = cpi->worst_quality; cpi->twopass.maxq_min_limit = cpi->best_quality; - tmp_q = estimate_max_q( cpi, - (cpi->twopass.total_coded_error_left / frames_left), - (int)(cpi->twopass.bits_left / frames_left)); + + tmp_q = estimate_max_q( + cpi, + cpi->twopass.total_left_stats, + (int)(cpi->twopass.bits_left / frames_left), + overhead_bits ); // Limit the maxq value returned subsequently. // This increases the risk of overspend or underspend if the initial @@ -2383,14 +2463,18 @@ void vp8_second_pass(VP8_COMP *cpi) // radical adjustments to the allowed quantizer range just to use up a // few surplus bits or get beneath the target rate. else if ( (cpi->common.current_video_frame < - (((unsigned int)cpi->twopass.total_stats->count * 255)>>8)) && + (((unsigned int)cpi->twopass.total_stats->count * 255)>>8)) && ((cpi->common.current_video_frame + cpi->baseline_gf_interval) < - (unsigned int)cpi->twopass.total_stats->count) ) + (unsigned int)cpi->twopass.total_stats->count) ) { if (frames_left < 1) frames_left = 1; - tmp_q = estimate_max_q(cpi, (cpi->twopass.total_coded_error_left / frames_left), (int)(cpi->twopass.bits_left / frames_left)); + tmp_q = estimate_max_q( + cpi, + cpi->twopass.total_left_stats, + (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) @@ -2398,13 +2482,14 @@ void vp8_second_pass(VP8_COMP *cpi) else if (tmp_q < cpi->active_worst_quality) cpi->active_worst_quality --; - cpi->active_worst_quality = ((cpi->active_worst_quality * 3) + tmp_q + 2) / 4; + cpi->active_worst_quality = + ((cpi->active_worst_quality * 3) + tmp_q + 2) / 4; } cpi->twopass.frames_to_key --; - cpi->twopass.total_error_left -= this_frame_error; - cpi->twopass.total_intra_error_left -= this_frame_intra_error; - cpi->twopass.total_coded_error_left -= this_frame_coded_error; + + // Update the total stats remaining sturcture + subtract_stats(cpi->twopass.total_left_stats, &this_frame ); } diff --git a/vp8/encoder/onyx_if.c b/vp8/encoder/onyx_if.c index ec5ff64ef..2dcddc0d1 100644 --- a/vp8/encoder/onyx_if.c +++ b/vp8/encoder/onyx_if.c @@ -339,6 +339,9 @@ static void dealloc_compressor_data(VP8_COMP *cpi) vpx_free(cpi->twopass.total_stats); cpi->twopass.total_stats = 0; + vpx_free(cpi->twopass.total_left_stats); + cpi->twopass.total_left_stats = 0; + vpx_free(cpi->twopass.this_frame_stats); cpi->twopass.this_frame_stats = 0; #endif @@ -1553,11 +1556,16 @@ void vp8_alloc_compressor_data(VP8_COMP *cpi) cpi->twopass.total_stats = vpx_calloc(1, sizeof(FIRSTPASS_STATS)); + vpx_free(cpi->twopass.total_left_stats); + cpi->twopass.total_left_stats = vpx_calloc(1, sizeof(FIRSTPASS_STATS)); + vpx_free(cpi->twopass.this_frame_stats); cpi->twopass.this_frame_stats = vpx_calloc(1, sizeof(FIRSTPASS_STATS)); - if(!cpi->twopass.total_stats || !cpi->twopass.this_frame_stats) + if( !cpi->twopass.total_stats || + !cpi->twopass.total_left_stats || + !cpi->twopass.this_frame_stats) vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR, "Failed to allocate firstpass stats"); #endif @@ -3812,12 +3820,13 @@ static void encode_frame_to_data_rate (cpi->avg_frame_qindex < cpi->active_worst_quality) ) { Q = cpi->avg_frame_qindex; + } - if ( (cpi->oxcf.end_usage == USAGE_CONSTRAINED_QUALITY) && - (Q < cpi->oxcf.cq_level) ) - { - Q = cpi->oxcf.cq_level; - } + // For constrained quality dont allow Q less than the cq level + if ( (cpi->oxcf.end_usage == USAGE_CONSTRAINED_QUALITY) && + (Q < cpi->cq_target_quality) ) + { + Q = cpi->cq_target_quality; } if ( cpi->pass == 2 ) @@ -3828,6 +3837,13 @@ static void encode_frame_to_data_rate cpi->active_best_quality = gf_high_motion_minq[Q]; else cpi->active_best_quality = gf_mid_motion_minq[Q]; + + // Constrained quality use slightly lower active best. + if ( cpi->oxcf.end_usage == USAGE_CONSTRAINED_QUALITY ) + { + cpi->active_best_quality = + cpi->active_best_quality * 15/16; + } } // One pass more conservative else @@ -3838,7 +3854,7 @@ static void encode_frame_to_data_rate cpi->active_best_quality = inter_minq[Q]; // For the constant/constrained quality mode we dont want - // the quality to rise above the cq level. + // q to fall below the cq level. if ((cpi->oxcf.end_usage == USAGE_CONSTRAINED_QUALITY) && (cpi->active_best_quality < cpi->cq_target_quality) ) { @@ -3891,8 +3907,9 @@ static void encode_frame_to_data_rate if (cpi->active_best_quality < cpi->best_quality) cpi->active_best_quality = cpi->best_quality; - else if (cpi->active_best_quality > cpi->active_worst_quality) - cpi->active_best_quality = cpi->active_worst_quality; + + if ( cpi->active_worst_quality < cpi->active_best_quality ) + cpi->active_worst_quality = cpi->active_best_quality; // Determine initial Q to try Q = vp8_regulate_q(cpi, cpi->this_frame_target); @@ -4622,7 +4639,7 @@ static void encode_frame_to_data_rate vp8_clear_system_state(); //__asm emms; - if (cpi->twopass.total_coded_error_left != 0.0) + if (cpi->twopass.total_left_stats->coded_error != 0.0) fprintf(f, "%10d %10d %10d %10d %10d %10d %10d %10d %6d %6d" "%6d %6d %6d %5d %5d %5d %8d %8.2f %10d %10.3f" "%10.3f %8d\n", @@ -4633,13 +4650,16 @@ static void encode_frame_to_data_rate (cpi->oxcf.starting_buffer_level-cpi->bits_off_target), (int)cpi->total_actual_bits, cm->base_qindex, cpi->active_best_quality, cpi->active_worst_quality, - cpi->ni_av_qi, cpi->cq_target_quality, cpi->zbin_over_quant, + cpi->ni_av_qi, cpi->cq_target_quality, + cpi->zbin_over_quant, //cpi->avg_frame_qindex, cpi->zbin_over_quant, cm->refresh_golden_frame, cm->refresh_alt_ref_frame, cm->frame_type, cpi->gfu_boost, - cpi->twopass.est_max_qcorrection_factor, (int)cpi->twopass.bits_left, - cpi->twopass.total_coded_error_left, - (double)cpi->twopass.bits_left / cpi->twopass.total_coded_error_left, + cpi->twopass.est_max_qcorrection_factor, + (int)cpi->twopass.bits_left, + cpi->twopass.total_left_stats->coded_error, + (double)cpi->twopass.bits_left / + cpi->twopass.total_left_stats->coded_error, cpi->tot_recode_hits); else fprintf(f, "%10d %10d %10d %10d %10d %10d %10d %10d %6d %6d" @@ -4652,15 +4672,19 @@ static void encode_frame_to_data_rate (cpi->oxcf.starting_buffer_level-cpi->bits_off_target), (int)cpi->total_actual_bits, cm->base_qindex, cpi->active_best_quality, cpi->active_worst_quality, - cpi->ni_av_qi, cpi->cq_target_quality, cpi->zbin_over_quant, + cpi->ni_av_qi, cpi->cq_target_quality, + cpi->zbin_over_quant, //cpi->avg_frame_qindex, cpi->zbin_over_quant, cm->refresh_golden_frame, cm->refresh_alt_ref_frame, cm->frame_type, cpi->gfu_boost, - cpi->twopass.est_max_qcorrection_factor, (int)cpi->twopass.bits_left, - cpi->twopass.total_coded_error_left, cpi->tot_recode_hits); + cpi->twopass.est_max_qcorrection_factor, + (int)cpi->twopass.bits_left, + cpi->twopass.total_left_stats->coded_error, + cpi->tot_recode_hits); fclose(f); + if ( 0 ) { FILE *fmodes = fopen("Modes.stt", "a"); int i; diff --git a/vp8/encoder/onyx_int.h b/vp8/encoder/onyx_int.h index 465faeec7..622f25068 100644 --- a/vp8/encoder/onyx_int.h +++ b/vp8/encoder/onyx_int.h @@ -120,6 +120,7 @@ typedef struct double MVrv; double MVcv; double mv_in_out_count; + double new_mv_count; double duration; double count; } @@ -567,6 +568,7 @@ typedef struct VP8_COMP FIRSTPASS_STATS *total_stats; FIRSTPASS_STATS *this_frame_stats; FIRSTPASS_STATS *stats_in, *stats_in_end, *stats_in_start; + FIRSTPASS_STATS *total_left_stats; int first_pass_done; int64_t bits_left; int64_t clip_bits_total; @@ -574,10 +576,6 @@ typedef struct VP8_COMP double modified_error_total; double modified_error_used; double modified_error_left; - double total_error_left; - double total_intra_error_left; - double total_coded_error_left; - double start_tot_err_left; double kf_intra_err_min; double gf_intra_err_min; int frames_to_key;