From patchwork Sat Sep 28 14:28:28 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anton Khirnov X-Patchwork-Id: 51915 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a59:d8ca:0:b0:48e:c0f8:d0de with SMTP id dy10csp1017438vqb; Sat, 28 Sep 2024 07:36:12 -0700 (PDT) X-Forwarded-Encrypted: i=2; AJvYcCVS+JEhsfxBWsIBBMdCkgj/U7Wvg79wj0YRID8tecKX2oxFsxerVGAkdmob4PpJMdI0sAVJS+/xJpludRKgKl0D@gmail.com X-Google-Smtp-Source: AGHT+IEvWmvQ/ry6gIivBBQmOfba+raouHCks/CkpFGfzCPD1vixp3/q4OugbynHgN07IyRLeCR8 X-Received: by 2002:a2e:d1a:0:b0:2f7:5d73:92a3 with SMTP id 38308e7fff4ca-2f9d3f7bbdcmr31389591fa.24.1727534171890; Sat, 28 Sep 2024 07:36:11 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1727534171; cv=none; d=google.com; s=arc-20240605; b=h8aHhuDAtY/PqpqgE4+Pp1VQlFFfZfpN4SXzaKdrSveZeCHtoeeQHVfiVnbCy+2V/6 6QQjPInSiKgeLRANjKtMzdbyqrJrYLRerxcg7su47EkwvjH0QvseivtHdYkLuSF3brJ5 h1eq5R8otyBhrcSaLgYxCAbQsSCPeP9T6xb060VK1uqg3LKvFKoefsPXKQYpk9BHlicP ID0LoM8++dDiNGFlEzbMx9AK/fnLb29AjTWCWWvAIos53Ld2T8Hp4J9i9IAU0/78O+L4 L/p9ntu5uFWaTzc8/bm6CCE4p6hfElfS9Spx/NhDIb5nb6YKYLKnCLOWeN9YHCdSRcwY taMQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=sender:errors-to:content-transfer-encoding:reply-to:list-subscribe :list-help:list-post:list-archive:list-unsubscribe:list-id :precedence:subject:mime-version:references:in-reply-to:message-id :date:to:from:dkim-signature:delivered-to; bh=pRbymuyk663l4dhqvSma0rPduD6mT2eKHGsx6uodTlo=; fh=YOA8vD9MJZuwZ71F/05pj6KdCjf6jQRmzLS+CATXUQk=; b=cWwEp4y4bzfPpWtDpqQyRH6vEFAZTzxkkgtczvtOk0JTNcIp08542M22DrQ9f3k+AO e5VraV4JlqP6murGTKbUB3OF1W1CEJ/h4WpP8bbp++/3zs/HXnjIo7RcYdV6HI8u/nml zaLxc8JDFp1/CUAMCbvnpMCOzddGkA+NlUdJ4bkrij9jC/UlBd17+qxw7jby/60qu7DB psG1oqgmHI9RKrsRdTys4BhTwVc8XWIDFINKPdeB0ZrLOpFYXcaFFoVXYPA6JcMqZ5EQ h6aCmJpUTBLsJH8HTrtWjYBXauj/J1hiFhu7efP0l3pBYVEJsfBTZFzNvpreM5BTZDwK u87w==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@khirnov.net header.s=mail header.b=rD4KEK6H; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id 38308e7fff4ca-2f9d460c15asi13079821fa.335.2024.09.28.07.36.11; Sat, 28 Sep 2024 07:36:11 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@khirnov.net header.s=mail header.b=rD4KEK6H; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 5CA3068DA0A; Sat, 28 Sep 2024 17:28:46 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail1.khirnov.net (quelana.khirnov.net [94.230.150.81]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 5CB0268D950 for ; Sat, 28 Sep 2024 17:28:35 +0300 (EEST) Authentication-Results: mail1.khirnov.net; dkim=pass (2048-bit key; unprotected) header.d=khirnov.net header.i=@khirnov.net header.a=rsa-sha256 header.s=mail header.b=rD4KEK6H; dkim-atps=neutral Received: from localhost (mail1.khirnov.net [IPv6:::1]) by mail1.khirnov.net (Postfix) with ESMTP id D74B44DE2 for ; Sat, 28 Sep 2024 16:28:34 +0200 (CEST) Received: from mail1.khirnov.net ([IPv6:::1]) by localhost (mail1.khirnov.net [IPv6:::1]) (amavis, port 10024) with ESMTP id qzVU632FhSF8 for ; Sat, 28 Sep 2024 16:28:34 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=khirnov.net; s=mail; t=1727533712; bh=VDz9Co4fo9YMowO4SJGW4X9Hegq5rRo0qe2rKGIKr7A=; h=From:To:Subject:Date:In-Reply-To:References:From; b=rD4KEK6HZluWjj2qDuFX/btcoT4Jd6CL0iQsM53OU7cDxmoRdpjscMKl9tslmnXQj KdbyW09WkefYeNQ8qIzle7V1FF0JtNRkHy0Ai1+/Z4cdzoAPZZI0QyGkxhQ4oBbbNU rif9zarC9cEaUJ11VWQ8GcouG4x3x0ev9hbOyjhG8bd7Vx6oImzvjppVrkyub6V5H/ U5B6Wes0IeUU0Gzmtafp+9ZbNZ7WdlEoxyuL8rRHDLDTl0o6aRfz1hJZqKIj87Ngbe x82gAKqElqduPEU3YEJ8+FQ3GYZ/Zoj/E6QWkHbMPEwH9qfjLpO8Lyq0NEhuKs5qoE CCgMrtaZX5Rxw== Received: from libav.khirnov.net (libav.khirnov.net [IPv6:2a00:c500:561:201::7]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256 client-signature RSA-PSS (2048 bits) client-digest SHA256) (Client CN "libav.khirnov.net", Issuer "smtp.khirnov.net SMTP CA" (verified OK)) by mail1.khirnov.net (Postfix) with ESMTPS id 9D57D4DE6 for ; Sat, 28 Sep 2024 16:28:32 +0200 (CEST) Received: from libav.khirnov.net (libav.khirnov.net [IPv6:::1]) by libav.khirnov.net (Postfix) with ESMTP id 862513A0998 for ; Sat, 28 Sep 2024 16:28:32 +0200 (CEST) From: Anton Khirnov To: ffmpeg-devel@ffmpeg.org Date: Sat, 28 Sep 2024 16:28:28 +0200 Message-ID: <20240928142830.961-3-anton@khirnov.net> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240928142830.961-1-anton@khirnov.net> References: <20240928142830.961-1-anton@khirnov.net> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 3/5] lavu/opt: consolidate common prologue for 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 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: CcVtTXzEDa+7 The options-setting functions share several operations at their beginnings - locating the option and the object to operate on, handling the read-only and deprecated flags, and constructing the pointer to the target value. Some of the functions also do not perform some of the checks, although they should. E.g. a deprecation warning is currently only printed for av_opt_set(). Introduce a prologue function that is called from every av_opt_set*() and performs all these common initialization operations. --- libavutil/opt.c | 183 +++++++++++++++++++++++++----------------------- 1 file changed, 97 insertions(+), 86 deletions(-) diff --git a/libavutil/opt.c b/libavutil/opt.c index 2b66318f92..81cb4b10f4 100644 --- a/libavutil/opt.c +++ b/libavutil/opt.c @@ -155,6 +155,49 @@ static void opt_free_array(const AVOption *o, void *parray, unsigned *count) *count = 0; } +/** + * Perform common setup for option-setting functions. + * + * @param require_type when non-0, require the option to be of this type + * @param ptgt target object is written here + * @param po the option is written here + * @param pdst pointer to option value is written here + */ +static int opt_set_init(void *obj, const char *name, int search_flags, + int require_type, + void **ptgt, const AVOption **po, void **pdst) +{ + const AVOption *o; + void *tgt; + + o = av_opt_find2(obj, name, NULL, 0, search_flags, &tgt); + if (!o || !tgt) + return AVERROR_OPTION_NOT_FOUND; + + if (o->flags & AV_OPT_FLAG_READONLY) + return AVERROR(EINVAL); + + if (require_type && (o->type != require_type)) { + av_log(obj, AV_LOG_ERROR, + "Tried to set option '%s' of type %s from value of type %s, " + "this is not supported\n", o->name, opt_type_desc[o->type].name, + opt_type_desc[require_type].name); + return AVERROR(EINVAL); + } + + if (o->flags & AV_OPT_FLAG_DEPRECATED) + av_log(obj, AV_LOG_WARNING, "The \"%s\" option is deprecated: %s\n", name, o->help); + + if (po) + *po = o; + if (ptgt) + *ptgt = tgt; + if (pdst) + *pdst = ((uint8_t *)tgt) + o->offset; + + return 0; +} + static int read_number(const AVOption *o, const void *dst, double *num, int *den, int64_t *intnum) { switch (TYPE_BASE(o->type)) { @@ -751,17 +794,12 @@ fail: int av_opt_set(void *obj, const char *name, const char *val, int search_flags) { void *dst, *target_obj; - const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj); - if (!o || !target_obj) - return AVERROR_OPTION_NOT_FOUND; + const AVOption *o; + int ret; - if (o->flags & AV_OPT_FLAG_READONLY) - return AVERROR(EINVAL); - - if (o->flags & AV_OPT_FLAG_DEPRECATED) - av_log(obj, AV_LOG_WARNING, "The \"%s\" option is deprecated: %s\n", name, o->help); - - dst = ((uint8_t *)target_obj) + o->offset; + ret = opt_set_init(obj, name, search_flags, 0, &target_obj, &o, &dst); + if (ret < 0) + return ret; return ((o->type & AV_OPT_TYPE_FLAG_ARRAY) ? opt_set_array : opt_set_elem)(obj, target_obj, o, val, dst); @@ -785,55 +823,50 @@ OPT_EVAL_NUMBER(double, AV_OPT_TYPE_DOUBLE, double) OPT_EVAL_NUMBER(q, AV_OPT_TYPE_RATIONAL, AVRational) static int set_number(void *obj, const char *name, double num, int den, int64_t intnum, - int search_flags) + int search_flags, int require_type) { - void *dst, *target_obj; - const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj); + void *dst; + const AVOption *o; + int ret; - if (!o || !target_obj) - return AVERROR_OPTION_NOT_FOUND; + ret = opt_set_init(obj, name, search_flags, require_type, NULL, &o, &dst); + if (ret < 0) + return ret; - if ((o->flags & AV_OPT_FLAG_READONLY) || (o->type & AV_OPT_TYPE_FLAG_ARRAY)) - return AVERROR(EINVAL); - - dst = ((uint8_t *)target_obj) + o->offset; return write_number(obj, o, dst, num, den, intnum); } int av_opt_set_int(void *obj, const char *name, int64_t val, int search_flags) { - return set_number(obj, name, 1, 1, val, search_flags); + return set_number(obj, name, 1, 1, val, search_flags, 0); } int av_opt_set_double(void *obj, const char *name, double val, int search_flags) { - return set_number(obj, name, val, 1, 1, search_flags); + return set_number(obj, name, val, 1, 1, search_flags, 0); } int av_opt_set_q(void *obj, const char *name, AVRational val, int search_flags) { - return set_number(obj, name, val.num, val.den, 1, search_flags); + return set_number(obj, name, val.num, val.den, 1, search_flags, 0); } int av_opt_set_bin(void *obj, const char *name, const uint8_t *val, int len, int search_flags) { - void *target_obj; - const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj); uint8_t *ptr; uint8_t **dst; int *lendst; + int ret; - if (!o || !target_obj) - return AVERROR_OPTION_NOT_FOUND; - - if (o->type != AV_OPT_TYPE_BINARY || o->flags & AV_OPT_FLAG_READONLY) - return AVERROR(EINVAL); + ret = opt_set_init(obj, name, search_flags, AV_OPT_TYPE_BINARY, + NULL, NULL, (void**)&dst); + if (ret < 0) + return ret; ptr = len ? av_malloc(len) : NULL; if (len && !ptr) return AVERROR(ENOMEM); - dst = (uint8_t **)(((uint8_t *)target_obj) + o->offset); lendst = (int *)(dst + 1); av_free(*dst); @@ -847,59 +880,42 @@ int av_opt_set_bin(void *obj, const char *name, const uint8_t *val, int len, int int av_opt_set_image_size(void *obj, const char *name, int w, int h, int search_flags) { - void *target_obj; - const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj); + const AVOption *o; + int *dst; + int ret; + + ret = opt_set_init(obj, name, search_flags, AV_OPT_TYPE_IMAGE_SIZE, + NULL, &o, (void**)&dst); + if (ret < 0) + return ret; - if (!o || !target_obj) - return AVERROR_OPTION_NOT_FOUND; - if (o->type != AV_OPT_TYPE_IMAGE_SIZE) { - av_log(obj, AV_LOG_ERROR, - "The value set by option '%s' is not an image size.\n", o->name); - return AVERROR(EINVAL); - } if (w<0 || h<0) { av_log(obj, AV_LOG_ERROR, "Invalid negative size value %dx%d for size '%s'\n", w, h, o->name); return AVERROR(EINVAL); } - *(int *)(((uint8_t *)target_obj) + o->offset) = w; - *(int *)(((uint8_t *)target_obj+sizeof(int)) + o->offset) = h; + + dst[0] = w; + dst[1] = h; + return 0; } int av_opt_set_video_rate(void *obj, const char *name, AVRational val, int search_flags) { - void *target_obj; - const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj); - - if (!o || !target_obj) - return AVERROR_OPTION_NOT_FOUND; - if (o->type != AV_OPT_TYPE_VIDEO_RATE) { - av_log(obj, AV_LOG_ERROR, - "The value set by option '%s' is not a video rate.\n", - o->name); - return AVERROR(EINVAL); - } - if (val.num <= 0 || val.den <= 0) - return AVERROR(EINVAL); - return set_number(obj, name, val.num, val.den, 1, search_flags); + return set_number(obj, name, val.num, val.den, 1, search_flags, AV_OPT_TYPE_VIDEO_RATE); } static int set_format(void *obj, const char *name, int fmt, int search_flags, enum AVOptionType type, const char *desc, int nb_fmts) { - void *target_obj; - const AVOption *o = av_opt_find2(obj, name, NULL, 0, - search_flags, &target_obj); - int min, max; + const AVOption *o; + int *dst; + int min, max, ret; - if (!o || !target_obj) - return AVERROR_OPTION_NOT_FOUND; - if (o->type != type) { - av_log(obj, AV_LOG_ERROR, - "The value set by option '%s' is not a %s format", name, desc); - return AVERROR(EINVAL); - } + ret = opt_set_init(obj, name, search_flags, type, NULL, &o, (void**)&dst); + if (ret < 0) + return ret; min = FFMAX(o->min, -1); max = FFMIN(o->max, nb_fmts-1); @@ -910,7 +926,7 @@ static int set_format(void *obj, const char *name, int fmt, int search_flags, fmt, name, desc, min, max); return AVERROR(ERANGE); } - *(int *)(((uint8_t *)target_obj) + o->offset) = fmt; + *dst = fmt; return 0; } @@ -927,16 +943,14 @@ int av_opt_set_sample_fmt(void *obj, const char *name, enum AVSampleFormat fmt, int av_opt_set_dict_val(void *obj, const char *name, const AVDictionary *val, int search_flags) { - void *target_obj; AVDictionary **dst; - const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj); + int ret; - if (!o || !target_obj) - return AVERROR_OPTION_NOT_FOUND; - if (o->flags & AV_OPT_FLAG_READONLY) - return AVERROR(EINVAL); + ret = opt_set_init(obj, name, search_flags, AV_OPT_TYPE_DICT, NULL, NULL, + (void**)&dst); + if (ret < 0) + return ret; - dst = (AVDictionary **)(((uint8_t *)target_obj) + o->offset); av_dict_free(dst); return av_dict_copy(dst, val, 0); @@ -946,16 +960,13 @@ int av_opt_set_chlayout(void *obj, const char *name, const AVChannelLayout *channel_layout, int search_flags) { - void *target_obj; - const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj); AVChannelLayout *dst; + int ret; - if (!o || !target_obj) - return AVERROR_OPTION_NOT_FOUND; - if (o->flags & AV_OPT_FLAG_READONLY) - return AVERROR(EINVAL); - - dst = (AVChannelLayout*)((uint8_t*)target_obj + o->offset); + ret = opt_set_init(obj, name, search_flags, AV_OPT_TYPE_CHLAYOUT, NULL, NULL, + (void**)&dst); + if (ret < 0) + return ret; return av_channel_layout_copy(dst, channel_layout); } @@ -2243,15 +2254,15 @@ int av_opt_set_array(void *obj, const char *name, int search_flags, int ret = 0; - o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj); - if (!o || !target_obj) - return AVERROR_OPTION_NOT_FOUND; + ret = opt_set_init(obj, name, search_flags, 0, &target_obj, &o, &parray); + if (ret < 0) + return ret; + if (!(o->type & AV_OPT_TYPE_FLAG_ARRAY) || (val_type & AV_OPT_TYPE_FLAG_ARRAY)) return AVERROR(EINVAL); arr = o->default_val.arr; - parray = (uint8_t *)target_obj + o->offset; array_size = opt_array_pcount(parray); elem_size = opt_type_desc[TYPE_BASE(o->type)].size;