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_M3U8_CLIENT_LOCK (demux->client);
GST_DEBUG_OBJECT (demux, "seeking to sequence %d", current_sequence); GST_DEBUG_OBJECT (demux, "seeking to sequence %d", current_sequence);
demux->client->sequence = 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; demux->need_segment = TRUE;
GST_M3U8_CLIENT_UNLOCK (demux->client); GST_M3U8_CLIENT_UNLOCK (demux->client);
@ -751,13 +752,15 @@ gst_hls_demux_loop (GstHLSDemux * demux)
demux->need_segment = TRUE; demux->need_segment = TRUE;
} }
if (demux->need_segment) { if (demux->need_segment) {
GstClockTime start = demux->position + demux->position_shift;
/* And send a newsegment */ /* And send a newsegment */
GST_DEBUG_OBJECT (demux, "Sending new-segment. Segment start:%" GST_DEBUG_OBJECT (demux, "Sending new-segment. segment start:%"
GST_TIME_FORMAT, GST_TIME_ARGS (demux->position)); GST_TIME_FORMAT, GST_TIME_ARGS (start));
gst_pad_push_event (demux->srcpad, gst_pad_push_event (demux->srcpad,
gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME, demux->position, gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME,
GST_CLOCK_TIME_NONE, demux->position)); start, GST_CLOCK_TIME_NONE, start));
demux->need_segment = FALSE; demux->need_segment = FALSE;
demux->position_shift = 0;
} }
if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_DURATION (buf))) 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); g_queue_clear (demux->queue);
demux->position = 0; demux->position = 0;
demux->position_shift = 0;
demux->need_segment = TRUE; demux->need_segment = TRUE;
} }
@ -1037,6 +1041,7 @@ gst_hls_demux_cache_fragments (GstHLSDemux * demux)
demux->client->sequence -= demux->fragments_cache; demux->client->sequence -= demux->fragments_cache;
else else
demux->client->sequence = 0; demux->client->sequence = 0;
gst_m3u8_client_get_current_position (demux->client, &demux->position);
GST_M3U8_CLIENT_UNLOCK (demux->client); GST_M3U8_CLIENT_UNLOCK (demux->client);
} else { } else {
GstClockTime duration = gst_m3u8_client_get_duration (demux->client); GstClockTime duration = gst_m3u8_client_get_duration (demux->client);

View File

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

View File

@ -468,13 +468,31 @@ _find_next (GstM3U8MediaFile * file, GstM3U8Client * client)
return TRUE; 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 gboolean
gst_m3u8_client_get_next_fragment (GstM3U8Client * client, gst_m3u8_client_get_next_fragment (GstM3U8Client * client,
gboolean * discontinuity, const gchar ** uri, GstClockTime * duration, gboolean * discontinuity, const gchar ** uri, GstClockTime * duration,
GstClockTime * timestamp) GstClockTime * timestamp)
{ {
GList *l; GList *l, *walk;
GList *walk;
GstM3U8MediaFile *file; GstM3U8MediaFile *file;
g_return_val_if_fail (client != NULL, FALSE); g_return_val_if_fail (client != NULL, FALSE);
@ -490,6 +508,8 @@ gst_m3u8_client_get_next_fragment (GstM3U8Client * client,
return FALSE; return FALSE;
} }
gst_m3u8_client_get_current_position (client, timestamp);
file = GST_M3U8_MEDIA_FILE (l->data); file = GST_M3U8_MEDIA_FILE (l->data);
*discontinuity = client->sequence != file->sequence; *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 gst_m3u8_client_get_next_fragment (GstM3U8Client * client,
gboolean * discontinuity, const gchar ** uri, GstClockTime * duration, gboolean * discontinuity, const gchar ** uri, GstClockTime * duration,
GstClockTime * timestamp); 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_duration (GstM3U8Client * client);
GstClockTime gst_m3u8_client_get_target_duration (GstM3U8Client * client); GstClockTime gst_m3u8_client_get_target_duration (GstM3U8Client * client);
const gchar *gst_m3u8_client_get_uri(GstM3U8Client * client); const gchar *gst_m3u8_client_get_uri(GstM3U8Client * client);