From patchwork Fri Apr 12 23:16:58 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Almer X-Patchwork-Id: 48035 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a21:670b:b0:1a9:af23:56c1 with SMTP id wh11csp572944pzb; Fri, 12 Apr 2024 16:17:35 -0700 (PDT) X-Forwarded-Encrypted: i=2; AJvYcCX2wAFncMs0ABsGxQa/jPMxo/AxhnOqBuHTv8Zwgh6AswL2cUYFg1aQlYISHL5DU5BK2PX77kuiVdiYmXnrlakWTUuLUssbvXQpCA== X-Google-Smtp-Source: AGHT+IHpsfwvfb7O+10cdO33XgNGoHwtu/Ysh1wyIokADdu18eCsORaIaZu6YycJ0JeVTNE+/IgW X-Received: by 2002:ac2:410a:0:b0:515:bacd:adbf with SMTP id b10-20020ac2410a000000b00515bacdadbfmr2415338lfi.34.1712963855479; Fri, 12 Apr 2024 16:17:35 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1712963855; cv=none; d=google.com; s=arc-20160816; b=Ho72m64GiipjesXWZwFuidntKae0VB0I5Ujqobzwpf+QkQS9oO21fgLhzDjvCxq1xF hdLAdZyzdSIwnWzwDIo1Z6xUzqtTjXajvpmPxd7c7v4hXXAgwG1vMJ5SNkcqZufa4d8J lFP1euh6/j+LQVWMy8F5e1eEzfDfCYSpurYETQlP7//poCax1br8fVHEr6hLpToB5fsi Uaq567dAFXwYFnDddwJ+eQ6rw5unfqHcJRLHuVRO/YBEMHogIGjijH8Gb0Yn4iSUbbwx /tSHeqEj/uZrr0qr3sjglYbuIiva8S0Jk3u706lMg5mTXmuxSHWrhE9YuIwZvlecGOFJ +o8w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; 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=kXzWWoN70o18WZ7I0Y+mguC9NdOCQE2783T0Fj6AoQ0=; fh=YOA8vD9MJZuwZ71F/05pj6KdCjf6jQRmzLS+CATXUQk=; b=GWxdkhVCKRD/Y1YC1sTItbIxEDjx4vh2DBjgfyPI6CTCQGGoyiK4iG/aSlZJTHrNHL 7ZC9Hvl7nUH9ClvIGI6zLMW0xz3Cys6CWOgr4/0J3BHYZVnzPKHJfz+AcsvG8mGKtBJr b/tuVd6jtOLzLxV498kN1FGV4CUwpd9x3K8oOgz9LX/nv5kK+81NQnGc3YPw/djeMG9j 1EQtK7aab+FMDlSyVh3SD/BUbgUn2z07dDILzlCIv5xThFsgGf3mvFuzJ63++JC1lLtR r9WR5VlR+N4Vb6mVqWVkPOdkgxKiSJEi+YXkO+3DOWwlhGp/i9/aEWIebhTQkgd2P+t6 NyqA==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20230601 header.b=TWC+A4Z3; 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; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id n13-20020a05640205cd00b0056e754a3a4dsi2138964edx.617.2024.04.12.16.17.35; Fri, 12 Apr 2024 16:17:35 -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=@gmail.com header.s=20230601 header.b=TWC+A4Z3; 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; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id C883668D2E8; Sat, 13 Apr 2024 02:17:23 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-pj1-f48.google.com (mail-pj1-f48.google.com [209.85.216.48]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 43DD468CFE3 for ; Sat, 13 Apr 2024 02:17:17 +0300 (EEST) Received: by mail-pj1-f48.google.com with SMTP id 98e67ed59e1d1-2a502547460so999964a91.2 for ; Fri, 12 Apr 2024 16:17:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1712963835; x=1713568635; darn=ffmpeg.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=LhoFMpDJThqsJKaGaH6h4zH2PmgCKB6XwtjwZbrvBWg=; b=TWC+A4Z33wFqHilrltlOibwXkp5afSNDbfWWWvNjIvGTE3rlDofiq53rWaKlHN6C0M W99qRGGvlx9hIn70HsYxOIm/Pl18grmzBlvzaPofEZPXBlx+z7t06c36oVkAvc7VbVRS 3AkCj8LXttd/ftZnrdFvTtW61odWaVm42pqWfSpW6l2/sio7pCsGeUz7UY/+2OmYbxO+ lNYWGqMhXLTLuYbIskfGdD8PEswG1n4fpnTJEvvBDqnNoNYHPbRI7/g+ImLknb/kfN0c rDjsb6RuYbb0yp8S2U9+mgdb/dsA/27pa3V1h6DuAuPn/owVUQgCaR4lzsqC3d/8skMH xQtg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1712963835; x=1713568635; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=LhoFMpDJThqsJKaGaH6h4zH2PmgCKB6XwtjwZbrvBWg=; b=oGU6OymHhl2Ci6GWGxpBBeVmFHb4TdF9NMAhM5dFtSnFvHlWB2RxL9CSMniXeT/Map 8ES3sFK4qMC94vaJoSQk6qURyKWZ54HfhSfb+xmSV40RMkvXuTosqk/ICBYkxNEOL0xo vpPcE2BEJg1wd5f7gcYmBp4qF5i0BTjSFfPoI2/sCxdx1qLjIpMjIj3zWg+BSGFmzzb3 BZyFBW+pR47nQbGO2aOeH5DFVyUhXn9Q34mh1s8Uu3hCnV9gdgMouPvnMVM7y6rEitlY un4UL1ZlZb/GqHW73aVugX3g+0Z5pEf8cMcbHlusytNFHP8rU47G2pCliR8tqK1aEMrV F1fA== X-Gm-Message-State: AOJu0YzX4RpPQY+sHjqKKuG8sm1zZzIFzbBzDAjpraC7xQJBBHDgHIbe hcDBuTUp89AAfRol/F+T+eFy/q83m3KbNUfIe+xIg1wnz8zGYgcDlZFOyA== X-Received: by 2002:a17:90b:4b48:b0:2a2:227a:50fc with SMTP id mi8-20020a17090b4b4800b002a2227a50fcmr3534936pjb.41.1712963834557; Fri, 12 Apr 2024 16:17:14 -0700 (PDT) Received: from localhost.localdomain ([190.194.167.233]) by smtp.gmail.com with ESMTPSA id x23-20020a17090a165700b0029b59bf77b4sm5438284pje.42.2024.04.12.16.17.13 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 12 Apr 2024 16:17:14 -0700 (PDT) From: James Almer To: ffmpeg-devel@ffmpeg.org Date: Fri, 12 Apr 2024 20:16:58 -0300 Message-ID: <20240412231658.4625-2-jamrial@gmail.com> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240412231658.4625-1-jamrial@gmail.com> References: <20240412231658.4625-1-jamrial@gmail.com> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 2/2] avutil/opt: add support for children objects in av_opt_serialize 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: giVgktMw/7d0 Signed-off-by: James Almer --- libavutil/opt.c | 65 +++++++++++++++++++++++++++++-------------- libavutil/opt.h | 1 + libavutil/tests/opt.c | 47 +++++++++++++++++++++++++++++-- tests/ref/fate/opt | 2 +- 4 files changed, 90 insertions(+), 25 deletions(-) diff --git a/libavutil/opt.c b/libavutil/opt.c index d11e9d2ac5..ecbf7efe5f 100644 --- a/libavutil/opt.c +++ b/libavutil/opt.c @@ -2386,26 +2386,22 @@ int av_opt_is_set_to_default_by_name(void *obj, const char *name, int search_fla return av_opt_is_set_to_default(target, o); } -int av_opt_serialize(void *obj, int opt_flags, int flags, char **buffer, - const char key_val_sep, const char pairs_sep) +static int opt_serialize(void *obj, int opt_flags, int flags, int *cnt, + AVBPrint *bprint, const char key_val_sep, const char pairs_sep) { const AVOption *o = NULL; + void *child = NULL; uint8_t *buf; - AVBPrint bprint; - int ret, cnt = 0; + int ret; const char special_chars[] = {pairs_sep, key_val_sep, '\0'}; - if (pairs_sep == '\0' || key_val_sep == '\0' || pairs_sep == key_val_sep || - pairs_sep == '\\' || key_val_sep == '\\') { - av_log(obj, AV_LOG_ERROR, "Invalid separator(s) found."); - return AVERROR(EINVAL); - } - - if (!obj || !buffer) - return AVERROR(EINVAL); - - *buffer = NULL; - av_bprint_init(&bprint, 64, AV_BPRINT_SIZE_UNLIMITED); + if (flags & AV_OPT_SERIALIZE_SEARCH_CHILDREN) + while (child = av_opt_child_next(obj, child)) { + ret = opt_serialize(child, opt_flags, flags, cnt, bprint, + key_val_sep, pairs_sep); + if (ret < 0) + return ret; + } while (o = av_opt_next(obj, o)) { if (o->type == AV_OPT_TYPE_CONST) @@ -2417,18 +2413,45 @@ int av_opt_serialize(void *obj, int opt_flags, int flags, char **buffer, if (flags & AV_OPT_SERIALIZE_SKIP_DEFAULTS && av_opt_is_set_to_default(obj, o) > 0) continue; if ((ret = av_opt_get(obj, o->name, 0, &buf)) < 0) { - av_bprint_finalize(&bprint, NULL); + av_bprint_finalize(bprint, NULL); return ret; } if (buf) { - if (cnt++) - av_bprint_append_data(&bprint, &pairs_sep, 1); - av_bprint_escape(&bprint, o->name, special_chars, AV_ESCAPE_MODE_BACKSLASH, 0); - av_bprint_append_data(&bprint, &key_val_sep, 1); - av_bprint_escape(&bprint, buf, special_chars, AV_ESCAPE_MODE_BACKSLASH, 0); + if ((*cnt)++) + av_bprint_append_data(bprint, &pairs_sep, 1); + av_bprint_escape(bprint, o->name, special_chars, AV_ESCAPE_MODE_BACKSLASH, 0); + av_bprint_append_data(bprint, &key_val_sep, 1); + av_bprint_escape(bprint, buf, special_chars, AV_ESCAPE_MODE_BACKSLASH, 0); av_freep(&buf); } } + + return 0; +} + +int av_opt_serialize(void *obj, int opt_flags, int flags, char **buffer, + const char key_val_sep, const char pairs_sep) +{ + AVBPrint bprint; + int ret, cnt = 0; + + if (pairs_sep == '\0' || key_val_sep == '\0' || pairs_sep == key_val_sep || + pairs_sep == '\\' || key_val_sep == '\\') { + av_log(obj, AV_LOG_ERROR, "Invalid separator(s) found."); + return AVERROR(EINVAL); + } + + if (!obj || !buffer) + return AVERROR(EINVAL); + + *buffer = NULL; + av_bprint_init(&bprint, 64, AV_BPRINT_SIZE_UNLIMITED); + + ret = opt_serialize(obj, opt_flags, flags, &cnt, &bprint, + key_val_sep, pairs_sep); + if (ret < 0) + return ret; + ret = av_bprint_finalize(&bprint, buffer); if (ret < 0) return ret; diff --git a/libavutil/opt.h b/libavutil/opt.h index e6013662f6..855e363091 100644 --- a/libavutil/opt.h +++ b/libavutil/opt.h @@ -929,6 +929,7 @@ int av_opt_flag_is_set(void *obj, const char *field_name, const char *flag_name) #define AV_OPT_SERIALIZE_SKIP_DEFAULTS 0x00000001 ///< Serialize options that are not set to default values only. #define AV_OPT_SERIALIZE_OPT_FLAGS_EXACT 0x00000002 ///< Serialize options that exactly match opt_flags only. +#define AV_OPT_SERIALIZE_SEARCH_CHILDREN 0x00000004 ///< Serialize options in possible children of the given object. /** * Serialize object's options. diff --git a/libavutil/tests/opt.c b/libavutil/tests/opt.c index 32301ba842..53d8951bcf 100644 --- a/libavutil/tests/opt.c +++ b/libavutil/tests/opt.c @@ -30,6 +30,7 @@ typedef struct TestContext { const AVClass *class; + struct ChildContext *child; int num; int toggle; char *string; @@ -123,10 +124,46 @@ static const char *test_get_name(void *ctx) return "test"; } +typedef struct ChildContext { + const AVClass *class; + int64_t child_num64; + int child_num; +} ChildContext; + +#undef OFFSET +#define OFFSET(x) offsetof(ChildContext, x) + +static const AVOption child_options[]= { + {"child_num64", "set num 64bit", OFFSET(child_num64), AV_OPT_TYPE_INT64, { .i64 = 0 }, 0, 100, 1 }, + {"child_num", "set child_num", OFFSET(child_num), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 100, 1 }, + { NULL }, +}; + +static const char *child_get_name(void *ctx) +{ + return "child"; +} + +static const AVClass child_class = { + .class_name = "ChildContext", + .item_name = child_get_name, + .option = child_options, + .version = LIBAVUTIL_VERSION_INT, +}; + +static void *test_child_next(void *obj, void *prev) +{ + TestContext *test_ctx = obj; + if (!prev) + return test_ctx->child; + return NULL; +} + static const AVClass test_class = { .class_name = "TestContext", .item_name = test_get_name, .option = test_options, + .child_next = test_child_next, .version = LIBAVUTIL_VERSION_INT, }; @@ -277,11 +314,15 @@ int main(void) av_set_options_string(&test_ctx, buf, "=", ","); av_free(buf); if (av_opt_serialize(&test_ctx, 0, 0, &buf, '=', ',') >= 0) { + ChildContext child_ctx = { 0 }; printf("%s\n", buf); av_free(buf); - if (av_opt_serialize(&test_ctx, 0, AV_OPT_SERIALIZE_SKIP_DEFAULTS, &buf, '=', ',') >= 0) { - if (strlen(buf)) - printf("%s\n", buf); + test_ctx.child = &child_ctx; + child_ctx.class = &child_class; + if (av_opt_serialize(&test_ctx, 0, + AV_OPT_SERIALIZE_SKIP_DEFAULTS|AV_OPT_SERIALIZE_SEARCH_CHILDREN, + &buf, '=', ',') >= 0) { + printf("%s\n", buf); av_free(buf); } } diff --git a/tests/ref/fate/opt b/tests/ref/fate/opt index 43bf0929a3..05d57066a1 100644 --- a/tests/ref/fate/opt +++ b/tests/ref/fate/opt @@ -179,7 +179,7 @@ Setting entry with key 'array_int' to value '' Setting entry with key 'array_str' to value 'str0|str\|1|str\\2' Setting entry with key 'array_dict' to value 'k00=v\\\\00:k01=v\,01,k10=v\\=1\\:0' num=0,toggle=1,rational=1/1,string=default,escape=\\\=\,,flags=0x00000001,size=200x300,pix_fmt=0bgr,sample_fmt=s16,video_rate=25/1,duration=0.001,color=0xffc0cbff,cl=hexagonal,bin=62696E00,bin1=,bin2=,num64=1,flt=0.333333,dbl=0.333333,bool1=auto,bool2=true,bool3=false,dict1=,dict2=happy\=\\:-),array_int=,array_str=str0|str\\|1|str\\\\2,array_dict=k00\=v\\\\\\\\00:k01\=v\\\,01\,k10\=v\\\\\=1\\\\:0 -flt=0.333333,dbl=0.333333,array_int= +child_num=0,flt=0.333333,dbl=0.333333,array_int= Testing av_set_options_string() Setting options string ''