FPMT: Handle refresh logic for encode reorder
During encode reorder, added extra cases to correctly
handle the reference refresh logic.
Change-Id: I40da969f85e22e58c90ce2d272f2f496a03d45b2
diff --git a/av1/encoder/encode_strategy.c b/av1/encoder/encode_strategy.c
index ffed121..d6d9306 100644
--- a/av1/encoder/encode_strategy.c
+++ b/av1/encoder/encode_strategy.c
@@ -643,7 +643,12 @@
#if CONFIG_FRAME_PARALLEL_ENCODE
static int get_refresh_idx(RefFrameMapPair ref_frame_map_pairs[REF_FRAMES],
- int update_arf, int cur_frame_disp) {
+ int update_arf,
+#if CONFIG_FRAME_PARALLEL_ENCODE_2
+ GF_GROUP *gf_group, int gf_index,
+ int enable_refresh_skip,
+#endif // CONFIG_FRAME_PARALLEL_ENCODE_2
+ int cur_frame_disp) {
int arf_count = 0;
int oldest_arf_order = INT32_MAX;
int oldest_arf_idx = -1;
@@ -659,6 +664,22 @@
// Do not refresh a future frame.
if (frame_order > cur_frame_disp) continue;
+#if CONFIG_FRAME_PARALLEL_ENCODE_2
+ if (enable_refresh_skip) {
+ int skip_frame = 0;
+ // Prevent refreshing a frame in gf_group->skip_frame_refresh.
+ for (int i = 0; i < REF_FRAMES; i++) {
+ int frame_to_skip = gf_group->skip_frame_refresh[gf_index][i];
+ if (frame_to_skip == INVALID_IDX) break;
+ if (frame_order == frame_to_skip) {
+ skip_frame = 1;
+ break;
+ }
+ }
+ if (skip_frame) continue;
+ }
+#endif // CONFIG_FRAME_PARALLEL_ENCODE_2
+
// Keep track of the oldest level 1 frame if the current frame is also level
// 1.
if (reference_frame_level == 1) {
@@ -681,6 +702,12 @@
if (update_arf && arf_count > 2) return oldest_arf_idx;
if (oldest_idx >= 0) return oldest_idx;
if (oldest_arf_idx >= 0) return oldest_arf_idx;
+#if CONFIG_FRAME_PARALLEL_ENCODE_2
+ if (oldest_idx == -1) {
+ assert(arf_count > 2 && enable_refresh_skip);
+ return oldest_arf_idx;
+ }
+#endif // CONFIG_FRAME_PARALLEL_ENCODE_2
assert(0 && "No valid refresh index found");
return -1;
}
@@ -692,6 +719,9 @@
#if CONFIG_FRAME_PARALLEL_ENCODE
int cur_disp_order,
RefFrameMapPair ref_frame_map_pairs[REF_FRAMES],
+#if CONFIG_FRAME_PARALLEL_ENCODE_2
+ int gf_index,
+#endif // CONFIG_FRAME_PARALLEL_ENCODE_2
#endif // CONFIG_FRAME_PARALLEL_ENCODE
const RefBufferStack *const ref_buffer_stack) {
const AV1_COMMON *const cm = &cpi->common;
@@ -779,10 +809,16 @@
refresh_mask = 1 << free_fb_index;
return refresh_mask;
}
-
+#if CONFIG_FRAME_PARALLEL_ENCODE_2
+ const int enable_refresh_skip = !is_one_pass_rt_params(cpi);
+#endif // CONFIG_FRAME_PARALLEL_ENCODE_2
const int update_arf = frame_update_type == ARF_UPDATE;
const int refresh_idx =
- get_refresh_idx(ref_frame_map_pairs, update_arf, cur_disp_order);
+ get_refresh_idx(ref_frame_map_pairs, update_arf,
+#if CONFIG_FRAME_PARALLEL_ENCODE_2
+ &cpi->ppi->gf_group, gf_index, enable_refresh_skip,
+#endif // CONFIG_FRAME_PARALLEL_ENCODE_2
+ cur_disp_order);
return 1 << refresh_idx;
#else
switch (frame_update_type) {
@@ -1630,6 +1666,9 @@
av1_get_refresh_frame_flags(cpi, &frame_params, frame_update_type,
#if CONFIG_FRAME_PARALLEL_ENCODE
cur_frame_disp, ref_frame_map_pairs,
+#if CONFIG_FRAME_PARALLEL_ENCODE_2
+ cpi->gf_frame_index,
+#endif // CONFIG_FRAME_PARALLEL_ENCODE_2
#endif // CONFIG_FRAME_PARALLEL_ENCODE
&cpi->ref_buffer_stack);
diff --git a/av1/encoder/encode_strategy.h b/av1/encoder/encode_strategy.h
index ab6cbf6..2335fe5 100644
--- a/av1/encoder/encode_strategy.h
+++ b/av1/encoder/encode_strategy.h
@@ -73,6 +73,9 @@
#if CONFIG_FRAME_PARALLEL_ENCODE
int cur_disp_order,
RefFrameMapPair ref_frame_map_pairs[REF_FRAMES],
+#if CONFIG_FRAME_PARALLEL_ENCODE_2
+ int gf_index,
+#endif // CONFIG_FRAME_PARALLEL_ENCODE_2
#endif // CONFIG_FRAME_PARALLEL_ENCODE
const RefBufferStack *const ref_buffer_stack);
diff --git a/av1/encoder/firstpass.h b/av1/encoder/firstpass.h
index 1bd2253..d6efc09 100644
--- a/av1/encoder/firstpass.h
+++ b/av1/encoder/firstpass.h
@@ -218,6 +218,9 @@
#if CONFIG_FRAME_PARALLEL_ENCODE_2
// Stores the display order hint of each frame in the current GF_GROUP.
int display_idx[MAX_STATIC_GF_GROUP_LENGTH];
+ // Stores the display order hint of the frames not to be
+ // refreshed by the current frame.
+ int skip_frame_refresh[MAX_STATIC_GF_GROUP_LENGTH][REF_FRAMES];
#endif // CONFIG_FRAME_PARALLEL_ENCODE_2
#endif // CONFIG_FRAME_PARALLEL_ENCODE
/*!\endcond */
diff --git a/av1/encoder/gop_structure.c b/av1/encoder/gop_structure.c
index 3110b99..af53555 100644
--- a/av1/encoder/gop_structure.c
+++ b/av1/encoder/gop_structure.c
@@ -136,6 +136,13 @@
// layer to 2.
assert(gf_group->frame_parallel_level[(*frame_ind) - 1] == 1);
gf_group->frame_parallel_level[*frame_ind] = 2;
+ // Store the display order hints of the past 2 INTNL_ARF_UPDATE
+ // frames which would not have been displayed at the time of the encode
+ // of current frame.
+ gf_group->skip_frame_refresh[*frame_ind][0] =
+ gf_group->display_idx[(*frame_ind) - 1];
+ gf_group->skip_frame_refresh[*frame_ind][1] =
+ gf_group->display_idx[(*frame_ind) - 2];
}
}
// If max_parallel_frames is not exceeded, encode the next internal ARF
@@ -530,6 +537,12 @@
sizeof(gf_group->is_frame_non_ref[0]) * MAX_STATIC_GF_GROUP_LENGTH);
memset(gf_group->src_offset, 0,
sizeof(gf_group->src_offset[0]) * MAX_STATIC_GF_GROUP_LENGTH);
+#if CONFIG_FRAME_PARALLEL_ENCODE_2
+ // Initialize gf_group->skip_frame_refresh with INVALID_IDX.
+ memset(gf_group->skip_frame_refresh, INVALID_IDX,
+ sizeof(gf_group->skip_frame_refresh[0][0]) *
+ MAX_STATIC_GF_GROUP_LENGTH * REF_FRAMES);
+#endif // CONFIG_FRAME_PARALLEL_ENCODE_2
#endif
if (first_frame_update_type == KF_UPDATE &&
@@ -661,6 +674,22 @@
&count_arf_frames, doh_gf_index_map, ¶llel_frame_count,
&first_frame_index, &cur_disp_index, actual_gf_length, use_altref + 1,
cpi->ppi->num_fp_contexts);
+
+ // Set gf_group->skip_frame_refresh.
+ for (int i = 0; i < actual_gf_length; i++) {
+ int count = 0;
+ if (gf_group->update_type[i] == INTNL_ARF_UPDATE) {
+ for (int j = 0; j < i; j++) {
+ // Store the display order hint of the frames which would not
+ // have been displayed at the encode call of frame 'i'.
+ if ((gf_group->display_idx[j] < gf_group->display_idx[i]) &&
+ gf_group->update_type[j] == INTNL_ARF_UPDATE) {
+ gf_group->skip_frame_refresh[i][count++] =
+ gf_group->display_idx[j];
+ }
+ }
+ }
+ }
} else {
// Set layer depth threshold for reordering as per the gf length.
int depth_thr =
diff --git a/av1/encoder/tpl_model.c b/av1/encoder/tpl_model.c
index 5a84dad..0907e5f 100644
--- a/av1/encoder/tpl_model.c
+++ b/av1/encoder/tpl_model.c
@@ -1343,6 +1343,9 @@
av1_get_refresh_frame_flags(cpi, &frame_params, frame_update_type,
#if CONFIG_FRAME_PARALLEL_ENCODE
true_disp, ref_frame_map_pairs,
+#if CONFIG_FRAME_PARALLEL_ENCODE_2
+ gf_index,
+#endif // CONFIG_FRAME_PARALLEL_ENCODE_2
#endif // CONFIG_FRAME_PARALLEL_ENCODE
&ref_buffer_stack);
@@ -1434,6 +1437,9 @@
av1_get_refresh_frame_flags(cpi, &frame_params, frame_update_type,
#if CONFIG_FRAME_PARALLEL_ENCODE
true_disp, ref_frame_map_pairs,
+#if CONFIG_FRAME_PARALLEL_ENCODE_2
+ gf_index,
+#endif // CONFIG_FRAME_PARALLEL_ENCODE_2
#endif // CONFIG_FRAME_PARALLEL_ENCODE
&ref_buffer_stack);
int refresh_frame_map_index = av1_get_refresh_ref_frame_map(refresh_mask);