Extend selective_ref_frame sf to prune LAST2 ref frame
LAST2 reference frame is pruned based on the temporal
distance and first-pass stats.
Instruction Count BD-Rate Loss(%)
cpu-used Reduction(%) avg.psnr ovr.psnr ssim
6 2.739 0.1308 0.1272 0.0697
STATS_CHANGED for speed 6
Change-Id: I53a943a876da1e0c0bf76d26793a5acd2621e9c7
diff --git a/av1/encoder/encodeframe.c b/av1/encoder/encodeframe.c
index c121d27..c119924 100644
--- a/av1/encoder/encodeframe.c
+++ b/av1/encoder/encodeframe.c
@@ -1562,7 +1562,9 @@
}
av1_setup_frame_buf_refs(cm);
- enforce_max_ref_frames(cpi, &cpi->ref_frame_flags);
+ enforce_max_ref_frames(cpi, &cpi->ref_frame_flags,
+ cm->cur_frame->ref_display_order_hint,
+ cm->current_frame.display_order_hint);
set_rel_frame_dist(&cpi->common, &cpi->ref_frame_dist_info,
cpi->ref_frame_flags);
av1_setup_frame_sign_bias(cm);
diff --git a/av1/encoder/encodeframe_utils.h b/av1/encoder/encodeframe_utils.h
index 55318aa..d1146f5 100644
--- a/av1/encoder/encodeframe_utils.h
+++ b/av1/encoder/encodeframe_utils.h
@@ -320,6 +320,92 @@
const TileInfo *const tile_info, const int mi_row,
const int mi_col);
+// This function will compute the number of reference frames to be disabled
+// based on selective_ref_frame speed feature.
+static AOM_INLINE unsigned int get_num_refs_to_disable(
+ const AV1_COMP *cpi, const int *ref_frame_flags,
+ const unsigned int *ref_display_order_hint,
+ unsigned int cur_frame_display_index) {
+ unsigned int num_refs_to_disable = 0;
+ if (cpi->sf.inter_sf.selective_ref_frame >= 3) {
+ num_refs_to_disable++;
+ if (cpi->sf.inter_sf.selective_ref_frame >= 5 &&
+ *ref_frame_flags & av1_ref_frame_flag_list[LAST2_FRAME]) {
+ const OrderHintInfo *const order_hint_info =
+ &cpi->common.seq_params.order_hint_info;
+ const int last2_frame_dist = av1_encoder_get_relative_dist(
+ order_hint_info, ref_display_order_hint[LAST2_FRAME - LAST_FRAME],
+ cur_frame_display_index);
+ // Disable LAST2_FRAME if it is a temporally distant frame
+ if (abs(last2_frame_dist) > 2) {
+ num_refs_to_disable++;
+ }
+#if !CONFIG_REALTIME_ONLY
+ else if (is_stat_consumption_stage_twopass(cpi)) {
+ const FIRSTPASS_STATS *const this_frame_stats =
+ read_one_frame_stats(&cpi->twopass, cur_frame_display_index);
+ const double coded_error_per_mb =
+ this_frame_stats->coded_error / cpi->frame_info.num_mbs;
+ // Disable LAST2_FRAME if the coded error of the current frame based on
+ // first pass stats is very low.
+ if (coded_error_per_mb < 100.0) num_refs_to_disable++;
+ }
+#endif // CONFIG_REALTIME_ONLY
+ }
+ }
+ return num_refs_to_disable;
+}
+
+static INLINE int get_max_allowed_ref_frames(
+ const AV1_COMP *cpi, const int *ref_frame_flags,
+ const unsigned int *ref_display_order_hint,
+ unsigned int cur_frame_display_index) {
+ const unsigned int max_reference_frames =
+ cpi->oxcf.ref_frm_cfg.max_reference_frames;
+ const unsigned int num_refs_to_disable = get_num_refs_to_disable(
+ cpi, ref_frame_flags, ref_display_order_hint, cur_frame_display_index);
+ const unsigned int max_allowed_refs_for_given_speed =
+ INTER_REFS_PER_FRAME - num_refs_to_disable;
+ return AOMMIN(max_allowed_refs_for_given_speed, max_reference_frames);
+}
+
+// Enforce the number of references for each arbitrary frame based on user
+// options and speed.
+static AOM_INLINE void enforce_max_ref_frames(
+ AV1_COMP *cpi, int *ref_frame_flags,
+ const unsigned int *ref_display_order_hint,
+ unsigned int cur_frame_display_index) {
+ MV_REFERENCE_FRAME ref_frame;
+ int total_valid_refs = 0;
+
+ for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) {
+ if (*ref_frame_flags & av1_ref_frame_flag_list[ref_frame]) {
+ total_valid_refs++;
+ }
+ }
+
+ const int max_allowed_refs = get_max_allowed_ref_frames(
+ cpi, ref_frame_flags, ref_display_order_hint, cur_frame_display_index);
+
+ for (int i = 0; i < 4 && total_valid_refs > max_allowed_refs; ++i) {
+ const MV_REFERENCE_FRAME ref_frame_to_disable = disable_order[i];
+
+ if (!(*ref_frame_flags & av1_ref_frame_flag_list[ref_frame_to_disable])) {
+ continue;
+ }
+
+ switch (ref_frame_to_disable) {
+ case LAST3_FRAME: *ref_frame_flags &= ~AOM_LAST3_FLAG; break;
+ case LAST2_FRAME: *ref_frame_flags &= ~AOM_LAST2_FLAG; break;
+ case ALTREF2_FRAME: *ref_frame_flags &= ~AOM_ALT2_FLAG; break;
+ case GOLDEN_FRAME: *ref_frame_flags &= ~AOM_GOLD_FLAG; break;
+ default: assert(0);
+ }
+ --total_valid_refs;
+ }
+ assert(total_valid_refs <= max_allowed_refs);
+}
+
#ifdef __cplusplus
} // extern "C"
#endif
diff --git a/av1/encoder/encoder.h b/av1/encoder/encoder.h
index da11708..e1d0142 100644
--- a/av1/encoder/encoder.h
+++ b/av1/encoder/encoder.h
@@ -3050,14 +3050,6 @@
GOLDEN_FRAME,
};
-static INLINE int get_max_allowed_ref_frames(
- int selective_ref_frame, unsigned int max_reference_frames) {
- const unsigned int max_allowed_refs_for_given_speed =
- (selective_ref_frame >= 3) ? INTER_REFS_PER_FRAME - 1
- : INTER_REFS_PER_FRAME;
- return AOMMIN(max_allowed_refs_for_given_speed, max_reference_frames);
-}
-
static const MV_REFERENCE_FRAME
ref_frame_priority_order[INTER_REFS_PER_FRAME] = {
LAST_FRAME, ALTREF_FRAME, BWDREF_FRAME, GOLDEN_FRAME,
@@ -3092,42 +3084,6 @@
return flags;
}
-// Enforce the number of references for each arbitrary frame based on user
-// options and speed.
-static AOM_INLINE void enforce_max_ref_frames(AV1_COMP *cpi,
- int *ref_frame_flags) {
- MV_REFERENCE_FRAME ref_frame;
- int total_valid_refs = 0;
-
- for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) {
- if (*ref_frame_flags & av1_ref_frame_flag_list[ref_frame]) {
- total_valid_refs++;
- }
- }
-
- const int max_allowed_refs =
- get_max_allowed_ref_frames(cpi->sf.inter_sf.selective_ref_frame,
- cpi->oxcf.ref_frm_cfg.max_reference_frames);
-
- for (int i = 0; i < 4 && total_valid_refs > max_allowed_refs; ++i) {
- const MV_REFERENCE_FRAME ref_frame_to_disable = disable_order[i];
-
- if (!(*ref_frame_flags & av1_ref_frame_flag_list[ref_frame_to_disable])) {
- continue;
- }
-
- switch (ref_frame_to_disable) {
- case LAST3_FRAME: *ref_frame_flags &= ~AOM_LAST3_FLAG; break;
- case LAST2_FRAME: *ref_frame_flags &= ~AOM_LAST2_FLAG; break;
- case ALTREF2_FRAME: *ref_frame_flags &= ~AOM_ALT2_FLAG; break;
- case GOLDEN_FRAME: *ref_frame_flags &= ~AOM_GOLD_FLAG; break;
- default: assert(0);
- }
- --total_valid_refs;
- }
- assert(total_valid_refs <= max_allowed_refs);
-}
-
// Returns a Sequence Header OBU stored in an aom_fixed_buf_t, or NULL upon
// failure. When a non-NULL aom_fixed_buf_t pointer is returned by this
// function, the memory must be freed by the caller. Both the buf member of the
diff --git a/av1/encoder/speed_features.c b/av1/encoder/speed_features.c
index 52fd85b..8e6dc70 100644
--- a/av1/encoder/speed_features.c
+++ b/av1/encoder/speed_features.c
@@ -681,6 +681,7 @@
if (speed >= 6) {
sf->inter_sf.prune_inter_modes_based_on_tpl = boosted ? 0 : 3;
sf->inter_sf.prune_nearmv_using_neighbors = 1;
+ sf->inter_sf.selective_ref_frame = 5;
sf->part_sf.prune_rectangular_split_based_on_qidx =
boosted || allow_screen_content_tools ? 0 : 1;
diff --git a/av1/encoder/speed_features.h b/av1/encoder/speed_features.h
index f3425b3..04df3d8 100644
--- a/av1/encoder/speed_features.h
+++ b/av1/encoder/speed_features.h
@@ -581,8 +581,8 @@
int prune_inter_modes_if_skippable;
// Drop less likely to be picked reference frames in the RD search.
- // Has five levels for now: 0, 1, 2, 3 and 4, where higher levels prune more
- // aggressively than lower ones. (0 means no pruning).
+ // Has six levels for now: 0, 1, 2, 3, 4 and 5, where higher levels prune
+ // more aggressively than lower ones. (0 means no pruning).
int selective_ref_frame;
// Prune reference frames for rectangular partitions.
diff --git a/av1/encoder/tpl_model.c b/av1/encoder/tpl_model.c
index aa6fa6a..b72ee68 100644
--- a/av1/encoder/tpl_model.c
+++ b/av1/encoder/tpl_model.c
@@ -26,6 +26,7 @@
#include "av1/encoder/encoder.h"
#include "av1/encoder/ethread.h"
+#include "av1/encoder/encodeframe_utils.h"
#include "av1/encoder/encode_strategy.h"
#include "av1/encoder/hybrid_fwd_txfm.h"
#include "av1/encoder/rd.h"
@@ -800,7 +801,8 @@
ref_frame_flags = get_ref_frame_flags(&cpi->sf, ref_frames_ordered,
cpi->ext_flags.ref_frame_flags);
- enforce_max_ref_frames(cpi, &ref_frame_flags);
+ enforce_max_ref_frames(cpi, &ref_frame_flags, ref_frame_display_indices,
+ tpl_frame->frame_display_index);
// Prune reference frames
for (idx = 0; idx < INTER_REFS_PER_FRAME; ++idx) {