[FFmpeg-devel] Using copyts with mpegts output fails after 26, 5 hours

Panagiotis Malakoudis malakudi at gmail.com
Thu May 2 20:13:10 EEST 2019


When outputing to mpegts format, using -copyts option makes program
fail after the oveflow of mpegts PCR happens at around 26 hours and 30
minutes. When not using -copyts, only a warning is reported.
In order to reproduce the issue, you first have to create a 27 hour
mpegts video.
I have described the problem in thorough at ticket
https://trac.ffmpeg.org/ticket/7876

The issue is resolved if you use a patch created originally by Arut
(Roman Arutyunyan) at
https://github.com/arut/ffmpeg-patches/blob/master/mpegts-33bit

I have converted the patch in order to apply with current git and
confirmed working fine, fixing the above mentioned issue. Original
author describes the patch as: "Implements smooth 33-bit mpeg-ts
timestamp overflow in mpegts muxer."

Here it is:
--- libavformat/mpegts.c 2019-04-30 16:11:49.000000000 +0300
+++ libavformat/mpegts.c 2019-04-30 18:55:12.736428766 +0300
@@ -163,6 +163,9 @@
     /** structure to keep track of Program->pids mapping */
     unsigned int nb_prg;
     struct Program *prg;
+
+    /** base timestamp for smooth rolling over 33bits */
+    int64_t base_ts;

     int8_t crc_validity[NB_PID_MAX];
     /** filters for various streams specified by PMT + for the PAT and PMT */
@@ -982,6 +985,26 @@
     pkt->size = len;
 }

+static int64_t unroll_timestamp(MpegTSContext *ts, int64_t t)
+{
+    int64_t dt;
+
+    if (t == AV_NOPTS_VALUE)
+        return t;
+
+    if (!ts->base_ts)
+        ts->base_ts = t;
+
+    dt = (t - ts->base_ts) & 0x01ffffffffll;
+    if (dt & 0x0100000000ll) {
+        dt |= 0xffffffff00000000ll;
+    }
+
+    ts->base_ts += dt;
+
+    return ts->base_ts;
+}
+
 static int new_pes_packet(PESContext *pes, AVPacket *pkt)
 {
     uint8_t *sd;
@@ -1005,8 +1028,8 @@
         pkt->stream_index = pes->sub_st->index;
     else
         pkt->stream_index = pes->st->index;
-    pkt->pts = pes->pts;
-    pkt->dts = pes->dts;
+    pkt->pts = unroll_timestamp(pes->ts, pes->pts);
+    pkt->dts = unroll_timestamp(pes->ts, pes->dts);
     /* store position of first TS packet of this PES packet */
     pkt->pos   = pes->ts_packet_pos;
     pkt->flags = pes->flags;


More information about the ffmpeg-devel mailing list