Revert "Port first pass stats handling from Vp9 into Av1"
This reverts commit da01c0dc76fdfa181475d12d4b7d25a82b1fcc72.
Reason for revert: Coding efficiency loss for vbr with > large kf interval. Need tuning of kf boost parameters.
Change-Id: I86175e3f59dc66bffb1af1ac1fdb757fdc0442ea
diff --git a/av1/encoder/firstpass.c b/av1/encoder/firstpass.c
index 9d896a2..8fdb0cb 100644
--- a/av1/encoder/firstpass.c
+++ b/av1/encoder/firstpass.c
@@ -47,32 +47,26 @@
#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 SECTION_NOISE_DEF 250.0
-#define LOW_I_THRESH 24000
-#define ARF_ABS_ZOOM_THRESH 4.0
+#define RC_FACTOR_MIN 0.75
+#define RC_FACTOR_MAX 1.75
#define NCOUNT_INTRA_THRESH 8192
#define NCOUNT_INTRA_FACTOR 3
-
-#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 NCOUNT_FRAME_II_THRESH 5.0
#define DOUBLE_DIVIDE_CHECK(x) ((x) < 0 ? (x)-0.000001 : (x) + 0.000001)
@@ -151,15 +145,11 @@
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;
@@ -181,15 +171,11 @@
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;
@@ -211,15 +197,11 @@
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;
@@ -256,23 +238,17 @@
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.
-static double calculate_mod_frame_score(const AV1_COMP *cpi,
- const AV1EncoderConfig *oxcf,
- const FIRSTPASS_STATS *this_frame,
- double av_err) {
- double modified_score =
+#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 =
av_err * pow(this_frame->coded_error * this_frame->weight /
DOUBLE_DIVIDE_CHECK(av_err),
oxcf->two_pass_vbrbias / 100.0);
@@ -282,35 +258,11 @@
// 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_score *=
+ modified_error *=
pow(calculate_active_area(cpi, this_frame), ACT_AREA_CORRECTION);
- // Normalize to a midpoint score.
- modified_score /= DOUBLE_DIVIDE_CHECK(twopass->mean_mod_score);
-
- return fclamp(modified_score, min_score, max_score);
+ return fclamp(modified_error, twopass->modified_error_min,
+ twopass->modified_error_max);
}
// This function returns the maximum target rate per frame.
@@ -527,170 +479,6 @@
}
#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) {
int mb_row, mb_col;
@@ -709,7 +497,6 @@
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;
@@ -718,11 +505,8 @@
int intercount = 0;
int second_ref_count = 0;
const int intrapenalty = INTRA_MODE_PENALTY;
- double neutral_count = 0.0;
+ double neutral_count;
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;
@@ -827,7 +611,6 @@
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;
@@ -862,34 +645,18 @@
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 < get_ul_intra_threshold(cm)) {
+ if (this_error < UL_INTRA_THRESH) {
++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;
@@ -1161,24 +928,6 @@
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;
@@ -1237,19 +986,14 @@
fps.weight = intra_factor * brightness_factor;
fps.frame = cm->current_video_frame;
- 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.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.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;
@@ -1346,20 +1090,13 @@
}
static double calc_correction_factor(double err_per_mb, double 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)));
+ double pt_low, double pt_high, int q,
+ aom_bit_depth_t bit_depth) {
+ const double error_term = err_per_mb / err_divisor;
// Adjustment based on actual quantizer to power term.
- power_term =
- q_pow_term[index] +
- (((q_pow_term[index + 1] - q_pow_term[index]) * (q % 32)) / 32.0);
+ const double power_term =
+ AOMMIN(av1_convert_qindex_to_q(q, bit_depth) * 0.01 + pt_low, pt_high);
// Calculate correction factor.
if (power_term < 1.0) assert(error_term >= 0.0);
@@ -1367,70 +1104,51 @@
return fclamp(pow(error_term, power_term), 0.05, 5.0);
}
-#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) {
+#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) {
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);
-// 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) {
+ if (section_target_bandwidth <= 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 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 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 int target_norm_bits_per_mb =
- (int)(((uint64_t)target_rate << BPER_MB_NORMBITS) / active_mbs);
+ (int)((uint64_t)section_target_bandwidth << BPER_MB_NORMBITS) /
+ active_mbs;
int q;
-// 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
+ // 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;
+
// 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, 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 int bits_per_mb = av1_rc_bits_per_mb(
- INTER_FRAME, q,
- factor * speed_term * cpi->twopass.bpm_factor * noise_factor,
+ INTER_FRAME, q, factor * speed_term * group_weight_factor,
cpi->common.bit_depth);
if (bits_per_mb <= target_norm_bits_per_mb) break;
}
@@ -1466,32 +1184,6 @@
*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
@@ -1505,6 +1197,24 @@
// 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;
@@ -1515,54 +1225,43 @@
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) {
- double sr_diff = (frame->sr_coded_error - frame->coded_error);
+ 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_decay = 1.0;
double modified_pct_inter;
double modified_pcnt_intra;
- const double motion_amplitude_part =
- frame->pcnt_motion * ((frame->mvc_abs + frame->mvr_abs) /
- (cpi->initial_height + cpi->initial_width));
+ const double motion_amplitude_factor =
+ frame->pcnt_motion * ((frame->mvc_abs + frame->mvr_abs) / 2);
modified_pct_inter = frame->pcnt_inter;
- 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;
+ if ((frame->intra_error / DOUBLE_DIVIDE_CHECK(frame->coded_error)) <
+ (double)NCOUNT_FRAME_II_THRESH) {
+ modified_pct_inter = frame->pcnt_inter - 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_amplitude_part -
+ sr_decay = 1.0 - (SR_DIFF_PART * sr_diff) -
+ (MOTION_AMP_PART * motion_amplitude_factor) -
(INTRA_PART * modified_pcnt_intra);
}
- return AOMMAX(sr_decay, DEFAULT_DECAY_LIMIT);
+ return AOMMAX(sr_decay, AOMMIN(DEFAULT_DECAY_LIMIT, modified_pct_inter));
}
// This function gives an estimate of how badly we believe the prediction
@@ -1663,59 +1362,38 @@
}
}
-#define BASELINE_ERR_PER_MB 12500.0
+#define BASELINE_ERR_PER_MB 1000.0
static double calc_frame_boost(AV1_COMP *cpi, const FIRSTPASS_STATS *this_frame,
- double this_frame_mv_in_out) {
+ 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.5 + (lq * 0.015)), 1.5);
- const double active_area = calculate_active_area(cpi, this_frame);
+ 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));
// Underlying boost factor is based on inter error ratio.
- frame_boost = (BASELINE_ERR_PER_MB * active_area) /
+ frame_boost = (BASELINE_ERR_PER_MB * num_mbs) /
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);
-
- // 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;
+ // In the extreme case the boost is halved.
+ else
+ frame_boost += frame_boost * (this_frame_mv_in_out / 2.0);
return AOMMIN(frame_boost, max_boost * boost_q_correction);
}
-static int calc_arf_boost(AV1_COMP *cpi, int f_frames, int b_frames) {
+static int calc_arf_boost(AV1_COMP *cpi, int offset, int f_frames, int b_frames,
+ int *f_boost, int *b_boost) {
TWO_PASS *const twopass = &cpi->twopass;
int i;
double boost_score = 0.0;
@@ -1729,7 +1407,7 @@
// 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);
+ const FIRSTPASS_STATS *this_frame = read_frame_stats(twopass, i + offset);
if (this_frame == NULL) break;
// Update the motion related elements to the boost calculation.
@@ -1739,7 +1417,8 @@
// 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) || detect_flash(twopass, i + 1);
+ flash_detected = detect_flash(twopass, i + offset) ||
+ detect_flash(twopass, i + offset + 1);
// Accumulate the effect of prediction quality decay.
if (!flash_detected) {
@@ -1749,11 +1428,12 @@
: decay_accumulator;
}
- boost_score += decay_accumulator *
- calc_frame_boost(cpi, this_frame, this_frame_mv_in_out);
+ boost_score +=
+ decay_accumulator *
+ calc_frame_boost(cpi, this_frame, this_frame_mv_in_out, GF_MAX_BOOST);
}
- arf_boost = (int)boost_score;
+ *f_boost = (int)boost_score;
// Reset for backward looking loop.
boost_score = 0.0;
@@ -1765,7 +1445,7 @@
// Search backward towards last gf position.
for (i = -1; i >= -b_frames; --i) {
- const FIRSTPASS_STATS *this_frame = read_frame_stats(twopass, i);
+ const FIRSTPASS_STATS *this_frame = read_frame_stats(twopass, i + offset);
if (this_frame == NULL) break;
// Update the motion related elements to the boost calculation.
@@ -1775,7 +1455,8 @@
// 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) || detect_flash(twopass, i + 1);
+ flash_detected = detect_flash(twopass, i + offset) ||
+ detect_flash(twopass, i + offset + 1);
// Cumulative effect of prediction quality decay.
if (!flash_detected) {
@@ -1785,13 +1466,15 @@
: decay_accumulator;
}
- boost_score += decay_accumulator *
- calc_frame_boost(cpi, this_frame, this_frame_mv_in_out);
+ boost_score +=
+ decay_accumulator *
+ calc_frame_boost(cpi, this_frame, this_frame_mv_in_out, GF_MAX_BOOST);
}
- arf_boost += (int)boost_score;
+ *b_boost = (int)boost_score;
- if (arf_boost < ((b_frames + f_frames) * 40))
- arf_boost = ((b_frames + f_frames) * 40);
+ arf_boost = (*f_boost + *b_boost);
+ if (arf_boost < ((b_frames + f_frames) * 20))
+ arf_boost = ((b_frames + f_frames) * 20);
arf_boost = AOMMAX(arf_boost, MIN_ARF_GF_BOOST);
return arf_boost;
@@ -2663,7 +2346,7 @@
}
static void allocate_gf_group_bits(AV1_COMP *cpi, int64_t gf_group_bits,
- int gf_arf_bits) {
+ double group_error, int gf_arf_bits) {
RATE_CONTROL *const rc = &cpi->rc;
const AV1EncoderConfig *const oxcf = &cpi->oxcf;
TWO_PASS *const twopass = &cpi->twopass;
@@ -2673,8 +2356,10 @@
int frame_index = 0;
int target_frame_size;
int key_frame;
- const int max_bits = frame_max_bits(&cpi->rc, oxcf);
+ const int max_bits = frame_max_bits(&cpi->rc, &cpi->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];
@@ -2718,23 +2403,18 @@
}
}
- 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 < normal_frames; ++i) {
+ for (i = 0; i < rc->baseline_gf_interval - rc->source_alt_ref_pending; ++i) {
if (EOF == input_stats(twopass, &frame_stats)) break;
- 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;
- }
+ 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);
if (rc->source_alt_ref_pending && cpi->multi_arf_enabled) {
mid_boost_bits += (target_frame_size >> 4);
@@ -2799,20 +2479,6 @@
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;
@@ -2823,22 +2489,19 @@
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;
@@ -2848,14 +2511,15 @@
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;
@@ -2873,8 +2537,7 @@
av1_zero(next_frame);
// Load stats for the current frame.
- mod_frame_err =
- calculate_norm_frame_score(cpi, twopass, oxcf, this_frame, av_err);
+ mod_frame_err = calculate_modified_err(cpi, twopass, oxcf, this_frame);
// 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.
@@ -2887,11 +2550,8 @@
#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.
@@ -2906,10 +2566,9 @@
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 + 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);
+ 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;
if (cpi->multi_arf_allowed) {
active_max_gf_interval = rc->max_gf_interval;
@@ -2918,19 +2577,13 @@
// 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 + arf_active_or_kf + AOMMIN(4, (int_lbq / 6));
+ active_max_gf_interval = 12 + 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 = 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;
+ active_max_gf_interval = rc->max_gf_interval;
}
}
@@ -2947,17 +2600,13 @@
++i;
// Accumulate error score of frames in this gf group.
- mod_frame_err =
- calculate_norm_frame_score(cpi, twopass, oxcf, this_frame, av_err);
+ mod_frame_err = calculate_modified_err(cpi, twopass, oxcf, this_frame);
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;
@@ -2987,9 +2636,7 @@
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(
@@ -3002,52 +2649,55 @@
allow_alt_ref = 0;
break;
}
-
- // 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);
- }
}
+ // 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);
+
// Break out conditions.
if (
// Break at active_max_gf_interval unless almost totally static.
- (i >= active_max_gf_interval && zero_motion_accumulator < 0.995) ||
+ (i >= (active_max_gf_interval + arf_active_or_kf) &&
+ zero_motion_accumulator < 0.995) ||
(
// Don't break out with a very short interval.
- (i >= active_min_gf_interval) &&
- ((rc->frames_to_key - i) >= rc->min_gf_interval) &&
+ (i >= active_min_gf_interval + arf_active_or_kf) &&
(!flash_detected) &&
((mv_ratio_accumulator > mv_ratio_accumulator_thresh) ||
- (abs_mv_in_out_accumulator > ARF_ABS_ZOOM_THRESH) ||
- (sr_accumulator > next_frame.intra_error)))) {
+ (abs_mv_in_out_accumulator > 3.0) ||
+ (mv_in_out_accumulator < -2.0) ||
+ ((boost_score - old_boost_score) < BOOST_BREAKOUT)))) {
// 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)) break;
+ if (i == (8 + 1) || i >= (12 + 1)) {
+ boost_score = old_boost_score;
+ 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, forward_frames, (i - 1));
+ rc->gfu_boost =
+ calc_arf_boost(cpi, 0, (i - 1), (i - 1), &f_boost, &b_boost);
rc->source_alt_ref_pending = 1;
// Test to see if multi arf is appropriate.
@@ -3057,8 +2707,6 @@
? 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;
}
@@ -3070,15 +2718,12 @@
}
#endif // CONFIG_BGSPRITE
} else {
- rc->gfu_boost = calc_arf_boost(cpi, 0, (i - 1));
+ rc->gfu_boost = AOMMAX((int)boost_score, MIN_ARF_GF_BOOST);
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:
@@ -3126,34 +2771,30 @@
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 = get_twopass_worst_quality(
+
+ 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(
cpi, group_av_err, (group_av_skip_pct + group_av_inactive_zone),
- group_av_noise, vbr_group_bits_per_frame);
+ vbr_group_bits_per_frame, twopass->kfgroup_inter_fraction * rc_factor);
twopass->active_worst_quality =
- (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
+ AOMMAX(tmp_q, twopass->active_worst_quality >> 1);
}
#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);
@@ -3161,8 +2802,22 @@
// 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_arf_bits);
+ allocate_gf_group_bits(cpi, gf_group_bits, gf_group_error_left, gf_arf_bits);
// Reset the file position.
reset_fpf_position(twopass, start_pos);
@@ -3172,11 +2827,6 @@
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
@@ -3204,9 +2854,6 @@
// 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,
@@ -3246,7 +2893,7 @@
// Examine how well the key frame predicts subsequent frames.
for (i = 0; i < 16; ++i) {
- double next_iiratio = (II_FACTOR * local_next_frame.intra_error /
+ double next_iiratio = (BOOST_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;
@@ -3266,7 +2913,7 @@
0.20) &&
(next_iiratio < 3.0)) ||
((boost_score - old_boost_score) < 3.0) ||
- (local_next_frame.intra_error < V_LOW_INTRA)) {
+ (local_next_frame.intra_error < 200)) {
break;
}
@@ -3304,15 +2951,14 @@
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);
@@ -3337,8 +2983,7 @@
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_norm_frame_score(cpi, twopass, oxcf, this_frame, av_err);
+ kf_mod_err = calculate_modified_err(cpi, twopass, oxcf, this_frame);
// 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;
@@ -3348,8 +2993,7 @@
while (twopass->stats_in < twopass->stats_in_end &&
rc->frames_to_key < cpi->oxcf.key_freq) {
// Accumulate kf group error.
- kf_group_err +=
- calculate_norm_frame_score(cpi, twopass, oxcf, this_frame, av_err);
+ kf_group_err += calculate_modified_err(cpi, twopass, oxcf, this_frame);
// Load the next frame's stats.
last_frame = *this_frame;
@@ -3409,8 +3053,7 @@
// 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_norm_frame_score(cpi, twopass, oxcf, &tmp_frame, av_err);
+ kf_group_err += calculate_modified_err(cpi, twopass, oxcf, &tmp_frame);
input_stats(twopass, &tmp_frame);
}
rc->next_key_frame_forced = 1;
@@ -3424,12 +3067,11 @@
// 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_norm_frame_score(cpi, twopass, oxcf, this_frame, av_err);
+ kf_group_err += calculate_modified_err(cpi, twopass, oxcf, this_frame);
}
// Calculate the number of bits that should be assigned to the kf group.
- if (twopass->bits_left > 0 && twopass->normalized_score_left > 0.0) {
+ if (twopass->bits_left > 0 && twopass->modified_error_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);
@@ -3439,7 +3081,7 @@
// 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->normalized_score_left));
+ twopass->bits_left * (kf_group_err / twopass->modified_error_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;
@@ -3455,43 +3097,35 @@
// 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;
- 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));
- // 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);
- // 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;
+ // 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 (loop_decay_counter > 0)
+ av_decay_accumulator /= (double)loop_decay_counter;
reset_fpf_position(twopass, start_position);
@@ -3503,13 +3137,24 @@
start_position, twopass->stats_in_end, rc->frames_to_key);
// Apply various clamps for min and max 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);
+ 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);
// 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.
@@ -3518,12 +3163,12 @@
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 = (kf_group_err - kf_mod_err);
+ twopass->kf_group_error_left = (int)(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->normalized_score_left -= kf_group_err;
+ twopass->modified_error_left -= kf_group_err;
}
#if USE_GF16_MULTI_LAYER
@@ -3862,11 +3507,9 @@
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_noise, section_target_bandwidth);
+ section_target_bandwidth, DEFAULT_GRP_WEIGHT);
twopass->active_worst_quality = tmp_q;
twopass->baseline_active_worst_quality = tmp_q;
@@ -3965,10 +3608,6 @@
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 =
@@ -3988,7 +3627,9 @@
++twopass->gf_group.index;
// If the rate control is drifting consider adjustment to min or maxq.
- if ((cpi->oxcf.rc_mode != AOM_Q) && !cpi->rc.is_src_frame_alt_ref) {
+ if ((cpi->oxcf.rc_mode != AOM_Q) &&
+ (cpi->twopass.gf_zeromotion_pct < VLOW_MOTION_THRESHOLD) &&
+ !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 892eae5..ee21b65 100644
--- a/av1/encoder/firstpass.h
+++ b/av1/encoder/firstpass.h
@@ -72,15 +72,11 @@
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;
@@ -143,10 +139,10 @@
FIRSTPASS_STATS total_left_stats;
int first_pass_done;
int64_t bits_left;
- double normalized_score_left;
- double mean_mod_score;
+ double modified_error_min;
+ double modified_error_max;
+ double modified_error_left;
double mb_av_energy;
- double mb_smooth_pct;
#if CONFIG_FP_MB_STATS
uint8_t *frame_mb_stats_buf;
@@ -160,25 +156,21 @@
int64_t kf_group_bits;
// Error score of frames still to be coded in kf group
- double kf_group_error_left;
+ int64_t 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 86e371b..523ffa1 100644
--- a/av1/encoder/ratectrl.c
+++ b/av1/encoder/ratectrl.c
@@ -121,7 +121,7 @@
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.70, bit_depth);
+ inter[i] = get_minq_index(maxq, 0.00000271, -0.00113, 0.90, bit_depth);
rtc[i] = get_minq_index(maxq, 0.00000271, -0.00113, 0.70, bit_depth);
}
}
@@ -178,19 +178,17 @@
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;
-
- 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;
- }
+ 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;
}
// Clip the frame target to the maximum allowed value.
@@ -452,11 +450,6 @@
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 =
@@ -1035,7 +1028,8 @@
// Extension to max or min Q if undershoot or overshoot is outside
// the permitted range.
- if (cpi->oxcf.rc_mode != AOM_Q) {
+ if ((cpi->oxcf.rc_mode != AOM_Q) &&
+ (cpi->twopass.gf_zeromotion_pct < VLOW_MOTION_THRESHOLD)) {
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 3e2e558..987f34c 100644
--- a/av1/encoder/temporal_filter.c
+++ b/av1/encoder/temporal_filter.c
@@ -538,16 +538,7 @@
av1_lookahead_depth(cpi->lookahead) - distance - 1;
int frames_fwd = (cpi->oxcf.arnr_max_frames - 1) >> 1;
int frames_bwd;
- 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;
- }
+ int q, frames, strength;
// Define the forward and backwards filter limits for this arnr group.
if (frames_fwd > frames_after_arf) frames_fwd = frames_after_arf;
@@ -569,11 +560,10 @@
else
q = ((int)av1_convert_qindex_to_q(cpi->rc.avg_frame_qindex[KEY_FRAME],
cpi->common.bit_depth));
-
if (q > 16) {
- strength = base_strength;
+ strength = oxcf->arnr_strength;
} else {
- strength = base_strength - ((16 - q) / 2);
+ strength = oxcf->arnr_strength - ((16 - q) / 2);
if (strength < 0) strength = 0;
}