From: James Almer <jamrial@gmail.com> To: ffmpeg-devel@ffmpeg.org Subject: [FFmpeg-devel] [PATCH 01/11] avutil/opt: allow passing a fake object to av_opt_set() Date: Tue, 18 Feb 2025 10:08:03 -0300 Message-ID: <20250218130813.74-1-jamrial@gmail.com> (raw) 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".
next reply other threads:[~2025-02-18 13:08 UTC|newest] Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top 2025-02-18 13:08 James Almer [this message] 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
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20250218130813.74-1-jamrial@gmail.com \ --to=jamrial@gmail.com \ --cc=ffmpeg-devel@ffmpeg.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
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