Refactor common code in 2 pass rate control Pull common code out into separate functions to make it easier to split out different rate control modes without duplicating code. No change in performance. Change-Id: I1bab72812361d81553e39697696e805e0a24fb84
diff --git a/av1/encoder/ratectrl.c b/av1/encoder/ratectrl.c index 3853f14..9e527d4 100644 --- a/av1/encoder/ratectrl.c +++ b/av1/encoder/ratectrl.c
@@ -1026,6 +1026,184 @@ #endif // USE_UNRESTRICTED_Q_IN_CQ_MODE #define STATIC_MOTION_THRESH 95 +static void get_intra_q_and_bounds_two_pass(const AV1_COMP *cpi, int width, + int height, int *active_best, + int *active_worst, int *arf_q, + int cq_level) { + const AV1_COMMON *const cm = &cpi->common; + const RATE_CONTROL *const rc = &cpi->rc; + const AV1EncoderConfig *const oxcf = &cpi->oxcf; + int active_best_quality; + int active_worst_quality = *active_worst; + const int bit_depth = cm->seq_params.bit_depth; + + if (rc->frames_to_key == 1 && oxcf->rc_mode == AOM_Q) { + // If the next frame is also a key frame or the current frame is the + // only frame in the sequence in AOM_Q mode, just use the cq_level + // as q. + active_best_quality = cq_level; + active_worst_quality = cq_level; + } else if (cm->current_frame.frame_type == KEY_FRAME && cm->show_frame == 0) { + // Handle the special case for forward reference key frames. + // Increase the boost because this keyframe is used as a forward and + // backward reference. + const int qindex = rc->last_boosted_qindex; + const double last_boosted_q = av1_convert_qindex_to_q(qindex, bit_depth); + const int delta_qindex = av1_compute_qdelta( + rc, last_boosted_q, last_boosted_q * 0.25, bit_depth); + active_best_quality = AOMMAX(qindex + delta_qindex, rc->best_quality); + // Update the arf_q since the forward keyframe is replacing the ALTREF + *arf_q = active_best_quality; + } else if (rc->this_key_frame_forced) { + // 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. + double last_boosted_q; + int delta_qindex; + int qindex; + + if (cpi->twopass.last_kfgroup_zeromotion_pct >= STATIC_MOTION_THRESH) { + qindex = AOMMIN(rc->last_kf_qindex, rc->last_boosted_qindex); + active_best_quality = qindex; + last_boosted_q = av1_convert_qindex_to_q(qindex, bit_depth); + delta_qindex = av1_compute_qdelta(rc, last_boosted_q, + last_boosted_q * 1.25, bit_depth); + active_worst_quality = + AOMMIN(qindex + delta_qindex, active_worst_quality); + } else { + qindex = rc->last_boosted_qindex; + last_boosted_q = av1_convert_qindex_to_q(qindex, bit_depth); + delta_qindex = av1_compute_qdelta(rc, last_boosted_q, + last_boosted_q * 0.50, bit_depth); + active_best_quality = AOMMAX(qindex + delta_qindex, rc->best_quality); + } + } else { + // Not forced keyframe. + double q_adj_factor = 1.0; + double q_val; + + // Baseline value derived from cpi->active_worst_quality and kf boost. + active_best_quality = + get_kf_active_quality(rc, active_worst_quality, bit_depth); + + if (cpi->twopass.kf_zeromotion_pct >= STATIC_KF_GROUP_THRESH) { + active_best_quality /= 3; + } + + // Allow somewhat lower kf minq with small image formats. + if ((width * height) <= (352 * 288)) { + q_adj_factor -= 0.25; + } + + // Make a further adjustment based on the kf zero motion measure. + q_adj_factor += 0.05 - (0.001 * (double)cpi->twopass.kf_zeromotion_pct); + + // 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); + + // Tweak active_best_quality for AOM_Q mode when superres is on, as this + // will be used directly as 'q' later. + if (oxcf->rc_mode == AOM_Q && + (oxcf->superres_mode == SUPERRES_QTHRESH || + oxcf->superres_mode == SUPERRES_AUTO) && + cm->superres_scale_denominator != SCALE_NUMERATOR) { + active_best_quality = + AOMMAX(active_best_quality - + ((cm->superres_scale_denominator - SCALE_NUMERATOR) * 4), + 0); + } + } + + *active_best = active_best_quality; + *active_worst = active_worst_quality; +} + +// Does some final adjustments to the q value and bounds. +static void postprocess_q_and_bounds(const AV1_COMP *cpi, int width, int height, + int *active_worst, int *active_best, + int *q_out, int is_intrl_arf_boost) { + const AV1_COMMON *const cm = &cpi->common; + const RATE_CONTROL *const rc = &cpi->rc; + const AV1EncoderConfig *oxcf = &cpi->oxcf; + const int bit_depth = cpi->common.seq_params.bit_depth; + int active_best_quality = *active_best; + int active_worst_quality = *active_worst; + int q; + + // Extension to max or min Q if undershoot or overshoot is outside + // the permitted range. + if (cpi->oxcf.rc_mode != AOM_Q) { + if (frame_is_intra_only(cm) || + (!rc->is_src_frame_alt_ref && + (cpi->refresh_golden_frame || is_intrl_arf_boost || + cpi->refresh_alt_ref_frame))) { + active_best_quality -= + (cpi->twopass.extend_minq + cpi->twopass.extend_minq_fast); + active_worst_quality += (cpi->twopass.extend_maxq / 2); + } else { + active_best_quality -= + (cpi->twopass.extend_minq + cpi->twopass.extend_minq_fast) / 2; + active_worst_quality += cpi->twopass.extend_maxq; + } + } + + aom_clear_system_state(); + // Static forced key frames Q restrictions dealt with elsewhere. + if (!(frame_is_intra_only(cm)) || !rc->this_key_frame_forced || + (cpi->twopass.last_kfgroup_zeromotion_pct < STATIC_MOTION_THRESH)) { + const int qdelta = av1_frame_type_qdelta(cpi, active_worst_quality); + active_worst_quality = + AOMMAX(active_worst_quality + qdelta, active_best_quality); + } + + // Modify active_best_quality for downscaled normal frames. + if (av1_frame_scaled(cm) && !frame_is_kf_gf_arf(cpi)) { + int qdelta = av1_compute_qdelta_by_rate( + rc, cm->current_frame.frame_type, active_best_quality, 2.0, bit_depth); + active_best_quality = + AOMMAX(active_best_quality + qdelta, rc->best_quality); + } + + 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); + + if (oxcf->rc_mode == AOM_Q || + (frame_is_intra_only(cm) && !rc->this_key_frame_forced && + cpi->twopass.kf_zeromotion_pct >= STATIC_KF_GROUP_THRESH && + rc->frames_to_key > 1)) { + q = active_best_quality; + // Special case code to try and match quality with forced key frames. + } else if (frame_is_intra_only(cm) && rc->this_key_frame_forced) { + // If static since last kf use better of last boosted and last kf q. + if (cpi->twopass.last_kfgroup_zeromotion_pct >= STATIC_MOTION_THRESH) { + q = AOMMIN(rc->last_kf_qindex, rc->last_boosted_qindex); + } else { + q = AOMMIN(rc->last_boosted_qindex, + (active_best_quality + active_worst_quality) / 2); + } + } else { + q = av1_rc_regulate_q(cpi, rc->this_frame_target, active_best_quality, + active_worst_quality, width, height); + if (q > active_worst_quality) { + // Special case when we are targeting the max allowed rate. + if (rc->this_frame_target >= rc->max_frame_bandwidth) + active_worst_quality = q; + else + q = active_worst_quality; + } + } + clamp(q, active_best_quality, active_worst_quality); + + *active_best = active_best_quality; + *active_worst = active_worst_quality; + *q_out = q; +} + static int rc_pick_q_and_bounds_two_pass(const AV1_COMP *cpi, int width, int height, int *bottom_index, int *top_index, int *arf_q) { @@ -1044,88 +1222,9 @@ const int is_intrl_arf_boost = gf_group->update_type[gf_group->index] == INTNL_ARF_UPDATE; - if (frame_is_intra_only(cm)) { - if (rc->frames_to_key == 1 && oxcf->rc_mode == AOM_Q) { - // If the next frame is also a key frame or the current frame is the - // only frame in the sequence in AOM_Q mode, just use the cq_level - // as q. - active_best_quality = cq_level; - active_worst_quality = cq_level; - } else if (cm->current_frame.frame_type == KEY_FRAME && - cm->show_frame == 0) { - // Handle the special case for forward reference key frames. - // Increase the boost because this keyframe is used as a forward and - // backward reference. - const int qindex = rc->last_boosted_qindex; - const double last_boosted_q = av1_convert_qindex_to_q(qindex, bit_depth); - const int delta_qindex = av1_compute_qdelta( - rc, last_boosted_q, last_boosted_q * 0.25, bit_depth); - active_best_quality = AOMMAX(qindex + delta_qindex, rc->best_quality); - // Update the arf_q since the forward keyframe is replacing the ALTREF - *arf_q = active_best_quality; - } else if (rc->this_key_frame_forced) { - // 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. - double last_boosted_q; - int delta_qindex; - int qindex; - - if (cpi->twopass.last_kfgroup_zeromotion_pct >= STATIC_MOTION_THRESH) { - qindex = AOMMIN(rc->last_kf_qindex, rc->last_boosted_qindex); - active_best_quality = qindex; - last_boosted_q = av1_convert_qindex_to_q(qindex, bit_depth); - delta_qindex = av1_compute_qdelta(rc, last_boosted_q, - last_boosted_q * 1.25, bit_depth); - active_worst_quality = - AOMMIN(qindex + delta_qindex, active_worst_quality); - } else { - qindex = rc->last_boosted_qindex; - last_boosted_q = av1_convert_qindex_to_q(qindex, bit_depth); - delta_qindex = av1_compute_qdelta(rc, last_boosted_q, - last_boosted_q * 0.50, bit_depth); - active_best_quality = AOMMAX(qindex + delta_qindex, rc->best_quality); - } - } else { - // Not forced keyframe. - double q_adj_factor = 1.0; - double q_val; - - // Baseline value derived from cpi->active_worst_quality and kf boost. - active_best_quality = - get_kf_active_quality(rc, active_worst_quality, bit_depth); - - if (cpi->twopass.kf_zeromotion_pct >= STATIC_KF_GROUP_THRESH) { - active_best_quality /= 3; - } - - // Allow somewhat lower kf minq with small image formats. - if ((width * height) <= (352 * 288)) { - q_adj_factor -= 0.25; - } - - // Make a further adjustment based on the kf zero motion measure. - q_adj_factor += 0.05 - (0.001 * (double)cpi->twopass.kf_zeromotion_pct); - - // 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); - - // Tweak active_best_quality for AOM_Q mode when superres is on, as this - // will be used directly as 'q' later. - if (oxcf->rc_mode == AOM_Q && - (oxcf->superres_mode == SUPERRES_QTHRESH || - oxcf->superres_mode == SUPERRES_AUTO) && - cm->superres_scale_denominator != SCALE_NUMERATOR) { - active_best_quality = - AOMMAX(active_best_quality - - ((cm->superres_scale_denominator - SCALE_NUMERATOR) * 4), - 0); - } - } + get_intra_q_and_bounds_two_pass(cpi, width, height, &active_best_quality, + &active_worst_quality, arf_q, cq_level); } else if (!rc->is_src_frame_alt_ref && (cpi->refresh_golden_frame || is_intrl_arf_boost || cpi->refresh_alt_ref_frame)) { @@ -1213,71 +1312,8 @@ } } - // Extension to max or min Q if undershoot or overshoot is outside - // the permitted range. - if (cpi->oxcf.rc_mode != AOM_Q) { - if (frame_is_intra_only(cm) || - (!rc->is_src_frame_alt_ref && - (cpi->refresh_golden_frame || is_intrl_arf_boost || - cpi->refresh_alt_ref_frame))) { - active_best_quality -= - (cpi->twopass.extend_minq + cpi->twopass.extend_minq_fast); - active_worst_quality += (cpi->twopass.extend_maxq / 2); - } else { - active_best_quality -= - (cpi->twopass.extend_minq + cpi->twopass.extend_minq_fast) / 2; - active_worst_quality += cpi->twopass.extend_maxq; - } - } - - aom_clear_system_state(); - // Static forced key frames Q restrictions dealt with elsewhere. - if (!(frame_is_intra_only(cm)) || !rc->this_key_frame_forced || - (cpi->twopass.last_kfgroup_zeromotion_pct < STATIC_MOTION_THRESH)) { - const int qdelta = av1_frame_type_qdelta(cpi, active_worst_quality); - active_worst_quality = - AOMMAX(active_worst_quality + qdelta, active_best_quality); - } - - // Modify active_best_quality for downscaled normal frames. - if (av1_frame_scaled(cm) && !frame_is_kf_gf_arf(cpi)) { - int qdelta = av1_compute_qdelta_by_rate( - rc, cm->current_frame.frame_type, active_best_quality, 2.0, bit_depth); - active_best_quality = - AOMMAX(active_best_quality + qdelta, rc->best_quality); - } - - 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); - - if (oxcf->rc_mode == AOM_Q || - (frame_is_intra_only(cm) && !rc->this_key_frame_forced && - cpi->twopass.kf_zeromotion_pct >= STATIC_KF_GROUP_THRESH && - rc->frames_to_key > 1)) { - q = active_best_quality; - // Special case code to try and match quality with forced key frames. - } else if (frame_is_intra_only(cm) && rc->this_key_frame_forced) { - // If static since last kf use better of last boosted and last kf q. - if (cpi->twopass.last_kfgroup_zeromotion_pct >= STATIC_MOTION_THRESH) { - q = AOMMIN(rc->last_kf_qindex, rc->last_boosted_qindex); - } else { - q = AOMMIN(rc->last_boosted_qindex, - (active_best_quality + active_worst_quality) / 2); - } - } else { - q = av1_rc_regulate_q(cpi, rc->this_frame_target, active_best_quality, - active_worst_quality, width, height); - if (q > active_worst_quality) { - // Special case when we are targeting the max allowed rate. - if (rc->this_frame_target >= rc->max_frame_bandwidth) - active_worst_quality = q; - else - q = active_worst_quality; - } - } - clamp(q, active_best_quality, active_worst_quality); + postprocess_q_and_bounds(cpi, width, height, &active_worst_quality, + &active_best_quality, &q, is_intrl_arf_boost); *top_index = active_worst_quality; *bottom_index = active_best_quality;