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 ESMTP id 1350E4874C for ; Wed, 17 Jan 2024 09:22:57 +0000 (UTC) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 6E29B68CDFB; Wed, 17 Jan 2024 11:22:48 +0200 (EET) Received: from mail1.khirnov.net (quelana.khirnov.net [94.230.150.81]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 4F9BE68C845 for ; Wed, 17 Jan 2024 11:22:40 +0200 (EET) 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=N0OnETFK; dkim-atps=neutral Received: from localhost (mail1.khirnov.net [IPv6:::1]) by mail1.khirnov.net (Postfix) with ESMTP id EE93619B7 for ; Wed, 17 Jan 2024 10:22:39 +0100 (CET) Received: from mail1.khirnov.net ([IPv6:::1]) by localhost (mail1.khirnov.net [IPv6:::1]) (amavis, port 10024) with ESMTP id aeqEXpmafDyw for ; Wed, 17 Jan 2024 10:22:39 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=khirnov.net; s=mail; t=1705483358; bh=CiycCJQHLOiVBs/faq5cOi4FfOmZxmI/jSYpruFdPWg=; h=From:To:Subject:Date:In-Reply-To:References:From; b=N0OnETFKV0krC08HVE1xs/xYI8sjU20p8qFPE51P+r3JNv1mfs8GagopsjRryDFdb NlgiqtEU4gEVjNPq615OI+jSBCu/HyFn60QooQCl8Q92evC6vVuMKtEzd2Cni0W0wd +3mV2TgjdRCf3dYMd5POE9QZAstzEApzutBl+aN4BFw14mF74GeOQ4ZoFg5cdAsgui IR5Ro8V1UjS1eHR3zIQrYA8CEgWPAfoE3vjApLB3V39U/A0JBU3mSGU+rH4NzPvKiQ Sr2QdhLi61MeKxlvOWTNvMgBnWITZYDFlUEvEQi0MLqfMWpo52WIH+9H0YWdElMyWM r2lP9BsPIV61g== 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 2C34D19B9 for ; Wed, 17 Jan 2024 10:22:38 +0100 (CET) Received: from libav.khirnov.net (libav.khirnov.net [IPv6:::1]) by libav.khirnov.net (Postfix) with ESMTP id 13EE63A061F for ; Wed, 17 Jan 2024 10:22:38 +0100 (CET) From: Anton Khirnov To: ffmpeg-devel@ffmpeg.org Date: Wed, 17 Jan 2024 10:22:31 +0100 Message-ID: <20240117092233.8503-4-anton@khirnov.net> X-Mailer: git-send-email 2.42.0 In-Reply-To: <20240117092233.8503-1-anton@khirnov.net> References: <20240117092233.8503-1-anton@khirnov.net> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 4/6] fftools/cmdutils: add option syntax for loading arbitrary arguments from a file 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: Aligned with analogous feature for filter options in ffmpeg CLI. --- Changelog | 2 + doc/fftools-common-opts.texi | 9 ++++ fftools/cmdutils.c | 99 ++++++++++++++++++++++++++++++------ fftools/cmdutils.h | 3 ++ fftools/ffmpeg.h | 1 - fftools/ffmpeg_opt.c | 26 ---------- 6 files changed, 97 insertions(+), 43 deletions(-) diff --git a/Changelog b/Changelog index 6b7c1439cd..c40b6d08fd 100644 --- a/Changelog +++ b/Changelog @@ -20,6 +20,8 @@ version : - fsync filter - Raw Captions with Time (RCWT) closed caption muxer - ffmpeg CLI -bsf option may now be used for input as well as output +- ffmpeg CLI options may now be used as -/opt , which is equivalent + to -opt > version 6.1: - libaribcaption decoder diff --git a/doc/fftools-common-opts.texi b/doc/fftools-common-opts.texi index f459bfdc1d..1974d79a4c 100644 --- a/doc/fftools-common-opts.texi +++ b/doc/fftools-common-opts.texi @@ -13,6 +13,15 @@ corresponding value to true. They can be set to false by prefixing the option name with "no". For example using "-nofoo" will set the boolean option with name "foo" to false. +Options that take arguments support a special syntax where the argument given on +the command line is interpreted as a path to the file from which the actual +argument value is loaded. To use this feature, add a forward slash '/' +immediately before the option name (after the leading dash). E.g. +@example +ffmpeg -i INPUT -/filter:v filter.script OUTPUT +@end example +will load a filtergraph description from the file named @file{filter.script}. + @anchor{Stream specifiers} @section Stream specifiers Some options are applied per-stream, e.g. bitrate or codec. Stream specifiers diff --git a/fftools/cmdutils.c b/fftools/cmdutils.c index 44228ea637..d7d5ddee45 100644 --- a/fftools/cmdutils.c +++ b/fftools/cmdutils.c @@ -37,6 +37,7 @@ #include "libswresample/swresample.h" #include "libavutil/avassert.h" #include "libavutil/avstring.h" +#include "libavutil/bprint.h" #include "libavutil/channel_layout.h" #include "libavutil/display.h" #include "libavutil/getenv_utf8.h" @@ -150,6 +151,9 @@ void show_help_children(const AVClass *class, int flags) static const OptionDef *find_option(const OptionDef *po, const char *name) { + if (*name == '/') + name++; + while (po->name) { const char *end; if (av_strstart(name, po->name, &end) && (!*end || *end == ':')) @@ -239,9 +243,32 @@ static int write_option(void *optctx, const OptionDef *po, const char *opt, * a global var*/ void *dst = po->flags & OPT_FLAG_OFFSET ? (uint8_t *)optctx + po->u.off : po->u.dst_ptr; + char *arg_allocated = NULL; + SpecifierOptList *sol = NULL; double num; - int ret; + int ret = 0; + + if (*opt == '/') { + opt++; + + if (po->type == OPT_TYPE_BOOL) { + av_log(NULL, AV_LOG_FATAL, + "Requested to load an argument from file for a bool option '%s'\n", + po->name); + return AVERROR(EINVAL); + } + + arg_allocated = file_read(arg); + if (!arg_allocated) { + av_log(NULL, AV_LOG_FATAL, + "Error reading the value for option '%s' from file: %s\n", + opt, arg); + return AVERROR(EINVAL); + } + + arg = arg_allocated; + } if (po->flags & OPT_FLAG_SPEC) { char *p = strchr(opt, ':'); @@ -250,32 +277,42 @@ static int write_option(void *optctx, const OptionDef *po, const char *opt, sol = dst; ret = GROW_ARRAY(sol->opt, sol->nb_opt); if (ret < 0) - return ret; + goto finish; str = av_strdup(p ? p + 1 : ""); - if (!str) - return AVERROR(ENOMEM); + if (!str) { + ret = AVERROR(ENOMEM); + goto finish; + } sol->opt[sol->nb_opt - 1].specifier = str; dst = &sol->opt[sol->nb_opt - 1].u; } if (po->type == OPT_TYPE_STRING) { char *str; - str = av_strdup(arg); + if (arg_allocated) { + str = arg_allocated; + arg_allocated = NULL; + } else + str = av_strdup(arg); av_freep(dst); - if (!str) - return AVERROR(ENOMEM); + + if (!str) { + ret = AVERROR(ENOMEM); + goto finish; + } + *(char **)dst = str; } else if (po->type == OPT_TYPE_BOOL || po->type == OPT_TYPE_INT) { ret = parse_number(opt, arg, OPT_TYPE_INT64, INT_MIN, INT_MAX, &num); if (ret < 0) - return ret; + goto finish; *(int *)dst = num; } else if (po->type == OPT_TYPE_INT64) { ret = parse_number(opt, arg, OPT_TYPE_INT64, INT64_MIN, INT64_MAX, &num); if (ret < 0) - return ret; + goto finish; *(int64_t *)dst = num; } else if (po->type == OPT_TYPE_TIME) { @@ -283,18 +320,18 @@ static int write_option(void *optctx, const OptionDef *po, const char *opt, if (ret < 0) { av_log(NULL, AV_LOG_ERROR, "Invalid duration for option %s: %s\n", opt, arg); - return ret; + goto finish; } } else if (po->type == OPT_TYPE_FLOAT) { ret = parse_number(opt, arg, OPT_TYPE_FLOAT, -INFINITY, INFINITY, &num); if (ret < 0) - return ret; + goto finish; *(float *)dst = num; } else if (po->type == OPT_TYPE_DOUBLE) { ret = parse_number(opt, arg, OPT_TYPE_DOUBLE, -INFINITY, INFINITY, &num); if (ret < 0) - return ret; + goto finish; *(double *)dst = num; } else { @@ -307,11 +344,13 @@ static int write_option(void *optctx, const OptionDef *po, const char *opt, av_log(NULL, AV_LOG_ERROR, "Failed to set value '%s' for option '%s': %s\n", arg, opt, av_err2str(ret)); - return ret; + goto finish; } } - if (po->flags & OPT_EXIT) - return AVERROR_EXIT; + if (po->flags & OPT_EXIT) { + ret = AVERROR_EXIT; + goto finish; + } if (sol) { sol->type = po->type; @@ -319,7 +358,9 @@ static int write_option(void *optctx, const OptionDef *po, const char *opt, find_option(defs, po->u1.name_canon) : po; } - return 0; +finish: + av_freep(&arg_allocated); + return ret; } int parse_option(void *optctx, const char *opt, const char *arg, @@ -1088,3 +1129,29 @@ double get_rotation(const int32_t *displaymatrix) return theta; } + +/* read file contents into a string */ +char *file_read(const char *filename) +{ + AVIOContext *pb = NULL; + int ret = avio_open(&pb, filename, AVIO_FLAG_READ); + AVBPrint bprint; + char *str; + + if (ret < 0) { + av_log(NULL, AV_LOG_ERROR, "Error opening file %s.\n", filename); + return NULL; + } + + av_bprint_init(&bprint, 0, AV_BPRINT_SIZE_UNLIMITED); + ret = avio_read_to_bprint(pb, &bprint, SIZE_MAX); + avio_closep(&pb); + if (ret < 0) { + av_bprint_finalize(&bprint, NULL); + return NULL; + } + ret = av_bprint_finalize(&bprint, &str); + if (ret < 0) + return NULL; + return str; +} diff --git a/fftools/cmdutils.h b/fftools/cmdutils.h index 53227abb47..8fa5ad4fc7 100644 --- a/fftools/cmdutils.h +++ b/fftools/cmdutils.h @@ -470,4 +470,7 @@ void *allocate_array_elem(void *array, size_t elem_size, int *nb_elems); double get_rotation(const int32_t *displaymatrix); +/* read file contents into a string */ +char *file_read(const char *filename); + #endif /* FFTOOLS_CMDUTILS_H */ diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 6137ac991e..cdde3c2c03 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -652,7 +652,6 @@ void remove_avoptions(AVDictionary **a, AVDictionary *b); int check_avoptions(AVDictionary *m); int assert_file_overwrite(const char *filename); -char *file_read(const char *filename); AVDictionary *strip_specifiers(const AVDictionary *dict); int find_codec(void *logctx, const char *name, enum AVMediaType type, int encoder, const AVCodec **codec); diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index 563f443bd8..ffb2c42421 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -765,32 +765,6 @@ int assert_file_overwrite(const char *filename) return 0; } -/* read file contents into a string */ -char *file_read(const char *filename) -{ - AVIOContext *pb = NULL; - int ret = avio_open(&pb, filename, AVIO_FLAG_READ); - AVBPrint bprint; - char *str; - - if (ret < 0) { - av_log(NULL, AV_LOG_ERROR, "Error opening file %s.\n", filename); - return NULL; - } - - av_bprint_init(&bprint, 0, AV_BPRINT_SIZE_UNLIMITED); - ret = avio_read_to_bprint(pb, &bprint, SIZE_MAX); - avio_closep(&pb); - if (ret < 0) { - av_bprint_finalize(&bprint, NULL); - return NULL; - } - ret = av_bprint_finalize(&bprint, &str); - if (ret < 0) - return NULL; - return str; -} - /* arg format is "output-stream-index:streamid-value". */ static int opt_streamid(void *optctx, const char *opt, const char *arg) { -- 2.42.0 _______________________________________________ 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".