Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
 help / color / mirror / Atom feed
* [FFmpeg-devel] [PATCH 01/11] avutil/opt: allow passing a fake object to av_opt_set()
@ 2025-02-18 13:08 James Almer
  2025-02-18 13:08 ` [FFmpeg-devel] [PATCH 02/11] avcodec/encode: add a function to gracefully reconfigure an encoder James Almer
                   ` (9 more replies)
  0 siblings, 10 replies; 11+ messages in thread
From: James Almer @ 2025-02-18 13:08 UTC (permalink / raw)
  To: ffmpeg-devel

The result will be a dry run of the process, where no value is set but all
the checks are made.
Useful for, as the AV_OPT_SEARCH_FAKE_OBJ flag states, run the relevant
process without having to allocate the corresponding object.

Signed-off-by: James Almer <jamrial@gmail.com>
---
 libavutil/opt.c | 77 ++++++++++++++++++++++++++++++++++++++++++-------
 libavutil/opt.h | 11 +++----
 2 files changed, 72 insertions(+), 16 deletions(-)

diff --git a/libavutil/opt.c b/libavutil/opt.c
index 44b507dbd4..196e3660e1 100644
--- a/libavutil/opt.c
+++ b/libavutil/opt.c
@@ -171,7 +171,7 @@ static int opt_set_init(void *obj, const char *name, int search_flags,
     void *tgt;
 
     o = av_opt_find2(obj, name, NULL, 0, search_flags, &tgt);
-    if (!o || !tgt)
+    if (!o || (!tgt && !(search_flags & AV_OPT_SEARCH_FAKE_OBJ)))
         return AVERROR_OPTION_NOT_FOUND;
 
     if (o->flags & AV_OPT_FLAG_READONLY)
@@ -226,7 +226,7 @@ static int opt_set_init(void *obj, const char *name, int search_flags,
     if (ptgt)
         *ptgt = tgt;
     if (pdst)
-        *pdst = ((uint8_t *)tgt) + o->offset;
+        *pdst = tgt ? ((uint8_t *)tgt) + o->offset : NULL;
 
     return 0;
 }
@@ -301,6 +301,9 @@ static int write_number(void *obj, const AVOption *o, void *dst, double num, int
         }
     }
 
+    if (!dst)
+        return 0;
+
     switch (type) {
     case AV_OPT_TYPE_PIXEL_FMT:
         *(enum AVPixelFormat *)dst = llrint(num / den) * intnum;
@@ -367,12 +370,15 @@ static int hexchar2int(char c) {
 
 static int set_string_binary(void *obj, const AVOption *o, const char *val, uint8_t **dst)
 {
-    int *lendst = (int *)(dst + 1);
+    int *lendst;
     uint8_t *bin, *ptr;
     int len;
 
+    if (dst) {
+        lendst = (int *)(dst + 1);
     av_freep(dst);
     *lendst = 0;
+    }
 
     if (!val || !(len = strlen(val)))
         return 0;
@@ -393,14 +399,19 @@ static int set_string_binary(void *obj, const AVOption *o, const char *val, uint
         }
         *ptr++ = (a << 4) | b;
     }
+    if (dst) {
     *dst    = bin;
     *lendst = len;
+    } else
+        av_free(bin);
 
     return 0;
 }
 
 static int set_string(void *obj, const AVOption *o, const char *val, uint8_t **dst)
 {
+    if (!dst)
+        return 0;
     av_freep(dst);
     if (!val)
         return 0;
@@ -495,7 +506,7 @@ static int set_string_number(void *obj, void *target_obj, const AVOption *o, con
                 }
             }
         }
