From 1a0d9b503d2e9c4278d6e93d40873dff9d191a25 Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Mon, 28 Aug 2017 22:45:20 -0400 Subject: [PATCH] avformat/concatdec: add fallback for calculating file duration If a file does not have a known duration, this leads to the timestamps starting over for the next file, causing non-monotonic timestamps. To prevent this, track the duration during demuxing and use it to determine the current file duration before opening the next file. Signed-off-by: Derek Buitenhuis --- libavformat/concatdec.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/libavformat/concatdec.c b/libavformat/concatdec.c index e8b37d6a08..0e189012ad 100644 --- a/libavformat/concatdec.c +++ b/libavformat/concatdec.c @@ -44,6 +44,7 @@ typedef struct { int64_t file_start_time; int64_t file_inpoint; int64_t duration; + int64_t next_dts; ConcatStream *streams; int64_t inpoint; int64_t outpoint; @@ -149,6 +150,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->next_dts = AV_NOPTS_VALUE; file->inpoint = AV_NOPTS_VALUE; file->outpoint = AV_NOPTS_VALUE; @@ -509,8 +511,14 @@ 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) - cat->cur_file->duration = cat->avf->duration - (cat->cur_file->file_inpoint - cat->cur_file->file_start_time); + if (cat->cur_file->duration == AV_NOPTS_VALUE) { + if (cat->avf->duration > 0 || cat->cur_file->next_dts == AV_NOPTS_VALUE) { + cat->cur_file->duration = cat->avf->duration; + } else { + cat->cur_file->duration = cat->cur_file->next_dts; + } + cat->cur_file->duration -= (cat->cur_file->file_inpoint - cat->cur_file->file_start_time); + } if (++fileno >= cat->nb_files) { cat->eof = 1; @@ -627,6 +635,14 @@ static int concat_read_packet(AVFormatContext *avf, AVPacket *pkt) memcpy(metadata, packed_metadata, metadata_len); av_freep(&packed_metadata); } + + if (cat->cur_file->duration == AV_NOPTS_VALUE && st->cur_dts != AV_NOPTS_VALUE) { + int64_t next_dts = av_rescale_q(st->cur_dts, st->time_base, AV_TIME_BASE_Q); + if (cat->cur_file->next_dts == AV_NOPTS_VALUE || next_dts > cat->cur_file->next_dts) { + cat->cur_file->next_dts = next_dts; + } + } + return ret; }