diff --git a/av1/encoder/firstpass.c b/av1/encoder/firstpass.c index 8fdb0cbe813e10300bb369485cb1ac233e74b163..9d896a2baada07e0d7feba15c501771a90727c5b 100644 --- a/av1/encoder/firstpass.c +++ b/av1/encoder/firstpass.c @@ -47,26 +47,32 @@ #define GROUP_ADAPTIVE_MAXQ 1 -#define BOOST_BREAKOUT 12.5 -#define BOOST_FACTOR 12.5 -#define FACTOR_PT_LOW 0.70 -#define FACTOR_PT_HIGH 0.90 #define FIRST_PASS_Q 10.0 -#define GF_MAX_BOOST 96.0 #define INTRA_MODE_PENALTY 1024 -#define KF_MAX_BOOST 128.0 -#define MIN_ARF_GF_BOOST 240 #define MIN_DECAY_FACTOR 0.01 -#define MIN_KF_BOOST 300 #define NEW_MV_MODE_PENALTY 32 #define DARK_THRESH 64 #define DEFAULT_GRP_WEIGHT 1.0 -#define RC_FACTOR_MIN 0.75 -#define RC_FACTOR_MAX 1.75 +#define SECTION_NOISE_DEF 250.0 +#define LOW_I_THRESH 24000 +#define ARF_ABS_ZOOM_THRESH 4.0 #define NCOUNT_INTRA_THRESH 8192 #define NCOUNT_INTRA_FACTOR 3 -#define NCOUNT_FRAME_II_THRESH 5.0 + +#define FRAMES_TO_CHECK_DECAY 8 +#define KF_BOOST_SCAN_MAX_FRAMES 32 + +#define MIN_ARF_GF_BOOST 240 +#define MIN_KF_TOT_BOOST 300 +#define MAX_KF_TOT_BOOST 5000 +#define KF_MAX_FRAME_BOOST 72.0 +#define GF_MAX_FRAME_BOOST 72.0 + +#define KF_ABS_ZOOM_THRESH 6.0 +#define ARF_ABS_ZOOM_THRESH 4.0 + +#define ALWAYS_ADJUST_BPM 0 #define DOUBLE_DIVIDE_CHECK(x) ((x) < 0 ? (x)-0.000001 : (x) + 0.000001) @@ -145,11 +151,15 @@ static void zero_stats(FIRSTPASS_STATS *section) { section->intra_error = 0.0; section->coded_error = 0.0; section->sr_coded_error = 0.0; + section->frame_noise_energy = 0.0; section->pcnt_inter = 0.0; section->pcnt_motion = 0.0; section->pcnt_second_ref = 0.0; section->pcnt_neutral = 0.0; + section->pcnt_intra_low = 0.0; + section->pcnt_intra_high = 0.0; section->intra_skip_pct = 0.0; + section->intra_smooth_pct = 0.0; section->inactive_zone_rows = 0.0; section->inactive_zone_cols = 0.0; section->MVr = 0.0; @@ -171,11 +181,15 @@ static void accumulate_stats(FIRSTPASS_STATS *section, section->intra_error += frame->intra_error; section->coded_error += frame->coded_error; section->sr_coded_error += frame->sr_coded_error; + section->frame_noise_energy += frame->frame_noise_energy; 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->pcnt_intra_low += frame->pcnt_intra_low; + section->pcnt_intra_high += frame->pcnt_intra_high; section->intra_skip_pct += frame->intra_skip_pct; + section->intra_smooth_pct += frame->intra_smooth_pct; section->inactive_zone_rows += frame->inactive_zone_rows; section->inactive_zone_cols += frame->inactive_zone_cols; section->MVr += frame->MVr; @@ -197,11 +211,15 @@ static void subtract_stats(FIRSTPASS_STATS *section, section->intra_error -= frame->intra_error; section->coded_error -= frame->coded_error; section->sr_coded_error -= frame->sr_coded_error; + section->frame_noise_energy -= frame->frame_noise_energy; 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->pcnt_intra_low -= frame->pcnt_intra_low; + section->pcnt_intra_high -= frame->pcnt_intra_high; section->intra_skip_pct -= frame->intra_skip_pct; + section->intra_smooth_pct -= frame->intra_smooth_pct; section->inactive_zone_rows -= frame->inactive_zone_rows; section->inactive_zone_cols -= frame->inactive_zone_cols; section->MVr -= frame->MVr; @@ -238,31 +256,61 @@ static double calculate_active_area(const AV1_COMP *cpi, return fclamp(active_pct, MIN_ACTIVE_AREA, MAX_ACTIVE_AREA); } +// Get the average weighted error for the clip (or corpus) +static double get_distribution_av_err(TWO_PASS *const twopass) { + const double av_weight = + twopass->total_stats.weight / twopass->total_stats.count; + + return (twopass->total_stats.coded_error * av_weight) / + twopass->total_stats.count; +} + +#define ACT_AREA_CORRECTION 0.5 // Calculate a modified Error used in distributing bits between easier and // harder frames. -#define ACT_AREA_CORRECTION 0.5 -static double calculate_modified_err(const AV1_COMP *cpi, - const TWO_PASS *twopass, - const AV1EncoderConfig *oxcf, - const FIRSTPASS_STATS *this_frame) { - const FIRSTPASS_STATS *const stats = &twopass->total_stats; - const double av_weight = stats->weight / stats->count; - const double av_err = (stats->coded_error * av_weight) / stats->count; - double modified_error = +static double calculate_mod_frame_score(const AV1_COMP *cpi, + const AV1EncoderConfig *oxcf, + const FIRSTPASS_STATS *this_frame, + double av_err) { + double modified_score = + av_err * pow(this_frame->coded_error * this_frame->weight / + DOUBLE_DIVIDE_CHECK(av_err), + oxcf->two_pass_vbrbias / 100.0); + + // Correction for active area. Frames with a reduced active area + // (eg due to formatting bars) have a higher error per mb for the + // remaining active MBs. The correction here assumes that coding + // 0.5N blocks of complexity 2X is a little easier than coding N + // blocks of complexity X. + modified_score *= + pow(calculate_active_area(cpi, this_frame), ACT_AREA_CORRECTION); + return modified_score; +} + +static double calculate_norm_frame_score(const AV1_COMP *cpi, + const TWO_PASS *twopass, + const AV1EncoderConfig *oxcf, + const FIRSTPASS_STATS *this_frame, + double av_err) { + double modified_score = av_err * pow(this_frame->coded_error * this_frame->weight / DOUBLE_DIVIDE_CHECK(av_err), oxcf->two_pass_vbrbias / 100.0); + const double min_score = (double)(oxcf->two_pass_vbrmin_section) / 100.0; + const double max_score = (double)(oxcf->two_pass_vbrmax_section) / 100.0; // Correction for active area. Frames with a reduced active area // (eg due to formatting bars) have a higher error per mb for the // remaining active MBs. The correction here assumes that coding // 0.5N blocks of complexity 2X is a little easier than coding N // blocks of complexity X. - modified_error *= + modified_score *= pow(calculate_active_area(cpi, this_frame), ACT_AREA_CORRECTION); - return fclamp(modified_error, twopass->modified_error_min, - twopass->modified_error_max); + // Normalize to a midpoint score. + modified_score /= DOUBLE_DIVIDE_CHECK(twopass->mean_mod_score); + + return fclamp(modified_score, min_score, max_score); } // This function returns the maximum target rate per frame. @@ -478,6 +526,170 @@ static double raw_motion_error_stdev(int *raw_motion_err_list, return raw_err_stdev; } +#define UL_INTRA_THRESH 50 +static int get_ul_intra_threshold(AV1_COMMON *cm) { + int ret_val = UL_INTRA_THRESH; + if (cm->use_highbitdepth) { + switch (cm->bit_depth) { + case AOM_BITS_8: ret_val = UL_INTRA_THRESH; break; + case AOM_BITS_10: ret_val = UL_INTRA_THRESH << 2; break; + case AOM_BITS_12: ret_val = UL_INTRA_THRESH << 4; break; + default: + assert(0 && + "cm->bit_depth should be AOM_BITS_8, " + "AOM_BITS_10 or AOM_BITS_12"); + } + } + return ret_val; +} + +#define SMOOTH_INTRA_THRESH 4000 +static int get_smooth_intra_threshold(AV1_COMMON *cm) { + int ret_val = SMOOTH_INTRA_THRESH; + if (cm->use_highbitdepth) { + switch (cm->bit_depth) { + case AOM_BITS_8: ret_val = SMOOTH_INTRA_THRESH; break; + case AOM_BITS_10: ret_val = SMOOTH_INTRA_THRESH << 4; break; + case AOM_BITS_12: ret_val = SMOOTH_INTRA_THRESH << 8; break; + default: + assert(0 && + "cm->bit_depth should be AOM_BITS_8, " + "AOM_BITS_10 or AOM_BITS_12"); + } + } + return ret_val; +} + +#define FP_DN_THRESH 8 +#define FP_MAX_DN_THRESH 16 +#define KERNEL_SIZE 3 +// Baseline Kernal weights for first pass noise metric +static uint8_t fp_dn_kernel_3[KERNEL_SIZE * KERNEL_SIZE] = { 1, 2, 1, 2, 4, + 2, 1, 2, 1 }; + +static int fp_estimate_point_noise(uint8_t *src_ptr, const int stride) { + int sum_weight = 0; + int sum_val = 0; + int i, j; + int max_diff = 0; + int diff; + int dn_diff; + uint8_t *tmp_ptr; + uint8_t *kernel_ptr; + uint8_t dn_val; + uint8_t centre_val = *src_ptr; + + kernel_ptr = fp_dn_kernel_3; + + // Apply the kernel + tmp_ptr = src_ptr - stride - 1; + for (i = 0; i < KERNEL_SIZE; ++i) { + for (j = 0; j < KERNEL_SIZE; ++j) { + diff = abs((int)centre_val - (int)tmp_ptr[j]); + max_diff = AOMMAX(max_diff, diff); + if (diff <= FP_DN_THRESH) { + sum_weight += *kernel_ptr; + sum_val += (int)tmp_ptr[j] * (int)*kernel_ptr; + } + ++kernel_ptr; + } + tmp_ptr += stride; + } + + if (max_diff < FP_MAX_DN_THRESH) + // Update the source value with the new filtered value + dn_val = (sum_val + (sum_weight >> 1)) / sum_weight; + else + dn_val = *src_ptr; + // return the noise energy as the square of the + // difference between the denoised and raw value. + dn_diff = (int)*src_ptr - (int)dn_val; + return dn_diff * dn_diff; +} + +static int fp_highbd_estimate_point_noise(uint8_t *src_ptr, int stride) { + int sum_weight = 0; + int sum_val = 0; + int i, j; + int max_diff = 0; + int diff; + int dn_diff; + uint8_t *tmp_ptr; + uint16_t *tmp_ptr16; + uint8_t *kernel_ptr; + uint16_t dn_val; + uint16_t centre_val = *CONVERT_TO_SHORTPTR(src_ptr); + + kernel_ptr = fp_dn_kernel_3; + + // Apply the kernel + tmp_ptr = src_ptr - stride - 1; + for (i = 0; i < KERNEL_SIZE; ++i) { + tmp_ptr16 = CONVERT_TO_SHORTPTR(tmp_ptr); + for (j = 0; j < KERNEL_SIZE; ++j) { + diff = abs((int)centre_val - (int)tmp_ptr16[j]); + max_diff = AOMMAX(max_diff, diff); + if (diff <= FP_DN_THRESH) { + sum_weight += *kernel_ptr; + sum_val += (int)tmp_ptr16[j] * (int)*kernel_ptr; + } + ++kernel_ptr; + } + tmp_ptr += stride; + } + + if (max_diff < FP_MAX_DN_THRESH) + // Update the source value with the new filtered value + dn_val = (sum_val + (sum_weight >> 1)) / sum_weight; + else + dn_val = *CONVERT_TO_SHORTPTR(src_ptr); + + // return the noise energy as the square of the difference between the + // denoised and raw value. + dn_diff = (int)(*CONVERT_TO_SHORTPTR(src_ptr)) - (int)dn_val; + return dn_diff * dn_diff; +} + +static int fp_estimate_block_noise(MACROBLOCK *x, BLOCK_SIZE bsize) { + MACROBLOCKD *xd = &x->e_mbd; + uint8_t *src_ptr = &x->plane[0].src.buf[0]; + const int width = num_4x4_blocks_wide_lookup[bsize] * 4; + const int height = num_4x4_blocks_high_lookup[bsize] * 4; + int w, h; + int stride = x->plane[0].src.stride; + int block_noise = 0; + + // Sampled points to reduce cost overhead. + for (h = 0; h < height; h += 2) { + for (w = 0; w < width; w += 2) { + if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) + block_noise += fp_highbd_estimate_point_noise(src_ptr, stride); + else + block_noise += fp_estimate_point_noise(src_ptr, stride); + ++src_ptr; + } + src_ptr += (stride - width); + } + return block_noise << 2; // Scale << 2 to account for sampling. +} + +// Scale an sse threshold to account for 8/10/12 bit. +static int scale_sse_threshold(AV1_COMMON *cm, int thresh) { + int ret_val = thresh; + if (cm->use_highbitdepth) { + switch (cm->bit_depth) { + case AOM_BITS_8: ret_val = thresh; break; + case AOM_BITS_10: ret_val = thresh << 4; break; + case AOM_BITS_12: ret_val = thresh << 8; break; + default: + assert(0 && + "cm->bit_depth should be VPX_BITS_8, " + "VPX_BITS_10 or VPX_BITS_12"); + } + } + return ret_val; +} + #define UL_INTRA_THRESH 50 #define INVALID_ROW -1 void av1_first_pass(AV1_COMP *cpi, const struct lookahead_entry *source) { @@ -497,6 +709,7 @@ void av1_first_pass(AV1_COMP *cpi, const struct lookahead_entry *source) { int64_t intra_error = 0; int64_t coded_error = 0; int64_t sr_coded_error = 0; + int64_t frame_noise_energy = 0; int sum_mvr = 0, sum_mvc = 0; int sum_mvr_abs = 0, sum_mvc_abs = 0; @@ -505,8 +718,11 @@ void av1_first_pass(AV1_COMP *cpi, const struct lookahead_entry *source) { int intercount = 0; int second_ref_count = 0; const int intrapenalty = INTRA_MODE_PENALTY; - double neutral_count; + double neutral_count = 0.0; int intra_skip_count = 0; + int intra_smooth_count = 0; + double intra_count_low = 0.0; + double intra_count_high = 0.0; int image_data_start_row = INVALID_ROW; int new_mv_count = 0; int sum_in_vectors = 0; @@ -611,6 +827,7 @@ void av1_first_pass(AV1_COMP *cpi, const struct lookahead_entry *source) { for (mb_col = 0; mb_col < cm->mb_cols; ++mb_col) { int this_error; + int this_intra_error; const int use_dc_pred = (mb_col || mb_row) && (!mb_col || !mb_row); const BLOCK_SIZE bsize = get_bsize(cm, mb_row, mb_col); double log_intra; @@ -645,18 +862,34 @@ void av1_first_pass(AV1_COMP *cpi, const struct lookahead_entry *source) { use_dc_pred ? (bsize >= BLOCK_16X16 ? TX_16X16 : TX_8X8) : TX_4X4; av1_encode_intra_block_plane(cpi, x, bsize, 0, 0, mb_row * 2, mb_col * 2); this_error = aom_get_mb_ss(x->plane[0].src_diff); + this_intra_error = this_error; // Keep a record of blocks that have almost no intra error residual // (i.e. are in effect completely flat and untextured in the intra // domain). In natural videos this is uncommon, but it is much more // common in animations, graphics and screen content, so may be used // as a signal to detect these types of content. - if (this_error < UL_INTRA_THRESH) { + if (this_error < get_ul_intra_threshold(cm)) { ++intra_skip_count; } else if ((mb_col > 0) && (image_data_start_row == INVALID_ROW)) { image_data_start_row = mb_row; } + // Blocks that are mainly smooth in the intra domain. + // Some special accounting for CQ but also these are better + // for testing noise levels. + if (this_error < get_smooth_intra_threshold(cm)) { + ++intra_smooth_count; + } + + if (cm->current_video_frame == 0) { + if (this_intra_error < scale_sse_threshold(cm, LOW_I_THRESH)) { + frame_noise_energy += fp_estimate_block_noise(x, bsize); + } else { + frame_noise_energy += (int64_t)SECTION_NOISE_DEF; + } + } + if (cm->use_highbitdepth) { switch (cm->bit_depth) { case AOM_BITS_8: break; @@ -928,6 +1161,24 @@ void av1_first_pass(AV1_COMP *cpi, const struct lookahead_entry *source) { else if (mv.col < 0) --sum_in_vectors; } + frame_noise_energy += (int64_t)SECTION_NOISE_DEF; + } else if (this_intra_error < scale_sse_threshold(cm, LOW_I_THRESH)) { + frame_noise_energy += fp_estimate_block_noise(x, bsize); + } else { + frame_noise_energy += (int64_t)SECTION_NOISE_DEF; + } + } else { // Intra < inter error + int scaled_low_intra_thresh = scale_sse_threshold(cm, LOW_I_THRESH); + if (this_intra_error < scaled_low_intra_thresh) { + frame_noise_energy += fp_estimate_block_noise(x, bsize); + if (motion_error < scaled_low_intra_thresh) { + intra_count_low += 1.0; + } else { + intra_count_high += 1.0; + } + } else { + frame_noise_energy += (int64_t)SECTION_NOISE_DEF; + intra_count_high += 1.0; } } raw_motion_err_list[raw_motion_err_counts++] = raw_motion_error; @@ -986,14 +1237,19 @@ void av1_first_pass(AV1_COMP *cpi, const struct lookahead_entry *source) { fps.weight = intra_factor * brightness_factor; fps.frame = cm->current_video_frame; - fps.coded_error = (double)(coded_error >> 8) + min_err; - fps.sr_coded_error = (double)(sr_coded_error >> 8) + min_err; - fps.intra_error = (double)(intra_error >> 8) + min_err; + fps.coded_error = ((double)(coded_error >> 8) + min_err) / num_mbs; + fps.sr_coded_error = ((double)(sr_coded_error >> 8) + min_err) / num_mbs; + fps.intra_error = ((double)(intra_error >> 8) + min_err) / num_mbs; + fps.frame_noise_energy = (double)(frame_noise_energy) / (double)num_mbs; + fps.count = 1.0; fps.pcnt_inter = (double)intercount / num_mbs; fps.pcnt_second_ref = (double)second_ref_count / num_mbs; fps.pcnt_neutral = (double)neutral_count / num_mbs; + fps.pcnt_intra_low = (double)intra_count_low / num_mbs; + fps.pcnt_intra_high = (double)intra_count_high / num_mbs; fps.intra_skip_pct = (double)intra_skip_count / num_mbs; + fps.intra_smooth_pct = (double)intra_smooth_count / num_mbs; fps.inactive_zone_rows = (double)image_data_start_row; fps.inactive_zone_cols = (double)0; // TODO(paulwilkins): fix fps.raw_error_stdev = raw_err_stdev; @@ -1090,13 +1346,20 @@ void av1_first_pass(AV1_COMP *cpi, const struct lookahead_entry *source) { } static double calc_correction_factor(double err_per_mb, double err_divisor, - double pt_low, double pt_high, int q, - aom_bit_depth_t bit_depth) { - const double error_term = err_per_mb / err_divisor; + int q) { + static const double q_pow_term[(QINDEX_RANGE >> 5) + 1] = { + 0.65, 0.70, 0.75, 0.85, 0.90, 0.90, 0.90, 1.00, 1.25 + }; + const double error_term = err_per_mb / DOUBLE_DIVIDE_CHECK(err_divisor); + const int index = q >> 5; + double power_term; + + assert((index >= 0) && (index < (QINDEX_RANGE >> 5))); // Adjustment based on actual quantizer to power term. - const double power_term = - AOMMIN(av1_convert_qindex_to_q(q, bit_depth) * 0.01 + pt_low, pt_high); + power_term = + q_pow_term[index] + + (((q_pow_term[index + 1] - q_pow_term[index]) * (q % 32)) / 32.0); // Calculate correction factor. if (power_term < 1.0) assert(error_term >= 0.0); @@ -1104,51 +1367,70 @@ static double calc_correction_factor(double err_per_mb, double err_divisor, return fclamp(pow(error_term, power_term), 0.05, 5.0); } -#define ERR_DIVISOR 100.0 -static int get_twopass_worst_quality(const AV1_COMP *cpi, - const double section_err, - double inactive_zone, - int section_target_bandwidth, - double group_weight_factor) { +#define ERR_DIVISOR 115.0 +#define NOISE_FACTOR_MIN 0.9 +#define NOISE_FACTOR_MAX 1.1 +static int get_twopass_worst_quality(AV1_COMP *cpi, const double section_err, + double inactive_zone, double section_noise, + int section_target_bandwidth) { const RATE_CONTROL *const rc = &cpi->rc; const AV1EncoderConfig *const oxcf = &cpi->oxcf; + TWO_PASS *const twopass = &cpi->twopass; + double last_group_rate_err; + // Clamp the target rate to VBR min / max limts. + const int target_rate = + av1_rc_clamp_pframe_target_size(cpi, section_target_bandwidth); + double noise_factor = pow((section_noise / SECTION_NOISE_DEF), 0.5); + noise_factor = fclamp(noise_factor, NOISE_FACTOR_MIN, NOISE_FACTOR_MAX); inactive_zone = fclamp(inactive_zone, 0.0, 1.0); - if (section_target_bandwidth <= 0) { +// TODO(jimbankoski): remove #if here or below when this has been +// well tested. +#if ALWAYS_ADJUST_BPM + // based on recent history adjust expectations of bits per + // macroblock. + last_group_rate_err = + (double)twopass->rolling_arf_group_actual_bits / + DOUBLE_DIVIDE_CHECK((double)twopass->rolling_arf_group_target_bits); + last_group_rate_err = AOMMAX(0.25, AOMMIN(4.0, last_group_rate_err)); + twopass->bpm_factor *= (3.0 + last_group_rate_err) / 4.0; + twopass->bpm_factor = AOMMAX(0.25, AOMMIN(4.0, twopass->bpm_factor)); +#endif + + if (target_rate <= 0) { return rc->worst_quality; // Highest value allowed } else { const int num_mbs = (cpi->oxcf.resize_mode != RESIZE_NONE) ? cpi->initial_mbs : cpi->common.MBs; - const int active_mbs = AOMMAX(1, num_mbs - (int)(num_mbs * inactive_zone)); - const double av_err_per_mb = section_err / active_mbs; - const double speed_term = 1.0; - double ediv_size_correction; + const double active_pct = AOMMAX(0.01, 1.0 - inactive_zone); + const int active_mbs = (int)AOMMAX(1, (double)num_mbs * active_pct); + const double av_err_per_mb = section_err / active_pct; + const double speed_term = 1.0 + 0.04 * oxcf->speed; const int target_norm_bits_per_mb = - (int)((uint64_t)section_target_bandwidth << BPER_MB_NORMBITS) / - active_mbs; + (int)(((uint64_t)target_rate << BPER_MB_NORMBITS) / active_mbs); int q; - // Larger image formats are expected to be a little harder to code - // relatively given the same prediction error score. This in part at - // least relates to the increased size and hence coding overheads of - // motion vectors. Some account of this is made through adjustment of - // the error divisor. - ediv_size_correction = - AOMMAX(0.2, AOMMIN(5.0, get_linear_size_factor(cpi))); - if (ediv_size_correction < 1.0) - ediv_size_correction = -(1.0 / ediv_size_correction); - ediv_size_correction *= 4.0; - +// TODO(jimbankoski): remove #if here or above when this has been +// well tested. +#if !ALWAYS_ADJUST_BPM + // based on recent history adjust expectations of bits per macroblock. + last_group_rate_err = + (double)twopass->rolling_arf_group_actual_bits / + DOUBLE_DIVIDE_CHECK((double)twopass->rolling_arf_group_target_bits); + last_group_rate_err = AOMMAX(0.25, AOMMIN(4.0, last_group_rate_err)); + twopass->bpm_factor *= (3.0 + last_group_rate_err) / 4.0; + twopass->bpm_factor = AOMMAX(0.25, AOMMIN(4.0, twopass->bpm_factor)); +#endif // Try and pick a max Q that will be high enough to encode the // content at the given rate. for (q = rc->best_quality; q < rc->worst_quality; ++q) { - const double factor = calc_correction_factor( - av_err_per_mb, ERR_DIVISOR - ediv_size_correction, FACTOR_PT_LOW, - FACTOR_PT_HIGH, q, cpi->common.bit_depth); + const double factor = + calc_correction_factor(av_err_per_mb, ERR_DIVISOR, q); const int bits_per_mb = av1_rc_bits_per_mb( - INTER_FRAME, q, factor * speed_term * group_weight_factor, + INTER_FRAME, q, + factor * speed_term * cpi->twopass.bpm_factor * noise_factor, cpi->common.bit_depth); if (bits_per_mb <= target_norm_bits_per_mb) break; } @@ -1184,6 +1466,32 @@ void av1_init_second_pass(AV1_COMP *cpi) { *stats = *twopass->stats_in_end; twopass->total_left_stats = *stats; + { + double modified_score_total = 0.0; + const FIRSTPASS_STATS *s = twopass->stats_in; + double av_err; + av_err = get_distribution_av_err(twopass); + // The first scan is unclamped and gives a raw average. + while (s < twopass->stats_in_end) { + modified_score_total += calculate_mod_frame_score(cpi, oxcf, s, av_err); + ++s; + } + + // The average error from this first scan is used to define the midpoint + // error for the rate distribution function. + twopass->mean_mod_score = + modified_score_total / DOUBLE_DIVIDE_CHECK(stats->count); + + modified_score_total = 0.0; + s = twopass->stats_in; + while (s < twopass->stats_in_end) { + modified_score_total += + calculate_norm_frame_score(cpi, twopass, oxcf, s, av_err); + ++s; + } + twopass->normalized_score_left = modified_score_total; + } + frame_rate = 10000000.0 * stats->count / stats->duration; // 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 @@ -1197,24 +1505,6 @@ void av1_init_second_pass(AV1_COMP *cpi) { // This variable monitors how far behind the second ref update is lagging. twopass->sr_update_lag = 1; - // Scan the first pass file and calculate a modified total error based upon - // the bias/power function used to allocate bits. - { - const double avg_error = - stats->coded_error / DOUBLE_DIVIDE_CHECK(stats->count); - const FIRSTPASS_STATS *s = twopass->stats_in; - double modified_error_total = 0.0; - twopass->modified_error_min = - (avg_error * oxcf->two_pass_vbrmin_section) / 100; - twopass->modified_error_max = - (avg_error * oxcf->two_pass_vbrmax_section) / 100; - while (s < twopass->stats_in_end) { - modified_error_total += calculate_modified_err(cpi, twopass, oxcf, s); - ++s; - } - twopass->modified_error_left = modified_error_total; - } - // Reset the vbr bits off target counters cpi->rc.vbr_bits_off_target = 0; cpi->rc.vbr_bits_off_target_fast = 0; @@ -1225,43 +1515,54 @@ void av1_init_second_pass(AV1_COMP *cpi) { twopass->kf_zeromotion_pct = 100; twopass->last_kfgroup_zeromotion_pct = 100; + // Initialize bits per macro_block estimate correction factor. + twopass->bpm_factor = 1.0; + // Initialize actual and target bits counters for ARF groups so that + // at the start we have a neutral bpm adjustment. + twopass->rolling_arf_group_target_bits = 1; + twopass->rolling_arf_group_actual_bits = 1; + if (oxcf->resize_mode != RESIZE_NONE) { setup_rf_level_maxq(cpi); } + + // Initialize the arnr strangth adjustment to 0 + twopass->arnr_strength_adjustment = 0; } #define SR_DIFF_PART 0.0015 -#define MOTION_AMP_PART 0.003 #define INTRA_PART 0.005 #define DEFAULT_DECAY_LIMIT 0.75 #define LOW_SR_DIFF_TRHESH 0.1 #define SR_DIFF_MAX 128.0 +#define LOW_CODED_ERR_PER_MB 10.0 +#define NCOUNT_FRAME_II_THRESH 6.0 static double get_sr_decay_rate(const AV1_COMP *cpi, const FIRSTPASS_STATS *frame) { - const int num_mbs = (cpi->oxcf.resize_mode != RESIZE_NONE) ? cpi->initial_mbs - : cpi->common.MBs; - double sr_diff = (frame->sr_coded_error - frame->coded_error) / num_mbs; + double sr_diff = (frame->sr_coded_error - frame->coded_error); double sr_decay = 1.0; double modified_pct_inter; double modified_pcnt_intra; - const double motion_amplitude_factor = - frame->pcnt_motion * ((frame->mvc_abs + frame->mvr_abs) / 2); + const double motion_amplitude_part = + frame->pcnt_motion * ((frame->mvc_abs + frame->mvr_abs) / + (cpi->initial_height + cpi->initial_width)); modified_pct_inter = frame->pcnt_inter; - if ((frame->intra_error / DOUBLE_DIVIDE_CHECK(frame->coded_error)) < - (double)NCOUNT_FRAME_II_THRESH) { - modified_pct_inter = frame->pcnt_inter - frame->pcnt_neutral; + if ((frame->coded_error > LOW_CODED_ERR_PER_MB) && + ((frame->intra_error / DOUBLE_DIVIDE_CHECK(frame->coded_error)) < + (double)NCOUNT_FRAME_II_THRESH)) { + modified_pct_inter = + frame->pcnt_inter + frame->pcnt_intra_low - frame->pcnt_neutral; } modified_pcnt_intra = 100 * (1.0 - modified_pct_inter); if ((sr_diff > LOW_SR_DIFF_TRHESH)) { sr_diff = AOMMIN(sr_diff, SR_DIFF_MAX); - sr_decay = 1.0 - (SR_DIFF_PART * sr_diff) - - (MOTION_AMP_PART * motion_amplitude_factor) - + sr_decay = 1.0 - (SR_DIFF_PART * sr_diff) - motion_amplitude_part - (INTRA_PART * modified_pcnt_intra); } - return AOMMAX(sr_decay, AOMMIN(DEFAULT_DECAY_LIMIT, modified_pct_inter)); + return AOMMAX(sr_decay, DEFAULT_DECAY_LIMIT); } // This function gives an estimate of how badly we believe the prediction @@ -1362,38 +1663,59 @@ static void accumulate_frame_motion_stats(const FIRSTPASS_STATS *stats, } } -#define BASELINE_ERR_PER_MB 1000.0 +#define BASELINE_ERR_PER_MB 12500.0 static double calc_frame_boost(AV1_COMP *cpi, const FIRSTPASS_STATS *this_frame, - double this_frame_mv_in_out, double max_boost) { + double this_frame_mv_in_out) { double frame_boost; const double lq = av1_convert_qindex_to_q( cpi->rc.avg_frame_qindex[INTER_FRAME], cpi->common.bit_depth); const double boost_q_correction = AOMMIN((0.5 + (lq * 0.015)), 1.5); - int num_mbs = (cpi->oxcf.resize_mode != RESIZE_NONE) ? cpi->initial_mbs - : cpi->common.MBs; - - // Correct for any inactive region in the image - num_mbs = (int)AOMMAX(1, num_mbs * calculate_active_area(cpi, this_frame)); + const double active_area = calculate_active_area(cpi, this_frame); // Underlying boost factor is based on inter error ratio. - frame_boost = (BASELINE_ERR_PER_MB * num_mbs) / + frame_boost = (BASELINE_ERR_PER_MB * active_area) / DOUBLE_DIVIDE_CHECK(this_frame->coded_error); - frame_boost = frame_boost * BOOST_FACTOR * boost_q_correction; - // Increase boost for frames where new data coming into frame (e.g. zoom out). - // Slightly reduce boost if there is a net balance of motion out of the frame - // (zoom in). The range for this_frame_mv_in_out is -1.0 to +1.0. if (this_frame_mv_in_out > 0.0) frame_boost += frame_boost * (this_frame_mv_in_out * 2.0); - // In the extreme case the boost is halved. - else - frame_boost += frame_boost * (this_frame_mv_in_out / 2.0); + + // Q correction and scalling + frame_boost = frame_boost * boost_q_correction; + + return AOMMIN(frame_boost, GF_MAX_FRAME_BOOST * boost_q_correction); +} + +#define KF_BASELINE_ERR_PER_MB 12500.0 +static double calc_kf_frame_boost(AV1_COMP *cpi, + const FIRSTPASS_STATS *this_frame, + double *sr_accumulator, + double this_frame_mv_in_out, + double max_boost) { + double frame_boost; + const double lq = av1_convert_qindex_to_q( + cpi->rc.avg_frame_qindex[INTER_FRAME], cpi->common.bit_depth); + const double boost_q_correction = AOMMIN((0.50 + (lq * 0.015)), 2.00); + const double active_area = calculate_active_area(cpi, this_frame); + + // Underlying boost factor is based on inter error ratio. + frame_boost = (KF_BASELINE_ERR_PER_MB * active_area) / + DOUBLE_DIVIDE_CHECK(this_frame->coded_error + *sr_accumulator); + // Update the accumulator for second ref error difference. + // This is intended to give an indication of how much the coded error is + // increasing over time. + *sr_accumulator += (this_frame->sr_coded_error - this_frame->coded_error); + *sr_accumulator = AOMMAX(0.0, *sr_accumulator); + + // Small adjustment for cases where there is a zoom out + if (this_frame_mv_in_out > 0.0) + frame_boost += frame_boost * (this_frame_mv_in_out * 2.0); + // Q correction and scalling + frame_boost = frame_boost * boost_q_correction; return AOMMIN(frame_boost, max_boost * boost_q_correction); } -static int calc_arf_boost(AV1_COMP *cpi, int offset, int f_frames, int b_frames, - int *f_boost, int *b_boost) { +static int calc_arf_boost(AV1_COMP *cpi, int f_frames, int b_frames) { TWO_PASS *const twopass = &cpi->twopass; int i; double boost_score = 0.0; @@ -1407,7 +1729,7 @@ static int calc_arf_boost(AV1_COMP *cpi, int offset, int f_frames, int b_frames, // Search forward from the proposed arf/next gf position. for (i = 0; i < f_frames; ++i) { - const FIRSTPASS_STATS *this_frame = read_frame_stats(twopass, i + offset); + const FIRSTPASS_STATS *this_frame = read_frame_stats(twopass, i); if (this_frame == NULL) break; // Update the motion related elements to the boost calculation. @@ -1417,8 +1739,7 @@ static int calc_arf_boost(AV1_COMP *cpi, int offset, int f_frames, int b_frames, // We want to discount the flash frame itself and the recovery // frame that follows as both will have poor scores. - flash_detected = detect_flash(twopass, i + offset) || - detect_flash(twopass, i + offset + 1); + flash_detected = detect_flash(twopass, i) || detect_flash(twopass, i + 1); // Accumulate the effect of prediction quality decay. if (!flash_detected) { @@ -1428,12 +1749,11 @@ static int calc_arf_boost(AV1_COMP *cpi, int offset, int f_frames, int b_frames, : decay_accumulator; } - boost_score += - decay_accumulator * - calc_frame_boost(cpi, this_frame, this_frame_mv_in_out, GF_MAX_BOOST); + boost_score += decay_accumulator * + calc_frame_boost(cpi, this_frame, this_frame_mv_in_out); } - *f_boost = (int)boost_score; + arf_boost = (int)boost_score; // Reset for backward looking loop. boost_score = 0.0; @@ -1445,7 +1765,7 @@ static int calc_arf_boost(AV1_COMP *cpi, int offset, int f_frames, int b_frames, // Search backward towards last gf position. for (i = -1; i >= -b_frames; --i) { - const FIRSTPASS_STATS *this_frame = read_frame_stats(twopass, i + offset); + const FIRSTPASS_STATS *this_frame = read_frame_stats(twopass, i); if (this_frame == NULL) break; // Update the motion related elements to the boost calculation. @@ -1455,8 +1775,7 @@ static int calc_arf_boost(AV1_COMP *cpi, int offset, int f_frames, int b_frames, // We want to discount the the flash frame itself and the recovery // frame that follows as both will have poor scores. - flash_detected = detect_flash(twopass, i + offset) || - detect_flash(twopass, i + offset + 1); + flash_detected = detect_flash(twopass, i) || detect_flash(twopass, i + 1); // Cumulative effect of prediction quality decay. if (!flash_detected) { @@ -1466,15 +1785,13 @@ static int calc_arf_boost(AV1_COMP *cpi, int offset, int f_frames, int b_frames, : decay_accumulator; } - boost_score += - decay_accumulator * - calc_frame_boost(cpi, this_frame, this_frame_mv_in_out, GF_MAX_BOOST); + boost_score += decay_accumulator * + calc_frame_boost(cpi, this_frame, this_frame_mv_in_out); } - *b_boost = (int)boost_score; + arf_boost += (int)boost_score; - arf_boost = (*f_boost + *b_boost); - if (arf_boost < ((b_frames + f_frames) * 20)) - arf_boost = ((b_frames + f_frames) * 20); + if (arf_boost < ((b_frames + f_frames) * 40)) + arf_boost = ((b_frames + f_frames) * 40); arf_boost = AOMMAX(arf_boost, MIN_ARF_GF_BOOST); return arf_boost; @@ -2346,7 +2663,7 @@ static void define_gf_group_structure(AV1_COMP *cpi) { } static void allocate_gf_group_bits(AV1_COMP *cpi, int64_t gf_group_bits, - double group_error, int gf_arf_bits) { + int gf_arf_bits) { RATE_CONTROL *const rc = &cpi->rc; const AV1EncoderConfig *const oxcf = &cpi->oxcf; TWO_PASS *const twopass = &cpi->twopass; @@ -2356,10 +2673,8 @@ static void allocate_gf_group_bits(AV1_COMP *cpi, int64_t gf_group_bits, int frame_index = 0; int target_frame_size; int key_frame; - const int max_bits = frame_max_bits(&cpi->rc, &cpi->oxcf); + const int max_bits = frame_max_bits(&cpi->rc, oxcf); int64_t total_group_bits = gf_group_bits; - double modified_err = 0.0; - double err_fraction; int mid_boost_bits = 0; int ext_arf_boost[MAX_EXT_ARFS]; @@ -2403,18 +2718,23 @@ static void allocate_gf_group_bits(AV1_COMP *cpi, int64_t gf_group_bits, } } + int normal_frames = (rc->baseline_gf_interval - rc->source_alt_ref_pending); + int normal_frame_bits; + int last_frame_reduction = 0; + if (normal_frames > 1) + normal_frame_bits = (int)(total_group_bits / normal_frames); + else + normal_frame_bits = (int)total_group_bits; + // Allocate bits to the other frames in the group. - for (i = 0; i < rc->baseline_gf_interval - rc->source_alt_ref_pending; ++i) { + for (i = 0; i < normal_frames; ++i) { if (EOF == input_stats(twopass, &frame_stats)) break; - modified_err = calculate_modified_err(cpi, twopass, oxcf, &frame_stats); - - if (group_error > 0) - err_fraction = modified_err / DOUBLE_DIVIDE_CHECK(group_error); - else - err_fraction = 0.0; - - target_frame_size = (int)((double)total_group_bits * err_fraction); + target_frame_size = normal_frame_bits; + if ((i == (normal_frames - 1)) && (i >= 1)) { + last_frame_reduction = normal_frame_bits / 16; + target_frame_size -= last_frame_reduction; + } if (rc->source_alt_ref_pending && cpi->multi_arf_enabled) { mid_boost_bits += (target_frame_size >> 4); @@ -2479,6 +2799,20 @@ static void allocate_gf_group_bits(AV1_COMP *cpi, int64_t gf_group_bits, cpi->multi_arf_last_grp_enabled = cpi->multi_arf_enabled; } +// Adjusts the ARNF filter for a GF group. +static void adjust_group_arnr_filter(AV1_COMP *cpi, double section_noise, + double section_inter, + double section_motion) { + TWO_PASS *const twopass = &cpi->twopass; + double section_zeromv = section_inter - section_motion; + + twopass->arnr_strength_adjustment = 0; + + if ((section_zeromv < 0.10) || (section_noise <= (SECTION_NOISE_DEF * 0.75))) + twopass->arnr_strength_adjustment -= 1; + if (section_zeromv > 0.50) twopass->arnr_strength_adjustment += 1; +} + // Analyse and define a gf/arf group. static void define_gf_group(AV1_COMP *cpi, FIRSTPASS_STATS *this_frame) { AV1_COMMON *const cm = &cpi->common; @@ -2489,19 +2823,22 @@ static void define_gf_group(AV1_COMP *cpi, FIRSTPASS_STATS *this_frame) { const FIRSTPASS_STATS *const start_pos = twopass->stats_in; int i; - double boost_score = 0.0; - double old_boost_score = 0.0; double gf_group_err = 0.0; #if GROUP_ADAPTIVE_MAXQ double gf_group_raw_error = 0.0; #endif + double gf_group_noise = 0.0; double gf_group_skip_pct = 0.0; double gf_group_inactive_zone_rows = 0.0; + double gf_group_inter = 0.0; + double gf_group_motion = 0.0; double gf_first_frame_err = 0.0; double mod_frame_err = 0.0; double mv_ratio_accumulator = 0.0; +#if CONFIG_BGSPRITE double decay_accumulator = 1.0; +#endif // CONFIG_BGSPRITE double zero_motion_accumulator = 1.0; double loop_decay_rate = 1.00; @@ -2511,15 +2848,14 @@ static void define_gf_group(AV1_COMP *cpi, FIRSTPASS_STATS *this_frame) { double mv_in_out_accumulator = 0.0; double abs_mv_in_out_accumulator = 0.0; double mv_ratio_accumulator_thresh; + double sr_accumulator = 0.0; + const double av_err = get_distribution_av_err(twopass); unsigned int allow_alt_ref = is_altref_enabled(cpi); - int f_boost = 0; - int b_boost = 0; int flash_detected; int active_max_gf_interval; int active_min_gf_interval; int64_t gf_group_bits; - double gf_group_error_left; int gf_arf_bits; const int is_key_frame = frame_is_intra_only(cm); const int arf_active_or_kf = is_key_frame || rc->source_alt_ref_active; @@ -2537,7 +2873,8 @@ static void define_gf_group(AV1_COMP *cpi, FIRSTPASS_STATS *this_frame) { av1_zero(next_frame); // Load stats for the current frame. - mod_frame_err = calculate_modified_err(cpi, twopass, oxcf, this_frame); + mod_frame_err = + calculate_norm_frame_score(cpi, twopass, oxcf, this_frame, av_err); // Note the error of the frame at the start of the group. This will be // the GF frame error if we code a normal gf. @@ -2550,8 +2887,11 @@ static void define_gf_group(AV1_COMP *cpi, FIRSTPASS_STATS *this_frame) { #if GROUP_ADAPTIVE_MAXQ gf_group_raw_error -= this_frame->coded_error; #endif + gf_group_noise -= this_frame->frame_noise_energy; gf_group_skip_pct -= this_frame->intra_skip_pct; gf_group_inactive_zone_rows -= this_frame->inactive_zone_rows; + gf_group_inter -= this_frame->pcnt_inter; + gf_group_motion -= this_frame->pcnt_motion; } // Motion breakout threshold for loop below depends on image size. @@ -2566,9 +2906,10 @@ static void define_gf_group(AV1_COMP *cpi, FIRSTPASS_STATS *this_frame) { int int_lbq = (int)(av1_convert_qindex_to_q(rc->last_boosted_qindex, cpi->common.bit_depth)); - active_min_gf_interval = rc->min_gf_interval + AOMMIN(2, int_max_q / 200); - if (active_min_gf_interval > rc->max_gf_interval) - active_min_gf_interval = rc->max_gf_interval; + active_min_gf_interval = + rc->min_gf_interval + arf_active_or_kf + AOMMIN(2, int_max_q / 200); + active_min_gf_interval = + AOMMIN(active_min_gf_interval, rc->max_gf_interval + arf_active_or_kf); if (cpi->multi_arf_allowed) { active_max_gf_interval = rc->max_gf_interval; @@ -2577,13 +2918,19 @@ static void define_gf_group(AV1_COMP *cpi, FIRSTPASS_STATS *this_frame) { // bits to spare and are better with a smaller interval and smaller boost. // At high Q when there are few bits to spare we are better with a longer // interval to spread the cost of the GF. - active_max_gf_interval = 12 + AOMMIN(4, (int_lbq / 6)); + // active_max_gf_interval = 12 + AOMMIN(4, (int_lbq / 6)); + active_max_gf_interval = 12 + arf_active_or_kf + AOMMIN(4, (int_lbq / 6)); // We have: active_min_gf_interval <= rc->max_gf_interval if (active_max_gf_interval < active_min_gf_interval) active_max_gf_interval = active_min_gf_interval; else if (active_max_gf_interval > rc->max_gf_interval) - active_max_gf_interval = rc->max_gf_interval; + active_max_gf_interval = AOMMIN(active_max_gf_interval, + rc->max_gf_interval + arf_active_or_kf); + // Would the active max drop us out just before the near the next kf? + if ((active_max_gf_interval <= rc->frames_to_key) && + (active_max_gf_interval >= (rc->frames_to_key - rc->min_gf_interval))) + active_max_gf_interval = rc->frames_to_key / 2; } } @@ -2600,13 +2947,17 @@ static void define_gf_group(AV1_COMP *cpi, FIRSTPASS_STATS *this_frame) { ++i; // Accumulate error score of frames in this gf group. - mod_frame_err = calculate_modified_err(cpi, twopass, oxcf, this_frame); + mod_frame_err = + calculate_norm_frame_score(cpi, twopass, oxcf, this_frame, av_err); gf_group_err += mod_frame_err; #if GROUP_ADAPTIVE_MAXQ gf_group_raw_error += this_frame->coded_error; #endif + gf_group_noise += this_frame->frame_noise_energy; gf_group_skip_pct += this_frame->intra_skip_pct; gf_group_inactive_zone_rows += this_frame->inactive_zone_rows; + gf_group_inter += this_frame->pcnt_inter; + gf_group_motion += this_frame->pcnt_motion; if (EOF == input_stats(twopass, &next_frame)) break; @@ -2636,7 +2987,9 @@ static void define_gf_group(AV1_COMP *cpi, FIRSTPASS_STATS *this_frame) { last_loop_decay_rate = loop_decay_rate; loop_decay_rate = get_prediction_decay_rate(cpi, &next_frame); +#if CONFIG_BGSPRITE decay_accumulator = decay_accumulator * loop_decay_rate; +#endif // CONFIG_BGSPRITE // Monitor for static sections. zero_motion_accumulator = AOMMIN( @@ -2649,55 +3002,52 @@ static void define_gf_group(AV1_COMP *cpi, FIRSTPASS_STATS *this_frame) { allow_alt_ref = 0; break; } - } - // Calculate a boost number for this frame. - boost_score += - decay_accumulator * - calc_frame_boost(cpi, &next_frame, this_frame_mv_in_out, GF_MAX_BOOST); + // Update the accumulator for second ref error difference. + // This is intended to give an indication of how much the coded error is + // increasing over time. + if (i == 1) { + sr_accumulator += next_frame.coded_error; + } else { + sr_accumulator += (next_frame.sr_coded_error - next_frame.coded_error); + } + } // Break out conditions. if ( // Break at active_max_gf_interval unless almost totally static. - (i >= (active_max_gf_interval + arf_active_or_kf) && - zero_motion_accumulator < 0.995) || + (i >= active_max_gf_interval && zero_motion_accumulator < 0.995) || ( // Don't break out with a very short interval. - (i >= active_min_gf_interval + arf_active_or_kf) && + (i >= active_min_gf_interval) && + ((rc->frames_to_key - i) >= rc->min_gf_interval) && (!flash_detected) && ((mv_ratio_accumulator > mv_ratio_accumulator_thresh) || - (abs_mv_in_out_accumulator > 3.0) || - (mv_in_out_accumulator < -2.0) || - ((boost_score - old_boost_score) < BOOST_BREAKOUT)))) { + (abs_mv_in_out_accumulator > ARF_ABS_ZOOM_THRESH) || + (sr_accumulator > next_frame.intra_error)))) { // If GF group interval is < 12, we force it to be 8. Otherwise, // if it is >= 12, we keep it as is. // NOTE: 'i' is 1 more than the GF group interval candidate that is being // checked. - if (i == (8 + 1) || i >= (12 + 1)) { - boost_score = old_boost_score; - break; - } + if (i == (8 + 1) || i >= (12 + 1)) break; } *this_frame = next_frame; - old_boost_score = boost_score; } - twopass->gf_zeromotion_pct = (int)(zero_motion_accumulator * 1000.0); - // Was the group length constrained by the requirement for a new KF? rc->constrained_gf_group = (i >= rc->frames_to_key) ? 1 : 0; const int num_mbs = (cpi->oxcf.resize_mode != RESIZE_NONE) ? cpi->initial_mbs : cpi->common.MBs; - assert(num_mbs > 0); - if (i) avg_sr_coded_error /= i; // Should we use the alternate reference frame. if (allow_alt_ref && (i < cpi->oxcf.lag_in_frames) && (i >= rc->min_gf_interval)) { + const int forward_frames = (rc->frames_to_key - i >= i - 1) + ? i - 1 + : AOMMAX(0, rc->frames_to_key - i); // Calculate the boost for alt ref. - rc->gfu_boost = - calc_arf_boost(cpi, 0, (i - 1), (i - 1), &f_boost, &b_boost); + rc->gfu_boost = calc_arf_boost(cpi, forward_frames, (i - 1)); rc->source_alt_ref_pending = 1; // Test to see if multi arf is appropriate. @@ -2707,6 +3057,8 @@ static void define_gf_group(AV1_COMP *cpi, FIRSTPASS_STATS *this_frame) { ? 1 : 0; #if CONFIG_BGSPRITE + if (i) avg_sr_coded_error /= i; + if (non_zero_pcnt_second_ref_count) { avg_pcnt_second_ref /= non_zero_pcnt_second_ref_count; } @@ -2718,12 +3070,15 @@ static void define_gf_group(AV1_COMP *cpi, FIRSTPASS_STATS *this_frame) { } #endif // CONFIG_BGSPRITE } else { - rc->gfu_boost = AOMMAX((int)boost_score, MIN_ARF_GF_BOOST); + rc->gfu_boost = calc_arf_boost(cpi, 0, (i - 1)); rc->source_alt_ref_pending = 0; } + rc->gfu_boost = AOMMIN((int)rc->gfu_boost, i * 200); + // Set the interval until the next gf. rc->baseline_gf_interval = i - (is_key_frame || rc->source_alt_ref_pending); + if (non_zero_stdev_count) avg_raw_err_stdev /= non_zero_stdev_count; // Disable extra altrefs and backward refs for "still" gf group: @@ -2771,30 +3126,34 @@ static void define_gf_group(AV1_COMP *cpi, FIRSTPASS_STATS *this_frame) { const int vbr_group_bits_per_frame = (int)(gf_group_bits / rc->baseline_gf_interval); const double group_av_err = gf_group_raw_error / rc->baseline_gf_interval; + const double group_av_noise = gf_group_noise / rc->baseline_gf_interval; const double group_av_skip_pct = gf_group_skip_pct / rc->baseline_gf_interval; const double group_av_inactive_zone = ((gf_group_inactive_zone_rows * 2) / (rc->baseline_gf_interval * (double)cm->mb_rows)); - - int tmp_q; - // rc factor is a weight factor that corrects for local rate control drift. - double rc_factor = 1.0; - if (rc->rate_error_estimate > 0) { - rc_factor = AOMMAX(RC_FACTOR_MIN, - (double)(100 - rc->rate_error_estimate) / 100.0); - } else { - rc_factor = AOMMIN(RC_FACTOR_MAX, - (double)(100 - rc->rate_error_estimate) / 100.0); - } - tmp_q = get_twopass_worst_quality( + int tmp_q = get_twopass_worst_quality( cpi, group_av_err, (group_av_skip_pct + group_av_inactive_zone), - vbr_group_bits_per_frame, twopass->kfgroup_inter_fraction * rc_factor); + group_av_noise, vbr_group_bits_per_frame); twopass->active_worst_quality = - AOMMAX(tmp_q, twopass->active_worst_quality >> 1); + (tmp_q + (twopass->active_worst_quality * 3)) >> 2; +#if ALWAYS_ADJUST_BPM + // Reset rolling actual and target bits counters for ARF groups. + twopass->rolling_arf_group_target_bits = 0; + twopass->rolling_arf_group_actual_bits = 0; +#endif // ALWAYS_ADJUST_BPM } #endif + // Context Adjustment of ARNR filter strength + if (rc->baseline_gf_interval > 1) { + adjust_group_arnr_filter(cpi, (gf_group_noise / rc->baseline_gf_interval), + (gf_group_inter / rc->baseline_gf_interval), + (gf_group_motion / rc->baseline_gf_interval)); + } else { + twopass->arnr_strength_adjustment = 0; + } + // Calculate the extra bits to be used for boosted frame(s) gf_arf_bits = calculate_boost_bits(rc->baseline_gf_interval, rc->gfu_boost, gf_group_bits); @@ -2802,22 +3161,8 @@ static void define_gf_group(AV1_COMP *cpi, FIRSTPASS_STATS *this_frame) { // Adjust KF group bits and error remaining. twopass->kf_group_error_left -= (int64_t)gf_group_err; - // If this is an arf update we want to remove the score for the overlay - // frame at the end which will usually be very cheap to code. - // The overlay frame has already, in effect, been coded so we want to spread - // the remaining bits among the other frames. - // For normal GFs remove the score for the GF itself unless this is - // also a key frame in which case it has already been accounted for. - if (rc->source_alt_ref_pending) { - gf_group_error_left = gf_group_err - mod_frame_err; - } else if (is_key_frame == 0) { - gf_group_error_left = gf_group_err - gf_first_frame_err; - } else { - gf_group_error_left = gf_group_err; - } - // Allocate bits to each of the frames in the GF group. - allocate_gf_group_bits(cpi, gf_group_bits, gf_group_error_left, gf_arf_bits); + allocate_gf_group_bits(cpi, gf_group_bits, gf_arf_bits); // Reset the file position. reset_fpf_position(twopass, start_pos); @@ -2827,6 +3172,11 @@ static void define_gf_group(AV1_COMP *cpi, FIRSTPASS_STATS *this_frame) { twopass->section_intra_rating = calculate_section_intra_ratio( start_pos, twopass->stats_in_end, rc->baseline_gf_interval); } +#if !ALWAYS_ADJUST_BPM + // Reset rolling actual and target bits counters for ARF groups. + twopass->rolling_arf_group_target_bits = 0; + twopass->rolling_arf_group_actual_bits = 0; +#endif // !ALWAYS_ADJUST_BPM } // Threshold for use of the lagging second reference frame. High second ref @@ -2854,6 +3204,9 @@ static void define_gf_group(AV1_COMP *cpi, FIRSTPASS_STATS *this_frame) { // ratio in the next frame. #define II_IMPROVEMENT_THRESHOLD 3.5 #define KF_II_MAX 128.0 +#define II_FACTOR 12.5 +// Test for very low intra complexity which could cause false key frames +#define V_LOW_INTRA 0.5 static int test_candidate_kf(TWO_PASS *twopass, const FIRSTPASS_STATS *last_frame, @@ -2893,7 +3246,7 @@ static int test_candidate_kf(TWO_PASS *twopass, // Examine how well the key frame predicts subsequent frames. for (i = 0; i < 16; ++i) { - double next_iiratio = (BOOST_FACTOR * local_next_frame.intra_error / + double next_iiratio = (II_FACTOR * local_next_frame.intra_error / DOUBLE_DIVIDE_CHECK(local_next_frame.coded_error)); if (next_iiratio > KF_II_MAX) next_iiratio = KF_II_MAX; @@ -2913,7 +3266,7 @@ static int test_candidate_kf(TWO_PASS *twopass, 0.20) && (next_iiratio < 3.0)) || ((boost_score - old_boost_score) < 3.0) || - (local_next_frame.intra_error < 200)) { + (local_next_frame.intra_error < V_LOW_INTRA)) { break; } @@ -2951,14 +3304,15 @@ static void find_next_key_frame(AV1_COMP *cpi, FIRSTPASS_STATS *this_frame) { FIRSTPASS_STATS next_frame; FIRSTPASS_STATS last_frame; int kf_bits = 0; - int loop_decay_counter = 0; double decay_accumulator = 1.0; - double av_decay_accumulator = 0.0; double zero_motion_accumulator = 1.0; double boost_score = 0.0; double kf_mod_err = 0.0; double kf_group_err = 0.0; double recent_loop_decay[FRAMES_TO_CHECK_DECAY]; + double sr_accumulator = 0.0; + double abs_mv_in_out_accumulator = 0.0; + const double av_err = get_distribution_av_err(twopass); av1_zero(next_frame); @@ -2983,7 +3337,8 @@ static void find_next_key_frame(AV1_COMP *cpi, FIRSTPASS_STATS *this_frame) { twopass->kf_group_bits = 0; // Total bits available to kf group twopass->kf_group_error_left = 0; // Group modified error score. - kf_mod_err = calculate_modified_err(cpi, twopass, oxcf, this_frame); + kf_mod_err = + calculate_norm_frame_score(cpi, twopass, oxcf, this_frame, av_err); // Initialize the decay rates for the recent frames to check for (j = 0; j < FRAMES_TO_CHECK_DECAY; ++j) recent_loop_decay[j] = 1.0; @@ -2993,7 +3348,8 @@ static void find_next_key_frame(AV1_COMP *cpi, FIRSTPASS_STATS *this_frame) { while (twopass->stats_in < twopass->stats_in_end && rc->frames_to_key < cpi->oxcf.key_freq) { // Accumulate kf group error. - kf_group_err += calculate_modified_err(cpi, twopass, oxcf, this_frame); + kf_group_err += + calculate_norm_frame_score(cpi, twopass, oxcf, this_frame, av_err); // Load the next frame's stats. last_frame = *this_frame; @@ -3053,7 +3409,8 @@ static void find_next_key_frame(AV1_COMP *cpi, FIRSTPASS_STATS *this_frame) { // Rescan to get the correct error data for the forced kf group. for (i = 0; i < rc->frames_to_key; ++i) { - kf_group_err += calculate_modified_err(cpi, twopass, oxcf, &tmp_frame); + kf_group_err += + calculate_norm_frame_score(cpi, twopass, oxcf, &tmp_frame, av_err); input_stats(twopass, &tmp_frame); } rc->next_key_frame_forced = 1; @@ -3067,11 +3424,12 @@ static void find_next_key_frame(AV1_COMP *cpi, FIRSTPASS_STATS *this_frame) { // Special case for the last key frame of the file. if (twopass->stats_in >= twopass->stats_in_end) { // Accumulate kf group error. - kf_group_err += calculate_modified_err(cpi, twopass, oxcf, this_frame); + kf_group_err += + calculate_norm_frame_score(cpi, twopass, oxcf, this_frame, av_err); } // Calculate the number of bits that should be assigned to the kf group. - if (twopass->bits_left > 0 && twopass->modified_error_left > 0.0) { + if (twopass->bits_left > 0 && twopass->normalized_score_left > 0.0) { // Maximum number of bits for a single normal frame (not key frame). const int max_bits = frame_max_bits(rc, &cpi->oxcf); @@ -3081,7 +3439,7 @@ static void find_next_key_frame(AV1_COMP *cpi, FIRSTPASS_STATS *this_frame) { // Default allocation based on bits left and relative // complexity of the section. twopass->kf_group_bits = (int64_t)( - twopass->bits_left * (kf_group_err / twopass->modified_error_left)); + twopass->bits_left * (kf_group_err / twopass->normalized_score_left)); // Clip based on maximum per frame rate defined by the user. max_grp_bits = (int64_t)max_bits * (int64_t)rc->frames_to_key; @@ -3097,35 +3455,43 @@ static void find_next_key_frame(AV1_COMP *cpi, FIRSTPASS_STATS *this_frame) { // Scan through the kf group collating various stats used to determine // how many bits to spend on it. - decay_accumulator = 1.0; boost_score = 0.0; + for (i = 0; i < (rc->frames_to_key - 1); ++i) { if (EOF == input_stats(twopass, &next_frame)) break; - // Monitor for static sections. - zero_motion_accumulator = AOMMIN(zero_motion_accumulator, - get_zero_motion_factor(cpi, &next_frame)); - - // Not all frames in the group are necessarily used in calculating boost. - if ((i <= rc->max_gf_interval) || - ((i <= (rc->max_gf_interval * 4)) && (decay_accumulator > 0.5))) { - const double frame_boost = - calc_frame_boost(cpi, this_frame, 0, KF_MAX_BOOST); - - // How fast is prediction quality decaying. - if (!detect_flash(twopass, 0)) { - const double loop_decay_rate = - get_prediction_decay_rate(cpi, &next_frame); - decay_accumulator *= loop_decay_rate; - decay_accumulator = AOMMAX(decay_accumulator, MIN_DECAY_FACTOR); - av_decay_accumulator += decay_accumulator; - ++loop_decay_counter; - } - boost_score += (decay_accumulator * frame_boost); + if (i <= KF_BOOST_SCAN_MAX_FRAMES) { + double frame_boost; + double zm_factor; + + // Monitor for static sections. + zero_motion_accumulator = AOMMIN( + zero_motion_accumulator, get_zero_motion_factor(cpi, &next_frame)); + + // Factor 0.75-1.25 based on how much of frame is static. + zm_factor = (0.75 + (zero_motion_accumulator / 2.0)); + + // The second (lagging) ref error is not valid immediately after + // a key frame because either the lag has not built up (in the + // case of the first key frame or it points to a refernce before + // the new key frame. + if (i < 2) sr_accumulator = 0.0; + frame_boost = calc_kf_frame_boost(cpi, &next_frame, &sr_accumulator, 0, + KF_MAX_FRAME_BOOST * zm_factor); + + boost_score += frame_boost; + + // Measure of zoom. Large zoom tends to indicate reduced boost. + abs_mv_in_out_accumulator += + fabs(next_frame.mv_in_out_count * next_frame.pcnt_motion); + + if ((frame_boost < 25.00) || + (abs_mv_in_out_accumulator > KF_ABS_ZOOM_THRESH)) + break; + } else { + break; } } - if (loop_decay_counter > 0) - av_decay_accumulator /= (double)loop_decay_counter; reset_fpf_position(twopass, start_position); @@ -3137,24 +3503,13 @@ static void find_next_key_frame(AV1_COMP *cpi, FIRSTPASS_STATS *this_frame) { start_position, twopass->stats_in_end, rc->frames_to_key); // Apply various clamps for min and max boost - rc->kf_boost = (int)(av_decay_accumulator * boost_score); - rc->kf_boost = AOMMAX(rc->kf_boost, (rc->frames_to_key * 3)); - rc->kf_boost = AOMMAX(rc->kf_boost, MIN_KF_BOOST); + rc->kf_boost = AOMMAX((int)boost_score, (rc->frames_to_key * 3)); + rc->kf_boost = AOMMAX(rc->kf_boost, MIN_KF_TOT_BOOST); + rc->kf_boost = AOMMIN(rc->kf_boost, MAX_KF_TOT_BOOST); // Work out how many bits to allocate for the key frame itself. kf_bits = calculate_boost_bits((rc->frames_to_key - 1), rc->kf_boost, twopass->kf_group_bits); - - // Work out the fraction of the kf group bits reserved for the inter frames - // within the group after discounting the bits for the kf itself. - if (twopass->kf_group_bits) { - twopass->kfgroup_inter_fraction = - (double)(twopass->kf_group_bits - kf_bits) / - (double)twopass->kf_group_bits; - } else { - twopass->kfgroup_inter_fraction = 1.0; - } - twopass->kf_group_bits -= kf_bits; // Save the bits to spend on the key frame. @@ -3163,12 +3518,12 @@ static void find_next_key_frame(AV1_COMP *cpi, FIRSTPASS_STATS *this_frame) { gf_group->rf_level[0] = KF_STD; // Note the total error score of the kf group minus the key frame itself. - twopass->kf_group_error_left = (int)(kf_group_err - kf_mod_err); + twopass->kf_group_error_left = (kf_group_err - kf_mod_err); // Adjust the count of total modified error left. // The count of bits left is adjusted elsewhere based on real coded frame // sizes. - twopass->modified_error_left -= kf_group_err; + twopass->normalized_score_left -= kf_group_err; } #if USE_GF16_MULTI_LAYER @@ -3507,9 +3862,11 @@ void av1_rc_get_second_pass_params(AV1_COMP *cpi) { const double section_inactive_zone = (twopass->total_left_stats.inactive_zone_rows * 2) / ((double)cm->mb_rows * section_length); + const double section_noise = + twopass->total_left_stats.frame_noise_energy / section_length; const int tmp_q = get_twopass_worst_quality( cpi, section_error, section_intra_skip + section_inactive_zone, - section_target_bandwidth, DEFAULT_GRP_WEIGHT); + section_noise, section_target_bandwidth); twopass->active_worst_quality = tmp_q; twopass->baseline_active_worst_quality = tmp_q; @@ -3608,6 +3965,10 @@ void av1_twopass_postencode_update(AV1_COMP *cpi) { rc->vbr_bits_off_target += rc->base_frame_target - rc->projected_frame_size; twopass->bits_left = AOMMAX(twopass->bits_left - bits_used, 0); + // Target vs actual bits for this arf group. + twopass->rolling_arf_group_target_bits += rc->this_frame_target; + twopass->rolling_arf_group_actual_bits += rc->projected_frame_size; + // Calculate the pct rc error. if (rc->total_actual_bits) { rc->rate_error_estimate = @@ -3627,9 +3988,7 @@ void av1_twopass_postencode_update(AV1_COMP *cpi) { ++twopass->gf_group.index; // If the rate control is drifting consider adjustment to min or maxq. - if ((cpi->oxcf.rc_mode != AOM_Q) && - (cpi->twopass.gf_zeromotion_pct < VLOW_MOTION_THRESHOLD) && - !cpi->rc.is_src_frame_alt_ref) { + if ((cpi->oxcf.rc_mode != AOM_Q) && !cpi->rc.is_src_frame_alt_ref) { const int maxq_adj_limit = rc->worst_quality - twopass->active_worst_quality; const int minq_adj_limit = diff --git a/av1/encoder/firstpass.h b/av1/encoder/firstpass.h index ee21b65f428ecbbfe739bb3555a4821e87b237fc..892eae54656304b2e4e2f1e04b9fb6077add4e75 100644 --- a/av1/encoder/firstpass.h +++ b/av1/encoder/firstpass.h @@ -72,11 +72,15 @@ typedef struct { double intra_error; double coded_error; double sr_coded_error; + double frame_noise_energy; double pcnt_inter; double pcnt_motion; double pcnt_second_ref; double pcnt_neutral; + double pcnt_intra_low; // Coded intra but low variance + double pcnt_intra_high; // Coded intra high variance double intra_skip_pct; + double intra_smooth_pct; // % of blocks that are smooth double inactive_zone_rows; // Image mask rows top and bottom. double inactive_zone_cols; // Image mask columns at left and right edges. double MVr; @@ -139,10 +143,10 @@ typedef struct { FIRSTPASS_STATS total_left_stats; int first_pass_done; int64_t bits_left; - double modified_error_min; - double modified_error_max; - double modified_error_left; + double normalized_score_left; + double mean_mod_score; double mb_av_energy; + double mb_smooth_pct; #if CONFIG_FP_MB_STATS uint8_t *frame_mb_stats_buf; @@ -156,21 +160,25 @@ typedef struct { int64_t kf_group_bits; // Error score of frames still to be coded in kf group - int64_t kf_group_error_left; + double kf_group_error_left; // The fraction for a kf groups total bits allocated to the inter frames double kfgroup_inter_fraction; + double bpm_factor; + int rolling_arf_group_target_bits; + int rolling_arf_group_actual_bits; + int sr_update_lag; int kf_zeromotion_pct; int last_kfgroup_zeromotion_pct; - int gf_zeromotion_pct; int active_worst_quality; int baseline_active_worst_quality; int extend_minq; int extend_maxq; int extend_minq_fast; + int arnr_strength_adjustment; GF_GROUP gf_group; } TWO_PASS; diff --git a/av1/encoder/ratectrl.c b/av1/encoder/ratectrl.c index 523ffa174c662a91181afd150f2e44857056d8f9..86e371b382b6cbf123f40351ad4dd13161498cfd 100644 --- a/av1/encoder/ratectrl.c +++ b/av1/encoder/ratectrl.c @@ -121,7 +121,7 @@ static void init_minq_luts(int *kf_low_m, int *kf_high_m, int *arfgf_low, kf_high_m[i] = get_minq_index(maxq, 0.0000021, -0.00125, 0.55, bit_depth); arfgf_low[i] = get_minq_index(maxq, 0.0000015, -0.0009, 0.30, bit_depth); arfgf_high[i] = get_minq_index(maxq, 0.0000021, -0.00125, 0.55, bit_depth); - inter[i] = get_minq_index(maxq, 0.00000271, -0.00113, 0.90, bit_depth); + inter[i] = get_minq_index(maxq, 0.00000271, -0.00113, 0.70, bit_depth); rtc[i] = get_minq_index(maxq, 0.00000271, -0.00113, 0.70, bit_depth); } } @@ -178,17 +178,19 @@ int av1_estimate_bits_at_q(FRAME_TYPE frame_type, int q, int mbs, int av1_rc_clamp_pframe_target_size(const AV1_COMP *const cpi, int target) { const RATE_CONTROL *rc = &cpi->rc; const AV1EncoderConfig *oxcf = &cpi->oxcf; - const int min_frame_target = - AOMMAX(rc->min_frame_bandwidth, rc->avg_frame_bandwidth >> 5); - // Clip the frame target to the minimum setup value. - if (cpi->rc.is_src_frame_alt_ref) { - // If there is an active ARF at this location use the minimum - // bits on this frame even if it is a constructed arf. - // The active maximum quantizer insures that an appropriate - // number of bits will be spent if needed for constructed ARFs. - target = min_frame_target; - } else if (target < min_frame_target) { - target = min_frame_target; + + if (cpi->oxcf.pass != 2) { + const int min_frame_target = + AOMMAX(rc->min_frame_bandwidth, rc->avg_frame_bandwidth >> 5); + if (target < min_frame_target) target = min_frame_target; + if (cpi->refresh_golden_frame && rc->is_src_frame_alt_ref) { + // If there is an active ARF at this location use the minimum + // bits on this frame even if it is a constructed arf. + // The active maximum quantizer insures that an appropriate + // number of bits will be spent if needed for + // constructed ARFs. + target = min_frame_target; + } } // Clip the frame target to the maximum allowed value. @@ -450,6 +452,11 @@ void av1_rc_update_rate_correction_factors(AV1_COMP *cpi, int width, else cpi->rc.rc_1_frame = 0; + if (cpi->rc.rc_1_frame == -1 && cpi->rc.rc_2_frame == 1 && + correction_factor > 1000) { + cpi->rc.rc_2_frame = 0; + } + if (correction_factor > 102) { // We are not already at the worst allowable quality correction_factor = @@ -1028,8 +1035,7 @@ static int rc_pick_q_and_bounds_two_pass(const AV1_COMP *cpi, int width, // Extension to max or min Q if undershoot or overshoot is outside // the permitted range. - if ((cpi->oxcf.rc_mode != AOM_Q) && - (cpi->twopass.gf_zeromotion_pct < VLOW_MOTION_THRESHOLD)) { + if (cpi->oxcf.rc_mode != AOM_Q) { if (frame_is_intra_only(cm) || (!rc->is_src_frame_alt_ref && (cpi->refresh_golden_frame || cpi->refresh_alt2_ref_frame || diff --git a/av1/encoder/temporal_filter.c b/av1/encoder/temporal_filter.c index 987f34c495503b5051f9aa1a19469f62619019e2..3e2e5580d5331ba6a63f21e50351a31caed1b76d 100644 --- a/av1/encoder/temporal_filter.c +++ b/av1/encoder/temporal_filter.c @@ -538,7 +538,16 @@ static void adjust_arnr_filter(AV1_COMP *cpi, int distance, int group_boost, av1_lookahead_depth(cpi->lookahead) - distance - 1; int frames_fwd = (cpi->oxcf.arnr_max_frames - 1) >> 1; int frames_bwd; - int q, frames, strength; + int q, frames, base_strength, strength; + + // Context dependent two pass adjustment to strength. + if (oxcf->pass == 2) { + base_strength = oxcf->arnr_strength + cpi->twopass.arnr_strength_adjustment; + // Clip to allowed range. + base_strength = AOMMIN(6, AOMMAX(0, base_strength)); + } else { + base_strength = oxcf->arnr_strength; + } // Define the forward and backwards filter limits for this arnr group. if (frames_fwd > frames_after_arf) frames_fwd = frames_after_arf; @@ -560,10 +569,11 @@ static void adjust_arnr_filter(AV1_COMP *cpi, int distance, int group_boost, else q = ((int)av1_convert_qindex_to_q(cpi->rc.avg_frame_qindex[KEY_FRAME], cpi->common.bit_depth)); + if (q > 16) { - strength = oxcf->arnr_strength; + strength = base_strength; } else { - strength = oxcf->arnr_strength - ((16 - q) / 2); + strength = base_strength - ((16 - q) / 2); if (strength < 0) strength = 0; }