/* * Copyright (c) 2016, Alliance for Open Media. All rights reserved. * * This source code is subject to the terms of the BSD 2 Clause License and * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License * was not distributed with this source code in the LICENSE file, you can * obtain it at www.aomedia.org/license/software. If the Alliance for Open * Media Patent License 1.0 was not distributed with this source code in the * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
#define FRAME_OVERHEAD_BITS 200 #define ASSIGN_MINQ_TABLE(bit_depth, name) \ do { \ switch (bit_depth) { \ case AOM_BITS_8: name = name##_8; break; \ case AOM_BITS_10: name = name##_10; break; \ case AOM_BITS_12: name = name##_12; break; \ default: \
assert(0 && \ "bit_depth should be AOM_BITS_8, AOM_BITS_10" \ " or AOM_BITS_12"); \
name = NULL; \
} \
} while (0)
// Tables relating active max Q to active min Q staticint kf_low_motion_minq_8[QINDEX_RANGE]; staticint kf_high_motion_minq_8[QINDEX_RANGE]; staticint arfgf_low_motion_minq_8[QINDEX_RANGE]; staticint arfgf_high_motion_minq_8[QINDEX_RANGE]; staticint inter_minq_8[QINDEX_RANGE]; staticint rtc_minq_8[QINDEX_RANGE];
// How many times less pixels there are to encode given the current scaling. // Temporary replacement for rcf_mult and rate_thresh_mult. staticdouble resize_rate_factor(const FrameDimensionCfg *const frm_dim_cfg, int width, int height) { return (double)(frm_dim_cfg->width * frm_dim_cfg->height) / (width * height);
}
// Functions to compute the active minq lookup table entries based on a // formulaic approach to facilitate easier adjustment of the Q tables. // The formulae were derived from computing a 3rd order polynomial best // fit to the original data (after plotting real maxq vs minq (not q index)) staticint get_minq_index(double maxq, double x3, double x2, double x1,
aom_bit_depth_t bit_depth) { constdouble minqtarget = AOMMIN(((x3 * maxq + x2) * maxq + x1) * maxq, maxq);
// Special case handling to deal with the step from q2.0 // down to lossless mode represented by q 1.0. if (minqtarget <= 2.0) return 0;
// These functions use formulaic calculations to make playing with the // quantizer tables easier. If necessary they can be replaced by lookup // tables if and when things settle down in the experimental bitstream double av1_convert_qindex_to_q(int qindex, aom_bit_depth_t bit_depth) { // Convert the index to a real Q value (scaled down to match old Q values) switch (bit_depth) { case AOM_BITS_8: return av1_ac_quant_QTX(qindex, 0, bit_depth) / 4.0; case AOM_BITS_10: return av1_ac_quant_QTX(qindex, 0, bit_depth) / 16.0; case AOM_BITS_12: return av1_ac_quant_QTX(qindex, 0, bit_depth) / 64.0; default:
assert(0 && "bit_depth should be AOM_BITS_8, AOM_BITS_10 or AOM_BITS_12"); return -1.0;
}
}
int av1_convert_q_to_qindex(double q, aom_bit_depth_t bit_depth) { int qindex = MINQ;
// Find the first qindex that matches or exceeds q. // Note: this operation can also be done with a binary search, as // av1_convert_qindex_to_q() is monotonically increasing with respect to // increasing qindex. while (qindex < MAXQ && av1_convert_qindex_to_q(qindex, bit_depth) < q) {
qindex++;
}
return qindex;
}
// Gets the appropriate bpmb enumerator based on the frame and content type staticint get_bpmb_enumerator(FRAME_TYPE frame_type, constint is_screen_content_type) { int enumerator;
// Adjustment based on spatial content and last encoded keyframe. // Allow for increase in enumerator to reduce overshoot. staticint adjust_rtc_keyframe(const RATE_CONTROL *rc, int enumerator) { // Don't adjust if most of the image is flat. if (rc->perc_spatial_flat_blocks > 70) return enumerator; if (rc->last_encoded_size_keyframe == 0 ||
rc->frames_since_scene_change < rc->frames_since_key) { // Very first frame, or if scene change happened after last keyframe. if (rc->frame_spatial_variance > 1000 ||
(rc->frame_spatial_variance > 500 && rc->perc_spatial_flat_blocks == 0)) return enumerator << 3; elseif (rc->frame_spatial_variance > 500 &&
rc->perc_spatial_flat_blocks < 10) return enumerator << 2; elseif (rc->frame_spatial_variance > 400) return enumerator << 1;
} elseif (rc->frames_since_scene_change >= rc->frames_since_key) { // There was no scene change before previous encoded keyframe, so // use the last_encoded/target_size_keyframe. if (rc->last_encoded_size_keyframe > 4 * rc->last_target_size_keyframe &&
rc->frame_spatial_variance > 500) return enumerator << 3; elseif (rc->last_encoded_size_keyframe >
2 * rc->last_target_size_keyframe &&
rc->frame_spatial_variance > 200) return enumerator << 2; elseif (rc->last_encoded_size_keyframe > rc->last_target_size_keyframe) return enumerator << 1;
} return enumerator;
}
int av1_rc_bits_per_mb(const AV1_COMP *cpi, FRAME_TYPE frame_type, int qindex, double correction_factor, int accurate_estimate) { const AV1_COMMON *const cm = &cpi->common; constint is_screen_content_type = cpi->is_screen_content_type; const aom_bit_depth_t bit_depth = cm->seq_params->bit_depth; constdouble q = av1_convert_qindex_to_q(qindex, bit_depth); int enumerator = get_bpmb_enumerator(frame_type, is_screen_content_type);
int av1_estimate_bits_at_q(const AV1_COMP *cpi, int q, double correction_factor) { const AV1_COMMON *const cm = &cpi->common; const FRAME_TYPE frame_type = cm->current_frame.frame_type; constint mbs = cm->mi_params.MBs; constint bpm =
(int)(av1_rc_bits_per_mb(cpi, frame_type, q, correction_factor,
cpi->sf.hl_sf.accurate_bit_estimate)); return AOMMAX(FRAME_OVERHEAD_BITS,
(int)((uint64_t)bpm * mbs) >> BPER_MB_NORMBITS);
}
staticint clamp_pframe_target_size(const AV1_COMP *const cpi, int64_t target,
FRAME_UPDATE_TYPE frame_update_type) { const RATE_CONTROL *rc = &cpi->rc; const RateControlCfg *const rc_cfg = &cpi->oxcf.rc_cfg; constint min_frame_target =
AOMMAX(rc->min_frame_bandwidth, rc->avg_frame_bandwidth >> 5); // Clip the frame target to the minimum setup value. if (frame_update_type == OVERLAY_UPDATE ||
frame_update_type == INTNL_OVERLAY_UPDATE) { // 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;
} elseif (target < min_frame_target) {
target = min_frame_target;
}
// Clip the frame target to the maximum allowed value. if (target > rc->max_frame_bandwidth) target = rc->max_frame_bandwidth; if (rc_cfg->max_inter_bitrate_pct) { const int64_t max_rate =
(int64_t)rc->avg_frame_bandwidth * rc_cfg->max_inter_bitrate_pct / 100;
target = AOMMIN(target, max_rate);
}
// Update the buffer level for higher temporal layers, given the encoded current // temporal layer. staticvoid update_layer_buffer_level(SVC *svc, int encoded_frame_size, bool is_screen) { constint current_temporal_layer = svc->temporal_layer_id; for (int i = current_temporal_layer + 1; i < svc->number_temporal_layers;
++i) { constint layer =
LAYER_IDS_TO_IDX(svc->spatial_layer_id, i, svc->number_temporal_layers);
LAYER_CONTEXT *lc = &svc->layer_context[layer];
PRIMARY_RATE_CONTROL *lp_rc = &lc->p_rc;
lp_rc->bits_off_target +=
(int)round(lc->target_bandwidth / lc->framerate) - encoded_frame_size; // Clip buffer level to maximum buffer size for the layer.
lp_rc->bits_off_target =
AOMMIN(lp_rc->bits_off_target, lp_rc->maximum_buffer_size);
lp_rc->buffer_level = lp_rc->bits_off_target;
// For screen-content mode: don't let buffer level go below threshold, // given here as -rc->maximum_ buffer_size, to allow buffer to come back // up sooner after slide change with big overshoot. if (is_screen) {
lp_rc->bits_off_target =
AOMMAX(lp_rc->bits_off_target, -lp_rc->maximum_buffer_size);
lp_rc->buffer_level = lp_rc->bits_off_target;
}
}
} // Update the buffer level: leaky bucket model. staticvoid update_buffer_level(AV1_COMP *cpi, int encoded_frame_size) { const AV1_COMMON *const cm = &cpi->common;
RATE_CONTROL *const rc = &cpi->rc;
PRIMARY_RATE_CONTROL *const p_rc = &cpi->ppi->p_rc;
// Non-viewable frames are a special case and are treated as pure overhead. if (!cm->show_frame)
p_rc->bits_off_target -= encoded_frame_size; else
p_rc->bits_off_target += rc->avg_frame_bandwidth - encoded_frame_size;
// Clip the buffer level to the maximum specified buffer size.
p_rc->bits_off_target =
AOMMIN(p_rc->bits_off_target, p_rc->maximum_buffer_size); // For screen-content mode: don't let buffer level go below threshold, // given here as -rc->maximum_ buffer_size, to allow buffer to come back // up sooner after slide change with big overshoot. if (cpi->oxcf.tune_cfg.content == AOM_CONTENT_SCREEN)
p_rc->bits_off_target =
AOMMAX(p_rc->bits_off_target, -p_rc->maximum_buffer_size);
p_rc->buffer_level = p_rc->bits_off_target;
if (cpi->ppi->use_svc)
update_layer_buffer_level(&cpi->svc, encoded_frame_size,
cpi->oxcf.tune_cfg.content == AOM_CONTENT_SCREEN);
#if CONFIG_FPMT_TEST /* The variable temp_buffer_level is introduced for quality * simulation purpose, it retains the value previous to the parallel * encode frames. The variable is updated based on the update flag. * * If there exist show_existing_frames between parallel frames, then to
* retain the temp state do not update it. */ int show_existing_between_parallel_frames =
(cpi->ppi->gf_group.update_type[cpi->gf_frame_index] ==
INTNL_OVERLAY_UPDATE &&
cpi->ppi->gf_group.frame_parallel_level[cpi->gf_frame_index + 1] == 2);
// Note get_default_max_gf_interval() requires the min_gf_interval to // be passed in to ensure that the max_gf_interval returned is at least as big // as that. staticint get_default_max_gf_interval(double framerate, int min_gf_interval) { int interval = AOMMIN(MAX_GF_INTERVAL, (int)(framerate * 0.75));
interval += (interval & 0x01); // Round to even value
interval = AOMMAX(MAX_GF_INTERVAL, interval); return AOMMAX(interval, min_gf_interval);
}
staticbool check_buffer_below_thresh(AV1_COMP *cpi, int64_t buffer_level, int drop_mark) {
SVC *svc = &cpi->svc; if (!cpi->ppi->use_svc || cpi->svc.number_spatial_layers == 1 ||
cpi->svc.framedrop_mode == AOM_LAYER_DROP) { return (buffer_level <= drop_mark);
} else { // For SVC in the AOM_FULL_SUPERFRAME_DROP): the condition on // buffer is checked on current and upper spatial layers. for (int i = svc->spatial_layer_id; i < svc->number_spatial_layers; ++i) { constint layer = LAYER_IDS_TO_IDX(i, svc->temporal_layer_id,
svc->number_temporal_layers);
LAYER_CONTEXT *lc = &svc->layer_context[layer];
PRIMARY_RATE_CONTROL *lrc = &lc->p_rc; // Exclude check for layer whose bitrate is 0. if (lc->target_bandwidth > 0) { constint drop_thresh = cpi->oxcf.rc_cfg.drop_frames_water_mark; constint drop_mark_layer =
(int)(drop_thresh * lrc->optimal_buffer_level / 100); if (lrc->buffer_level <= drop_mark_layer) returntrue;
}
} returnfalse;
}
}
int av1_rc_drop_frame(AV1_COMP *cpi) { const AV1EncoderConfig *oxcf = &cpi->oxcf;
RATE_CONTROL *const rc = &cpi->rc;
PRIMARY_RATE_CONTROL *const p_rc = &cpi->ppi->p_rc; #if CONFIG_FPMT_TEST constint simulate_parallel_frame =
cpi->ppi->gf_group.frame_parallel_level[cpi->gf_frame_index] > 0 &&
cpi->ppi->fpmt_unit_test_cfg == PARALLEL_SIMULATION_ENCODE;
int64_t buffer_level =
simulate_parallel_frame ? p_rc->temp_buffer_level : p_rc->buffer_level; #else
int64_t buffer_level = p_rc->buffer_level; #endif // Never drop on key frame, or for frame whose base layer is key. // If drop_count_consec hits or exceeds max_consec_drop then don't drop. if (cpi->common.current_frame.frame_type == KEY_FRAME ||
(cpi->ppi->use_svc &&
cpi->svc.layer_context[cpi->svc.temporal_layer_id].is_key_frame) ||
!oxcf->rc_cfg.drop_frames_water_mark ||
(rc->max_consec_drop > 0 &&
rc->drop_count_consec >= rc->max_consec_drop)) { return 0;
} else {
SVC *svc = &cpi->svc; // In the full_superframe framedrop mode for svc, if the previous spatial // layer was dropped, drop the current spatial layer. if (cpi->ppi->use_svc && svc->spatial_layer_id > 0 &&
svc->drop_spatial_layer[svc->spatial_layer_id - 1] &&
svc->framedrop_mode == AOM_FULL_SUPERFRAME_DROP) return 1; // -1 is passed here for drop_mark since we are checking if // buffer goes below 0 (<= -1). if (check_buffer_below_thresh(cpi, buffer_level, -1)) { // Always drop if buffer is below 0.
rc->drop_count_consec++; return 1;
} else { // If buffer is below drop_mark, for now just drop every other frame // (starting with the next frame) until it increases back over drop_mark. constint drop_mark = (int)(oxcf->rc_cfg.drop_frames_water_mark *
p_rc->optimal_buffer_level / 100); constbool buffer_below_thresh =
check_buffer_below_thresh(cpi, buffer_level, drop_mark); if (!buffer_below_thresh && rc->decimation_factor > 0) {
--rc->decimation_factor;
} elseif (buffer_below_thresh && rc->decimation_factor == 0) {
rc->decimation_factor = 1;
} if (rc->decimation_factor > 0) { if (rc->decimation_count > 0) {
--rc->decimation_count;
rc->drop_count_consec++; return 1;
} else {
rc->decimation_count = rc->decimation_factor; return 0;
}
} else {
rc->decimation_count = 0; return 0;
}
}
}
}
staticint adjust_q_cbr(const AV1_COMP *cpi, int q, int active_worst_quality, int width, int height) { const RATE_CONTROL *const rc = &cpi->rc; const PRIMARY_RATE_CONTROL *const p_rc = &cpi->ppi->p_rc; const AV1_COMMON *const cm = &cpi->common; const SVC *const svc = &cpi->svc; const RefreshFrameInfo *const refresh_frame = &cpi->refresh_frame; // Flag to indicate previous frame has overshoot, and buffer level // for current frame is low (less than ~half of optimal). For such // (inter) frames, if the source_sad is non-zero, relax the max_delta_up // and clamp applied below. constbool overshoot_buffer_low =
cpi->rc.rc_1_frame == -1 && rc->frame_source_sad > 1000 &&
p_rc->buffer_level < (p_rc->optimal_buffer_level >> 1) &&
rc->frames_since_key > 4; int max_delta_down; int max_delta_up = overshoot_buffer_low ? 120 : 20; constint change_avg_frame_bandwidth =
abs(rc->avg_frame_bandwidth - rc->prev_avg_frame_bandwidth) >
0.1 * (rc->avg_frame_bandwidth);
// Set the maximum adjustment down for Q for this frame. if (cpi->oxcf.q_cfg.aq_mode == CYCLIC_REFRESH_AQ &&
cpi->cyclic_refresh->apply_cyclic_refresh) { // For static screen type content limit the Q drop till the start of the // next refresh cycle. if (cpi->is_screen_content_type &&
(cpi->cyclic_refresh->sb_index > cpi->cyclic_refresh->last_sb_index)) {
max_delta_down = AOMMIN(8, AOMMAX(1, rc->q_1_frame / 32));
} else {
max_delta_down = AOMMIN(16, AOMMAX(1, rc->q_1_frame / 8));
} if (!cpi->ppi->use_svc && cpi->is_screen_content_type) { // Link max_delta_up to max_delta_down and buffer status. if (p_rc->buffer_level > p_rc->optimal_buffer_level) {
max_delta_up = AOMMAX(4, max_delta_down);
} elseif (!overshoot_buffer_low) {
max_delta_up = AOMMAX(8, max_delta_down);
}
}
} else {
max_delta_down = (cpi->is_screen_content_type)
? AOMMIN(8, AOMMAX(1, rc->q_1_frame / 16))
: AOMMIN(16, AOMMAX(1, rc->q_1_frame / 8));
} // For screen static content with stable buffer level: relax the // limit on max_delta_down and apply bias qp, based on buffer fullness. // Only for high speeds levels for now to avoid bdrate regression. if (cpi->sf.rt_sf.rc_faster_convergence_static == 1 &&
cpi->sf.rt_sf.check_scene_detection && rc->frame_source_sad == 0 &&
rc->static_since_last_scene_change &&
p_rc->buffer_level > (p_rc->optimal_buffer_level >> 1) &&
cpi->oxcf.q_cfg.aq_mode == CYCLIC_REFRESH_AQ &&
cpi->cyclic_refresh->counter_encode_maxq_scene_change > 4) { int qp_delta = 32; int qp_bias = 16; if (p_rc->buffer_level > p_rc->optimal_buffer_level) {
qp_delta = 60;
qp_bias = 32;
} if (cpi->rc.rc_1_frame == 1) q = q - qp_bias;
max_delta_down = AOMMAX(max_delta_down, qp_delta);
max_delta_up = AOMMIN(max_delta_up, 4);
}
// If resolution changes or avg_frame_bandwidth significantly changed, // then set this flag to indicate change in target bits per macroblock. constint change_target_bits_mb =
cm->prev_frame &&
(width != cm->prev_frame->width || height != cm->prev_frame->height ||
change_avg_frame_bandwidth); // Apply some control/clamp to QP under certain conditions. // Delay the use of the clamping for svc until after num_temporal_layers, // to make they have been set for each temporal layer. // Check for rc->q_1/2_frame > 0 in case they have not been set due to // dropped frames. if (!frame_is_intra_only(cm) && rc->frames_since_key > 1 &&
rc->q_1_frame > 0 && rc->q_2_frame > 0 &&
(!cpi->ppi->use_svc ||
svc->current_superframe > (unsignedint)svc->number_temporal_layers) &&
!change_target_bits_mb && !cpi->rc.rtc_external_ratectrl &&
(!cpi->oxcf.rc_cfg.gf_cbr_boost_pct ||
!(refresh_frame->alt_ref_frame || refresh_frame->golden_frame))) { // If in the previous two frames we have seen both overshoot and undershoot // clamp Q between the two. if (rc->rc_1_frame * rc->rc_2_frame == -1 &&
rc->q_1_frame != rc->q_2_frame && !overshoot_buffer_low) { int qclamp = clamp(q, AOMMIN(rc->q_1_frame, rc->q_2_frame),
AOMMAX(rc->q_1_frame, rc->q_2_frame)); // If the previous frame had overshoot and the current q needs to // increase above the clamped value, reduce the clamp for faster reaction // to overshoot. if (cpi->rc.rc_1_frame == -1 && q > qclamp && rc->frames_since_key > 10)
q = (q + qclamp) >> 1; else
q = qclamp;
} // Adjust Q base on source content change from scene detection. if (cpi->sf.rt_sf.check_scene_detection && rc->prev_avg_source_sad > 0 &&
rc->frames_since_key > 10 && rc->frame_source_sad > 0 &&
!cpi->rc.rtc_external_ratectrl) { constint bit_depth = cm->seq_params->bit_depth; double delta =
(double)rc->avg_source_sad / (double)rc->prev_avg_source_sad - 1.0; // Push Q downwards if content change is decreasing and buffer level // is stable (at least 1/4-optimal level), so not overshooting. Do so // only for high Q to avoid excess overshoot. // Else reduce decrease in Q from previous frame if content change is // increasing and buffer is below max (so not undershooting). if (delta < 0.0 &&
p_rc->buffer_level > (p_rc->optimal_buffer_level >> 2) &&
q > (rc->worst_quality >> 1)) { double q_adj_factor = 1.0 + 0.5 * tanh(4.0 * delta); double q_val = av1_convert_qindex_to_q(q, bit_depth);
q += av1_compute_qdelta(rc, q_val, q_val * q_adj_factor, bit_depth);
} elseif (rc->q_1_frame - q > 0 && delta > 0.1 &&
p_rc->buffer_level < AOMMIN(p_rc->maximum_buffer_size,
p_rc->optimal_buffer_level << 1)) {
q = (3 * q + rc->q_1_frame) >> 2;
}
} // Limit the decrease in Q from previous frame. if (rc->q_1_frame - q > max_delta_down) q = rc->q_1_frame - max_delta_down; // Limit the increase in Q from previous frame. elseif (q - rc->q_1_frame > max_delta_up)
q = rc->q_1_frame + max_delta_up;
} // Adjustment for temporal layers. if (svc->number_temporal_layers > 1 && svc->spatial_layer_id == 0 &&
!change_target_bits_mb && !cpi->rc.rtc_external_ratectrl &&
cpi->oxcf.resize_cfg.resize_mode != RESIZE_DYNAMIC) { if (svc->temporal_layer_id > 0) { // Constrain enhancement relative to the previous base TL0. // Get base temporal layer TL0. constint layer = LAYER_IDS_TO_IDX(0, 0, svc->number_temporal_layers);
LAYER_CONTEXT *lc = &svc->layer_context[layer]; // lc->rc.avg_frame_bandwidth and lc->p_rc.last_q correspond to the // last TL0 frame. constint last_qindex_tl0 =
rc->frames_since_key < svc->number_temporal_layers
? lc->p_rc.last_q[KEY_FRAME]
: lc->p_rc.last_q[INTER_FRAME]; if (rc->avg_frame_bandwidth < lc->rc.avg_frame_bandwidth &&
q < last_qindex_tl0 - 4)
q = last_qindex_tl0 - 4;
} elseif (cpi->svc.temporal_layer_id == 0 && !frame_is_intra_only(cm) &&
p_rc->buffer_level > (p_rc->optimal_buffer_level >> 2) &&
rc->frame_source_sad < 100000) { // Push base TL0 Q down if buffer is stable and frame_source_sad // is below threshold. int delta = (svc->number_temporal_layers == 2) ? 4 : 10;
q = q - delta;
}
} // For non-svc (single layer): if resolution has increased push q closer // to the active_worst to avoid excess overshoot. if (!cpi->ppi->use_svc && cm->prev_frame &&
(width * height > 1.5 * cm->prev_frame->width * cm->prev_frame->height))
q = (q + active_worst_quality) >> 1; // For single layer RPS: Bias Q based on distance of closest reference. if (cpi->ppi->rtc_ref.bias_recovery_frame) { constint min_dist = av1_svc_get_min_ref_dist(cpi);
q = q - AOMMIN(min_dist, 20);
} return AOMMAX(AOMMIN(q, cpi->rc.worst_quality), cpi->rc.best_quality);
}
/*!\brief Gets a rate vs Q correction factor * * This function returns the current value of a correction factor used to * dynamically adjust the relationship between Q and the expected number * of bits for the frame. * * \ingroup rate_control * \param[in] cpi Top level encoder instance structure * \param[in] width Frame width * \param[in] height Frame height * * \return Returns a correction factor for the current frame
*/ staticdouble get_rate_correction_factor(const AV1_COMP *cpi, int width, int height) { const RATE_CONTROL *const rc = &cpi->rc; const PRIMARY_RATE_CONTROL *const p_rc = &cpi->ppi->p_rc; const RefreshFrameInfo *const refresh_frame = &cpi->refresh_frame; double rcf; double rate_correction_factors_kfstd; double rate_correction_factors_gfarfstd; double rate_correction_factors_internormal;
/*!\brief Sets a rate vs Q correction factor * * This function updates the current value of a correction factor used to * dynamically adjust the relationship between Q and the expected number * of bits for the frame. * * \ingroup rate_control * \param[in] cpi Top level encoder instance structure * \param[in] is_encode_stage Indicates if recode loop or post-encode * \param[in] factor New correction factor * \param[in] width Frame width * \param[in] height Frame height * * \remark Updates the rate correction factor for the * current frame type in cpi->rc.
*/ staticvoid set_rate_correction_factor(AV1_COMP *cpi, int is_encode_stage, double factor, int width, int height) {
RATE_CONTROL *const rc = &cpi->rc;
PRIMARY_RATE_CONTROL *const p_rc = &cpi->ppi->p_rc; const RefreshFrameInfo *const refresh_frame = &cpi->refresh_frame; int update_default_rcf = 1; // Normalize RCF to account for the size-dependent scaling factor.
factor /= resize_rate_factor(&cpi->oxcf.frm_dim_cfg, width, height);
void av1_rc_update_rate_correction_factors(AV1_COMP *cpi, int is_encode_stage, int width, int height) { const AV1_COMMON *const cm = &cpi->common; double correction_factor = 1.0; double rate_correction_factor =
get_rate_correction_factor(cpi, width, height); double adjustment_limit; int projected_size_based_on_q = 0; int cyclic_refresh_active =
cpi->oxcf.q_cfg.aq_mode == CYCLIC_REFRESH_AQ && cpi->common.seg.enabled;
// Do not update the rate factors for arf overlay frames. if (cpi->rc.is_src_frame_alt_ref) return;
// Don't update rate correction factors here on scene changes as // it is already reset in av1_encodedframe_overshoot_cbr(), // but reset variables related to previous frame q and size. // Note that the counter of frames since the last scene change // is only valid when cyclic refresh mode is enabled and that // this break out only applies to scene changes that are not // recorded as INTRA only key frames. // Note that av1_encodedframe_overshoot_cbr() is only entered // if cpi->sf.rt_sf.overshoot_detection_cbr == FAST_DETECTION_MAXQ // and cpi->rc.high_source_sad = 1. if ((cpi->oxcf.q_cfg.aq_mode == CYCLIC_REFRESH_AQ) &&
(cpi->sf.rt_sf.overshoot_detection_cbr == FAST_DETECTION_MAXQ) &&
cpi->rc.high_source_sad &&
(cpi->cyclic_refresh->counter_encode_maxq_scene_change == 0) &&
!frame_is_intra_only(cm) && !cpi->ppi->use_svc) {
cpi->rc.q_2_frame = cm->quant_params.base_qindex;
cpi->rc.q_1_frame = cm->quant_params.base_qindex;
cpi->rc.rc_2_frame = 0;
cpi->rc.rc_1_frame = 0; return;
}
// Clear down mmx registers to allow floating point in what follows
// Work out how big we would have expected the frame to be at this Q given // the current correction factor. // Stay in double to avoid int overflow when values are large if (cyclic_refresh_active) {
projected_size_based_on_q =
av1_cyclic_refresh_estimate_bits_at_q(cpi, rate_correction_factor);
} else {
projected_size_based_on_q = av1_estimate_bits_at_q(
cpi, cm->quant_params.base_qindex, rate_correction_factor);
} // Work out a size correction factor. if (projected_size_based_on_q > FRAME_OVERHEAD_BITS)
correction_factor = (double)cpi->rc.projected_frame_size /
(double)projected_size_based_on_q;
// Clamp correction factor to prevent anything too extreme
correction_factor = AOMMAX(correction_factor, 0.25);
// Decide how heavily to dampen the adjustment if (correction_factor > 0.0) { if (cpi->is_screen_content_type) {
adjustment_limit =
0.25 + 0.5 * AOMMIN(0.5, fabs(log10(correction_factor)));
} else {
adjustment_limit =
0.25 + 0.75 * AOMMIN(0.5, fabs(log10(correction_factor)));
}
} else {
adjustment_limit = 0.75;
}
// Adjustment to delta Q and number of blocks updated in cyclic refresh // based on over or under shoot of target in current frame. if (cyclic_refresh_active && cpi->rc.this_frame_target > 0) {
CYCLIC_REFRESH *const cr = cpi->cyclic_refresh; if (correction_factor > 1.25) {
cr->percent_refresh_adjustment =
AOMMAX(cr->percent_refresh_adjustment - 1, -5);
cr->rate_ratio_qdelta_adjustment =
AOMMAX(cr->rate_ratio_qdelta_adjustment - 0.05, -0.0);
} elseif (correction_factor < 0.5) {
cr->percent_refresh_adjustment =
AOMMIN(cr->percent_refresh_adjustment + 1, 5);
cr->rate_ratio_qdelta_adjustment =
AOMMIN(cr->rate_ratio_qdelta_adjustment + 0.05, 0.25);
}
}
if (correction_factor > 1.01) { // We are not already at the worst allowable quality
correction_factor = (1.0 + ((correction_factor - 1.0) * adjustment_limit));
rate_correction_factor = rate_correction_factor * correction_factor; // Keep rate_correction_factor within limits if (rate_correction_factor > MAX_BPB_FACTOR)
rate_correction_factor = MAX_BPB_FACTOR;
} elseif (correction_factor < 0.99) { // We are not already at the best allowable quality
correction_factor = 1.0 / correction_factor;
correction_factor = (1.0 + ((correction_factor - 1.0) * adjustment_limit));
correction_factor = 1.0 / correction_factor;
// Calculate rate for the given 'q'. staticint get_bits_per_mb(const AV1_COMP *cpi, int use_cyclic_refresh, double correction_factor, int q) { const AV1_COMMON *const cm = &cpi->common; return use_cyclic_refresh
? av1_cyclic_refresh_rc_bits_per_mb(cpi, q, correction_factor)
: av1_rc_bits_per_mb(cpi, cm->current_frame.frame_type, q,
correction_factor,
cpi->sf.hl_sf.accurate_bit_estimate);
}
/*!\brief Searches for a Q index value predicted to give an average macro * block rate closest to the target value. * * Similar to find_qindex_by_rate() function, but returns a q index with a * rate just above or below the desired rate, depending on which of the two * rates is closer to the desired rate. * Also, respects the selected aq_mode when computing the rate. * * \ingroup rate_control * \param[in] desired_bits_per_mb Target bits per mb * \param[in] cpi Top level encoder instance structure * \param[in] correction_factor Current Q to rate correction factor * \param[in] best_qindex Min allowed Q value. * \param[in] worst_qindex Max allowed Q value. * * \return Returns a correction factor for the current frame
*/ staticint find_closest_qindex_by_rate(int desired_bits_per_mb, const AV1_COMP *cpi, double correction_factor, int best_qindex, int worst_qindex) { constint use_cyclic_refresh = cpi->oxcf.q_cfg.aq_mode == CYCLIC_REFRESH_AQ &&
cpi->cyclic_refresh->apply_cyclic_refresh;
// Find 'qindex' based on 'desired_bits_per_mb'.
assert(best_qindex <= worst_qindex); int low = best_qindex; int high = worst_qindex; while (low < high) { constint mid = (low + high) >> 1; constint mid_bits_per_mb =
get_bits_per_mb(cpi, use_cyclic_refresh, correction_factor, mid); if (mid_bits_per_mb > desired_bits_per_mb) {
low = mid + 1;
} else {
high = mid;
}
}
assert(low == high);
// Calculate rate difference of this q index from the desired rate. constint curr_q = low; constint curr_bits_per_mb =
get_bits_per_mb(cpi, use_cyclic_refresh, correction_factor, curr_q); constint curr_bit_diff = (curr_bits_per_mb <= desired_bits_per_mb)
? desired_bits_per_mb - curr_bits_per_mb
: INT_MAX;
assert((curr_bit_diff != INT_MAX && curr_bit_diff >= 0) ||
curr_q == worst_qindex);
// Pick one of the two q indices, depending on which one has rate closer to // the desired rate. return (curr_bit_diff <= prev_bit_diff) ? curr_q : prev_q;
}
int av1_rc_regulate_q(const AV1_COMP *cpi, int target_bits_per_frame, int active_best_quality, int active_worst_quality, int width, int height) { constint MBs = av1_get_MBs(width, height); constdouble correction_factor =
get_rate_correction_factor(cpi, width, height); constint target_bits_per_mb =
(int)(((uint64_t)target_bits_per_frame << BPER_MB_NORMBITS) / MBs);
int q =
find_closest_qindex_by_rate(target_bits_per_mb, cpi, correction_factor,
active_best_quality, active_worst_quality); if (cpi->oxcf.rc_cfg.mode == AOM_CBR && has_no_stats_stage(cpi)) return adjust_q_cbr(cpi, q, active_worst_quality, width, height);
return q;
}
staticint get_active_quality(int q, int gfu_boost, int low, int high, int *low_motion_minq, int *high_motion_minq) { if (gfu_boost > high) { return low_motion_minq[q];
} elseif (gfu_boost < low) { return high_motion_minq[q];
} else { constint gap = high - low; constint offset = high - gfu_boost; constint qdiff = high_motion_minq[q] - low_motion_minq[q]; constint adjustment = ((offset * qdiff) + (gap >> 1)) / gap; return low_motion_minq[q] + adjustment;
}
}
staticint get_kf_active_quality(const PRIMARY_RATE_CONTROL *const p_rc, int q,
aom_bit_depth_t bit_depth) { int *kf_low_motion_minq; int *kf_high_motion_minq;
ASSIGN_MINQ_TABLE(bit_depth, kf_low_motion_minq);
ASSIGN_MINQ_TABLE(bit_depth, kf_high_motion_minq); return get_active_quality(q, p_rc->kf_boost, kf_low, kf_high,
kf_low_motion_minq, kf_high_motion_minq);
}
staticint get_gf_active_quality_no_rc(int gfu_boost, int q,
aom_bit_depth_t bit_depth) { int *arfgf_low_motion_minq; int *arfgf_high_motion_minq;
ASSIGN_MINQ_TABLE(bit_depth, arfgf_low_motion_minq);
ASSIGN_MINQ_TABLE(bit_depth, arfgf_high_motion_minq); return get_active_quality(q, gfu_boost, gf_low, gf_high,
arfgf_low_motion_minq, arfgf_high_motion_minq);
}
staticint get_gf_active_quality(const PRIMARY_RATE_CONTROL *const p_rc, int q,
aom_bit_depth_t bit_depth) { return get_gf_active_quality_no_rc(p_rc->gfu_boost, q, bit_depth);
}
staticint get_gf_high_motion_quality(int q, aom_bit_depth_t bit_depth) { int *arfgf_high_motion_minq;
ASSIGN_MINQ_TABLE(bit_depth, arfgf_high_motion_minq); return arfgf_high_motion_minq[q];
}
// Adjust active_worst_quality level based on buffer level. staticint calc_active_worst_quality_no_stats_cbr(const AV1_COMP *cpi) { // Adjust active_worst_quality: If buffer is above the optimal/target level, // bring active_worst_quality down depending on fullness of buffer. // If buffer is below the optimal level, let the active_worst_quality go from // ambient Q (at buffer = optimal level) to worst_quality level // (at buffer = critical level). const AV1_COMMON *const cm = &cpi->common; const RATE_CONTROL *rc = &cpi->rc; const PRIMARY_RATE_CONTROL *p_rc = &cpi->ppi->p_rc; const SVC *const svc = &cpi->svc; unsignedint num_frames_weight_key = 5 * cpi->svc.number_temporal_layers; // Buffer level below which we push active_worst to worst_quality.
int64_t critical_level = p_rc->optimal_buffer_level >> 3;
int64_t buff_lvl_step = 0; int adjustment = 0; int active_worst_quality; int ambient_qp; if (frame_is_intra_only(cm)) return rc->worst_quality; // For ambient_qp we use minimum of avg_frame_qindex[KEY_FRAME/INTER_FRAME] // for the first few frames following key frame. These are both initialized // to worst_quality and updated with (3/4, 1/4) average in postencode_update. // So for first few frames following key, the qp of that key frame is weighted // into the active_worst_quality setting. For SVC the key frame should // correspond to layer (0, 0), so use that for layer context. int avg_qindex_key = p_rc->avg_frame_qindex[KEY_FRAME]; if (svc->number_temporal_layers > 1) { int layer = LAYER_IDS_TO_IDX(0, 0, svc->number_temporal_layers); const LAYER_CONTEXT *lc = &svc->layer_context[layer]; const PRIMARY_RATE_CONTROL *const lp_rc = &lc->p_rc;
avg_qindex_key =
AOMMIN(lp_rc->avg_frame_qindex[KEY_FRAME], lp_rc->last_q[KEY_FRAME]);
} if (svc->temporal_layer_id > 0 &&
rc->frames_since_key < 2 * svc->number_temporal_layers) {
ambient_qp = avg_qindex_key;
} else {
ambient_qp =
(cm->current_frame.frame_number < num_frames_weight_key)
? AOMMIN(p_rc->avg_frame_qindex[INTER_FRAME], avg_qindex_key)
: p_rc->avg_frame_qindex[INTER_FRAME];
}
ambient_qp = AOMMIN(rc->worst_quality, ambient_qp);
if (p_rc->buffer_level > p_rc->optimal_buffer_level) { // Adjust down. int max_adjustment_down; // Maximum adjustment down for Q
if (max_adjustment_down) {
buff_lvl_step =
((p_rc->maximum_buffer_size - p_rc->optimal_buffer_level) /
max_adjustment_down); if (buff_lvl_step)
adjustment = (int)((p_rc->buffer_level - p_rc->optimal_buffer_level) /
buff_lvl_step);
active_worst_quality -= adjustment;
}
} elseif (p_rc->buffer_level > critical_level) { // Adjust up from ambient Q.
active_worst_quality = AOMMIN(rc->worst_quality, ambient_qp); if (critical_level) {
buff_lvl_step = (p_rc->optimal_buffer_level - critical_level); if (buff_lvl_step) {
adjustment = (int)((rc->worst_quality - ambient_qp) *
(p_rc->optimal_buffer_level - p_rc->buffer_level) /
buff_lvl_step);
}
active_worst_quality += adjustment;
}
} else { // Set to worst_quality if buffer is below critical level.
active_worst_quality = rc->worst_quality;
} return active_worst_quality;
}
// Calculate the active_best_quality level. staticint calc_active_best_quality_no_stats_cbr(const AV1_COMP *cpi, int active_worst_quality, int width, int height) { const AV1_COMMON *const cm = &cpi->common; const RATE_CONTROL *const rc = &cpi->rc; const PRIMARY_RATE_CONTROL *const p_rc = &cpi->ppi->p_rc; const RefreshFrameInfo *const refresh_frame = &cpi->refresh_frame; const CurrentFrame *const current_frame = &cm->current_frame; int *rtc_minq; constint bit_depth = cm->seq_params->bit_depth; int active_best_quality = rc->best_quality;
ASSIGN_MINQ_TABLE(bit_depth, rtc_minq);
if (frame_is_intra_only(cm)) { // Handle the special case for key frames forced when we have reached // the maximum key frame interval. Here force the Q to a range // based on the ambient Q to reduce the risk of popping. if (p_rc->this_key_frame_forced) { int qindex = p_rc->last_boosted_qindex; double last_boosted_q = av1_convert_qindex_to_q(qindex, bit_depth); int delta_qindex = av1_compute_qdelta(rc, last_boosted_q,
(last_boosted_q * 0.75), bit_depth);
active_best_quality = AOMMAX(qindex + delta_qindex, rc->best_quality);
} elseif (current_frame->frame_number > 0) { // not first frame of one pass and kf_boost is set double q_adj_factor = 1.0; double q_val;
active_best_quality = get_kf_active_quality(
p_rc, p_rc->avg_frame_qindex[KEY_FRAME], bit_depth); // Allow somewhat lower kf minq with small image formats. if ((width * height) <= (352 * 288)) {
q_adj_factor -= 0.25;
} // Convert the adjustment factor to a qindex delta // on active_best_quality.
q_val = av1_convert_qindex_to_q(active_best_quality, bit_depth);
active_best_quality +=
av1_compute_qdelta(rc, q_val, q_val * q_adj_factor, bit_depth);
}
} elseif (!rc->is_src_frame_alt_ref && !cpi->ppi->use_svc &&
cpi->oxcf.rc_cfg.gf_cbr_boost_pct &&
(refresh_frame->golden_frame || refresh_frame->alt_ref_frame)) { // Use the lower of active_worst_quality and recent // average Q as basis for GF/ARF best Q limit unless last frame was // a key frame. int q = active_worst_quality; if (rc->frames_since_key > 1 &&
p_rc->avg_frame_qindex[INTER_FRAME] < active_worst_quality) {
q = p_rc->avg_frame_qindex[INTER_FRAME];
}
active_best_quality = get_gf_active_quality(p_rc, q, bit_depth);
} else { // Use the lower of active_worst_quality and recent/average Q.
FRAME_TYPE frame_type =
(current_frame->frame_number > 1) ? INTER_FRAME : KEY_FRAME; if (p_rc->avg_frame_qindex[frame_type] < active_worst_quality)
active_best_quality = rtc_minq[p_rc->avg_frame_qindex[frame_type]]; else
active_best_quality = rtc_minq[active_worst_quality];
} return active_best_quality;
}
#if RT_PASSIVE_STRATEGY staticint get_q_passive_strategy(const AV1_COMP *const cpi, constint q_candidate, constint threshold) { const AV1_COMMON *const cm = &cpi->common; const PRIMARY_RATE_CONTROL *const p_rc = &cpi->ppi->p_rc; const CurrentFrame *const current_frame = &cm->current_frame; int sum = 0; int count = 0; int i = 1; while (i < MAX_Q_HISTORY) { int frame_id = current_frame->frame_number - i; if (frame_id <= 0) break;
sum += p_rc->q_history[frame_id % MAX_Q_HISTORY];
++count;
++i;
} if (count > 0) { constint avg_q = sum / count; if (abs(avg_q - q_candidate) <= threshold) return avg_q;
} return q_candidate;
} #endif// RT_PASSIVE_STRATEGY
/*!\brief Picks q and q bounds given CBR rate control parameters in \c cpi->rc. * * Handles the special case when using: * - Constant bit-rate mode: \c cpi->oxcf.rc_cfg.mode == \ref AOM_CBR, and * - 1-pass encoding without LAP (look-ahead processing), so 1st pass stats are * NOT available. * * \ingroup rate_control * \param[in] cpi Top level encoder structure * \param[in] width Coded frame width * \param[in] height Coded frame height * \param[out] bottom_index Bottom bound for q index (best quality) * \param[out] top_index Top bound for q index (worst quality) * \return Returns selected q index to be used for encoding this frame.
*/ staticint rc_pick_q_and_bounds_no_stats_cbr(const AV1_COMP *cpi, int width, int height, int *bottom_index, int *top_index) { const AV1_COMMON *const cm = &cpi->common; const RATE_CONTROL *const rc = &cpi->rc; const PRIMARY_RATE_CONTROL *const p_rc = &cpi->ppi->p_rc; const CurrentFrame *const current_frame = &cm->current_frame; int q; int active_worst_quality = calc_active_worst_quality_no_stats_cbr(cpi); int active_best_quality = calc_active_best_quality_no_stats_cbr(
cpi, active_worst_quality, width, height);
assert(has_no_stats_stage(cpi));
assert(cpi->oxcf.rc_cfg.mode == AOM_CBR);
// Clip the active best and worst quality values to limits
active_best_quality =
clamp(active_best_quality, rc->best_quality, rc->worst_quality);
active_worst_quality =
clamp(active_worst_quality, active_best_quality, rc->worst_quality);
// Limit Q range for the adaptive loop. if (current_frame->frame_type == KEY_FRAME && !p_rc->this_key_frame_forced &&
current_frame->frame_number != 0) { int qdelta = 0;
qdelta = av1_compute_qdelta_by_rate(cpi, current_frame->frame_type,
active_worst_quality, 2.0);
*top_index = active_worst_quality + qdelta;
*top_index = AOMMAX(*top_index, *bottom_index);
}
q = av1_rc_regulate_q(cpi, rc->this_frame_target, active_best_quality,
active_worst_quality, width, height); #if RT_PASSIVE_STRATEGY if (current_frame->frame_type != KEY_FRAME &&
cpi->oxcf.tune_cfg.content == AOM_CONTENT_SCREEN) {
q = get_q_passive_strategy(cpi, q, 50);
} #endif// RT_PASSIVE_STRATEGY if (q > *top_index) { // Special case when we are targeting the max allowed rate if (rc->this_frame_target >= rc->max_frame_bandwidth)
*top_index = q; else
q = *top_index;
}
staticint gf_group_pyramid_level(const GF_GROUP *gf_group, int gf_index) { return gf_group->layer_depth[gf_index];
}
staticint get_active_cq_level(const RATE_CONTROL *rc, const PRIMARY_RATE_CONTROL *p_rc, const AV1EncoderConfig *const oxcf, int intra_only, aom_superres_mode superres_mode, int superres_denom) { const RateControlCfg *const rc_cfg = &oxcf->rc_cfg; staticconstdouble cq_adjust_threshold = 0.1; int active_cq_level = rc_cfg->cq_level; if (rc_cfg->mode == AOM_CQ || rc_cfg->mode == AOM_Q) { // printf("Superres %d %d %d = %d\n", superres_denom, intra_only, // rc->frames_to_key, !(intra_only && rc->frames_to_key <= 1)); if ((superres_mode == AOM_SUPERRES_QTHRESH ||
superres_mode == AOM_SUPERRES_AUTO) &&
superres_denom != SCALE_NUMERATOR) { int mult = SUPERRES_QADJ_PER_DENOM_KEYFRAME_SOLO; if (intra_only && rc->frames_to_key <= 1) {
mult = 0;
} elseif (intra_only) {
mult = SUPERRES_QADJ_PER_DENOM_KEYFRAME;
} else {
mult = SUPERRES_QADJ_PER_DENOM_ARFFRAME;
}
active_cq_level = AOMMAX(
active_cq_level - ((superres_denom - SCALE_NUMERATOR) * mult), 0);
}
} if (rc_cfg->mode == AOM_CQ && p_rc->total_target_bits > 0) { constdouble x = (double)p_rc->total_actual_bits / p_rc->total_target_bits; if (x < cq_adjust_threshold) {
active_cq_level = (int)(active_cq_level * x / cq_adjust_threshold);
}
} return active_cq_level;
}
/*!\brief Picks q and q bounds given non-CBR rate control params in \c cpi->rc. * * Handles the special case when using: * - Any rate control other than constant bit-rate mode: * \c cpi->oxcf.rc_cfg.mode != \ref AOM_CBR, and * - 1-pass encoding without LAP (look-ahead processing), so 1st pass stats are * NOT available. * * \ingroup rate_control * \param[in] cpi Top level encoder structure * \param[in] width Coded frame width * \param[in] height Coded frame height * \param[out] bottom_index Bottom bound for q index (best quality) * \param[out] top_index Top bound for q index (worst quality) * \return Returns selected q index to be used for encoding this frame.
*/ staticint rc_pick_q_and_bounds_no_stats(const AV1_COMP *cpi, int width, int height, int *bottom_index, int *top_index) { const AV1_COMMON *const cm = &cpi->common; const RATE_CONTROL *const rc = &cpi->rc; const PRIMARY_RATE_CONTROL *const p_rc = &cpi->ppi->p_rc; const CurrentFrame *const current_frame = &cm->current_frame; const AV1EncoderConfig *const oxcf = &cpi->oxcf; const RefreshFrameInfo *const refresh_frame = &cpi->refresh_frame; constenum aom_rc_mode rc_mode = oxcf->rc_cfg.mode;
int active_best_quality; int active_worst_quality = calc_active_worst_quality_no_stats_vbr(cpi); int q; int *inter_minq;
ASSIGN_MINQ_TABLE(bit_depth, inter_minq);
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.