aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicolas George <george@nsup.org>2021-07-28 12:34:19 +0200
committerNicolas George <george@nsup.org>2021-08-22 11:44:16 +0200
commit0210c8fee2c340ae799dcf6076bd9bf2ea8f7431 (patch)
tree58b60848715b9c77457ab1d39ac8078be27ba5c6
parent46fb395952be32692385449ee214461603480b4b (diff)
downloadffmpeg-0210c8fee2c340ae799dcf6076bd9bf2ea8f7431.tar.gz
lavf/concatdec: support per-file options
-rw-r--r--doc/demuxers.texi4
-rw-r--r--libavformat/concatdec.c35
2 files changed, 38 insertions, 1 deletions
diff --git a/doc/demuxers.texi b/doc/demuxers.texi
index 5f18e4551b..eb3351833a 100644
--- a/doc/demuxers.texi
+++ b/doc/demuxers.texi
@@ -151,6 +151,10 @@ 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{option @var{key} @var{value}}
+Option to access, open and probe the file.
+Can be present multiple times.
+
@item @code{stream}
Introduce a stream in the virtual file.
All subsequent stream-related directives apply to the last introduced
diff --git a/libavformat/concatdec.c b/libavformat/concatdec.c
index ed6b9d8044..30db456b0e 100644
--- a/libavformat/concatdec.c
+++ b/libavformat/concatdec.c
@@ -52,6 +52,7 @@ typedef struct {
int64_t inpoint;
int64_t outpoint;
AVDictionary *metadata;
+ AVDictionary *options;
int nb_streams;
} ConcatFile;
@@ -330,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)
@@ -345,12 +347,22 @@ 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 ||
+ ret = av_dict_copy(&options, file->options, 0);
+ if (ret < 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);
+ av_dict_free(&options);
avformat_close_input(&cat->avf);
return ret;
}
+ if (options) {
+ av_log(avf, AV_LOG_WARNING, "Unused options for '%s'.\n", file->url);
+ /* TODO log unused options once we have a proper string API */
+ av_dict_free(&options);
+ }
cat->cur_file = file;
file->start_time = !fileno ? 0 :
cat->files[fileno - 1].start_time +
@@ -387,6 +399,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].options);
}
if (cat->avf)
avformat_close_input(&cat->avf);
@@ -458,6 +471,26 @@ static int concat_read_header(AVFormatContext *avf)
FAIL(AVERROR_INVALIDDATA);
}
av_freep(&metadata);
+ } else if (!strcmp(keyword, "option")) {
+ char *key, *val;
+ if (cat->safe) {
+ av_log(avf, AV_LOG_ERROR, "Options not permitted in safe mode.\n");
+ FAIL(AVERROR(EPERM));
+ }
+ if (!file) {
+ av_log(avf, AV_LOG_ERROR, "Line %d: %s without file\n",
+ line, keyword);
+ FAIL(AVERROR_INVALIDDATA);
+ }
+ if (!(key = av_get_token((const char **)&cursor, SPACE_CHARS)) ||
+ !(val = av_get_token((const char **)&cursor, SPACE_CHARS))) {
+ av_freep(&key);
+ FAIL(AVERROR(ENOMEM));
+ }
+ ret = av_dict_set(&file->options, key, val,
+ AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL);
+ if (ret < 0)
+ FAIL(ret);
} else if (!strcmp(keyword, "stream")) {
if (!avformat_new_stream(avf, NULL))
FAIL(AVERROR(ENOMEM));