/* * Copyright (c) 2010 The WebM project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree.
*/
// Resets the first pass file to the given position using a relative seek from // the current position. staticvoid reset_fpf_position(TWO_PASS *p, const FIRSTPASS_STATS *position) {
p->stats_in = position;
}
// Read frame stats at an offset from the current position. staticconst FIRSTPASS_STATS *read_frame_stats(const TWO_PASS *p, int offset) { if ((offset >= 0 && p->stats_in + offset >= p->stats_in_end) ||
(offset < 0 && p->stats_in + offset < p->stats_in_start)) { return NULL;
}
// Calculate an active area of the image that discounts formatting // bars and partially discounts other 0 energy areas. #define MIN_ACTIVE_AREA 0.5 #define MAX_ACTIVE_AREA 1.0 staticdouble calculate_active_area(const FRAME_INFO *frame_info, const FIRSTPASS_STATS *this_frame) { double active_pct;
// Get the average weighted error for the clip (or corpus) staticdouble get_distribution_av_err(VP9_COMP *cpi, TWO_PASS *const twopass) { constdouble av_weight =
twopass->total_stats.weight / twopass->total_stats.count;
#define ACT_AREA_CORRECTION 0.5 // Calculate a modified Error used in distributing bits between easier and // harder frames. staticdouble calculate_mod_frame_score(const VP9_COMP *cpi, const VP9EncoderConfig *oxcf, const FIRSTPASS_STATS *this_frame, constdouble 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->frame_info, this_frame),
ACT_AREA_CORRECTION);
// 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(frame_info, this_frame), ACT_AREA_CORRECTION);
// Normalize to a midpoint score.
modified_score /= DOUBLE_DIVIDE_CHECK(mean_mod_score); return fclamp(modified_score, min_score, max_score);
}
// Refine the motion search range according to the frame dimension // for first pass test. staticint get_search_range(const VP9_COMP *cpi) { int sr = 0; constint dim = VPXMIN(cpi->initial_width, cpi->initial_height);
while ((dim << sr) < MAX_FULL_PEL_VAL) ++sr; return sr;
}
// Reduce limits to keep the motion search within MV_MAX of ref_mv. Not doing // this can be problematic for big videos (8K) and may cause assert failure // (or memory violation) in mv_cost. Limits are only modified if they would // be non-empty. Returns 1 if limits are non-empty. staticint intersect_limits_with_mv_max(MvLimits *mv_limits, const MV *ref_mv) { constint row_min =
VPXMAX(mv_limits->row_min, (ref_mv->row + 7 - MV_MAX) >> 3); constint row_max =
VPXMIN(mv_limits->row_max, (ref_mv->row - 1 + MV_MAX) >> 3); constint col_min =
VPXMAX(mv_limits->col_min, (ref_mv->col + 7 - MV_MAX) >> 3); constint col_max =
VPXMIN(mv_limits->col_max, (ref_mv->col - 1 + MV_MAX) >> 3); if (row_min > row_max || col_min > col_max) { return 0;
}
mv_limits->row_min = row_min;
mv_limits->row_max = row_max;
mv_limits->col_min = col_min;
mv_limits->col_max = col_max; return 1;
}
staticint find_fp_qindex(vpx_bit_depth_t bit_depth) { int i;
for (i = 0; i < QINDEX_RANGE; ++i) if (vp9_convert_qindex_to_q(i, bit_depth) >= FIRST_PASS_Q) break;
if (i == QINDEX_RANGE) i--;
return i;
}
staticvoid set_first_pass_params(VP9_COMP *cpi) {
VP9_COMMON *const cm = &cpi->common; if (!cpi->refresh_alt_ref_frame &&
(cm->current_video_frame == 0 || (cpi->frame_flags & FRAMEFLAGS_KEY))) {
cm->frame_type = KEY_FRAME;
} else {
cm->frame_type = INTER_FRAME;
} // Do not use periodic key frames.
cpi->rc.frames_to_key = INT_MAX;
}
// Scale an sse threshold to account for 8/10/12 bit. staticint scale_sse_threshold(VP9_COMMON *cm, int thresh) { int ret_val = thresh; #if CONFIG_VP9_HIGHBITDEPTH if (cm->use_highbitdepth) { switch (cm->bit_depth) { case VPX_BITS_8: ret_val = thresh; break; case VPX_BITS_10: ret_val = thresh << 4; break; default:
assert(cm->bit_depth == VPX_BITS_12);
ret_val = thresh << 8; break;
}
} #else
(void)cm; #endif// CONFIG_VP9_HIGHBITDEPTH return ret_val;
}
// This threshold is used to track blocks where to all intents and purposes // the intra prediction error 0. Though the metric we test against // is technically a sse we are mainly interested in blocks where all the pixels // in the 8 bit domain have an error of <= 1 (where error = sse) so a // linear scaling for 10 and 12 bit gives similar results. #define UL_INTRA_THRESH 50 staticint get_ul_intra_threshold(VP9_COMMON *cm) { int ret_val = UL_INTRA_THRESH; #if CONFIG_VP9_HIGHBITDEPTH if (cm->use_highbitdepth) { switch (cm->bit_depth) { case VPX_BITS_8: ret_val = UL_INTRA_THRESH; break; case VPX_BITS_10: ret_val = UL_INTRA_THRESH << 2; break; default:
assert(cm->bit_depth == VPX_BITS_12);
ret_val = UL_INTRA_THRESH << 4; break;
}
} #else
(void)cm; #endif// CONFIG_VP9_HIGHBITDEPTH return ret_val;
}
// Estimate noise at a single point based on the impact of a spatial kernel // on the point value staticint fp_estimate_point_noise(uint8_t *src_ptr, constint 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 = VPXMAX(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;
} #if CONFIG_VP9_HIGHBITDEPTH staticint fp_highbd_estimate_point_noise(uint8_t *src_ptr, constint 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);
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;
} #endif
// Estimate noise for a block. staticint fp_estimate_block_noise(MACROBLOCK *x, BLOCK_SIZE bsize) { #if CONFIG_VP9_HIGHBITDEPTH
MACROBLOCKD *xd = &x->e_mbd; #endif
uint8_t *src_ptr = &x->plane[0].src.buf[0]; constint width = num_4x4_blocks_wide_lookup[bsize] * 4; constint 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 CONFIG_VP9_HIGHBITDEPTH 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); #else
block_noise += fp_estimate_point_noise(src_ptr, stride); #endif
++src_ptr;
}
src_ptr += (stride - width);
} return block_noise << 2; // Scale << 2 to account for sampling.
}
// This function is called to test the functionality of row based // multi-threading in unit tests for bit-exactness staticvoid accumulate_floating_point_stats(VP9_COMP *cpi,
TileDataEnc *first_tile_col) {
VP9_COMMON *const cm = &cpi->common; int mb_row, mb_col;
first_tile_col->fp_data.intra_factor = 0;
first_tile_col->fp_data.brightness_factor = 0;
first_tile_col->fp_data.neutral_count = 0; for (mb_row = 0; mb_row < cm->mb_rows; ++mb_row) { for (mb_col = 0; mb_col < cm->mb_cols; ++mb_col) { constint mb_index = mb_row * cm->mb_cols + mb_col;
first_tile_col->fp_data.intra_factor +=
cpi->twopass.fp_mb_float_stats[mb_index].frame_mb_intra_factor;
first_tile_col->fp_data.brightness_factor +=
cpi->twopass.fp_mb_float_stats[mb_index].frame_mb_brightness_factor;
first_tile_col->fp_data.neutral_count +=
cpi->twopass.fp_mb_float_stats[mb_index].frame_mb_neutral_count;
}
}
}
staticvoid first_pass_stat_calc(VP9_COMP *cpi, FIRSTPASS_STATS *fps,
FIRSTPASS_DATA *fp_acc_data) {
VP9_COMMON *const cm = &cpi->common; // The minimum error here insures some bit allocation to frames even // in static regions. The allocation per MB declines for larger formats // where the typical "real" energy per MB also falls. // Initial estimate here uses sqrt(mbs) to define the min_err, where the // number of mbs is proportional to the image area. constint num_mbs = (cpi->oxcf.resize_mode != RESIZE_NONE) ? cpi->initial_mbs
: cpi->common.MBs; constdouble min_err = 200 * sqrt(num_mbs);
// Clamp the image start to rows/2. This number of rows is discarded top // and bottom as dead data so rows / 2 means the frame is blank. if ((fp_acc_data->image_data_start_row > cm->mb_rows / 2) ||
(fp_acc_data->image_data_start_row == INVALID_ROW)) {
fp_acc_data->image_data_start_row = cm->mb_rows / 2;
} // Exclude any image dead zone if (fp_acc_data->image_data_start_row > 0) {
fp_acc_data->intra_skip_count =
VPXMAX(0, fp_acc_data->intra_skip_count -
(fp_acc_data->image_data_start_row * cm->mb_cols * 2));
}
xd->plane[0].dst.buf = new_yv12->y_buffer + recon_yoffset;
xd->plane[1].dst.buf = new_yv12->u_buffer + recon_uvoffset;
xd->plane[2].dst.buf = new_yv12->v_buffer + recon_uvoffset;
xd->mi[0]->sb_type = bsize;
xd->mi[0]->ref_frame[0] = INTRA_FRAME;
set_mi_row_col(xd, &tile, mb_row << 1, num_8x8_blocks_high_lookup[bsize],
mb_col << 1, num_8x8_blocks_wide_lookup[bsize], cm->mi_rows,
cm->mi_cols); // Are edges available for intra prediction? // Since the firstpass does not populate the mi_grid_visible, // above_mi/left_mi must be overwritten with a nonzero value when edges // are available. Required by vp9_predict_intra_block().
xd->above_mi = (mb_row != 0) ? &mi_above : NULL;
xd->left_mi = ((mb_col << 1) > tile.mi_col_start) ? &mi_left : NULL;
// Do intra 16x16 prediction.
x->skip_encode = 0;
x->fp_src_pred = 0; // Do intra prediction based on source pixels for tile boundaries if (mb_col == mb_col_start && mb_col != 0) {
xd->left_mi = &mi_left;
x->fp_src_pred = 1;
}
xd->mi[0]->mode = DC_PRED;
xd->mi[0]->tx_size =
use_dc_pred ? (bsize >= BLOCK_16X16 ? TX_16X16 : TX_8X8) : TX_4X4; // Fix - zero the 16x16 block first. This ensures correct this_error for // block sizes smaller than 16x16.
vp9_zero_array(x->plane[0].src_diff, 256);
vp9_encode_intra_block_plane(x, bsize, 0, 0);
this_error = vpx_get_mb_ss(x->plane[0].src_diff);
this_intra_error = this_error;
// Keep a record of blocks that have very low 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)) {
++(fp_acc_data->intra_skip_count);
} elseif ((mb_col > 0) &&
(fp_acc_data->image_data_start_row == INVALID_ROW)) {
fp_acc_data->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)) {
++(fp_acc_data->intra_smooth_count);
}
// Special case noise measurement for first frame. if (cm->current_video_frame == 0) { if (this_intra_error < scale_sse_threshold(cm, LOW_I_THRESH)) {
fp_acc_data->frame_noise_energy += fp_estimate_block_noise(x, bsize);
} else {
fp_acc_data->frame_noise_energy += (int64_t)SECTION_NOISE_DEF;
}
}
#if CONFIG_VP9_HIGHBITDEPTH if (cm->use_highbitdepth) { switch (cm->bit_depth) { case VPX_BITS_8: break; case VPX_BITS_10: this_error >>= 4; break; default:
assert(cm->bit_depth == VPX_BITS_12);
this_error >>= 8; break;
}
} #endif// CONFIG_VP9_HIGHBITDEPTH
// Intrapenalty below deals with situations where the intra and inter // error scores are very low (e.g. a plain black frame). // We do not have special cases in first pass for 0,0 and nearest etc so // all inter modes carry an overhead cost estimate for the mv. // When the error score is very low this causes us to pick all or lots of // INTRA modes and throw lots of key frames. // This penalty adds a cost matching that of a 0,0 mv to the intra case.
this_error += intrapenalty;
// Accumulate the intra error.
fp_acc_data->intra_error += (int64_t)this_error;
// Set up limit values for motion vectors to prevent them extending // outside the UMV borders.
x->mv_limits.col_min = -((mb_col * 16) + BORDER_MV_PIXELS_B16);
x->mv_limits.col_max =
((cm->mb_cols - 1 - mb_col) * 16) + BORDER_MV_PIXELS_B16;
// Other than for intra-only frame do a motion search. if (!frame_is_intra_only(cm)) { int tmp_err, motion_error, this_motion_error, raw_motion_error; // Assume 0,0 motion with no mv overhead.
MV mv = { 0, 0 }, tmp_mv = { 0, 0 }; struct buf_2d unscaled_last_source_buf_2d;
vp9_variance_fn_ptr_t v_fn_ptr = cpi->fn_ptr[bsize];
#if CONFIG_RATE_CTRL if (cpi->oxcf.use_simple_encode_api) { // Store zero mv as default
store_fp_motion_vector(cpi, &mv, mb_row, mb_col, LAST_FRAME, 0);
} #endif// CONFIG_RAGE_CTRL
// Compute the motion error of the 0,0 motion using the last source // frame as the reference. Skip the further motion search on // reconstructed frame if this error is very small.
unscaled_last_source_buf_2d.buf =
cpi->unscaled_last_source->y_buffer + recon_yoffset;
unscaled_last_source_buf_2d.stride = cpi->unscaled_last_source->y_stride; #if CONFIG_VP9_HIGHBITDEPTH if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
raw_motion_error = highbd_get_prediction_error(
bsize, &x->plane[0].src, &unscaled_last_source_buf_2d, xd->bd);
} else {
raw_motion_error = get_prediction_error(bsize, &x->plane[0].src,
&unscaled_last_source_buf_2d);
} #else
raw_motion_error = get_prediction_error(bsize, &x->plane[0].src,
&unscaled_last_source_buf_2d); #endif// CONFIG_VP9_HIGHBITDEPTH
if (raw_motion_error > NZ_MOTION_PENALTY) { // Test last reference frame using the previous best mv as the // starting point (best reference) for the search.
first_pass_motion_search(cpi, x, best_ref_mv, &mv, &motion_error);
// If the current best reference mv is not centered on 0,0 then do a // 0,0 based search as well. if (!is_zero_mv(best_ref_mv)) {
tmp_err = INT_MAX;
first_pass_motion_search(cpi, x, &zero_mv, &tmp_mv, &tmp_err);
// Search in an older reference frame. if ((cm->current_video_frame > 1) && gld_yv12 != NULL) { // Assume 0,0 motion with no mv overhead. int gf_motion_error;
if (gf_motion_error < motion_error && gf_motion_error < this_error)
++(fp_acc_data->second_ref_count);
// Reset to last frame as reference buffer.
xd->plane[0].pre[0].buf = first_ref_buf->y_buffer + recon_yoffset;
xd->plane[1].pre[0].buf = first_ref_buf->u_buffer + recon_uvoffset;
xd->plane[2].pre[0].buf = first_ref_buf->v_buffer + recon_uvoffset;
// In accumulating a score for the older reference frame take the // best of the motion predicted score and the intra coded error // (just as will be done for) accumulation of "coded_error" for // the last frame. if (gf_motion_error < this_error)
fp_acc_data->sr_coded_error += gf_motion_error; else
fp_acc_data->sr_coded_error += this_error;
} else {
fp_acc_data->sr_coded_error += motion_error;
}
} else {
fp_acc_data->sr_coded_error += motion_error;
}
// Start by assuming that intra mode is best.
best_ref_mv->row = 0;
best_ref_mv->col = 0;
if (motion_error <= this_error) {
vpx_clear_system_state();
// Keep a count of cases where the inter and intra were very close // and very low. This helps with scene cut detection for example in // cropped clips with black bars at the sides or top and bottom. if (((this_error - intrapenalty) * 9 <= motion_error * 10) &&
(this_error < (2 * intrapenalty))) {
fp_acc_data->neutral_count += 1.0; if (cpi->row_mt_bit_exact)
cpi->twopass.fp_mb_float_stats[mb_index].frame_mb_neutral_count =
1.0; // Also track cases where the intra is not much worse than the inter // and use this in limiting the GF/arf group length.
} elseif ((this_error > NCOUNT_INTRA_THRESH) &&
(this_error < (NCOUNT_INTRA_FACTOR * motion_error))) {
mb_neutral_count =
(double)motion_error / DOUBLE_DIVIDE_CHECK((double)this_error);
fp_acc_data->neutral_count += mb_neutral_count; if (cpi->row_mt_bit_exact)
cpi->twopass.fp_mb_float_stats[mb_index].frame_mb_neutral_count =
mb_neutral_count;
}
// Don't allow a value of 0 for duration. // (Section duration is also defaulted to minimum of 1.0).
fps.duration = VPXMAX(1.0, (double)(source->ts_end - source->ts_start));
// Don't want to do output stats with a stack variable!
twopass->this_frame_stats = fps;
output_stats(&twopass->this_frame_stats);
accumulate_stats(&twopass->total_stats, &fps);
}
// Copy the previous Last Frame back into gf and arf buffers if // the prediction is good enough... but also don't allow it to lag too far. if ((twopass->sr_update_lag > 3) ||
((cm->current_video_frame > 0) &&
(twopass->this_frame_stats.pcnt_inter > 0.20) &&
((twopass->this_frame_stats.intra_error /
DOUBLE_DIVIDE_CHECK(twopass->this_frame_stats.coded_error)) > 2.0))) { if (gld_yv12 != NULL) {
ref_cnt_fb(pool->frame_bufs, &cm->ref_frame_map[cpi->gld_fb_idx],
cm->ref_frame_map[cpi->lst_fb_idx]);
}
twopass->sr_update_lag = 1;
} else {
++twopass->sr_update_lag;
}
vpx_extend_frame_borders(new_yv12);
// The frame we just compressed now becomes the last frame.
ref_cnt_fb(pool->frame_bufs, &cm->ref_frame_map[cpi->lst_fb_idx],
cm->new_fb_idx);
// Special case for the first frame. Copy into the GF buffer as a second // reference. if (cm->current_video_frame == 0 && cpi->gld_fb_idx != INVALID_IDX) {
ref_cnt_fb(pool->frame_bufs, &cm->ref_frame_map[cpi->gld_fb_idx],
cm->ref_frame_map[cpi->lst_fb_idx]);
}
// In the first pass, every frame is considered as a show frame.
update_frame_indexes(cm, /*show_frame=*/1); if (cpi->use_svc) vp9_inc_frame_in_layer(cpi);
}
// Adjustment based on quantizer to the power term.
power_term =
q_pow_term[index] +
(((q_pow_term[index + 1] - q_pow_term[index]) * (q % 32)) / 32.0);
// Clamp the target rate to VBR min / max limts. constint target_rate =
vp9_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 CONFIG_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 = VPXMAX(0.25, VPXMIN(4.0, last_group_rate_err));
twopass->bpm_factor *= (3.0 + last_group_rate_err) / 4.0;
twopass->bpm_factor = VPXMAX(0.25, VPXMIN(4.0, twopass->bpm_factor)); #endif
// TODO(jimbankoski): remove #if here or above when this has been // well tested. #if !CONFIG_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 = VPXMAX(0.25, VPXMIN(4.0, last_group_rate_err));
twopass->bpm_factor *= (3.0 + last_group_rate_err) / 4.0;
twopass->bpm_factor = VPXMAX(0.25, VPXMIN(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) { constdouble factor =
calc_correction_factor(av_err_per_mb, wq_err_divisor(cpi), q); constint bits_per_mb = vp9_rc_bits_per_mb(
INTER_FRAME, q,
factor * speed_term * cpi->twopass.bpm_factor * noise_factor,
cpi->common.bit_depth); if ((uint64_t)bits_per_mb <= target_norm_bits_per_mb) break;
}
// Restriction on active max q for constrained quality mode. if (cpi->oxcf.rc_mode == VPX_CQ) q = VPXMAX(q, oxcf->cq_level); return q;
}
}
staticvoid setup_rf_level_maxq(VP9_COMP *cpi) { int i;
RATE_CONTROL *const rc = &cpi->rc; for (i = INTER_NORMAL; i < RATE_FACTOR_LEVELS; ++i) { int qdelta = vp9_frame_type_qdelta(cpi, i, rc->worst_quality);
rc->rf_level_maxq[i] = VPXMAX(rc->worst_quality + qdelta, rc->best_quality);
}
}
staticvoid init_subsampling(VP9_COMP *cpi) { const VP9_COMMON *const cm = &cpi->common;
RATE_CONTROL *const rc = &cpi->rc; constint w = cm->width; constint h = cm->height; int i;
for (i = 0; i < FRAME_SCALE_STEPS; ++i) { // Note: Frames with odd-sized dimensions may result from this scaling.
rc->frame_width[i] = (w * 16) / frame_scale_factor[i];
rc->frame_height[i] = (h * 16) / frame_scale_factor[i];
}
setup_rf_level_maxq(cpi);
}
void calculate_coded_size(VP9_COMP *cpi, int *scaled_frame_width, int *scaled_frame_height) {
RATE_CONTROL *const rc = &cpi->rc;
*scaled_frame_width = rc->frame_width[rc->frame_size_selector];
*scaled_frame_height = rc->frame_height[rc->frame_size_selector];
}
// Scan the first pass file and calculate a modified score for each // frame that is used to distribute bits. The modified score is assumed // to provide a linear basis for bit allocation. I.e., a frame A with a score // that is double that of frame B will be allocated 2x as many bits.
{ double modified_score_total = 0.0; const FIRSTPASS_STATS *s = twopass->stats_in; double av_err;
if (oxcf->vbr_corpus_complexity) {
twopass->mean_mod_score = (double)oxcf->vbr_corpus_complexity / 10.0;
av_err = get_distribution_av_err(cpi, twopass);
} else {
av_err = get_distribution_av_err(cpi, 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);
}
// Second scan using clamps based on the previous cycle average. // This may modify the total and average somewhat but we don't bother with // further iterations.
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;
// If using Corpus wide VBR mode then update the clip target bandwidth to // reflect how the clip compares to the rest of the corpus. if (oxcf->vbr_corpus_complexity) {
oxcf->target_bandwidth =
(int64_t)((double)oxcf->target_bandwidth *
(twopass->normalized_score_left / stats->count));
}
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 // encoded in the second pass is a guess. However, the sum duration is not. // It is calculated based on the actual durations of all frames from the // first pass.
vp9_new_framerate(cpi, frame_rate);
twopass->bits_left =
(int64_t)(stats->duration * oxcf->target_bandwidth / 10000000.0);
// This variable monitors how far behind the second ref update is lagging.
twopass->sr_update_lag = 1;
// Reset the vbr bits off target counters
rc->vbr_bits_off_target = 0;
rc->vbr_bits_off_target_fast = 0;
rc->rate_error_estimate = 0;
// 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) {
init_subsampling(cpi);
}
// Initialize the arnr strangth adjustment to 0
twopass->arnr_strength_adjustment = 0;
}
/* This function considers how the quality of prediction may be deteriorating * with distance. It compares the coded error for the last frame and the * second reference frame (usually two frames old) and also applies a factor * based on the extent of INTRA coding. * * The decay factor is then used to reduce the contribution of frames further * from the alt-ref or golden frame, to the bitrate boost calculation for that * alt-ref or golden frame.
*/ staticdouble get_sr_decay_rate(const TWO_PASS *const twopass, const FIRSTPASS_STATS *frame) { double sr_diff = (frame->sr_coded_error - frame->coded_error); double sr_decay = 1.0;
// Do nothing if the second ref to last frame error difference is // very small or even negative. if ((sr_diff > LOW_SR_DIFF_TRHESH)) { constdouble sr_diff_part =
twopass->sr_diff_factor * ((sr_diff * 0.25) / frame->intra_error); double modified_pct_inter = frame->pcnt_inter; double modified_pcnt_intra;
// This function gives an estimate of how badly we believe the prediction // quality is decaying from frame to frame. staticdouble get_zero_motion_factor(const TWO_PASS *const twopass, const FIRSTPASS_STATS *frame_stats) { constdouble zero_motion_pct =
frame_stats->pcnt_inter - frame_stats->pcnt_motion; double sr_decay = get_sr_decay_rate(twopass, frame_stats); return VPXMIN(sr_decay, zero_motion_pct);
}
staticint get_show_idx(const TWO_PASS *twopass) { return (int)(twopass->stats_in - twopass->stats_in_start);
} // Function to test for a condition where a complex transition is followed // by a static section. For example in slide shows where there is a fade // between slides. This is to help with more optimal kf and gf positioning. staticint check_transition_to_still(const FIRST_PASS_INFO *first_pass_info, int show_idx, int still_interval) { int j; int num_frames = fps_get_num_frames(first_pass_info); if (show_idx + still_interval > num_frames) { return 0;
}
// Look ahead a few frames to see if static condition persists... for (j = 0; j < still_interval; ++j) { const FIRSTPASS_STATS *stats =
fps_get_frame_stats(first_pass_info, show_idx + j); if (stats->pcnt_inter - stats->pcnt_motion < 0.999) break;
}
// Only if it does do we signal a transition to still. return j == still_interval;
}
// This function detects a flash through the high relative pcnt_second_ref // score in the frame following a flash frame. The offset passed in should // reflect this. staticint detect_flash_from_frame_stats(const FIRSTPASS_STATS *frame_stats) { // What we are looking for here is a situation where there is a // brief break in prediction (such as a flash) but subsequent frames // are reasonably well predicted by an earlier (pre flash) frame. // The recovery after a flash is indicated by a high pcnt_second_ref // usage or a second ref coded error notabley lower than the last // frame coded error. if (frame_stats == NULL) { return 0;
} return (frame_stats->sr_coded_error < frame_stats->coded_error) ||
((frame_stats->pcnt_second_ref > frame_stats->pcnt_inter) &&
(frame_stats->pcnt_second_ref >= 0.5));
}
// Accumulate a measure of how uniform (or conversely how random) the motion // field is (a ratio of abs(mv) / mv). if (pct > 0.05) { constdouble mvr_ratio =
fabs(stats->mvr_abs) / DOUBLE_DIVIDE_CHECK(fabs(stats->MVr)); constdouble mvc_ratio =
fabs(stats->mvc_abs) / DOUBLE_DIVIDE_CHECK(fabs(stats->MVc));
// Frame booost is based on inter error.
frame_boost = (twopass->kf_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 = VPXMAX(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 scaling // The 40.0 value here is an experimentally derived baseline minimum. // This value is in line with the minimum per frame boost in the alt_ref // boost calculation.
frame_boost =
(frame_boost + twopass->kf_frame_min_boost) * boost_q_correction;
// Maximum allowed boost this frame. May be different for first vs subsequent // key frames.
max_boost = (cpi->common.current_video_frame == 0)
? twopass->kf_frame_max_boost_first
: twopass->kf_frame_max_boost_subs;
max_boost *= zm_factor * boost_q_correction;
return VPXMIN(frame_boost, max_boost);
}
staticint compute_arf_boost(const FRAME_INFO *frame_info,
TWO_PASS *const twopass, int arf_show_idx, int f_frames, int b_frames, int avg_frame_qindex) { const FIRST_PASS_INFO *first_pass_info = &twopass->first_pass_info; int i; double boost_score = 0.0; double mv_ratio_accumulator = 0.0; double decay_accumulator = 1.0; double this_frame_mv_in_out = 0.0; double mv_in_out_accumulator = 0.0; double abs_mv_in_out_accumulator = 0.0; int arf_boost; int flash_detected = 0;
// Search forward from the proposed arf/next gf position. for (i = 0; i < f_frames; ++i) { const FIRSTPASS_STATS *this_frame =
fps_get_frame_stats(first_pass_info, arf_show_idx + i); const FIRSTPASS_STATS *next_frame =
fps_get_frame_stats(first_pass_info, arf_show_idx + i + 1); if (this_frame == NULL) break;
// Update the motion related elements to the boost calculation.
accumulate_frame_motion_stats(
this_frame, &this_frame_mv_in_out, &mv_in_out_accumulator,
&abs_mv_in_out_accumulator, &mv_ratio_accumulator);
// We want to discount the flash frame itself and the recovery // frame that follows as both will have poor scores.
flash_detected = detect_flash_from_frame_stats(this_frame) ||
detect_flash_from_frame_stats(next_frame);
// Search backward towards last gf position. for (i = -1; i >= -b_frames; --i) { const FIRSTPASS_STATS *this_frame =
fps_get_frame_stats(first_pass_info, arf_show_idx + i); const FIRSTPASS_STATS *next_frame =
fps_get_frame_stats(first_pass_info, arf_show_idx + i + 1); if (this_frame == NULL) break;
// Update the motion related elements to the boost calculation.
accumulate_frame_motion_stats(
this_frame, &this_frame_mv_in_out, &mv_in_out_accumulator,
&abs_mv_in_out_accumulator, &mv_ratio_accumulator);
// We want to discount the flash frame itself and the recovery // frame that follows as both will have poor scores.
flash_detected = detect_flash_from_frame_stats(this_frame) ||
detect_flash_from_frame_stats(next_frame);
// Calculate a section intra ratio used in setting max loop filter. staticint calculate_section_intra_ratio(const FIRSTPASS_STATS *begin, const FIRSTPASS_STATS *end, int section_length) { const FIRSTPASS_STATS *s = begin; double intra_error = 0.0; double coded_error = 0.0; int i = 0;
while (s < end && i < section_length) {
intra_error += s->intra_error;
coded_error += s->coded_error;
++s;
++i;
}
// Clip based on user supplied data rate variability limit. if (total_group_bits > (int64_t)max_bits * gop_frames)
total_group_bits = (int64_t)max_bits * gop_frames;
return total_group_bits;
}
// Calculate the number bits extra to assign to boosted frames in a group. staticint calculate_boost_bits(int frame_count, int boost,
int64_t total_group_bits) { int allocation_chunks;
// return 0 for invalid inputs (could arise e.g. through rounding errors) if (!boost || (total_group_bits <= 0) || (frame_count < 0)) return 0;
// Calculate the number of extra bits for use in the boosted frame or frames. return VPXMAX((int)(((int64_t)boost * total_group_bits) / allocation_chunks),
0);
}
// Used in corpus vbr: Calculates the total normalized group complexity score // for a given number of frames starting at the current position in the stats // file. staticdouble calculate_group_score(VP9_COMP *cpi, double av_score, int frame_count) {
VP9EncoderConfig *const oxcf = &cpi->oxcf;
TWO_PASS *const twopass = &cpi->twopass; const FIRSTPASS_STATS *s = twopass->stats_in; double score_total = 0.0; int i = 0;
// We don't ever want to return a 0 score here. if (frame_count == 0) return 1.0;
while ((i < frame_count) && (s < twopass->stats_in_end)) {
score_total += calculate_norm_frame_score(cpi, twopass, oxcf, s, av_score);
++s;
++i;
}
return score_total;
}
staticvoid find_arf_order(VP9_COMP *cpi, GF_GROUP *gf_group, int *index_counter, int depth, int start, int end) {
TWO_PASS *twopass = &cpi->twopass; const FIRSTPASS_STATS *const start_pos = twopass->stats_in;
FIRSTPASS_STATS fpf_frame; constint mid = (start + end + 1) >> 1; constint min_frame_interval = 2; int idx;
// For key frames the frame target rate is already set and it // is also the golden frame. // === [frame_index == 0] === if (!key_frame)
set_gf_overlay_frame_type(gf_group, frame_index, rc->source_alt_ref_active);
// TODO(b/345523905): Why do we need to set an overlay frame in the end?
set_gf_overlay_frame_type(gf_group, frame_index, rc->source_alt_ref_pending);
gf_group->arf_src_offset[frame_index] = 0;
gf_group->frame_gop_index[frame_index] = rc->baseline_gf_interval;
// Set the frame ops number.
gf_group->gf_group_size = frame_index;
}
constint show_frame_count = gop_coding_frames - gop_decision->use_alt_ref; int frame_index = 0; int show_frame_index = 0;
for (int i = frame_index; i < gop_coding_frames; i++) {
set_gf_frame_type(gop_decision->update_type[i], show_frame_count, gf_group,
&frame_index, &show_frame_index);
gf_group->ext_rc_ref[i].last_index = 0;
gf_group->ext_rc_ref[i].golden_index = 0;
gf_group->ext_rc_ref[i].altref_index = 0; for (int ref_frame = 0; ref_frame < 3; ref_frame++) { const vpx_rc_ref_frame_t *const ext_ref_frame =
&gop_decision->ref_frame_list[i]; constint ref_index = ext_ref_frame->index[ref_frame];
gf_group->ref_frame_list[i][ref_frame] = ext_ref_frame->index[ref_frame]; switch (ext_ref_frame->name[ref_frame]) { case VPX_RC_LAST_FRAME:
gf_group->ext_rc_ref[i].last_index = ref_index; break; case VPX_RC_GOLDEN_FRAME:
gf_group->ext_rc_ref[i].golden_index = ref_index; break; case VPX_RC_ALTREF_FRAME:
gf_group->ext_rc_ref[i].altref_index = ref_index; break; default: break;
}
} if (gf_group->update_type[i] == OVERLAY_UPDATE) { // From ext_rc, overlay may not update any ref. But here we force it to // update its arf's slot. This is probably OK since the arf and this // overlay frame should be very similar.
gf_group->update_ref_idx[i] = gf_group->ext_rc_ref[i].altref_index;
}
} // max_layer_depth is hardcoded to match the behavior of // define_gf_group_structure() // TODO(angiebird): Check whether max_layer_depth has performance impact.
gf_group->max_layer_depth = 2;
gf_group->allowed_max_layer_depth = 1;
gf_group->gf_group_size = gop_coding_frames;
// TODO(b/345523905): Why do we need to set an overlay frame in the end?
assert(show_frame_count == show_frame_index); if (gop_decision->use_alt_ref) {
gf_group_set_overlay_frame(gf_group, gf_group->gf_group_size,
show_frame_index);
} else {
gf_group_set_inter_normal_frame(gf_group, gf_group->gf_group_size,
show_frame_index);
}
staticvoid allocate_gf_group_bits(VP9_COMP *cpi, int64_t gf_group_bits, int gf_arf_bits) {
VP9EncoderConfig *const oxcf = &cpi->oxcf;
RATE_CONTROL *const rc = &cpi->rc;
TWO_PASS *const twopass = &cpi->twopass;
GF_GROUP *const gf_group = &twopass->gf_group;
FIRSTPASS_STATS frame_stats; int i; int frame_index = 0; int target_frame_size; int key_frame; constint max_bits = frame_max_bits(&cpi->rc, oxcf);
int64_t total_group_bits = gf_group_bits; int mid_frame_idx; int normal_frames; int normal_frame_bits; int last_frame_reduction = 0; double av_score = 1.0; double tot_norm_frame_score = 1.0; double this_frame_score = 1.0;
// Define the GF structure and specify int gop_frames = gf_group->gf_group_size;
key_frame = cpi->common.frame_type == KEY_FRAME;
// For key frames the frame target rate is already set and it // is also the golden frame. // === [frame_index == 0] === if (!key_frame) {
gf_group->bit_allocation[frame_index] =
rc->source_alt_ref_active ? 0 : gf_arf_bits;
}
// Deduct the boost bits for arf (or gf if it is not a key frame) // from the group total. if (rc->source_alt_ref_pending || !key_frame) total_group_bits -= gf_arf_bits;
++frame_index;
// === [frame_index == 1] === // Store the bits to spend on the ARF if there is one. if (rc->source_alt_ref_pending) {
gf_group->bit_allocation[frame_index] = gf_arf_bits;
if (cpi->multi_layer_arf) { int idx; int arf_depth_bits[MAX_ARF_LAYERS] = { 0 }; int arf_depth_count[MAX_ARF_LAYERS] = { 0 }; int arf_depth_boost[MAX_ARF_LAYERS] = { 0 }; int total_arfs = 1; // Account for the base layer ARF.
for (idx = 0; idx < gop_frames; ++idx) { if (gf_group->update_type[idx] == ARF_UPDATE) {
arf_depth_boost[gf_group->layer_depth[idx]] += gf_group->gfu_boost[idx];
++arf_depth_count[gf_group->layer_depth[idx]];
}
}
// Allocate bits to the other frames in the group. for (i = 0; i < normal_frames; ++i) { if (EOF == input_stats(twopass, &frame_stats)) break; if (oxcf->vbr_corpus_complexity) {
this_frame_score = calculate_norm_frame_score(cpi, twopass, oxcf,
&frame_stats, av_score);
normal_frame_bits = (int)((double)total_group_bits *
(this_frame_score / tot_norm_frame_score));
}
// Add in some extra bits for the middle frame in the group.
gf_group->bit_allocation[mid_frame_idx] += last_frame_reduction;
// Note: // We need to configure the frame at the end of the sequence + 1 that will be // the start frame for the next group. Otherwise prior to the call to // vp9_rc_get_second_pass_params() the data will be undefined.
}
// Adjusts the ARNF filter for a GF group. staticvoid adjust_group_arnr_filter(VP9_COMP *cpi, double section_noise, double section_inter, double section_motion) {
TWO_PASS *const twopass = &cpi->twopass; double section_zeromv = section_inter - section_motion;
if (section_zeromv > 0.50) twopass->arnr_strength_adjustment += 1;
}
// Analyse and define a gf/arf group. #define ARF_ABS_ZOOM_THRESH 4.0
#define MAX_GF_BOOST 5400
typedefstruct RANGE { int min; int max;
} RANGE;
/* get_gop_coding_frame_num() depends on several fields in RATE_CONTROL *rc as * follows. * Static fields: * (The following fields will remain unchanged after initialization of encoder.) * rc->static_scene_max_gf_interval * rc->min_gf_interval * twopass->sr_diff_factor * twopass->sr_default_decay_limit * twopass->zm_factor * * Dynamic fields: * (The following fields will be updated before or after coding each frame.) * rc->frames_to_key * rc->frames_since_key * rc->source_alt_ref_active * * Special case: if CONFIG_RATE_CTRL is true, the external arf indexes will * determine the arf position. * * TODO(angiebird): Separate the dynamic fields and static fields into two * structs.
*/ staticint get_gop_coding_frame_num( int *use_alt_ref, const FRAME_INFO *frame_info, const TWO_PASS *const twopass, const RATE_CONTROL *rc, int gf_start_show_idx, const RANGE *active_gf_interval, double gop_intra_factor, int lag_in_frames, int *end_of_sequence) { const FIRST_PASS_INFO *first_pass_info = &twopass->first_pass_info; double loop_decay_rate = 1.00; double mv_ratio_accumulator = 0.0; double this_frame_mv_in_out = 0.0; double mv_in_out_accumulator = 0.0; double abs_mv_in_out_accumulator = 0.0; double sr_accumulator = 0.0; // Motion breakout threshold for loop below depends on image size. double mv_ratio_accumulator_thresh =
(frame_info->frame_height + frame_info->frame_width) / 4.0; double zero_motion_accumulator = 1.0; int gop_coding_frames;
// Test for the case where there is a brief flash but the prediction // quality back to an earlier frame is then restored.
next_next_frame = fps_get_frame_stats(
first_pass_info, gf_start_show_idx + gop_coding_frames + 1);
flash_detected = detect_flash_from_frame_stats(next_next_frame);
// Update the motion related elements to the boost calculation.
accumulate_frame_motion_stats(
next_frame, &this_frame_mv_in_out, &mv_in_out_accumulator,
&abs_mv_in_out_accumulator, &mv_ratio_accumulator);
// Accumulate the effect of prediction quality decay. if (!flash_detected) { double last_loop_decay_rate = loop_decay_rate;
loop_decay_rate = get_prediction_decay_rate(twopass, next_frame);
// Break clause to detect very still sections after motion. For example, // a static image after a fade or other transition. if (gop_coding_frames > rc->min_gf_interval && loop_decay_rate >= 0.999 &&
last_loop_decay_rate < 0.9) { int still_interval = 5; if (check_transition_to_still(first_pass_info,
gf_start_show_idx + gop_coding_frames,
still_interval)) {
*use_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 (gop_coding_frames == 1) {
sr_accumulator += next_frame->coded_error;
} else {
sr_accumulator +=
(next_frame->sr_coded_error - next_frame->coded_error);
}
}
// Break out conditions. // Break at maximum of active_gf_interval->max unless almost totally // static. // // Note that the addition of a test of rc->source_alt_ref_active is // deliberate. The effect of this is that after a normal altref group even // if the material is static there will be one normal length GF group // before allowing longer GF groups. The reason for this is that in cases // such as slide shows where slides are separated by a complex transition // such as a fade, the arf group spanning the transition may not be coded // at a very high quality and hence this frame (with its overlay) is a // poor golden frame to use for an extended group. if ((gop_coding_frames >= active_gf_interval->max) &&
((zero_motion_accumulator < 0.995) || (rc->source_alt_ref_active))) { break;
} if ( // Don't break out with a very short interval.
(gop_coding_frames >= active_gf_interval->min) && // If possible don't break very close to a kf
((rc->frames_to_key - gop_coding_frames) >= rc->min_gf_interval) &&
(gop_coding_frames & 0x01) && (!flash_detected) &&
((mv_ratio_accumulator > mv_ratio_accumulator_thresh) ||
(abs_mv_in_out_accumulator > ARF_ABS_ZOOM_THRESH) ||
(sr_accumulator > gop_intra_factor * next_frame->intra_error))) { break;
}
}
*use_alt_ref &= zero_motion_accumulator < 0.995;
*use_alt_ref &= gop_coding_frames < lag_in_frames;
*use_alt_ref &= gop_coding_frames >= rc->min_gf_interval; return gop_coding_frames;
}
static RANGE get_active_gf_inverval_range_simple(int min_gf_interval, int arf_active_or_kf, int frames_to_key) {
RANGE active_gf_interval;
active_gf_interval.min = min_gf_interval + arf_active_or_kf + 2;
active_gf_interval.max = 16 + arf_active_or_kf;
static RANGE get_active_gf_inverval_range( const FRAME_INFO *frame_info, const RATE_CONTROL *rc, int arf_active_or_kf, int gf_start_show_idx, int active_worst_quality, int last_boosted_qindex) {
RANGE active_gf_interval; int int_max_q = (int)(vp9_convert_qindex_to_q(active_worst_quality,
frame_info->bit_depth)); int q_term = (gf_start_show_idx == 0)
? int_max_q / 32
: (int)(vp9_convert_qindex_to_q(last_boosted_qindex,
frame_info->bit_depth) /
6);
active_gf_interval.min =
rc->min_gf_interval + arf_active_or_kf + VPXMIN(2, int_max_q / 200);
active_gf_interval.min =
VPXMIN(active_gf_interval.min, rc->max_gf_interval + arf_active_or_kf);
// The value chosen depends on the active Q range. At low Q we have // 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_gf_interval.max = 11 + arf_active_or_kf + VPXMIN(5, q_term);
// Force max GF interval to be odd.
active_gf_interval.max = active_gf_interval.max | 0x01;
// Would the active max drop us out just before the near the next kf? if ((active_gf_interval.max <= rc->frames_to_key) &&
(active_gf_interval.max >= (rc->frames_to_key - rc->min_gf_interval))) {
active_gf_interval.max = rc->frames_to_key / 2;
}
active_gf_interval.max =
VPXMAX(active_gf_interval.max, active_gf_interval.min); return active_gf_interval;
}
staticint get_arf_layers(int multi_layer_arf, int max_layers, int coding_frame_num) {
assert(max_layers <= MAX_ARF_LAYERS); if (multi_layer_arf) { int layers = 0; int i; for (i = coding_frame_num; i > 0; i >>= 1) {
++layers;
}
layers = VPXMIN(max_layers, layers); return layers;
} else { return 1;
}
}
// If this is a key frame or the overlay from a previous arf then // the error score / cost of this frame has already been accounted for. constint arf_active_or_kf = is_key_frame || rc->source_alt_ref_active; int is_alt_ref_flash = 0;
double gop_intra_factor; int gop_frames;
RANGE active_gf_interval; // Whether this is at the end of last GOP of this sequence. int end_of_sequence = 0;
// Reset the GF group data structures unless this is a key // frame in which case it will already have been done. if (is_key_frame == 0) {
vp9_zero(twopass->gf_group);
++rc->gop_global_index;
} else {
rc->gop_global_index = 0;
}
if (gop_decision_ready) {
gop_coding_frames = gop_decision.gop_coding_frames;
use_alt_ref = gop_decision.use_alt_ref;
}
#if CONFIG_RATE_CTRL // If the external gop_command is on, we will override the decisions // of gop_coding_frames and use_alt_ref. if (cpi->oxcf.use_simple_encode_api) { const GOP_COMMAND *gop_command = &cpi->encode_command.gop_command;
assert(allow_alt_ref == 1); if (gop_command->use) {
gop_coding_frames = gop_command_coding_frame_count(gop_command);
use_alt_ref = gop_command->use_alt_ref;
}
} #endif
// Was the group length constrained by the requirement for a new KF?
rc->constrained_gf_group = (gop_coding_frames >= rc->frames_to_key) ? 1 : 0;
// Should we use the alternate reference frame. if (use_alt_ref) { constint f_frames =
(rc->frames_to_key - gop_coding_frames >= gop_coding_frames - 1)
? gop_coding_frames - 1
: VPXMAX(0, rc->frames_to_key - gop_coding_frames); constint b_frames = gop_coding_frames - 1; constint avg_inter_frame_qindex = rc->avg_frame_qindex[INTER_FRAME]; // TODO(angiebird): figure out why arf's location is assigned this way constint arf_show_idx = VPXMIN(gf_start_show_idx + gop_coding_frames + 1,
fps_get_num_frames(first_pass_info));
// Calculate the boost for alt ref.
rc->gfu_boost =
compute_arf_boost(frame_info, twopass, arf_show_idx, f_frames, b_frames,
avg_inter_frame_qindex);
rc->source_alt_ref_pending = 1;
} else { constint f_frames = gop_coding_frames - 1; constint b_frames = 0; constint avg_inter_frame_qindex = rc->avg_frame_qindex[INTER_FRAME]; // TODO(angiebird): figure out why arf's location is assigned this way constint gld_show_idx =
VPXMIN(gf_start_show_idx + 1, fps_get_num_frames(first_pass_info)); constint arf_boost =
compute_arf_boost(frame_info, twopass, gld_show_idx, f_frames, b_frames,
avg_inter_frame_qindex);
rc->gfu_boost = VPXMIN((int)twopass->gf_max_total_boost, arf_boost);
rc->source_alt_ref_pending = 0;
}
if (!is_lossless_requested(&cpi->oxcf)) { if (rc->frames_since_key >= rc->frames_to_key) { // Increase the active best quality in the second half of key frame // interval.
rc->arf_active_best_quality_adjustment_factor =
LAST_ALR_ACTIVE_BEST_QUALITY_ADJUSTMENT_FACTOR +
(1.0 - LAST_ALR_ACTIVE_BEST_QUALITY_ADJUSTMENT_FACTOR) *
(rc->frames_to_key - gop_coding_frames) /
(VPXMAX(1, ((rc->frames_to_key + rc->frames_since_key) / 2 -
gop_coding_frames)));
rc->arf_increase_active_best_quality = 1;
} elseif ((rc->frames_to_key - gop_coding_frames) > 0) { // Reduce the active best quality in the first half of key frame interval.
rc->arf_active_best_quality_adjustment_factor =
LAST_ALR_ACTIVE_BEST_QUALITY_ADJUSTMENT_FACTOR +
(1.0 - LAST_ALR_ACTIVE_BEST_QUALITY_ADJUSTMENT_FACTOR) *
(rc->frames_since_key + gop_coding_frames) /
(VPXMAX(1, (rc->frames_to_key + rc->frames_since_key) / 2 +
gop_coding_frames));
rc->arf_increase_active_best_quality = -1;
}
}
#ifdef AGGRESSIVE_VBR // Limit maximum boost based on interval length.
rc->gfu_boost = VPXMIN((int)rc->gfu_boost, gop_coding_frames * 140); #else
rc->gfu_boost = VPXMIN((int)rc->gfu_boost, gop_coding_frames * 200); #endif
// Cap the ARF boost when perceptual quality AQ mode is enabled. This is // designed to improve the perceptual quality of high value content and to // make consistent quality across consecutive frames. It will hurt objective // quality. if (oxcf->aq_mode == PERCEPTUAL_AQ)
rc->gfu_boost = VPXMIN(rc->gfu_boost, MIN_ARF_GF_BOOST);
if (rc->source_alt_ref_pending)
is_alt_ref_flash = detect_flash(twopass, rc->baseline_gf_interval);
{ constdouble av_err = get_distribution_av_err(cpi, twopass); constdouble mean_mod_score = twopass->mean_mod_score; // If the first frame is a key frame or the overlay from a previous arf then // the error score / cost of this frame has already been accounted for. int start_idx = arf_active_or_kf ? 1 : 0; int j; for (j = start_idx; j < gop_coding_frames; ++j) { int show_idx = gf_start_show_idx + j; const FIRSTPASS_STATS *frame_stats =
fps_get_frame_stats(first_pass_info, show_idx); // TODO(b/345831640): Why do we set gop_coding_frames as the upperbound of // the for loop here? gop_coding_frames does not reflect the "show frame // count" in a GOP. Therefore, it's possible to get a NULL pointer from // fps_get_frame_stats(). Here we mitigate the issue using break whenever // frame_stats == NULL. Show we set the upperbound to show frame count? if (frame_stats == NULL) { if (cpi->ext_ratectrl.ready &&
(cpi->ext_ratectrl.funcs.rc_type & VPX_RC_GOP) != 0 &&
cpi->ext_ratectrl.funcs.get_gop_decision != NULL) { // Since in ext_ratectrl, gop_coding_frames means the count of both // show and no show frames. Using this variable to access // first_pass_info will trigger out-of-range error because // first_pass_info only contains show frames. This part is used for // computing gf_group_err which will be used to compute gf_group_bits // for libvpx internal rate control. Since ext_ratectrl is using // external rate control module, this part becomes non-critical. // Hence, we can safely turn off this error reporting. In the future, // we should refactor the code so that this part is not used by // ext_ratectrl. break;
}
vpx_internal_error(&cm->error, VPX_CODEC_ERROR, "In define_gf_group(), frame_stats is NULL when " "calculating gf_group_err."); break;
} // Accumulate error score of frames in this gf group.
gf_group_err += calc_norm_frame_score(oxcf, frame_info, frame_stats,
mean_mod_score, av_err);
gf_group_raw_error += frame_stats->coded_error;
gf_group_noise += frame_stats->frame_noise_energy;
gf_group_skip_pct += frame_stats->intra_skip_pct;
gf_group_inactive_zone_rows += frame_stats->inactive_zone_rows;
gf_group_inter += frame_stats->pcnt_inter;
gf_group_motion += frame_stats->pcnt_motion;
}
}
// Calculate the bits to be allocated to the gf/arf group as a whole
gf_group_bits = calculate_total_gf_group_bits(cpi, gf_group_err);
// Store the average moise level measured for the group // TODO(any): Experiment with removal of else condition (gop_frames = 0) so // that consumption of group noise energy is based on previous gf group if (gop_frames > 0)
twopass->gf_group.group_noise_energy = (int)(gf_group_noise / gop_frames); else
twopass->gf_group.group_noise_energy = 0;
// Calculate an estimate of the maxq needed for the group. // We are more aggressive about correcting for sections // where there could be significant overshoot than for easier // sections where we do not wish to risk creating an overshoot // of the allocated bit budget. if ((cpi->oxcf.rc_mode != VPX_Q) && (rc->baseline_gf_interval > 1)) { constint vbr_group_bits_per_frame = (int)(gf_group_bits / gop_frames); constdouble group_av_err = gf_group_raw_error / gop_frames; constdouble group_av_noise = gf_group_noise / gop_frames; constdouble group_av_skip_pct = gf_group_skip_pct / gop_frames; constdouble group_av_inactive_zone = ((gf_group_inactive_zone_rows * 2) /
(gop_frames * (double)cm->mb_rows)); int 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);
twopass->active_worst_quality =
(int)((tmp_q + (twopass->active_worst_quality *
(twopass->active_wq_factor - 1))) /
twopass->active_wq_factor);
#if CONFIG_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
}
// Calculate the extra bits to be used for boosted frame(s)
gf_arf_bits = calculate_boost_bits((rc->baseline_gf_interval - 1),
rc->gfu_boost, gf_group_bits);
// Adjust KF group bits and error remaining.
twopass->kf_group_error_left -= gf_group_err;
// Decide GOP structure. if (gop_decision_ready) {
ext_rc_define_gf_group_structure(&gop_decision, &twopass->gf_group); // Set the fb idx for the first frame in this GOP.
cpi->lst_fb_idx = twopass->gf_group.ext_rc_ref[0].last_index;
cpi->gld_fb_idx = twopass->gf_group.ext_rc_ref[0].golden_index;
cpi->alt_fb_idx = twopass->gf_group.ext_rc_ref[0].altref_index;
} else {
define_gf_group_structure(cpi);
}
// Allocate bits to each of the frames in the GF group.
allocate_gf_group_bits(cpi, gf_group_bits, gf_arf_bits);
// Reset the file position.
reset_fpf_position(twopass, start_pos);
// Calculate a section intra ratio used in setting max loop filter.
twopass->section_intra_rating = calculate_section_intra_ratio(
start_pos, twopass->stats_in_end, rc->baseline_gf_interval);
if (oxcf->resize_mode == RESIZE_DYNAMIC) { // Default to starting GF groups at normal frame size.
cpi->rc.next_frame_size_selector = UNSCALED;
} #if !CONFIG_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
rc->preserve_arf_as_gld = rc->preserve_next_arf_as_gld;
rc->preserve_next_arf_as_gld = 0; // If alt ref frame is flash do not set preserve_arf_as_gld if (!is_lossless_requested(&cpi->oxcf) && !cpi->use_svc &&
cpi->oxcf.aq_mode == NO_AQ && cpi->multi_layer_arf && !is_alt_ref_flash)
rc->preserve_next_arf_as_gld = 1;
}
// Intra / Inter threshold very low #define VERY_LOW_II 1.5 // Clean slide transitions we expect a sharp single frame spike in error. #define ERROR_SPIKE 5.0
// Slide show transition detection. // Tests for case where there is very low error either side of the current frame // but much higher just for this frame. This can help detect key frames in // slide shows even where the slides are pictures of different sizes. // Also requires that intra and inter errors are very similar to help eliminate // harmful false positives. // It will not help if the transition is a fade or other multi-frame effect. staticint slide_transition(const FIRSTPASS_STATS *this_frame, const FIRSTPASS_STATS *last_frame, const FIRSTPASS_STATS *next_frame) { return (this_frame->intra_error < (this_frame->coded_error * VERY_LOW_II)) &&
(this_frame->coded_error > (last_frame->coded_error * ERROR_SPIKE)) &&
(this_frame->coded_error > (next_frame->coded_error * ERROR_SPIKE));
}
// This test looks for anomalous changes in the nature of the intra signal // related to the previous and next frame as an indicator for coding a key // frame. This test serves to detect some additional scene cuts, // especially in lowish motion and low contrast sections, that are missed // by the other tests. staticint intra_step_transition(const FIRSTPASS_STATS *this_frame, const FIRSTPASS_STATS *last_frame, const FIRSTPASS_STATS *next_frame) { double last_ii_ratio; double this_ii_ratio; double next_ii_ratio; double last_pcnt_intra = 1.0 - last_frame->pcnt_inter; double this_pcnt_intra = 1.0 - this_frame->pcnt_inter; double next_pcnt_intra = 1.0 - next_frame->pcnt_inter; double mod_this_intra = this_pcnt_intra + this_frame->pcnt_neutral;
// Calculate ii ratio for this frame last frame and next frame.
last_ii_ratio =
last_frame->intra_error / DOUBLE_DIVIDE_CHECK(last_frame->coded_error);
this_ii_ratio =
this_frame->intra_error / DOUBLE_DIVIDE_CHECK(this_frame->coded_error);
next_ii_ratio =
next_frame->intra_error / DOUBLE_DIVIDE_CHECK(next_frame->coded_error);
// Return true the intra/inter ratio for the current frame is // low but better in the next and previous frame and the relative usage of // intra in the current frame is markedly higher than the last and next frame. if ((this_ii_ratio < 2.0) && (last_ii_ratio > 2.25) &&
(next_ii_ratio > 2.25) && (this_pcnt_intra > (3 * last_pcnt_intra)) &&
(this_pcnt_intra > (3 * next_pcnt_intra)) &&
((this_pcnt_intra > 0.075) || (mod_this_intra > 0.85))) { return 1; // Very low inter intra ratio (i.e. not much gain from inter coding), most // blocks neutral on coding method and better inter prediction either side
} elseif ((this_ii_ratio < 1.25) && (mod_this_intra > 0.85) &&
(this_ii_ratio < last_ii_ratio * 0.9) &&
(this_ii_ratio < next_ii_ratio * 0.9)) { return 1;
} else { return 0;
}
}
// Minimum % intra coding observed in first pass (1.0 = 100%) #define MIN_INTRA_LEVEL 0.25 // Threshold for use of the lagging second reference frame. Scene cuts do not // usually have a high second ref usage. #define SECOND_REF_USAGE_THRESH 0.2 // Hard threshold where the first pass chooses intra for almost all blocks. // In such a case even if the frame is not a scene cut coding a key frame // may be a good option. #define VERY_LOW_INTER_THRESH 0.05 // Maximum threshold for the relative ratio of intra error score vs best // inter error score. #define KF_II_ERR_THRESHOLD 2.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
// Get the next frame details if (show_idx + 1 + i == fps_get_num_frames(first_pass_info) - 1) break;
}
// If there is tolerable prediction for at least the next 3 frames then // break out else discard this potential key frame and move on if (boost_score > 30.0 && (i > 3)) {
is_viable_kf = 1;
} else {
is_viable_kf = 0;
}
}
int vp9_get_frames_to_next_key(const VP9EncoderConfig *oxcf, const TWO_PASS *const twopass, int kf_show_idx, int min_gf_interval) { const FIRST_PASS_INFO *first_pass_info = &twopass->first_pass_info; double recent_loop_decay[FRAMES_TO_CHECK_DECAY]; int j; int frames_to_key; int max_frames_to_key = first_pass_info->num_frames - kf_show_idx;
max_frames_to_key = VPXMIN(max_frames_to_key, oxcf->key_freq);
// 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; // Find the next keyframe. if (!oxcf->auto_key) {
frames_to_key = max_frames_to_key;
} else {
frames_to_key = 1; while (frames_to_key < max_frames_to_key) { // Provided that we are not at the end of the file... if (kf_show_idx + frames_to_key + 1 < first_pass_info->num_frames) { double loop_decay_rate; double decay_accumulator; const FIRSTPASS_STATS *next_frame = fps_get_frame_stats(
first_pass_info, kf_show_idx + frames_to_key + 1);
// Check for a scene cut. if (test_candidate_kf(first_pass_info, kf_show_idx + frames_to_key)) break;
// How fast is the prediction quality decaying?
loop_decay_rate = get_prediction_decay_rate(twopass, next_frame);
// We want to know something about the recent past... rather than // as used elsewhere where we are concerned with decay in prediction // quality since the last GF or KF.
recent_loop_decay[(frames_to_key - 1) % FRAMES_TO_CHECK_DECAY] =
loop_decay_rate;
decay_accumulator = 1.0; for (j = 0; j < FRAMES_TO_CHECK_DECAY; ++j)
decay_accumulator *= recent_loop_decay[j];
// Special check for transition or high motion followed by a // static scene. if ((frames_to_key - 1) > min_gf_interval && loop_decay_rate >= 0.999 &&
decay_accumulator < 0.9) { int still_interval = oxcf->key_freq - (frames_to_key - 1); // TODO(angiebird): Figure out why we use "+1" here int show_idx = kf_show_idx + frames_to_key; if (check_transition_to_still(first_pass_info, show_idx,
still_interval)) { break;
}
}
}
++frames_to_key;
}
} return frames_to_key;
}
// If there is a max kf interval set by the user we must obey it. // We already breakout of the loop above at 2x max. // This code centers the extra kf if the actual natural interval // is between 1x and 2x. if (rc->frames_to_key >= cpi->oxcf.key_freq) {
rc->next_key_frame_forced = 1;
} else {
rc->next_key_frame_forced = 0;
}
for (i = 0; i < rc->frames_to_key; ++i) { const FIRSTPASS_STATS *frame_stats =
fps_get_frame_stats(first_pass_info, kf_show_idx + i); // Accumulate kf group error.
kf_group_err += calc_norm_frame_score(oxcf, frame_info, frame_stats,
mean_mod_score, av_err);
}
// Calculate the number of bits that should be assigned to the kf group. if (twopass->bits_left > 0 && twopass->normalized_score_left > 0.0) { // Maximum number of bits for a single normal frame (not key frame). constint max_bits = frame_max_bits(rc, &cpi->oxcf);
// Maximum number of bits allocated to the key frame group.
int64_t max_grp_bits;
// 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));
// Clip based on maximum per frame rate defined by the user.
max_grp_bits = (int64_t)max_bits * (int64_t)rc->frames_to_key; if (twopass->kf_group_bits > max_grp_bits)
twopass->kf_group_bits = max_grp_bits;
} else {
twopass->kf_group_bits = 0;
}
twopass->kf_group_bits = VPXMAX(0, twopass->kf_group_bits);
// Scan through the kf group collating various stats used to determine // how many bits to spend on it.
boost_score = 0.0;
for (i = 0; i < VPXMIN(MAX_SCAN_FRAMES_FOR_KF_BOOST, (rc->frames_to_key - 1));
++i) { if (EOF == input_stats(twopass, &next_frame)) break;
for (i = 0; i < (rc->frames_to_key - 1); ++i) { if (EOF == input_stats(twopass, &next_frame)) break;
// The zero motion test here insures that if we mark a kf group as static // it is static throughout not just the first KF_BOOST_SCAN_MAX_FRAMES. // It also allows for a larger boost on long static groups. if ((i <= kf_boost_scan_frames) || (zero_motion_accumulator >= 0.99)) { double frame_boost; double zm_factor;
// Monitor for static sections. // First frame in kf group the second ref indicator is invalid. if (i > 0) {
zero_motion_accumulator =
VPXMIN(zero_motion_accumulator,
get_zero_motion_factor(twopass, &next_frame));
} else {
zero_motion_accumulator =
next_frame.pcnt_inter - next_frame.pcnt_motion;
}
// 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 reference before the new key // frame. if (i < 2) sr_accumulator = 0.0;
frame_boost =
calc_kf_frame_boost(cpi, &next_frame, &sr_accumulator, 0, 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);
// Store the zero motion percentage
twopass->kf_zeromotion_pct = (int)(zero_motion_accumulator * 100.0);
// Calculate a section intra ratio used in setting max loop filter.
twopass->key_frame_section_intra_rating = calculate_section_intra_ratio(
start_position, twopass->stats_in_end, rc->frames_to_key);
// Special case for static / slide show content but don't apply // if the kf group is very short. if ((zero_motion_accumulator > 0.99) && (rc->frames_to_key > 8)) {
rc->kf_boost = (int)(twopass->kf_max_total_boost);
} else { // Apply various clamps for min and max oost
rc->kf_boost = VPXMAX((int)boost_score, (rc->frames_to_key * 3));
rc->kf_boost = VPXMAX(rc->kf_boost, MIN_KF_TOT_BOOST);
rc->kf_boost = VPXMIN(rc->kf_boost, (int)(twopass->kf_max_total_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); // Based on the spatial complexity, increase the bits allocated to key frame.
kf_bits +=
(int)((twopass->kf_group_bits - kf_bits) * (kf_mod_err / kf_group_err));
max_kf_bits =
twopass->kf_group_bits - (rc->frames_to_key - 1) * FRAME_OVERHEAD_BITS;
max_kf_bits = lclamp(max_kf_bits, 0, INT_MAX);
kf_bits = VPXMIN(kf_bits, (int)max_kf_bits);
twopass->kf_group_bits -= kf_bits;
// Save the bits to spend on the key frame.
gf_group->bit_allocation[0] = kf_bits;
gf_group->update_type[0] = KF_UPDATE;
gf_group->rf_level[0] = KF_STD;
gf_group->layer_depth[0] = 0;
// 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);
// 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;
if (oxcf->resize_mode == RESIZE_DYNAMIC) { // Default to normal-sized frame on keyframes.
cpi->rc.next_frame_size_selector = UNSCALED;
}
}
// Configure image size specific vizier parameters. // Later these will be set via additional command line options void vp9_init_vizier_params(TWO_PASS *const twopass, int screen_area) { // When |use_vizier_rc_params| is 1, we expect the rc parameters below to // have been initialised on the command line as adjustment factors such // that a factor of 1.0 will match the default behavior when // |use_vizier_rc_params| is 0 if (twopass->use_vizier_rc_params) {
twopass->active_wq_factor *= AV_WQ_FACTOR;
twopass->err_per_mb *= BASELINE_ERR_PER_MB;
twopass->sr_default_decay_limit *= DEFAULT_DECAY_LIMIT; if (twopass->sr_default_decay_limit > 1.0) // > 1.0 here makes no sense
twopass->sr_default_decay_limit = 1.0;
twopass->sr_diff_factor *= 1.0;
twopass->gf_frame_max_boost *= GF_MAX_FRAME_BOOST;
twopass->gf_max_total_boost *= MAX_GF_BOOST; // NOTE: In use max boost has precedence over min boost. So even if min is // somehow set higher than max the final boost value will be clamped to the // appropriate maximum.
twopass->kf_frame_min_boost *= KF_MIN_FRAME_BOOST;
twopass->kf_frame_max_boost_first *= KF_MAX_FRAME_BOOST;
twopass->kf_frame_max_boost_subs *= KF_MAX_FRAME_BOOST;
twopass->kf_max_total_boost *= MAX_KF_TOT_BOOST;
twopass->zm_factor *= DEFAULT_ZM_FACTOR; if (twopass->zm_factor > 1.0) // > 1.0 here makes no sense
twopass->zm_factor = 1.0;
// Correction for the fact that the kf_err_per_mb_factor default is // already different for different video formats and ensures that a passed // in value of 1.0 on the vizier command line will still match the current // default. if (screen_area < 1280 * 720) {
twopass->kf_err_per_mb *= 2000.0;
} elseif (screen_area < 1920 * 1080) {
twopass->kf_err_per_mb *= 500.0;
} else {
twopass->kf_err_per_mb *= 250.0;
}
} else { // When |use_vizier_rc_params| is 0, use defaults.
twopass->active_wq_factor = AV_WQ_FACTOR;
twopass->err_per_mb = BASELINE_ERR_PER_MB;
twopass->sr_default_decay_limit = DEFAULT_DECAY_LIMIT;
twopass->sr_diff_factor = 1.0;
twopass->gf_frame_max_boost = GF_MAX_FRAME_BOOST;
twopass->gf_max_total_boost = MAX_GF_BOOST;
twopass->kf_frame_min_boost = KF_MIN_FRAME_BOOST;
twopass->kf_frame_max_boost_first = KF_MAX_FRAME_BOOST;
twopass->kf_frame_max_boost_subs = KF_MAX_FRAME_BOOST;
twopass->kf_max_total_boost = MAX_KF_TOT_BOOST;
twopass->zm_factor = DEFAULT_ZM_FACTOR;
// Configure image size specific vizier parameters
if (cm->current_video_frame == 0) {
unsigned int screen_area = (cm->width * cm->height);
vp9_init_vizier_params(twopass, screen_area);
}
// If this is an arf frame then we don't want to read the stats file or
// advance the input pointer as we already have what we need.
if (gf_group->update_type[gf_group->index] == ARF_UPDATE) {
int target_rate;
// The multiplication by 256 reverses a scaling factor of (>> 8)
// applied when combining MB error values for the frame.
twopass->mb_av_energy = log((this_frame.intra_error * 256.0) + 1.0);
twopass->mb_smooth_pct = this_frame.intra_smooth_pct;
return;
}
vpx_clear_system_state();
if (cpi->oxcf.rc_mode == VPX_Q) {
twopass->active_worst_quality = cpi->oxcf.cq_level;
} else if (cm->current_video_frame == 0) {
const int frames_left =
(int)(twopass->total_stats.count - cm->current_video_frame);
// Special case code for first frame.
int64_t section_target_bandwidth = twopass->bits_left / frames_left;
section_target_bandwidth = VPXMIN(section_target_bandwidth, INT_MAX);
const double section_length = twopass->total_left_stats.count;
const double section_error =
twopass->total_left_stats.coded_error / section_length;
const double section_intra_skip =
twopass->total_left_stats.intra_skip_pct / section_length;
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;
int tmp_q;
// Set the frame content type flag.
if (this_frame.intra_skip_pct >= FC_ANIMATION_THRESH)
twopass->fr_content_type = FC_GRAPHICS_ANIMATION;
else
twopass->fr_content_type = FC_NORMAL;
// Keyframe and section processing.
if (rc->frames_to_key == 0 || (cpi->frame_flags & FRAMEFLAGS_KEY)) {
// Define next KF group and assign bits to it.
find_next_key_frame(cpi, show_idx);
} else {
cm->frame_type = INTER_FRAME;
}
// Define a new GF/ARF group. (Should always enter here for key frames).
if (rc->frames_till_gf_update_due == 0) {
define_gf_group(cpi, show_idx);
// The multiplication by 256 reverses a scaling factor of (>> 8)
// applied when combining MB error values for the frame.
twopass->mb_av_energy = log((this_frame.intra_error * 256.0) + 1.0);
twopass->mb_smooth_pct = this_frame.intra_smooth_pct;
// Update the total stats remaining structure.
subtract_stats(&twopass->total_left_stats, &this_frame);
}
// VBR correction is done through rc->vbr_bits_off_target. Based on the
// sign of this value, a limited % adjustment is made to the target rate
// of subsequent frames, to try and push it back towards 0. This method
// is designed to prevent extreme behaviour at the end of a clip
// or group of frames.
rc->vbr_bits_off_target += rc->base_frame_target - rc->projected_frame_size;
twopass->bits_left = VPXMAX(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;
// Increment the gf group index ready for the next frame.
++twopass->gf_group.index;
// If the rate control is drifting consider adjustment to min or maxq.
if ((cpi->oxcf.rc_mode != VPX_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 =
(cpi->oxcf.rc_mode == VPX_CQ ? MINQ_ADJ_LIMIT_CQ : MINQ_ADJ_LIMIT);
int aq_extend_min = 0;
int aq_extend_max = 0;
// Extend min or Max Q range to account for imbalance from the base
// value when using AQ.
if (cpi->oxcf.aq_mode != NO_AQ && cpi->oxcf.aq_mode != PSNR_AQ &&
cpi->oxcf.aq_mode != PERCEPTUAL_AQ) {
if (cm->seg.aq_av_offset < 0) {
// The balance of the AQ map tends towarda lowering the average Q.
aq_extend_min = 0;
aq_extend_max = VPXMIN(maxq_adj_limit, -cm->seg.aq_av_offset);
} else {
// The balance of the AQ map tends towards raising the average Q.
aq_extend_min = VPXMIN(minq_adj_limit, cm->seg.aq_av_offset);
aq_extend_max = 0;
}
}
// Undershoot.
if (rc->rate_error_estimate > cpi->oxcf.under_shoot_pct) {
--twopass->extend_maxq;
if (rc->rolling_target_bits >= rc->rolling_actual_bits)
++twopass->extend_minq;
// Overshoot.
} else if (rc->rate_error_estimate < -cpi->oxcf.over_shoot_pct) {
--twopass->extend_minq;
if (rc->rolling_target_bits < rc->rolling_actual_bits)
++twopass->extend_maxq;
} else {
// Adjustment for extreme local overshoot.
if (rc->projected_frame_size > (2 * rc->base_frame_target) &&
rc->projected_frame_size > (2 * rc->avg_frame_bandwidth))
++twopass->extend_maxq;
// Unwind undershoot or overshoot adjustment.
if (rc->rolling_target_bits < rc->rolling_actual_bits)
--twopass->extend_minq;
else if (rc->rolling_target_bits > rc->rolling_actual_bits)
--twopass->extend_maxq;
}
// If there is a big and undexpected undershoot then feed the extra
// bits back in quickly. One situation where this may happen is if a
// frame is unexpectedly almost perfectly predicted by the ARF or GF
// but not very well predcited by the previous frame.
if (!frame_is_kf_gf_arf(cpi) && !cpi->rc.is_src_frame_alt_ref) {
int fast_extra_thresh = rc->base_frame_target / HIGH_UNDERSHOOT_RATIO;
if (rc->projected_frame_size < fast_extra_thresh) {
rc->vbr_bits_off_target_fast +=
fast_extra_thresh - rc->projected_frame_size;
rc->vbr_bits_off_target_fast =
VPXMIN(rc->vbr_bits_off_target_fast,
(4 * (int64_t)rc->avg_frame_bandwidth));
// Fast adaptation of minQ if necessary to use up the extra bits.
if (rc->avg_frame_bandwidth) {
twopass->extend_minq_fast =
(int)(rc->vbr_bits_off_target_fast * 8 / rc->avg_frame_bandwidth);
}
twopass->extend_minq_fast = VPXMIN(
twopass->extend_minq_fast, minq_adj_limit - twopass->extend_minq);
} else if (rc->vbr_bits_off_target_fast) {
twopass->extend_minq_fast = VPXMIN(
twopass->extend_minq_fast, minq_adj_limit - twopass->extend_minq);
} else {
twopass->extend_minq_fast = 0;
}
}
}
}
#if CONFIG_RATE_CTRL
void vp9_get_next_group_of_picture(const VP9_COMP *cpi, int *first_is_key_frame,
int *use_alt_ref, int *coding_frame_count,
int *first_show_idx,
int *last_gop_use_alt_ref) {
const GOP_COMMAND *gop_command = &cpi->encode_command.gop_command;
// We make a copy of rc here because we want to get information from the
// encoder without changing its state.
// TODO(angiebird): Avoid copying rc here.
RATE_CONTROL rc = cpi->rc;
const int multi_layer_arf = 0;
const int allow_alt_ref = 1;
// We assume that current_video_frame is updated to the show index of the
// frame we are about to called. Note that current_video_frame is updated at
// the end of encode_frame_to_data_rate().
// TODO(angiebird): Avoid this kind of fragile style.
*first_show_idx = cpi->common.current_video_frame;
*last_gop_use_alt_ref = rc.source_alt_ref_active;
// Under CONFIG_RATE_CTRL, once the first_pass_info is ready, the number of
// coding frames (including show frame and alt ref) can be determined.
int vp9_get_coding_frame_num(const VP9EncoderConfig *oxcf,
const TWO_PASS *const twopass,
const FRAME_INFO *frame_info, int multi_layer_arf,
int allow_alt_ref) {
const FIRST_PASS_INFO *first_pass_info = &twopass->first_pass_info;
int coding_frame_num = 0;
RATE_CONTROL rc;
int gop_coding_frame_count;
int gop_show_frames;
int show_idx = 0;
int last_gop_use_alt_ref = 0;
vp9_rc_init(oxcf, 1, &rc);
while (show_idx < first_pass_info->num_frames) {
int use_alt_ref;
int first_is_key_frame = 0;
if (rc.frames_to_key == 0) {
rc.frames_to_key = vp9_get_frames_to_next_key(oxcf, twopass, show_idx,
rc.min_gf_interval);
rc.frames_since_key = 0;
first_is_key_frame = 1;
}
// key_frame_map points to an int array with size equal to
// first_pass_info->num_frames, which is also the number of show frames in the
// video.
memset(key_frame_map, 0,
sizeof(*key_frame_map) * first_pass_info->num_frames);
while (show_idx < first_pass_info->num_frames) {
int key_frame_group_size;
key_frame_map[show_idx] = 1;
key_frame_group_size =
vp9_get_frames_to_next_key(oxcf, twopass, show_idx, rc.min_gf_interval);
assert(key_frame_group_size > 0);
show_idx += key_frame_group_size;
}
assert(show_idx == first_pass_info->num_frames);
}
#endif // CONFIG_RATE_CTRL
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.