Filter noise variance in first pass stats.
This produces neutral results for standard test sets, but helps when
the input stats are not stable.
Change-Id: Id48ef7359c609849eb0b2e45c5565e7f5a741764
diff --git a/av1/encoder/pass2_strategy.c b/av1/encoder/pass2_strategy.c
index 1dd9721..0a80915 100644
--- a/av1/encoder/pass2_strategy.c
+++ b/av1/encoder/pass2_strategy.c
@@ -19,6 +19,7 @@
#include <stdint.h>
+#include "aom_mem/aom_mem.h"
#include "config/aom_config.h"
#include "config/aom_scale_rtcd.h"
@@ -3508,6 +3509,39 @@
}
}
+// Smooth-out the noise variance so it is more stable
+// TODO(bohanli): Use a better low-pass filter than averaging
+static void smooth_filter_noise(FIRSTPASS_STATS *first_stats,
+ FIRSTPASS_STATS *last_stats) {
+ int len = (int)(last_stats - first_stats);
+ double *smooth_noise = aom_malloc(len * sizeof(*smooth_noise));
+ if (!smooth_noise) return;
+
+ for (int i = 0; i < len; i++) {
+ double total_noise = 0;
+ double total_wt = 0;
+ for (int j = -HALF_FILT_LEN; j <= HALF_FILT_LEN; j++) {
+ int idx = AOMMIN(AOMMAX(i + j, 0), len - 1);
+ if (first_stats[idx].is_flash) continue;
+
+ total_noise += first_stats[idx].noise_var;
+ total_wt += 1.0;
+ }
+ if (total_wt > 0.01) {
+ total_noise /= total_wt;
+ } else {
+ total_noise = first_stats[i].noise_var;
+ }
+ smooth_noise[i] = total_noise;
+ }
+
+ for (int i = 0; i < len; i++) {
+ first_stats[i].noise_var = smooth_noise[i];
+ }
+
+ aom_free(smooth_noise);
+}
+
// Estimate the noise variance of each frame from the first pass stats
void av1_estimate_noise(FIRSTPASS_STATS *first_stats,
FIRSTPASS_STATS *last_stats) {
@@ -3595,6 +3629,8 @@
this_stats++) {
this_stats->noise_var = (first_stats + 2)->noise_var;
}
+
+ smooth_filter_noise(first_stats, last_stats);
}
// Estimate correlation coefficient of each frame with its previous frame.
diff --git a/test/ratectrl_qmode_test.cc b/test/ratectrl_qmode_test.cc
index fa0c19a..bcbab4b 100644
--- a/test/ratectrl_qmode_test.cc
+++ b/test/ratectrl_qmode_test.cc
@@ -1017,7 +1017,7 @@
std::back_inserter(gop_interval_list),
[](GopStruct const &x) { return x.show_frame_count; });
EXPECT_THAT(gop_interval_list,
- ElementsAre(21, 9, 30, 30, 16, 14, 21, 9, 30, 12, 16, 2, 30, 10));
+ ElementsAre(21, 9, 30, 30, 17, 13, 21, 9, 30, 12, 16, 2, 30, 10));
}
// TODO(b/242892473): Add a test which passes lookahead GOPs.