Realtime mode with lookahead for 1 pass
Make nonzero lookahead (lag_in_frames > 0) work with
1 pass realtime mode. This new encoding mode is for
single spatial layer and VBR mode. And disallowed
for REALTIIME_CONFIG=1 (lag-in-frames is kept forced
to 0 for this build config under realtime mode).
The gop/pyramid structure is set in the function
define_gf_group_pass0(), with the gop length and depth
set by the user via the parameters:
--min/max-gf-interval, --gf-min/max-pyr-height
The gop structure will be fixed (based on user settings) for
the whole sequence for now, adaptation to the source content
will be added later.
The nonrd-pickmode encoding (speed >= 7) is expanded to
support the additional references for prediction in this
encoding mode.
Test for this encoding mode added in datarate_test,cc.
Initial borg result for speed 8, comparing nonzero lookahead
(with gf-interval=16 and pyr-height=1) vs lookahead=0:
bdrate gain of ~15/19% (avg_psnr/ssim) with IC speed slowdown of ~50%.
The case of spatial layers was done here (not merged in):
https://aomedia-review.googlesource.com/c/aom/+/193401
Change-Id: I50eeff1a87884f7237f5163b209f79fdae899979
diff --git a/apps/aomenc.c b/apps/aomenc.c
index 3caae90..c3eb292 100644
--- a/apps/aomenc.c
+++ b/apps/aomenc.c
@@ -1206,10 +1206,12 @@
}
config->use_16bit_internal |= config->cfg.g_bit_depth > AOM_BITS_8;
+#if CONFIG_REALTIME_ONLY
if (global->usage == AOM_USAGE_REALTIME && config->cfg.g_lag_in_frames != 0) {
aom_tools_warn("non-zero lag-in-frames option ignored in realtime mode.\n");
config->cfg.g_lag_in_frames = 0;
}
+#endif
if (global->usage == AOM_USAGE_ALL_INTRA) {
if (config->cfg.g_lag_in_frames != 0) {
diff --git a/av1/av1_cx_iface.c b/av1/av1_cx_iface.c
index a1ee702..c049a99 100644
--- a/av1/av1_cx_iface.c
+++ b/av1/av1_cx_iface.c
@@ -1356,10 +1356,13 @@
color_cfg->chroma_sample_position = extra_cfg->chroma_sample_position;
// Set Group of frames configuration.
- // Force lag_in_frames to 0 for REALTIME mode
+#if CONFIG_REALTIME_ONLY
gf_cfg->lag_in_frames = (oxcf->mode == REALTIME)
? 0
: clamp(cfg->g_lag_in_frames, 0, MAX_LAG_BUFFERS);
+#else
+ gf_cfg->lag_in_frames = clamp(cfg->g_lag_in_frames, 0, MAX_LAG_BUFFERS);
+#endif
gf_cfg->enable_auto_arf = extra_cfg->enable_auto_alt_ref;
gf_cfg->enable_auto_brf = extra_cfg->enable_auto_bwd_ref;
gf_cfg->min_gf_interval = extra_cfg->min_gf_interval;
@@ -3009,7 +3012,7 @@
set_encoder_config(&priv->oxcf, &priv->cfg, &priv->extra_cfg);
if (priv->oxcf.rc_cfg.mode != AOM_CBR &&
- priv->oxcf.pass == AOM_RC_ONE_PASS && priv->oxcf.mode == GOOD) {
+ priv->oxcf.pass == AOM_RC_ONE_PASS) {
// Enable look ahead - enabled for AOM_Q, AOM_CQ, AOM_VBR
*num_lap_buffers =
AOMMIN((int)priv->cfg.g_lag_in_frames,
@@ -3522,7 +3525,7 @@
#endif // CONFIG_MULTITHREAD
// Call for LAP stage
- if (cpi_lap != NULL) {
+ if (cpi_lap != NULL && !is_one_pass_rt_lag_params(cpi)) {
if (cpi_lap->ppi->b_freeze_internal_state) {
av1_save_all_coding_context(cpi_lap);
}
diff --git a/av1/encoder/encode_strategy.c b/av1/encoder/encode_strategy.c
index b18b21f..5ac74da 100644
--- a/av1/encoder/encode_strategy.c
+++ b/av1/encoder/encode_strategy.c
@@ -1302,8 +1302,7 @@
return -1;
}
- // TODO(sarahparker) finish bit allocation for one pass pyramid
- if (has_no_stats_stage(cpi)) {
+ if (has_no_stats_stage(cpi) && !is_one_pass_rt_lag_params(cpi)) {
gf_cfg->gf_max_pyr_height =
AOMMIN(gf_cfg->gf_max_pyr_height, USE_ALTREF_FOR_ONE_PASS);
gf_cfg->gf_min_pyr_height =
diff --git a/av1/encoder/encoder.h b/av1/encoder/encoder.h
index c68f7e9..95202d1 100644
--- a/av1/encoder/encoder.h
+++ b/av1/encoder/encoder.h
@@ -4127,7 +4127,8 @@
static inline int is_stat_consumption_stage(const AV1_COMP *const cpi) {
return (is_stat_consumption_stage_twopass(cpi) ||
(cpi->oxcf.pass == AOM_RC_ONE_PASS &&
- (cpi->compressor_stage == ENCODE_STAGE) && cpi->ppi->lap_enabled));
+ (cpi->compressor_stage == ENCODE_STAGE) && cpi->ppi->lap_enabled &&
+ cpi->oxcf.mode != REALTIME));
}
// Decide whether 'dv_costs' need to be allocated/stored during the encoding.
@@ -4148,11 +4149,18 @@
static inline int has_no_stats_stage(const AV1_COMP *const cpi) {
assert(
IMPLIES(!cpi->ppi->lap_enabled, cpi->compressor_stage == ENCODE_STAGE));
- return (cpi->oxcf.pass == AOM_RC_ONE_PASS && !cpi->ppi->lap_enabled);
+ return (cpi->oxcf.pass == AOM_RC_ONE_PASS &&
+ (!cpi->ppi->lap_enabled || cpi->oxcf.mode == REALTIME));
}
/*!\cond */
+static inline int is_one_pass_rt_lag_params(const AV1_COMP *cpi) {
+ return cpi->oxcf.pass == AOM_RC_ONE_PASS &&
+ cpi->oxcf.gf_cfg.lag_in_frames > 0 && cpi->oxcf.mode == REALTIME &&
+ cpi->oxcf.rc_cfg.mode != AOM_CBR;
+}
+
static inline int is_one_pass_rt_params(const AV1_COMP *cpi) {
return has_no_stats_stage(cpi) && cpi->oxcf.gf_cfg.lag_in_frames == 0 &&
(cpi->oxcf.mode == REALTIME || cpi->svc.number_spatial_layers > 1);
diff --git a/av1/encoder/nonrd_opt.h b/av1/encoder/nonrd_opt.h
index 1e783e9..9f81c0a 100644
--- a/av1/encoder/nonrd_opt.h
+++ b/av1/encoder/nonrd_opt.h
@@ -21,7 +21,9 @@
#define RTC_MODES (AOMMAX(RTC_INTER_MODES, RTC_INTRA_MODES))
#define CALC_BIASED_RDCOST(rdcost) (7 * (rdcost) >> 3)
#define NUM_COMP_INTER_MODES_RT (6)
+#define NUM_COMP_INTER_MODES_RT_FULL (10)
#define NUM_INTER_MODES 12
+#define NUM_INTER_MODES_FULL 28
#define CAP_TX_SIZE_FOR_BSIZE_GT32(tx_mode_search_type, bsize) \
(((tx_mode_search_type) != ONLY_4X4 && (bsize) > BLOCK_32X32) ? true : false)
#define TX_SIZE_FOR_BSIZE_GT32 (TX_16X16)
@@ -144,6 +146,23 @@
{ ALTREF_FRAME, GLOBALMV }, { ALTREF_FRAME, NEWMV },
};
+static const REF_MODE ref_mode_set_full[NUM_INTER_MODES_FULL] = {
+ { LAST_FRAME, NEARESTMV }, { LAST_FRAME, NEARMV },
+ { LAST_FRAME, GLOBALMV }, { LAST_FRAME, NEWMV },
+ { GOLDEN_FRAME, NEARESTMV }, { GOLDEN_FRAME, NEARMV },
+ { GOLDEN_FRAME, GLOBALMV }, { GOLDEN_FRAME, NEWMV },
+ { ALTREF_FRAME, NEARESTMV }, { ALTREF_FRAME, NEARMV },
+ { ALTREF_FRAME, GLOBALMV }, { ALTREF_FRAME, NEWMV },
+ { LAST2_FRAME, NEARESTMV }, { LAST2_FRAME, NEARMV },
+ { LAST2_FRAME, GLOBALMV }, { LAST2_FRAME, NEWMV },
+ { LAST3_FRAME, NEARESTMV }, { LAST3_FRAME, NEARMV },
+ { LAST3_FRAME, GLOBALMV }, { LAST3_FRAME, NEWMV },
+ { BWDREF_FRAME, NEARESTMV }, { BWDREF_FRAME, NEARMV },
+ { BWDREF_FRAME, GLOBALMV }, { BWDREF_FRAME, NEWMV },
+ { ALTREF2_FRAME, NEARESTMV }, { ALTREF2_FRAME, NEARMV },
+ { ALTREF2_FRAME, GLOBALMV }, { ALTREF2_FRAME, NEWMV },
+};
+
static const COMP_REF_MODE comp_ref_mode_set[NUM_COMP_INTER_MODES_RT] = {
{ { LAST_FRAME, GOLDEN_FRAME }, GLOBAL_GLOBALMV },
{ { LAST_FRAME, GOLDEN_FRAME }, NEAREST_NEARESTMV },
@@ -153,6 +172,20 @@
{ { LAST_FRAME, ALTREF_FRAME }, NEAREST_NEARESTMV },
};
+static const COMP_REF_MODE
+ comp_ref_mode_set_full[NUM_COMP_INTER_MODES_RT_FULL] = {
+ { { LAST_FRAME, GOLDEN_FRAME }, GLOBAL_GLOBALMV },
+ { { LAST_FRAME, GOLDEN_FRAME }, NEAREST_NEARESTMV },
+ { { LAST_FRAME, LAST2_FRAME }, GLOBAL_GLOBALMV },
+ { { LAST_FRAME, LAST2_FRAME }, NEAREST_NEARESTMV },
+ { { LAST_FRAME, ALTREF_FRAME }, GLOBAL_GLOBALMV },
+ { { LAST_FRAME, ALTREF_FRAME }, NEAREST_NEARESTMV },
+ { { LAST_FRAME, BWDREF_FRAME }, GLOBAL_GLOBALMV },
+ { { LAST_FRAME, BWDREF_FRAME }, NEAREST_NEARESTMV },
+ { { LAST_FRAME, ALTREF2_FRAME }, GLOBAL_GLOBALMV },
+ { { LAST_FRAME, ALTREF2_FRAME }, NEAREST_NEARESTMV },
+ };
+
static const int_interpfilters filters_ref_set[9] = {
[0].as_filters = { EIGHTTAP_REGULAR, EIGHTTAP_REGULAR },
[1].as_filters = { EIGHTTAP_SMOOTH, EIGHTTAP_SMOOTH },
@@ -466,7 +499,8 @@
&frame_mv[NEARESTMV][ref_frame], &frame_mv[NEARMV][ref_frame], 0);
frame_mv[GLOBALMV][ref_frame] = mbmi_ext->global_mvs[ref_frame];
// Early exit for non-LAST frame if force_skip_low_temp_var is set.
- if (!ref_is_scaled && bsize >= BLOCK_8X8 && !skip_pred_mv &&
+ if (!is_one_pass_rt_lag_params(cpi) && !ref_is_scaled &&
+ bsize >= BLOCK_8X8 && !skip_pred_mv &&
!(force_skip_low_temp_var && ref_frame != LAST_FRAME)) {
av1_mv_pred(cpi, x, yv12_mb[ref_frame][0].buf, yv12->y_stride, ref_frame,
bsize);
diff --git a/av1/encoder/nonrd_pickmode.c b/av1/encoder/nonrd_pickmode.c
index 72c82db..f201006 100644
--- a/av1/encoder/nonrd_pickmode.c
+++ b/av1/encoder/nonrd_pickmode.c
@@ -311,7 +311,8 @@
int_mv *this_ref_frm_newmv = &frame_mv[NEWMV][ref_frame];
unsigned int y_sad_zero;
if (ref_frame > LAST_FRAME && cpi->oxcf.rc_cfg.mode == AOM_CBR &&
- (cpi->ref_frame_flags & AOM_LAST_FLAG) && gf_temporal_ref) {
+ (cpi->ref_frame_flags & AOM_LAST_FLAG) && gf_temporal_ref &&
+ !is_one_pass_rt_lag_params(cpi)) {
int tmp_sad;
int dis;
@@ -371,7 +372,8 @@
const MACROBLOCKD *xd,
const ModeCosts *mode_costs,
int segment_id, BLOCK_SIZE bsize,
- unsigned int *ref_costs_single) {
+ unsigned int *ref_costs_single,
+ int is_one_pass_rt_lag) {
int seg_ref_active =
segfeature_active(&cm->seg, segment_id, SEG_LVL_REF_FRAME);
if (seg_ref_active) {
@@ -395,6 +397,18 @@
ref_costs_single[GOLDEN_FRAME] += mode_costs->single_ref_cost[0][1][0];
ref_costs_single[ALTREF_FRAME] += mode_costs->single_ref_cost[0][0][1];
ref_costs_single[ALTREF_FRAME] += mode_costs->single_ref_cost[0][2][0];
+ if (is_one_pass_rt_lag) {
+ ref_costs_single[ALTREF2_FRAME] = base_cost;
+ ref_costs_single[BWDREF_FRAME] = base_cost;
+ ref_costs_single[LAST2_FRAME] = base_cost;
+ ref_costs_single[LAST3_FRAME] = base_cost;
+ ref_costs_single[LAST2_FRAME] += mode_costs->single_ref_cost[0][0][0];
+ ref_costs_single[LAST3_FRAME] += mode_costs->single_ref_cost[0][0][0];
+ ref_costs_single[BWDREF_FRAME] += mode_costs->single_ref_cost[0][0][1];
+ ref_costs_single[BWDREF_FRAME] += mode_costs->single_ref_cost[0][1][0];
+ ref_costs_single[ALTREF2_FRAME] += mode_costs->single_ref_cost[0][0][1];
+ ref_costs_single[ALTREF2_FRAME] += mode_costs->single_ref_cost[0][2][0];
+ }
}
}
@@ -2213,14 +2227,12 @@
const int *use_ref_frame_mask, int comp_index,
bool comp_use_zero_zeromv_only, MV_REFERENCE_FRAME *last_comp_ref_frame,
BLOCK_SIZE bsize) {
- const MV_REFERENCE_FRAME *rf = comp_ref_mode_set[comp_index].ref_frame;
+ const MV_REFERENCE_FRAME *rf =
+ is_one_pass_rt_lag_params(cpi)
+ ? comp_ref_mode_set_full[comp_index].ref_frame
+ : comp_ref_mode_set[comp_index].ref_frame;
int skip_gf = 0;
int skip_alt = 0;
- *this_mode = comp_ref_mode_set[comp_index].pred_mode;
- *ref_frame = rf[0];
- *ref_frame2 = rf[1];
- assert(*ref_frame == LAST_FRAME);
- assert(*this_mode == GLOBAL_GLOBALMV || *this_mode == NEAREST_NEARESTMV);
if (x->source_variance < 50 && bsize > BLOCK_16X16) {
if (x->color_sensitivity_sb_g[COLOR_SENS_IDX(AOM_PLANE_U)] == 1 ||
x->color_sensitivity_sb_g[COLOR_SENS_IDX(AOM_PLANE_V)] == 1)
@@ -2352,7 +2364,8 @@
// Estimate cost for single reference frames
estimate_single_ref_frame_costs(cm, xd, mode_costs, segment_id, bsize,
- search_state->ref_costs_single);
+ search_state->ref_costs_single,
+ is_one_pass_rt_lag_params(cpi));
// Reset flag to indicate modes evaluated
av1_zero(search_state->mode_checked);
@@ -2388,9 +2401,17 @@
&search_state->use_scaled_ref_frame[LAST_FRAME]);
}
// Update mask to use all reference frame
- get_ref_frame_use_mask(cpi, x, mi, mi_row, mi_col, bsize, gf_temporal_ref,
- search_state->use_ref_frame_mask,
- force_skip_low_temp_var);
+ if (!is_one_pass_rt_lag_params(cpi)) {
+ get_ref_frame_use_mask(cpi, x, mi, mi_row, mi_col, bsize, gf_temporal_ref,
+ search_state->use_ref_frame_mask,
+ force_skip_low_temp_var);
+ } else {
+ for (MV_REFERENCE_FRAME ref_frame_iter = LAST_FRAME;
+ ref_frame_iter <= ALTREF_FRAME; ++ref_frame_iter) {
+ search_state->use_ref_frame_mask[ref_frame_iter] =
+ cpi->ref_frame_flags & (1 << (ref_frame_iter - 1));
+ }
+ }
skip_pred_mv = x->force_zeromv_skip_for_blk ||
(x->nonrd_prune_ref_frame_search > 2 &&
@@ -2431,6 +2452,15 @@
// for allowed compound modes, setup ref mv stack and reference frame.
if (idx >= num_inter_modes) {
const int comp_index = idx - num_inter_modes;
+ const COMP_REF_MODE *const comp_modes = is_one_pass_rt_lag_params(cpi)
+ ? comp_ref_mode_set_full
+ : comp_ref_mode_set;
+ const MV_REFERENCE_FRAME *rf = comp_modes[comp_index].ref_frame;
+ *this_mode = comp_modes[comp_index].pred_mode;
+ *ref_frame = rf[0];
+ *ref_frame2 = rf[1];
+ assert(*ref_frame == LAST_FRAME);
+ assert(*this_mode == GLOBAL_GLOBALMV || *this_mode == NEAREST_NEARESTMV);
if (!setup_compound_params_from_comp_idx(
cpi, x, search_state->yv12_mb, this_mode, ref_frame, ref_frame2,
search_state->frame_mv, search_state->use_ref_frame_mask,
@@ -2440,9 +2470,15 @@
}
*is_single_pred = 0;
} else {
- *this_mode = ref_mode_set[idx].pred_mode;
- *ref_frame = ref_mode_set[idx].ref_frame;
*ref_frame2 = NONE_FRAME;
+ const REF_MODE *const single_modes =
+ is_one_pass_rt_lag_params(cpi) ? ref_mode_set_full : ref_mode_set;
+ *this_mode = single_modes[idx].pred_mode;
+ *ref_frame = single_modes[idx].ref_frame;
+ }
+
+ if (is_one_pass_rt_lag_params(cpi) && cpi->rc.is_src_frame_alt_ref) {
+ if (*this_mode != GLOBALMV || *ref_frame != ALTREF_FRAME) return true;
}
if (cpi->sf.rt_sf.skip_newmv_mode_sad_screen && cpi->rc.high_source_sad &&
@@ -2521,6 +2557,7 @@
// Skip compound mode based on variance of previously evaluated single
// reference modes.
if (rt_sf->prune_compoundmode_with_singlemode_var && !*is_single_pred &&
+ !is_one_pass_rt_lag_params(cpi) &&
prune_compoundmode_with_singlemode_var(
*this_mode, *ref_frame, *ref_frame2, search_state->frame_mv,
search_state->mode_checked, search_state->vars,
@@ -2577,6 +2614,8 @@
return true;
}
+ if (is_one_pass_rt_lag_params(cpi)) return false;
+
// Skip mode based on block size, reference frame mode and other block
// properties.
if (skip_mode_by_bsize_and_ref_frame(
@@ -3243,7 +3282,8 @@
int best_early_term = 0;
int force_skip_low_temp_var = 0;
unsigned int sse_zeromv_norm = UINT_MAX;
- const int num_inter_modes = NUM_INTER_MODES;
+ const int num_inter_modes =
+ is_one_pass_rt_lag_params(cpi) ? NUM_INTER_MODES_FULL : NUM_INTER_MODES;
const REAL_TIME_SPEED_FEATURES *const rt_sf = &cpi->sf.rt_sf;
bool check_globalmv = rt_sf->check_globalmv_on_single_ref;
PRED_BUFFER tmp_buffer[4];
@@ -3274,7 +3314,9 @@
int_mv svc_mv = { .as_int = 0 };
int force_mv_inter_layer = 0;
bool comp_use_zero_zeromv_only = 0;
- int tot_num_comp_modes = NUM_COMP_INTER_MODES_RT;
+ int tot_num_comp_modes = is_one_pass_rt_lag_params(cpi)
+ ? NUM_COMP_INTER_MODES_RT_FULL
+ : NUM_COMP_INTER_MODES_RT;
#if CONFIG_AV1_TEMPORAL_DENOISING
const int denoise_recheck_zeromv = 1;
AV1_PICKMODE_CTX_DEN ctx_den;
@@ -3371,9 +3413,14 @@
tx_mode_to_biggest_tx_size[txfm_params->tx_mode_search_type]),
TX_16X16);
- fill_single_inter_mode_costs(search_state.single_inter_mode_costs,
- num_inter_modes, ref_mode_set, mode_costs,
- mbmi_ext->mode_context);
+ if (!is_one_pass_rt_lag_params(cpi))
+ fill_single_inter_mode_costs(search_state.single_inter_mode_costs,
+ num_inter_modes, ref_mode_set, mode_costs,
+ mbmi_ext->mode_context);
+ else
+ fill_single_inter_mode_costs(search_state.single_inter_mode_costs,
+ num_inter_modes, ref_mode_set_full, mode_costs,
+ mbmi_ext->mode_context);
MV_REFERENCE_FRAME last_comp_ref_frame = NONE_FRAME;
diff --git a/av1/encoder/pass2_strategy.c b/av1/encoder/pass2_strategy.c
index dac8758..a4b40ce 100644
--- a/av1/encoder/pass2_strategy.c
+++ b/av1/encoder/pass2_strategy.c
@@ -2190,13 +2190,9 @@
const GFConfig *const gf_cfg = &oxcf->gf_cfg;
int target;
- if (oxcf->q_cfg.aq_mode == CYCLIC_REFRESH_AQ) {
- av1_cyclic_refresh_set_golden_update(cpi);
- } else {
- p_rc->baseline_gf_interval = p_rc->gf_intervals[p_rc->cur_gf_index];
- rc->intervals_till_gf_calculate_due--;
- p_rc->cur_gf_index++;
- }
+ p_rc->baseline_gf_interval = p_rc->gf_intervals[p_rc->cur_gf_index];
+ rc->intervals_till_gf_calculate_due--;
+ p_rc->cur_gf_index++;
// correct frames_to_key when lookahead queue is flushing
correct_frames_to_key(cpi);
@@ -2208,7 +2204,13 @@
p_rc->constrained_gf_group =
(p_rc->baseline_gf_interval >= rc->frames_to_key) ? 1 : 0;
- gf_group->max_layer_depth_allowed = oxcf->gf_cfg.gf_max_pyr_height;
+ // Default for pyr_height if inputs not set.
+ if (oxcf->gf_cfg.gf_max_pyr_height == 0 ||
+ oxcf->gf_cfg.gf_min_pyr_height == 0) {
+ gf_group->max_layer_depth_allowed = 1;
+ } else {
+ gf_group->max_layer_depth_allowed = oxcf->gf_cfg.gf_max_pyr_height;
+ }
// Rare case when the look-ahead is less than the target GOP length, can't
// generate ARF frame.
@@ -3900,7 +3902,7 @@
p_rc->frames_till_regions_update = rest_frames;
int ret;
- if (cpi->ppi->lap_enabled) {
+ if (cpi->ppi->lap_enabled && !is_one_pass_rt_lag_params(cpi)) {
mark_flashes(twopass->stats_buf_ctx->stats_in_start,
twopass->stats_buf_ctx->stats_in_end);
estimate_noise(twopass->stats_buf_ctx->stats_in_start,
@@ -4021,6 +4023,13 @@
define_gf_group(cpi, frame_params, 0);
+ if (is_one_pass_rt_lag_params(cpi)) {
+ rc->frames_till_gf_update_due = p_rc->baseline_gf_interval;
+ frame_params->frame_type = gf_group->frame_type[cpi->gf_frame_index];
+ av1_setup_target_rate(cpi);
+ return;
+ }
+
if (gf_group->update_type[cpi->gf_frame_index] != ARF_UPDATE &&
rc->frames_since_key > 0)
process_first_pass_stats(cpi, &this_frame);
diff --git a/av1/encoder/ratectrl.c b/av1/encoder/ratectrl.c
index de2db3f..e043f6b 100644
--- a/av1/encoder/ratectrl.c
+++ b/av1/encoder/ratectrl.c
@@ -2747,7 +2747,7 @@
int av1_calc_pframe_target_size_one_pass_vbr(
const AV1_COMP *const cpi, FRAME_UPDATE_TYPE frame_update_type) {
- static const int af_ratio = 10;
+ const int af_ratio = is_one_pass_rt_lag_params(cpi) ? 6 : 10;
const RATE_CONTROL *const rc = &cpi->rc;
const PRIMARY_RATE_CONTROL *const p_rc = &cpi->ppi->p_rc;
int64_t target;
diff --git a/av1/encoder/speed_features.c b/av1/encoder/speed_features.c
index 446caf8..da5471c 100644
--- a/av1/encoder/speed_features.c
+++ b/av1/encoder/speed_features.c
@@ -1836,6 +1836,15 @@
// disable for now.
if (cpi->active_map.enabled)
sf->rt_sf.set_zeromv_skip_based_on_source_sad = 0;
+
+ if (is_one_pass_rt_lag_params(cpi)) {
+ sf->rt_sf.use_nonrd_altref_frame = 1;
+ // For non-zero lag: disable the 3 speed features below for now,
+ // until further testing.
+ sf->rt_sf.use_rtc_tf = 0;
+ sf->rt_sf.nonrd_check_partition_merge_mode = 0;
+ sf->rt_sf.nonrd_check_partition_split = 0;
+ }
}
static void set_rt_speed_features_framesize_independent(AV1_COMP *cpi,
@@ -1974,7 +1983,7 @@
sf->rt_sf.mode_search_skip_flags |= FLAG_SKIP_INTRA_DIRMISMATCH;
sf->rt_sf.num_inter_modes_for_tx_search = 5;
sf->rt_sf.prune_inter_modes_using_temp_var = 1;
- sf->rt_sf.use_real_time_ref_set = 1;
+ sf->rt_sf.use_real_time_ref_set = is_one_pass_rt_lag_params(cpi) ? 0 : 1;
sf->rt_sf.use_simple_rd_model = 1;
sf->rt_sf.prune_inter_modes_with_golden_ref = boosted ? 0 : 1;
// TODO(any): This sf could be removed.
@@ -2003,6 +2012,13 @@
sf->rt_sf.use_fast_fixed_part = 0;
sf->rt_sf.increase_source_sad_thresh = 0;
+ if (is_one_pass_rt_lag_params(cpi) && speed <= 6) {
+ sf->hl_sf.frame_parameter_update = 1;
+ sf->inter_sf.use_dist_wtd_comp_flag = 0;
+ sf->inter_sf.disable_masked_comp = 1;
+ sf->inter_sf.disable_onesided_comp = 1;
+ }
+
if (speed >= 6) {
sf->mv_sf.use_fullpel_costlist = 1;
diff --git a/test/datarate_test.cc b/test/datarate_test.cc
index c10c5c6..9f3fff8 100644
--- a/test/datarate_test.cc
+++ b/test/datarate_test.cc
@@ -355,6 +355,29 @@
RunBasicRateTargetingTestReversed(&video, bitrate_array[GET_PARAM(4)], 0.5,
1.5);
}
+
+ virtual void BasicRateTargetingVBRLagRealtime() {
+ ::libaom_test::I420VideoSource video("niklas_640_480_30.yuv", 320, 240, 30,
+ 1, 0, 200);
+ cfg_.rc_min_quantizer = 0;
+ cfg_.rc_max_quantizer = 63;
+ cfg_.g_error_resilient = 0;
+ cfg_.rc_end_usage = AOM_VBR;
+ cfg_.g_lag_in_frames = 48;
+ cfg_.g_pass = AOM_RC_ONE_PASS;
+ cfg_.g_usage = AOM_USAGE_REALTIME;
+ cfg_.g_profile = 0;
+ cfg_.g_timebase = video.timebase();
+ cfg_.g_threads = 1;
+
+ ResetModel();
+ lag_realtime_mode_ = 1;
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ ASSERT_GE(effective_datarate_, cfg_.rc_target_bitrate * 0.85)
+ << " The datarate for the file is lower than target by too much!";
+ ASSERT_LE(effective_datarate_, cfg_.rc_target_bitrate * 2.0)
+ << " The datarate for the file is greater than target by too much!";
+ }
};
// Params: test mode, speed, aq mode.
@@ -610,6 +633,10 @@
BasicRateTargetingCifCBRKf();
}
+TEST_P(DatarateTestRealtime, BasicRateTargetingVBRLagRealtime) {
+ BasicRateTargetingVBRLagRealtime();
+}
+
// Check that (1) the first dropped frame gets earlier and earlier
// as the drop frame threshold is increased, and (2) that the total number of
// frame drops does not decrease as we increase frame drop threshold.
diff --git a/test/datarate_test.h b/test/datarate_test.h
index 9741282..9b91cb4 100644
--- a/test/datarate_test.h
+++ b/test/datarate_test.h
@@ -69,6 +69,7 @@
effective_datarate_dynamic_[i] = 0.0;
}
avif_mode_ = 0;
+ lag_realtime_mode_ = 0;
}
void PreEncodeFrameHook(::libaom_test::VideoSource *video,
@@ -117,6 +118,12 @@
encoder->Control(AOME_SET_CQ_LEVEL, 0);
encoder->Control(AV1E_SET_AQ_MODE, (aq_mode_ > 0) ? 1 : 0);
}
+ if (lag_realtime_mode_) {
+ encoder->Control(AV1E_SET_MIN_GF_INTERVAL, 16);
+ encoder->Control(AV1E_SET_MAX_GF_INTERVAL, 16);
+ encoder->Control(AV1E_SET_GF_MAX_PYRAMID_HEIGHT, 1);
+ encoder->Control(AV1E_SET_GF_MIN_PYRAMID_HEIGHT, 1);
+ }
}
if (speed_change_test_) {
@@ -282,6 +289,7 @@
int64_t bits_total_dynamic_[3];
int frame_number_dynamic_[3];
int avif_mode_;
+ int lag_realtime_mode_;
};
} // namespace
diff --git a/test/encode_test_driver.cc b/test/encode_test_driver.cc
index 6ad10bd..6d42f4b 100644
--- a/test/encode_test_driver.cc
+++ b/test/encode_test_driver.cc
@@ -196,7 +196,7 @@
ASSERT_NO_FATAL_FAILURE(video->Begin());
encoder->InitEncoder(video);
- if (mode_ == kRealTime) {
+ if (mode_ == kRealTime && cfg_.g_lag_in_frames == 0) {
encoder->Control(AOME_SET_ENABLEAUTOALTREF, 0);
}