From: marcos ashton via ffmpeg-devel <ffmpeg-devel@ffmpeg.org>
To: ffmpeg-devel@ffmpeg.org
Cc: michealni@gmx.at, marcos ashton <marcosashiglesias@gmail.com>
Subject: [FFmpeg-devel] [PATCH 1/3] tests/fate/libavutil: add FATE test for film_grain_params
Date: Fri, 20 Feb 2026 16:25:45 +0000
Message-ID: <20260220162547.175335-2-marcosashiglesias@gmail.com> (raw)
In-Reply-To: <20260220162547.175335-1-marcosashiglesias@gmail.com>
Add a unit test covering alloc, create_side_data, and select
for AV1 and H.274 film grain parameter types (22 cases).
Signed-off-by: marcos ashton <marcosashiglesias@gmail.com>
---
libavutil/Makefile | 1 +
libavutil/tests/film_grain_params.c | 240 ++++++++++++++++++++++++++++
tests/fate/libavutil.mak | 4 +
tests/ref/fate/film_grain_params | 30 ++++
4 files changed, 275 insertions(+)
create mode 100644 libavutil/tests/film_grain_params.c
create mode 100644 tests/ref/fate/film_grain_params
diff --git a/libavutil/Makefile b/libavutil/Makefile
index c5241895ff..6526d4d73d 100644
--- a/libavutil/Makefile
+++ b/libavutil/Makefile
@@ -277,6 +277,7 @@ TESTPROGS = adler32 \
eval \
file \
fifo \
+ film_grain_params \
hash \
hmac \
hwdevice \
diff --git a/libavutil/tests/film_grain_params.c b/libavutil/tests/film_grain_params.c
new file mode 100644
index 0000000000..043c2bf3a9
--- /dev/null
+++ b/libavutil/tests/film_grain_params.c
@@ -0,0 +1,240 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdio.h>
+
+#include "libavutil/film_grain_params.c"
+
+static AVFrame *create_frame(enum AVPixelFormat format, int width, int height)
+{
+ AVFrame *frame = av_frame_alloc();
+ if (!frame)
+ return NULL;
+ frame->format = format;
+ frame->width = width;
+ frame->height = height;
+ return frame;
+}
+
+static AVFilmGrainParams *add_grain(AVFrame *frame,
+ enum AVFilmGrainParamsType type,
+ int width, int height,
+ int sub_x, int sub_y,
+ int bd_luma, int bd_chroma)
+{
+ AVFilmGrainParams *fgp = av_film_grain_params_create_side_data(frame);
+ if (!fgp)
+ return NULL;
+ fgp->type = type;
+ fgp->width = width;
+ fgp->height = height;
+ fgp->subsampling_x = sub_x;
+ fgp->subsampling_y = sub_y;
+ fgp->bit_depth_luma = bd_luma;
+ fgp->bit_depth_chroma = bd_chroma;
+ return fgp;
+}
+
+int main(void)
+{
+ AVFilmGrainParams *fgp;
+ const AVFilmGrainParams *sel;
+ AVFrame *frame;
+ size_t size;
+
+ printf("Testing av_film_grain_params_alloc()\n");
+
+ fgp = av_film_grain_params_alloc(&size);
+ printf("alloc with size: %s\n", (fgp && size > 0) ? "OK" : "FAIL");
+ av_free(fgp);
+
+ fgp = av_film_grain_params_alloc(NULL);
+ printf("alloc without size: %s\n", fgp ? "OK" : "FAIL");
+ av_free(fgp);
+
+ printf("\nTesting av_film_grain_params_create_side_data()\n");
+
+ frame = av_frame_alloc();
+ fgp = av_film_grain_params_create_side_data(frame);
+ printf("create: %s\n", fgp ? "OK" : "FAIL");
+ printf("defaults: range=%d pri=%d trc=%d space=%d\n",
+ fgp->color_range, fgp->color_primaries,
+ fgp->color_trc, fgp->color_space);
+ av_frame_free(&frame);
+
+ printf("\nTesting av_film_grain_params_select()\n");
+
+ /* invalid format */
+ frame = av_frame_alloc();
+ frame->format = -1;
+ sel = av_film_grain_params_select(frame);
+ printf("invalid format: %s\n", sel ? "FAIL" : "NULL");
+ av_frame_free(&frame);
+
+ /* no side data */
+ frame = create_frame(AV_PIX_FMT_YUV420P, 1920, 1080);
+ sel = av_film_grain_params_select(frame);
+ printf("no side data: %s\n", sel ? "FAIL" : "NULL");
+ av_frame_free(&frame);
+
+ /* NONE type - skipped */
+ frame = create_frame(AV_PIX_FMT_YUV420P, 1920, 1080);
+ add_grain(frame, AV_FILM_GRAIN_PARAMS_NONE, 0, 0, 1, 1, 0, 0);
+ sel = av_film_grain_params_select(frame);
+ printf("NONE type: %s\n", sel ? "FAIL" : "NULL");
+ av_frame_free(&frame);
+
+ /* AV1 exact subsampling match (YUV420P: sub 1,1) */
+ frame = create_frame(AV_PIX_FMT_YUV420P, 1920, 1080);
+ add_grain(frame, AV_FILM_GRAIN_PARAMS_AV1, 0, 0, 1, 1, 0, 0);
+ sel = av_film_grain_params_select(frame);
+ printf("AV1 match: %s\n", sel ? "OK" : "FAIL");
+ av_frame_free(&frame);
+
+ /* AV1 subsampling mismatch */
+ frame = create_frame(AV_PIX_FMT_YUV420P, 1920, 1080);
+ add_grain(frame, AV_FILM_GRAIN_PARAMS_AV1, 0, 0, 0, 0, 0, 0);
+ sel = av_film_grain_params_select(frame);
+ printf("AV1 sub mismatch: %s\n", sel ? "FAIL" : "NULL");
+ av_frame_free(&frame);
+
+ /* H274 exact match */
+ frame = create_frame(AV_PIX_FMT_YUV420P, 1920, 1080);
+ add_grain(frame, AV_FILM_GRAIN_PARAMS_H274, 0, 0, 1, 1, 0, 0);
+ sel = av_film_grain_params_select(frame);
+ printf("H274 match: %s\n", sel ? "OK" : "FAIL");
+ av_frame_free(&frame);
+
+ /* H274 lower subsampling OK (grain sub 0,0 < YUV420P sub 1,1) */
+ frame = create_frame(AV_PIX_FMT_YUV420P, 1920, 1080);
+ add_grain(frame, AV_FILM_GRAIN_PARAMS_H274, 0, 0, 0, 0, 0, 0);
+ sel = av_film_grain_params_select(frame);
+ printf("H274 lower sub: %s\n", sel ? "OK" : "FAIL");
+ av_frame_free(&frame);
+
+ /* H274 higher subsampling FAIL (grain sub 1,1 > YUV444P sub 0,0) */
+ frame = create_frame(AV_PIX_FMT_YUV444P, 1920, 1080);
+ add_grain(frame, AV_FILM_GRAIN_PARAMS_H274, 0, 0, 1, 1, 0, 0);
+ sel = av_film_grain_params_select(frame);
+ printf("H274 higher sub: %s\n", sel ? "FAIL" : "NULL");
+ av_frame_free(&frame);
+
+ /* width too large */
+ frame = create_frame(AV_PIX_FMT_YUV420P, 1920, 1080);
+ add_grain(frame, AV_FILM_GRAIN_PARAMS_AV1, 3840, 0, 1, 1, 0, 0);
+ sel = av_film_grain_params_select(frame);
+ printf("width too large: %s\n", sel ? "FAIL" : "NULL");
+ av_frame_free(&frame);
+
+ /* height too large */
+ frame = create_frame(AV_PIX_FMT_YUV420P, 1920, 1080);
+ add_grain(frame, AV_FILM_GRAIN_PARAMS_AV1, 0, 2160, 1, 1, 0, 0);
+ sel = av_film_grain_params_select(frame);
+ printf("height too large: %s\n", sel ? "FAIL" : "NULL");
+ av_frame_free(&frame);
+
+ /* width/height = 0 (unspecified) - passes */
+ frame = create_frame(AV_PIX_FMT_YUV420P, 1920, 1080);
+ add_grain(frame, AV_FILM_GRAIN_PARAMS_AV1, 0, 0, 1, 1, 0, 0);
+ sel = av_film_grain_params_select(frame);
+ printf("size unspecified: %s\n", sel ? "OK" : "FAIL");
+ av_frame_free(&frame);
+
+ /* bit_depth_luma mismatch (grain=10, YUV420P=8) */
+ frame = create_frame(AV_PIX_FMT_YUV420P, 1920, 1080);
+ add_grain(frame, AV_FILM_GRAIN_PARAMS_AV1, 0, 0, 1, 1, 10, 0);
+ sel = av_film_grain_params_select(frame);
+ printf("bd_luma mismatch: %s\n", sel ? "FAIL" : "NULL");
+ av_frame_free(&frame);
+
+ /* bit_depth_chroma mismatch (grain=10, YUV420P=8) */
+ frame = create_frame(AV_PIX_FMT_YUV420P, 1920, 1080);
+ add_grain(frame, AV_FILM_GRAIN_PARAMS_AV1, 0, 0, 1, 1, 0, 10);
+ sel = av_film_grain_params_select(frame);
+ printf("bd_chroma mismatch: %s\n", sel ? "FAIL" : "NULL");
+ av_frame_free(&frame);
+
+ /* bit_depth = 0 (unspecified) - passes */
+ frame = create_frame(AV_PIX_FMT_YUV420P, 1920, 1080);
+ add_grain(frame, AV_FILM_GRAIN_PARAMS_AV1, 0, 0, 1, 1, 0, 0);
+ sel = av_film_grain_params_select(frame);
+ printf("bd unspecified: %s\n", sel ? "OK" : "FAIL");
+ av_frame_free(&frame);
+
+ /* bit_depth exact match (grain=8, YUV420P=8) */
+ frame = create_frame(AV_PIX_FMT_YUV420P, 1920, 1080);
+ add_grain(frame, AV_FILM_GRAIN_PARAMS_AV1, 0, 0, 1, 1, 8, 8);
+ sel = av_film_grain_params_select(frame);
+ printf("bd exact match: %s\n", sel ? "OK" : "FAIL");
+ av_frame_free(&frame);
+
+ /* color_range mismatch */
+ frame = create_frame(AV_PIX_FMT_YUV420P, 1920, 1080);
+ frame->color_range = AVCOL_RANGE_MPEG;
+ fgp = add_grain(frame, AV_FILM_GRAIN_PARAMS_AV1, 0, 0, 1, 1, 0, 0);
+ fgp->color_range = AVCOL_RANGE_JPEG;
+ sel = av_film_grain_params_select(frame);
+ printf("color_range mismatch: %s\n", sel ? "FAIL" : "NULL");
+ av_frame_free(&frame);
+
+ /* color_primaries mismatch */
+ frame = create_frame(AV_PIX_FMT_YUV420P, 1920, 1080);
+ frame->color_primaries = AVCOL_PRI_BT709;
+ fgp = add_grain(frame, AV_FILM_GRAIN_PARAMS_AV1, 0, 0, 1, 1, 0, 0);
+ fgp->color_primaries = AVCOL_PRI_BT470M;
+ sel = av_film_grain_params_select(frame);
+ printf("color_primaries mismatch: %s\n", sel ? "FAIL" : "NULL");
+ av_frame_free(&frame);
+
+ /* color_trc mismatch */
+ frame = create_frame(AV_PIX_FMT_YUV420P, 1920, 1080);
+ frame->color_trc = AVCOL_TRC_BT709;
+ fgp = add_grain(frame, AV_FILM_GRAIN_PARAMS_AV1, 0, 0, 1, 1, 0, 0);
+ fgp->color_trc = AVCOL_TRC_GAMMA22;
+ sel = av_film_grain_params_select(frame);
+ printf("color_trc mismatch: %s\n", sel ? "FAIL" : "NULL");
+ av_frame_free(&frame);
+
+ /* color_space mismatch */
+ frame = create_frame(AV_PIX_FMT_YUV420P, 1920, 1080);
+ frame->colorspace = AVCOL_SPC_BT709;
+ fgp = add_grain(frame, AV_FILM_GRAIN_PARAMS_AV1, 0, 0, 1, 1, 0, 0);
+ fgp->color_space = AVCOL_SPC_BT470BG;
+ sel = av_film_grain_params_select(frame);
+ printf("color_space mismatch: %s\n", sel ? "FAIL" : "NULL");
+ av_frame_free(&frame);
+
+ /* color properties UNSPECIFIED - passes */
+ frame = create_frame(AV_PIX_FMT_YUV420P, 1920, 1080);
+ add_grain(frame, AV_FILM_GRAIN_PARAMS_AV1, 0, 0, 1, 1, 0, 0);
+ sel = av_film_grain_params_select(frame);
+ printf("color unspecified: %s\n", sel ? "OK" : "FAIL");
+ av_frame_free(&frame);
+
+ /* multiple entries - best selection by size */
+ frame = create_frame(AV_PIX_FMT_YUV420P, 1920, 1080);
+ add_grain(frame, AV_FILM_GRAIN_PARAMS_AV1, 640, 480, 1, 1, 0, 0);
+ add_grain(frame, AV_FILM_GRAIN_PARAMS_AV1, 1280, 720, 1, 1, 0, 0);
+ add_grain(frame, AV_FILM_GRAIN_PARAMS_AV1, 1000, 1080, 1, 1, 0, 0);
+ sel = av_film_grain_params_select(frame);
+ printf("best selection: width=%d height=%d\n",
+ sel ? sel->width : -1, sel ? sel->height : -1);
+ av_frame_free(&frame);
+
+ return 0;
+}
diff --git a/tests/fate/libavutil.mak b/tests/fate/libavutil.mak
index 6bf03b2438..4992f4e64f 100644
--- a/tests/fate/libavutil.mak
+++ b/tests/fate/libavutil.mak
@@ -87,6 +87,10 @@ FATE_LIBAVUTIL += fate-fifo
fate-fifo: libavutil/tests/fifo$(EXESUF)
fate-fifo: CMD = run libavutil/tests/fifo$(EXESUF)
+FATE_LIBAVUTIL += fate-film_grain_params
+fate-film_grain_params: libavutil/tests/film_grain_params$(EXESUF)
+fate-film_grain_params: CMD = run libavutil/tests/film_grain_params$(EXESUF)
+
FATE_LIBAVUTIL += fate-hash
fate-hash: libavutil/tests/hash$(EXESUF)
fate-hash: CMD = run libavutil/tests/hash$(EXESUF)
diff --git a/tests/ref/fate/film_grain_params b/tests/ref/fate/film_grain_params
new file mode 100644
index 0000000000..1b3f8f2b30
--- /dev/null
+++ b/tests/ref/fate/film_grain_params
@@ -0,0 +1,30 @@
+Testing av_film_grain_params_alloc()
+alloc with size: OK
+alloc without size: OK
+
+Testing av_film_grain_params_create_side_data()
+create: OK
+defaults: range=0 pri=2 trc=2 space=2
+
+Testing av_film_grain_params_select()
+invalid format: NULL
+no side data: NULL
+NONE type: NULL
+AV1 match: OK
+AV1 sub mismatch: NULL
+H274 match: OK
+H274 lower sub: OK
+H274 higher sub: NULL
+width too large: NULL
+height too large: NULL
+size unspecified: OK
+bd_luma mismatch: NULL
+bd_chroma mismatch: NULL
+bd unspecified: OK
+bd exact match: OK
+color_range mismatch: NULL
+color_primaries mismatch: NULL
+color_trc mismatch: NULL
+color_space mismatch: NULL
+color unspecified: OK
+best selection: width=1000 height=1080
--
2.53.0
_______________________________________________
ffmpeg-devel mailing list -- ffmpeg-devel@ffmpeg.org
To unsubscribe send an email to ffmpeg-devel-leave@ffmpeg.org
next prev parent reply other threads:[~2026-02-20 18:41 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-02-20 16:25 [FFmpeg-devel] [PATCH 0/3] tests: improve FATE coverage for film_grain_params, CNG, aderivative/aintegral marcos ashton via ffmpeg-devel
2026-02-20 16:25 ` marcos ashton via ffmpeg-devel [this message]
2026-02-20 16:25 ` [FFmpeg-devel] [PATCH 2/3] tests/fate/voice: add FATE test for CNG encoder roundtrip marcos ashton via ffmpeg-devel
2026-02-20 16:25 ` [FFmpeg-devel] [PATCH 3/3] tests/fate/filter-audio: add FATE tests for aderivative and aintegral marcos ashton via ffmpeg-devel
2026-02-22 13:59 ` [FFmpeg-devel] Re: [PATCH 0/3] tests: improve FATE coverage for film_grain_params, CNG, aderivative/aintegral hassan hany via ffmpeg-devel
2026-02-22 15:44 ` Marcos Ashton via ffmpeg-devel
2026-02-22 15:51 ` hassan hany via ffmpeg-devel
2026-02-22 17:14 ` Marcos Ashton via ffmpeg-devel
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260220162547.175335-2-marcosashiglesias@gmail.com \
--to=ffmpeg-devel@ffmpeg.org \
--cc=marcosashiglesias@gmail.com \
--cc=michealni@gmx.at \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
This inbox may be cloned and mirrored by anyone:
git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git
# If you have public-inbox 1.1+ installed, you may
# initialize and index your mirror using the following commands:
public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \
ffmpegdev@gitmailbox.com
public-inbox-index ffmpegdev
Example config snippet for mirrors.
AGPL code for this site: git clone https://public-inbox.org/public-inbox.git