rtc: Fixes to the reference structure
On a GF update (that is not key frame), refbuf_state should
be explicitly set to REFBUF_UPDATE, otherwise it will keep
the value of REFBUF_RESET on the GF udpate, which will also
refresh the moving ARF reference. This was not the intended
behavior for rtc. The REFBUF states were introduced in this CL:
https://aomedia-review.googlesource.com/c/aom/+/117788
so this issue has existed since then.
Also fix to avoid removing golden as reference in
get_ref_frame_flags(). The logic there was conditioned on
the nord_pickmode speeed feature, so for speed 5 and 6 the
golden could be removed as a reference. Fix is to condition it
on the rtc mode.
avg. bdrate gains on speed 7/8/9 rtc set: 1.8/1.78/0.7
Small speed slowdown ~1-2% observed on vga for speed >= 7.
For speed 6: bdrate gain ~4.3% but bigger slowdown, ~10%,
since GF is enabled as a reference with this change.
To avoid this, added speed feature to enable/disable golden ref
in pickmode, and disabled it for speed 5/6, so keep the same
behavior for now and avoid the ~10% slowdown.
bdrate gain for speed 6 with gf-ref speed feature off is 1.6%.
Change-Id: I1c44004efb59c604f82231a882dc005cdb70999c
diff --git a/av1/encoder/encode_strategy.c b/av1/encoder/encode_strategy.c
index 1d89a72..123ce56 100644
--- a/av1/encoder/encode_strategy.c
+++ b/av1/encoder/encode_strategy.c
@@ -1716,8 +1716,9 @@
}
// Work out which reference frame slots may be used.
- frame_params.ref_frame_flags = get_ref_frame_flags(
- &cpi->sf, ref_frame_buf, ext_flags->ref_frame_flags);
+ frame_params.ref_frame_flags =
+ get_ref_frame_flags(&cpi->sf, is_one_pass_rt_params(cpi), ref_frame_buf,
+ ext_flags->ref_frame_flags);
#if CONFIG_FRAME_PARALLEL_ENCODE
// Set primary_ref_frame of non-reference frames as PRIMARY_REF_NONE.
diff --git a/av1/encoder/encoder.h b/av1/encoder/encoder.h
index 059bb55..12d2c26 100644
--- a/av1/encoder/encoder.h
+++ b/av1/encoder/encoder.h
@@ -3691,6 +3691,7 @@
};
static INLINE int get_ref_frame_flags(const SPEED_FEATURES *const sf,
+ const int use_one_pass_rt_params,
const YV12_BUFFER_CONFIG **ref_frames,
const int ext_ref_frame_flags) {
// cpi->ext_flags.ref_frame_flags allows certain reference types to be
@@ -3702,12 +3703,12 @@
for (int i = 1; i < INTER_REFS_PER_FRAME; ++i) {
const YV12_BUFFER_CONFIG *const this_ref = ref_frames[i];
// If this_ref has appeared before, mark the corresponding ref frame as
- // invalid. For nonrd mode, only disable GOLDEN_FRAME if it's the same
- // as LAST_FRAME or ALTREF_FRAME (if ALTREF is being used in nonrd).
- int index = (sf->rt_sf.use_nonrd_pick_mode &&
- ref_frame_priority_order[i] == GOLDEN_FRAME)
- ? (1 + sf->rt_sf.use_nonrd_altref_frame)
- : i;
+ // invalid. For one_pass_rt mode, only disable GOLDEN_FRAME if it's the
+ // same as LAST_FRAME or ALTREF_FRAME (if ALTREF is being used in nonrd).
+ int index =
+ (use_one_pass_rt_params && ref_frame_priority_order[i] == GOLDEN_FRAME)
+ ? (1 + sf->rt_sf.use_nonrd_altref_frame)
+ : i;
for (int j = 0; j < index; ++j) {
if (this_ref == ref_frames[j]) {
flags &= ~(1 << (ref_frame_priority_order[i] - 1));
diff --git a/av1/encoder/ratectrl.c b/av1/encoder/ratectrl.c
index 667c0bd..da31d50 100644
--- a/av1/encoder/ratectrl.c
+++ b/av1/encoder/ratectrl.c
@@ -2525,10 +2525,11 @@
ext_refresh_frame_flags->alt_ref_frame = 0;
for (int i = 0; i < INTER_REFS_PER_FRAME; ++i) svc->ref_idx[i] = 7;
for (int i = 0; i < REF_FRAMES; ++i) svc->refresh[i] = 0;
- // Always reference LAST, GOLDEN, ALTREF
+ // Set the reference frame flags.
ext_flags->ref_frame_flags ^= AOM_LAST_FLAG;
- ext_flags->ref_frame_flags ^= AOM_GOLD_FLAG;
ext_flags->ref_frame_flags ^= AOM_ALT_FLAG;
+ if (cpi->sf.rt_sf.use_golden_frame)
+ ext_flags->ref_frame_flags ^= AOM_GOLD_FLAG;
if (cpi->sf.rt_sf.ref_frame_comp_nonrd == 1)
ext_flags->ref_frame_flags ^= AOM_LAST2_FLAG;
const int sh = 7 - gld_fixed_slot;
@@ -2743,6 +2744,8 @@
gf_group->size = p_rc->baseline_gf_interval;
gf_group->update_type[0] =
(frame_type == KEY_FRAME) ? KF_UPDATE : GF_UPDATE;
+ gf_group->refbuf_state[cpi->gf_frame_index] =
+ (frame_type == KEY_FRAME) ? REFBUF_RESET : REFBUF_UPDATE;
gf_update = 1;
}
return gf_update;
diff --git a/av1/encoder/speed_features.c b/av1/encoder/speed_features.c
index f747f96..8d8c270 100644
--- a/av1/encoder/speed_features.c
+++ b/av1/encoder/speed_features.c
@@ -1386,6 +1386,7 @@
if (cpi->oxcf.kf_cfg.key_freq_max != 0 &&
cm->width * cm->height > 640 * 480)
sf->rt_sf.use_temporal_noise_estimate = 1;
+ sf->rt_sf.use_golden_frame = 0;
}
if (speed >= 6) {
@@ -1393,6 +1394,7 @@
}
if (speed >= 7) {
+ sf->rt_sf.use_golden_frame = 1;
sf->part_sf.default_max_partition_size = BLOCK_128X128;
sf->part_sf.default_min_partition_size = BLOCK_8X8;
sf->part_sf.partition_search_type = VAR_BASED_PARTITION;
diff --git a/av1/encoder/speed_features.h b/av1/encoder/speed_features.h
index e30b459..af018f1 100644
--- a/av1/encoder/speed_features.h
+++ b/av1/encoder/speed_features.h
@@ -1191,6 +1191,9 @@
// Use ALTREF frame in non-RD mode decision.
int use_nonrd_altref_frame;
+ // Use GOLDEN frame in pickmode decision.
+ int use_golden_frame;
+
// Use compound reference for non-RD mode.
int use_comp_ref_nonrd;
diff --git a/av1/encoder/tpl_model.c b/av1/encoder/tpl_model.c
index dde49af..4874509 100644
--- a/av1/encoder/tpl_model.c
+++ b/av1/encoder/tpl_model.c
@@ -1095,8 +1095,9 @@
}
// Work out which reference frame slots may be used.
- ref_frame_flags = get_ref_frame_flags(&cpi->sf, ref_frames_ordered,
- cpi->ext_flags.ref_frame_flags);
+ ref_frame_flags =
+ get_ref_frame_flags(&cpi->sf, is_one_pass_rt_params(cpi),
+ ref_frames_ordered, cpi->ext_flags.ref_frame_flags);
enforce_max_ref_frames(cpi, &ref_frame_flags, ref_frame_display_indices,
tpl_frame->frame_display_index);