PR #25613 opened by Kilian (lusoris)
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25613
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25613.patch

`libvmaf` falls back to XML for any `log_fmt` it does not know, so 
`log_fmt=jsn` exits 0 and writes an XML file under the requested name. This PR 
rejects unknown values in `init()` and `init_cuda()`, with or without 
`log_path`. Found by the automated review of PR 24978 and independent of it.

| `log_fmt`, on 17a4a474f4 x86-64 with libvmaf 3.2.0 | Before | After |
| --- | --- | --- |
| `jsn`, with `log_path` | exit 0, XML file | exit 234, `Unknown log format 
'jsn', must be one of xml, json, csv, sub` |
| `jsn`, without `log_path` | exit 0 | exit 234, same message |
| empty string | exit 0, XML file | exit 234 |
| `XML` | exit 0, XML file | exit 234 |
| `xml`, `json`, `csv`, `sub`, unset | exit 0 | exit 0, same format, same score 
|

**Behaviour change:** a command line that passed an unknown or uppercase value 
and silently got XML now fails.

Tested with GCC 16 on the CPU filter; `init_cuda()` has the same check but was 
not built here. FATE has no `libvmaf` test; `fate-source` passes and the file 
builds without warnings.



>From ba6c2e1306ddbc60822a4a3bc4225574f81facd2 Mon Sep 17 00:00:00 2001
From: lusoris <[email protected]>
Date: Fri, 30 Oct 2026 12:58:29 +0100
Subject: [PATCH] avfilter/vf_libvmaf: reject unknown log formats

log_fmt_map() fell back to XML for any string it did not know, so a
typo such as log_fmt=jsn exited 0 and wrote an XML file under the name
the user asked for. The mistake only surfaced when a later step failed
to parse that file.

Validate the option in init() and init_cuda(), before libvmaf is set
up. The check also runs without log_path, so a bad option fails the
same way whether or not a log is written. NULL still maps to XML.

Signed-off-by: lusoris <[email protected]>
---
 libavfilter/vf_libvmaf.c | 55 ++++++++++++++++++++++++++++------------
 1 file changed, 39 insertions(+), 16 deletions(-)

diff --git a/libavfilter/vf_libvmaf.c b/libavfilter/vf_libvmaf.c
index 851b0982f02..9a735362fbb 100644
--- a/libavfilter/vf_libvmaf.c
+++ b/libavfilter/vf_libvmaf.c
@@ -519,6 +519,36 @@ static enum VmafLogLevel log_level_map(int log_level)
     }
 }
 
+static enum VmafOutputFormat log_fmt_map(const char *log_fmt)
+{
+    if (log_fmt) {
+        if (!strcmp(log_fmt, "xml"))
+            return VMAF_OUTPUT_FORMAT_XML;
+        if (!strcmp(log_fmt, "json"))
+            return VMAF_OUTPUT_FORMAT_JSON;
+        if (!strcmp(log_fmt, "csv"))
+            return VMAF_OUTPUT_FORMAT_CSV;
+        if (!strcmp(log_fmt, "sub"))
+            return VMAF_OUTPUT_FORMAT_SUB;
+    }
+
+    return log_fmt ? VMAF_OUTPUT_FORMAT_NONE : VMAF_OUTPUT_FORMAT_XML;
+}
+
+static av_cold int check_log_fmt(AVFilterContext *ctx)
+{
+    LIBVMAFContext *s = ctx->priv;
+
+    if (log_fmt_map(s->log_fmt) == VMAF_OUTPUT_FORMAT_NONE) {
+        av_log(ctx, AV_LOG_ERROR,
+               "Unknown log format '%s', must be one of xml, json, csv, sub\n",
+               s->log_fmt);
+        return AVERROR(EINVAL);
+    }
+
+    return 0;
+}
+
 static av_cold int init(AVFilterContext *ctx)
 {
     LIBVMAFContext *s = ctx->priv;
@@ -530,6 +560,10 @@ static av_cold int init(AVFilterContext *ctx)
         .n_threads = s->n_threads,
     };
 
+    err = check_log_fmt(ctx);
+    if (err < 0)
+        return err;
+
     err = vmaf_init(&s->vmaf, cfg);
     if (err)
         return AVERROR(EINVAL);
@@ -604,22 +638,6 @@ static int activate(AVFilterContext *ctx)
     return ff_framesync_activate(&s->fs);
 }
 
-static enum VmafOutputFormat log_fmt_map(const char *log_fmt)
-{
-    if (log_fmt) {
-        if (!strcmp(log_fmt, "xml"))
-            return VMAF_OUTPUT_FORMAT_XML;
-        if (!strcmp(log_fmt, "json"))
-            return VMAF_OUTPUT_FORMAT_JSON;
-        if (!strcmp(log_fmt, "csv"))
-            return VMAF_OUTPUT_FORMAT_CSV;
-        if (!strcmp(log_fmt, "sub"))
-            return VMAF_OUTPUT_FORMAT_SUB;
-    }
-
-    return VMAF_OUTPUT_FORMAT_XML;
-}
-
 static enum VmafPoolingMethod pool_method_map(const char *pool_method)
 {
     if (pool_method) {
@@ -887,6 +905,11 @@ static int do_vmaf_cuda(FFFrameSync* fs)
 static av_cold int init_cuda(AVFilterContext *ctx)
 {
     LIBVMAFContext *s = ctx->priv;
+    int err = check_log_fmt(ctx);
+
+    if (err < 0)
+        return err;
+
     s->fs.on_event = do_vmaf_cuda;
     return 0;
 }
-- 
2.54.0

_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to