Speed up the interpolation filter search
If we can find a good match, skip the interpolation filter search. This
is added at speed 4.
Midres set borg test result:
avg_psnr: ovr_psnr: ssim:
0.071 0.077 0.080
Observed 1% - 3% encoder speedups.
STATS_CHANGED
Change-Id: Ic4e3b0ff7691e73bcba92bb3aafb21fc838138d3
diff --git a/av1/encoder/rdopt.c b/av1/encoder/rdopt.c
index d482839..126a00a 100644
--- a/av1/encoder/rdopt.c
+++ b/av1/encoder/rdopt.c
@@ -8926,8 +8926,8 @@
}
// check if there is saved result match with this search
-static INLINE int is_interp_filter_match(const INTERPOLATION_FILTER_STATS *st,
- MB_MODE_INFO *const mi) {
+static INLINE int is_interp_filter_exact_match(
+ const INTERPOLATION_FILTER_STATS *st, MB_MODE_INFO *const mi) {
for (int i = 0; i < 2; ++i) {
if ((st->ref_frames[i] != mi->ref_frame[i]) ||
(st->mv[i].as_int != mi->mv[i].as_int)) {
@@ -8939,6 +8939,27 @@
return 1;
}
+// return mv_diff
+static INLINE int is_interp_filter_good_match(
+ const INTERPOLATION_FILTER_STATS *st, MB_MODE_INFO *const mi) {
+ const int is_comp = has_second_ref(mi);
+ int i;
+
+ for (i = 0; i < 1 + is_comp; ++i) {
+ if (st->ref_frames[i] != mi->ref_frame[i]) return -1;
+ }
+
+ const int thr = is_comp ? 7 : 3;
+ int mv_diff = 0;
+ for (i = 0; i < 1 + is_comp; ++i) {
+ mv_diff += abs(st->mv[i].as_mv.row - mi->mv[i].as_mv.row) +
+ abs(st->mv[i].as_mv.col - mi->mv[i].as_mv.col);
+ }
+ if (mv_diff > thr) return -1;
+
+ return mv_diff;
+}
+
// Checks if characteristics of search match
static INLINE int is_comp_rd_match(const AV1_COMP *const cpi,
const MACROBLOCK *const x,
@@ -8987,12 +9008,35 @@
static INLINE int find_interp_filter_in_stats(
MB_MODE_INFO *const mbmi, INTERPOLATION_FILTER_STATS *interp_filter_stats,
- int interp_filter_stats_idx) {
- for (int j = 0; j < interp_filter_stats_idx; ++j) {
- const INTERPOLATION_FILTER_STATS *st = &interp_filter_stats[j];
- if (is_interp_filter_match(st, mbmi)) {
- mbmi->interp_filters = st->filters;
- return j;
+ int interp_filter_stats_idx, int skip_level) {
+ if (skip_level < 2) {
+ // Find exact match.
+ // TODO(yunqing): Use a small threshold instead. Combine this with finding
+ // good enough match.
+ for (int j = 0; j < interp_filter_stats_idx; ++j) {
+ const INTERPOLATION_FILTER_STATS *st = &interp_filter_stats[j];
+ if (is_interp_filter_exact_match(st, mbmi)) {
+ mbmi->interp_filters = st->filters;
+ return j;
+ }
+ }
+ } else {
+ // Find good enough match.
+ // TODO(yunqing): Separate single-ref mode and comp mode stats for fast
+ // search.
+ int best = INT_MAX;
+ int match = -1;
+ for (int j = 0; j < interp_filter_stats_idx; ++j) {
+ const INTERPOLATION_FILTER_STATS *st = &interp_filter_stats[j];
+ const int mv_diff = is_interp_filter_good_match(st, mbmi);
+ if (mv_diff != -1 && mv_diff < best) {
+ best = mv_diff;
+ match = j;
+ }
+ }
+ if (match != -1) {
+ mbmi->interp_filters = interp_filter_stats[match].filters;
+ return match;
}
}
return -1; // no match result found
@@ -9067,8 +9111,9 @@
int interp_filter_stats_idx) {
int match_found_idx = -1;
if (cpi->sf.skip_repeat_interpolation_filter_search && need_search)
- match_found_idx = find_interp_filter_in_stats(mbmi, interp_filter_stats,
- interp_filter_stats_idx);
+ match_found_idx = find_interp_filter_in_stats(
+ mbmi, interp_filter_stats, interp_filter_stats_idx,
+ cpi->sf.skip_repeat_interpolation_filter_search);
if (!need_search || match_found_idx == -1)
set_default_interp_filters(mbmi, assign_filter);
diff --git a/av1/encoder/speed_features.c b/av1/encoder/speed_features.c
index 1339bc1..f90aa64 100644
--- a/av1/encoder/speed_features.c
+++ b/av1/encoder/speed_features.c
@@ -462,6 +462,7 @@
// sf->tx_domain_dist_level = 2;
sf->tx_domain_dist_thres_level = 2;
sf->simple_motion_search_prune_agg = 2;
+ sf->skip_repeat_interpolation_filter_search = 2;
}
}