Opened 3 years ago

Closed 3 years ago

#4924 closed defect (fixed)

PTS/DTS timestamps get broken when concatenating MPEG-TS files using -f concat

Reported by: jsnajdr Owned by: cus
Priority: important Component: avfilter
Version: git-master Keywords: concat regression
Cc: cus@passwd.hu Blocked By:
Blocking: Reproduced by developer: no
Analyzed by developer: no

Description (last modified by cehoyos)

Steps to reproduce:

  1. Download two *.ts files and a list.txt from this Dropbox URL:

https://www.dropbox.com/sh/j4rm230kj7qwlr1/AACkhVF8Eb7nQF77qORG85JAa?dl=0

  1. Concat them with this command:

ffmpeg -f concat -i list.txt -c copy output.ts

  1. Look at the PTS/DTS timestamps of the output.ts file:

ffprobe -show_entries packet=codec_type,stream_index,pts,dts output.ts

Expected result:

The timestamps are in a continuous range and the transitions from one chunk to the next are seamless.

Actual result:

The timestamps from the first chunk are OK, but at the start of the second, they start to be shifted by a big time interval backwards, which causes a timestamp wrap by 233. This causes a huge discontinuity and a resulting file duration of 26 hours instead of 6 seconds.

Fixing the delta-computing algorithm in libavformat/concatdec.c:concat_read_packet fixed the issue for me (see the patch below). But I suspect it doesn't work in the general case. My case is special in that the timestamps are not-overlapping, following one sequence across files. Concatenating files where timestamps always start from zero probably won't work. I don't know how to fix it, the timestamp shifting/scaling logic is very complex and confusing.

Used software:

ffmpeg bleeding-edge from Github master. The issue is new in 2.8 - it didn't happen in 2.7.

Proposed patch:

diff --git a/libavformat/concatdec.c b/libavformat/concatdec.c
index 832b7f4..1151b10 100644
--- a/libavformat/concatdec.c
+++ b/libavformat/concatdec.c
@@ -580,7 +580,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));
 
-    delta = av_rescale_q(cat->cur_file->start_time - cat->cur_file->file_inpoint,
+    delta = av_rescale_q(cat->cur_file->file_start_time - cat->cur_file->file_inpoint,
                          AV_TIME_BASE_Q,
                          cat->avf->streams[pkt->stream_index]->time_base);

Attachments (3)

chunk-106.ts (161.6 KB) - added by cehoyos 3 years ago.
chunk-107.ts (130.5 KB) - added by cehoyos 3 years ago.
list.txt (36 bytes) - added by cehoyos 3 years ago.

Download all attachments as: .zip

Change History (8)

comment:1 Changed 3 years ago by cehoyos

  • Component changed from ffmpeg to avfilter
  • Description modified (diff)
  • Keywords concat regression added
  • Priority changed from normal to important
  • Version changed from unspecified to git-master

Please send your patch to the FFmpeg development mailing list, patches are ignored on this bug tracker.

Changed 3 years ago by cehoyos

Changed 3 years ago by cehoyos

Changed 3 years ago by cehoyos

comment:2 Changed 3 years ago by cus

  • Cc cus@passwd.hu added

The main cause of the regression is that avformatcontext->start_time is unset after opening the stream, but set after reading the first packet.

With my inpoint patch concat demuxer was changed to use the start_time before reading the first packet.

comment:3 Changed 3 years ago by jsnajdr

Marton, in concatdec.c:open_file, shouldn't you get the file_start_time from cat->avf->start_time instead of from avf->start_time? The cat->avf struct contains the correct info, my debugging shows, as it's been read by avformat_find_stream_info a few lines earlier. I can't find where avf->start_time is set, but it contains garbage - when processing the first file, it's 0, when processing the second, it's the start_time of the first, and when processing third and next ones it stays at the same value (the first file's start_time).

comment:4 Changed 3 years ago by cus

  • Owner set to cus
  • Status changed from new to open

You're right. avf->start_time is the start time of the output format context, that's why it is unset, the code should use the input format context, which is cat->avf->start_time like you said.

I'll make a patch and submit it to ffmpeg-devel.

Thanks for figuring this out, and sorry for the regression.

comment:5 Changed 3 years ago by cus

  • Resolution set to fixed
  • Status changed from open to closed
Note: See TracTickets for help on using tickets.