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