From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by master.gitmailbox.com (Postfix) with ESMTPS id B719C4D1F7 for ; Tue, 18 Feb 2025 13:08:43 +0000 (UTC) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id CC70068C0DB; Tue, 18 Feb 2025 15:08:38 +0200 (EET) Received: from mail-pl1-f175.google.com (mail-pl1-f175.google.com [209.85.214.175]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 76F9F68B4AD for ; Tue, 18 Feb 2025 15:08:32 +0200 (EET) Received: by mail-pl1-f175.google.com with SMTP id d9443c01a7336-22100006bc8so55179285ad.0 for ; Tue, 18 Feb 2025 05:08:32 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1739884110; x=1740488910; darn=ffmpeg.org; h=content-transfer-encoding:mime-version:message-id:date:subject:to :from:from:to:cc:subject:date:message-id:reply-to; bh=JhP0be6KGUgb4+L/V1XWHyZN/PlyfcAm+oVziBXygQE=; b=I16DHot77QcWjDJG7BZg1DuMsaJFlWBdo+6nOrXn1OK1k0kMxwePQdOI8Rbq7ExzVf bIApjAM6AROyEZDnC5JWb79w+T+v+ZfrNfqfsKGzIaKygYiZZ4wnSYBjJYwwVh9OZ4ry X9L2w80PtbKNWXybo2kxFL7gnJq+Yc8C7j4MFUfFZEfIaZbsx8gYEdnSfwM4iJrx9eQc +D/QvgVHgIGZfFUVW6NVG0iOA8ohlQ3Epbh54toOUT11+JjhWVUmQM0sP52z3GRlLbAU KFdej0C/EPQ0jzNBiF0YSm+4sxygoMACtCSMSG+WESYdUruDPiwVQx8xlTschz0IL3fh vYDQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1739884110; x=1740488910; h=content-transfer-encoding:mime-version:message-id:date:subject:to :from:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=JhP0be6KGUgb4+L/V1XWHyZN/PlyfcAm+oVziBXygQE=; b=RKemjvfJIS7xxFlFfaPPV7Y6nlVKTqg0e3Kug/XGtqNPkQd9I8O7mlj2Itycw7pBQ9 C91HaKUzI0poGJUkSnaRiBsIjd2D0FMny7h1s8/CedBnvXS2ggSN64/inyOfGRCC5B2s rY9Qeh4FoIshVQkc3w5YcLx6JQO9TicKDLlZmgFr2kE9jrXet/Ro5f889nwcm4wp4x2h gjGNGcHg5XFCvHEHdsOq5JwuIwO4mbapJmXnE+WJMDewBJBH34um8j4KAJbiPzeTAYVD qh48/UAS1htYQXorAhw9Gw5yvTo6+A5+y5LcC/BoKyZDfc2/ZjEwZucMksA4PsS1ODo5 tepw== X-Gm-Message-State: AOJu0YxbJ4ja6QVbHeth88j/y7d9IXTXStT3vKdZYOS1tQR2M6P9Pq8h f9Ree3aTqoq59RN+yNa8BcNNCOfP55MMm4sDa/ZTM2ZMvsqYcj2TojikD1Bh X-Gm-Gg: ASbGncvY2iDR/IpnC8HaxH0vF786i6tzmW38u0VTahv31ZqVDEmZ2oEHs7yviwgBGLK POdaK+hSZ0YMIKqX30QQ/RH2X/PSnxXculbvI/xTxPfqZc2nXm/yxMMJvt/bPCpgvHAu7XYwxtu bHyM4AHPNhZw6v6/TK4oN+a24ZI2bOpMut51AMzeeiacBcrxa0Pvul5uX6xYw6d6ZV1A/U9naey NlYWxRj6TkZdLi5Lk7OMKxEORhACl1agFhjG20AhU3K4rQSsTiA7ErOPF0w56y/ZQ8/Gnte8whS xOAMejQ0168uwQpTMt90yUia5GZ6Og== X-Google-Smtp-Source: AGHT+IH9InxHARwV7RrsWVA/jRrrOL9Fn/0yz6TZJA1NYAwek7AAEGow7p+F1S8iNzJau3Dn1KUJ4g== X-Received: by 2002:a17:902:e886:b0:21f:9c48:254b with SMTP id d9443c01a7336-22104063669mr244484565ad.24.1739884110004; Tue, 18 Feb 2025 05:08:30 -0800 (PST) Received: from localhost.localdomain ([2800:2121:b040:c:a0a7:974:71c7:ca89]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-220d556d66fsm89178635ad.180.2025.02.18.05.08.28 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 18 Feb 2025 05:08:29 -0800 (PST) From: James Almer To: ffmpeg-devel@ffmpeg.org Date: Tue, 18 Feb 2025 10:08:03 -0300 Message-ID: <20250218130813.74-1-jamrial@gmail.com> X-Mailer: git-send-email 2.48.1 MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 01/11] avutil/opt: allow passing a fake object to av_opt_set() X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Archived-At: List-Archive: List-Post: 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 --- 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".