hlsdemux: Keep track of timestamps by adding them up during playback

...instead of adding them from the start of playlist every time. This
among other things fixes timestamps for live streams, where the playlist
is some kind of ringbuffer of fragments and thus adding from the beginning
of the playlist will miss the past fragments.

https://bugzilla.gnome.org/show_bug.cgi?id=724983
This commit is contained in:
Sebastian Dröge 2014-02-23 15:18:22 +01:00
parent 090bf91974
commit b3a7242910
3 changed files with 8 additions and 24 deletions

View file

@ -329,7 +329,7 @@ gst_hls_demux_src_event (GstPad * pad, GstObject * parent, GstEvent * event)
GstSeekType start_type, stop_type; GstSeekType start_type, stop_type;
gint64 start, stop; gint64 start, stop;
GList *walk; GList *walk;
GstClockTime position, current_pos, target_pos; GstClockTime current_pos, target_pos;
gint current_sequence; gint current_sequence;
GstM3U8MediaFile *file; GstM3U8MediaFile *file;
@ -388,8 +388,8 @@ gst_hls_demux_src_event (GstPad * pad, GstObject * parent, 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;
gst_m3u8_client_get_current_position (demux->client, &position); demux->client->sequence_position = current_pos;
demux->position_shift = start - position; demux->position_shift = start - current_pos;
demux->need_segment = TRUE; demux->need_segment = TRUE;
GST_M3U8_CLIENT_UNLOCK (demux->client); GST_M3U8_CLIENT_UNLOCK (demux->client);

View file

@ -484,6 +484,7 @@ gst_m3u8_client_new (const gchar * uri)
client->main = gst_m3u8_new (); client->main = gst_m3u8_new ();
client->current = NULL; client->current = NULL;
client->sequence = -1; client->sequence = -1;
client->sequence_position = 0;
client->update_failed_count = 0; client->update_failed_count = 0;
g_mutex_init (&client->lock); g_mutex_init (&client->lock);
gst_m3u8_set_uri (client->main, g_strdup (uri)); gst_m3u8_set_uri (client->main, g_strdup (uri));
@ -546,6 +547,7 @@ gst_m3u8_client_update (GstM3U8Client * self, gchar * data)
if (m3u8->files && self->sequence == -1) { if (m3u8->files && self->sequence == -1) {
self->sequence = self->sequence =
GST_M3U8_MEDIA_FILE (g_list_first (m3u8->files)->data)->sequence; GST_M3U8_MEDIA_FILE (g_list_first (m3u8->files)->data)->sequence;
self->sequence_position = 0;
GST_DEBUG ("Setting first sequence at %d", self->sequence); GST_DEBUG ("Setting first sequence at %d", self->sequence);
} }
@ -570,24 +572,6 @@ _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;
}
}
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,
@ -613,7 +597,7 @@ gst_m3u8_client_get_next_fragment (GstM3U8Client * client,
file->sequence, client->sequence); file->sequence, client->sequence);
if (timestamp) if (timestamp)
gst_m3u8_client_get_current_position (client, timestamp); *timestamp = client->sequence_position;
if (discontinuity) if (discontinuity)
*discontinuity = client->sequence != file->sequence; *discontinuity = client->sequence != file->sequence;
@ -652,6 +636,7 @@ gst_m3u8_client_advance_fragment (GstM3U8Client * client)
file = GST_M3U8_MEDIA_FILE (l->data); file = GST_M3U8_MEDIA_FILE (l->data);
GST_DEBUG ("Advancing from sequence %u", file->sequence); GST_DEBUG ("Advancing from sequence %u", file->sequence);
client->sequence = file->sequence + 1; client->sequence = file->sequence + 1;
client->sequence_position += file->duration;
GST_M3U8_CLIENT_UNLOCK (client); GST_M3U8_CLIENT_UNLOCK (client);
} }

View file

@ -76,6 +76,7 @@ struct _GstM3U8Client
GstM3U8 *current; GstM3U8 *current;
guint update_failed_count; guint update_failed_count;
gint sequence; /* the next sequence for this client */ gint sequence; /* the next sequence for this client */
GstClockTime sequence_position; /* position of this sequence */
GMutex lock; GMutex lock;
}; };
@ -88,8 +89,6 @@ 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, const gchar ** key, const guint8 ** iv); GstClockTime * timestamp, const gchar ** key, const guint8 ** iv);
void gst_m3u8_client_advance_fragment (GstM3U8Client * client); void gst_m3u8_client_advance_fragment (GstM3U8Client * client);
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);