Adjust level based reference mapping
This will avoid mapping golden and altref based on their level if
all reference frames are at the same level. This fixes a performance
drop with low delay and ld subgop configs.
STATS_CHANGED
Change-Id: I7efe7492d21eddd8c4fe2152f23fb79729c2e1be
diff --git a/av1/encoder/encode_strategy.c b/av1/encoder/encode_strategy.c
index a70e17b..f5550fa 100644
--- a/av1/encoder/encode_strategy.c
+++ b/av1/encoder/encode_strategy.c
@@ -1271,6 +1271,10 @@
ref->used = 1;
}
+// Threshold dictating when we are allowed to start considering
+// leaving lowest level frames unmapped
+#define LOW_LEVEL_FRAMES_TR 5
+
// Find which reference buffer should be left out of the named mapping.
// This is because there are 8 reference buffers and only 7 named slots.
static void set_unmapped_ref(RefBufMapData *buffer_map, int n_bufs,
@@ -1281,7 +1285,8 @@
if (n_bufs <= ALTREF_FRAME) return;
for (int i = 0; i < n_bufs; i++) {
if (buffer_map[i].used) continue;
- if (buffer_map[i].pyr_level != min_level || n_bufs == n_min_level_refs) {
+ if (buffer_map[i].pyr_level != min_level ||
+ n_min_level_refs >= LOW_LEVEL_FRAMES_TR) {
int dist = abs(cur_frame_disp - buffer_map[i].disp_order);
if (dist > max_dist) {
max_dist = dist;
@@ -1338,6 +1343,8 @@
int n_min_level_refs = 0;
int n_past_high_level = 0;
int closest_past_ref = -1;
+ int golden_idx = -1;
+ int altref_idx = -1;
// Find the GOLDEN_FRAME and BWDREF_FRAME.
// Also collect various stats about the reference frames for the remaining
@@ -1346,10 +1353,15 @@
if (buffer_map[i].pyr_level == min_level) {
// Keep track of the number of lowest level frames
n_min_level_refs++;
- if (buffer_map[i].disp_order < cur_frame_disp &&
+ if (buffer_map[i].disp_order < cur_frame_disp && golden_idx == -1 &&
remapped_ref_idx[GOLDEN_FRAME - LAST_FRAME] == INVALID_IDX) {
- // Map the GOLDEN_FRAME
- add_ref_to_slot(&buffer_map[i], remapped_ref_idx, GOLDEN_FRAME);
+ // Save index for GOLDEN
+ golden_idx = i;
+ } else if (buffer_map[i].disp_order > cur_frame_disp &&
+ altref_idx == -1 &&
+ remapped_ref_idx[ALTREF_FRAME - LAST_FRAME] == INVALID_IDX) {
+ // Save index for ALTREF
+ altref_idx = i;
}
} else if (buffer_map[i].disp_order == cur_frame_disp) {
// Map the BWDREF_FRAME if this is the show_existing_frame
@@ -1367,6 +1379,17 @@
closest_past_ref = i;
}
+ // Do not map GOLDEN and ALTREF based on their pyramid level if all reference
+ // frames have the same level
+ if (n_min_level_refs < n_bufs) {
+ // Map the GOLDEN_FRAME
+ if (golden_idx > -1)
+ add_ref_to_slot(&buffer_map[golden_idx], remapped_ref_idx, GOLDEN_FRAME);
+ // Map the ALTREF_FRAME
+ if (altref_idx > -1)
+ add_ref_to_slot(&buffer_map[altref_idx], remapped_ref_idx, ALTREF_FRAME);
+ }
+
// Find the buffer to be excluded from the mapping
set_unmapped_ref(buffer_map, n_bufs, n_min_level_refs, min_level,
cur_frame_disp);
@@ -1385,21 +1408,6 @@
}
}
- // Assign low level frames
- buf_map_idx = n_bufs - 1;
- for (int frame = ALTREF_FRAME; frame >= LAST_FRAME; frame--) {
- // Continue if the current ref slot is already full
- if (remapped_ref_idx[frame - LAST_FRAME] != INVALID_IDX) continue;
- // Find the next unmapped low level reference buffer
- for (; buf_map_idx >= 0; buf_map_idx--) {
- if (buffer_map[buf_map_idx].pyr_level != min_level) continue;
- if (!buffer_map[buf_map_idx].used) break;
- }
- if (buf_map_idx < 0) break;
- if (buffer_map[buf_map_idx].used) break;
- add_ref_to_slot(&buffer_map[buf_map_idx], remapped_ref_idx, frame);
- }
-
// Place remaining past frames
buf_map_idx = closest_past_ref;
for (int frame = LAST_FRAME; frame < REF_FRAMES; frame++) {
@@ -1436,12 +1444,8 @@
void av1_get_ref_frames(AV1_COMP *const cpi, RefBufferStack *ref_buffer_stack,
int cur_frame_disp,
RefFrameMapPair ref_frame_map_pairs[REF_FRAMES]) {
- // TODO(sarahparker) Enable this for low delay once the performance drop is
- // addressed
- if (cpi->oxcf.gf_cfg.lag_in_frames > 0) {
- get_ref_frames_subgop(cpi, cur_frame_disp, ref_frame_map_pairs);
- return;
- }
+ get_ref_frames_subgop(cpi, cur_frame_disp, ref_frame_map_pairs);
+ return;
// TODO(sarahparker) Delete this all with stack deletion
AV1_COMMON *cm = &cpi->common;