mpegtspacketizer: Detect PCR wraparound in skew code
authorEdward Hervey <edward.hervey@collabora.co.uk>
Sun, 20 May 2012 11:27:29 +0000 (13:27 +0200)
committerEdward Hervey <edward.hervey@collabora.co.uk>
Tue, 22 May 2012 14:51:25 +0000 (16:51 +0200)
If the received PCR is going backwards (by a safe margin), include
that wraparound for further calculation.

https://bugzilla.gnome.org/show_bug.cgi?id=674536

gst/mpegtsdemux/mpegtspacketizer.c
gst/mpegtsdemux/mpegtspacketizer.h

index 84a0b59..d25bc9e 100644 (file)
@@ -33,6 +33,7 @@
 
 /* maximal PCR time */
 #define PCR_MAX_VALUE (((((guint64)1)<<33) * 300) + 298)
+#define PCR_GST_MAX_VALUE (PCR_MAX_VALUE * GST_MSECOND / (27000))
 #define PTS_DTS_MAX_VALUE (((guint64)1) << 33)
 
 #include "mpegtspacketizer.h"
@@ -2956,6 +2957,7 @@ mpegts_packetizer_reset_skew (MpegTSPacketizer2 * packetizer)
   packetizer->skew = 0;
   packetizer->prev_send_diff = GST_CLOCK_TIME_NONE;
   packetizer->prev_out_time = GST_CLOCK_TIME_NONE;
+  packetizer->wrap_count = 0;
   GST_DEBUG ("reset skew correction");
 }
 
@@ -3053,10 +3055,8 @@ calculate_skew (MpegTSPacketizer2 * packetizer, guint64 pcrtime,
   GstClockTime gstpcrtime, out_time;
   guint64 slope;
 
-  gstpcrtime = PCRTIME_TO_GSTTIME (pcrtime);
-
-  /* keep track of the last extended pcrtime */
-  packetizer->last_pcrtime = gstpcrtime;
+  gstpcrtime =
+      PCRTIME_TO_GSTTIME (pcrtime) + packetizer->wrap_count * PCR_GST_MAX_VALUE;
 
   /* first time, lock on to time and gstpcrtime */
   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (packetizer->base_time))) {
@@ -3074,17 +3074,20 @@ calculate_skew (MpegTSPacketizer2 * packetizer, guint64 pcrtime,
 
   if (G_LIKELY (gstpcrtime >= packetizer->base_pcrtime))
     send_diff = gstpcrtime - packetizer->base_pcrtime;
-  else if (GST_CLOCK_TIME_IS_VALID (time)) {
-    /* elapsed time at sender, timestamps can go backwards and thus be smaller
-     * than our base time, take a new base time in that case. */
-    GST_WARNING ("backward timestamps at server, taking new base time");
-    mpegts_packetizer_resync (packetizer, time, gstpcrtime, FALSE);
-    send_diff = 0;
+  else if (GST_CLOCK_TIME_IS_VALID (time)
+      && (packetizer->last_pcrtime - gstpcrtime > PCR_GST_MAX_VALUE / 2)) {
+    /* Detect wraparounds */
+    GST_DEBUG ("PCR wrap");
+    packetizer->wrap_count++;
+    gstpcrtime =
+        PCRTIME_TO_GSTTIME (pcrtime) +
+        packetizer->wrap_count * PCR_GST_MAX_VALUE;
+    send_diff = gstpcrtime - packetizer->base_pcrtime;
   } else {
     GST_WARNING ("backward timestamps at server but no timestamps");
     send_diff = 0;
     /* at least try to get a new timestamp.. */
-    packetizer->base_time = -1;
+    packetizer->base_time = GST_CLOCK_TIME_NONE;
   }
 
   GST_DEBUG ("gstpcr %" GST_TIME_FORMAT ", buftime %" GST_TIME_FORMAT ", base %"
@@ -3092,6 +3095,9 @@ calculate_skew (MpegTSPacketizer2 * packetizer, guint64 pcrtime,
       GST_TIME_ARGS (gstpcrtime), GST_TIME_ARGS (time),
       GST_TIME_ARGS (packetizer->base_pcrtime), GST_TIME_ARGS (send_diff));
 
+  /* keep track of the last extended pcrtime */
+  packetizer->last_pcrtime = gstpcrtime;
+
   /* we don't have an arrival timestamp so we can't do skew detection. we
    * should still apply a timestamp based on RTP timestamp and base_time */
   if (!GST_CLOCK_TIME_IS_VALID (time)
index f588cd3..f4811ca 100644 (file)
@@ -104,6 +104,7 @@ struct _MpegTSPacketizer2 {
   gint64         window_min;
   gint64         skew;
   gint64         prev_send_diff;
+  gint           wrap_count;
 
   /* offset/bitrate calculator */
   gboolean       calculate_offset;