-        if (type == AV_OPT_TYPE_FLAGS) {
+        if (type == AV_OPT_TYPE_FLAGS && dst) {
             intnum = *(unsigned int*)dst;
             if (cmd == '+')
                 d = intnum | (int64_t)d;
@@ -513,24 +524,32 @@ static int set_string_number(void *obj, void *target_obj, const AVOption *o, con
 
 static int set_string_image_size(void *obj, const AVOption *o, const char *val, int *dst)
 {
+    int tmp[2];
     int ret;
 
     if (!val || !strcmp(val, "none")) {
+        if (dst) {
         dst[0] =
         dst[1] = 0;
+        }
         return 0;
     }
-    ret = av_parse_video_size(dst, dst + 1, val);
+    ret = av_parse_video_size(&tmp[0], &tmp[1], val);
     if (ret < 0)
         av_log(obj, AV_LOG_ERROR, "Unable to parse option value \"%s\" as image size\n", val);
+    if (dst)
+        memcpy(dst, tmp, sizeof(tmp));
     return ret;
 }
 
 static int set_string_video_rate(void *obj, const AVOption *o, const char *val, AVRational *dst)
 {
-    int ret = av_parse_video_rate(dst, val);
+    AVRational tmp;
+    int ret = av_parse_video_rate(&tmp, val);
     if (ret < 0)
         av_log(obj, AV_LOG_ERROR, "Unable to parse option value \"%s\" as video rate\n", val);
+    if (dst)
+        *dst = tmp;
     return ret;
 }
 
@@ -541,9 +560,12 @@ static int set_string_color(void *obj, const AVOption *o, const char *val, uint8
     if (!val) {
         return 0;
     } else {
-        ret = av_parse_color(dst, val, -1, obj);
+        uint8_t tmp[4];
+        ret = av_parse_color(tmp, val, -1, obj);
         if (ret < 0)
             av_log(obj, AV_LOG_ERROR, "Unable to parse option value \"%s\" as color\n", val);
+        if (dst)
+            memcpy(dst, tmp, sizeof(tmp));
         return ret;
     }
     return 0;
@@ -579,6 +601,7 @@ static int set_string_bool(void *obj, const AVOption *o, const char *val, int *d
     if (n < o->min || n > o->max)
         goto fail;
 
+    if (dst)
     *dst = n;
     return 0;
 
@@ -623,6 +646,7 @@ static int set_string_fmt(void *obj, const AVOption *o, const char *val, uint8_t
         return AVERROR(ERANGE);
     }
 
+    if (dst)
     *(int *)dst = fmt;
     return 0;
 }
@@ -661,6 +685,9 @@ static int set_string_dict(void *obj, const AVOption *o, const char *val, uint8_
         }
     }
 
+    if (!dst)
+        return 0;
+
     av_dict_free((AVDictionary **)dst);
     *dst = (uint8_t *)options;
 
@@ -670,11 +697,21 @@ static int set_string_dict(void *obj, const AVOption *o, const char *val, uint8_
 static int set_string_channel_layout(void *obj, const AVOption *o,
                                      const char *val, void *dst)
 {
+    AVChannelLayout tmp;
     AVChannelLayout *channel_layout = dst;
+    int ret;
+    if (dst)
     av_channel_layout_uninit(channel_layout);
+    else
+        channel_layout = &tmp;
     if (!val)
         return 0;
-    return av_channel_layout_from_string(channel_layout, val);
+    ret = av_channel_layout_from_string(channel_layout, val);
+    if (ret < 0)
+        return ret;
+    if (!dst)
+        av_channel_layout_uninit(channel_layout);
+    return 0;
 }
 
 static int opt_set_elem(void *obj, void *target_obj, const AVOption *o,
@@ -733,6 +770,7 @@ static int opt_set_elem(void *obj, void *target_obj, const AVOption *o,
                        usecs / 1000000.0, o->name, o->min / 1000000.0, o->max / 1000000.0);
                 return AVERROR(ERANGE);
             }
+            if (dst)
             *(int64_t *)dst = usecs;
             return 0;
         }
@@ -812,6 +850,7 @@ static int opt_set_array(void *obj, void *target_obj, const AVOption *o,
     }
     av_freep(&str);
 
+    if (dst)
     opt_free_array(o, dst, opt_array_pcount(dst));
 
     if (arr && nb_elems < arr->size_min) {
@@ -822,8 +861,10 @@ static int opt_set_array(void *obj, void *target_obj, const AVOption *o,
         goto fail;
     }
 
+    if (dst) {
     *((void **)dst)        = elems;
     *opt_array_pcount(dst) = nb_elems;
+    }
 
     return 0;
 fail:
@@ -873,8 +914,10 @@ static int set_number(void *obj, const char *name, double num, int den, int64_t
     ret = opt_set_init(obj, name, search_flags, require_type, NULL, &o, &dst);
     if (ret < 0)
         return ret;
+    if (dst)
+        ret = write_number(obj, o, dst, num, den, intnum);
 
-    return write_number(obj, o, dst, num, den, intnum);
+    return ret;
 }
 
 int av_opt_set_int(void *obj, const char *name, int64_t val, int search_flags)
@@ -904,6 +947,7 @@ int av_opt_set_bin(void *obj, const char *name, const uint8_t *val, int len, int
     if (ret < 0)
         return ret;
 
+    if (dst) {
     ptr = len ? av_malloc(len) : NULL;
     if (len && !ptr)
         return AVERROR(ENOMEM);
@@ -915,6 +959,7 @@ int av_opt_set_bin(void *obj, const char *name, const uint8_t *val, int len, int
     *lendst = len;
     if (len)
         memcpy(ptr, val, len);
+    }
 
     return 0;
 }
@@ -936,8 +981,10 @@ int av_opt_set_image_size(void *obj, const char *name, int w, int h, int search_
         return AVERROR(EINVAL);
     }
 
+    if (dst) {
     dst[0] = w;
     dst[1] = h;
+    }
 
     return 0;
 }
@@ -967,6 +1014,7 @@ static int set_format(void *obj, const char *name, int fmt, int search_flags,
                fmt, name, desc, min, max);
         return AVERROR(ERANGE);
     }
+    if (dst)
     *dst = fmt;
     return 0;
 }
@@ -992,9 +1040,13 @@ int av_opt_set_dict_val(void *obj, const char *name, const AVDictionary *val,
     if (ret < 0)
         return ret;
 
+    if (dst) {
     av_dict_free(dst);
 
-    return av_dict_copy(dst, val, 0);
+        ret = av_dict_copy(dst, val, 0);
+    }
+
+    return ret;
 }
 
 int av_opt_set_chlayout(void *obj, const char *name,
@@ -1009,7 +1061,10 @@ int av_opt_set_chlayout(void *obj, const char *name,
     if (ret < 0)
         return ret;
 
-    return av_channel_layout_copy(dst, channel_layout);
+    if (dst)
+        ret = av_channel_layout_copy(dst, channel_layout);
+
+    return ret;
 }
 
 static void format_duration(char *buf, size_t size, int64_t d)
diff --git a/libavutil/opt.h b/libavutil/opt.h
index d313679263..227e677355 100644
--- a/libavutil/opt.h
+++ b/libavutil/opt.h
@@ -605,10 +605,10 @@ const AVClass *av_opt_child_class_iterate(const AVClass *parent, void **iter);
 #define AV_OPT_SEARCH_CHILDREN   (1 << 0) /**< Search in possible children of the
                                                given object first. */
 /**
- *  The obj passed to av_opt_find() is fake -- only a double pointer to AVClass
- *  instead of a required pointer to a struct containing AVClass. This is
- *  useful for searching for options without needing to allocate the corresponding
- *  object.
+ *  The obj passed to av_opt_find() or av_opt_set() is fake -- only a double pointer
+ *  to AVClass instead of a required pointer to a struct containing AVClass. This is
+ *  useful for searching for options or verifying they can be applied without needing
+ *  to allocate the corresponding object.
  */
 #define AV_OPT_SEARCH_FAKE_OBJ   (1 << 1)
 
@@ -842,7 +842,8 @@ int av_opt_copy(void *dest, const void *src);
  * @{
  * Those functions set the field of obj with the given name to value.
  *
- * @param[in] obj A struct whose first element is a pointer to an AVClass.
+ * @param[in] obj A struct whose first element is a pointer to an AVClass. Alternatively
+ * a double pointer to an AVClass, if AV_OPT_SEARCH_FAKE_OBJ search flag is set.
  * @param[in] name the name of the field to set
  * @param[in] val The value to set. In case of av_opt_set() if the field is not
  * of a string type, then the given string is parsed.
-- 
2.48.1

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2025-02-18 13:10 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-02-18 13:08 [FFmpeg-devel] [PATCH 01/11] avutil/opt: allow passing a fake object to av_opt_set() James Almer
2025-02-18 13:08 ` [FFmpeg-devel] [PATCH 02/11] avcodec/encode: add a function to gracefully reconfigure an encoder James Almer
2025-02-18 13:08 ` [FFmpeg-devel] [PATCH 03/11] avcodec/libx264: refactor encoder configuration functions James Almer
2025-02-18 13:08 ` [FFmpeg-devel] [PATCH 04/11] avcodec/libx264: add support for encoder reconfiguration James Almer
2025-02-18 13:08 ` [FFmpeg-devel] [PATCH 05/11] avcodec/libaomenc: refactor encoder configuration functions James Almer
2025-02-18 13:08 ` [FFmpeg-devel] [PATCH 06/11] avcodec/libaomenc: add support for encoder reconfiguration James Almer
2025-02-18 13:08 ` [FFmpeg-devel] [PATCH 07/11] fftools/ffmpeg_filter: add AVOptions to OutputFilter James Almer
2025-02-18 13:08 ` [FFmpeg-devel] [PATCH 08/11] fftools/ffmpeg_enc: split off parts of enc_open() into a separate function James Almer
2025-02-18 13:08 ` [FFmpeg-devel] [PATCH 09/11] fftools/ffmpeg_enc: split off encoder flushing in encoder_thread() " James Almer
2025-02-18 13:08 ` [FFmpeg-devel] [PATCH 10/11] fftools/ffmpeg_enc: store a few more AVCodecContext fields in Encoder James Almer
2025-02-18 13:08 ` [FFmpeg-devel] [PATCH 11/11] fftools/ffmpeg: support reinitializing the encoder James Almer

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