Tweak the rate control for GOOD mode. BDRate improvement on PSNR and VMAF/VMAF-NEG. STATS_CHANGED Change-Id: I240ea8c626564c0abd43e0efdf538ac5680bba1d
diff --git a/av1/encoder/pass2_strategy.c b/av1/encoder/pass2_strategy.c index 06905b3..b4b2abf 100644 --- a/av1/encoder/pass2_strategy.c +++ b/av1/encoder/pass2_strategy.c
@@ -602,11 +602,15 @@ // Increase boost for frames where new data coming into frame (e.g. zoom out). // Slightly reduce boost if there is a net balance of motion out of the frame // (zoom in). The range for this_frame_mv_in_out is -1.0 to +1.0. - if (this_frame_mv_in_out > 0.0) + if (this_frame_mv_in_out > 0.0) { frame_boost += frame_boost * (this_frame_mv_in_out * 2.0); + if (!p_rc->accumulate_stats_stage) + max_boost += max_boost * (this_frame_mv_in_out * 2.0); + } // In the extreme case the boost is halved. - else + else { frame_boost += frame_boost * (this_frame_mv_in_out / 2.0); + } return AOMMIN(frame_boost, max_boost * boost_q_correction); } @@ -987,21 +991,6 @@ gf_group->bit_allocation[gf_group_size] = 0; } -// Returns true if KF group and GF group both are almost completely static. -static inline int is_almost_static(double gf_zero_motion, int kf_zero_motion, - int is_lap_enabled) { - if (is_lap_enabled) { - /* - * when LAP enabled kf_zero_motion is not reliable, so use strict - * constraint on gf_zero_motion. - */ - return (gf_zero_motion >= 0.999); - } else { - return (gf_zero_motion >= 0.995) && - (kf_zero_motion >= STATIC_KF_GROUP_THRESH); - } -} - #define ARF_ABS_ZOOM_THRESH 4.4 static inline int detect_gf_cut(AV1_COMP *cpi, int frame_index, int cur_start, int flash_detected, int active_max_gf_interval, @@ -1041,9 +1030,7 @@ // If almost totally static, we will not use the the max GF length later, // so we can continue for more frames. - if (((frame_index - cur_start) >= active_max_gf_interval + 1) && - !is_almost_static(gf_stats->zero_motion_accumulator, - twopass->kf_zeromotion_pct, cpi->ppi->lap_enabled)) { + if ((frame_index - cur_start) >= active_max_gf_interval + 1) { return 1; } return 0; @@ -2410,6 +2397,51 @@ const AV1EncoderConfig *const oxcf = &cpi->oxcf; const RateControlCfg *const rc_cfg = &oxcf->rc_cfg; + TWO_PASS_FRAME stats_in_backup = cpi->twopass_frame; + int gfu_boost_sum = 0; + int gfu_count = 0; + int accumulate_i = 0; + p_rc->accumulate_stats_stage = true; + if (rc->frames_since_key == 0) { + for (int k = 0; k < MAX_NUM_GF_INTERVALS; k++) { + if (p_rc->gf_intervals[k] == 0) { + break; + } + + int new_i = p_rc->gf_intervals[k]; + int ext_len_new = new_i - (k == 0 ? is_intra_only : 0); + if (use_alt_ref) { + if (accumulate_i >= rc->frames_to_key) { + break; + } + const int forward_frames = + (rc->frames_to_key - accumulate_i - new_i >= ext_len_new) + ? ext_len_new + : AOMMAX(0, rc->frames_to_key - accumulate_i - new_i); + if (k) { + cpi->twopass_frame.stats_in += new_i; + if (cpi->twopass_frame.stats_in >= + twopass->stats_buf_ctx->stats_in_end) { + cpi->twopass_frame.stats_in = twopass->stats_buf_ctx->stats_in_end; + } + } + reset_fpf_position(&cpi->twopass_frame, cpi->twopass_frame.stats_in); + // Calculate the boost for alt ref. + int gfu_boost_tmp = av1_calc_arf_boost( + twopass, &cpi->twopass_frame, p_rc, frame_info, alt_offset, + forward_frames, ext_len_new, &p_rc->num_stats_used_for_gfu_boost, + &p_rc->num_stats_required_for_gfu_boost, cpi->ppi->lap_enabled); + gfu_boost_sum += gfu_boost_tmp; + } + gfu_count++; + accumulate_i += new_i; + } + assert(gfu_count > 0); + p_rc->gfu_boost_average = gfu_boost_sum / gfu_count; + } + cpi->twopass_frame = stats_in_backup; + p_rc->accumulate_stats_stage = false; + int ext_len = i - is_intra_only; if (use_alt_ref) { const int forward_frames = (rc->frames_to_key - i >= ext_len) @@ -2530,7 +2562,6 @@ RATE_CONTROL *const rc = &cpi->rc; PRIMARY_RATE_CONTROL *const p_rc = &cpi->ppi->p_rc; const AV1EncoderConfig *const oxcf = &cpi->oxcf; - TWO_PASS *const twopass = &cpi->ppi->twopass; FIRSTPASS_STATS next_frame; const FIRSTPASS_STATS *const start_pos = cpi->twopass_frame.stats_in; GF_GROUP *gf_group = &cpi->ppi->gf_group; @@ -2595,11 +2626,8 @@ int use_alt_ref; if (can_disable_arf) { - use_alt_ref = - !is_almost_static(gf_stats.zero_motion_accumulator, - twopass->kf_zeromotion_pct, cpi->ppi->lap_enabled) && - p_rc->use_arf_in_this_kf_group && (i < gf_cfg->lag_in_frames) && - (i >= MIN_GF_INTERVAL); + use_alt_ref = p_rc->use_arf_in_this_kf_group && + (i < gf_cfg->lag_in_frames) && (i >= MIN_GF_INTERVAL); } else { use_alt_ref = p_rc->use_arf_in_this_kf_group && (i < gf_cfg->lag_in_frames) && (i > 2); @@ -4096,7 +4124,6 @@ if (rc->intervals_till_gf_calculate_due == 0 || 1) { calculate_gf_length(cpi, max_gop_length, MAX_NUM_GF_INTERVALS); } - if (max_gop_length > 16 && oxcf->algo_cfg.enable_tpl_model && oxcf->gf_cfg.lag_in_frames >= 32 && cpi->sf.tpl_sf.gop_length_decision_method != 3) {
diff --git a/av1/encoder/ratectrl.c b/av1/encoder/ratectrl.c index fe339d4..6da81c1 100644 --- a/av1/encoder/ratectrl.c +++ b/av1/encoder/ratectrl.c
@@ -41,6 +41,8 @@ #define USE_UNRESTRICTED_Q_IN_CQ_MODE 0 +#define RES_NUM 2 + // Max rate target for 1080P and below encodes under normal circumstances // (1920 * 1080 / (16 * 16)) * MAX_MB_RATE bits per MB #define MAX_MB_RATE 250 @@ -68,36 +70,48 @@ } \ } while (0) +#define ASSIGN_MINQ_TABLE_2(bit_depth, name, res_idx) \ + do { \ + switch (bit_depth) { \ + case AOM_BITS_8: name = name##_8[res_idx]; break; \ + case AOM_BITS_10: name = name##_10[res_idx]; break; \ + case AOM_BITS_12: name = name##_12[res_idx]; 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 -static int kf_low_motion_minq_8[QINDEX_RANGE]; -static int kf_high_motion_minq_8[QINDEX_RANGE]; -static int arfgf_low_motion_minq_8[QINDEX_RANGE]; -static int arfgf_high_motion_minq_8[QINDEX_RANGE]; -static int inter_minq_8[QINDEX_RANGE]; +static int kf_low_motion_minq_8[RES_NUM][QINDEX_RANGE]; +static int kf_high_motion_minq_8[RES_NUM][QINDEX_RANGE]; +static int arfgf_low_motion_minq_8[RES_NUM][QINDEX_RANGE]; +static int arfgf_high_motion_minq_8[RES_NUM][QINDEX_RANGE]; +static int inter_minq_8[RES_NUM][QINDEX_RANGE]; static int rtc_minq_8[QINDEX_RANGE]; -static int kf_low_motion_minq_10[QINDEX_RANGE]; -static int kf_high_motion_minq_10[QINDEX_RANGE]; -static int arfgf_low_motion_minq_10[QINDEX_RANGE]; -static int arfgf_high_motion_minq_10[QINDEX_RANGE]; -static int inter_minq_10[QINDEX_RANGE]; +static int kf_low_motion_minq_10[RES_NUM][QINDEX_RANGE]; +static int kf_high_motion_minq_10[RES_NUM][QINDEX_RANGE]; +static int arfgf_low_motion_minq_10[RES_NUM][QINDEX_RANGE]; +static int arfgf_high_motion_minq_10[RES_NUM][QINDEX_RANGE]; +static int inter_minq_10[RES_NUM][QINDEX_RANGE]; static int rtc_minq_10[QINDEX_RANGE]; -static int kf_low_motion_minq_12[QINDEX_RANGE]; -static int kf_high_motion_minq_12[QINDEX_RANGE]; -static int arfgf_low_motion_minq_12[QINDEX_RANGE]; -static int arfgf_high_motion_minq_12[QINDEX_RANGE]; -static int inter_minq_12[QINDEX_RANGE]; +static int kf_low_motion_minq_12[RES_NUM][QINDEX_RANGE]; +static int kf_high_motion_minq_12[RES_NUM][QINDEX_RANGE]; +static int arfgf_low_motion_minq_12[RES_NUM][QINDEX_RANGE]; +static int arfgf_high_motion_minq_12[RES_NUM][QINDEX_RANGE]; +static int inter_minq_12[RES_NUM][QINDEX_RANGE]; static int rtc_minq_12[QINDEX_RANGE]; -static int gf_high = 2400; -static int gf_low = 300; -#ifdef STRICT_RC -static int kf_high = 3200; -#else -static int kf_high = 5000; -#endif -static int kf_low = 400; +static int gf_high_1 = 2875; +static int gf_low_1 = 562; +static int gf_high_2 = 4994; +static int gf_low_2 = 100; +static int kf_high = 8000; +static int kf_low = 553; // How many times less pixels there are to encode given the current scaling. // Temporary replacement for rcf_mult and rate_thresh_mult. static double resize_rate_factor(const FrameDimensionCfg *const frm_dim_cfg, @@ -120,18 +134,33 @@ return av1_find_qindex(minqtarget, bit_depth, 0, QINDEX_RANGE - 1); } -static void init_minq_luts(int *kf_low_m, int *kf_high_m, int *arfgf_low, - int *arfgf_high, int *inter, int *rtc, +static double x1[RES_NUM][5] = { + { 0.1771, 0.379, 0.3279, 0.6634, 1.385 }, + { 0.1917, 0.3760, 0.34570, 0.6916, 1.14820 }, +}; + +static void init_minq_luts(int kf_low_m[RES_NUM][QINDEX_RANGE], + int kf_high_m[RES_NUM][QINDEX_RANGE], + int arfgf_low[RES_NUM][QINDEX_RANGE], + int arfgf_high[RES_NUM][QINDEX_RANGE], + int inter[RES_NUM][QINDEX_RANGE], int *rtc, aom_bit_depth_t bit_depth) { int i; - for (i = 0; i < QINDEX_RANGE; i++) { - const double maxq = av1_convert_qindex_to_q(i, bit_depth); - kf_low_m[i] = get_minq_index(maxq, 0.000001, -0.0004, 0.150, bit_depth); - kf_high_m[i] = get_minq_index(maxq, 0.0000021, -0.00125, 0.45, bit_depth); - arfgf_low[i] = get_minq_index(maxq, 0.0000015, -0.0009, 0.30, bit_depth); - arfgf_high[i] = get_minq_index(maxq, 0.0000021, -0.00125, 0.55, bit_depth); - inter[i] = get_minq_index(maxq, 0.00000271, -0.00113, 0.90, bit_depth); - rtc[i] = get_minq_index(maxq, 0.00000271, -0.00113, 0.70, bit_depth); + for (int res = 0; res < RES_NUM; res++) { + for (i = 0; i < QINDEX_RANGE; i++) { + const double maxq = av1_convert_qindex_to_q(i, bit_depth); + kf_low_m[res][i] = + get_minq_index(maxq, 0.000001, -0.0004, x1[res][0], bit_depth); + kf_high_m[res][i] = + get_minq_index(maxq, 0.0000021, -0.00125, x1[res][1], bit_depth); + arfgf_low[res][i] = + get_minq_index(maxq, 0.0000015, -0.0009, x1[res][2], bit_depth); + arfgf_high[res][i] = + get_minq_index(maxq, 0.0000021, -0.00125, x1[res][3], bit_depth); + inter[res][i] = + get_minq_index(maxq, 0.00000271, -0.00113, x1[res][4], bit_depth); + rtc[i] = get_minq_index(maxq, 0.00000271, -0.00113, 0.70, bit_depth); + } } } @@ -1123,34 +1152,44 @@ } } +static int gfboost_thresh[3] = { 4000, 4000, 3000 }; + static int get_kf_active_quality(const PRIMARY_RATE_CONTROL *const p_rc, int q, - aom_bit_depth_t bit_depth) { + aom_bit_depth_t bit_depth, const int res_idx) { 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); + ASSIGN_MINQ_TABLE_2(bit_depth, kf_low_motion_minq, res_idx > 1); + ASSIGN_MINQ_TABLE_2(bit_depth, kf_high_motion_minq, res_idx > 1); return get_active_quality(q, p_rc->kf_boost, kf_low, kf_high, kf_low_motion_minq, kf_high_motion_minq); } -static int get_gf_active_quality_no_rc(int gfu_boost, int q, - aom_bit_depth_t bit_depth) { +static int get_gf_active_quality_no_rc(const PRIMARY_RATE_CONTROL *const p_rc, + int q, aom_bit_depth_t bit_depth, + const int res_idx) { 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, + ASSIGN_MINQ_TABLE_2(bit_depth, arfgf_low_motion_minq, res_idx > 1); + ASSIGN_MINQ_TABLE_2(bit_depth, arfgf_high_motion_minq, res_idx > 1); + + int gf_low_local = + (p_rc->gfu_boost_average < gfboost_thresh[res_idx]) ? gf_low_1 : gf_low_2; + int gf_high_local = (p_rc->gfu_boost_average < gfboost_thresh[res_idx]) + ? gf_high_1 + : gf_high_2; + return get_active_quality(q, p_rc->gfu_boost, gf_low_local, gf_high_local, arfgf_low_motion_minq, arfgf_high_motion_minq); } static int 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); + aom_bit_depth_t bit_depth, const int res_idx) { + return get_gf_active_quality_no_rc(p_rc, q, bit_depth, res_idx); } -static int get_gf_high_motion_quality(int q, aom_bit_depth_t bit_depth) { +static int get_gf_high_motion_quality(int q, aom_bit_depth_t bit_depth, + const int res_idx) { int *arfgf_high_motion_minq; - ASSIGN_MINQ_TABLE(bit_depth, arfgf_high_motion_minq); + ASSIGN_MINQ_TABLE_2(bit_depth, arfgf_high_motion_minq, res_idx > 1); return arfgf_high_motion_minq[q]; } @@ -1310,6 +1349,11 @@ int active_best_quality = rc->best_quality; ASSIGN_MINQ_TABLE(bit_depth, rtc_minq); + const int is_608p_or_larger = AOMMIN(cm->width, cm->height) >= 608; + const int is_480p_or_larger = AOMMIN(cm->width, cm->height) >= 480; + // res_idx is 0 for res < 480p, 1 for 480p, 2 for 608p+ + const int res_idx = is_480p_or_larger + is_608p_or_larger; + 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 @@ -1325,7 +1369,7 @@ 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); + p_rc, p_rc->avg_frame_qindex[KEY_FRAME], bit_depth, res_idx); // Allow somewhat lower kf minq with small image formats. if ((width * height) <= (352 * 288)) { q_adj_factor -= 0.25; @@ -1347,7 +1391,7 @@ 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); + active_best_quality = get_gf_active_quality(p_rc, q, bit_depth, res_idx); } else { // Use the lower of active_worst_quality and recent/average Q. FRAME_TYPE frame_type = @@ -1519,6 +1563,11 @@ const RefreshFrameInfo *const refresh_frame = &cpi->refresh_frame; const enum aom_rc_mode rc_mode = oxcf->rc_cfg.mode; + const int is_608p_or_larger = AOMMIN(cm->width, cm->height) >= 608; + const int is_480p_or_larger = AOMMIN(cm->width, cm->height) >= 480; + // res_idx is 0 for res < 480p, 1 for 480p, 2 for 608p+ + const int res_idx = is_480p_or_larger + is_608p_or_larger; + assert(has_no_stats_stage(cpi)); assert(rc_mode == AOM_VBR || (!USE_UNRESTRICTED_Q_IN_CQ_MODE && rc_mode == AOM_CQ) || @@ -1533,7 +1582,7 @@ int active_worst_quality = calc_active_worst_quality_no_stats_vbr(cpi); int q; int *inter_minq; - ASSIGN_MINQ_TABLE(bit_depth, inter_minq); + ASSIGN_MINQ_TABLE_2(bit_depth, inter_minq, res_idx > 1); if (frame_is_intra_only(cm)) { if (rc_mode == AOM_Q) { @@ -1560,7 +1609,7 @@ double q_adj_factor = 1.0; active_best_quality = get_kf_active_quality( - p_rc, p_rc->avg_frame_qindex[KEY_FRAME], bit_depth); + p_rc, p_rc->avg_frame_qindex[KEY_FRAME], bit_depth, res_idx); // Allow somewhat lower kf minq with small image formats. if ((width * height) <= (352 * 288)) { @@ -1587,7 +1636,7 @@ // For constrained quality don't allow Q less than the cq level if (rc_mode == AOM_CQ) { if (q < cq_level) q = cq_level; - active_best_quality = get_gf_active_quality(p_rc, q, bit_depth); + active_best_quality = get_gf_active_quality(p_rc, q, bit_depth, res_idx); // Constrained quality use slightly lower active best. active_best_quality = active_best_quality * 15 / 16; } else if (rc_mode == AOM_Q) { @@ -1599,7 +1648,7 @@ : av1_compute_qdelta(rc, q_val, q_val * 0.50, bit_depth); active_best_quality = AOMMAX(qindex + delta_qindex, rc->best_quality); } else { - active_best_quality = get_gf_active_quality(p_rc, q, bit_depth); + active_best_quality = get_gf_active_quality(p_rc, q, bit_depth, res_idx); } } else { if (rc_mode == AOM_Q) { @@ -1737,6 +1786,11 @@ int active_worst_quality = *active_worst; const int bit_depth = cm->seq_params->bit_depth; + const int is_608p_or_larger = AOMMIN(cm->width, cm->height) >= 608; + const int is_480p_or_larger = AOMMIN(cm->width, cm->height) >= 480; + // res_idx is 0 for res < 480p, 1 for 480p, 2 for 608p+ + const int res_idx = is_480p_or_larger + is_608p_or_larger; + if (rc->frames_to_key <= 1 && oxcf->rc_cfg.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 @@ -1783,7 +1837,7 @@ // Baseline value derived from active_worst_quality and kf boost. active_best_quality = - get_kf_active_quality(p_rc, active_worst_quality, bit_depth); + get_kf_active_quality(p_rc, active_worst_quality, bit_depth, res_idx); if (cpi->is_screen_content_type) { active_best_quality /= 2; } @@ -1973,14 +2027,20 @@ const RefreshFrameInfo *const refresh_frame = &cpi->refresh_frame; const GF_GROUP *gf_group = &cpi->ppi->gf_group; const enum aom_rc_mode rc_mode = oxcf->rc_cfg.mode; - int *inter_minq; - ASSIGN_MINQ_TABLE(bit_depth, inter_minq); int active_best_quality = 0; FRAME_UPDATE_TYPE update_type = gf_group->update_type[gf_index]; const int is_intrl_arf_boost = update_type == INTNL_ARF_UPDATE; int is_leaf_frame = !(update_type == ARF_UPDATE || update_type == GF_UPDATE || is_intrl_arf_boost); + const int is_608p_or_larger = AOMMIN(cm->width, cm->height) >= 608; + const int is_480p_or_larger = AOMMIN(cm->width, cm->height) >= 480; + // res_idx is 0 for res < 480p, 1 for 480p, 2 for 608p+ + const int res_idx = is_480p_or_larger + is_608p_or_larger; + + int *inter_minq; + ASSIGN_MINQ_TABLE_2(bit_depth, inter_minq, res_idx > 1); + // TODO(jingning): Consider to rework this hack that covers issues incurred // in lightfield setting. if (cm->tiles.large_scale) { @@ -2012,10 +2072,10 @@ q = p_rc->avg_frame_qindex[INTER_FRAME]; } if (rc_mode == AOM_CQ && q < cq_level) q = cq_level; - active_best_quality = get_gf_active_quality(p_rc, q, bit_depth); + active_best_quality = get_gf_active_quality(p_rc, q, bit_depth, res_idx); // Constrained quality use slightly lower active best. if (rc_mode == AOM_CQ) active_best_quality = active_best_quality * 15 / 16; - const int min_boost = get_gf_high_motion_quality(q, bit_depth); + const int min_boost = get_gf_high_motion_quality(q, bit_depth, res_idx); const int boost = min_boost - active_best_quality; active_best_quality = min_boost - (int)(boost * p_rc->arf_boost_factor); if (!is_intrl_arf_boost) return active_best_quality;
diff --git a/av1/encoder/ratectrl.h b/av1/encoder/ratectrl.h index 4d6ef52..e83b7c0 100644 --- a/av1/encoder/ratectrl.h +++ b/av1/encoder/ratectrl.h
@@ -329,6 +329,16 @@ int gfu_boost; /*! + * Average boost factor of ARFs and GFs within a kf interval + */ + int gfu_boost_average; + + /*! + * Indicate if it is gfu_boost accumulation stage + */ + bool accumulate_stats_stage; + + /*! * Stores the determined gf group lengths for a set of gf groups */ int gf_intervals[MAX_NUM_GF_INTERVALS];
diff --git a/av1/encoder/speed_features.c b/av1/encoder/speed_features.c index 37f0788..7971136 100644 --- a/av1/encoder/speed_features.c +++ b/av1/encoder/speed_features.c
@@ -1307,7 +1307,6 @@ sf->tpl_sf.prune_intra_modes = 1; sf->tpl_sf.reduce_first_step_size = 6; sf->tpl_sf.subpel_force_stop = QUARTER_PEL; - sf->tpl_sf.gop_length_decision_method = 1; sf->tx_sf.adaptive_txb_search_level = boosted ? 2 : 3; sf->tx_sf.tx_type_search.use_skip_flag_prediction = 2; @@ -2194,7 +2193,7 @@ } static inline void init_tpl_sf(TPL_SPEED_FEATURES *tpl_sf) { - tpl_sf->gop_length_decision_method = 0; + tpl_sf->gop_length_decision_method = 1; tpl_sf->prune_intra_modes = 0; tpl_sf->prune_starting_mv = 0; tpl_sf->reduce_first_step_size = 0;