[FFmpeg-devel] [PATCH 01/11] avutil/opt: allow passing a fake object to av_opt_set()
James Almer
jamrial at gmail.com
Tue Feb 18 15:08:03 EET 2025
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 at 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
More information about the ffmpeg-devel
mailing list