1
0
mirror of https://github.com/FFmpeg/FFmpeg.git synced 2025-11-23 21:54:53 +02:00

lavf/concatdec: support per-file options

This commit is contained in:
Nicolas George
2021-07-28 12:34:19 +02:00
parent 46fb395952
commit 0210c8fee2
2 changed files with 38 additions and 1 deletions

View File

@@ -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 each file packet. You can specify this directive multiple times to add multiple
metadata entries. 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} @item @code{stream}
Introduce a stream in the virtual file. Introduce a stream in the virtual file.
All subsequent stream-related directives apply to the last introduced All subsequent stream-related directives apply to the last introduced

View File

@@ -52,6 +52,7 @@ typedef struct {
int64_t inpoint; int64_t inpoint;
int64_t outpoint; int64_t outpoint;
AVDictionary *metadata; AVDictionary *metadata;
AVDictionary *options;
int nb_streams; int nb_streams;
} ConcatFile; } ConcatFile;
@@ -330,6 +331,7 @@ static int open_file(AVFormatContext *avf, unsigned fileno)
{ {
ConcatContext *cat = avf->priv_data; ConcatContext *cat = avf->priv_data;
ConcatFile *file = &cat->files[fileno]; ConcatFile *file = &cat->files[fileno];
AVDictionary *options = NULL;
int ret; int ret;
if (cat->avf) if (cat->avf)
@@ -345,12 +347,22 @@ static int open_file(AVFormatContext *avf, unsigned fileno)
if ((ret = ff_copy_whiteblacklists(cat->avf, avf)) < 0) if ((ret = ff_copy_whiteblacklists(cat->avf, avf)) < 0)
return ret; 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) { (ret = avformat_find_stream_info(cat->avf, NULL)) < 0) {
av_log(avf, AV_LOG_ERROR, "Impossible to open '%s'\n", file->url); av_log(avf, AV_LOG_ERROR, "Impossible to open '%s'\n", file->url);
av_dict_free(&options);
avformat_close_input(&cat->avf); avformat_close_input(&cat->avf);
return ret; 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; cat->cur_file = file;
file->start_time = !fileno ? 0 : file->start_time = !fileno ? 0 :
cat->files[fileno - 1].start_time + cat->files[fileno - 1].start_time +
@@ -387,6 +399,7 @@ static int concat_read_close(AVFormatContext *avf)
} }
av_freep(&cat->files[i].streams); av_freep(&cat->files[i].streams);
av_dict_free(&cat->files[i].metadata); av_dict_free(&cat->files[i].metadata);
av_dict_free(&cat->files[i].options);
} }
if (cat->avf) if (cat->avf)
avformat_close_input(&cat->avf); avformat_close_input(&cat->avf);
@@ -458,6 +471,26 @@ static int concat_read_header(AVFormatContext *avf)
FAIL(AVERROR_INVALIDDATA); FAIL(AVERROR_INVALIDDATA);
} }
av_freep(&metadata); 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")) { } else if (!strcmp(keyword, "stream")) {
if (!avformat_new_stream(avf, NULL)) if (!avformat_new_stream(avf, NULL))
FAIL(AVERROR(ENOMEM)); FAIL(AVERROR(ENOMEM));