diff options
Diffstat (limited to 'ext/hls/m3u8.c')
-rwxr-xr-x | ext/hls/m3u8.c | 81 |
1 files changed, 77 insertions, 4 deletions
diff --git a/ext/hls/m3u8.c b/ext/hls/m3u8.c index c737b3d4a..ee0a45d84 100755 --- a/ext/hls/m3u8.c +++ b/ext/hls/m3u8.c @@ -51,8 +51,8 @@ gst_g_list_copy_deep (GList * list, GCopyFunc func, gpointer user_data) static GstM3U8 *gst_m3u8_new (void); static void gst_m3u8_free (GstM3U8 * m3u8); -static gboolean gst_m3u8_update (GstM3U8 * m3u8, gchar * data, - gboolean * updated); +static gboolean gst_m3u8_update (GstM3U8Client * client, GstM3U8 * m3u8, + gchar * data, gboolean * updated); static GstM3U8MediaFile *gst_m3u8_media_file_new (gchar * uri, gchar * title, GstClockTime duration, guint sequence); static void gst_m3u8_media_file_free (GstM3U8MediaFile * self); @@ -382,7 +382,8 @@ gst_m3u8_compare_playlist_by_bitrate (gconstpointer a, gconstpointer b) * @data: a m3u8 playlist text data, taking ownership */ static gboolean -gst_m3u8_update (GstM3U8 * self, gchar * data, gboolean * updated) +gst_m3u8_update (GstM3U8Client * client, GstM3U8 * self, gchar * data, + gboolean * updated) { gint val; GstClockTime duration; @@ -723,6 +724,37 @@ gst_m3u8_update (GstM3U8 * self, gchar * data, gboolean * updated) self->current_variant = g_list_find_custom (self->lists, top_variant_uri, (GCompareFunc) _m3u8_compare_uri); } + /* calculate the start and end times of this media playlist. */ + if (self->files) { + GList *walk; + GstM3U8MediaFile *file; + GstClockTime duration = 0; + + for (walk = self->files; walk; walk = walk->next) { + file = walk->data; + duration += file->duration; + if (file->sequence > client->highest_sequence_number) { + if (client->highest_sequence_number >= 0) { + /* if an update of the media playlist has been missed, there + will be a gap between self->highest_sequence_number and the + first sequence number in this media playlist. In this situation + assume that the missing fragments had a duration of + targetduration each */ + client->last_file_end += + (file->sequence - client->highest_sequence_number - + 1) * self->targetduration; + } + client->last_file_end += file->duration; + client->highest_sequence_number = file->sequence; + } + } + if (GST_M3U8_CLIENT_IS_LIVE (client)) { + client->first_file_start = client->last_file_end - duration; + GST_DEBUG ("Live playlist range %" GST_TIME_FORMAT " -> %" + GST_TIME_FORMAT, GST_TIME_ARGS (client->first_file_start), + GST_TIME_ARGS (client->last_file_end)); + } + } return TRUE; } @@ -740,6 +772,7 @@ gst_m3u8_client_new (const gchar * uri, const gchar * base_uri) client->sequence = -1; client->sequence_position = 0; client->update_failed_count = 0; + client->highest_sequence_number = -1; g_mutex_init (&client->lock); gst_m3u8_set_uri (client->main, g_strdup (uri), g_strdup (base_uri), NULL); @@ -781,7 +814,7 @@ gst_m3u8_client_update (GstM3U8Client * self, gchar * data) GST_M3U8_CLIENT_LOCK (self); m3u8 = self->current ? self->current : self->main; - if (!gst_m3u8_update (m3u8, data, &updated)) + if (!gst_m3u8_update (self, m3u8, data, &updated)) goto out; if (!updated) { @@ -1228,3 +1261,43 @@ gst_m3u8_client_get_current_fragment_duration (GstM3U8Client * client) GST_M3U8_CLIENT_UNLOCK (client); return dur; } + +gboolean +gst_m3u8_client_get_seek_range (GstM3U8Client * client, gint64 * start, + gint64 * stop) +{ + GstClockTime duration = 0; + GList *walk; + GstM3U8MediaFile *file; + guint count; + + g_return_val_if_fail (client != NULL, FALSE); + + GST_M3U8_CLIENT_LOCK (client); + + if (client->current == NULL || client->current->files == NULL) { + GST_M3U8_CLIENT_UNLOCK (client); + return FALSE; + } + + count = g_list_length (client->current->files); + + /* count is used to make sure the seek range is never closer than + GST_M3U8_LIVE_MIN_FRAGMENT_DISTANCE fragments from the end of the + playlist - see 6.3.3. "Playing the Playlist file" of the HLS draft */ + for (walk = client->current->files; + walk && count >= GST_M3U8_LIVE_MIN_FRAGMENT_DISTANCE; walk = walk->next) { + file = walk->data; + --count; + duration += file->duration; + } + + if (duration <= 0) { + GST_M3U8_CLIENT_UNLOCK (client); + return FALSE; + } + *start = client->first_file_start; + *stop = *start + duration; + GST_M3U8_CLIENT_UNLOCK (client); + return TRUE; +} |