diff --git a/vp8/encoder/firstpass.c b/vp8/encoder/firstpass.c index 35adb9d108af26494769bfe033c764cf350d2c45..4f3b75ce21c6abeaa629709779a56938e741a167 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 ec5ff64ef2eeb7c5f01c197c620b6ca58d84ac9a..2dcddc0d11ce2a590ba61b5f40c0cf54fd05f528 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 465faeec7d0f1e414b2b5adf6678c9d0857f4d71..622f25068418aaac988deb6770890eb1c041a1a6 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;