From patchwork Wed Feb 3 18:37:35 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?q?Jan_Ekstr=C3=B6m?= X-Patchwork-Id: 25373 Return-Path: X-Original-To: patchwork@ffaux-bg.ffmpeg.org Delivered-To: patchwork@ffaux-bg.ffmpeg.org Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by ffaux.localdomain (Postfix) with ESMTP id 9322F44B48A for ; Wed, 3 Feb 2021 20:44:36 +0200 (EET) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 6E39F689A81; Wed, 3 Feb 2021 20:44:36 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-ed1-f49.google.com (mail-ed1-f49.google.com [209.85.208.49]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 749CC689956 for ; Wed, 3 Feb 2021 20:44:30 +0200 (EET) Received: by mail-ed1-f49.google.com with SMTP id s3so847665edi.7 for ; Wed, 03 Feb 2021 10:44:30 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:subject:date:message-id:mime-version :content-transfer-encoding; bh=C5BTeGMYaZ9TV9g/bRyAynImYlEwSrQW02eZZkJ7OMg=; b=iL9zD24raTsNauD/evF3Y4wDgiFBnOOof8qCI9QB1oKqWtzvCsTYzdjLmME+6P0wHE Oeew3WBV/BFDh5pYFxu2BuioNC0X3V1gFgb3l0SsxqGOZViZSgSJUHnkOqzvwcpq0Fyz Szuf+SiJ99+qVf9kB43Kjl+c7qh1i/SRIOSI2ENYhbKP8sFExKEfhDz+hSumCTNfPJSV QUgm4WaRnUYMZegaRl8eG+tF+/U5/mbn92fnVQRBcwSy1vfld/mJk49av7iKa7N6bVQi LegL5H3CU3c/QGaFRuWUm/JeKCDwa/CtzfSl1kQilwfh33TDUuI1/VtThUp/JEkUuTGc 7PXA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:mime-version :content-transfer-encoding; bh=C5BTeGMYaZ9TV9g/bRyAynImYlEwSrQW02eZZkJ7OMg=; b=qc3jD7j4aJpDTyRedD3CcZGxURCYeCq6TQi1gG+/9dqCXHcV2nqUKPwZNArEAFimGu iaKSsXmcgvKrEuBG6lsvW366YCHlr1l1zTTuRWLphOSDFy5tp2GIoMK1zIpLvbfCiHyE bkjW9thqlt+Qm/GVrJNa/kISpgECx2qIShc4KDdeTvD7T9niweRe8MMqci5h3Hg3cy7+ L8SMF4bYLPW1TpvGTPHQapfqtYTElYEQdfpGZuUUF4JnVFRm8NSLhLa/PFKv+ue0XeYw p0ZH+oLSR6Hm9Sv+C6vWl7peCy+dUPwU2XnXBbF5qblTigolNMqF0t4bk1WFBwCEbM9a qzmQ== X-Gm-Message-State: AOAM530y6HDubkMHLO57yfpViPuXKaf8OX442sicFh80JrMkcWKi/9Pp ruA0xOjtDUB0gvaolpHqhaWGLau+KUI= X-Google-Smtp-Source: ABdhPJyzjrlG8aKkFxML3NdHHBDXiukkrTpvekVxRV7LZydxb+po3Fd1ysDLLJgapysUA5BlfaM13Q== X-Received: by 2002:a2e:5812:: with SMTP id m18mr2453172ljb.83.1612377458634; Wed, 03 Feb 2021 10:37:38 -0800 (PST) Received: from localhost.localdomain (91-159-194-103.elisa-laajakaista.fi. [91.159.194.103]) by smtp.gmail.com with ESMTPSA id n1sm314804lfk.251.2021.02.03.10.37.37 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 03 Feb 2021 10:37:37 -0800 (PST) From: =?utf-8?q?Jan_Ekstr=C3=B6m?= To: ffmpeg-devel@ffmpeg.org Date: Wed, 3 Feb 2021 20:37:35 +0200 Message-Id: <20210203183735.34501-1-jeebjp@gmail.com> X-Mailer: git-send-email 2.29.2 MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH v2] avformat/concatdec: add support for setting input options X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 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" This way protocol or format related options can be set for all of the files opened during concatenation both globally as well as per-file. --- doc/demuxers.texi | 12 +++++++ libavformat/concatdec.c | 69 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 80 insertions(+), 1 deletion(-) diff --git a/doc/demuxers.texi b/doc/demuxers.texi index 3c15ab9eee..0b4ce9a36c 100644 --- a/doc/demuxers.texi +++ b/doc/demuxers.texi @@ -149,6 +149,14 @@ Metadata of the packets of the file. The specified metadata will be set for each file packet. You can specify this directive multiple times to add multiple metadata entries. +@item @code{input_options @var{key=value:key2=value2}} +Input options passed on when reading a specific file, using a :-separated list +of key=value pairs. Requires @code{safe} to be non-positive. Global options for +all files can be set with the @code{input_options} demuxer option. When using +both options on the list of files as well as globally via the demuxer option, +the global ones get applied first and the file-specific options are then applied +on top of them. + @item @code{stream} Introduce a stream in the virtual file. All subsequent stream-related directives apply to the last introduced @@ -204,6 +212,10 @@ expressed in microseconds. The duration metadata is only set if it is known based on the concat file. The default is 0. +@item input_options +Input options to be passed on for all opened inputs using a :-separated list of +key=value pairs. + @end table @subsection Examples diff --git a/libavformat/concatdec.c b/libavformat/concatdec.c index 6d5b9914f9..f4e6609f12 100644 --- a/libavformat/concatdec.c +++ b/libavformat/concatdec.c @@ -52,6 +52,7 @@ typedef struct { int64_t outpoint; AVDictionary *metadata; int nb_streams; + AVDictionary *input_options; } ConcatFile; typedef struct { @@ -66,6 +67,7 @@ typedef struct { ConcatMatchMode stream_match_mode; unsigned auto_convert; int segment_time_metadata; + AVDictionary *input_options; } ConcatContext; static int concat_probe(const AVProbeData *probe) @@ -329,6 +331,7 @@ static int open_file(AVFormatContext *avf, unsigned fileno) { ConcatContext *cat = avf->priv_data; ConcatFile *file = &cat->files[fileno]; + AVDictionary *options = NULL; int ret; if (cat->avf) @@ -344,12 +347,37 @@ static int open_file(AVFormatContext *avf, unsigned fileno) if ((ret = ff_copy_whiteblacklists(cat->avf, avf)) < 0) return ret; - if ((ret = avformat_open_input(&cat->avf, file->url, NULL, NULL)) < 0 || + // Apply global AVOptions first + if (cat->input_options && + (ret = av_dict_copy(&options, cat->input_options, 0) < 0)) + return ret; + + // then apply file-specific AVOptions + if (file->input_options && + (ret = av_dict_copy(&options, file->input_options, 0) < 0)) + return ret; + + if ((ret = avformat_open_input(&cat->avf, file->url, NULL, &options)) < 0 || (ret = avformat_find_stream_info(cat->avf, NULL)) < 0) { av_log(avf, AV_LOG_ERROR, "Impossible to open '%s'\n", file->url); avformat_close_input(&cat->avf); + av_dict_free(&options); return ret; } + + if (av_dict_count(options)) { + AVDictionaryEntry *en = NULL; + + while ((en = av_dict_get(options, "", en, AV_DICT_IGNORE_SUFFIX))) { + av_log(avf, AV_LOG_WARNING, + "Option '%s' set to '%s' was ignored when opening %s " + "with the %s reader!\n", + en->key, en->value, file->url, cat->avf->iformat->name); + } + } + + av_dict_free(&options); + cat->cur_file = file; file->start_time = !fileno ? 0 : cat->files[fileno - 1].start_time + @@ -386,6 +414,7 @@ static int concat_read_close(AVFormatContext *avf) } av_freep(&cat->files[i].streams); av_dict_free(&cat->files[i].metadata); + av_dict_free(&cat->files[i].input_options); } if (cat->avf) avformat_close_input(&cat->avf); @@ -457,6 +486,41 @@ static int concat_read_header(AVFormatContext *avf) FAIL(AVERROR_INVALIDDATA); } av_freep(&metadata); + } else if (!strncmp(keyword, "input_options", 13)) { + if (!file) { + av_log(avf, AV_LOG_ERROR, "Line %d: %s without file\n", + line, keyword); + FAIL(AVERROR_INVALIDDATA); + } + + if (cat->safe > 0) { + av_log(avf, AV_LOG_ERROR, + "Line %d: Input options cannot be set in file list in " + " safe mode!\n", line); + FAIL(AVERROR(EPERM)); + } + + { + char *input_options = av_get_token((const char **)&cursor, + SPACE_CHARS); + if (!input_options) { + av_log(avf, AV_LOG_ERROR, + "Line %d: key=value pairs required!\n", line); + FAIL(AVERROR_INVALIDDATA); + } + + if ((ret = + av_dict_parse_string(&file->input_options, input_options, + "=", ":", 0)) < 0) { + av_log(avf, AV_LOG_ERROR, + "Line %d: failed to parse input options string\n", + line); + av_freep(&input_options); + FAIL(AVERROR_INVALIDDATA); + } + + av_freep(&input_options); + } } else if (!strcmp(keyword, "stream")) { if (!avformat_new_stream(avf, NULL)) FAIL(AVERROR(ENOMEM)); @@ -764,6 +828,9 @@ static const AVOption options[] = { OFFSET(auto_convert), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, DEC }, { "segment_time_metadata", "output file segment start time and duration as packet metadata", OFFSET(segment_time_metadata), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, DEC }, + { "input_options", + "set options for all opened inputs using a :-separated list of key=value pairs", + OFFSET(input_options), AV_OPT_TYPE_DICT, { .str = NULL }, 0, 0, DEC }, { NULL } };