[FFmpeg-devel] [PATCH 1/4] concatdec: add support for specifying inpoint of files
Marton Balint
cus at passwd.hu
Mon Jul 6 02:28:48 CEST 2015
Signed-off-by: Marton Balint <cus at passwd.hu>
---
doc/demuxers.texi | 17 +++++++++++++++++
libavformat/concatdec.c | 48 +++++++++++++++++++++++++++++++++++-------------
2 files changed, 52 insertions(+), 13 deletions(-)
diff --git a/doc/demuxers.texi b/doc/demuxers.texi
index 35a1561..4bad1c8 100644
--- a/doc/demuxers.texi
+++ b/doc/demuxers.texi
@@ -112,6 +112,23 @@ file is not available or accurate.
If the duration is set for all files, then it is possible to seek in the
whole concatenated video.
+ at item @code{in @var{timestamp}}
+In point of the file. When the demuxer opens the file it instantly seeks to the
+specified timestamp. Seeking is done so that all streams can be presented
+successfully at In point.
+
+This directive works best with intra frame codecs, because for non-intra frame
+ones you will usually get extra packets before the actual In point and the
+decoded content will most likely contain frames before In point too.
+
+For each file, packets before the file In point will have timestamps less than
+the calculated start timestamp of the file (negative in case of the first
+file), and the duration of the files (if not specified by the @code{duration}
+directive) will be reduced based on their specified In point.
+
+Because of potential packets before the specified In point, packet timestamps
+may overlap between two concatenated files.
+
@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 e95ff34..c61a1a3 100644
--- a/libavformat/concatdec.c
+++ b/libavformat/concatdec.c
@@ -43,6 +43,7 @@ typedef struct {
int64_t start_time;
int64_t duration;
ConcatStream *streams;
+ int64_t inpoint;
int nb_streams;
} ConcatFile;
@@ -142,6 +143,7 @@ static int add_file(AVFormatContext *avf, char *filename, ConcatFile **rfile,
file->url = url;
file->start_time = AV_NOPTS_VALUE;
file->duration = AV_NOPTS_VALUE;
+ file->inpoint = AV_NOPTS_VALUE;
return 0;
@@ -308,6 +310,10 @@ static int open_file(AVFormatContext *avf, unsigned fileno)
cat->files[fileno - 1].duration;
if ((ret = match_streams(avf)) < 0)
return ret;
+ if (file->inpoint != AV_NOPTS_VALUE) {
+ if ((ret = avformat_seek_file(cat->avf, -1, INT64_MIN, file->inpoint, file->inpoint, 0) < 0))
+ return ret;
+ }
return 0;
}
@@ -353,20 +359,23 @@ static int concat_read_header(AVFormatContext *avf)
}
if ((ret = add_file(avf, filename, &file, &nb_files_alloc)) < 0)
goto fail;
- } else if (!strcmp(keyword, "duration")) {
+ } else if (!strcmp(keyword, "duration") || !strcmp(keyword, "in")) {
char *dur_str = get_keyword(&cursor);
int64_t dur;
if (!file) {
- av_log(avf, AV_LOG_ERROR, "Line %d: duration without file\n",
- line);
+ av_log(avf, AV_LOG_ERROR, "Line %d: %s without file\n",
+ line, keyword);
FAIL(AVERROR_INVALIDDATA);
}
if ((ret = av_parse_time(&dur, dur_str, 1)) < 0) {
- av_log(avf, AV_LOG_ERROR, "Line %d: invalid duration '%s'\n",
- line, dur_str);
+ av_log(avf, AV_LOG_ERROR, "Line %d: invalid %s '%s'\n",
+ line, keyword, dur_str);
goto fail;
}
- file->duration = dur;
+ if (!strcmp(keyword, "duration"))
+ file->duration = dur;
+ else if (!strcmp(keyword, "in"))
+ file->inpoint = dur;
} else if (!strcmp(keyword, "stream")) {
if (!avformat_new_stream(avf, NULL))
FAIL(AVERROR(ENOMEM));
@@ -428,8 +437,12 @@ static int open_next_file(AVFormatContext *avf)
ConcatContext *cat = avf->priv_data;
unsigned fileno = cat->cur_file - cat->files;
- if (cat->cur_file->duration == AV_NOPTS_VALUE)
+ if (cat->cur_file->duration == AV_NOPTS_VALUE) {
+ int64_t file_start_time = (cat->avf->start_time == AV_NOPTS_VALUE) ? 0 : cat->avf->start_time;
cat->cur_file->duration = cat->avf->duration;
+ if (cat->cur_file->inpoint != AV_NOPTS_VALUE)
+ cat->cur_file->duration -= (cat->cur_file->inpoint - file_start_time);
+ }
if (++fileno >= cat->nb_files)
return AVERROR_EOF;
@@ -476,11 +489,23 @@ static int filter_packet(AVFormatContext *avf, ConcatStream *cs, AVPacket *pkt)
return 0;
}
+static int64_t get_cur_file_inpoint(ConcatContext *cat)
+{
+ int64_t file_inpoint = cat->cur_file->inpoint;
+ if (file_inpoint == AV_NOPTS_VALUE) {
+ int64_t file_start_time = cat->avf->start_time;
+ if (file_start_time == AV_NOPTS_VALUE)
+ file_start_time = 0;
+ return file_start_time;
+ }
+ return file_inpoint;
+}
+
static int concat_read_packet(AVFormatContext *avf, AVPacket *pkt)
{
ConcatContext *cat = avf->priv_data;
int ret;
- int64_t file_start_time, delta;
+ int64_t delta;
ConcatStream *cs;
AVStream *st;
@@ -517,10 +542,7 @@ static int concat_read_packet(AVFormatContext *avf, AVPacket *pkt)
av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &st->time_base),
av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &st->time_base));
- file_start_time = cat->avf->start_time;
- if (file_start_time == AV_NOPTS_VALUE)
- file_start_time = 0;
- delta = av_rescale_q(cat->cur_file->start_time - file_start_time,
+ delta = av_rescale_q(cat->cur_file->start_time - get_cur_file_inpoint(cat),
AV_TIME_BASE_Q,
cat->avf->streams[pkt->stream_index]->time_base);
if (pkt->pts != AV_NOPTS_VALUE)
@@ -547,7 +569,7 @@ static int try_seek(AVFormatContext *avf, int stream,
int64_t min_ts, int64_t ts, int64_t max_ts, int flags)
{
ConcatContext *cat = avf->priv_data;
- int64_t t0 = cat->cur_file->start_time - cat->avf->start_time;
+ int64_t t0 = cat->cur_file->start_time - get_cur_file_inpoint(cat);
ts -= t0;
min_ts = min_ts == INT64_MIN ? INT64_MIN : min_ts - t0;
--
2.1.4
More information about the ffmpeg-devel
mailing list