From 55e420615976bf88b1fa882e158e78e1cdeb04b0 Mon Sep 17 00:00:00 2001 From: Youness Alaoui Date: Thu, 8 Sep 2011 23:56:33 +0000 Subject: [PATCH] hlsdemux: Report the correct timestamp for live streams 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 | 15 ++++++++++----- gst/hls/gsthlsdemux.h | 1 + gst/hls/m3u8.c | 24 ++++++++++++++++++++++-- gst/hls/m3u8.h | 2 ++ 4 files changed, 35 insertions(+), 7 deletions(-) diff --git a/gst/hls/gsthlsdemux.c b/gst/hls/gsthlsdemux.c index f87bf3a222..ad29f78370 100644 --- a/gst/hls/gsthlsdemux.c +++ b/gst/hls/gsthlsdemux.c @@ -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); diff --git a/gst/hls/gsthlsdemux.h b/gst/hls/gsthlsdemux.h index bac8ef3174..a09a88b769 100644 --- a/gst/hls/gsthlsdemux.h +++ b/gst/hls/gsthlsdemux.h @@ -89,6 +89,7 @@ struct _GstHLSDemux /* Position in the stream */ GstClockTime position; + GstClockTime position_shift; gboolean need_segment; }; diff --git a/gst/hls/m3u8.c b/gst/hls/m3u8.c index c407d72d83..cffca7d37b 100644 --- a/gst/hls/m3u8.c +++ b/gst/hls/m3u8.c @@ -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; diff --git a/gst/hls/m3u8.h b/gst/hls/m3u8.h index 8c83990f87..a428a67a48 100644 --- a/gst/hls/m3u8.h +++ b/gst/hls/m3u8.h @@ -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);