PR #21008 opened by Kacper Michajłow (kasper93) URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/21008 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/21008.patch
This allow to pass DOS path in filter graph string. Although we use `:` as separator, we can make an exception for DOS path looking string. In which cases first `:` is allowed to be included in the value. Fixes drawvg filter, which would otherwise fail to parse `file` option when DOS path is provided. Fixes: fate-filter-drawvg-video From 32c47d9fb67575e9b5667d1f0a6e39a294fac9e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kacper=20Michaj=C5=82ow?= <[email protected]> Date: Mon, 24 Nov 2025 21:17:29 +0100 Subject: [PATCH] avutil/opt: support DOS paths in key value parser This allow to pass DOS path in filter graph string. Although we use `:` as separator, we can make an exception for DOS path looking string. In which cases first `:` is allowed to be included in the value. Fixes drawvg filter, which would otherwise fail to parse `file` option when DOS path is provided. Fixes: fate-filter-drawvg-video --- libavutil/opt.c | 32 ++++++++++++++++++++++++++++++++ libavutil/tests/opt.c | 5 +++++ tests/ref/fate/opt | 19 +++++++++++++++++++ 3 files changed, 56 insertions(+) diff --git a/libavutil/opt.c b/libavutil/opt.c index fc5834e168..39d9177869 100644 --- a/libavutil/opt.c +++ b/libavutil/opt.c @@ -41,6 +41,7 @@ #include "bprint.h" #include "version.h" +#include <ctype.h> #include <float.h> #define TYPE_BASE(type) ((type) & ~AV_OPT_TYPE_FLAG_ARRAY) @@ -1872,6 +1873,31 @@ static int get_key(const char **ropts, const char *delim, char **rkey) return 0; } +#ifdef HAVE_DOS_PATHS +static int get_dos_path(const char **ropts, const char *delim, char **rval) +{ + const char *opts = *ropts; + const char *val_start, *val_end; + + if (!isalpha(opts[0]) || opts[1] != ':' || (opts[2] != '\\' && opts[2] != '/')) + return AVERROR(EINVAL); + + val_start = opts += strspn(opts, WHITESPACES); + opts += 2; // skip drive letter and colon + while (*opts && !strchr(delim, *opts)) + opts++; + val_end = opts; + while (val_end > val_start && strrchr(WHITESPACES, val_end[-1])) + val_end--; + if (!(*rval = av_malloc(val_end - val_start + 1))) + return AVERROR(ENOMEM); + memcpy(*rval, val_start, val_end - val_start); + (*rval)[val_end - val_start] = 0; + *ropts = opts; + return 0; +} +#endif + int av_opt_get_key_value(const char **ropts, const char *key_val_sep, const char *pairs_sep, unsigned flags, @@ -1884,6 +1910,12 @@ int av_opt_get_key_value(const char **ropts, if ((ret = get_key(&opts, key_val_sep, &key)) < 0 && !(flags & AV_OPT_FLAG_IMPLICIT_KEY)) return AVERROR(EINVAL); +#ifdef HAVE_DOS_PATHS + // If value looks like a DOS path, try to parse it as a value. + if (pairs_sep && strchr(pairs_sep, ':') && + get_dos_path(&opts, pairs_sep, &val) >= 0) + {} else +#endif if (!(val = av_get_token(&opts, pairs_sep))) { av_free(key); return AVERROR(ENOMEM); diff --git a/libavutil/tests/opt.c b/libavutil/tests/opt.c index 8ab76c4690..c5bf169310 100644 --- a/libavutil/tests/opt.c +++ b/libavutil/tests/opt.c @@ -516,6 +516,11 @@ int main(void) ":", "=", " 5 : hello : size = pal ", + "string=C:/dir/hello.txt ", + "string=C:/dir/hello.txt:size=pal", + "string=C:\\dir\\hello.txt:size=pal", + "string = C:/dir/hello.txt : size = pal", + "string = C:\\dir\\hello.txt : size = pal", "a_very_long_option_name_that_will_need_to_be_ellipsized_around_here=42" }; static const char * const shorthand[] = { "num", "string", NULL }; diff --git a/tests/ref/fate/opt b/tests/ref/fate/opt index 1f82f7e4bd..86f5f7c139 100644 --- a/tests/ref/fate/opt +++ b/tests/ref/fate/opt @@ -507,6 +507,25 @@ Setting 'num' to value '5' Setting 'string' to value 'hello' Setting 'size' to value 'pal' OK ' 5 : hello : size = pal ' +Setting options string 'string=C:/dir/hello.txt ' +Setting 'string' to value 'C:/dir/hello.txt' +OK 'string=C:/dir/hello.txt ' +Setting options string 'string=C:/dir/hello.txt:size=pal' +Setting 'string' to value 'C:/dir/hello.txt' +Setting 'size' to value 'pal' +OK 'string=C:/dir/hello.txt:size=pal' +Setting options string 'string=C:\dir\hello.txt:size=pal' +Setting 'string' to value 'C:\dir\hello.txt' +Setting 'size' to value 'pal' +OK 'string=C:\dir\hello.txt:size=pal' +Setting options string 'string = C:/dir/hello.txt : size = pal' +Setting 'string' to value 'C' +No option name near '/dir/hello.txt : size = pal' +Error 'string = C:/dir/hello.txt : size = pal' +Setting options string 'string = C:\dir\hello.txt : size = pal' +Setting 'string' to value 'C' +No option name near '\dir\hello.txt : size = pal' +Error 'string = C:\dir\hello.txt : size = pal' Setting options string 'a_very_long_option_name_that_will_need_to_be_ellipsized_around_here=42' Setting 'a_very_long_option_name_that_will_need_to_be_ellipsized_around_here' to value '42' Option 'a_very_long_option_name_that_will_need_to_be_ellipsized_around_here' not found -- 2.49.1 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
