[PR] avutil/opt: ignore range check on default values (PR #24301)

Niklas Haas via ffmpeg-devel <[email protected]>
Newsgroups gmane.comp.video.ffmpeg.devel
Message-ID <[email protected]>
PR #24301 opened by Niklas Haas (haasn)
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24301
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24301.patch

Filters may want to deliberately set a default value that is outside the
range of permissible values. One use case for this is AV_OPT_TYPE_RATIONAL,
which does not currently permit a value of { .dbl = NAN } by default, even
though the semi-equivalent AV_OPT_TYPE_FLOAT/DOUBLE do.

This is a genuine inconsistency, and universally rejecting the range check
for default options is probably the right way to solve it.

Signed-off-by: Niklas Haas <[email protected]>

# Summary of changes

Briefly describe what this PR does and why.

<!--
If this PR requires new FATE test samples, attach them to the PR and
list their target paths below (relative to the fate-suite root).

Attached filenames must match the sample's filename:

```fate-samples
# e.g. vorbis/new-sample.ogg
```
-->



>From 0ade1d2e1d09dcd87bcf92f442c9a44c79c4ba02 Mon Sep 17 00:00:00 2001
From: Niklas Haas <[email protected]>
Date: Fri, 28 Aug 2026 13:18:32 +0200
Subject: [PATCH] avutil/opt: ignore range check on default values

Filters may want to deliberately set a default value that is outside the
range of permissible values. One use case for this is AV_OPT_TYPE_RATIONAL,
which does not currently permit a value of { .dbl = NAN } by default, even
though the semi-equivalent AV_OPT_TYPE_FLOAT/DOUBLE do.

This is a genuine inconsistency, and universally rejecting the range check
for default options is probably the right way to solve it.

Signed-off-by: Niklas Haas <[email protected]>
---
 libavutil/opt.c | 24 +++++++++++++-----------
 1 file changed, 13 insertions(+), 11 deletions(-)

diff --git a/libavutil/opt.c b/libavutil/opt.c
index 6fa1ec9929..17bd453dad 100644
--- a/libavutil/opt.c
+++ b/libavutil/opt.c
@@ -272,19 +272,21 @@ static int read_number(const AVOption *o, const void *dst, double *num, int *den
     return AVERROR(EINVAL);
 }
 
-static int write_number(void *obj, const AVOption *o, void *dst, double num, int den, int64_t intnum)
+static int write_number(void *obj, const AVOption *o, void *dst,
+                        double num, int den, int64_t intnum,
+                        int ignore_range)
 {
     void *logctx = dst ? obj : NULL;
     const enum AVOptionType type = TYPE_BASE(o->type);
 
-    if (type != AV_OPT_TYPE_FLAGS &&
+    if (!ignore_range && type != AV_OPT_TYPE_FLAGS &&
         (!den || o->max * den < num * intnum || o->min * den > num * intnum)) {
         num = den ? num * intnum / den : (num && intnum ? INFINITY : NAN);
         av_log(obj, AV_LOG_ERROR, "Value %f for parameter '%s' out of range [%g - %g]\n",
                num, o->name, o->min, o->max);
         return AVERROR(ERANGE);
     }
-    if (type == AV_OPT_TYPE_FLAGS) {
+    if (!ignore_range && type == AV_OPT_TYPE_FLAGS) {
         double d = num*intnum/den;
         if (d < -1.5 || d > 0xFFFFFFFF+0.5 || (llrint(d*256) & 255)) {
             av_log(logctx, AV_LOG_ERROR,
@@ -433,7 +435,7 @@ static int set_string_number(void *obj, void *target_obj, const AVOption *o, con
         int num, den;
         char c;
         if (sscanf(val, "%d%*1[:/]%d%c", &num, &den, &c) == 2) {
-            if ((ret = write_number(obj, o, dst, 1, den, num)) >= 0)
+            if ((ret = write_number(obj, o, dst, 1, den, num, 0)) >= 0)
                 return ret;
             ret = 0;
         }
@@ -510,7 +512,7 @@ static int set_string_number(void *obj, void *target_obj, const AVOption *o, con
                 d = intnum &~(int64_t)d;
         }
 
-        if ((ret = write_number(obj, o, dst, d, 1, 1)) < 0)
+        if ((ret = write_number(obj, o, dst, d, 1, 1, 0)) < 0)
             return ret;
         val += i;
         if (!i || !*val)
@@ -761,7 +763,7 @@ static int opt_set_elem(void *obj, void *target_obj, const AVOption *o,
         ret = set_string_video_rate(obj, o, val, &tmp);
         if (ret < 0)
             return ret;
-        return write_number(obj, o, dst, 1, tmp.den, tmp.num);
+        return write_number(obj, o, dst, 1, tmp.den, tmp.num, 0);
     }
     case AV_OPT_TYPE_PIXEL_FMT:
         return set_string_pixel_fmt(obj, o, val, dst);
@@ -928,7 +930,7 @@ static int set_number(void *obj, const char *name, double num, int den, int64_t
     if (ret < 0)
         return ret;
     if (dst)
-        ret = write_number(obj, o, dst, num, den, intnum);
+        ret = write_number(obj, o, dst, num, den, intnum, 0);
 
     return ret;
 }
@@ -1798,19 +1800,19 @@ void av_opt_set_defaults2(void *s, int mask, int flags)
             case AV_OPT_TYPE_DURATION:
             case AV_OPT_TYPE_PIXEL_FMT:
             case AV_OPT_TYPE_SAMPLE_FMT:
-                write_number(s, opt, dst, 1, 1, opt->default_val.i64);
+                write_number(s, opt, dst, 1, 1, opt->default_val.i64, 1);
                 break;
             case AV_OPT_TYPE_DOUBLE:
             case AV_OPT_TYPE_FLOAT: {
                 double val;
                 val = opt->default_val.dbl;
-                write_number(s, opt, dst, val, 1, 1);
+                write_number(s, opt, dst, val, 1, 1, 1);
             }
             break;
             case AV_OPT_TYPE_RATIONAL: {
                 AVRational val;
                 val = av_d2q(opt->default_val.dbl, INT_MAX);
-                write_number(s, opt, dst, 1, val.den, val.num);
+                write_number(s, opt, dst, 1, val.den, val.num, 1);
             }
             break;
             case AV_OPT_TYPE_COLOR:
@@ -2482,7 +2484,7 @@ int av_opt_set_array(void *obj, const char *name, int search_flags,
             default: av_assert0(0);
             }
 
-            ret = write_number(obj, o, dst, num, den, intnum);
+            ret = write_number(obj, o, dst, num, den, intnum, 0);
             if (ret < 0)
                 goto fail;
         } else {
-- 
2.52.0

_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.