From patchwork Mon Feb 8 11:32:37 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: 25502 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 26CFD44AA4A for ; Mon, 8 Feb 2021 13:32:47 +0200 (EET) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id EFA3568818C; Mon, 8 Feb 2021 13:32:46 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-lf1-f48.google.com (mail-lf1-f48.google.com [209.85.167.48]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 721FC680728 for ; Mon, 8 Feb 2021 13:32:41 +0200 (EET) Received: by mail-lf1-f48.google.com with SMTP id v5so19487632lft.13 for ; Mon, 08 Feb 2021 03:32:41 -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=NzncPqjaIEV1bqmyK+0S/lOnJNBlToY5I0uhTlG0dnA=; b=Qa8tbhkhClyBMUhTzRi7yvsmbr6wVP04RqqRzaj5tye1I87u6aqRRvSxDkB72+297n wyn3sQvcgomSf/WjAm2lHXbxmYCqLNSglvST0CBpu+MGPA0qsvSP7R71BkTdg9kNhlSj x/qdGt2NSKU6mGoI3rm0JjrHEqw8/MO+Od2LhamfotRCFpWTmKLbVtGajUJ167VIpFAX Mhj4jQ3mEndgBkxp8VKghM311CBaRm2bFc9N4vfkcnUNazVbUDSiBhiWQ3+blQWtKVbX OCnUpsbXPASDUUNeJCnZ7loBppUhPOUtfbDqTPYF1kkXOStr0pYz0tYuD3uKbXGpH5uR JSDw== 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=NzncPqjaIEV1bqmyK+0S/lOnJNBlToY5I0uhTlG0dnA=; b=o1P3+rEdmWnY45AP+OUBpgj6X3HB0LGNWSaIsmWmxGLf/Sv7WSNeWuvdNVObU6n2DY 3yOYAUdS0zmxpGSP2kZtE3/1h8NBoF8P6ICFRj3cBHWwnl3Wbrkbdo6QJ0omIwNWHnUP cbLqrd2WMptBDbNhE6yiGmU+a2WcBxKE8kbZZJzzji4q+FfPco4GXlTdFHMA792tMn5r C6RbHCk1t1YNkemojMof2ZJYx1fFQaN+9KAuj49f8bRV867elFbk/09MU7Xgj293xA4J JYz3gRfTfd4nbstJjmJrRZTmtKAfbKeMWvCRA3RhTOB4G0rpADc5boIep0mcFdwcadXU Nldw== X-Gm-Message-State: AOAM530LO3rz4GjetqtQ4a1/JBeK6zA2MYXS10Y9c1VIlOSDw3qfHEY+ fFkqJCNkdr0eH4oLIKm5z3yKa1FHULM= X-Google-Smtp-Source: ABdhPJxgOCaXYKf1Xm32nzbxILo9zpYdpYRNRc8PauMHJ52ssaU1FpHFb00v0JH/E6VXm1SXh5Uhiw== X-Received: by 2002:a05:6512:3185:: with SMTP id i5mr9796273lfe.653.1612783960653; Mon, 08 Feb 2021 03:32:40 -0800 (PST) Received: from localhost.localdomain (91-159-194-103.elisa-laajakaista.fi. [91.159.194.103]) by smtp.gmail.com with ESMTPSA id u20sm454002ljo.6.2021.02.08.03.32.39 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 08 Feb 2021 03:32:39 -0800 (PST) From: =?utf-8?q?Jan_Ekstr=C3=B6m?= To: ffmpeg-devel@ffmpeg.org Date: Mon, 8 Feb 2021 13:32:37 +0200 Message-Id: <20210208113237.32705-1-jeebjp@gmail.com> X-Mailer: git-send-email 2.29.2 MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH v3] 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. --- Changes from v2: 1. Added an example, although I had issues figuring out something useful that is not a hack for something. Ended up doing a disablement of advanced edit list functionality, since that can sometimes lead to unwanted behavior. * First idea was to override the input format for a file without an extension. For that, we have no AVOption it seems. * Then came the idea of utilizing the framerate option in the raw h264 demuxer. That didn't work because apparently if there is a header in there that probed/parsed frame rate field gets utilized. * Third idea was either the one I picked, or analyzeduration/probesize for MPEG-TS. I opted for the mp4 case. 2. Quoted the : in documentation with @code{:}. 3. Fixed a duplicate space in a log message. --- doc/demuxers.texi | 24 ++++++++++++++ libavformat/concatdec.c | 69 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 92 insertions(+), 1 deletion(-) diff --git a/doc/demuxers.texi b/doc/demuxers.texi index 3c15ab9eee..20601f9575 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 @code{:}-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 @@ -231,6 +243,18 @@ duration 20.0 file subdir/file-2.wav @end example + +@item +Disabling advanced edit list capability for the first input file via +input_options: +@example +ffconcat version 1.0 + +file file-1.mp4 +input_options advanced_editlist=false + +file file-2.mp4 +@end example @end itemize @section dash diff --git a/libavformat/concatdec.c b/libavformat/concatdec.c index 6d5b9914f9..89d75cedc6 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 } };