Commit 2a8c6d30b9 for ffmpeg
commit 2a8c6d30b934f9bd8429f96f605e5fc7c5751679
Author: lusoris <lusoris@proton.me>
Date: Fri Oct 9 18:19:54 2026 +0200
avcodec/av1dec: remove the coding bias from exported chroma grain params
export_film_grain() copied cb_mult, cb_luma_mult and cb_offset (and the
Cr equivalents) straight from the bitstream, where they are coded with
a bias of 128, 128 and 256. AVFilmGrainAOMParams holds them unbiased:
the uv_offset documentation gives a range of [-256, 255], the AFGS1
parser in aom_film_grain.c subtracts the bias, the film grain
synthesizer uses the values as signed multipliers and offsets, and
libdav1d exports them unbiased. The AR coefficients a few lines above
are already unbiased the same way.
With -export_side_data film_grain and a hwaccel, the native decoder
therefore exported values 128 or 256 higher than libdav1d for the
same stream, and any consumer applying the exported grain scaled
chroma noise wrong.
Signed-off-by: lusoris <lusoris@proton.me>
diff --git a/libavcodec/av1dec.c b/libavcodec/av1dec.c
index 5f06dd1467..0fa6e9245b 100644
--- a/libavcodec/av1dec.c
+++ b/libavcodec/av1dec.c
@@ -1129,12 +1129,12 @@ static int export_film_grain(AVCodecContext *avctx, AVFrame *frame)
aom->ar_coeffs_uv[1][i] = film_grain->ar_coeffs_cr_plus_128[i] - 128;
}
- aom->uv_mult[0] = film_grain->cb_mult;
- aom->uv_mult[1] = film_grain->cr_mult;
- aom->uv_mult_luma[0] = film_grain->cb_luma_mult;
- aom->uv_mult_luma[1] = film_grain->cr_luma_mult;
- aom->uv_offset[0] = film_grain->cb_offset;
- aom->uv_offset[1] = film_grain->cr_offset;
+ aom->uv_mult[0] = film_grain->cb_mult - 128;
+ aom->uv_mult[1] = film_grain->cr_mult - 128;
+ aom->uv_mult_luma[0] = film_grain->cb_luma_mult - 128;
+ aom->uv_mult_luma[1] = film_grain->cr_luma_mult - 128;
+ aom->uv_offset[0] = film_grain->cb_offset - 256;
+ aom->uv_offset[1] = film_grain->cr_offset - 256;
return 0;
}