Gate the VBR changes in 2fed9c3 only when mode!=REALTIME With this change, we can revert the threshold adjustment in unit test BasicRateTargetingVBRLagRealtime in 32fa66 too. Bug: 491358676 Change-Id: Iefd2ed25c4278d59dcaad5470d91a7b9dd5fe806
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c index 6182f1d..93d276f 100644 --- a/av1/encoder/encoder.c +++ b/av1/encoder/encoder.c
@@ -1537,6 +1537,7 @@ cm->current_frame_id = -1; cpi->tile_data = NULL; cpi->last_show_frame_buf = NULL; + cpi->ppi->p_rc.rtc_mode = (cpi->oxcf.mode == REALTIME); realloc_segmentation_maps(cpi); cpi->refresh_frame.alt_ref_frame = false;
diff --git a/av1/encoder/pass2_strategy.c b/av1/encoder/pass2_strategy.c index b4b2abf..93ca3e4 100644 --- a/av1/encoder/pass2_strategy.c +++ b/av1/encoder/pass2_strategy.c
@@ -604,7 +604,7 @@ // (zoom in). The range for this_frame_mv_in_out is -1.0 to +1.0. if (this_frame_mv_in_out > 0.0) { frame_boost += frame_boost * (this_frame_mv_in_out * 2.0); - if (!p_rc->accumulate_stats_stage) + if (!p_rc->accumulate_stats_stage && !p_rc->rtc_mode) max_boost += max_boost * (this_frame_mv_in_out * 2.0); } // In the extreme case the boost is halved. @@ -991,6 +991,21 @@ 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, @@ -1030,7 +1045,10 @@ // 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) { + if ((frame_index - cur_start) >= active_max_gf_interval + 1 && + ((cpi->oxcf.mode != REALTIME) || + !is_almost_static(gf_stats->zero_motion_accumulator, + twopass->kf_zeromotion_pct, cpi->ppi->lap_enabled))) { return 1; } return 0; @@ -2397,50 +2415,53 @@ 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) { + if (cpi->oxcf.mode != REALTIME) { + 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; } - 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; + + 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; } - 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; } - gfu_count++; - accumulate_i += new_i; + assert(gfu_count > 0); + p_rc->gfu_boost_average = gfu_boost_sum / gfu_count; } - 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; } - cpi->twopass_frame = stats_in_backup; - p_rc->accumulate_stats_stage = false; int ext_len = i - is_intra_only; if (use_alt_ref) { @@ -2562,6 +2583,7 @@ 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; @@ -2626,8 +2648,12 @@ int use_alt_ref; if (can_disable_arf) { - use_alt_ref = 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) && + ((cpi->oxcf.mode != REALTIME) || + !is_almost_static(gf_stats.zero_motion_accumulator, + twopass->kf_zeromotion_pct, cpi->ppi->lap_enabled)); } else { use_alt_ref = p_rc->use_arf_in_this_kf_group && (i < gf_cfg->lag_in_frames) && (i > 2);
diff --git a/av1/encoder/ratectrl.c b/av1/encoder/ratectrl.c index 6da81c1..c22cfdf 100644 --- a/av1/encoder/ratectrl.c +++ b/av1/encoder/ratectrl.c
@@ -42,6 +42,7 @@ #define USE_UNRESTRICTED_Q_IN_CQ_MODE 0 #define RES_NUM 2 +#define MODE_NUM 2 // Max rate target for 1080P and below encodes under normal circumstances // (1920 * 1080 / (16 * 16)) * MAX_MB_RATE bits per MB @@ -70,39 +71,39 @@ } \ } 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; \ - } \ +#define ASSIGN_MINQ_TABLE_2(bit_depth, name, res_idx, mode_idx) \ + do { \ + switch (bit_depth) { \ + case AOM_BITS_8: name = name##_8[mode_idx][res_idx]; break; \ + case AOM_BITS_10: name = name##_10[mode_idx][res_idx]; break; \ + case AOM_BITS_12: name = name##_12[mode_idx][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[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 kf_low_motion_minq_8[MODE_NUM][RES_NUM][QINDEX_RANGE]; +static int kf_high_motion_minq_8[MODE_NUM][RES_NUM][QINDEX_RANGE]; +static int arfgf_low_motion_minq_8[MODE_NUM][RES_NUM][QINDEX_RANGE]; +static int arfgf_high_motion_minq_8[MODE_NUM][RES_NUM][QINDEX_RANGE]; +static int inter_minq_8[MODE_NUM][RES_NUM][QINDEX_RANGE]; static int rtc_minq_8[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 kf_low_motion_minq_10[MODE_NUM][RES_NUM][QINDEX_RANGE]; +static int kf_high_motion_minq_10[MODE_NUM][RES_NUM][QINDEX_RANGE]; +static int arfgf_low_motion_minq_10[MODE_NUM][RES_NUM][QINDEX_RANGE]; +static int arfgf_high_motion_minq_10[MODE_NUM][RES_NUM][QINDEX_RANGE]; +static int inter_minq_10[MODE_NUM][RES_NUM][QINDEX_RANGE]; static int rtc_minq_10[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 kf_low_motion_minq_12[MODE_NUM][RES_NUM][QINDEX_RANGE]; +static int kf_high_motion_minq_12[MODE_NUM][RES_NUM][QINDEX_RANGE]; +static int arfgf_low_motion_minq_12[MODE_NUM][RES_NUM][QINDEX_RANGE]; +static int arfgf_high_motion_minq_12[MODE_NUM][RES_NUM][QINDEX_RANGE]; +static int inter_minq_12[MODE_NUM][RES_NUM][QINDEX_RANGE]; static int rtc_minq_12[QINDEX_RANGE]; static int gf_high_1 = 2875; @@ -112,6 +113,12 @@ static int kf_high = 8000; static int kf_low = 553; + +static int gf_high_rtc = 2400; +static int gf_low_rtc = 300; +static int kf_high_rtc = 5000; +static int kf_low_rtc = 400; + // 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, @@ -134,32 +141,40 @@ return av1_find_qindex(minqtarget, bit_depth, 0, QINDEX_RANGE - 1); } -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 double x1[MODE_NUM][RES_NUM][5] = { + { + { 0.1771, 0.379, 0.3279, 0.6634, 1.385 }, + { 0.1917, 0.3760, 0.34570, 0.6916, 1.14820 }, + }, + { + { 0.15, 0.45, 0.30, 0.55, 0.90 }, + { 0.15, 0.45, 0.30, 0.55, 0.90 }, + }, }; -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, +static void init_minq_luts(int kf_low_m[MODE_NUM][RES_NUM][QINDEX_RANGE], + int kf_high_m[MODE_NUM][RES_NUM][QINDEX_RANGE], + int arfgf_low[MODE_NUM][RES_NUM][QINDEX_RANGE], + int arfgf_high[MODE_NUM][RES_NUM][QINDEX_RANGE], + int inter[MODE_NUM][RES_NUM][QINDEX_RANGE], int *rtc, aom_bit_depth_t bit_depth) { int i; - 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); + for (int mode = 0; mode < MODE_NUM; mode++) { + 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[mode][res][i] = get_minq_index(maxq, 0.000001, -0.0004, + x1[mode][res][0], bit_depth); + kf_high_m[mode][res][i] = get_minq_index(maxq, 0.0000021, -0.00125, + x1[mode][res][1], bit_depth); + arfgf_low[mode][res][i] = get_minq_index(maxq, 0.0000015, -0.0009, + x1[mode][res][2], bit_depth); + arfgf_high[mode][res][i] = get_minq_index(maxq, 0.0000021, -0.00125, + x1[mode][res][3], bit_depth); + inter[mode][res][i] = get_minq_index(maxq, 0.00000271, -0.00113, + x1[mode][res][4], bit_depth); + rtc[i] = get_minq_index(maxq, 0.00000271, -0.00113, 0.70, bit_depth); + } } } } @@ -1158,9 +1173,15 @@ aom_bit_depth_t bit_depth, const int res_idx) { int *kf_low_motion_minq; int *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, + ASSIGN_MINQ_TABLE_2(bit_depth, kf_low_motion_minq, res_idx > 1, + p_rc->rtc_mode); + ASSIGN_MINQ_TABLE_2(bit_depth, kf_high_motion_minq, res_idx > 1, + p_rc->rtc_mode); + + int kf_low_local = p_rc->rtc_mode ? kf_low_rtc : kf_low; + int kf_high_local = p_rc->rtc_mode ? kf_high_rtc : kf_high; + + return get_active_quality(q, p_rc->kf_boost, kf_low_local, kf_high_local, kf_low_motion_minq, kf_high_motion_minq); } @@ -1169,14 +1190,24 @@ const int res_idx) { int *arfgf_low_motion_minq; int *arfgf_high_motion_minq; - 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); + ASSIGN_MINQ_TABLE_2(bit_depth, arfgf_low_motion_minq, res_idx > 1, + p_rc->rtc_mode); + ASSIGN_MINQ_TABLE_2(bit_depth, arfgf_high_motion_minq, res_idx > 1, + p_rc->rtc_mode); + int gf_low_local, gf_high_local; - 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; + if (p_rc->rtc_mode == false) { + gf_low_local = (p_rc->gfu_boost_average < gfboost_thresh[res_idx]) + ? gf_low_1 + : gf_low_2; + gf_high_local = (p_rc->gfu_boost_average < gfboost_thresh[res_idx]) + ? gf_high_1 + : gf_high_2; + } else { + gf_low_local = gf_low_rtc; + gf_high_local = gf_high_rtc; + } + return get_active_quality(q, p_rc->gfu_boost, gf_low_local, gf_high_local, arfgf_low_motion_minq, arfgf_high_motion_minq); } @@ -1187,9 +1218,9 @@ } static int get_gf_high_motion_quality(int q, aom_bit_depth_t bit_depth, - const int res_idx) { + const int res_idx, bool rtc_mode) { int *arfgf_high_motion_minq; - ASSIGN_MINQ_TABLE_2(bit_depth, arfgf_high_motion_minq, res_idx > 1); + ASSIGN_MINQ_TABLE_2(bit_depth, arfgf_high_motion_minq, res_idx > 1, rtc_mode); return arfgf_high_motion_minq[q]; } @@ -1582,7 +1613,7 @@ int active_worst_quality = calc_active_worst_quality_no_stats_vbr(cpi); int q; int *inter_minq; - ASSIGN_MINQ_TABLE_2(bit_depth, inter_minq, res_idx > 1); + ASSIGN_MINQ_TABLE_2(bit_depth, inter_minq, res_idx > 1, p_rc->rtc_mode); if (frame_is_intra_only(cm)) { if (rc_mode == AOM_Q) { @@ -2039,7 +2070,7 @@ 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); + ASSIGN_MINQ_TABLE_2(bit_depth, inter_minq, res_idx > 1, p_rc->rtc_mode); // TODO(jingning): Consider to rework this hack that covers issues incurred // in lightfield setting. @@ -2075,7 +2106,8 @@ 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, res_idx); + const int min_boost = + get_gf_high_motion_quality(q, bit_depth, res_idx, p_rc->rtc_mode); 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 e83b7c0..a854304 100644 --- a/av1/encoder/ratectrl.h +++ b/av1/encoder/ratectrl.h
@@ -339,6 +339,11 @@ bool accumulate_stats_stage; /*! + * Indicate if it is realtime mode or not + */ + bool rtc_mode; + + /*! * Stores the determined gf group lengths for a set of gf groups */ int gf_intervals[MAX_NUM_GF_INTERVALS];
diff --git a/test/datarate_test.cc b/test/datarate_test.cc index 0969e9f..c777d4a 100644 --- a/test/datarate_test.cc +++ b/test/datarate_test.cc
@@ -373,16 +373,8 @@ ResetModel(); lag_realtime_mode_ = 1; ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); -#if CONFIG_REALTIME_ONLY - // With CONFIG_REALTIME_ONLY=1, lag_in_frames is set to 0, and along with - // other factors in that configuration the threshold needs to be lowered - // after commit 2fed9c389d. - ASSERT_GE(effective_datarate_, cfg_.rc_target_bitrate * 0.8) - << " The datarate for the file is lower than target by too much!"; -#else ASSERT_GE(effective_datarate_, cfg_.rc_target_bitrate * 0.85) << " The datarate for the file is lower than target by too much!"; -#endif ASSERT_LE(effective_datarate_, cfg_.rc_target_bitrate * 2.0) << " The datarate for the file is greater than target by too much!"; }