Commit 20e8e3df1b for aom
commit 20e8e3df1b70c6c373f37770089145ac6045b471
Author: Cheng Chen <chengchen@google.com>
Date: Mon Apr 27 11:45:51 2026 -0700
Fix NaN and divided by zero issues in film grain
Also clamp the error to avoid error drifting.
BUG=aomedia:503810640
Change-Id: Idaf1eeb2f8ce435c7feb17c5c86a4fdca15c2b69
diff --git a/aom_dsp/noise_model.c b/aom_dsp/noise_model.c
index aa8e6218db..562252b3bb 100644
--- a/aom_dsp/noise_model.c
+++ b/aom_dsp/noise_model.c
@@ -144,6 +144,11 @@ static int equation_system_solve(aom_equation_system_t *eqns) {
if (ret == 0) {
return 0;
}
+ for (int i = 0; i < n; ++i) {
+ if (isnan((float)eqns->x[i])) {
+ return 0;
+ }
+ }
return 1;
}
@@ -482,7 +487,8 @@ int aom_flat_block_finder_init(aom_flat_block_finder_t *block_finder,
for (i = 0; i < kLowPolyNumParams; ++i) {
memset(eqns.b, 0, sizeof(*eqns.b) * kLowPolyNumParams);
eqns.b[i] = 1;
- equation_system_solve(&eqns);
+ const int ret = equation_system_solve(&eqns);
+ if (!ret) return ret;
for (j = 0; j < kLowPolyNumParams; ++j) {
AtA_inv[j * kLowPolyNumParams + i] = eqns.x[j];
@@ -1259,7 +1265,10 @@ int aom_noise_model_get_grain_parameters(aom_noise_model_t *const noise_model,
if (c == 0) {
avg_luma_strength = average_strength;
} else {
- y_corr[c - 1] = avg_luma_strength * eqns->x[n_coeff] / average_strength;
+ y_corr[c - 1] =
+ average_strength > 1e-6
+ ? avg_luma_strength * eqns->x[n_coeff] / average_strength
+ : 0;
max_coeff = AOMMAX(max_coeff, y_corr[c - 1]);
min_coeff = AOMMIN(min_coeff, y_corr[c - 1]);
}
@@ -1336,8 +1345,11 @@ static float *get_half_cos_window(int block_size) {
INT_TYPE new_val = (INT_TYPE)AOMMIN( \
AOMMAX(result[result_idx] * block_normalization + 0.5f, 0), \
block_normalization); \
- const float err = \
+ float err = \
-(((float)new_val) / block_normalization - result[result_idx]); \
+ if (fabsf(err) < 1e-6f) { \
+ err = 0.0f; \
+ } \
denoised[y * stride + x] = new_val; \
if (x + 1 < (w >> chroma_sub_w)) { \
result[result_idx + 1] += err * 7.0f / 16.0f; \
diff --git a/test/encode_api_test.cc b/test/encode_api_test.cc
index 858c3a444d..19bedc657a 100644
--- a/test/encode_api_test.cc
+++ b/test/encode_api_test.cc
@@ -49,12 +49,28 @@ static void *Memset16(void *dest, int val, size_t length) {
}
static void FillImage(aom_image_t *img, uint8_t val) {
+ for (int p = 0; p < 3; ++p) {
+ uint8_t *buf = img->planes[p];
+ const int w = aom_img_plane_width(img, p);
+ const int h = aom_img_plane_height(img, p);
+ for (int r = 0; r < h; ++r) {
+ memset(buf, val, w);
+ buf += img->stride[p];
+ }
+ }
+}
+
+static void FillImageRandom(aom_image_t *img) {
+ ::libaom_test::ACMRandom rnd;
+ rnd.Reset(::libaom_test::ACMRandom::DeterministicSeed());
for (int p = 0; p < 3; ++p) {
uint8_t *buf = img->planes[p];
const int h = p == 0 ? (int)img->d_h : (int)((img->d_h + 1) / 2);
const int w = p == 0 ? (int)img->d_w : (int)((img->d_w + 1) / 2);
for (int r = 0; r < h; ++r) {
- memset(buf, val, w);
+ for (int c = 0; c < w; ++c) {
+ buf[c] = rnd.Rand8();
+ }
buf += img->stride[p];
}
}
@@ -2554,4 +2570,62 @@ TEST(EncodeAPI, SvcSourceLastTL0Uninitialized) {
aom_img_free(img);
ASSERT_EQ(aom_codec_destroy(&codec), AOM_CODEC_OK);
}
+
+TEST(EncodeAPI, Buganizer503810640) {
+ aom_codec_iface_t *iface = aom_codec_av1_cx();
+ aom_codec_enc_cfg_t cfg;
+ ASSERT_EQ(aom_codec_enc_config_default(iface, &cfg, AOM_USAGE_REALTIME),
+ AOM_CODEC_OK);
+
+ cfg.g_w = 176;
+ cfg.g_h = 144;
+
+ aom_codec_ctx_t codec;
+ ASSERT_EQ(aom_codec_enc_init(&codec, iface, &cfg, 0), AOM_CODEC_OK);
+ ASSERT_EQ(aom_codec_control(&codec, AV1E_SET_DENOISE_NOISE_LEVEL, 29),
+ AOM_CODEC_OK);
+
+ aom_image_t *raw = aom_img_alloc(nullptr, AOM_IMG_FMT_I420, 176, 144, 1);
+ ASSERT_NE(raw, nullptr);
+
+ FillImage(raw, 128);
+ ::libaom_test::ACMRandom rnd;
+ rnd.Reset(::libaom_test::ACMRandom::DeterministicSeed());
+ for (int y = 0; y < 144; ++y) {
+ for (int x = 0; x < 176; ++x) {
+ raw->planes[AOM_PLANE_Y][y * raw->stride[AOM_PLANE_Y] + x] = rnd.Rand8();
+ }
+ }
+
+ ASSERT_EQ(aom_codec_encode(&codec, raw, 0, 1, 0), AOM_CODEC_OK);
+
+ aom_img_free(raw);
+ ASSERT_EQ(aom_codec_destroy(&codec), AOM_CODEC_OK);
+}
+
+TEST(EncodeAPI, Buganizer503810640V2) {
+ aom_codec_iface_t *iface = aom_codec_av1_cx();
+ aom_codec_enc_cfg_t cfg;
+ ASSERT_EQ(aom_codec_enc_config_default(iface, &cfg, AOM_USAGE_REALTIME),
+ AOM_CODEC_OK);
+
+ cfg.g_w = 437;
+ cfg.g_h = 1121;
+
+ aom_codec_ctx_t codec;
+ ASSERT_EQ(aom_codec_enc_init(&codec, iface, &cfg, 0), AOM_CODEC_OK);
+ ASSERT_EQ(aom_codec_control(&codec, AV1E_SET_DENOISE_NOISE_LEVEL, 29),
+ AOM_CODEC_OK);
+
+ aom_image_t *raw = aom_img_alloc(nullptr, AOM_IMG_FMT_I420, 437, 1121, 1);
+ ASSERT_NE(raw, nullptr);
+
+ FillImageRandom(raw);
+
+ ASSERT_EQ(aom_codec_encode(&codec, raw, 0, 1, 0), AOM_CODEC_OK);
+
+ aom_img_free(raw);
+ ASSERT_EQ(aom_codec_destroy(&codec), AOM_CODEC_OK);
+}
+
} // namespace