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.
This commit is contained in:
Youness Alaoui 2011-09-08 23:56:33 +00:00 committed by Sebastian Dröge
parent 894ac8f493
commit 55e4206159
4 changed files with 35 additions and 7 deletions

View 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);

View file

@ -89,6 +89,7 @@ struct _GstHLSDemux
/* Position in the stream */
GstClockTime position;
GstClockTime position_shift;
gboolean need_segment;
};

View 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;

View 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);