hlsdemux2: Download new header when it changes
[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  * Consumes the input buffer when it returns FALSE, but
1123  * replaces / returns the input buffer in the `buffer` parameter
1124  * when it returns TRUE.
1125  *
1126  * Returns TRUE if we are done with typefinding */
1127 static gboolean
1128 gst_hls_demux_typefind_stream (GstHLSDemux * hlsdemux,
1129     GstAdaptiveDemux2Stream * stream, GstBuffer ** out_buffer, gboolean at_eos,
1130     GstFlowReturn * ret)
1131 {
1132   GstHLSDemuxStream *hls_stream = GST_HLS_DEMUX_STREAM_CAST (stream);   // FIXME: pass HlsStream into function
1133   GstCaps *caps = NULL;
1134   guint buffer_size;
1135   GstTypeFindProbability prob = GST_TYPE_FIND_NONE;
1136   GstMapInfo info;
1137   GstBuffer *buffer = *out_buffer;
1138
1139   if (hls_stream->pending_typefind_buffer) {
1140     /* Append to the existing typefind buffer and create a new one that
1141      * we'll return (or consume below) */
1142     buffer = *out_buffer =
1143         gst_buffer_append (hls_stream->pending_typefind_buffer, buffer);
1144     hls_stream->pending_typefind_buffer = NULL;
1145   }
1146
1147   gst_buffer_map (buffer, &info, GST_MAP_READ);
1148   buffer_size = info.size;
1149
1150   /* Typefind could miss if buffer is too small. In this case we
1151    * will retry later */
1152   if (buffer_size >= (2 * 1024) || at_eos) {
1153     caps =
1154         gst_type_find_helper_for_data (GST_OBJECT_CAST (hlsdemux), info.data,
1155         info.size, &prob);
1156   }
1157
1158   if (G_UNLIKELY (!caps)) {
1159     /* Won't need this mapping any more all paths return inside this if() */
1160     gst_buffer_unmap (buffer, &info);
1161
1162     /* Only fail typefinding if we already a good amount of data
1163      * and we still don't know the type */
1164     if (buffer_size > (2 * 1024 * 1024) || at_eos) {
1165       GST_ELEMENT_ERROR (hlsdemux, STREAM, TYPE_NOT_FOUND,
1166           ("Could not determine type of stream"), (NULL));
1167       gst_buffer_unref (buffer);
1168       *ret = GST_FLOW_NOT_NEGOTIATED;
1169     } else {
1170       GST_LOG_OBJECT (stream, "Not enough data to typefind");
1171       hls_stream->pending_typefind_buffer = buffer;     /* Transfer the ref */
1172       *ret = GST_FLOW_OK;
1173     }
1174     *out_buffer = NULL;
1175     return FALSE;
1176   }
1177
1178   GST_DEBUG_OBJECT (stream,
1179       "Typefind result: %" GST_PTR_FORMAT " prob:%d", caps, prob);
1180
1181   if (hls_stream->parser_type == GST_HLS_PARSER_NONE) {
1182     hls_stream->parser_type = caps_to_parser_type (caps);
1183     if (hls_stream->parser_type == GST_HLS_PARSER_NONE) {
1184       GST_WARNING_OBJECT (stream,
1185           "Unsupported stream type %" GST_PTR_FORMAT, caps);
1186       GST_MEMDUMP_OBJECT (stream, "unknown data", info.data,
1187           MIN (info.size, 128));
1188       gst_buffer_unref (buffer);
1189       *ret = GST_FLOW_ERROR;
1190       return FALSE;
1191     }
1192     if (hls_stream->parser_type == GST_HLS_PARSER_ISOBMFF)
1193       hls_stream->presentation_offset = 0;
1194   }
1195
1196   gst_adaptive_demux2_stream_set_caps (stream, caps);
1197
1198   hls_stream->do_typefind = FALSE;
1199
1200   gst_buffer_unmap (buffer, &info);
1201
1202   /* We are done with typefinding. Doesn't consume the input buffer */
1203   *ret = GST_FLOW_OK;
1204   return TRUE;
1205 }
1206
1207 static GstHLSTimeMap *
1208 time_map_in_list (GList * list, gint64 dsn)
1209 {
1210   GList *iter;
1211
1212   for (iter = list; iter; iter = iter->next) {
1213     GstHLSTimeMap *map = iter->data;
1214
1215     if (map->dsn == dsn)
1216       return map;
1217   }
1218
1219   return NULL;
1220 }
1221
1222 GstHLSTimeMap *
1223 gst_hls_find_time_map (GstHLSDemux * demux, gint64 dsn)
1224 {
1225   return time_map_in_list (demux->mappings, dsn);
1226 }
1227
1228 /* Compute the stream time for the given internal time, based on the provided
1229  * time map.
1230  *
1231  * Will handle mpeg-ts wraparound. */
1232 GstClockTimeDiff
1233 gst_hls_internal_to_stream_time (GstHLSTimeMap * map,
1234     GstClockTime internal_time)
1235 {
1236   if (map->internal_time == GST_CLOCK_TIME_NONE)
1237     return GST_CLOCK_STIME_NONE;
1238
1239   /* Handle MPEG-TS Wraparound */
1240   if (internal_time < map->internal_time &&
1241       map->internal_time - internal_time > (MPEG_TS_MAX_PTS / 2))
1242     internal_time += MPEG_TS_MAX_PTS;
1243
1244   return (map->stream_time + internal_time - map->internal_time);
1245 }
1246
1247 /* Handle the internal time discovered on a segment.
1248  *
1249  * This function is called by the individual buffer parsers once they have
1250  * extracted that internal time (which is most of the time based on mpegts time,
1251  * but can also be ISOBMFF pts).
1252  *
1253  * This will update the time map when appropriate.
1254  *
1255  * If a synchronization issue is detected, the appropriate steps will be taken
1256  * and the RESYNC return value will be returned
1257  */
1258 GstHLSParserResult
1259 gst_hlsdemux_handle_internal_time (GstHLSDemux * demux,
1260     GstHLSDemuxStream * hls_stream, GstClockTime internal_time)
1261 {
1262   GstM3U8MediaSegment *current_segment = hls_stream->current_segment;
1263   GstHLSTimeMap *map;
1264   GstClockTimeDiff current_stream_time;
1265   GstClockTimeDiff real_stream_time, difference;
1266
1267   g_return_val_if_fail (current_segment != NULL, GST_HLS_PARSER_RESULT_ERROR);
1268
1269   current_stream_time = current_segment->stream_time;
1270
1271   GST_DEBUG_OBJECT (hls_stream,
1272       "Got internal time %" GST_TIME_FORMAT " for current segment stream time %"
1273       GST_STIME_FORMAT, GST_TIME_ARGS (internal_time),
1274       GST_STIME_ARGS (current_stream_time));
1275
1276   map = gst_hls_find_time_map (demux, current_segment->discont_sequence);
1277
1278   /* Time mappings will always be created upon initial parsing and when advancing */
1279   g_assert (map);
1280
1281   /* Handle the first internal time of a discont sequence. We can only store/use
1282    * those values for variant streams. */
1283   if (!GST_CLOCK_TIME_IS_VALID (map->internal_time)) {
1284     if (!hls_stream->is_variant) {
1285       GST_WARNING_OBJECT (hls_stream,
1286           "Got data from a new discont sequence on a rendition stream, can't validate stream time");
1287       return GST_HLS_PARSER_RESULT_DONE;
1288     }
1289     GST_DEBUG_OBJECT (hls_stream,
1290         "Updating time map dsn:%" G_GINT64_FORMAT " stream_time:%"
1291         GST_STIME_FORMAT " internal_time:%" GST_TIME_FORMAT, map->dsn,
1292         GST_STIME_ARGS (current_stream_time), GST_TIME_ARGS (internal_time));
1293     /* The stream time for a mapping should always be positive ! */
1294     g_assert (current_stream_time >= 0);
1295
1296     if (hls_stream->parser_type == GST_HLS_PARSER_ISOBMFF)
1297       hls_stream->presentation_offset = internal_time;
1298
1299     map->stream_time = current_stream_time;
1300     map->internal_time = internal_time;
1301
1302     gst_hls_demux_start_rendition_streams (demux);
1303     return GST_HLS_PARSER_RESULT_DONE;
1304   }
1305
1306   /* The information in a discont is always valid */
1307   if (current_segment->discont) {
1308     GST_DEBUG_OBJECT (hls_stream,
1309         "DISCONT segment, Updating time map to stream_time:%" GST_STIME_FORMAT
1310         " internal_time:%" GST_TIME_FORMAT, GST_STIME_ARGS (internal_time),
1311         GST_TIME_ARGS (current_stream_time));
1312     map->stream_time = current_stream_time;
1313     map->internal_time = internal_time;
1314     return GST_HLS_PARSER_RESULT_DONE;
1315   }
1316
1317   /* Check if the segment is the expected one */
1318   real_stream_time = gst_hls_internal_to_stream_time (map, internal_time);
1319   difference = current_stream_time - real_stream_time;
1320   GST_DEBUG_OBJECT (hls_stream,
1321       "Segment contains stream time %" GST_STIME_FORMAT
1322       " difference against expected : %" GST_STIME_FORMAT,
1323       GST_STIME_ARGS (real_stream_time), GST_STIME_ARGS (difference));
1324
1325   if (ABS (difference) > 10 * GST_MSECOND) {
1326     /* Update the value */
1327     GST_DEBUG_OBJECT (hls_stream,
1328         "Updating current stream time to %" GST_STIME_FORMAT,
1329         GST_STIME_ARGS (real_stream_time));
1330     current_segment->stream_time = real_stream_time;
1331
1332     gst_hls_media_playlist_recalculate_stream_time (hls_stream->playlist,
1333         hls_stream->current_segment);
1334     gst_hls_media_playlist_dump (hls_stream->playlist);
1335
1336     if (ABS (difference) > (hls_stream->current_segment->duration / 2)) {
1337       GstAdaptiveDemux2Stream *stream = (GstAdaptiveDemux2Stream *) hls_stream;
1338       GstM3U8MediaSegment *actual_segment;
1339
1340       /* We are at the wrong segment, try to figure out the *actual* segment */
1341       GST_DEBUG_OBJECT (hls_stream,
1342           "Trying to seek to the correct segment for %" GST_STIME_FORMAT,
1343           GST_STIME_ARGS (current_stream_time));
1344       actual_segment =
1345           gst_hls_media_playlist_seek (hls_stream->playlist, TRUE,
1346           GST_SEEK_FLAG_SNAP_NEAREST, current_stream_time);
1347
1348       if (actual_segment) {
1349         GST_DEBUG_OBJECT (hls_stream, "Synced to position %" GST_STIME_FORMAT,
1350             GST_STIME_ARGS (actual_segment->stream_time));
1351         gst_m3u8_media_segment_unref (hls_stream->current_segment);
1352         hls_stream->current_segment = actual_segment;
1353         /* Ask parent class to restart this fragment */
1354         return GST_HLS_PARSER_RESULT_RESYNC;
1355       }
1356
1357       GST_WARNING_OBJECT (hls_stream,
1358           "Could not find a replacement stream, carrying on with segment");
1359       stream->discont = TRUE;
1360       stream->fragment.stream_time = real_stream_time;
1361     }
1362   }
1363
1364   return GST_HLS_PARSER_RESULT_DONE;
1365 }
1366
1367 static GstHLSParserResult
1368 gst_hls_demux_handle_buffer_content (GstHLSDemux * demux,
1369     GstHLSDemuxStream * hls_stream, gboolean draining, GstBuffer ** buffer)
1370 {
1371   GstHLSTimeMap *map;
1372   GstAdaptiveDemux2Stream *stream = (GstAdaptiveDemux2Stream *) hls_stream;
1373   GstClockTimeDiff current_stream_time =
1374       hls_stream->current_segment->stream_time;
1375   GstClockTime current_duration = hls_stream->current_segment->duration;
1376   GstHLSParserResult parser_ret;
1377
1378   GST_LOG_OBJECT (stream,
1379       "stream_time:%" GST_STIME_FORMAT " duration:%" GST_TIME_FORMAT
1380       " discont:%d draining:%d header:%d index:%d",
1381       GST_STIME_ARGS (current_stream_time), GST_TIME_ARGS (current_duration),
1382       hls_stream->current_segment->discont, draining,
1383       stream->downloading_header, stream->downloading_index);
1384
1385   /* FIXME : Replace the boolean parser return value (and this function's return
1386    *  value) by an enum which clearly specifies whether:
1387    *
1388    * * The content parsing happened succesfully and it no longer needs to be
1389    *   called for the remainder of this fragment
1390    * * More data is needed in order to parse the data
1391    * * There was a fatal error parsing the contents (ex: invalid/incompatible
1392    *   content)
1393    * * The computed fragment stream time is out of sync
1394    */
1395
1396   g_assert (demux->mappings);
1397   map =
1398       gst_hls_find_time_map (demux,
1399       hls_stream->current_segment->discont_sequence);
1400   if (!map) {
1401     /* For rendition streams, we can't do anything without time mapping */
1402     if (!hls_stream->is_variant) {
1403       GST_DEBUG_OBJECT (stream,
1404           "No available time mapping for dsn:%" G_GINT64_FORMAT
1405           " using estimated stream time",
1406           hls_stream->current_segment->discont_sequence);
1407       goto out_done;
1408     }
1409
1410     /* Variants will be able to fill in the the time mapping, so we can carry on without a time mapping */
1411   } else {
1412     GST_DEBUG_OBJECT (stream,
1413         "Using mapping dsn:%" G_GINT64_FORMAT " stream_time:%" GST_TIME_FORMAT
1414         " internal_time:%" GST_TIME_FORMAT, map->dsn,
1415         GST_TIME_ARGS (map->stream_time), GST_TIME_ARGS (map->internal_time));
1416   }
1417
1418   switch (hls_stream->parser_type) {
1419     case GST_HLS_PARSER_MPEGTS:
1420       parser_ret =
1421           gst_hlsdemux_handle_content_mpegts (demux, hls_stream, draining,
1422           buffer);
1423       break;
1424     case GST_HLS_PARSER_ID3:
1425       parser_ret =
1426           gst_hlsdemux_handle_content_id3 (demux, hls_stream, draining, buffer);
1427       break;
1428     case GST_HLS_PARSER_WEBVTT:
1429     {
1430       /* Furthermore it will handle timeshifting itself */
1431       parser_ret =
1432           gst_hlsdemux_handle_content_webvtt (demux, hls_stream, draining,
1433           buffer);
1434       break;
1435     }
1436     case GST_HLS_PARSER_ISOBMFF:
1437       parser_ret =
1438           gst_hlsdemux_handle_content_isobmff (demux, hls_stream, draining,
1439           buffer);
1440       break;
1441     case GST_HLS_PARSER_NONE:
1442     default:
1443     {
1444       GST_ERROR_OBJECT (stream, "Unknown stream type");
1445       goto out_error;
1446     }
1447   }
1448
1449   if (parser_ret == GST_HLS_PARSER_RESULT_NEED_MORE_DATA) {
1450     if (stream->downloading_index || stream->downloading_header)
1451       goto out_need_more;
1452     /* Else if we're draining, it's an error */
1453     if (draining)
1454       goto out_error;
1455     /* Else we just need more data */
1456     goto out_need_more;
1457   }
1458
1459   if (parser_ret == GST_HLS_PARSER_RESULT_ERROR)
1460     goto out_error;
1461
1462   if (parser_ret == GST_HLS_PARSER_RESULT_RESYNC)
1463     goto out_resync;
1464
1465 out_done:
1466   GST_DEBUG_OBJECT (stream, "Done. Finished parsing");
1467   return GST_HLS_PARSER_RESULT_DONE;
1468
1469 out_error:
1470   GST_DEBUG_OBJECT (stream, "Done. Error while parsing");
1471   return GST_HLS_PARSER_RESULT_ERROR;
1472
1473 out_need_more:
1474   GST_DEBUG_OBJECT (stream, "Done. Need more data");
1475   return GST_HLS_PARSER_RESULT_NEED_MORE_DATA;
1476
1477 out_resync:
1478   GST_DEBUG_OBJECT (stream, "Done. Resync required");
1479   return GST_HLS_PARSER_RESULT_RESYNC;
1480 }
1481
1482 static GstFlowReturn
1483 gst_hls_demux_handle_buffer (GstAdaptiveDemux * demux,
1484     GstAdaptiveDemux2Stream * stream, GstBuffer * buffer, gboolean at_eos)
1485 {
1486   GstHLSDemuxStream *hls_stream = GST_HLS_DEMUX_STREAM_CAST (stream);   // FIXME: pass HlsStream into function
1487   GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (demux);
1488   GstFlowReturn ret = GST_FLOW_OK;
1489   GstBuffer *pending_header_data = NULL;
1490
1491   /* If current segment is not present, this means that a playlist update
1492    * happened between the moment ::update_fragment_info() was called and the
1493    * moment we received data. And that playlist update couldn't match the
1494    * current position. This will happen in live playback when we are downloading
1495    * too slowly, therefore we try to "catch up" back to live
1496    */
1497   if (hls_stream->current_segment == NULL) {
1498     GST_WARNING_OBJECT (stream, "Lost sync");
1499     /* Drop the buffer */
1500     gst_buffer_unref (buffer);
1501     return GST_ADAPTIVE_DEMUX_FLOW_LOST_SYNC;
1502   }
1503
1504   GST_DEBUG_OBJECT (stream,
1505       "buffer:%p at_eos:%d do_typefind:%d uri:%s", buffer, at_eos,
1506       hls_stream->do_typefind, hls_stream->current_segment->uri);
1507
1508   if (buffer == NULL)
1509     goto out;
1510
1511   /* If we need to do typefind and we're not done with it (or we errored), return */
1512   if (G_UNLIKELY (hls_stream->do_typefind) &&
1513       !gst_hls_demux_typefind_stream (hlsdemux, stream, &buffer, at_eos,
1514           &ret)) {
1515     goto out;
1516   }
1517   g_assert (hls_stream->pending_typefind_buffer == NULL);
1518
1519   if (hls_stream->process_buffer_content) {
1520     GstHLSParserResult parse_ret;
1521
1522     if (hls_stream->pending_segment_data) {
1523       if (hls_stream->pending_data_is_header) {
1524         /* Keep a copy of the header data in case we need to requeue it
1525          * due to GST_ADAPTIVE_DEMUX_FLOW_RESTART_FRAGMENT below */
1526         pending_header_data = gst_buffer_ref (hls_stream->pending_segment_data);
1527       }
1528       buffer = gst_buffer_append (hls_stream->pending_segment_data, buffer);
1529       hls_stream->pending_segment_data = NULL;
1530     }
1531
1532     /* Try to get the timing information */
1533     parse_ret =
1534         gst_hls_demux_handle_buffer_content (hlsdemux, hls_stream, at_eos,
1535         &buffer);
1536
1537     switch (parse_ret) {
1538       case GST_HLS_PARSER_RESULT_NEED_MORE_DATA:
1539         /* If we don't have enough, store and return */
1540         hls_stream->pending_segment_data = buffer;
1541         hls_stream->pending_data_is_header =
1542             (stream->downloading_header == TRUE);
1543         if (hls_stream->pending_data_is_header)
1544           stream->send_segment = TRUE;
1545         goto out;
1546       case GST_HLS_PARSER_RESULT_ERROR:
1547         /* Error, drop buffer and return */
1548         gst_buffer_unref (buffer);
1549         ret = GST_FLOW_ERROR;
1550         goto out;
1551       case GST_HLS_PARSER_RESULT_RESYNC:
1552         /* Resync, drop buffer and return */
1553         gst_buffer_unref (buffer);
1554         ret = GST_ADAPTIVE_DEMUX_FLOW_RESTART_FRAGMENT;
1555         /* If we had a pending set of header data, requeue it */
1556         if (pending_header_data != NULL) {
1557           g_assert (hls_stream->pending_segment_data == NULL);
1558
1559           GST_DEBUG_OBJECT (hls_stream,
1560               "Requeueing header data %" GST_PTR_FORMAT
1561               " before returning RESTART_FRAGMENT", pending_header_data);
1562           hls_stream->pending_segment_data = pending_header_data;
1563           pending_header_data = NULL;
1564         }
1565         goto out;
1566       case GST_HLS_PARSER_RESULT_DONE:
1567         /* Done parsing, carry on */
1568         hls_stream->process_buffer_content = FALSE;
1569         break;
1570     }
1571   }
1572
1573   if (!buffer)
1574     goto out;
1575
1576   buffer = gst_buffer_make_writable (buffer);
1577
1578   GST_BUFFER_OFFSET (buffer) = hls_stream->current_offset;
1579   hls_stream->current_offset += gst_buffer_get_size (buffer);
1580   GST_BUFFER_OFFSET_END (buffer) = hls_stream->current_offset;
1581
1582   GST_DEBUG_OBJECT (stream, "We have a buffer, pushing: %" GST_PTR_FORMAT,
1583       buffer);
1584
1585   ret = gst_adaptive_demux2_stream_push_buffer (stream, buffer);
1586
1587 out:
1588   if (pending_header_data != NULL) {
1589     /* Throw away the pending header data now. If it wasn't consumed above,
1590      * we won't need it */
1591     gst_buffer_unref (pending_header_data);
1592   }
1593
1594   GST_DEBUG_OBJECT (stream, "Returning %s", gst_flow_get_name (ret));
1595   return ret;
1596 }
1597
1598 static GstFlowReturn
1599 gst_hls_demux_finish_fragment (GstAdaptiveDemux * demux,
1600     GstAdaptiveDemux2Stream * stream)
1601 {
1602   GstHLSDemuxStream *hls_stream = GST_HLS_DEMUX_STREAM_CAST (stream);   // FIXME: pass HlsStream into function
1603   GstFlowReturn ret = GST_FLOW_OK;
1604
1605   GST_DEBUG_OBJECT (stream, "Finishing fragment uri:%s",
1606       hls_stream->current_segment->uri);
1607
1608   /* Drain all pending data */
1609   if (hls_stream->current_key)
1610     gst_hls_demux_stream_decrypt_end (hls_stream);
1611
1612   if (hls_stream->current_segment && stream->last_ret == GST_FLOW_OK) {
1613     if (hls_stream->pending_decrypted_buffer) {
1614       if (hls_stream->current_key) {
1615         GstMapInfo info;
1616         gssize unpadded_size;
1617
1618         /* Handle pkcs7 unpadding here */
1619         gst_buffer_map (hls_stream->pending_decrypted_buffer, &info,
1620             GST_MAP_READ);
1621         unpadded_size = info.size - info.data[info.size - 1];
1622         gst_buffer_unmap (hls_stream->pending_decrypted_buffer, &info);
1623
1624         gst_buffer_resize (hls_stream->pending_decrypted_buffer, 0,
1625             unpadded_size);
1626       }
1627
1628       ret =
1629           gst_hls_demux_handle_buffer (demux, stream,
1630           hls_stream->pending_decrypted_buffer, TRUE);
1631       hls_stream->pending_decrypted_buffer = NULL;
1632     }
1633
1634     if (ret == GST_FLOW_OK || ret == GST_FLOW_NOT_LINKED) {
1635       if (G_UNLIKELY (hls_stream->pending_typefind_buffer)) {
1636         GstBuffer *buf = hls_stream->pending_typefind_buffer;
1637         hls_stream->pending_typefind_buffer = NULL;
1638
1639         gst_hls_demux_handle_buffer (demux, stream, buf, TRUE);
1640       }
1641
1642       if (hls_stream->pending_segment_data) {
1643         GstBuffer *buf = hls_stream->pending_segment_data;
1644         hls_stream->pending_segment_data = NULL;
1645
1646         ret = gst_hls_demux_handle_buffer (demux, stream, buf, TRUE);
1647       }
1648     }
1649   }
1650
1651   gst_hls_demux_stream_clear_pending_data (hls_stream, FALSE);
1652
1653   if (G_UNLIKELY (stream->downloading_header || stream->downloading_index))
1654     return GST_FLOW_OK;
1655
1656   if (hls_stream->current_segment == NULL) {
1657     /* We can't advance, we just return OK for now and let the base class
1658      * trigger a new download (or fail and resync itself) */
1659     return GST_FLOW_OK;
1660   }
1661
1662   if (ret == GST_FLOW_OK || ret == GST_FLOW_NOT_LINKED) {
1663     /* We can update the stream current position with a more accurate value
1664      * before advancing. Note that we don't have any period so we can set the
1665      * stream_time as-is on the stream current position */
1666     stream->current_position = hls_stream->current_segment->stream_time;
1667     return gst_adaptive_demux2_stream_advance_fragment (demux, stream,
1668         hls_stream->current_segment->duration);
1669   }
1670   return ret;
1671 }
1672
1673 static GstFlowReturn
1674 gst_hls_demux_data_received (GstAdaptiveDemux * demux,
1675     GstAdaptiveDemux2Stream * stream, GstBuffer * buffer)
1676 {
1677   GstHLSDemuxStream *hls_stream = GST_HLS_DEMUX_STREAM_CAST (stream);
1678   GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (demux);
1679
1680   if (hls_stream->current_segment == NULL)
1681     return GST_ADAPTIVE_DEMUX_FLOW_LOST_SYNC;
1682
1683   if (hls_stream->current_offset == -1)
1684     hls_stream->current_offset = 0;
1685
1686   /* Is it encrypted? */
1687   if (hls_stream->current_key) {
1688     GError *err = NULL;
1689     gsize size;
1690     GstBuffer *decrypted_buffer;
1691     GstBuffer *tmp_buffer;
1692
1693     if (hls_stream->pending_encrypted_data == NULL)
1694       hls_stream->pending_encrypted_data = gst_adapter_new ();
1695
1696     gst_adapter_push (hls_stream->pending_encrypted_data, buffer);
1697     size = gst_adapter_available (hls_stream->pending_encrypted_data);
1698
1699     /* must be a multiple of 16 */
1700     size &= (~0xF);
1701
1702     if (size == 0) {
1703       return GST_FLOW_OK;
1704     }
1705
1706     buffer = gst_adapter_take_buffer (hls_stream->pending_encrypted_data, size);
1707     decrypted_buffer =
1708         gst_hls_demux_decrypt_fragment (hlsdemux, hls_stream, buffer, &err);
1709     if (err) {
1710       GST_ELEMENT_ERROR (demux, STREAM, DECODE, ("Failed to decrypt buffer"),
1711           ("decryption failed %s", err->message));
1712       g_error_free (err);
1713       return GST_FLOW_ERROR;
1714     }
1715
1716     tmp_buffer = hls_stream->pending_decrypted_buffer;
1717     hls_stream->pending_decrypted_buffer = decrypted_buffer;
1718     buffer = tmp_buffer;
1719     if (!buffer)
1720       return GST_FLOW_OK;
1721   }
1722
1723   return gst_hls_demux_handle_buffer (demux, stream, buffer, FALSE);
1724 }
1725
1726 static void
1727 gst_hls_demux_stream_finalize (GObject * object)
1728 {
1729   GstAdaptiveDemux2Stream *stream = (GstAdaptiveDemux2Stream *) object;
1730   GstHLSDemuxStream *hls_stream = GST_HLS_DEMUX_STREAM_CAST (object);
1731   GstHLSDemux *hlsdemux = (GstHLSDemux *) stream->demux;
1732
1733   if (hls_stream == hlsdemux->main_stream)
1734     hlsdemux->main_stream = NULL;
1735
1736   g_free (hls_stream->lang);
1737   g_free (hls_stream->name);
1738
1739   if (hls_stream->playlist) {
1740     gst_hls_media_playlist_unref (hls_stream->playlist);
1741     hls_stream->playlist = NULL;
1742   }
1743
1744   if (hls_stream->init_file) {
1745     gst_m3u8_init_file_unref (hls_stream->init_file);
1746     hls_stream->init_file = NULL;
1747   }
1748
1749   if (hls_stream->pending_encrypted_data)
1750     g_object_unref (hls_stream->pending_encrypted_data);
1751
1752   gst_buffer_replace (&hls_stream->pending_decrypted_buffer, NULL);
1753   gst_buffer_replace (&hls_stream->pending_typefind_buffer, NULL);
1754   gst_buffer_replace (&hls_stream->pending_segment_data, NULL);
1755
1756   if (hls_stream->moov)
1757     gst_isoff_moov_box_free (hls_stream->moov);
1758
1759   if (hls_stream->current_key) {
1760     g_free (hls_stream->current_key);
1761     hls_stream->current_key = NULL;
1762   }
1763   if (hls_stream->current_iv) {
1764     g_free (hls_stream->current_iv);
1765     hls_stream->current_iv = NULL;
1766   }
1767   if (hls_stream->current_rendition) {
1768     gst_hls_rendition_stream_unref (hls_stream->current_rendition);
1769     hls_stream->current_rendition = NULL;
1770   }
1771   if (hls_stream->pending_rendition) {
1772     gst_hls_rendition_stream_unref (hls_stream->pending_rendition);
1773     hls_stream->pending_rendition = NULL;
1774   }
1775
1776   if (hls_stream->current_segment) {
1777     gst_m3u8_media_segment_unref (hls_stream->current_segment);
1778     hls_stream->current_segment = NULL;
1779   }
1780   gst_hls_demux_stream_decrypt_end (hls_stream);
1781
1782   G_OBJECT_CLASS (stream_parent_class)->finalize (object);
1783 }
1784
1785 static gboolean
1786 gst_hls_demux_stream_has_next_fragment (GstAdaptiveDemux2Stream * stream)
1787 {
1788   GstHLSDemuxStream *hls_stream = (GstHLSDemuxStream *) stream;
1789
1790   GST_DEBUG_OBJECT (stream, "has next ?");
1791
1792   return gst_hls_media_playlist_has_next_fragment (hls_stream->playlist,
1793       hls_stream->current_segment, stream->demux->segment.rate > 0);
1794 }
1795
1796 static GstFlowReturn
1797 gst_hls_demux_advance_fragment (GstAdaptiveDemux2Stream * stream)
1798 {
1799   GstHLSDemuxStream *hlsdemux_stream = GST_HLS_DEMUX_STREAM_CAST (stream);
1800   GstHLSDemux *hlsdemux = (GstHLSDemux *) stream->demux;
1801   GstM3U8MediaSegment *new_segment = NULL;
1802
1803   GST_DEBUG_OBJECT (stream,
1804       "Current segment sn:%" G_GINT64_FORMAT " stream_time:%" GST_STIME_FORMAT
1805       " uri:%s", hlsdemux_stream->current_segment->sequence,
1806       GST_STIME_ARGS (hlsdemux_stream->current_segment->stream_time),
1807       hlsdemux_stream->current_segment->uri);
1808
1809   new_segment =
1810       gst_hls_media_playlist_advance_fragment (hlsdemux_stream->playlist,
1811       hlsdemux_stream->current_segment, stream->demux->segment.rate > 0);
1812   if (new_segment) {
1813     hlsdemux_stream->reset_pts = FALSE;
1814     if (new_segment->discont_sequence !=
1815         hlsdemux_stream->current_segment->discont_sequence)
1816       gst_hls_demux_add_time_mapping (hlsdemux, new_segment->discont_sequence,
1817           new_segment->stream_time, new_segment->datetime);
1818     gst_m3u8_media_segment_unref (hlsdemux_stream->current_segment);
1819     hlsdemux_stream->current_segment = new_segment;
1820     GST_DEBUG_OBJECT (stream,
1821         "Advanced to segment sn:%" G_GINT64_FORMAT " stream_time:%"
1822         GST_STIME_FORMAT " uri:%s", hlsdemux_stream->current_segment->sequence,
1823         GST_STIME_ARGS (hlsdemux_stream->current_segment->stream_time),
1824         hlsdemux_stream->current_segment->uri);
1825     return GST_FLOW_OK;
1826   }
1827
1828   GST_LOG_OBJECT (stream, "Could not advance to next fragment");
1829   if (GST_HLS_MEDIA_PLAYLIST_IS_LIVE (hlsdemux_stream->playlist)) {
1830     gst_m3u8_media_segment_unref (hlsdemux_stream->current_segment);
1831     hlsdemux_stream->current_segment = NULL;
1832     return GST_FLOW_OK;
1833   }
1834
1835   return GST_FLOW_EOS;
1836 }
1837
1838 static GstHLSMediaPlaylist *
1839 download_media_playlist (GstHLSDemux * demux, gchar * uri, GError ** err,
1840     GstHLSMediaPlaylist * current)
1841 {
1842   GstAdaptiveDemux *adaptive_demux;
1843   const gchar *main_uri;
1844   DownloadRequest *download;
1845   GstBuffer *buf;
1846   gchar *playlist_data;
1847   GstHLSMediaPlaylist *playlist = NULL;
1848   gchar *base_uri;
1849   gboolean playlist_uri_change = FALSE;
1850
1851   adaptive_demux = GST_ADAPTIVE_DEMUX (demux);
1852   main_uri = gst_adaptive_demux_get_manifest_ref_uri (adaptive_demux);
1853
1854   /* If there's no previous playlist, or the URI changed this
1855    * is not a refresh/update but a switch to a new playlist */
1856   playlist_uri_change = (current == NULL || g_strcmp0 (uri, current->uri) != 0);
1857
1858   if (!playlist_uri_change) {
1859     GST_LOG_OBJECT (demux, "Updating the playlist");
1860   }
1861
1862   download =
1863       downloadhelper_fetch_uri (adaptive_demux->download_helper,
1864       uri, main_uri, DOWNLOAD_FLAG_COMPRESS | DOWNLOAD_FLAG_FORCE_REFRESH, err);
1865
1866   if (download == NULL)
1867     return NULL;
1868
1869   /* Set the base URI of the playlist to the redirect target if any */
1870   if (download->redirect_permanent && download->redirect_uri) {
1871     uri = g_strdup (download->redirect_uri);
1872     base_uri = NULL;
1873   } else {
1874     uri = g_strdup (download->uri);
1875     base_uri = g_strdup (download->redirect_uri);
1876   }
1877
1878   if (download->state == DOWNLOAD_REQUEST_STATE_ERROR) {
1879     GST_WARNING_OBJECT (demux,
1880         "Couldn't get the playlist, got HTTP status code %d",
1881         download->status_code);
1882     download_request_unref (download);
1883     if (err)
1884       g_set_error (err, GST_STREAM_ERROR, GST_STREAM_ERROR_WRONG_TYPE,
1885           "Couldn't download the playlist");
1886     goto out;
1887   }
1888   buf = download_request_take_buffer (download);
1889   download_request_unref (download);
1890
1891   /* there should be a buf if there wasn't an error (handled above) */
1892   g_assert (buf);
1893
1894   playlist_data = gst_hls_buf_to_utf8_text (buf);
1895   gst_buffer_unref (buf);
1896
1897   if (playlist_data == NULL) {
1898     GST_WARNING_OBJECT (demux, "Couldn't validate playlist encoding");
1899     if (err)
1900       g_set_error (err, GST_STREAM_ERROR, GST_STREAM_ERROR_WRONG_TYPE,
1901           "Couldn't validate playlist encoding");
1902     goto out;
1903   }
1904
1905   if (!playlist_uri_change && current
1906       && gst_hls_media_playlist_has_same_data (current, playlist_data)) {
1907     GST_DEBUG_OBJECT (demux, "Same playlist data");
1908     playlist = gst_hls_media_playlist_ref (current);
1909     playlist->reloaded = TRUE;
1910     g_free (playlist_data);
1911   } else {
1912     playlist = gst_hls_media_playlist_parse (playlist_data, uri, base_uri);
1913     if (!playlist) {
1914       GST_WARNING_OBJECT (demux, "Couldn't parse playlist");
1915       if (err)
1916         g_set_error (err, GST_STREAM_ERROR, GST_STREAM_ERROR_FAILED,
1917             "Couldn't parse playlist");
1918     }
1919   }
1920
1921 out:
1922   g_free (uri);
1923   g_free (base_uri);
1924
1925   return playlist;
1926 }
1927
1928 static GstHLSTimeMap *
1929 gst_hls_time_map_new (void)
1930 {
1931   GstHLSTimeMap *map = g_new0 (GstHLSTimeMap, 1);
1932
1933   map->stream_time = GST_CLOCK_TIME_NONE;
1934   map->internal_time = GST_CLOCK_TIME_NONE;
1935
1936   return map;
1937 }
1938
1939 static void
1940 gst_hls_time_map_free (GstHLSTimeMap * map)
1941 {
1942   if (map->pdt)
1943     g_date_time_unref (map->pdt);
1944   g_free (map);
1945 }
1946
1947 static void
1948 gst_hls_demux_add_time_mapping (GstHLSDemux * demux, gint64 dsn,
1949     GstClockTimeDiff stream_time, GDateTime * pdt)
1950 {
1951 #ifndef GST_DISABLE_GST_DEBUG
1952   gchar *datestring = NULL;
1953 #endif
1954   GstHLSTimeMap *map;
1955   GList *tmp;
1956   GstClockTime offset = 0;
1957
1958   /* Check if we don't already have a mapping for the given dsn */
1959   for (tmp = demux->mappings; tmp; tmp = tmp->next) {
1960     GstHLSTimeMap *map = tmp->data;
1961
1962     if (map->dsn == dsn) {
1963 #ifndef GST_DISABLE_GST_DEBUG
1964       if (map->pdt)
1965         datestring = g_date_time_format_iso8601 (map->pdt);
1966       GST_DEBUG_OBJECT (demux,
1967           "Already have mapping, dsn:%" G_GINT64_FORMAT " stream_time:%"
1968           GST_TIME_FORMAT " internal_time:%" GST_TIME_FORMAT " pdt:%s",
1969           map->dsn, GST_TIME_ARGS (map->stream_time),
1970           GST_TIME_ARGS (map->internal_time), datestring);
1971       g_free (datestring);
1972 #endif
1973       return;
1974     }
1975   }
1976
1977 #ifndef GST_DISABLE_GST_DEBUG
1978   if (pdt)
1979     datestring = g_date_time_format_iso8601 (pdt);
1980   GST_DEBUG_OBJECT (demux,
1981       "New mapping, dsn:%" G_GINT64_FORMAT " stream_time:%" GST_TIME_FORMAT
1982       " pdt:%s", dsn, GST_TIME_ARGS (stream_time), datestring);
1983   g_free (datestring);
1984 #endif
1985
1986   if (stream_time < 0) {
1987     offset = -stream_time;
1988     stream_time = 0;
1989     /* Handle negative stream times. This can happen for example when the server
1990      * returns an older playlist.
1991      *
1992      * Shift the values accordingly to end up with non-negative reference stream
1993      * time */
1994     GST_DEBUG_OBJECT (demux,
1995         "Shifting values before storage (offset : %" GST_TIME_FORMAT ")",
1996         GST_TIME_ARGS (offset));
1997   }
1998
1999   map = gst_hls_time_map_new ();
2000   map->dsn = dsn;
2001   map->stream_time = stream_time;
2002   if (pdt) {
2003     if (offset)
2004       map->pdt = g_date_time_add (pdt, offset / GST_USECOND);
2005     else
2006       map->pdt = g_date_time_ref (pdt);
2007   }
2008
2009   demux->mappings = g_list_append (demux->mappings, map);
2010 }
2011
2012 /* Remove any time mapping which isn't currently used by any stream playlist */
2013 static void
2014 gst_hls_prune_time_mappings (GstHLSDemux * hlsdemux)
2015 {
2016   GstAdaptiveDemux *demux = (GstAdaptiveDemux *) hlsdemux;
2017   GList *active = NULL;
2018   GList *iterstream;
2019
2020   for (iterstream = demux->input_period->streams; iterstream;
2021       iterstream = iterstream->next) {
2022     GstAdaptiveDemux2Stream *stream = iterstream->data;
2023     GstHLSDemuxStream *hls_stream = (GstHLSDemuxStream *) stream;
2024     gint64 dsn = G_MAXINT64;
2025     guint idx, len;
2026
2027     if (!hls_stream->playlist)
2028       continue;
2029     len = hls_stream->playlist->segments->len;
2030     for (idx = 0; idx < len; idx++) {
2031       GstM3U8MediaSegment *segment =
2032           g_ptr_array_index (hls_stream->playlist->segments, idx);
2033
2034       if (dsn == G_MAXINT64 || segment->discont_sequence != dsn) {
2035         dsn = segment->discont_sequence;
2036         if (!time_map_in_list (active, dsn)) {
2037           GstHLSTimeMap *map = gst_hls_find_time_map (hlsdemux, dsn);
2038           if (map) {
2039             GST_DEBUG_OBJECT (demux,
2040                 "Keeping active time map dsn:%" G_GINT64_FORMAT, map->dsn);
2041             /* Move active dsn to active list */
2042             hlsdemux->mappings = g_list_remove (hlsdemux->mappings, map);
2043             active = g_list_append (active, map);
2044           }
2045         }
2046       }
2047     }
2048   }
2049
2050   g_list_free_full (hlsdemux->mappings, (GDestroyNotify) gst_hls_time_map_free);
2051   hlsdemux->mappings = active;
2052 }
2053
2054 /* Go over the DSN from the playlist and add any missing time mapping */
2055 static void
2056 gst_hls_update_time_mappings (GstHLSDemux * demux,
2057     GstHLSMediaPlaylist * playlist)
2058 {
2059   guint idx, len = playlist->segments->len;
2060   gint64 dsn = G_MAXINT64;
2061
2062   for (idx = 0; idx < len; idx++) {
2063     GstM3U8MediaSegment *segment = g_ptr_array_index (playlist->segments, idx);
2064
2065     if (dsn == G_MAXINT64 || segment->discont_sequence != dsn) {
2066       dsn = segment->discont_sequence;
2067       if (!gst_hls_find_time_map (demux, segment->discont_sequence))
2068         gst_hls_demux_add_time_mapping (demux, segment->discont_sequence,
2069             segment->stream_time, segment->datetime);
2070     }
2071   }
2072 }
2073
2074 static void
2075 setup_initial_playlist (GstHLSDemux * demux, GstHLSMediaPlaylist * playlist)
2076 {
2077   guint idx, len = playlist->segments->len;
2078   GstM3U8MediaSegment *segment;
2079   GstClockTimeDiff pos = 0;
2080
2081   GST_DEBUG_OBJECT (demux,
2082       "Setting up initial variant segment and time mapping");
2083
2084   /* This is the initial variant playlist. We will use it to base all our timing
2085    * from. */
2086
2087   for (idx = 0; idx < len; idx++) {
2088     segment = g_ptr_array_index (playlist->segments, idx);
2089
2090     segment->stream_time = pos;
2091     pos += segment->duration;
2092   }
2093 }
2094
2095 /* Reset hlsdemux in case of live synchronization loss (i.e. when a media
2096  * playlist update doesn't match at all with the previous one) */
2097 static void
2098 gst_hls_demux_reset_for_lost_sync (GstHLSDemux * hlsdemux)
2099 {
2100   GstAdaptiveDemux *demux = (GstAdaptiveDemux *) hlsdemux;
2101   GList *iter;
2102
2103   GST_DEBUG_OBJECT (hlsdemux, "Resetting for lost sync");
2104
2105   for (iter = demux->input_period->streams; iter; iter = iter->next) {
2106     GstHLSDemuxStream *hls_stream = iter->data;
2107     GstAdaptiveDemux2Stream *stream = (GstAdaptiveDemux2Stream *) hls_stream;
2108
2109     if (hls_stream->current_segment)
2110       gst_m3u8_media_segment_unref (hls_stream->current_segment);
2111     hls_stream->current_segment = NULL;
2112
2113     if (hls_stream->is_variant) {
2114       GstHLSTimeMap *map;
2115       /* Resynchronize the variant stream */
2116       g_assert (stream->current_position != GST_CLOCK_STIME_NONE);
2117       hls_stream->current_segment =
2118           gst_hls_media_playlist_get_starting_segment (hls_stream->playlist);
2119       hls_stream->current_segment->stream_time = stream->current_position;
2120       gst_hls_media_playlist_recalculate_stream_time (hls_stream->playlist,
2121           hls_stream->current_segment);
2122       GST_DEBUG_OBJECT (stream,
2123           "Resynced variant playlist to %" GST_STIME_FORMAT,
2124           GST_STIME_ARGS (stream->current_position));
2125       map =
2126           gst_hls_find_time_map (hlsdemux,
2127           hls_stream->current_segment->discont_sequence);
2128       if (map)
2129         map->internal_time = GST_CLOCK_TIME_NONE;
2130       gst_hls_update_time_mappings (hlsdemux, hls_stream->playlist);
2131       gst_hls_media_playlist_dump (hls_stream->playlist);
2132     } else {
2133       /* Force playlist update for the rendition streams, it will resync to the
2134        * variant stream on the next round */
2135       if (hls_stream->playlist)
2136         gst_hls_media_playlist_unref (hls_stream->playlist);
2137       hls_stream->playlist = NULL;
2138       hls_stream->playlist_fetched = FALSE;
2139     }
2140   }
2141 }
2142
2143 static GstFlowReturn
2144 gst_hls_demux_stream_update_media_playlist (GstHLSDemux * demux,
2145     GstHLSDemuxStream * stream, gchar ** uri, GError ** err)
2146 {
2147   GstHLSMediaPlaylist *new_playlist;
2148
2149   GST_DEBUG_OBJECT (stream, "Updating %s", *uri);
2150
2151   new_playlist = download_media_playlist (demux, *uri, err, stream->playlist);
2152   if (new_playlist == NULL) {
2153     GST_WARNING_OBJECT (stream, "Could not get playlist '%s'", *uri);
2154     return GST_FLOW_ERROR;
2155   }
2156
2157   /* Check if a redirect happened */
2158   if (g_strcmp0 (*uri, new_playlist->uri)) {
2159     GST_DEBUG_OBJECT (stream, "Playlist URI update : '%s'  =>  '%s'", *uri,
2160         new_playlist->uri);
2161     g_free (*uri);
2162     *uri = g_strdup (new_playlist->uri);
2163   }
2164
2165   /* Synchronize playlist with previous one. If we can't update the playlist
2166    * timing and inform the base class that we lost sync */
2167   if (stream->playlist
2168       && !gst_hls_media_playlist_sync_to_playlist (new_playlist,
2169           stream->playlist)) {
2170     /* Failure to synchronize with the previous media playlist is only fatal for
2171      * variant streams. */
2172     if (stream->is_variant) {
2173       GST_DEBUG_OBJECT (stream,
2174           "Could not synchronize new variant playlist with previous one !");
2175       goto lost_sync;
2176     }
2177
2178     /* For rendition streams, we can attempt synchronization against the
2179      * variant playlist which is constantly updated */
2180     if (demux->main_stream->playlist
2181         && !gst_hls_media_playlist_sync_to_playlist (new_playlist,
2182             demux->main_stream->playlist)) {
2183       GST_DEBUG_OBJECT (stream,
2184           "Could not do fallback synchronization of rendition stream to variant stream");
2185       goto lost_sync;
2186     }
2187   } else if (!stream->is_variant && demux->main_stream->playlist) {
2188     /* For initial rendition media playlist, attempt to synchronize the playlist
2189      * against the variant stream. This is non-fatal if it fails. */
2190     GST_DEBUG_OBJECT (stream,
2191         "Attempting to synchronize initial rendition stream with variant stream");
2192     gst_hls_media_playlist_sync_to_playlist (new_playlist,
2193         demux->main_stream->playlist);
2194   }
2195
2196   if (stream->current_segment) {
2197     GstM3U8MediaSegment *new_segment;
2198     GST_DEBUG_OBJECT (stream,
2199         "Current segment sn:%" G_GINT64_FORMAT " stream_time:%" GST_STIME_FORMAT
2200         " uri:%s", stream->current_segment->sequence,
2201         GST_STIME_ARGS (stream->current_segment->stream_time),
2202         stream->current_segment->uri);
2203
2204     /* Use best-effort techniques to find the correponding current media segment
2205      * in the new playlist. This might be off in some cases, but it doesn't matter
2206      * since we will be checking the embedded timestamp later */
2207     new_segment =
2208         gst_hls_media_playlist_sync_to_segment (new_playlist,
2209         stream->current_segment);
2210     if (new_segment) {
2211       if (new_segment->discont_sequence !=
2212           stream->current_segment->discont_sequence)
2213         gst_hls_demux_add_time_mapping (demux, new_segment->discont_sequence,
2214             new_segment->stream_time, new_segment->datetime);
2215       /* This can happen in case of misaligned variants/renditions. Only warn about it */
2216       if (new_segment->stream_time != stream->current_segment->stream_time)
2217         GST_WARNING_OBJECT (stream,
2218             "Returned segment stream time %" GST_STIME_FORMAT
2219             " differs from current stream time %" GST_STIME_FORMAT,
2220             GST_STIME_ARGS (new_segment->stream_time),
2221             GST_STIME_ARGS (stream->current_segment->stream_time));
2222     } else {
2223       /* Not finding a matching segment only happens in live (otherwise we would
2224        * have found a match by stream time) when we are at the live edge. This is normal*/
2225       GST_DEBUG_OBJECT (stream, "Could not find a matching segment");
2226     }
2227     gst_m3u8_media_segment_unref (stream->current_segment);
2228     stream->current_segment = new_segment;
2229   } else {
2230     GST_DEBUG_OBJECT (stream, "No current segment");
2231   }
2232
2233   if (stream->playlist) {
2234     gst_hls_media_playlist_unref (stream->playlist);
2235     stream->playlist = new_playlist;
2236   } else {
2237     if (stream->is_variant) {
2238       GST_DEBUG_OBJECT (stream, "Setting up initial playlist");
2239       setup_initial_playlist (demux, new_playlist);
2240     }
2241     stream->playlist = new_playlist;
2242   }
2243
2244   if (stream->is_variant) {
2245     /* Update time mappings. We only use the variant stream for collecting
2246      * mappings since it is the reference on which rendition stream timing will
2247      * be based. */
2248     gst_hls_update_time_mappings (demux, stream->playlist);
2249   }
2250   gst_hls_media_playlist_dump (stream->playlist);
2251
2252   if (stream->current_segment) {
2253     GST_DEBUG_OBJECT (stream,
2254         "After update, current segment now sn:%" G_GINT64_FORMAT
2255         " stream_time:%" GST_STIME_FORMAT " uri:%s",
2256         stream->current_segment->sequence,
2257         GST_STIME_ARGS (stream->current_segment->stream_time),
2258         stream->current_segment->uri);
2259   } else {
2260     GST_DEBUG_OBJECT (stream, "No current segment selected");
2261   }
2262
2263   GST_DEBUG_OBJECT (stream, "done");
2264
2265   return GST_FLOW_OK;
2266
2267   /* ERRORS */
2268 lost_sync:
2269   {
2270     /* Set new playlist, lost sync handler will know what to do with it */
2271     if (stream->playlist)
2272       gst_hls_media_playlist_unref (stream->playlist);
2273     stream->playlist = new_playlist;
2274
2275     gst_hls_demux_reset_for_lost_sync (demux);
2276
2277     return GST_ADAPTIVE_DEMUX_FLOW_LOST_SYNC;
2278   }
2279 }
2280
2281 static GstFlowReturn
2282 gst_hls_demux_stream_update_rendition_playlist (GstHLSDemux * demux,
2283     GstHLSDemuxStream * stream)
2284 {
2285   GstFlowReturn ret = GST_FLOW_OK;
2286   GstHLSRenditionStream *target_rendition =
2287       stream->pending_rendition ? stream->
2288       pending_rendition : stream->current_rendition;
2289
2290   ret = gst_hls_demux_stream_update_media_playlist (demux, stream,
2291       &target_rendition->uri, NULL);
2292   if (ret != GST_FLOW_OK)
2293     return ret;
2294
2295   if (stream->pending_rendition) {
2296     gst_hls_rendition_stream_unref (stream->current_rendition);
2297     /* Stealing ref */
2298     stream->current_rendition = stream->pending_rendition;
2299     stream->pending_rendition = NULL;
2300   }
2301
2302   stream->playlist_fetched = TRUE;
2303
2304   return ret;
2305 }
2306
2307 static GstFlowReturn
2308 gst_hls_demux_stream_update_variant_playlist (GstHLSDemux * demux,
2309     GstHLSDemuxStream * stream, GError ** err)
2310 {
2311   GstFlowReturn ret = GST_FLOW_OK;
2312   GstHLSVariantStream *target_variant =
2313       demux->pending_variant ? demux->pending_variant : demux->current_variant;
2314
2315   ret = gst_hls_demux_stream_update_media_playlist (demux, stream,
2316       &target_variant->uri, err);
2317   if (ret != GST_FLOW_OK)
2318     return ret;
2319
2320   if (demux->pending_variant) {
2321     gst_hls_variant_stream_unref (demux->current_variant);
2322     /* Stealing ref */
2323     demux->current_variant = demux->pending_variant;
2324     demux->pending_variant = NULL;
2325   }
2326
2327   stream->playlist_fetched = TRUE;
2328
2329   return ret;
2330 }
2331
2332 static GstFlowReturn
2333 gst_hls_demux_update_fragment_info (GstAdaptiveDemux2Stream * stream)
2334 {
2335   GstFlowReturn ret = GST_FLOW_OK;
2336   GstHLSDemuxStream *hlsdemux_stream = GST_HLS_DEMUX_STREAM_CAST (stream);
2337   GstAdaptiveDemux *demux = stream->demux;
2338   GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (demux);
2339   GstM3U8MediaSegment *file;
2340   gboolean discont;
2341
2342   /* If the rendition playlist needs to be updated, do it now */
2343   if (!hlsdemux_stream->is_variant && !hlsdemux_stream->playlist_fetched) {
2344     ret = gst_hls_demux_stream_update_rendition_playlist (hlsdemux,
2345         hlsdemux_stream);
2346     if (ret != GST_FLOW_OK)
2347       return ret;
2348   }
2349
2350   GST_DEBUG_OBJECT (stream,
2351       "Updating fragment information, current_position:%" GST_TIME_FORMAT,
2352       GST_TIME_ARGS (stream->current_position));
2353
2354   /* Find the current segment if we don't already have it */
2355   if (hlsdemux_stream->current_segment == NULL) {
2356     GST_LOG_OBJECT (stream, "No current segment");
2357     if (stream->current_position == GST_CLOCK_TIME_NONE) {
2358       GST_DEBUG_OBJECT (stream, "Setting up initial segment");
2359       hlsdemux_stream->current_segment =
2360           gst_hls_media_playlist_get_starting_segment
2361           (hlsdemux_stream->playlist);
2362     } else {
2363       if (gst_hls_media_playlist_has_lost_sync (hlsdemux_stream->playlist,
2364               stream->current_position)) {
2365         GST_WARNING_OBJECT (stream, "Lost SYNC !");
2366         return GST_ADAPTIVE_DEMUX_FLOW_LOST_SYNC;
2367       }
2368       GST_DEBUG_OBJECT (stream,
2369           "Looking up segment for position %" GST_TIME_FORMAT,
2370           GST_TIME_ARGS (stream->current_position));
2371       hlsdemux_stream->current_segment =
2372           gst_hls_media_playlist_seek (hlsdemux_stream->playlist, TRUE,
2373           GST_SEEK_FLAG_SNAP_NEAREST, stream->current_position);
2374
2375       if (hlsdemux_stream->current_segment == NULL) {
2376         GST_INFO_OBJECT (stream, "At the end of the current media playlist");
2377         return GST_FLOW_EOS;
2378       }
2379
2380       /* Update time mapping. If it already exists it will be ignored */
2381       gst_hls_demux_add_time_mapping (hlsdemux,
2382           hlsdemux_stream->current_segment->discont_sequence,
2383           hlsdemux_stream->current_segment->stream_time,
2384           hlsdemux_stream->current_segment->datetime);
2385     }
2386   }
2387
2388   file = hlsdemux_stream->current_segment;
2389
2390   GST_DEBUG_OBJECT (stream, "Current segment stream_time %" GST_STIME_FORMAT,
2391       GST_STIME_ARGS (file->stream_time));
2392
2393   discont = file->discont || stream->discont;
2394
2395   gboolean need_header = GST_ADAPTIVE_DEMUX2_STREAM_NEED_HEADER (stream);
2396
2397   /* Check if the MAP header file changed and update it */
2398   if (file->init_file != NULL
2399       && !gst_m3u8_init_file_equal (hlsdemux_stream->init_file,
2400           file->init_file)) {
2401     GST_DEBUG_OBJECT (stream, "MAP header info changed. Updating");
2402     if (hlsdemux_stream->init_file != NULL)
2403       gst_m3u8_init_file_unref (hlsdemux_stream->init_file);
2404     hlsdemux_stream->init_file = gst_m3u8_init_file_ref (file->init_file);
2405     need_header = TRUE;
2406   }
2407
2408   if (file->init_file && need_header) {
2409     GstM3U8InitFile *header_file = file->init_file;
2410     g_free (stream->fragment.header_uri);
2411     stream->fragment.header_uri = g_strdup (header_file->uri);
2412     stream->fragment.header_range_start = header_file->offset;
2413     if (header_file->size != -1) {
2414       stream->fragment.header_range_end =
2415           header_file->offset + header_file->size - 1;
2416     } else {
2417       stream->fragment.header_range_end = -1;
2418     }
2419
2420     stream->need_header = TRUE;
2421   }
2422
2423   /* set up our source for download */
2424   if (hlsdemux_stream->reset_pts || discont || demux->segment.rate < 0.0) {
2425     stream->fragment.stream_time = file->stream_time;
2426   } else {
2427     stream->fragment.stream_time = GST_CLOCK_STIME_NONE;
2428   }
2429
2430   g_free (hlsdemux_stream->current_key);
2431   hlsdemux_stream->current_key = g_strdup (file->key);
2432   g_free (hlsdemux_stream->current_iv);
2433   hlsdemux_stream->current_iv = g_memdup2 (file->iv, sizeof (file->iv));
2434
2435   g_free (stream->fragment.uri);
2436   stream->fragment.uri = g_strdup (file->uri);
2437
2438   GST_DEBUG_OBJECT (stream, "Stream URI now %s", file->uri);
2439
2440   stream->fragment.range_start = file->offset;
2441   if (file->size != -1)
2442     stream->fragment.range_end = file->offset + file->size - 1;
2443   else
2444     stream->fragment.range_end = -1;
2445
2446   stream->fragment.duration = file->duration;
2447
2448   stream->recommended_buffering_threshold =
2449       gst_hls_media_playlist_recommended_buffering_threshold
2450       (hlsdemux_stream->playlist);
2451
2452   if (discont)
2453     stream->discont = TRUE;
2454
2455   return ret;
2456 }
2457
2458 static gboolean
2459 gst_hls_demux_stream_can_start (GstAdaptiveDemux * demux,
2460     GstAdaptiveDemux2Stream * stream)
2461 {
2462   GstHLSDemux *hlsdemux = (GstHLSDemux *) demux;
2463   GstHLSDemuxStream *hls_stream = (GstHLSDemuxStream *) stream;
2464   GList *tmp;
2465
2466   GST_DEBUG_OBJECT (demux, "is_variant:%d mappings:%p", hls_stream->is_variant,
2467       hlsdemux->mappings);
2468
2469   /* Variant streams can always start straight away */
2470   if (hls_stream->is_variant)
2471     return TRUE;
2472
2473   /* Renditions of the exact same type as the variant are pure alternatives,
2474    * they must be started. This can happen for example with audio-only manifests
2475    * where the initial stream selected is a rendition and not a variant */
2476   if (hls_stream->rendition_type == hlsdemux->main_stream->rendition_type)
2477     return TRUE;
2478
2479   /* Rendition streams only require delaying if we don't have time mappings yet */
2480   if (!hlsdemux->mappings)
2481     return FALSE;
2482
2483   /* We can start if we have at least one internal time observation */
2484   for (tmp = hlsdemux->mappings; tmp; tmp = tmp->next) {
2485     GstHLSTimeMap *map = tmp->data;
2486     if (map->internal_time != GST_CLOCK_TIME_NONE)
2487       return TRUE;
2488   }
2489
2490   /* Otherwise we have to wait */
2491   return FALSE;
2492 }
2493
2494 /* Returns TRUE if the rendition stream switched group-id */
2495 static gboolean
2496 gst_hls_demux_update_rendition_stream (GstHLSDemux * hlsdemux,
2497     GstHLSDemuxStream * hls_stream, GError ** err)
2498 {
2499   gchar *current_group_id, *requested_group_id;
2500   GstHLSRenditionStream *replacement_media = NULL;
2501   GList *tmp;
2502
2503   /* There always should be a current variant set */
2504   g_assert (hlsdemux->current_variant);
2505   /* There always is a GstHLSRenditionStream set for rendition streams */
2506   g_assert (hls_stream->current_rendition);
2507
2508   requested_group_id =
2509       hlsdemux->current_variant->media_groups[hls_stream->
2510       current_rendition->mtype];
2511   current_group_id = hls_stream->current_rendition->group_id;
2512
2513   GST_DEBUG_OBJECT (hlsdemux,
2514       "Checking playlist change for variant stream %s lang: %s current group-id: %s / requested group-id: %s",
2515       gst_stream_type_get_name (hls_stream->rendition_type), hls_stream->lang,
2516       current_group_id, requested_group_id);
2517
2518
2519   if (!g_strcmp0 (requested_group_id, current_group_id)) {
2520     GST_DEBUG_OBJECT (hlsdemux, "No change needed");
2521     return FALSE;
2522   }
2523
2524   GST_DEBUG_OBJECT (hlsdemux,
2525       "group-id changed, looking for replacement playlist");
2526
2527   /* Need to switch/update */
2528   for (tmp = hlsdemux->master->renditions; tmp; tmp = tmp->next) {
2529     GstHLSRenditionStream *cand = tmp->data;
2530
2531     if (cand->mtype == hls_stream->current_rendition->mtype
2532         && !g_strcmp0 (cand->lang, hls_stream->lang)
2533         && !g_strcmp0 (cand->group_id, requested_group_id)) {
2534       replacement_media = cand;
2535       break;
2536     }
2537   }
2538   if (!replacement_media) {
2539     GST_ERROR_OBJECT (hlsdemux,
2540         "Could not find a replacement playlist. Staying with previous one");
2541     return FALSE;
2542   }
2543
2544   GST_DEBUG_OBJECT (hlsdemux, "Use replacement playlist %s",
2545       replacement_media->name);
2546   hls_stream->playlist_fetched = FALSE;
2547   if (hls_stream->pending_rendition) {
2548     GST_ERROR_OBJECT (hlsdemux,
2549         "Already had a pending rendition switch to '%s'",
2550         hls_stream->pending_rendition->name);
2551     gst_hls_rendition_stream_unref (hls_stream->pending_rendition);
2552   }
2553   hls_stream->pending_rendition =
2554       gst_hls_rendition_stream_ref (replacement_media);
2555   return TRUE;
2556 }
2557
2558 static gboolean
2559 gst_hls_demux_select_bitrate (GstAdaptiveDemux2Stream * stream, guint64 bitrate)
2560 {
2561   GstAdaptiveDemux *demux = GST_ADAPTIVE_DEMUX_CAST (stream->demux);
2562   GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (stream->demux);
2563   GstHLSDemuxStream *hls_stream = GST_HLS_DEMUX_STREAM_CAST (stream);
2564
2565   /* Fast-Path, no changes possible */
2566   if (hlsdemux->master == NULL || hlsdemux->master->is_simple)
2567     return FALSE;
2568
2569   if (hls_stream->is_variant) {
2570     gdouble play_rate = gst_adaptive_demux_play_rate (demux);
2571     gboolean changed = FALSE;
2572
2573     /* Handle variant streams */
2574     GST_DEBUG_OBJECT (hlsdemux,
2575         "Checking playlist change for main variant stream");
2576     gst_hls_demux_change_playlist (hlsdemux, bitrate / MAX (1.0,
2577             ABS (play_rate)), &changed);
2578
2579     GST_DEBUG_OBJECT (hlsdemux, "Returning changed: %d", changed);
2580     return changed;
2581   }
2582
2583   /* Handle rendition streams */
2584   return gst_hls_demux_update_rendition_stream (hlsdemux, hls_stream, NULL);
2585 }
2586
2587 static void
2588 gst_hls_demux_reset (GstAdaptiveDemux * ademux)
2589 {
2590   GstHLSDemux *demux = GST_HLS_DEMUX_CAST (ademux);
2591
2592   GST_DEBUG_OBJECT (demux, "resetting");
2593
2594   if (demux->master) {
2595     gst_hls_master_playlist_unref (demux->master);
2596     demux->master = NULL;
2597   }
2598   if (demux->current_variant != NULL) {
2599     gst_hls_variant_stream_unref (demux->current_variant);
2600     demux->current_variant = NULL;
2601   }
2602   if (demux->pending_variant != NULL) {
2603     gst_hls_variant_stream_unref (demux->pending_variant);
2604     demux->pending_variant = NULL;
2605   }
2606
2607   g_list_free_full (demux->mappings, (GDestroyNotify) gst_hls_time_map_free);
2608   demux->mappings = NULL;
2609
2610   gst_hls_demux_clear_all_pending_data (demux);
2611 }
2612
2613 /*
2614  * update: TRUE only when requested from parent class (via
2615  * ::demux_update_manifest() or ::change_playlist() ).
2616  */
2617 static GstFlowReturn
2618 gst_hls_demux_update_playlist (GstHLSDemux * demux, gboolean update,
2619     GError ** err)
2620 {
2621   GstFlowReturn ret = GST_FLOW_OK;
2622   GstAdaptiveDemux *adaptive_demux = GST_ADAPTIVE_DEMUX (demux);
2623
2624   GST_DEBUG_OBJECT (demux, "update:%d", update);
2625
2626   /* Download and update the appropriate variant playlist (pending if any, else
2627    * current) */
2628   ret = gst_hls_demux_stream_update_variant_playlist (demux, demux->main_stream,
2629       err);
2630   if (ret != GST_FLOW_OK)
2631     return ret;
2632
2633   if (update && gst_hls_demux_is_live (adaptive_demux)) {
2634     GList *tmp;
2635     GST_DEBUG_OBJECT (demux,
2636         "LIVE, Marking rendition streams to be updated next");
2637     /* We're live, instruct all rendition medias to be updated next */
2638     for (tmp = adaptive_demux->input_period->streams; tmp; tmp = tmp->next) {
2639       GstHLSDemuxStream *hls_stream = tmp->data;
2640       if (!hls_stream->is_variant)
2641         hls_stream->playlist_fetched = FALSE;
2642     }
2643   }
2644
2645   return GST_FLOW_OK;
2646 }
2647
2648 static gboolean
2649 gst_hls_demux_change_playlist (GstHLSDemux * demux, guint max_bitrate,
2650     gboolean * changed)
2651 {
2652   GstHLSVariantStream *lowest_variant, *lowest_ivariant;
2653   GstHLSVariantStream *previous_variant, *new_variant;
2654   gint old_bandwidth, new_bandwidth;
2655   GstAdaptiveDemux *adaptive_demux = GST_ADAPTIVE_DEMUX_CAST (demux);
2656   GstAdaptiveDemux2Stream *stream;
2657
2658   g_return_val_if_fail (demux->main_stream != NULL, FALSE);
2659   stream = (GstAdaptiveDemux2Stream *) demux->main_stream;
2660
2661   /* Make sure we keep a reference in case we need to switch back */
2662   previous_variant = gst_hls_variant_stream_ref (demux->current_variant);
2663   new_variant =
2664       gst_hls_master_playlist_get_variant_for_bitrate (demux->master,
2665       demux->current_variant, max_bitrate, adaptive_demux->min_bitrate);
2666
2667 retry_failover_protection:
2668   old_bandwidth = previous_variant->bandwidth;
2669   new_bandwidth = new_variant->bandwidth;
2670
2671   /* Don't do anything else if the playlist is the same */
2672   if (new_bandwidth == old_bandwidth) {
2673     gst_hls_variant_stream_unref (previous_variant);
2674     return TRUE;
2675   }
2676
2677   gst_hls_demux_set_current_variant (demux, new_variant);
2678
2679   GST_INFO_OBJECT (demux, "Client was on %dbps, max allowed is %dbps, switching"
2680       " to bitrate %dbps", old_bandwidth, max_bitrate, new_bandwidth);
2681
2682   if (gst_hls_demux_update_playlist (demux, TRUE, NULL) == GST_FLOW_OK) {
2683     const gchar *main_uri;
2684     gchar *uri = new_variant->uri;
2685
2686     main_uri = gst_adaptive_demux_get_manifest_ref_uri (adaptive_demux);
2687     gst_element_post_message (GST_ELEMENT_CAST (demux),
2688         gst_message_new_element (GST_OBJECT_CAST (demux),
2689             gst_structure_new (GST_ADAPTIVE_DEMUX_STATISTICS_MESSAGE_NAME,
2690                 "manifest-uri", G_TYPE_STRING,
2691                 main_uri, "uri", G_TYPE_STRING,
2692                 uri, "bitrate", G_TYPE_INT, new_bandwidth, NULL)));
2693     if (changed)
2694       *changed = TRUE;
2695     stream->discont = TRUE;
2696   } else if (gst_adaptive_demux2_is_running (GST_ADAPTIVE_DEMUX_CAST (demux))) {
2697     GstHLSVariantStream *failover_variant = NULL;
2698     GList *failover;
2699
2700     GST_INFO_OBJECT (demux, "Unable to update playlist. Switching back");
2701
2702     /* we find variants by bitrate by going from highest to lowest, so it's
2703      * possible that there's another variant with the same bitrate before the
2704      * one selected which we can use as failover */
2705     failover = g_list_find (demux->master->variants, new_variant);
2706     if (failover != NULL)
2707       failover = failover->prev;
2708     if (failover != NULL)
2709       failover_variant = failover->data;
2710     if (failover_variant && new_bandwidth == failover_variant->bandwidth) {
2711       new_variant = failover_variant;
2712       goto retry_failover_protection;
2713     }
2714
2715     gst_hls_demux_set_current_variant (demux, previous_variant);
2716
2717     /*  Try a lower bitrate (or stop if we just tried the lowest) */
2718     if (previous_variant->iframe) {
2719       lowest_ivariant = demux->master->iframe_variants->data;
2720       if (new_bandwidth == lowest_ivariant->bandwidth) {
2721         gst_hls_variant_stream_unref (previous_variant);
2722         return FALSE;
2723       }
2724     } else {
2725       lowest_variant = demux->master->variants->data;
2726       if (new_bandwidth == lowest_variant->bandwidth) {
2727         gst_hls_variant_stream_unref (previous_variant);
2728         return FALSE;
2729       }
2730     }
2731     gst_hls_variant_stream_unref (previous_variant);
2732     return gst_hls_demux_change_playlist (demux, new_bandwidth - 1, changed);
2733   }
2734
2735   gst_hls_variant_stream_unref (previous_variant);
2736   return TRUE;
2737 }
2738
2739 #if defined(HAVE_OPENSSL)
2740 static gboolean
2741 gst_hls_demux_stream_decrypt_start (GstHLSDemuxStream * stream,
2742     const guint8 * key_data, const guint8 * iv_data)
2743 {
2744   EVP_CIPHER_CTX *ctx;
2745 #if OPENSSL_VERSION_NUMBER < 0x10100000L
2746   EVP_CIPHER_CTX_init (&stream->aes_ctx);
2747   ctx = &stream->aes_ctx;
2748 #else
2749   stream->aes_ctx = EVP_CIPHER_CTX_new ();
2750   ctx = stream->aes_ctx;
2751 #endif
2752   if (!EVP_DecryptInit_ex (ctx, EVP_aes_128_cbc (), NULL, key_data, iv_data))
2753     return FALSE;
2754   EVP_CIPHER_CTX_set_padding (ctx, 0);
2755   return TRUE;
2756 }
2757
2758 static gboolean
2759 decrypt_fragment (GstHLSDemuxStream * stream, gsize length,
2760     const guint8 * encrypted_data, guint8 * decrypted_data)
2761 {
2762   int len, flen = 0;
2763   EVP_CIPHER_CTX *ctx;
2764
2765 #if OPENSSL_VERSION_NUMBER < 0x10100000L
2766   ctx = &stream->aes_ctx;
2767 #else
2768   ctx = stream->aes_ctx;
2769 #endif
2770
2771   if (G_UNLIKELY (length > G_MAXINT || length % 16 != 0))
2772     return FALSE;
2773
2774   len = (int) length;
2775   if (!EVP_DecryptUpdate (ctx, decrypted_data, &len, encrypted_data, len))
2776     return FALSE;
2777   EVP_DecryptFinal_ex (ctx, decrypted_data + len, &flen);
2778   g_return_val_if_fail (len + flen == length, FALSE);
2779   return TRUE;
2780 }
2781
2782 static void
2783 gst_hls_demux_stream_decrypt_end (GstHLSDemuxStream * stream)
2784 {
2785 #if OPENSSL_VERSION_NUMBER < 0x10100000L
2786   EVP_CIPHER_CTX_cleanup (&stream->aes_ctx);
2787 #else
2788   EVP_CIPHER_CTX_free (stream->aes_ctx);
2789   stream->aes_ctx = NULL;
2790 #endif
2791 }
2792
2793 #elif defined(HAVE_NETTLE)
2794 static gboolean
2795 gst_hls_demux_stream_decrypt_start (GstHLSDemuxStream * stream,
2796     const guint8 * key_data, const guint8 * iv_data)
2797 {
2798   aes128_set_decrypt_key (&stream->aes_ctx.ctx, key_data);
2799   CBC_SET_IV (&stream->aes_ctx, iv_data);
2800
2801   return TRUE;
2802 }
2803
2804 static gboolean
2805 decrypt_fragment (GstHLSDemuxStream * stream, gsize length,
2806     const guint8 * encrypted_data, guint8 * decrypted_data)
2807 {
2808   if (length % 16 != 0)
2809     return FALSE;
2810
2811   CBC_DECRYPT (&stream->aes_ctx, aes128_decrypt, length, decrypted_data,
2812       encrypted_data);
2813
2814   return TRUE;
2815 }
2816
2817 static void
2818 gst_hls_demux_stream_decrypt_end (GstHLSDemuxStream * stream)
2819 {
2820   /* NOP */
2821 }
2822
2823 #elif defined(HAVE_LIBGCRYPT)
2824 static gboolean
2825 gst_hls_demux_stream_decrypt_start (GstHLSDemuxStream * stream,
2826     const guint8 * key_data, const guint8 * iv_data)
2827 {
2828   gcry_error_t err = 0;
2829   gboolean ret = FALSE;
2830
2831   err =
2832       gcry_cipher_open (&stream->aes_ctx, GCRY_CIPHER_AES128,
2833       GCRY_CIPHER_MODE_CBC, 0);
2834   if (err)
2835     goto out;
2836   err = gcry_cipher_setkey (stream->aes_ctx, key_data, 16);
2837   if (err)
2838     goto out;
2839   err = gcry_cipher_setiv (stream->aes_ctx, iv_data, 16);
2840   if (!err)
2841     ret = TRUE;
2842
2843 out:
2844   if (!ret)
2845     if (stream->aes_ctx)
2846       gcry_cipher_close (stream->aes_ctx);
2847
2848   return ret;
2849 }
2850
2851 static gboolean
2852 decrypt_fragment (GstHLSDemuxStream * stream, gsize length,
2853     const guint8 * encrypted_data, guint8 * decrypted_data)
2854 {
2855   gcry_error_t err = 0;
2856
2857   err = gcry_cipher_decrypt (stream->aes_ctx, decrypted_data, length,
2858       encrypted_data, length);
2859
2860   return err == 0;
2861 }
2862
2863 static void
2864 gst_hls_demux_stream_decrypt_end (GstHLSDemuxStream * stream)
2865 {
2866   if (stream->aes_ctx) {
2867     gcry_cipher_close (stream->aes_ctx);
2868     stream->aes_ctx = NULL;
2869   }
2870 }
2871
2872 #else
2873 /* NO crypto available */
2874 static gboolean
2875 gst_hls_demux_stream_decrypt_start (GstHLSDemuxStream * stream,
2876     const guint8 * key_data, const guint8 * iv_data)
2877 {
2878   GST_ERROR ("No crypto available");
2879   return FALSE;
2880 }
2881
2882 static gboolean
2883 decrypt_fragment (GstHLSDemuxStream * stream, gsize length,
2884     const guint8 * encrypted_data, guint8 * decrypted_data)
2885 {
2886   GST_ERROR ("Cannot decrypt fragment, no crypto available");
2887   return FALSE;
2888 }
2889
2890 static void
2891 gst_hls_demux_stream_decrypt_end (GstHLSDemuxStream * stream)
2892 {
2893   return;
2894 }
2895 #endif
2896
2897 static GstBuffer *
2898 gst_hls_demux_decrypt_fragment (GstHLSDemux * demux, GstHLSDemuxStream * stream,
2899     GstBuffer * encrypted_buffer, GError ** err)
2900 {
2901   GstBuffer *decrypted_buffer = NULL;
2902   GstMapInfo encrypted_info, decrypted_info;
2903
2904   decrypted_buffer =
2905       gst_buffer_new_allocate (NULL, gst_buffer_get_size (encrypted_buffer),
2906       NULL);
2907
2908   gst_buffer_map (encrypted_buffer, &encrypted_info, GST_MAP_READ);
2909   gst_buffer_map (decrypted_buffer, &decrypted_info, GST_MAP_WRITE);
2910
2911   if (!decrypt_fragment (stream, encrypted_info.size,
2912           encrypted_info.data, decrypted_info.data))
2913     goto decrypt_error;
2914
2915
2916   gst_buffer_unmap (decrypted_buffer, &decrypted_info);
2917   gst_buffer_unmap (encrypted_buffer, &encrypted_info);
2918
2919   gst_buffer_unref (encrypted_buffer);
2920
2921   return decrypted_buffer;
2922
2923 decrypt_error:
2924   GST_ERROR_OBJECT (demux, "Failed to decrypt fragment");
2925   g_set_error (err, GST_STREAM_ERROR, GST_STREAM_ERROR_DECRYPT,
2926       "Failed to decrypt fragment");
2927
2928   gst_buffer_unmap (decrypted_buffer, &decrypted_info);
2929   gst_buffer_unmap (encrypted_buffer, &encrypted_info);
2930
2931   gst_buffer_unref (encrypted_buffer);
2932   gst_buffer_unref (decrypted_buffer);
2933
2934   return NULL;
2935 }
2936
2937 static gint64
2938 gst_hls_demux_get_manifest_update_interval (GstAdaptiveDemux * demux)
2939 {
2940   GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (demux);
2941   GstClockTime target_duration = 5 * GST_SECOND;
2942
2943   if (hlsdemux->main_stream && hlsdemux->main_stream->playlist) {
2944     GstHLSMediaPlaylist *playlist = hlsdemux->main_stream->playlist;
2945
2946     if (playlist->version > 5) {
2947       target_duration = hlsdemux->main_stream->playlist->targetduration;
2948     } else if (playlist->segments->len) {
2949       GstM3U8MediaSegment *last_seg =
2950           g_ptr_array_index (playlist->segments, playlist->segments->len - 1);
2951       target_duration = last_seg->duration;
2952     }
2953     if (playlist->reloaded && target_duration > (playlist->targetduration / 2)) {
2954       GST_DEBUG_OBJECT (demux,
2955           "Playlist didn't change previously, returning lower update interval");
2956       target_duration /= 2;
2957     }
2958   }
2959
2960   GST_DEBUG_OBJECT (demux, "Returning update interval of %" GST_TIME_FORMAT,
2961       GST_TIME_ARGS (target_duration));
2962
2963   return gst_util_uint64_scale (target_duration, G_USEC_PER_SEC, GST_SECOND);
2964 }
2965
2966 static GstClockTime
2967 gst_hls_demux_get_presentation_offset (GstAdaptiveDemux * demux,
2968     GstAdaptiveDemux2Stream * stream)
2969 {
2970   GstHLSDemux *hlsdemux = (GstHLSDemux *) demux;
2971   GstHLSDemuxStream *hls_stream = (GstHLSDemuxStream *) stream;
2972
2973   GST_DEBUG_OBJECT (stream, "presentation_offset %" GST_TIME_FORMAT,
2974       GST_TIME_ARGS (hls_stream->presentation_offset));
2975
2976   /* If this stream and the variant stream are ISOBMFF, returns the presentation
2977    * offset of the variant stream */
2978   if (hls_stream->parser_type == GST_HLS_PARSER_ISOBMFF
2979       && hlsdemux->main_stream->parser_type == GST_HLS_PARSER_ISOBMFF)
2980     return hlsdemux->main_stream->presentation_offset;
2981   return hls_stream->presentation_offset;
2982 }
2983
2984 static gboolean
2985 gst_hls_demux_get_live_seek_range (GstAdaptiveDemux * demux, gint64 * start,
2986     gint64 * stop)
2987 {
2988   GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (demux);
2989   gboolean ret = FALSE;
2990
2991   if (hlsdemux->main_stream && hlsdemux->main_stream->playlist)
2992     ret =
2993         gst_hls_media_playlist_get_seek_range (hlsdemux->main_stream->playlist,
2994         start, stop);
2995
2996   return ret;
2997 }
2998
2999 static gboolean
3000 hlsdemux2_element_init (GstPlugin * plugin)
3001 {
3002   gboolean ret = TRUE;
3003
3004   GST_DEBUG_CATEGORY_INIT (gst_hls_demux2_debug, "hlsdemux2", 0,
3005       "hlsdemux2 element");
3006
3007   if (!adaptivedemux2_base_element_init (plugin))
3008     return TRUE;
3009
3010   ret = gst_element_register (plugin, "hlsdemux2",
3011       GST_RANK_PRIMARY + 1, GST_TYPE_HLS_DEMUX2);
3012
3013   return ret;
3014 }