hlsdemux: Report the correct timestamp for live streams
authorYouness Alaoui <youness.alaoui@collabora.co.uk>
Thu, 8 Sep 2011 23:56:33 +0000 (23:56 +0000)
committerSebastian Dröge <sebastian.droege@collabora.co.uk>
Fri, 9 Sep 2011 10:21:36 +0000 (12:21 +0200)
Buffers would always start with timestamp 0 and we'd start streaming
from the first buffer, but live streams always start streaming from
the last fragment - 3 fragments in the playlist, which makes its
timestamp, as returned by get_next_fragment, be whatever position
they had in the playlist. This makes sure the position correctly
reports the position of the buffer in the playlist, and added a shifting
variable to allow seeking in the middle of fragments.

gst/hls/gsthlsdemux.c
gst/hls/gsthlsdemux.h
gst/hls/m3u8.c
gst/hls/m3u8.h

index f87bf3a..ad29f78 100644 (file)
@@ -410,7 +410,8 @@ gst_hls_demux_src_event (GstPad * pad, GstEvent * event)
       GST_M3U8_CLIENT_LOCK (demux->client);
       GST_DEBUG_OBJECT (demux, "seeking to sequence %d", current_sequence);
       demux->client->sequence = current_sequence;
-      demux->position = start;
+      gst_m3u8_client_get_current_position (demux->client, &demux->position);
+      demux->position_shift = start - demux->position;
       demux->need_segment = TRUE;
       GST_M3U8_CLIENT_UNLOCK (demux->client);
 
@@ -751,13 +752,15 @@ gst_hls_demux_loop (GstHLSDemux * demux)
     demux->need_segment = TRUE;
   }
   if (demux->need_segment) {
+    GstClockTime start = demux->position + demux->position_shift;
     /* And send a newsegment */
-    GST_DEBUG_OBJECT (demux, "Sending new-segment. Segment start:%"
-        GST_TIME_FORMAT, GST_TIME_ARGS (demux->position));
+    GST_DEBUG_OBJECT (demux, "Sending new-segment. segment start:%"
+        GST_TIME_FORMAT, GST_TIME_ARGS (start));
     gst_pad_push_event (demux->srcpad,
-        gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME, demux->position,
-            GST_CLOCK_TIME_NONE, demux->position));
+        gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME,
+            start, GST_CLOCK_TIME_NONE, start));
     demux->need_segment = FALSE;
+    demux->position_shift = 0;
   }
 
   if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_DURATION (buf)))
@@ -886,6 +889,7 @@ gst_hls_demux_reset (GstHLSDemux * demux, gboolean dispose)
   g_queue_clear (demux->queue);
 
   demux->position = 0;
+  demux->position_shift = 0;
   demux->need_segment = TRUE;
 }
 
@@ -1037,6 +1041,7 @@ gst_hls_demux_cache_fragments (GstHLSDemux * demux)
       demux->client->sequence -= demux->fragments_cache;
     else
       demux->client->sequence = 0;
+    gst_m3u8_client_get_current_position (demux->client, &demux->position);
     GST_M3U8_CLIENT_UNLOCK (demux->client);
   } else {
     GstClockTime duration = gst_m3u8_client_get_duration (demux->client);
index bac8ef3..a09a88b 100644 (file)
@@ -89,6 +89,7 @@ struct _GstHLSDemux
 
   /* Position in the stream */
   GstClockTime position;
+  GstClockTime position_shift;
   gboolean need_segment;
 };
 
index c407d72..cffca7d 100644 (file)
@@ -468,13 +468,31 @@ _find_next (GstM3U8MediaFile * file, GstM3U8Client * client)
   return TRUE;
 }
 
+void
+gst_m3u8_client_get_current_position (GstM3U8Client * client,
+    GstClockTime * timestamp)
+{
+  GList *l;
+  GList *walk;
+
+  l = g_list_find_custom (client->current->files, client,
+      (GCompareFunc) _find_next);
+
+  *timestamp = 0;
+  for (walk = client->current->files; walk; walk = walk->next) {
+    if (walk == l)
+      break;
+    *timestamp += GST_M3U8_MEDIA_FILE (walk->data)->duration;
+  }
+  *timestamp *= GST_SECOND;
+}
+
 gboolean
 gst_m3u8_client_get_next_fragment (GstM3U8Client * client,
     gboolean * discontinuity, const gchar ** uri, GstClockTime * duration,
     GstClockTime * timestamp)
 {
-  GList *l;
-  GList *walk;
+  GList *l, *walk;
   GstM3U8MediaFile *file;
 
   g_return_val_if_fail (client != NULL, FALSE);
@@ -490,6 +508,8 @@ gst_m3u8_client_get_next_fragment (GstM3U8Client * client,
     return FALSE;
   }
 
+  gst_m3u8_client_get_current_position (client, timestamp);
+
   file = GST_M3U8_MEDIA_FILE (l->data);
 
   *discontinuity = client->sequence != file->sequence;
index 8c83990..a428a67 100644 (file)
@@ -84,6 +84,8 @@ void gst_m3u8_client_set_current (GstM3U8Client * client, GstM3U8 * m3u8);
 gboolean gst_m3u8_client_get_next_fragment (GstM3U8Client * client,
     gboolean * discontinuity, const gchar ** uri, GstClockTime * duration,
     GstClockTime * timestamp);
+void gst_m3u8_client_get_current_position (GstM3U8Client * client,
+    GstClockTime * timestamp);
 GstClockTime gst_m3u8_client_get_duration (GstM3U8Client * client);
 GstClockTime gst_m3u8_client_get_target_duration (GstM3U8Client * client);
 const gchar *gst_m3u8_client_get_uri(GstM3U8Client * client);