hlsdemux2: Handle loss of synchronization in live
[platform/upstream/gstreamer.git] / subprojects / gst-plugins-good / ext / adaptivedemux2 / hls / gsthlsdemux.c
1 /* GStreamer
2  * Copyright (C) 2010 Marc-Andre Lureau <marcandre.lureau@gmail.com>
3  * Copyright (C) 2010 Andoni Morales Alastruey <ylatuya@gmail.com>
4  * Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
5  *  Author: Youness Alaoui <youness.alaoui@collabora.co.uk>, Collabora Ltd.
6  *  Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
7  * Copyright (C) 2014 Sebastian Dröge <sebastian@centricular.com>
8  * Copyright (C) 2015 Tim-Philipp Müller <tim@centricular.com>
9  *
10  * Copyright (C) 2021-2022 Centricular Ltd
11  *   Author: Edward Hervey <edward@centricular.com>
12  *   Author: Jan Schmidt <jan@centricular.com>
13  *
14  * Gsthlsdemux.c:
15  *
16  * This library is free software; you can redistribute it and/or
17  * modify it under the terms of the GNU Library General Public
18  * License as published by the Free Software Foundation; either
19  * version 2 of the License, or (at your option) any later version.
20  *
21  * This library is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24  * Library General Public License for more details.
25  *
26  * You should have received a copy of the GNU Library General Public
27  * License along with this library; if not, write to the
28  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
29  * Boston, MA 02110-1301, USA.
30  */
31 /**
32  * SECTION:element-hlsdemux2
33  * @title: hlsdemux2
34  *
35  * HTTP Live Streaming demuxer element.
36  *
37  * ## Example launch line
38  * |[
39  * gst-launch-1.0 playbin3 uri=http://devimages.apple.com/iphone/samples/bipbop/gear4/prog_index.m3u8
40  * ]|
41  *
42  * Since: 1.22
43  */
44
45 #ifdef HAVE_CONFIG_H
46 #  include "config.h"
47 #endif
48
49 #include <string.h>
50 #include <gst/base/gsttypefindhelper.h>
51 #include <gst/tag/tag.h>
52
53 #include "gsthlselements.h"
54 #include "gstadaptivedemuxelements.h"
55 #include "gsthlsdemux.h"
56
57 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
58     GST_PAD_SINK,
59     GST_PAD_ALWAYS,
60     GST_STATIC_CAPS ("application/x-hls"));
61
62 GST_DEBUG_CATEGORY (gst_hls_demux2_debug);
63 #define GST_CAT_DEFAULT gst_hls_demux2_debug
64
65 enum
66 {
67   PROP_0,
68
69   PROP_START_BITRATE,
70 };
71
72 #define DEFAULT_START_BITRATE 0
73
74 /* Maximum values for mpeg-ts DTS values */
75 #define MPEG_TS_MAX_PTS (((((guint64)1) << 33) * (guint64)100000) / 9)
76
77 /* GObject */
78 static void gst_hls_demux_finalize (GObject * obj);
79
80 /* GstElement */
81 static GstStateChangeReturn
82 gst_hls_demux_change_state (GstElement * element, GstStateChange transition);
83
84 /* GstHLSDemux */
85 static GstFlowReturn gst_hls_demux_update_playlist (GstHLSDemux * demux,
86     gboolean update, GError ** err);
87
88 /* FIXME: the return value is never used? */
89 static gboolean gst_hls_demux_change_playlist (GstHLSDemux * demux,
90     guint max_bitrate, gboolean * changed);
91 static GstBuffer *gst_hls_demux_decrypt_fragment (GstHLSDemux * demux,
92     GstHLSDemuxStream * stream, GstBuffer * encrypted_buffer, GError ** err);
93 static gboolean
94 gst_hls_demux_stream_decrypt_start (GstHLSDemuxStream * stream,
95     const guint8 * key_data, const guint8 * iv_data);
96 static void gst_hls_demux_stream_decrypt_end (GstHLSDemuxStream * stream);
97
98 static gboolean gst_hls_demux_is_live (GstAdaptiveDemux * demux);
99 static GstClockTime gst_hls_demux_get_duration (GstAdaptiveDemux * demux);
100 static gint64 gst_hls_demux_get_manifest_update_interval (GstAdaptiveDemux *
101     demux);
102 static gboolean gst_hls_demux_process_manifest (GstAdaptiveDemux * demux,
103     GstBuffer * buf);
104 static GstFlowReturn gst_hls_demux_stream_update_rendition_playlist (GstHLSDemux
105     * demux, GstHLSDemuxStream * stream);
106 static GstFlowReturn gst_hls_demux_update_manifest (GstAdaptiveDemux * demux);
107
108 static void setup_initial_playlist (GstHLSDemux * demux,
109     GstHLSMediaPlaylist * playlist);
110 static void gst_hls_demux_add_time_mapping (GstHLSDemux * demux,
111     gint64 dsn, GstClockTimeDiff stream_time, GDateTime * pdt);
112 static void
113 gst_hls_update_time_mappings (GstHLSDemux * demux,
114     GstHLSMediaPlaylist * playlist);
115
116 static void gst_hls_prune_time_mappings (GstHLSDemux * demux);
117
118 static gboolean gst_hls_demux_seek (GstAdaptiveDemux * demux, GstEvent * seek);
119 static GstFlowReturn gst_hls_demux_stream_seek (GstAdaptiveDemux2Stream *
120     stream, gboolean forward, GstSeekFlags flags, GstClockTimeDiff ts,
121     GstClockTimeDiff * final_ts);
122 static gboolean
123 gst_hls_demux_start_fragment (GstAdaptiveDemux * demux,
124     GstAdaptiveDemux2Stream * stream);
125 static GstFlowReturn gst_hls_demux_finish_fragment (GstAdaptiveDemux * demux,
126     GstAdaptiveDemux2Stream * stream);
127 static GstFlowReturn gst_hls_demux_data_received (GstAdaptiveDemux * demux,
128     GstAdaptiveDemux2Stream * stream, GstBuffer * buffer);
129
130 static gboolean gst_hls_demux_stream_has_next_fragment (GstAdaptiveDemux2Stream
131     * stream);
132 static GstFlowReturn gst_hls_demux_advance_fragment (GstAdaptiveDemux2Stream *
133     stream);
134 static GstFlowReturn gst_hls_demux_update_fragment_info (GstAdaptiveDemux2Stream
135     * stream);
136 static gboolean gst_hls_demux_stream_can_start (GstAdaptiveDemux * demux,
137     GstAdaptiveDemux2Stream * stream);
138 static void gst_hls_demux_stream_update_tracks (GstAdaptiveDemux * demux,
139     GstAdaptiveDemux2Stream * stream);
140 static gboolean gst_hls_demux_select_bitrate (GstAdaptiveDemux2Stream * stream,
141     guint64 bitrate);
142 static void gst_hls_demux_reset (GstAdaptiveDemux * demux);
143 static gboolean gst_hls_demux_get_live_seek_range (GstAdaptiveDemux * demux,
144     gint64 * start, gint64 * stop);
145 static GstClockTime gst_hls_demux_get_presentation_offset (GstAdaptiveDemux *
146     demux, GstAdaptiveDemux2Stream * stream);
147 static void gst_hls_demux_set_current_variant (GstHLSDemux * hlsdemux,
148     GstHLSVariantStream * variant);
149
150 static void gst_hls_demux_stream_finalize (GObject * object);
151
152 #define gst_hls_demux_stream_parent_class stream_parent_class
153 G_DEFINE_TYPE (GstHLSDemuxStream, gst_hls_demux_stream,
154     GST_TYPE_ADAPTIVE_DEMUX2_STREAM);
155
156 static gboolean hlsdemux2_element_init (GstPlugin * plugin);
157
158 GST_ELEMENT_REGISTER_DEFINE_CUSTOM (hlsdemux2, hlsdemux2_element_init);
159
160 static void
161 gst_hls_demux_stream_class_init (GstHLSDemuxStreamClass * klass)
162 {
163   GObjectClass *gobject_class = (GObjectClass *) klass;
164
165   gobject_class->finalize = gst_hls_demux_stream_finalize;
166 }
167
168 static void
169 gst_hls_demux_stream_init (GstHLSDemuxStream * stream)
170 {
171   stream->parser_type = GST_HLS_PARSER_NONE;
172   stream->do_typefind = TRUE;
173   stream->reset_pts = TRUE;
174   stream->presentation_offset = 60 * GST_SECOND;
175 }
176
177 typedef struct _GstHLSDemux2 GstHLSDemux2;
178 typedef struct _GstHLSDemux2Class GstHLSDemux2Class;
179
180 #define gst_hls_demux2_parent_class parent_class
181 G_DEFINE_TYPE_WITH_CODE (GstHLSDemux2, gst_hls_demux2, GST_TYPE_ADAPTIVE_DEMUX,
182     hls2_element_init ());
183
184 static void
185 gst_hls_demux_finalize (GObject * obj)
186 {
187   GstHLSDemux *demux = GST_HLS_DEMUX (obj);
188
189   gst_hls_demux_reset (GST_ADAPTIVE_DEMUX_CAST (demux));
190   g_mutex_clear (&demux->keys_lock);
191   if (demux->keys) {
192     g_hash_table_unref (demux->keys);
193     demux->keys = NULL;
194   }
195
196   G_OBJECT_CLASS (parent_class)->finalize (obj);
197 }
198
199 static void
200 gst_hls_demux_set_property (GObject * object, guint prop_id,
201     const GValue * value, GParamSpec * pspec)
202 {
203   GstHLSDemux *demux = GST_HLS_DEMUX (object);
204
205   switch (prop_id) {
206     case PROP_START_BITRATE:
207       demux->start_bitrate = g_value_get_uint (value);
208       break;
209     default:
210       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
211       break;
212   }
213 }
214
215 static void
216 gst_hls_demux_get_property (GObject * object, guint prop_id,
217     GValue * value, GParamSpec * pspec)
218 {
219   GstHLSDemux *demux = GST_HLS_DEMUX (object);
220
221   switch (prop_id) {
222     case PROP_START_BITRATE:
223       g_value_set_uint (value, demux->start_bitrate);
224       break;
225     default:
226       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
227       break;
228   }
229 }
230
231
232 static void
233 gst_hls_demux2_class_init (GstHLSDemux2Class * klass)
234 {
235   GObjectClass *gobject_class;
236   GstElementClass *element_class;
237   GstAdaptiveDemuxClass *adaptivedemux_class;
238
239   gobject_class = (GObjectClass *) klass;
240   element_class = (GstElementClass *) klass;
241   adaptivedemux_class = (GstAdaptiveDemuxClass *) klass;
242
243   gobject_class->set_property = gst_hls_demux_set_property;
244   gobject_class->get_property = gst_hls_demux_get_property;
245   gobject_class->finalize = gst_hls_demux_finalize;
246
247   g_object_class_install_property (gobject_class, PROP_START_BITRATE,
248       g_param_spec_uint ("start-bitrate", "Starting Bitrate",
249           "Initial bitrate to use to choose first alternate (0 = automatic) (bits/s)",
250           0, G_MAXUINT, DEFAULT_START_BITRATE,
251           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
252
253   element_class->change_state = GST_DEBUG_FUNCPTR (gst_hls_demux_change_state);
254
255   gst_element_class_add_static_pad_template (element_class, &sinktemplate);
256
257   gst_element_class_set_static_metadata (element_class,
258       "HLS Demuxer",
259       "Codec/Demuxer/Adaptive",
260       "HTTP Live Streaming demuxer",
261       "Edward Hervey <edward@centricular.com>\n"
262       "Jan Schmidt <jan@centricular.com>");
263
264   adaptivedemux_class->is_live = gst_hls_demux_is_live;
265   adaptivedemux_class->get_live_seek_range = gst_hls_demux_get_live_seek_range;
266   adaptivedemux_class->get_presentation_offset =
267       gst_hls_demux_get_presentation_offset;
268   adaptivedemux_class->get_duration = gst_hls_demux_get_duration;
269   adaptivedemux_class->get_manifest_update_interval =
270       gst_hls_demux_get_manifest_update_interval;
271   adaptivedemux_class->process_manifest = gst_hls_demux_process_manifest;
272   adaptivedemux_class->update_manifest = gst_hls_demux_update_manifest;
273   adaptivedemux_class->reset = gst_hls_demux_reset;
274   adaptivedemux_class->seek = gst_hls_demux_seek;
275   adaptivedemux_class->stream_seek = gst_hls_demux_stream_seek;
276   adaptivedemux_class->stream_has_next_fragment =
277       gst_hls_demux_stream_has_next_fragment;
278   adaptivedemux_class->stream_advance_fragment = gst_hls_demux_advance_fragment;
279   adaptivedemux_class->stream_update_fragment_info =
280       gst_hls_demux_update_fragment_info;
281   adaptivedemux_class->stream_select_bitrate = gst_hls_demux_select_bitrate;
282   adaptivedemux_class->stream_can_start = gst_hls_demux_stream_can_start;
283   adaptivedemux_class->stream_update_tracks =
284       gst_hls_demux_stream_update_tracks;
285
286   adaptivedemux_class->start_fragment = gst_hls_demux_start_fragment;
287   adaptivedemux_class->finish_fragment = gst_hls_demux_finish_fragment;
288   adaptivedemux_class->data_received = gst_hls_demux_data_received;
289 }
290
291 static void
292 gst_hls_demux2_init (GstHLSDemux * demux)
293 {
294   demux->keys = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
295   g_mutex_init (&demux->keys_lock);
296 }
297
298 static GstStateChangeReturn
299 gst_hls_demux_change_state (GstElement * element, GstStateChange transition)
300 {
301   GstStateChangeReturn ret;
302   GstHLSDemux *demux = GST_HLS_DEMUX (element);
303
304   switch (transition) {
305     case GST_STATE_CHANGE_READY_TO_PAUSED:
306       gst_hls_demux_reset (GST_ADAPTIVE_DEMUX_CAST (demux));
307       break;
308     default:
309       break;
310   }
311
312   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
313
314   switch (transition) {
315     case GST_STATE_CHANGE_PAUSED_TO_READY:
316       gst_hls_demux_reset (GST_ADAPTIVE_DEMUX_CAST (demux));
317       g_hash_table_remove_all (demux->keys);
318       break;
319     default:
320       break;
321   }
322   return ret;
323 }
324
325 static guint64
326 gst_hls_demux_get_bitrate (GstHLSDemux * hlsdemux)
327 {
328   GstAdaptiveDemux *demux = GST_ADAPTIVE_DEMUX_CAST (hlsdemux);
329
330   /* FIXME !!!
331    *
332    * No, there isn't a single output :D */
333
334   /* Valid because hlsdemux only has a single output */
335   if (demux->input_period->streams) {
336     GstAdaptiveDemux2Stream *stream = demux->input_period->streams->data;
337     return stream->current_download_rate;
338   }
339
340   return 0;
341 }
342
343 static void
344 gst_hls_demux_stream_clear_pending_data (GstHLSDemuxStream * hls_stream,
345     gboolean force)
346 {
347   GST_DEBUG_OBJECT (hls_stream, "force : %d", force);
348   if (hls_stream->pending_encrypted_data)
349     gst_adapter_clear (hls_stream->pending_encrypted_data);
350   gst_buffer_replace (&hls_stream->pending_decrypted_buffer, NULL);
351   gst_buffer_replace (&hls_stream->pending_typefind_buffer, NULL);
352   if (force || !hls_stream->pending_data_is_header) {
353     gst_buffer_replace (&hls_stream->pending_segment_data, NULL);
354     hls_stream->pending_data_is_header = FALSE;
355   }
356   hls_stream->current_offset = -1;
357   hls_stream->process_buffer_content = TRUE;
358   gst_hls_demux_stream_decrypt_end (hls_stream);
359 }
360
361 static void
362 gst_hls_demux_clear_all_pending_data (GstHLSDemux * hlsdemux)
363 {
364   GstAdaptiveDemux *demux = (GstAdaptiveDemux *) hlsdemux;
365   GList *walk;
366
367   if (!demux->input_period)
368     return;
369
370   for (walk = demux->input_period->streams; walk != NULL; walk = walk->next) {
371     GstHLSDemuxStream *hls_stream = GST_HLS_DEMUX_STREAM_CAST (walk->data);
372     gst_hls_demux_stream_clear_pending_data (hls_stream, TRUE);
373   }
374 }
375
376 #define SEEK_UPDATES_PLAY_POSITION(r, start_type, stop_type) \
377   ((r >= 0 && start_type != GST_SEEK_TYPE_NONE) || \
378    (r < 0 && stop_type != GST_SEEK_TYPE_NONE))
379
380 #define IS_SNAP_SEEK(f) (f & (GST_SEEK_FLAG_SNAP_BEFORE |         \
381                               GST_SEEK_FLAG_SNAP_AFTER |          \
382                               GST_SEEK_FLAG_SNAP_NEAREST |        \
383                               GST_SEEK_FLAG_TRICKMODE_KEY_UNITS | \
384                               GST_SEEK_FLAG_KEY_UNIT))
385
386 static gboolean
387 gst_hls_demux_seek (GstAdaptiveDemux * demux, GstEvent * seek)
388 {
389   GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (demux);
390   GstFormat format;
391   GstSeekFlags flags;
392   GstSeekType start_type, stop_type;
393   gint64 start, stop;
394   gdouble rate, old_rate;
395   GList *walk;
396   gint64 current_pos, target_pos, final_pos;
397   guint64 bitrate;
398
399   gst_event_parse_seek (seek, &rate, &format, &flags, &start_type, &start,
400       &stop_type, &stop);
401
402   if (!SEEK_UPDATES_PLAY_POSITION (rate, start_type, stop_type)) {
403     /* nothing to do if we don't have to update the current position */
404     return TRUE;
405   }
406
407   old_rate = demux->segment.rate;
408
409   bitrate = gst_hls_demux_get_bitrate (hlsdemux);
410
411   /* Use I-frame variants for trick modes */
412   if (hlsdemux->master->iframe_variants != NULL
413       && rate < -1.0 && old_rate >= -1.0 && old_rate <= 1.0) {
414     GError *err = NULL;
415
416     /* Switch to I-frame variant */
417     gst_hls_demux_set_current_variant (hlsdemux,
418         hlsdemux->master->iframe_variants->data);
419
420     if (gst_hls_demux_update_playlist (hlsdemux, FALSE, &err) != GST_FLOW_OK) {
421       GST_ELEMENT_ERROR_FROM_ERROR (hlsdemux, "Could not switch playlist", err);
422       return FALSE;
423     }
424     //hlsdemux->discont = TRUE;
425
426     gst_hls_demux_change_playlist (hlsdemux, bitrate / ABS (rate), NULL);
427   } else if (rate > -1.0 && rate <= 1.0 && (old_rate < -1.0 || old_rate > 1.0)) {
428     GError *err = NULL;
429     /* Switch to normal variant */
430     gst_hls_demux_set_current_variant (hlsdemux,
431         hlsdemux->master->variants->data);
432
433     if (gst_hls_demux_update_playlist (hlsdemux, FALSE, &err) != GST_FLOW_OK) {
434       GST_ELEMENT_ERROR_FROM_ERROR (hlsdemux, "Could not switch playlist", err);
435       return FALSE;
436     }
437     //hlsdemux->discont = TRUE;
438     /* TODO why not continue using the same? that was being used up to now? */
439     gst_hls_demux_change_playlist (hlsdemux, bitrate, NULL);
440   }
441
442   target_pos = rate < 0 ? stop : start;
443   final_pos = target_pos;
444
445   /* properly cleanup pending decryption status */
446   if (flags & GST_SEEK_FLAG_FLUSH) {
447     gst_hls_demux_clear_all_pending_data (hlsdemux);
448     gst_hls_prune_time_mappings (hlsdemux);
449   }
450
451   for (walk = demux->input_period->streams; walk; walk = g_list_next (walk)) {
452     GstAdaptiveDemux2Stream *stream =
453         GST_ADAPTIVE_DEMUX2_STREAM_CAST (walk->data);
454
455     /* Only seek on selected streams */
456     if (!gst_adaptive_demux2_stream_is_selected (stream))
457       continue;
458
459     if (gst_hls_demux_stream_seek (stream, rate >= 0, flags, target_pos,
460             &current_pos) != GST_FLOW_OK) {
461       GST_ERROR_OBJECT (stream, "Failed to seek on stream");
462       return FALSE;
463     }
464
465     /* FIXME: use minimum position always ? */
466     if (final_pos > current_pos)
467       final_pos = current_pos;
468   }
469
470   if (IS_SNAP_SEEK (flags)) {
471     if (rate >= 0)
472       gst_segment_do_seek (&demux->segment, rate, format, flags, start_type,
473           final_pos, stop_type, stop, NULL);
474     else
475       gst_segment_do_seek (&demux->segment, rate, format, flags, start_type,
476           start, stop_type, final_pos, NULL);
477   }
478
479   return TRUE;
480 }
481
482 static GstFlowReturn
483 gst_hls_demux_stream_seek (GstAdaptiveDemux2Stream * stream, gboolean forward,
484     GstSeekFlags flags, GstClockTimeDiff ts, GstClockTimeDiff * final_ts)
485 {
486   GstFlowReturn ret = GST_FLOW_OK;
487   GstHLSDemuxStream *hls_stream = GST_HLS_DEMUX_STREAM_CAST (stream);
488   GstHLSDemux *hlsdemux = (GstHLSDemux *) stream->demux;
489   GstM3U8MediaSegment *new_position;
490
491   GST_DEBUG_OBJECT (stream,
492       "is_variant:%d media:%p current_variant:%p forward:%d ts:%"
493       GST_TIME_FORMAT, hls_stream->is_variant, hls_stream->current_rendition,
494       hlsdemux->current_variant, forward, GST_TIME_ARGS (ts));
495
496   /* If the rendition playlist needs to be updated, do it now */
497   if (!hls_stream->is_variant && !hls_stream->playlist_fetched) {
498     ret = gst_hls_demux_stream_update_rendition_playlist (hlsdemux, hls_stream);
499     if (ret != GST_FLOW_OK) {
500       GST_WARNING_OBJECT (stream,
501           "Failed to update the rendition playlist before seeking");
502       return ret;
503     }
504   }
505
506   new_position =
507       gst_hls_media_playlist_seek (hls_stream->playlist, forward, flags, ts);
508   if (new_position) {
509     if (hls_stream->current_segment)
510       gst_m3u8_media_segment_unref (hls_stream->current_segment);
511     hls_stream->current_segment = new_position;
512     hls_stream->reset_pts = TRUE;
513     if (final_ts)
514       *final_ts = new_position->stream_time;
515   } else {
516     GST_WARNING_OBJECT (stream, "Seeking failed");
517     ret = GST_FLOW_ERROR;
518   }
519
520   return ret;
521 }
522
523 static GstFlowReturn
524 gst_hls_demux_update_manifest (GstAdaptiveDemux * demux)
525 {
526   GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (demux);
527
528   return gst_hls_demux_update_playlist (hlsdemux, TRUE, NULL);
529 }
530
531 static GstAdaptiveDemux2Stream *
532 create_common_hls_stream (GstHLSDemux * demux, const gchar * name)
533 {
534   GstAdaptiveDemux2Stream *stream;
535
536   stream = g_object_new (GST_TYPE_HLS_DEMUX_STREAM, "name", name, NULL);
537   gst_adaptive_demux2_add_stream ((GstAdaptiveDemux *) demux, stream);
538
539   return stream;
540 }
541
542 static GstAdaptiveDemuxTrack *
543 new_track_for_rendition (GstHLSDemux * demux, GstHLSRenditionStream * rendition,
544     GstCaps * caps, GstStreamFlags flags, GstTagList * tags)
545 {
546   GstAdaptiveDemuxTrack *track;
547   gchar *stream_id;
548   GstStreamType stream_type = gst_stream_type_from_hls_type (rendition->mtype);
549
550   if (rendition->name)
551     stream_id =
552         g_strdup_printf ("%s-%s", gst_stream_type_get_name (stream_type),
553         rendition->name);
554   else if (rendition->lang)
555     stream_id =
556         g_strdup_printf ("%s-%s", gst_stream_type_get_name (stream_type),
557         rendition->lang);
558   else
559     stream_id = g_strdup (gst_stream_type_get_name (stream_type));
560
561   if (rendition->lang) {
562     if (tags == NULL)
563       tags = gst_tag_list_new_empty ();
564     if (gst_tag_check_language_code (rendition->lang))
565       gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_LANGUAGE_CODE,
566           rendition->lang, NULL);
567     else
568       gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_LANGUAGE_NAME,
569           rendition->lang, NULL);
570   }
571
572   if (stream_type == GST_STREAM_TYPE_TEXT)
573     flags |= GST_STREAM_FLAG_SPARSE;
574
575   if (rendition->is_default)
576     flags |= GST_STREAM_FLAG_SELECT;
577
578   track =
579       gst_adaptive_demux_track_new ((GstAdaptiveDemux *) demux, stream_type,
580       flags, stream_id, caps, tags);
581   g_free (stream_id);
582
583   return track;
584 }
585
586 static GstHLSRenditionStream *
587 find_uriless_rendition (GstHLSDemux * demux, GstStreamType stream_type)
588 {
589   GList *tmp;
590
591   for (tmp = demux->master->renditions; tmp; tmp = tmp->next) {
592     GstHLSRenditionStream *media = tmp->data;
593     if (media->uri == NULL &&
594         gst_stream_type_from_hls_type (media->mtype) == stream_type)
595       return media;
596   }
597   return NULL;
598 }
599
600 static GstCaps *
601 get_caps_of_stream_type (GstCaps * full_caps, GstStreamType streamtype)
602 {
603   GstCaps *ret = NULL;
604
605   guint i;
606   for (i = 0; i < gst_caps_get_size (full_caps); i++) {
607     GstStructure *st = gst_caps_get_structure (full_caps, i);
608
609     if (gst_hls_get_stream_type_from_structure (st) == streamtype) {
610       ret = gst_caps_new_empty ();
611       gst_caps_append_structure (ret, gst_structure_copy (st));
612       break;
613     }
614   }
615
616   return ret;
617 }
618
619 static void
620 gst_hls_demux_stream_update_tracks (GstAdaptiveDemux * demux,
621     GstAdaptiveDemux2Stream * stream)
622 {
623   GstHLSDemux *hlsdemux = (GstHLSDemux *) demux;
624   GstHLSDemuxStream *hlsdemux_stream = (GstHLSDemuxStream *) stream;
625   guint i;
626   GstStreamType uriless_types = 0;
627   GstCaps *variant_caps = NULL;
628
629   GST_DEBUG_OBJECT (demux, "Update tracks of variant stream");
630
631   if (hlsdemux->master->have_codecs) {
632     variant_caps = gst_hls_master_playlist_get_common_caps (hlsdemux->master);
633   }
634
635   /* Use the stream->stream_collection and manifest to create the appropriate tracks */
636   for (i = 0; i < gst_stream_collection_get_size (stream->stream_collection);
637       i++) {
638     GstStream *gst_stream =
639         gst_stream_collection_get_stream (stream->stream_collection, i);
640     GstStreamType stream_type = gst_stream_get_stream_type (gst_stream);
641     GstAdaptiveDemuxTrack *track;
642     GstHLSRenditionStream *embedded_media = NULL;
643     /* tracks from the variant streams should be prefered over those provided by renditions */
644     GstStreamFlags flags =
645         gst_stream_get_stream_flags (gst_stream) | GST_STREAM_FLAG_SELECT;
646     GstCaps *manifest_caps = NULL;
647
648     if (stream_type == GST_STREAM_TYPE_UNKNOWN)
649       continue;
650
651     if (variant_caps)
652       manifest_caps = get_caps_of_stream_type (variant_caps, stream_type);
653     hlsdemux_stream->rendition_type |= stream_type;
654
655     if ((uriless_types & stream_type) == 0) {
656       /* Do we have a uriless media for this stream type */
657       /* Find if there is a rendition without URI, it will be provided by this variant */
658       embedded_media = find_uriless_rendition (hlsdemux, stream_type);
659       /* Remember we used this type for a embedded media */
660       uriless_types |= stream_type;
661     }
662
663     if (embedded_media) {
664       GstTagList *tags = gst_stream_get_tags (gst_stream);
665       GST_DEBUG_OBJECT (demux, "Adding track '%s' to main variant stream",
666           embedded_media->name);
667       track =
668           new_track_for_rendition (hlsdemux, embedded_media, manifest_caps,
669           flags, tags ? gst_tag_list_make_writable (tags) : tags);
670     } else {
671       gchar *stream_id;
672       stream_id =
673           g_strdup_printf ("main-%s-%d", gst_stream_type_get_name (stream_type),
674           i);
675
676       GST_DEBUG_OBJECT (demux, "Adding track '%s' to main variant stream",
677           stream_id);
678       track =
679           gst_adaptive_demux_track_new (demux, stream_type,
680           flags, stream_id, manifest_caps, NULL);
681       g_free (stream_id);
682     }
683     track->upstream_stream_id =
684         g_strdup (gst_stream_get_stream_id (gst_stream));
685     gst_adaptive_demux2_stream_add_track (stream, track);
686     gst_adaptive_demux_track_unref (track);
687   }
688
689   if (variant_caps)
690     gst_caps_unref (variant_caps);
691
692   /* Update the stream object with rendition types.
693    * FIXME: rendition_type could be removed */
694   stream->stream_type = hlsdemux_stream->rendition_type;
695 }
696
697 static void
698 create_main_variant_stream (GstHLSDemux * demux)
699 {
700   GstAdaptiveDemux2Stream *stream;
701   GstHLSDemuxStream *hlsdemux_stream;
702
703   GST_DEBUG_OBJECT (demux, "Creating main variant stream");
704
705   stream = create_common_hls_stream (demux, "hlsstream-variant");
706   demux->main_stream = hlsdemux_stream = (GstHLSDemuxStream *) stream;
707   hlsdemux_stream->is_variant = TRUE;
708   hlsdemux_stream->playlist_fetched = TRUE;
709   /* Due to HLS manifest information being so unreliable/inconsistent, we will
710    * create the actual tracks once we have information about the streams present
711    * in the variant data stream */
712   stream->pending_tracks = TRUE;
713 }
714
715 static GstHLSDemuxStream *
716 create_rendition_stream (GstHLSDemux * demux, GstHLSRenditionStream * media)
717 {
718   GstAdaptiveDemux2Stream *stream;
719   GstAdaptiveDemuxTrack *track;
720   GstHLSDemuxStream *hlsdemux_stream;
721   gchar *stream_name;
722
723   GST_DEBUG_OBJECT (demux,
724       "Creating stream for media %s lang:%s (%" GST_PTR_FORMAT ")", media->name,
725       media->lang, media->caps);
726
727   /* We can't reliably provide caps for HLS target tracks since they might
728    * change at any point in time */
729   track = new_track_for_rendition (demux, media, NULL, 0, NULL);
730
731   stream_name = g_strdup_printf ("hlsstream-%s", track->stream_id);
732   stream = create_common_hls_stream (demux, stream_name);
733   g_free (stream_name);
734   hlsdemux_stream = (GstHLSDemuxStream *) stream;
735
736   hlsdemux_stream->is_variant = FALSE;
737   hlsdemux_stream->playlist_fetched = FALSE;
738   stream->stream_type = hlsdemux_stream->rendition_type =
739       gst_stream_type_from_hls_type (media->mtype);
740   if (media->lang)
741     hlsdemux_stream->lang = g_strdup (media->lang);
742   if (media->name)
743     hlsdemux_stream->name = g_strdup (media->name);
744
745   gst_adaptive_demux2_stream_add_track (stream, track);
746   gst_adaptive_demux_track_unref (track);
747
748   return hlsdemux_stream;
749 }
750
751 static GstHLSDemuxStream *
752 existing_rendition_stream (GList * streams, GstHLSRenditionStream * media)
753 {
754   GList *tmp;
755   GstStreamType stream_type = gst_stream_type_from_hls_type (media->mtype);
756
757   for (tmp = streams; tmp; tmp = tmp->next) {
758     GstHLSDemuxStream *demux_stream = tmp->data;
759
760     if (demux_stream->is_variant)
761       continue;
762
763     if (demux_stream->rendition_type == stream_type) {
764       if (!g_strcmp0 (demux_stream->name, media->name))
765         return demux_stream;
766       if (media->lang && !g_strcmp0 (demux_stream->lang, media->lang))
767         return demux_stream;
768     }
769   }
770
771   return NULL;
772 }
773
774 static gboolean
775 gst_hls_demux_setup_streams (GstAdaptiveDemux * demux)
776 {
777   GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (demux);
778   GstHLSVariantStream *playlist = hlsdemux->current_variant;
779   GList *tmp;
780   GList *streams = NULL;
781
782   if (playlist == NULL) {
783     GST_WARNING_OBJECT (demux, "Can't configure streams - no variant selected");
784     return FALSE;
785   }
786
787   GST_DEBUG_OBJECT (demux, "Setting up streams");
788
789   /* If there are alternate renditions, we will produce a GstAdaptiveDemux2Stream
790    * and GstAdaptiveDemuxTrack for each combination of GstStreamType and other
791    * unique identifier (for now just language)
792    *
793    * Which actual GstHLSMedia to use for each stream will be determined based on
794    * the `group-id` (if present and more than one) selected on the main variant
795    * stream */
796   for (tmp = hlsdemux->master->renditions; tmp; tmp = tmp->next) {
797     GstHLSRenditionStream *media = tmp->data;
798     GstHLSDemuxStream *media_stream, *previous_media_stream;
799
800     GST_LOG_OBJECT (demux, "Rendition %s name:'%s' lang:'%s' uri:%s",
801         gst_stream_type_get_name (gst_stream_type_from_hls_type (media->mtype)),
802         media->name, media->lang, media->uri);
803
804     if (media->uri == NULL) {
805       GST_DEBUG_OBJECT (demux,
806           "Skipping media '%s' , it's provided by the variant stream",
807           media->name);
808       continue;
809     }
810
811     media_stream = previous_media_stream =
812         existing_rendition_stream (streams, media);
813
814     if (!media_stream) {
815       media_stream = create_rendition_stream (hlsdemux, tmp->data);
816     } else
817       GST_DEBUG_OBJECT (demux, "Re-using existing GstHLSDemuxStream %s %s",
818           media_stream->name, media_stream->lang);
819
820     /* Is this rendition active in the current variant ? */
821     if (!g_strcmp0 (playlist->media_groups[media->mtype], media->group_id)) {
822       GST_DEBUG_OBJECT (demux, "Enabling rendition");
823       if (media_stream->current_rendition)
824         gst_hls_rendition_stream_unref (media_stream->current_rendition);
825       media_stream->current_rendition = gst_hls_rendition_stream_ref (media);
826     }
827
828     if (!previous_media_stream)
829       streams = g_list_append (streams, media_stream);
830   }
831
832   /* Free the list (but not the contents, which are stored
833    * elsewhere */
834   if (streams)
835     g_list_free (streams);
836
837   create_main_variant_stream (hlsdemux);
838
839   return TRUE;
840 }
841
842 static const gchar *
843 gst_adaptive_demux_get_manifest_ref_uri (GstAdaptiveDemux * d)
844 {
845   return d->manifest_base_uri ? d->manifest_base_uri : d->manifest_uri;
846 }
847
848 static void
849 gst_hls_demux_set_current_variant (GstHLSDemux * hlsdemux,
850     GstHLSVariantStream * variant)
851 {
852   if (hlsdemux->current_variant == variant || variant == NULL)
853     return;
854
855   if (hlsdemux->current_variant != NULL) {
856     GST_DEBUG_OBJECT (hlsdemux, "Will switch from variant '%s' to '%s'",
857         hlsdemux->current_variant->name, variant->name);
858     if (hlsdemux->pending_variant) {
859       GST_ERROR_OBJECT (hlsdemux, "Already waiting for pending variant '%s'",
860           hlsdemux->pending_variant->name);
861       gst_hls_variant_stream_unref (hlsdemux->pending_variant);
862     }
863     hlsdemux->pending_variant = gst_hls_variant_stream_ref (variant);
864   } else {
865     GST_DEBUG_OBJECT (hlsdemux, "Setting variant '%s'", variant->name);
866     hlsdemux->current_variant = gst_hls_variant_stream_ref (variant);
867   }
868 }
869
870 static gboolean
871 gst_hls_demux_process_manifest (GstAdaptiveDemux * demux, GstBuffer * buf)
872 {
873   GstHLSVariantStream *variant;
874   GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (demux);
875   gchar *playlist = NULL;
876   gboolean ret;
877   GstHLSMediaPlaylist *simple_media_playlist = NULL;
878
879   GST_INFO_OBJECT (demux, "Initial playlist location: %s (base uri: %s)",
880       demux->manifest_uri, demux->manifest_base_uri);
881
882   playlist = gst_hls_buf_to_utf8_text (buf);
883   if (playlist == NULL) {
884     GST_WARNING_OBJECT (demux, "Error validating initial playlist");
885     return FALSE;
886   }
887
888   if (hlsdemux->master) {
889     gst_hls_master_playlist_unref (hlsdemux->master);
890     hlsdemux->master = NULL;
891   }
892   hlsdemux->master = gst_hls_master_playlist_new_from_data (playlist,
893       gst_adaptive_demux_get_manifest_ref_uri (demux));
894
895   if (hlsdemux->master == NULL) {
896     /* In most cases, this will happen if we set a wrong url in the
897      * source element and we have received the 404 HTML response instead of
898      * the playlist */
899     GST_ELEMENT_ERROR (demux, STREAM, DECODE, ("Invalid playlist."),
900         ("Could not parse playlist. Check if the URL is correct."));
901     return FALSE;
902   }
903
904   if (hlsdemux->master->is_simple) {
905     simple_media_playlist =
906         gst_hls_media_playlist_parse (playlist,
907         gst_adaptive_demux_get_manifest_ref_uri (demux), NULL);
908   }
909
910   /* select the initial variant stream */
911   if (demux->connection_speed == 0) {
912     variant = hlsdemux->master->default_variant;
913   } else if (hlsdemux->start_bitrate > 0) {
914     variant =
915         gst_hls_master_playlist_get_variant_for_bitrate (hlsdemux->master,
916         NULL, hlsdemux->start_bitrate, demux->min_bitrate);
917   } else {
918     variant =
919         gst_hls_master_playlist_get_variant_for_bitrate (hlsdemux->master,
920         NULL, demux->connection_speed, demux->min_bitrate);
921   }
922
923   if (variant) {
924     GST_INFO_OBJECT (hlsdemux,
925         "Manifest processed, initial variant selected : `%s`", variant->name);
926     gst_hls_demux_set_current_variant (hlsdemux, variant);      // FIXME: inline?
927   }
928
929   GST_DEBUG_OBJECT (hlsdemux, "Manifest handled, now setting up streams");
930
931   ret = gst_hls_demux_setup_streams (demux);
932
933   if (simple_media_playlist) {
934     hlsdemux->main_stream->playlist = simple_media_playlist;
935     hlsdemux->main_stream->current_segment =
936         gst_hls_media_playlist_get_starting_segment (simple_media_playlist);
937     setup_initial_playlist (hlsdemux, simple_media_playlist);
938     gst_hls_update_time_mappings (hlsdemux, simple_media_playlist);
939     gst_hls_media_playlist_dump (simple_media_playlist);
940   }
941
942   /* get the selected media playlist (unless the initial list was one already) */
943   if (!hlsdemux->master->is_simple) {
944     GError *err = NULL;
945
946     if (gst_hls_demux_update_playlist (hlsdemux, FALSE, &err) != GST_FLOW_OK) {
947       GST_ELEMENT_ERROR_FROM_ERROR (demux, "Could not fetch media playlist",
948           err);
949       return FALSE;
950     }
951   }
952
953   return ret;
954 }
955
956 static GstClockTime
957 gst_hls_demux_get_duration (GstAdaptiveDemux * demux)
958 {
959   GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (demux);
960   GstClockTime duration = GST_CLOCK_TIME_NONE;
961
962   if (hlsdemux->main_stream)
963     duration =
964         gst_hls_media_playlist_get_duration (hlsdemux->main_stream->playlist);
965
966   return duration;
967 }
968
969 static gboolean
970 gst_hls_demux_is_live (GstAdaptiveDemux * demux)
971 {
972   GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (demux);
973   gboolean is_live = FALSE;
974
975   if (hlsdemux->main_stream)
976     is_live = gst_hls_media_playlist_is_live (hlsdemux->main_stream->playlist);
977
978   return is_live;
979 }
980
981 static const GstHLSKey *
982 gst_hls_demux_get_key (GstHLSDemux * demux, const gchar * key_url,
983     const gchar * referer, gboolean allow_cache)
984 {
985   GstAdaptiveDemux *adaptive_demux = GST_ADAPTIVE_DEMUX (demux);
986   DownloadRequest *key_request;
987   DownloadFlags dl_flags = DOWNLOAD_FLAG_NONE;
988   GstBuffer *key_buffer;
989   GstHLSKey *key;
990   GError *err = NULL;
991
992   GST_LOG_OBJECT (demux, "Looking up key for key url %s", key_url);
993
994   g_mutex_lock (&demux->keys_lock);
995
996   key = g_hash_table_lookup (demux->keys, key_url);
997
998   if (key != NULL) {
999     GST_LOG_OBJECT (demux, "Found key for key url %s in key cache", key_url);
1000     goto out;
1001   }
1002
1003   GST_INFO_OBJECT (demux, "Fetching key %s", key_url);
1004
1005   if (!allow_cache)
1006     dl_flags |= DOWNLOAD_FLAG_FORCE_REFRESH;
1007
1008   key_request =
1009       downloadhelper_fetch_uri (adaptive_demux->download_helper,
1010       key_url, referer, dl_flags, &err);
1011   if (key_request == NULL) {
1012     GST_WARNING_OBJECT (demux, "Failed to download key to decrypt data: %s",
1013         err ? err->message : "error");
1014     g_clear_error (&err);
1015     goto out;
1016   }
1017
1018   key_buffer = download_request_take_buffer (key_request);
1019   download_request_unref (key_request);
1020
1021   key = g_new0 (GstHLSKey, 1);
1022   if (gst_buffer_extract (key_buffer, 0, key->data, 16) < 16)
1023     GST_WARNING_OBJECT (demux, "Download decryption key is too short!");
1024
1025   g_hash_table_insert (demux->keys, g_strdup (key_url), key);
1026
1027   gst_buffer_unref (key_buffer);
1028
1029 out:
1030
1031   g_mutex_unlock (&demux->keys_lock);
1032
1033   if (key != NULL)
1034     GST_MEMDUMP_OBJECT (demux, "Key", key->data, 16);
1035
1036   return key;
1037 }
1038
1039 static gboolean
1040 gst_hls_demux_start_fragment (GstAdaptiveDemux * demux,
1041     GstAdaptiveDemux2Stream * stream)
1042 {
1043   GstHLSDemuxStream *hls_stream = GST_HLS_DEMUX_STREAM_CAST (stream);
1044   GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (demux);
1045   const GstHLSKey *key;
1046   GstHLSMediaPlaylist *m3u8;
1047
1048   GST_DEBUG_OBJECT (stream, "Fragment starting");
1049
1050   gst_hls_demux_stream_clear_pending_data (hls_stream, FALSE);
1051
1052   /* If no decryption is needed, there's nothing to be done here */
1053   if (hls_stream->current_key == NULL)
1054     return TRUE;
1055
1056   m3u8 = hls_stream->playlist;
1057
1058   key = gst_hls_demux_get_key (hlsdemux, hls_stream->current_key,
1059       m3u8->uri, m3u8->allowcache);
1060
1061   if (key == NULL)
1062     goto key_failed;
1063
1064   if (!gst_hls_demux_stream_decrypt_start (hls_stream, key->data,
1065           hls_stream->current_iv))
1066     goto decrypt_start_failed;
1067
1068   return TRUE;
1069
1070 key_failed:
1071   {
1072     GST_ELEMENT_ERROR (demux, STREAM, DECRYPT_NOKEY,
1073         ("Couldn't retrieve key for decryption"), (NULL));
1074     GST_WARNING_OBJECT (demux, "Failed to decrypt data");
1075     return FALSE;
1076   }
1077 decrypt_start_failed:
1078   {
1079     GST_ELEMENT_ERROR (demux, STREAM, DECRYPT, ("Failed to start decrypt"),
1080         ("Couldn't set key and IV or plugin was built without crypto library"));
1081     return FALSE;
1082   }
1083 }
1084
1085 static void
1086 gst_hls_demux_start_rendition_streams (GstHLSDemux * hlsdemux)
1087 {
1088   GstAdaptiveDemux *demux = (GstAdaptiveDemux *) hlsdemux;
1089   GList *tmp;
1090
1091   for (tmp = demux->input_period->streams; tmp; tmp = tmp->next) {
1092     GstAdaptiveDemux2Stream *stream = (GstAdaptiveDemux2Stream *) tmp->data;
1093     GstHLSDemuxStream *hls_stream = (GstHLSDemuxStream *) stream;
1094
1095     if (!hls_stream->is_variant
1096         && gst_adaptive_demux2_stream_is_selected (stream))
1097       gst_adaptive_demux2_stream_start (stream);
1098   }
1099 }
1100
1101 static GstHLSParserType
1102 caps_to_parser_type (const GstCaps * caps)
1103 {
1104   const GstStructure *s = gst_caps_get_structure (caps, 0);
1105
1106   if (gst_structure_has_name (s, "video/mpegts"))
1107     return GST_HLS_PARSER_MPEGTS;
1108   if (gst_structure_has_name (s, "application/x-id3"))
1109     return GST_HLS_PARSER_ID3;
1110   if (gst_structure_has_name (s, "application/x-subtitle-vtt"))
1111     return GST_HLS_PARSER_WEBVTT;
1112   if (gst_structure_has_name (s, "video/quicktime"))
1113     return GST_HLS_PARSER_ISOBMFF;
1114
1115   return GST_HLS_PARSER_NONE;
1116 }
1117
1118 /* Identify the nature of data for this stream
1119  *
1120  * Will also setup the appropriate parser (tsreader) if needed
1121  *
1122  * Returns TRUE if we are done with typefinding */
1123 static gboolean
1124 gst_hls_demux_typefind_stream (GstHLSDemux * hlsdemux,
1125     GstAdaptiveDemux2Stream * stream, GstBuffer * buffer, gboolean at_eos,
1126     GstFlowReturn * ret)
1127 {
1128   GstHLSDemuxStream *hls_stream = GST_HLS_DEMUX_STREAM_CAST (stream);   // FIXME: pass HlsStream into function
1129   GstCaps *caps = NULL;
1130   guint buffer_size;
1131   GstTypeFindProbability prob = GST_TYPE_FIND_NONE;
1132   GstMapInfo info;
1133
1134   if (hls_stream->pending_typefind_buffer)
1135     buffer = gst_buffer_append (hls_stream->pending_typefind_buffer, buffer);
1136   hls_stream->pending_typefind_buffer = NULL;
1137
1138   gst_buffer_map (buffer, &info, GST_MAP_READ);
1139   buffer_size = info.size;
1140
1141   /* Typefind could miss if buffer is too small. In this case we
1142    * will retry later */
1143   if (buffer_size >= (2 * 1024) || at_eos) {
1144     caps =
1145         gst_type_find_helper_for_data (GST_OBJECT_CAST (hlsdemux), info.data,
1146         info.size, &prob);
1147   }
1148
1149   if (G_UNLIKELY (!caps)) {
1150     /* Won't need this mapping any more all paths return inside this if() */
1151     gst_buffer_unmap (buffer, &info);
1152
1153     /* Only fail typefinding if we already a good amount of data
1154      * and we still don't know the type */
1155     if (buffer_size > (2 * 1024 * 1024) || at_eos) {
1156       GST_ELEMENT_ERROR (hlsdemux, STREAM, TYPE_NOT_FOUND,
1157           ("Could not determine type of stream"), (NULL));
1158       gst_buffer_unref (buffer);
1159       *ret = GST_FLOW_NOT_NEGOTIATED;
1160     } else {
1161       GST_LOG_OBJECT (stream, "Not enough data to typefind");
1162       hls_stream->pending_typefind_buffer = buffer;
1163       *ret = GST_FLOW_OK;
1164     }
1165     return FALSE;
1166   }
1167
1168   GST_DEBUG_OBJECT (stream,
1169       "Typefind result: %" GST_PTR_FORMAT " prob:%d", caps, prob);
1170
1171   if (hls_stream->parser_type == GST_HLS_PARSER_NONE) {
1172     hls_stream->parser_type = caps_to_parser_type (caps);
1173     if (hls_stream->parser_type == GST_HLS_PARSER_NONE) {
1174       GST_WARNING_OBJECT (stream,
1175           "Unsupported stream type %" GST_PTR_FORMAT, caps);
1176       GST_MEMDUMP_OBJECT (stream, "unknown data", info.data,
1177           MIN (info.size, 128));
1178       *ret = GST_FLOW_ERROR;
1179       return FALSE;
1180     }
1181     if (hls_stream->parser_type == GST_HLS_PARSER_ISOBMFF)
1182       hls_stream->presentation_offset = 0;
1183   }
1184
1185   gst_adaptive_demux2_stream_set_caps (stream, caps);
1186
1187   hls_stream->do_typefind = FALSE;
1188
1189   gst_buffer_unmap (buffer, &info);
1190
1191   /* We are done with typefinding */
1192   *ret = GST_FLOW_OK;
1193   return TRUE;
1194 }
1195
1196 static GstHLSTimeMap *
1197 time_map_in_list (GList * list, gint64 dsn)
1198 {
1199   GList *iter;
1200
1201   for (iter = list; iter; iter = iter->next) {
1202     GstHLSTimeMap *map = iter->data;
1203
1204     if (map->dsn == dsn)
1205       return map;
1206   }
1207
1208   return NULL;
1209 }
1210
1211 GstHLSTimeMap *
1212 gst_hls_find_time_map (GstHLSDemux * demux, gint64 dsn)
1213 {
1214   return time_map_in_list (demux->mappings, dsn);
1215 }
1216
1217 /* Compute the stream time for the given internal time, based on the provided
1218  * time map.
1219  *
1220  * Will handle mpeg-ts wraparound. */
1221 GstClockTimeDiff
1222 gst_hls_internal_to_stream_time (GstHLSTimeMap * map,
1223     GstClockTime internal_time)
1224 {
1225   if (map->internal_time == GST_CLOCK_TIME_NONE)
1226     return GST_CLOCK_STIME_NONE;
1227
1228   /* Handle MPEG-TS Wraparound */
1229   if (internal_time < map->internal_time &&
1230       map->internal_time - internal_time > (MPEG_TS_MAX_PTS / 2))
1231     internal_time += MPEG_TS_MAX_PTS;
1232
1233   return (map->stream_time + internal_time - map->internal_time);
1234 }
1235
1236 /* Handle the internal time discovered on a segment.
1237  *
1238  * This function is called by the individual buffer parsers once they have
1239  * extracted that internal time (which is most of the time based on mpegts time,
1240  * but can also be ISOBMFF pts).
1241  *
1242  * This will update the time map when appropriate.
1243  *
1244  * If a synchronization issue is detected, the appropriate steps will be taken
1245  * and the RESYNC return value will be returned
1246  */
1247 GstHLSParserResult
1248 gst_hlsdemux_handle_internal_time (GstHLSDemux * demux,
1249     GstHLSDemuxStream * hls_stream, GstClockTime internal_time)
1250 {
1251   GstM3U8MediaSegment *current_segment = hls_stream->current_segment;
1252   GstHLSTimeMap *map;
1253   GstClockTimeDiff current_stream_time;
1254   GstClockTimeDiff real_stream_time, difference;
1255
1256   g_return_val_if_fail (current_segment != NULL, GST_HLS_PARSER_RESULT_ERROR);
1257
1258   current_stream_time = current_segment->stream_time;
1259
1260   GST_DEBUG_OBJECT (hls_stream,
1261       "Got internal time %" GST_TIME_FORMAT " for current segment stream time %"
1262       GST_STIME_FORMAT, GST_TIME_ARGS (internal_time),
1263       GST_STIME_ARGS (current_stream_time));
1264
1265   map = gst_hls_find_time_map (demux, current_segment->discont_sequence);
1266
1267   /* Time mappings will always be created upon initial parsing and when advancing */
1268   g_assert (map);
1269
1270   /* Handle the first internal time of a discont sequence. We can only store/use
1271    * those values for variant streams. */
1272   if (!GST_CLOCK_TIME_IS_VALID (map->internal_time)) {
1273     if (!hls_stream->is_variant) {
1274       GST_WARNING_OBJECT (hls_stream,
1275           "Got data from a new discont sequence on a rendition stream, can't validate stream time");
1276       return GST_HLS_PARSER_RESULT_DONE;
1277     }
1278     GST_DEBUG_OBJECT (hls_stream,
1279         "Updating time map dsn:%" G_GINT64_FORMAT " stream_time:%"
1280         GST_STIME_FORMAT " internal_time:%" GST_TIME_FORMAT, map->dsn,
1281         GST_STIME_ARGS (current_stream_time), GST_TIME_ARGS (internal_time));
1282     /* The stream time for a mapping should always be positive ! */
1283     g_assert (current_stream_time >= 0);
1284
1285     if (hls_stream->parser_type == GST_HLS_PARSER_ISOBMFF)
1286       hls_stream->presentation_offset = internal_time;
1287
1288     map->stream_time = current_stream_time;
1289     map->internal_time = internal_time;
1290
1291     gst_hls_demux_start_rendition_streams (demux);
1292     return GST_HLS_PARSER_RESULT_DONE;
1293   }
1294
1295   /* The information in a discont is always valid */
1296   if (current_segment->discont) {
1297     GST_DEBUG_OBJECT (hls_stream,
1298         "DISCONT segment, Updating time map to stream_time:%" GST_STIME_FORMAT
1299         " internal_time:%" GST_TIME_FORMAT, GST_STIME_ARGS (internal_time),
1300         GST_TIME_ARGS (current_stream_time));
1301     map->stream_time = current_stream_time;
1302     map->internal_time = internal_time;
1303     return GST_HLS_PARSER_RESULT_DONE;
1304   }
1305
1306   /* Check if the segment is the expected one */
1307   real_stream_time = gst_hls_internal_to_stream_time (map, internal_time);
1308   difference = current_stream_time - real_stream_time;
1309   GST_DEBUG_OBJECT (hls_stream,
1310       "Segment contains stream time %" GST_STIME_FORMAT
1311       " difference against expected : %" GST_STIME_FORMAT,
1312       GST_STIME_ARGS (real_stream_time), GST_STIME_ARGS (difference));
1313
1314   if (ABS (difference) > 10 * GST_MSECOND) {
1315     /* Update the value */
1316     GST_DEBUG_OBJECT (hls_stream,
1317         "Updating current stream time to %" GST_STIME_FORMAT,
1318         GST_STIME_ARGS (real_stream_time));
1319     current_segment->stream_time = real_stream_time;
1320
1321     gst_hls_media_playlist_recalculate_stream_time (hls_stream->playlist,
1322         hls_stream->current_segment);
1323     gst_hls_media_playlist_dump (hls_stream->playlist);
1324
1325     if (ABS (difference) > (hls_stream->current_segment->duration / 2)) {
1326       GstAdaptiveDemux2Stream *stream = (GstAdaptiveDemux2Stream *) hls_stream;
1327       GstM3U8MediaSegment *actual_segment;
1328
1329       /* We are at the wrong segment, try to figure out the *actual* segment */
1330       GST_DEBUG_OBJECT (hls_stream,
1331           "Trying to seek to the correct segment for %" GST_STIME_FORMAT,
1332           GST_STIME_ARGS (current_stream_time));
1333       actual_segment =
1334           gst_hls_media_playlist_seek (hls_stream->playlist, TRUE,
1335           GST_SEEK_FLAG_SNAP_NEAREST, current_stream_time);
1336
1337       if (actual_segment) {
1338         GST_DEBUG_OBJECT (hls_stream, "Synced to position %" GST_STIME_FORMAT,
1339             GST_STIME_ARGS (actual_segment->stream_time));
1340         gst_m3u8_media_segment_unref (hls_stream->current_segment);
1341         hls_stream->current_segment = actual_segment;
1342         /* Ask parent class to restart this fragment */
1343         return GST_HLS_PARSER_RESULT_RESYNC;
1344       }
1345
1346       GST_WARNING_OBJECT (hls_stream,
1347           "Could not find a replacement stream, carrying on with segment");
1348       stream->discont = TRUE;
1349       stream->fragment.stream_time = real_stream_time;
1350     }
1351   }
1352
1353   return GST_HLS_PARSER_RESULT_DONE;
1354 }
1355
1356 static GstHLSParserResult
1357 gst_hls_demux_handle_buffer_content (GstHLSDemux * demux,
1358     GstHLSDemuxStream * hls_stream, gboolean draining, GstBuffer ** buffer)
1359 {
1360   GstHLSTimeMap *map;
1361   GstAdaptiveDemux2Stream *stream = (GstAdaptiveDemux2Stream *) hls_stream;
1362   GstClockTimeDiff current_stream_time =
1363       hls_stream->current_segment->stream_time;
1364   GstClockTime current_duration = hls_stream->current_segment->duration;
1365   GstHLSParserResult parser_ret;
1366
1367   GST_LOG_OBJECT (stream,
1368       "stream_time:%" GST_STIME_FORMAT " duration:%" GST_TIME_FORMAT
1369       " discont:%d draining:%d header:%d index:%d",
1370       GST_STIME_ARGS (current_stream_time), GST_TIME_ARGS (current_duration),
1371       hls_stream->current_segment->discont, draining,
1372       stream->downloading_header, stream->downloading_index);
1373
1374   /* FIXME : Replace the boolean parser return value (and this function's return
1375    *  value) by an enum which clearly specifies whether:
1376    *
1377    * * The content parsing happened succesfully and it no longer needs to be
1378    *   called for the remainder of this fragment
1379    * * More data is needed in order to parse the data
1380    * * There was a fatal error parsing the contents (ex: invalid/incompatible
1381    *   content)
1382    * * The computed fragment stream time is out of sync
1383    */
1384
1385   g_assert (demux->mappings);
1386   map =
1387       gst_hls_find_time_map (demux,
1388       hls_stream->current_segment->discont_sequence);
1389   if (!map) {
1390     /* For rendition streams, we can't do anything without time mapping */
1391     if (!hls_stream->is_variant) {
1392       GST_DEBUG_OBJECT (stream,
1393           "No available time mapping for dsn:%" G_GINT64_FORMAT
1394           " using estimated stream time",
1395           hls_stream->current_segment->discont_sequence);
1396       goto out_done;
1397     }
1398
1399     /* Variants will be able to fill in the the time mapping, so we can carry on without a time mapping */
1400   } else {
1401     GST_DEBUG_OBJECT (stream,
1402         "Using mapping dsn:%" G_GINT64_FORMAT " stream_time:%" GST_TIME_FORMAT
1403         " internal_time:%" GST_TIME_FORMAT, map->dsn,
1404         GST_TIME_ARGS (map->stream_time), GST_TIME_ARGS (map->internal_time));
1405   }
1406
1407   switch (hls_stream->parser_type) {
1408     case GST_HLS_PARSER_MPEGTS:
1409       parser_ret =
1410           gst_hlsdemux_handle_content_mpegts (demux, hls_stream, draining,
1411           buffer);
1412       break;
1413     case GST_HLS_PARSER_ID3:
1414       parser_ret =
1415           gst_hlsdemux_handle_content_id3 (demux, hls_stream, draining, buffer);
1416       break;
1417     case GST_HLS_PARSER_WEBVTT:
1418     {
1419       /* Furthermore it will handle timeshifting itself */
1420       parser_ret =
1421           gst_hlsdemux_handle_content_webvtt (demux, hls_stream, draining,
1422           buffer);
1423       break;
1424     }
1425     case GST_HLS_PARSER_ISOBMFF:
1426       parser_ret =
1427           gst_hlsdemux_handle_content_isobmff (demux, hls_stream, draining,
1428           buffer);
1429       break;
1430     case GST_HLS_PARSER_NONE:
1431     default:
1432     {
1433       GST_ERROR_OBJECT (stream, "Unknown stream type");
1434       goto out_error;
1435     }
1436   }
1437
1438   if (parser_ret == GST_HLS_PARSER_RESULT_NEED_MORE_DATA) {
1439     if (stream->downloading_index || stream->downloading_header)
1440       goto out_need_more;
1441     /* Else if we're draining, it's an error */
1442     if (draining)
1443       goto out_error;
1444     /* Else we just need more data */
1445     goto out_need_more;
1446   }
1447
1448   if (parser_ret == GST_HLS_PARSER_RESULT_ERROR)
1449     goto out_error;
1450
1451   if (parser_ret == GST_HLS_PARSER_RESULT_RESYNC)
1452     goto out_resync;
1453
1454 out_done:
1455   GST_DEBUG_OBJECT (stream, "Done. Finished parsing");
1456   return GST_HLS_PARSER_RESULT_DONE;
1457
1458 out_error:
1459   GST_DEBUG_OBJECT (stream, "Done. Error while parsing");
1460   return GST_HLS_PARSER_RESULT_ERROR;
1461
1462 out_need_more:
1463   GST_DEBUG_OBJECT (stream, "Done. Need more data");
1464   return GST_HLS_PARSER_RESULT_NEED_MORE_DATA;
1465
1466 out_resync:
1467   GST_DEBUG_OBJECT (stream, "Done. Resync required");
1468   return GST_HLS_PARSER_RESULT_RESYNC;
1469 }
1470
1471 static GstFlowReturn
1472 gst_hls_demux_handle_buffer (GstAdaptiveDemux * demux,
1473     GstAdaptiveDemux2Stream * stream, GstBuffer * buffer, gboolean at_eos)
1474 {
1475   GstHLSDemuxStream *hls_stream = GST_HLS_DEMUX_STREAM_CAST (stream);   // FIXME: pass HlsStream into function
1476   GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (demux);
1477   GstFlowReturn ret = GST_FLOW_OK;
1478
1479   g_assert (hls_stream->current_segment);
1480   GST_DEBUG_OBJECT (stream,
1481       "buffer:%p at_eos:%d do_typefind:%d uri:%s", buffer, at_eos,
1482       hls_stream->do_typefind, hls_stream->current_segment->uri);
1483
1484   if (buffer == NULL)
1485     goto out;
1486
1487   /* If we need to do typefind and we're not done with it (or we errored), return */
1488   if (G_UNLIKELY (hls_stream->do_typefind) &&
1489       !gst_hls_demux_typefind_stream (hlsdemux, stream, buffer, at_eos, &ret))
1490     goto out;
1491   g_assert (hls_stream->pending_typefind_buffer == NULL);
1492
1493   if (hls_stream->process_buffer_content) {
1494     GstHLSParserResult parse_ret;
1495
1496     if (hls_stream->pending_segment_data) {
1497       buffer = gst_buffer_append (hls_stream->pending_segment_data, buffer);
1498       hls_stream->pending_segment_data = NULL;
1499     }
1500
1501     /* Try to get the timing information */
1502     parse_ret =
1503         gst_hls_demux_handle_buffer_content (hlsdemux, hls_stream, at_eos,
1504         &buffer);
1505
1506     switch (parse_ret) {
1507       case GST_HLS_PARSER_RESULT_NEED_MORE_DATA:
1508         /* If we don't have enough, store and return */
1509         hls_stream->pending_segment_data = buffer;
1510         hls_stream->pending_data_is_header =
1511             (stream->downloading_header == TRUE);
1512         if (hls_stream->pending_data_is_header)
1513           stream->send_segment = TRUE;
1514         goto out;
1515       case GST_HLS_PARSER_RESULT_ERROR:
1516         /* Error, drop buffer and return */
1517         gst_buffer_unref (buffer);
1518         ret = GST_FLOW_ERROR;
1519         goto out;
1520       case GST_HLS_PARSER_RESULT_RESYNC:
1521         /* Resync, drop buffer and return */
1522         gst_buffer_unref (buffer);
1523         ret = GST_ADAPTIVE_DEMUX_FLOW_RESTART_FRAGMENT;
1524         goto out;
1525       case GST_HLS_PARSER_RESULT_DONE:
1526         /* Done parsing, carry on */
1527         hls_stream->process_buffer_content = FALSE;
1528         break;
1529     }
1530   }
1531
1532   if (!buffer)
1533     goto out;
1534
1535   buffer = gst_buffer_make_writable (buffer);
1536
1537   GST_BUFFER_OFFSET (buffer) = hls_stream->current_offset;
1538   hls_stream->current_offset += gst_buffer_get_size (buffer);
1539   GST_BUFFER_OFFSET_END (buffer) = hls_stream->current_offset;
1540
1541   GST_DEBUG_OBJECT (stream, "We have a buffer, pushing: %" GST_PTR_FORMAT,
1542       buffer);
1543
1544   ret = gst_adaptive_demux2_stream_push_buffer (stream, buffer);
1545
1546 out:
1547   GST_DEBUG_OBJECT (stream, "Returning %s", gst_flow_get_name (ret));
1548   return ret;
1549 }
1550
1551 static GstFlowReturn
1552 gst_hls_demux_finish_fragment (GstAdaptiveDemux * demux,
1553     GstAdaptiveDemux2Stream * stream)
1554 {
1555   GstHLSDemuxStream *hls_stream = GST_HLS_DEMUX_STREAM_CAST (stream);   // FIXME: pass HlsStream into function
1556   GstFlowReturn ret = GST_FLOW_OK;
1557
1558   GST_DEBUG_OBJECT (stream, "Finishing fragment uri:%s",
1559       hls_stream->current_segment->uri);
1560
1561   /* Drain all pending data */
1562   if (hls_stream->current_key)
1563     gst_hls_demux_stream_decrypt_end (hls_stream);
1564
1565   if (stream->last_ret == GST_FLOW_OK) {
1566     if (hls_stream->pending_decrypted_buffer) {
1567       if (hls_stream->current_key) {
1568         GstMapInfo info;
1569         gssize unpadded_size;
1570
1571         /* Handle pkcs7 unpadding here */
1572         gst_buffer_map (hls_stream->pending_decrypted_buffer, &info,
1573             GST_MAP_READ);
1574         unpadded_size = info.size - info.data[info.size - 1];
1575         gst_buffer_unmap (hls_stream->pending_decrypted_buffer, &info);
1576
1577         gst_buffer_resize (hls_stream->pending_decrypted_buffer, 0,
1578             unpadded_size);
1579       }
1580
1581       ret =
1582           gst_hls_demux_handle_buffer (demux, stream,
1583           hls_stream->pending_decrypted_buffer, TRUE);
1584       hls_stream->pending_decrypted_buffer = NULL;
1585     }
1586
1587     if (ret == GST_FLOW_OK || ret == GST_FLOW_NOT_LINKED) {
1588       if (G_UNLIKELY (hls_stream->pending_typefind_buffer)) {
1589         GstBuffer *buf = hls_stream->pending_typefind_buffer;
1590         hls_stream->pending_typefind_buffer = NULL;
1591
1592         gst_hls_demux_handle_buffer (demux, stream, buf, TRUE);
1593       }
1594
1595       if (hls_stream->pending_segment_data) {
1596         GstBuffer *buf = hls_stream->pending_segment_data;
1597         hls_stream->pending_segment_data = NULL;
1598
1599         ret = gst_hls_demux_handle_buffer (demux, stream, buf, TRUE);
1600       }
1601     }
1602   }
1603
1604   gst_hls_demux_stream_clear_pending_data (hls_stream, FALSE);
1605
1606   if (G_UNLIKELY (stream->downloading_header || stream->downloading_index))
1607     return GST_FLOW_OK;
1608
1609   if (ret == GST_FLOW_OK || ret == GST_FLOW_NOT_LINKED) {
1610     /* We can update the stream current position with a more accurate value
1611      * before advancing. Note that we don't have any period so we can set the
1612      * stream_time as-is on the stream current position */
1613     stream->current_position = hls_stream->current_segment->stream_time;
1614     return gst_adaptive_demux2_stream_advance_fragment (demux, stream,
1615         hls_stream->current_segment->duration);
1616   }
1617   return ret;
1618 }
1619
1620 static GstFlowReturn
1621 gst_hls_demux_data_received (GstAdaptiveDemux * demux,
1622     GstAdaptiveDemux2Stream * stream, GstBuffer * buffer)
1623 {
1624   GstHLSDemuxStream *hls_stream = GST_HLS_DEMUX_STREAM_CAST (stream);
1625   GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (demux);
1626
1627   if (hls_stream->current_offset == -1)
1628     hls_stream->current_offset = 0;
1629
1630   /* Is it encrypted? */
1631   if (hls_stream->current_key) {
1632     GError *err = NULL;
1633     gsize size;
1634     GstBuffer *decrypted_buffer;
1635     GstBuffer *tmp_buffer;
1636
1637     if (hls_stream->pending_encrypted_data == NULL)
1638       hls_stream->pending_encrypted_data = gst_adapter_new ();
1639
1640     gst_adapter_push (hls_stream->pending_encrypted_data, buffer);
1641     size = gst_adapter_available (hls_stream->pending_encrypted_data);
1642
1643     /* must be a multiple of 16 */
1644     size &= (~0xF);
1645
1646     if (size == 0) {
1647       return GST_FLOW_OK;
1648     }
1649
1650     buffer = gst_adapter_take_buffer (hls_stream->pending_encrypted_data, size);
1651     decrypted_buffer =
1652         gst_hls_demux_decrypt_fragment (hlsdemux, hls_stream, buffer, &err);
1653     if (err) {
1654       GST_ELEMENT_ERROR (demux, STREAM, DECODE, ("Failed to decrypt buffer"),
1655           ("decryption failed %s", err->message));
1656       g_error_free (err);
1657       return GST_FLOW_ERROR;
1658     }
1659
1660     tmp_buffer = hls_stream->pending_decrypted_buffer;
1661     hls_stream->pending_decrypted_buffer = decrypted_buffer;
1662     buffer = tmp_buffer;
1663     if (!buffer)
1664       return GST_FLOW_OK;
1665   }
1666
1667   return gst_hls_demux_handle_buffer (demux, stream, buffer, FALSE);
1668 }
1669
1670 static void
1671 gst_hls_demux_stream_finalize (GObject * object)
1672 {
1673   GstAdaptiveDemux2Stream *stream = (GstAdaptiveDemux2Stream *) object;
1674   GstHLSDemuxStream *hls_stream = GST_HLS_DEMUX_STREAM_CAST (object);
1675   GstHLSDemux *hlsdemux = (GstHLSDemux *) stream->demux;
1676
1677   if (hls_stream == hlsdemux->main_stream)
1678     hlsdemux->main_stream = NULL;
1679
1680   g_free (hls_stream->lang);
1681   g_free (hls_stream->name);
1682
1683   if (hls_stream->playlist) {
1684     gst_hls_media_playlist_unref (hls_stream->playlist);
1685     hls_stream->playlist = NULL;
1686   }
1687
1688   if (hls_stream->pending_encrypted_data)
1689     g_object_unref (hls_stream->pending_encrypted_data);
1690
1691   gst_buffer_replace (&hls_stream->pending_decrypted_buffer, NULL);
1692   gst_buffer_replace (&hls_stream->pending_typefind_buffer, NULL);
1693   gst_buffer_replace (&hls_stream->pending_segment_data, NULL);
1694
1695   if (hls_stream->moov)
1696     gst_isoff_moov_box_free (hls_stream->moov);
1697
1698   if (hls_stream->current_key) {
1699     g_free (hls_stream->current_key);
1700     hls_stream->current_key = NULL;
1701   }
1702   if (hls_stream->current_iv) {
1703     g_free (hls_stream->current_iv);
1704     hls_stream->current_iv = NULL;
1705   }
1706   if (hls_stream->current_rendition) {
1707     gst_hls_rendition_stream_unref (hls_stream->current_rendition);
1708     hls_stream->current_rendition = NULL;
1709   }
1710   if (hls_stream->pending_rendition) {
1711     gst_hls_rendition_stream_unref (hls_stream->pending_rendition);
1712     hls_stream->pending_rendition = NULL;
1713   }
1714
1715   if (hls_stream->current_segment) {
1716     gst_m3u8_media_segment_unref (hls_stream->current_segment);
1717     hls_stream->current_segment = NULL;
1718   }
1719   gst_hls_demux_stream_decrypt_end (hls_stream);
1720
1721   G_OBJECT_CLASS (stream_parent_class)->finalize (object);
1722 }
1723
1724 static gboolean
1725 gst_hls_demux_stream_has_next_fragment (GstAdaptiveDemux2Stream * stream)
1726 {
1727   GstHLSDemuxStream *hls_stream = (GstHLSDemuxStream *) stream;
1728
1729   GST_DEBUG_OBJECT (stream, "has next ?");
1730
1731   return gst_hls_media_playlist_has_next_fragment (hls_stream->playlist,
1732       hls_stream->current_segment, stream->demux->segment.rate > 0);
1733 }
1734
1735 static GstFlowReturn
1736 gst_hls_demux_advance_fragment (GstAdaptiveDemux2Stream * stream)
1737 {
1738   GstHLSDemuxStream *hlsdemux_stream = GST_HLS_DEMUX_STREAM_CAST (stream);
1739   GstHLSDemux *hlsdemux = (GstHLSDemux *) stream->demux;
1740   GstM3U8MediaSegment *new_segment = NULL;
1741
1742   GST_DEBUG_OBJECT (stream,
1743       "Current segment sn:%" G_GINT64_FORMAT " stream_time:%" GST_STIME_FORMAT
1744       " uri:%s", hlsdemux_stream->current_segment->sequence,
1745       GST_STIME_ARGS (hlsdemux_stream->current_segment->stream_time),
1746       hlsdemux_stream->current_segment->uri);
1747
1748   new_segment =
1749       gst_hls_media_playlist_advance_fragment (hlsdemux_stream->playlist,
1750       hlsdemux_stream->current_segment, stream->demux->segment.rate > 0);
1751   if (new_segment) {
1752     hlsdemux_stream->reset_pts = FALSE;
1753     if (new_segment->discont_sequence !=
1754         hlsdemux_stream->current_segment->discont_sequence)
1755       gst_hls_demux_add_time_mapping (hlsdemux, new_segment->discont_sequence,
1756           new_segment->stream_time, new_segment->datetime);
1757     gst_m3u8_media_segment_unref (hlsdemux_stream->current_segment);
1758     hlsdemux_stream->current_segment = new_segment;
1759     GST_DEBUG_OBJECT (stream,
1760         "Advanced to segment sn:%" G_GINT64_FORMAT " stream_time:%"
1761         GST_STIME_FORMAT " uri:%s", hlsdemux_stream->current_segment->sequence,
1762         GST_STIME_ARGS (hlsdemux_stream->current_segment->stream_time),
1763         hlsdemux_stream->current_segment->uri);
1764     return GST_FLOW_OK;
1765   }
1766
1767   GST_LOG_OBJECT (stream, "Could not advance to next fragment");
1768   if (GST_HLS_MEDIA_PLAYLIST_IS_LIVE (hlsdemux_stream->playlist)) {
1769     gst_m3u8_media_segment_unref (hlsdemux_stream->current_segment);
1770     hlsdemux_stream->current_segment = NULL;
1771     return GST_FLOW_OK;
1772   }
1773
1774   return GST_FLOW_EOS;
1775 }
1776
1777 static GstHLSMediaPlaylist *
1778 download_media_playlist (GstHLSDemux * demux, gchar * uri, GError ** err,
1779     GstHLSMediaPlaylist * current)
1780 {
1781   GstAdaptiveDemux *adaptive_demux;
1782   const gchar *main_uri;
1783   DownloadRequest *download;
1784   GstBuffer *buf;
1785   gchar *playlist_data;
1786   GstHLSMediaPlaylist *playlist = NULL;
1787   gchar *base_uri;
1788   gboolean playlist_uri_change = FALSE;
1789
1790   adaptive_demux = GST_ADAPTIVE_DEMUX (demux);
1791   main_uri = gst_adaptive_demux_get_manifest_ref_uri (adaptive_demux);
1792
1793   /* If there's no previous playlist, or the URI changed this
1794    * is not a refresh/update but a switch to a new playlist */
1795   playlist_uri_change = (current == NULL || g_strcmp0 (uri, current->uri) != 0);
1796
1797   if (!playlist_uri_change) {
1798     GST_LOG_OBJECT (demux, "Updating the playlist");
1799   }
1800
1801   download =
1802       downloadhelper_fetch_uri (adaptive_demux->download_helper,
1803       uri, main_uri, DOWNLOAD_FLAG_COMPRESS | DOWNLOAD_FLAG_FORCE_REFRESH, err);
1804
1805   if (download == NULL)
1806     return NULL;
1807
1808   /* Set the base URI of the playlist to the redirect target if any */
1809   if (download->redirect_permanent && download->redirect_uri) {
1810     uri = g_strdup (download->redirect_uri);
1811     base_uri = NULL;
1812   } else {
1813     uri = g_strdup (download->uri);
1814     base_uri = g_strdup (download->redirect_uri);
1815   }
1816
1817   if (download->state == DOWNLOAD_REQUEST_STATE_ERROR) {
1818     GST_WARNING_OBJECT (demux,
1819         "Couldn't get the playlist, got HTTP status code %d",
1820         download->status_code);
1821     download_request_unref (download);
1822     if (err)
1823       g_set_error (err, GST_STREAM_ERROR, GST_STREAM_ERROR_WRONG_TYPE,
1824           "Couldn't download the playlist");
1825     goto out;
1826   }
1827   buf = download_request_take_buffer (download);
1828   download_request_unref (download);
1829
1830   /* there should be a buf if there wasn't an error (handled above) */
1831   g_assert (buf);
1832
1833   playlist_data = gst_hls_buf_to_utf8_text (buf);
1834   gst_buffer_unref (buf);
1835
1836   if (playlist_data == NULL) {
1837     GST_WARNING_OBJECT (demux, "Couldn't validate playlist encoding");
1838     if (err)
1839       g_set_error (err, GST_STREAM_ERROR, GST_STREAM_ERROR_WRONG_TYPE,
1840           "Couldn't validate playlist encoding");
1841     goto out;
1842   }
1843
1844   if (!playlist_uri_change && current
1845       && gst_hls_media_playlist_has_same_data (current, playlist_data)) {
1846     GST_DEBUG_OBJECT (demux, "Same playlist data");
1847     playlist = gst_hls_media_playlist_ref (current);
1848     playlist->reloaded = TRUE;
1849     g_free (playlist_data);
1850   } else {
1851     playlist = gst_hls_media_playlist_parse (playlist_data, uri, base_uri);
1852     if (!playlist) {
1853       GST_WARNING_OBJECT (demux, "Couldn't parse playlist");
1854       if (err)
1855         g_set_error (err, GST_STREAM_ERROR, GST_STREAM_ERROR_FAILED,
1856             "Couldn't parse playlist");
1857     }
1858   }
1859
1860 out:
1861   g_free (uri);
1862   g_free (base_uri);
1863
1864   return playlist;
1865 }
1866
1867 static GstHLSTimeMap *
1868 gst_hls_time_map_new (void)
1869 {
1870   GstHLSTimeMap *map = g_new0 (GstHLSTimeMap, 1);
1871
1872   map->stream_time = GST_CLOCK_TIME_NONE;
1873   map->internal_time = GST_CLOCK_TIME_NONE;
1874
1875   return map;
1876 }
1877
1878 static void
1879 gst_hls_demux_add_time_mapping (GstHLSDemux * demux, gint64 dsn,
1880     GstClockTimeDiff stream_time, GDateTime * pdt)
1881 {
1882 #ifndef GST_DISABLE_GST_DEBUG
1883   gchar *datestring = NULL;
1884 #endif
1885   GstHLSTimeMap *map;
1886   GList *tmp;
1887
1888   g_assert (stream_time >= 0);
1889
1890   /* Check if we don't already have a mapping for the given dsn */
1891   for (tmp = demux->mappings; tmp; tmp = tmp->next) {
1892     GstHLSTimeMap *map = tmp->data;
1893
1894     if (map->dsn == dsn) {
1895 #ifndef GST_DISABLE_GST_DEBUG
1896       if (map->pdt)
1897         datestring = g_date_time_format_iso8601 (map->pdt);
1898       GST_DEBUG_OBJECT (demux,
1899           "Already have mapping, dsn:%" G_GINT64_FORMAT " stream_time:%"
1900           GST_TIME_FORMAT " internal_time:%" GST_TIME_FORMAT " pdt:%s",
1901           map->dsn, GST_TIME_ARGS (map->stream_time),
1902           GST_TIME_ARGS (map->internal_time), datestring);
1903       g_free (datestring);
1904 #endif
1905       return;
1906     }
1907   }
1908
1909 #ifndef GST_DISABLE_GST_DEBUG
1910   if (pdt)
1911     datestring = g_date_time_format_iso8601 (pdt);
1912   GST_DEBUG_OBJECT (demux,
1913       "New mapping, dsn:%" G_GINT64_FORMAT " stream_time:%" GST_TIME_FORMAT
1914       " pdt:%s", dsn, GST_TIME_ARGS (stream_time), datestring);
1915   g_free (datestring);
1916 #endif
1917
1918   map = gst_hls_time_map_new ();
1919   map->dsn = dsn;
1920   map->stream_time = stream_time;
1921   if (pdt)
1922     map->pdt = g_date_time_ref (pdt);
1923
1924   demux->mappings = g_list_append (demux->mappings, map);
1925 }
1926
1927 /* Remove any time mapping which isn't currently used by any stream playlist */
1928 static void
1929 gst_hls_prune_time_mappings (GstHLSDemux * hlsdemux)
1930 {
1931   GstAdaptiveDemux *demux = (GstAdaptiveDemux *) hlsdemux;
1932   GList *active = NULL;
1933   GList *iterstream;
1934
1935   for (iterstream = demux->input_period->streams; iterstream;
1936       iterstream = iterstream->next) {
1937     GstAdaptiveDemux2Stream *stream = iterstream->data;
1938     GstHLSDemuxStream *hls_stream = (GstHLSDemuxStream *) stream;
1939     gint64 dsn = G_MAXINT64;
1940     guint idx, len;
1941
1942     if (!hls_stream->playlist)
1943       continue;
1944     len = hls_stream->playlist->segments->len;
1945     for (idx = 0; idx < len; idx++) {
1946       GstM3U8MediaSegment *segment =
1947           g_ptr_array_index (hls_stream->playlist->segments, idx);
1948
1949       if (dsn == G_MAXINT64 || segment->discont_sequence != dsn) {
1950         dsn = segment->discont_sequence;
1951         if (!time_map_in_list (active, dsn)) {
1952           GstHLSTimeMap *map = gst_hls_find_time_map (hlsdemux, dsn);
1953           if (map) {
1954             GST_DEBUG_OBJECT (demux,
1955                 "Keeping active time map dsn:%" G_GINT64_FORMAT, map->dsn);
1956             /* Move active dsn to active list */
1957             hlsdemux->mappings = g_list_remove (hlsdemux->mappings, map);
1958             active = g_list_append (active, map);
1959           }
1960         }
1961       }
1962     }
1963   }
1964
1965   g_list_free_full (hlsdemux->mappings, g_free);
1966   hlsdemux->mappings = active;
1967 }
1968
1969 /* Go over the DSN from the playlist and add any missing time mapping */
1970 static void
1971 gst_hls_update_time_mappings (GstHLSDemux * demux,
1972     GstHLSMediaPlaylist * playlist)
1973 {
1974   guint idx, len = playlist->segments->len;
1975   gint64 dsn = G_MAXINT64;
1976
1977   for (idx = 0; idx < len; idx++) {
1978     GstM3U8MediaSegment *segment = g_ptr_array_index (playlist->segments, idx);
1979
1980     if (dsn == G_MAXINT64 || segment->discont_sequence != dsn) {
1981       dsn = segment->discont_sequence;
1982       if (!gst_hls_find_time_map (demux, segment->discont_sequence))
1983         gst_hls_demux_add_time_mapping (demux, segment->discont_sequence,
1984             segment->stream_time, segment->datetime);
1985     }
1986   }
1987 }
1988
1989 static void
1990 setup_initial_playlist (GstHLSDemux * demux, GstHLSMediaPlaylist * playlist)
1991 {
1992   guint idx, len = playlist->segments->len;
1993   GstM3U8MediaSegment *segment;
1994   GstClockTimeDiff pos = 0;
1995
1996   GST_DEBUG_OBJECT (demux,
1997       "Setting up initial variant segment and time mapping");
1998
1999   /* This is the initial variant playlist. We will use it to base all our timing
2000    * from. */
2001
2002   for (idx = 0; idx < len; idx++) {
2003     segment = g_ptr_array_index (playlist->segments, idx);
2004
2005     segment->stream_time = pos;
2006     pos += segment->duration;
2007   }
2008 }
2009
2010 /* Reset hlsdemux in case of live synchronization loss (i.e. when a media
2011  * playlist update doesn't match at all with the previous one) */
2012 static void
2013 gst_hls_demux_reset_for_lost_sync (GstHLSDemux * hlsdemux)
2014 {
2015   GstAdaptiveDemux *demux = (GstAdaptiveDemux *) hlsdemux;
2016   GList *iter;
2017
2018   GST_DEBUG_OBJECT (hlsdemux, "Resetting for lost sync");
2019
2020   for (iter = demux->input_period->streams; iter; iter = iter->next) {
2021     GstHLSDemuxStream *hls_stream = iter->data;
2022     GstAdaptiveDemux2Stream *stream = (GstAdaptiveDemux2Stream *) hls_stream;
2023
2024     if (hls_stream->current_segment)
2025       gst_m3u8_media_segment_unref (hls_stream->current_segment);
2026     hls_stream->current_segment = NULL;
2027
2028     if (hls_stream->is_variant) {
2029       GstHLSTimeMap *map;
2030       /* Resynchronize the variant stream */
2031       g_assert (stream->current_position != GST_CLOCK_STIME_NONE);
2032       hls_stream->current_segment =
2033           gst_hls_media_playlist_get_starting_segment (hls_stream->playlist);
2034       hls_stream->current_segment->stream_time = stream->current_position;
2035       gst_hls_media_playlist_recalculate_stream_time (hls_stream->playlist,
2036           hls_stream->current_segment);
2037       GST_DEBUG_OBJECT (stream,
2038           "Resynced variant playlist to %" GST_STIME_FORMAT,
2039           GST_STIME_ARGS (stream->current_position));
2040       map =
2041           gst_hls_find_time_map (hlsdemux,
2042           hls_stream->current_segment->discont_sequence);
2043       if (map)
2044         map->internal_time = GST_CLOCK_TIME_NONE;
2045       gst_hls_update_time_mappings (hlsdemux, hls_stream->playlist);
2046       gst_hls_media_playlist_dump (hls_stream->playlist);
2047     } else {
2048       /* Force playlist update for the rendition streams, it will resync to the
2049        * variant stream on the next round */
2050       if (hls_stream->playlist)
2051         gst_hls_media_playlist_unref (hls_stream->playlist);
2052       hls_stream->playlist = NULL;
2053       hls_stream->playlist_fetched = FALSE;
2054     }
2055   }
2056 }
2057
2058 static GstFlowReturn
2059 gst_hls_demux_stream_update_media_playlist (GstHLSDemux * demux,
2060     GstHLSDemuxStream * stream, gchar ** uri, GError ** err)
2061 {
2062   GstHLSMediaPlaylist *new_playlist;
2063
2064   GST_DEBUG_OBJECT (stream, "Updating %s", *uri);
2065
2066   new_playlist = download_media_playlist (demux, *uri, err, stream->playlist);
2067   if (new_playlist == NULL) {
2068     GST_WARNING_OBJECT (stream, "Could not get playlist '%s'", *uri);
2069     return GST_FLOW_ERROR;
2070   }
2071
2072   /* Check if a redirect happened */
2073   if (g_strcmp0 (*uri, new_playlist->uri)) {
2074     GST_DEBUG_OBJECT (stream, "Playlist URI update : '%s'  =>  '%s'", *uri,
2075         new_playlist->uri);
2076     g_free (*uri);
2077     *uri = g_strdup (new_playlist->uri);
2078   }
2079
2080   /* Synchronize playlist with previous one. If we can't update the playlist
2081    * timing and inform the base class that we lost sync */
2082   if (stream->playlist
2083       && !gst_hls_media_playlist_sync_to_playlist (new_playlist,
2084           stream->playlist)) {
2085     /* Failure to synchronize with the previous media playlist is only fatal for
2086      * variant streams. */
2087     if (stream->is_variant) {
2088       GST_DEBUG_OBJECT (stream,
2089           "Could not synchronize new variant playlist with previous one !");
2090       goto lost_sync;
2091     }
2092
2093     /* For rendition streams, we can attempt synchronization against the
2094      * variant playlist which is constantly updated */
2095     if (demux->main_stream->playlist
2096         && !gst_hls_media_playlist_sync_to_playlist (new_playlist,
2097             demux->main_stream->playlist)) {
2098       GST_DEBUG_OBJECT (stream,
2099           "Could not do fallback synchronization of rendition stream to variant stream");
2100       goto lost_sync;
2101     }
2102   } else if (!stream->is_variant && demux->main_stream->playlist) {
2103     /* For initial rendition media playlist, attempt to synchronize the playlist
2104      * against the variant stream. This is non-fatal if it fails. */
2105     GST_DEBUG_OBJECT (stream,
2106         "Attempting to synchronize initial rendition stream with variant stream");
2107     gst_hls_media_playlist_sync_to_playlist (new_playlist,
2108         demux->main_stream->playlist);
2109   }
2110
2111   if (stream->current_segment) {
2112     GstM3U8MediaSegment *new_segment;
2113     GST_DEBUG_OBJECT (stream,
2114         "Current segment sn:%" G_GINT64_FORMAT " stream_time:%" GST_STIME_FORMAT
2115         " uri:%s", stream->current_segment->sequence,
2116         GST_STIME_ARGS (stream->current_segment->stream_time),
2117         stream->current_segment->uri);
2118
2119     /* Use best-effort techniques to find the correponding current media segment
2120      * in the new playlist. This might be off in some cases, but it doesn't matter
2121      * since we will be checking the embedded timestamp later */
2122     new_segment =
2123         gst_hls_media_playlist_sync_to_segment (new_playlist,
2124         stream->current_segment);
2125     if (new_segment) {
2126       if (new_segment->discont_sequence !=
2127           stream->current_segment->discont_sequence)
2128         gst_hls_demux_add_time_mapping (demux, new_segment->discont_sequence,
2129             new_segment->stream_time, new_segment->datetime);
2130       /* This can happen in case of misaligned variants/renditions. Only warn about it */
2131       if (new_segment->stream_time != stream->current_segment->stream_time)
2132         GST_WARNING_OBJECT (stream,
2133             "Returned segment stream time %" GST_STIME_FORMAT
2134             " differs from current stream time %" GST_STIME_FORMAT,
2135             GST_STIME_ARGS (new_segment->stream_time),
2136             GST_STIME_ARGS (stream->current_segment->stream_time));
2137     } else {
2138       /* Not finding a matching segment only happens in live (otherwise we would
2139        * have found a match by stream time) when we are at the live edge. This is normal*/
2140       GST_DEBUG_OBJECT (stream, "Could not find a matching segment");
2141     }
2142     gst_m3u8_media_segment_unref (stream->current_segment);
2143     stream->current_segment = new_segment;
2144   } else {
2145     GST_DEBUG_OBJECT (stream, "No current segment");
2146   }
2147
2148   if (stream->playlist) {
2149     gst_hls_media_playlist_unref (stream->playlist);
2150     stream->playlist = new_playlist;
2151   } else {
2152     GST_DEBUG_OBJECT (stream, "Setting up initial playlist");
2153     stream->playlist = new_playlist;
2154     setup_initial_playlist (demux, new_playlist);
2155   }
2156
2157   if (stream->is_variant) {
2158     /* Update time mappings. We only use the variant stream for collecting
2159      * mappings since it is the reference on which rendition stream timing will
2160      * be based. */
2161     gst_hls_update_time_mappings (demux, stream->playlist);
2162   }
2163   gst_hls_media_playlist_dump (stream->playlist);
2164
2165   if (stream->current_segment) {
2166     GST_DEBUG_OBJECT (stream,
2167         "After update, current segment now sn:%" G_GINT64_FORMAT
2168         " stream_time:%" GST_STIME_FORMAT " uri:%s",
2169         stream->current_segment->sequence,
2170         GST_STIME_ARGS (stream->current_segment->stream_time),
2171         stream->current_segment->uri);
2172   } else {
2173     GST_DEBUG_OBJECT (stream, "No current segment selected");
2174   }
2175
2176   GST_DEBUG_OBJECT (stream, "done");
2177
2178   return GST_FLOW_OK;
2179
2180   /* ERRORS */
2181 lost_sync:
2182   {
2183     /* Set new playlist, lost sync handler will know what to do with it */
2184     if (stream->playlist)
2185       gst_hls_media_playlist_unref (stream->playlist);
2186     stream->playlist = new_playlist;
2187
2188     gst_hls_demux_reset_for_lost_sync (demux);
2189
2190     return GST_ADAPTIVE_DEMUX_FLOW_LOST_SYNC;
2191   }
2192 }
2193
2194 static GstFlowReturn
2195 gst_hls_demux_stream_update_rendition_playlist (GstHLSDemux * demux,
2196     GstHLSDemuxStream * stream)
2197 {
2198   GstFlowReturn ret = GST_FLOW_OK;
2199   GstHLSRenditionStream *target_rendition =
2200       stream->pending_rendition ? stream->pending_rendition : stream->
2201       current_rendition;
2202
2203   ret = gst_hls_demux_stream_update_media_playlist (demux, stream,
2204       &target_rendition->uri, NULL);
2205   if (ret != GST_FLOW_OK)
2206     return ret;
2207
2208   if (stream->pending_rendition) {
2209     gst_hls_rendition_stream_unref (stream->current_rendition);
2210     /* Stealing ref */
2211     stream->current_rendition = stream->pending_rendition;
2212     stream->pending_rendition = NULL;
2213   }
2214
2215   stream->playlist_fetched = TRUE;
2216
2217   return ret;
2218 }
2219
2220 static GstFlowReturn
2221 gst_hls_demux_stream_update_variant_playlist (GstHLSDemux * demux,
2222     GstHLSDemuxStream * stream, GError ** err)
2223 {
2224   GstFlowReturn ret = GST_FLOW_OK;
2225   GstHLSVariantStream *target_variant =
2226       demux->pending_variant ? demux->pending_variant : demux->current_variant;
2227
2228   ret = gst_hls_demux_stream_update_media_playlist (demux, stream,
2229       &target_variant->uri, err);
2230   if (ret != GST_FLOW_OK)
2231     return ret;
2232
2233   if (demux->pending_variant) {
2234     gst_hls_variant_stream_unref (demux->current_variant);
2235     /* Stealing ref */
2236     demux->current_variant = demux->pending_variant;
2237     demux->pending_variant = NULL;
2238   }
2239
2240   stream->playlist_fetched = TRUE;
2241
2242   return ret;
2243 }
2244
2245 static GstFlowReturn
2246 gst_hls_demux_update_fragment_info (GstAdaptiveDemux2Stream * stream)
2247 {
2248   GstFlowReturn ret = GST_FLOW_OK;
2249   GstHLSDemuxStream *hlsdemux_stream = GST_HLS_DEMUX_STREAM_CAST (stream);
2250   GstAdaptiveDemux *demux = stream->demux;
2251   GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (demux);
2252   GstM3U8MediaSegment *file;
2253   gboolean discont;
2254
2255   /* If the rendition playlist needs to be updated, do it now */
2256   if (!hlsdemux_stream->is_variant && !hlsdemux_stream->playlist_fetched) {
2257     ret = gst_hls_demux_stream_update_rendition_playlist (hlsdemux,
2258         hlsdemux_stream);
2259     if (ret != GST_FLOW_OK)
2260       return ret;
2261   }
2262
2263   GST_DEBUG_OBJECT (stream,
2264       "Updating fragment information, current_position:%" GST_TIME_FORMAT,
2265       GST_TIME_ARGS (stream->current_position));
2266
2267   /* Find the current segment if we don't already have it */
2268   if (hlsdemux_stream->current_segment == NULL) {
2269     GST_LOG_OBJECT (stream, "No current segment");
2270     if (stream->current_position == GST_CLOCK_TIME_NONE) {
2271       GST_DEBUG_OBJECT (stream, "Setting up initial segment");
2272       hlsdemux_stream->current_segment =
2273           gst_hls_media_playlist_get_starting_segment
2274           (hlsdemux_stream->playlist);
2275     } else {
2276       if (gst_hls_media_playlist_has_lost_sync (hlsdemux_stream->playlist,
2277               stream->current_position)) {
2278         GST_WARNING_OBJECT (stream, "Lost SYNC !");
2279         return GST_ADAPTIVE_DEMUX_FLOW_LOST_SYNC;
2280       }
2281       GST_DEBUG_OBJECT (stream,
2282           "Looking up segment for position %" GST_TIME_FORMAT,
2283           GST_TIME_ARGS (stream->current_position));
2284       hlsdemux_stream->current_segment =
2285           gst_hls_media_playlist_seek (hlsdemux_stream->playlist, TRUE,
2286           GST_SEEK_FLAG_SNAP_NEAREST, stream->current_position);
2287
2288       if (hlsdemux_stream->current_segment == NULL) {
2289         GST_INFO_OBJECT (stream, "At the end of the current media playlist");
2290         return GST_FLOW_EOS;
2291       }
2292
2293       /* Update time mapping. If it already exists it will be ignored */
2294       gst_hls_demux_add_time_mapping (hlsdemux,
2295           hlsdemux_stream->current_segment->discont_sequence,
2296           hlsdemux_stream->current_segment->stream_time,
2297           hlsdemux_stream->current_segment->datetime);
2298     }
2299   }
2300
2301   file = hlsdemux_stream->current_segment;
2302
2303   GST_DEBUG_OBJECT (stream, "Current segment stream_time %" GST_STIME_FORMAT,
2304       GST_STIME_ARGS (file->stream_time));
2305
2306   discont = file->discont || stream->discont;
2307
2308   if (GST_ADAPTIVE_DEMUX2_STREAM_NEED_HEADER (stream) && file->init_file) {
2309     GstM3U8InitFile *header_file = file->init_file;
2310     g_free (stream->fragment.header_uri);
2311     stream->fragment.header_uri = g_strdup (header_file->uri);
2312     stream->fragment.header_range_start = header_file->offset;
2313     if (header_file->size != -1) {
2314       stream->fragment.header_range_end =
2315           header_file->offset + header_file->size - 1;
2316     } else {
2317       stream->fragment.header_range_end = -1;
2318     }
2319   }
2320
2321   /* set up our source for download */
2322   if (hlsdemux_stream->reset_pts || discont || demux->segment.rate < 0.0) {
2323     stream->fragment.stream_time = file->stream_time;
2324   } else {
2325     stream->fragment.stream_time = GST_CLOCK_STIME_NONE;
2326   }
2327
2328   g_free (hlsdemux_stream->current_key);
2329   hlsdemux_stream->current_key = g_strdup (file->key);
2330   g_free (hlsdemux_stream->current_iv);
2331   hlsdemux_stream->current_iv = g_memdup2 (file->iv, sizeof (file->iv));
2332
2333   g_free (stream->fragment.uri);
2334   stream->fragment.uri = g_strdup (file->uri);
2335
2336   GST_DEBUG_OBJECT (stream, "Stream URI now %s", file->uri);
2337
2338   stream->fragment.range_start = file->offset;
2339   if (file->size != -1)
2340     stream->fragment.range_end = file->offset + file->size - 1;
2341   else
2342     stream->fragment.range_end = -1;
2343
2344   stream->fragment.duration = file->duration;
2345
2346   if (discont)
2347     stream->discont = TRUE;
2348
2349   return ret;
2350 }
2351
2352 static gboolean
2353 gst_hls_demux_stream_can_start (GstAdaptiveDemux * demux,
2354     GstAdaptiveDemux2Stream * stream)
2355 {
2356   GstHLSDemux *hlsdemux = (GstHLSDemux *) demux;
2357   GstHLSDemuxStream *hls_stream = (GstHLSDemuxStream *) stream;
2358   GList *tmp;
2359
2360   GST_DEBUG_OBJECT (demux, "is_variant:%d mappings:%p", hls_stream->is_variant,
2361       hlsdemux->mappings);
2362
2363   /* Variant streams can always start straight away */
2364   if (hls_stream->is_variant)
2365     return TRUE;
2366
2367   /* Renditions of the exact same type as the variant are pure alternatives,
2368    * they must be started. This can happen for example with audio-only manifests
2369    * where the initial stream selected is a rendition and not a variant */
2370   if (hls_stream->rendition_type == hlsdemux->main_stream->rendition_type)
2371     return TRUE;
2372
2373   /* Rendition streams only require delaying if we don't have time mappings yet */
2374   if (!hlsdemux->mappings)
2375     return FALSE;
2376
2377   /* We can start if we have at least one internal time observation */
2378   for (tmp = hlsdemux->mappings; tmp; tmp = tmp->next) {
2379     GstHLSTimeMap *map = tmp->data;
2380     if (map->internal_time != GST_CLOCK_TIME_NONE)
2381       return TRUE;
2382   }
2383
2384   /* Otherwise we have to wait */
2385   return FALSE;
2386 }
2387
2388 /* Returns TRUE if the rendition stream switched group-id */
2389 static gboolean
2390 gst_hls_demux_update_rendition_stream (GstHLSDemux * hlsdemux,
2391     GstHLSDemuxStream * hls_stream, GError ** err)
2392 {
2393   gchar *current_group_id, *requested_group_id;
2394   GstHLSRenditionStream *replacement_media = NULL;
2395   GList *tmp;
2396
2397   /* There always should be a current variant set */
2398   g_assert (hlsdemux->current_variant);
2399   /* There always is a GstHLSRenditionStream set for rendition streams */
2400   g_assert (hls_stream->current_rendition);
2401
2402   requested_group_id =
2403       hlsdemux->current_variant->media_groups[hls_stream->
2404       current_rendition->mtype];
2405   current_group_id = hls_stream->current_rendition->group_id;
2406
2407   GST_DEBUG_OBJECT (hlsdemux,
2408       "Checking playlist change for variant stream %s lang: %s current group-id: %s / requested group-id: %s",
2409       gst_stream_type_get_name (hls_stream->rendition_type), hls_stream->lang,
2410       current_group_id, requested_group_id);
2411
2412
2413   if (!g_strcmp0 (requested_group_id, current_group_id)) {
2414     GST_DEBUG_OBJECT (hlsdemux, "No change needed");
2415     return FALSE;
2416   }
2417
2418   GST_DEBUG_OBJECT (hlsdemux,
2419       "group-id changed, looking for replacement playlist");
2420
2421   /* Need to switch/update */
2422   for (tmp = hlsdemux->master->renditions; tmp; tmp = tmp->next) {
2423     GstHLSRenditionStream *cand = tmp->data;
2424
2425     if (cand->mtype == hls_stream->current_rendition->mtype
2426         && !g_strcmp0 (cand->lang, hls_stream->lang)
2427         && !g_strcmp0 (cand->group_id, requested_group_id)) {
2428       replacement_media = cand;
2429       break;
2430     }
2431   }
2432   if (!replacement_media) {
2433     GST_ERROR_OBJECT (hlsdemux,
2434         "Could not find a replacement playlist. Staying with previous one");
2435     return FALSE;
2436   }
2437
2438   GST_DEBUG_OBJECT (hlsdemux, "Use replacement playlist %s",
2439       replacement_media->name);
2440   hls_stream->playlist_fetched = FALSE;
2441   if (hls_stream->pending_rendition) {
2442     GST_ERROR_OBJECT (hlsdemux,
2443         "Already had a pending rendition switch to '%s'",
2444         hls_stream->pending_rendition->name);
2445     gst_hls_rendition_stream_unref (hls_stream->pending_rendition);
2446   }
2447   hls_stream->pending_rendition =
2448       gst_hls_rendition_stream_ref (replacement_media);
2449   return TRUE;
2450 }
2451
2452 static gboolean
2453 gst_hls_demux_select_bitrate (GstAdaptiveDemux2Stream * stream, guint64 bitrate)
2454 {
2455   GstAdaptiveDemux *demux = GST_ADAPTIVE_DEMUX_CAST (stream->demux);
2456   GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (stream->demux);
2457   GstHLSDemuxStream *hls_stream = GST_HLS_DEMUX_STREAM_CAST (stream);
2458
2459   /* Fast-Path, no changes possible */
2460   if (hlsdemux->master == NULL || hlsdemux->master->is_simple)
2461     return FALSE;
2462
2463   if (hls_stream->is_variant) {
2464     gdouble play_rate = gst_adaptive_demux_play_rate (demux);
2465     gboolean changed = FALSE;
2466
2467     /* Handle variant streams */
2468     GST_DEBUG_OBJECT (hlsdemux,
2469         "Checking playlist change for main variant stream");
2470     gst_hls_demux_change_playlist (hlsdemux, bitrate / MAX (1.0,
2471             ABS (play_rate)), &changed);
2472
2473     GST_DEBUG_OBJECT (hlsdemux, "Returning changed: %d", changed);
2474     return changed;
2475   }
2476
2477   /* Handle rendition streams */
2478   return gst_hls_demux_update_rendition_stream (hlsdemux, hls_stream, NULL);
2479 }
2480
2481 static void
2482 gst_hls_demux_reset (GstAdaptiveDemux * ademux)
2483 {
2484   GstHLSDemux *demux = GST_HLS_DEMUX_CAST (ademux);
2485
2486   GST_DEBUG_OBJECT (demux, "resetting");
2487
2488   if (demux->master) {
2489     gst_hls_master_playlist_unref (demux->master);
2490     demux->master = NULL;
2491   }
2492   if (demux->current_variant != NULL) {
2493     gst_hls_variant_stream_unref (demux->current_variant);
2494     demux->current_variant = NULL;
2495   }
2496   if (demux->pending_variant != NULL) {
2497     gst_hls_variant_stream_unref (demux->pending_variant);
2498     demux->pending_variant = NULL;
2499   }
2500
2501   g_list_free_full (demux->mappings, g_free);
2502   demux->mappings = NULL;
2503
2504   gst_hls_demux_clear_all_pending_data (demux);
2505 }
2506
2507 /*
2508  * update: TRUE only when requested from parent class (via
2509  * ::demux_update_manifest() or ::change_playlist() ).
2510  */
2511 static GstFlowReturn
2512 gst_hls_demux_update_playlist (GstHLSDemux * demux, gboolean update,
2513     GError ** err)
2514 {
2515   GstFlowReturn ret = GST_FLOW_OK;
2516   GstAdaptiveDemux *adaptive_demux = GST_ADAPTIVE_DEMUX (demux);
2517
2518   GST_DEBUG_OBJECT (demux, "update:%d", update);
2519
2520   /* Download and update the appropriate variant playlist (pending if any, else
2521    * current) */
2522   ret = gst_hls_demux_stream_update_variant_playlist (demux, demux->main_stream,
2523       err);
2524   if (ret != GST_FLOW_OK)
2525     return ret;
2526
2527   if (update && gst_hls_demux_is_live (adaptive_demux)) {
2528     GList *tmp;
2529     GST_DEBUG_OBJECT (demux,
2530         "LIVE, Marking rendition streams to be updated next");
2531     /* We're live, instruct all rendition medias to be updated next */
2532     for (tmp = adaptive_demux->input_period->streams; tmp; tmp = tmp->next) {
2533       GstHLSDemuxStream *hls_stream = tmp->data;
2534       if (!hls_stream->is_variant)
2535         hls_stream->playlist_fetched = FALSE;
2536     }
2537   }
2538
2539   return GST_FLOW_OK;
2540 }
2541
2542 static gboolean
2543 gst_hls_demux_change_playlist (GstHLSDemux * demux, guint max_bitrate,
2544     gboolean * changed)
2545 {
2546   GstHLSVariantStream *lowest_variant, *lowest_ivariant;
2547   GstHLSVariantStream *previous_variant, *new_variant;
2548   gint old_bandwidth, new_bandwidth;
2549   GstAdaptiveDemux *adaptive_demux = GST_ADAPTIVE_DEMUX_CAST (demux);
2550   GstAdaptiveDemux2Stream *stream;
2551
2552   g_return_val_if_fail (demux->main_stream != NULL, FALSE);
2553   stream = (GstAdaptiveDemux2Stream *) demux->main_stream;
2554
2555   /* Make sure we keep a reference in case we need to switch back */
2556   previous_variant = gst_hls_variant_stream_ref (demux->current_variant);
2557   new_variant =
2558       gst_hls_master_playlist_get_variant_for_bitrate (demux->master,
2559       demux->current_variant, max_bitrate, adaptive_demux->min_bitrate);
2560
2561 retry_failover_protection:
2562   old_bandwidth = previous_variant->bandwidth;
2563   new_bandwidth = new_variant->bandwidth;
2564
2565   /* Don't do anything else if the playlist is the same */
2566   if (new_bandwidth == old_bandwidth) {
2567     gst_hls_variant_stream_unref (previous_variant);
2568     return TRUE;
2569   }
2570
2571   gst_hls_demux_set_current_variant (demux, new_variant);
2572
2573   GST_INFO_OBJECT (demux, "Client was on %dbps, max allowed is %dbps, switching"
2574       " to bitrate %dbps", old_bandwidth, max_bitrate, new_bandwidth);
2575
2576   if (gst_hls_demux_update_playlist (demux, TRUE, NULL) == GST_FLOW_OK) {
2577     const gchar *main_uri;
2578     gchar *uri = new_variant->uri;
2579
2580     main_uri = gst_adaptive_demux_get_manifest_ref_uri (adaptive_demux);
2581     gst_element_post_message (GST_ELEMENT_CAST (demux),
2582         gst_message_new_element (GST_OBJECT_CAST (demux),
2583             gst_structure_new (GST_ADAPTIVE_DEMUX_STATISTICS_MESSAGE_NAME,
2584                 "manifest-uri", G_TYPE_STRING,
2585                 main_uri, "uri", G_TYPE_STRING,
2586                 uri, "bitrate", G_TYPE_INT, new_bandwidth, NULL)));
2587     if (changed)
2588       *changed = TRUE;
2589     stream->discont = TRUE;
2590   } else if (gst_adaptive_demux2_is_running (GST_ADAPTIVE_DEMUX_CAST (demux))) {
2591     GstHLSVariantStream *failover_variant = NULL;
2592     GList *failover;
2593
2594     GST_INFO_OBJECT (demux, "Unable to update playlist. Switching back");
2595
2596     /* we find variants by bitrate by going from highest to lowest, so it's
2597      * possible that there's another variant with the same bitrate before the
2598      * one selected which we can use as failover */
2599     failover = g_list_find (demux->master->variants, new_variant);
2600     if (failover != NULL)
2601       failover = failover->prev;
2602     if (failover != NULL)
2603       failover_variant = failover->data;
2604     if (failover_variant && new_bandwidth == failover_variant->bandwidth) {
2605       new_variant = failover_variant;
2606       goto retry_failover_protection;
2607     }
2608
2609     gst_hls_demux_set_current_variant (demux, previous_variant);
2610     /*  Try a lower bitrate (or stop if we just tried the lowest) */
2611     if (previous_variant->iframe) {
2612       lowest_ivariant = demux->master->iframe_variants->data;
2613       if (new_bandwidth == lowest_ivariant->bandwidth)
2614         return FALSE;
2615     } else {
2616       lowest_variant = demux->master->variants->data;
2617       if (new_bandwidth == lowest_variant->bandwidth)
2618         return FALSE;
2619     }
2620     return gst_hls_demux_change_playlist (demux, new_bandwidth - 1, changed);
2621   }
2622
2623   gst_hls_variant_stream_unref (previous_variant);
2624   return TRUE;
2625 }
2626
2627 #if defined(HAVE_OPENSSL)
2628 static gboolean
2629 gst_hls_demux_stream_decrypt_start (GstHLSDemuxStream * stream,
2630     const guint8 * key_data, const guint8 * iv_data)
2631 {
2632   EVP_CIPHER_CTX *ctx;
2633 #if OPENSSL_VERSION_NUMBER < 0x10100000L
2634   EVP_CIPHER_CTX_init (&stream->aes_ctx);
2635   ctx = &stream->aes_ctx;
2636 #else
2637   stream->aes_ctx = EVP_CIPHER_CTX_new ();
2638   ctx = stream->aes_ctx;
2639 #endif
2640   if (!EVP_DecryptInit_ex (ctx, EVP_aes_128_cbc (), NULL, key_data, iv_data))
2641     return FALSE;
2642   EVP_CIPHER_CTX_set_padding (ctx, 0);
2643   return TRUE;
2644 }
2645
2646 static gboolean
2647 decrypt_fragment (GstHLSDemuxStream * stream, gsize length,
2648     const guint8 * encrypted_data, guint8 * decrypted_data)
2649 {
2650   int len, flen = 0;
2651   EVP_CIPHER_CTX *ctx;
2652
2653 #if OPENSSL_VERSION_NUMBER < 0x10100000L
2654   ctx = &stream->aes_ctx;
2655 #else
2656   ctx = stream->aes_ctx;
2657 #endif
2658
2659   if (G_UNLIKELY (length > G_MAXINT || length % 16 != 0))
2660     return FALSE;
2661
2662   len = (int) length;
2663   if (!EVP_DecryptUpdate (ctx, decrypted_data, &len, encrypted_data, len))
2664     return FALSE;
2665   EVP_DecryptFinal_ex (ctx, decrypted_data + len, &flen);
2666   g_return_val_if_fail (len + flen == length, FALSE);
2667   return TRUE;
2668 }
2669
2670 static void
2671 gst_hls_demux_stream_decrypt_end (GstHLSDemuxStream * stream)
2672 {
2673 #if OPENSSL_VERSION_NUMBER < 0x10100000L
2674   EVP_CIPHER_CTX_cleanup (&stream->aes_ctx);
2675 #else
2676   EVP_CIPHER_CTX_free (stream->aes_ctx);
2677   stream->aes_ctx = NULL;
2678 #endif
2679 }
2680
2681 #elif defined(HAVE_NETTLE)
2682 static gboolean
2683 gst_hls_demux_stream_decrypt_start (GstHLSDemuxStream * stream,
2684     const guint8 * key_data, const guint8 * iv_data)
2685 {
2686   aes128_set_decrypt_key (&stream->aes_ctx.ctx, key_data);
2687   CBC_SET_IV (&stream->aes_ctx, iv_data);
2688
2689   return TRUE;
2690 }
2691
2692 static gboolean
2693 decrypt_fragment (GstHLSDemuxStream * stream, gsize length,
2694     const guint8 * encrypted_data, guint8 * decrypted_data)
2695 {
2696   if (length % 16 != 0)
2697     return FALSE;
2698
2699   CBC_DECRYPT (&stream->aes_ctx, aes128_decrypt, length, decrypted_data,
2700       encrypted_data);
2701
2702   return TRUE;
2703 }
2704
2705 static void
2706 gst_hls_demux_stream_decrypt_end (GstHLSDemuxStream * stream)
2707 {
2708   /* NOP */
2709 }
2710
2711 #elif defined(HAVE_LIBGCRYPT)
2712 static gboolean
2713 gst_hls_demux_stream_decrypt_start (GstHLSDemuxStream * stream,
2714     const guint8 * key_data, const guint8 * iv_data)
2715 {
2716   gcry_error_t err = 0;
2717   gboolean ret = FALSE;
2718
2719   err =
2720       gcry_cipher_open (&stream->aes_ctx, GCRY_CIPHER_AES128,
2721       GCRY_CIPHER_MODE_CBC, 0);
2722   if (err)
2723     goto out;
2724   err = gcry_cipher_setkey (stream->aes_ctx, key_data, 16);
2725   if (err)
2726     goto out;
2727   err = gcry_cipher_setiv (stream->aes_ctx, iv_data, 16);
2728   if (!err)
2729     ret = TRUE;
2730
2731 out:
2732   if (!ret)
2733     if (stream->aes_ctx)
2734       gcry_cipher_close (stream->aes_ctx);
2735
2736   return ret;
2737 }
2738
2739 static gboolean
2740 decrypt_fragment (GstHLSDemuxStream * stream, gsize length,
2741     const guint8 * encrypted_data, guint8 * decrypted_data)
2742 {
2743   gcry_error_t err = 0;
2744
2745   err = gcry_cipher_decrypt (stream->aes_ctx, decrypted_data, length,
2746       encrypted_data, length);
2747
2748   return err == 0;
2749 }
2750
2751 static void
2752 gst_hls_demux_stream_decrypt_end (GstHLSDemuxStream * stream)
2753 {
2754   if (stream->aes_ctx) {
2755     gcry_cipher_close (stream->aes_ctx);
2756     stream->aes_ctx = NULL;
2757   }
2758 }
2759
2760 #else
2761 /* NO crypto available */
2762 static gboolean
2763 gst_hls_demux_stream_decrypt_start (GstHLSDemuxStream * stream,
2764     const guint8 * key_data, const guint8 * iv_data)
2765 {
2766   GST_ERROR ("No crypto available");
2767   return FALSE;
2768 }
2769
2770 static gboolean
2771 decrypt_fragment (GstHLSDemuxStream * stream, gsize length,
2772     const guint8 * encrypted_data, guint8 * decrypted_data)
2773 {
2774   GST_ERROR ("Cannot decrypt fragment, no crypto available");
2775   return FALSE;
2776 }
2777
2778 static void
2779 gst_hls_demux_stream_decrypt_end (GstHLSDemuxStream * stream)
2780 {
2781   return;
2782 }
2783 #endif
2784
2785 static GstBuffer *
2786 gst_hls_demux_decrypt_fragment (GstHLSDemux * demux, GstHLSDemuxStream * stream,
2787     GstBuffer * encrypted_buffer, GError ** err)
2788 {
2789   GstBuffer *decrypted_buffer = NULL;
2790   GstMapInfo encrypted_info, decrypted_info;
2791
2792   decrypted_buffer =
2793       gst_buffer_new_allocate (NULL, gst_buffer_get_size (encrypted_buffer),
2794       NULL);
2795
2796   gst_buffer_map (encrypted_buffer, &encrypted_info, GST_MAP_READ);
2797   gst_buffer_map (decrypted_buffer, &decrypted_info, GST_MAP_WRITE);
2798
2799   if (!decrypt_fragment (stream, encrypted_info.size,
2800           encrypted_info.data, decrypted_info.data))
2801     goto decrypt_error;
2802
2803
2804   gst_buffer_unmap (decrypted_buffer, &decrypted_info);
2805   gst_buffer_unmap (encrypted_buffer, &encrypted_info);
2806
2807   gst_buffer_unref (encrypted_buffer);
2808
2809   return decrypted_buffer;
2810
2811 decrypt_error:
2812   GST_ERROR_OBJECT (demux, "Failed to decrypt fragment");
2813   g_set_error (err, GST_STREAM_ERROR, GST_STREAM_ERROR_DECRYPT,
2814       "Failed to decrypt fragment");
2815
2816   gst_buffer_unmap (decrypted_buffer, &decrypted_info);
2817   gst_buffer_unmap (encrypted_buffer, &encrypted_info);
2818
2819   gst_buffer_unref (encrypted_buffer);
2820   gst_buffer_unref (decrypted_buffer);
2821
2822   return NULL;
2823 }
2824
2825 static gint64
2826 gst_hls_demux_get_manifest_update_interval (GstAdaptiveDemux * demux)
2827 {
2828   GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (demux);
2829   GstClockTime target_duration = 5 * GST_SECOND;
2830
2831   if (hlsdemux->main_stream && hlsdemux->main_stream->playlist) {
2832     GstHLSMediaPlaylist *playlist = hlsdemux->main_stream->playlist;
2833
2834     if (playlist->version > 5) {
2835       target_duration = hlsdemux->main_stream->playlist->targetduration;
2836     } else if (playlist->segments->len) {
2837       GstM3U8MediaSegment *last_seg =
2838           g_ptr_array_index (playlist->segments, playlist->segments->len - 1);
2839       target_duration = last_seg->duration;
2840     }
2841     if (playlist->reloaded && target_duration > (playlist->targetduration / 2)) {
2842       GST_DEBUG_OBJECT (demux,
2843           "Playlist didn't change previously, returning lower update interval");
2844       target_duration /= 2;
2845     }
2846   }
2847
2848   GST_DEBUG_OBJECT (demux, "Returning update interval of %" GST_TIME_FORMAT,
2849       GST_TIME_ARGS (target_duration));
2850
2851   return gst_util_uint64_scale (target_duration, G_USEC_PER_SEC, GST_SECOND);
2852 }
2853
2854 static GstClockTime
2855 gst_hls_demux_get_presentation_offset (GstAdaptiveDemux * demux,
2856     GstAdaptiveDemux2Stream * stream)
2857 {
2858   GstHLSDemux *hlsdemux = (GstHLSDemux *) demux;
2859   GstHLSDemuxStream *hls_stream = (GstHLSDemuxStream *) stream;
2860
2861   GST_DEBUG_OBJECT (stream, "presentation_offset %" GST_TIME_FORMAT,
2862       GST_TIME_ARGS (hls_stream->presentation_offset));
2863
2864   /* If this stream and the variant stream are ISOBMFF, returns the presentation
2865    * offset of the variant stream */
2866   if (hls_stream->parser_type == GST_HLS_PARSER_ISOBMFF
2867       && hlsdemux->main_stream->parser_type == GST_HLS_PARSER_ISOBMFF)
2868     return hlsdemux->main_stream->presentation_offset;
2869   return hls_stream->presentation_offset;
2870 }
2871
2872 static gboolean
2873 gst_hls_demux_get_live_seek_range (GstAdaptiveDemux * demux, gint64 * start,
2874     gint64 * stop)
2875 {
2876   GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (demux);
2877   gboolean ret = FALSE;
2878
2879   if (hlsdemux->main_stream && hlsdemux->main_stream->playlist)
2880     ret =
2881         gst_hls_media_playlist_get_seek_range (hlsdemux->main_stream->playlist,
2882         start, stop);
2883
2884   return ret;
2885 }
2886
2887 static gboolean
2888 hlsdemux2_element_init (GstPlugin * plugin)
2889 {
2890   gboolean ret = TRUE;
2891
2892   GST_DEBUG_CATEGORY_INIT (gst_hls_demux2_debug, "hlsdemux2", 0,
2893       "hlsdemux2 element");
2894
2895   if (!adaptivedemux2_base_element_init (plugin))
2896     return TRUE;
2897
2898   ret = gst_element_register (plugin, "hlsdemux2",
2899       GST_RANK_PRIMARY + 1, GST_TYPE_HLS_DEMUX2);
2900
2901   return ret;
2902 }