adaptivedemux: Get rid of internal stream adapter and let subclasses handle this...
[platform/upstream/gstreamer.git] / ext / 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  *
9  * Gsthlsdemux.c:
10  *
11  * This library is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Library General Public
13  * License as published by the Free Software Foundation; either
14  * version 2 of the License, or (at your option) any later version.
15  *
16  * This library is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  * Library General Public License for more details.
20  *
21  * You should have received a copy of the GNU Library General Public
22  * License along with this library; if not, write to the
23  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
24  * Boston, MA 02110-1301, USA.
25  */
26 /**
27  * SECTION:element-hlsdemux
28  *
29  * HTTP Live Streaming demuxer element.
30  *
31  * <refsect2>
32  * <title>Example launch line</title>
33  * |[
34  * gst-launch-1.0 souphttpsrc location=http://devimages.apple.com/iphone/samples/bipbop/gear4/prog_index.m3u8 ! hlsdemux ! decodebin ! videoconvert ! videoscale ! autovideosink
35  * ]|
36  * </refsect2>
37  */
38
39 #ifdef HAVE_CONFIG_H
40 #  include "config.h"
41 #endif
42
43 #include <string.h>
44 #include <gst/base/gsttypefindhelper.h>
45 #include "gsthlsdemux.h"
46
47 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src_%u",
48     GST_PAD_SRC,
49     GST_PAD_SOMETIMES,
50     GST_STATIC_CAPS_ANY);
51
52 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
53     GST_PAD_SINK,
54     GST_PAD_ALWAYS,
55     GST_STATIC_CAPS ("application/x-hls"));
56
57 GST_DEBUG_CATEGORY_STATIC (gst_hls_demux_debug);
58 #define GST_CAT_DEFAULT gst_hls_demux_debug
59
60 /* GObject */
61 static void gst_hls_demux_finalize (GObject * obj);
62
63 /* GstElement */
64 static GstStateChangeReturn
65 gst_hls_demux_change_state (GstElement * element, GstStateChange transition);
66
67 /* GstHLSDemux */
68 static gboolean gst_hls_demux_update_playlist (GstHLSDemux * demux,
69     gboolean update, GError ** err);
70 static gchar *gst_hls_src_buf_to_utf8_playlist (GstBuffer * buf);
71
72 static gboolean gst_hls_demux_change_playlist (GstHLSDemux * demux,
73     guint max_bitrate, gboolean * changed);
74 static GstBuffer *gst_hls_demux_decrypt_fragment (GstHLSDemux * demux,
75     GstBuffer * encrypted_buffer, GError ** err);
76 static gboolean
77 gst_hls_demux_decrypt_start (GstHLSDemux * demux, const guint8 * key_data,
78     const guint8 * iv_data);
79 static void gst_hls_demux_decrypt_end (GstHLSDemux * demux);
80
81 static gboolean gst_hls_demux_is_live (GstAdaptiveDemux * demux);
82 static GstClockTime gst_hls_demux_get_duration (GstAdaptiveDemux * demux);
83 static gint64 gst_hls_demux_get_manifest_update_interval (GstAdaptiveDemux *
84     demux);
85 static gboolean gst_hls_demux_process_manifest (GstAdaptiveDemux * demux,
86     GstBuffer * buf);
87 static GstFlowReturn gst_hls_demux_update_manifest (GstAdaptiveDemux * demux);
88 static gboolean gst_hls_demux_seek (GstAdaptiveDemux * demux, GstEvent * seek);
89 static gboolean
90 gst_hls_demux_start_fragment (GstAdaptiveDemux * demux,
91     GstAdaptiveDemuxStream * stream);
92 static GstFlowReturn gst_hls_demux_finish_fragment (GstAdaptiveDemux * demux,
93     GstAdaptiveDemuxStream * stream);
94 static GstFlowReturn gst_hls_demux_data_received (GstAdaptiveDemux * demux,
95     GstAdaptiveDemuxStream * stream, GstBuffer * buffer);
96 static gboolean gst_hls_demux_stream_has_next_fragment (GstAdaptiveDemuxStream *
97     stream);
98 static GstFlowReturn gst_hls_demux_advance_fragment (GstAdaptiveDemuxStream *
99     stream);
100 static GstFlowReturn gst_hls_demux_update_fragment_info (GstAdaptiveDemuxStream
101     * stream);
102 static gboolean gst_hls_demux_select_bitrate (GstAdaptiveDemuxStream * stream,
103     guint64 bitrate);
104 static void gst_hls_demux_reset (GstAdaptiveDemux * demux);
105 static gboolean gst_hls_demux_get_live_seek_range (GstAdaptiveDemux * demux,
106     gint64 * start, gint64 * stop);
107
108 #define gst_hls_demux_parent_class parent_class
109 G_DEFINE_TYPE (GstHLSDemux, gst_hls_demux, GST_TYPE_ADAPTIVE_DEMUX);
110
111 static void
112 gst_hls_demux_finalize (GObject * obj)
113 {
114   GstHLSDemux *demux = GST_HLS_DEMUX (obj);
115
116   gst_hls_demux_reset (GST_ADAPTIVE_DEMUX_CAST (demux));
117   g_object_unref (demux->pending_encrypted_data);
118   gst_m3u8_client_free (demux->client);
119
120   G_OBJECT_CLASS (parent_class)->finalize (obj);
121 }
122
123 static void
124 gst_hls_demux_class_init (GstHLSDemuxClass * klass)
125 {
126   GObjectClass *gobject_class;
127   GstElementClass *element_class;
128   GstAdaptiveDemuxClass *adaptivedemux_class;
129
130   gobject_class = (GObjectClass *) klass;
131   element_class = (GstElementClass *) klass;
132   adaptivedemux_class = (GstAdaptiveDemuxClass *) klass;
133
134   gobject_class->finalize = gst_hls_demux_finalize;
135
136   element_class->change_state = GST_DEBUG_FUNCPTR (gst_hls_demux_change_state);
137
138   gst_element_class_add_static_pad_template (element_class, &srctemplate);
139   gst_element_class_add_static_pad_template (element_class, &sinktemplate);
140
141   gst_element_class_set_static_metadata (element_class,
142       "HLS Demuxer",
143       "Codec/Demuxer/Adaptive",
144       "HTTP Live Streaming demuxer",
145       "Marc-Andre Lureau <marcandre.lureau@gmail.com>\n"
146       "Andoni Morales Alastruey <ylatuya@gmail.com>");
147
148   adaptivedemux_class->is_live = gst_hls_demux_is_live;
149   adaptivedemux_class->get_live_seek_range = gst_hls_demux_get_live_seek_range;
150   adaptivedemux_class->get_duration = gst_hls_demux_get_duration;
151   adaptivedemux_class->get_manifest_update_interval =
152       gst_hls_demux_get_manifest_update_interval;
153   adaptivedemux_class->process_manifest = gst_hls_demux_process_manifest;
154   adaptivedemux_class->update_manifest = gst_hls_demux_update_manifest;
155   adaptivedemux_class->reset = gst_hls_demux_reset;
156   adaptivedemux_class->seek = gst_hls_demux_seek;
157   adaptivedemux_class->stream_has_next_fragment =
158       gst_hls_demux_stream_has_next_fragment;
159   adaptivedemux_class->stream_advance_fragment = gst_hls_demux_advance_fragment;
160   adaptivedemux_class->stream_update_fragment_info =
161       gst_hls_demux_update_fragment_info;
162   adaptivedemux_class->stream_select_bitrate = gst_hls_demux_select_bitrate;
163
164   adaptivedemux_class->start_fragment = gst_hls_demux_start_fragment;
165   adaptivedemux_class->finish_fragment = gst_hls_demux_finish_fragment;
166   adaptivedemux_class->data_received = gst_hls_demux_data_received;
167
168   GST_DEBUG_CATEGORY_INIT (gst_hls_demux_debug, "hlsdemux", 0,
169       "hlsdemux element");
170 }
171
172 static void
173 gst_hls_demux_init (GstHLSDemux * demux)
174 {
175   demux->do_typefind = TRUE;
176   demux->pending_encrypted_data = gst_adapter_new ();
177 }
178
179 static GstStateChangeReturn
180 gst_hls_demux_change_state (GstElement * element, GstStateChange transition)
181 {
182   GstStateChangeReturn ret;
183   GstHLSDemux *demux = GST_HLS_DEMUX (element);
184
185   switch (transition) {
186     case GST_STATE_CHANGE_READY_TO_PAUSED:
187       gst_hls_demux_reset (GST_ADAPTIVE_DEMUX_CAST (demux));
188       break;
189     default:
190       break;
191   }
192
193   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
194
195   switch (transition) {
196     case GST_STATE_CHANGE_PAUSED_TO_READY:
197       gst_hls_demux_reset (GST_ADAPTIVE_DEMUX_CAST (demux));
198       break;
199     default:
200       break;
201   }
202   return ret;
203 }
204
205 static GstPad *
206 gst_hls_demux_create_pad (GstHLSDemux * hlsdemux)
207 {
208   gchar *name;
209   GstPad *pad;
210
211   name = g_strdup_printf ("src_%u", hlsdemux->srcpad_counter++);
212   pad = gst_pad_new_from_static_template (&srctemplate, name);
213   g_free (name);
214
215   return pad;
216 }
217
218 static guint64
219 gst_hls_demux_get_bitrate (GstHLSDemux * hlsdemux)
220 {
221   GstAdaptiveDemux *demux = GST_ADAPTIVE_DEMUX_CAST (hlsdemux);
222
223   /* Valid because hlsdemux only has a single output */
224   if (demux->streams) {
225     GstAdaptiveDemuxStream *stream = demux->streams->data;
226     return stream->current_download_rate;
227   }
228
229   return 0;
230 }
231
232 static gboolean
233 gst_hls_demux_seek (GstAdaptiveDemux * demux, GstEvent * seek)
234 {
235   GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (demux);
236   GstFormat format;
237   GstSeekFlags flags;
238   GstSeekType start_type, stop_type;
239   gint64 start, stop;
240   gdouble rate;
241   GList *walk, *current_file = NULL;
242   GstClockTime current_pos, target_pos;
243   gint64 current_sequence;
244   GstM3U8MediaFile *file;
245   guint64 bitrate;
246   gboolean snap_before, snap_after, snap_nearest, keyunit;
247   gboolean reverse;
248
249   gst_event_parse_seek (seek, &rate, &format, &flags, &start_type, &start,
250       &stop_type, &stop);
251
252   bitrate = gst_hls_demux_get_bitrate (hlsdemux);
253
254   /* properly cleanup pending decryption status */
255   if (flags & GST_SEEK_FLAG_FLUSH) {
256     gst_hls_demux_decrypt_end (hlsdemux);
257   }
258
259   /* Use I-frame variants for trick modes */
260   if (hlsdemux->client->main->iframe_lists && rate < -1.0
261       && demux->segment.rate >= -1.0 && demux->segment.rate <= 1.0) {
262     GError *err = NULL;
263
264     GST_M3U8_CLIENT_LOCK (hlsdemux->client);
265     /* Switch to I-frame variant */
266     hlsdemux->client->main->current_variant =
267         hlsdemux->client->main->iframe_lists;
268     GST_M3U8_CLIENT_UNLOCK (hlsdemux->client);
269     gst_m3u8_client_set_current (hlsdemux->client,
270         hlsdemux->client->main->iframe_lists->data);
271     gst_uri_downloader_reset (demux->downloader);
272     if (!gst_hls_demux_update_playlist (hlsdemux, FALSE, &err)) {
273       GST_ELEMENT_ERROR_FROM_ERROR (hlsdemux, "Could not switch playlist", err);
274       return FALSE;
275     }
276     //hlsdemux->discont = TRUE;
277     hlsdemux->do_typefind = TRUE;
278
279     gst_hls_demux_change_playlist (hlsdemux, bitrate / ABS (rate), NULL);
280   } else if (rate > -1.0 && rate <= 1.0 && (demux->segment.rate < -1.0
281           || demux->segment.rate > 1.0)) {
282     GError *err = NULL;
283     GST_M3U8_CLIENT_LOCK (hlsdemux->client);
284     /* Switch to normal variant */
285     hlsdemux->client->main->current_variant = hlsdemux->client->main->lists;
286     GST_M3U8_CLIENT_UNLOCK (hlsdemux->client);
287     gst_m3u8_client_set_current (hlsdemux->client,
288         hlsdemux->client->main->lists->data);
289     gst_uri_downloader_reset (demux->downloader);
290     if (!gst_hls_demux_update_playlist (hlsdemux, FALSE, &err)) {
291       GST_ELEMENT_ERROR_FROM_ERROR (hlsdemux, "Could not switch playlist", err);
292       return FALSE;
293     }
294     //hlsdemux->discont = TRUE;
295     hlsdemux->do_typefind = TRUE;
296     /* TODO why not continue using the same? that was being used up to now? */
297     gst_hls_demux_change_playlist (hlsdemux, bitrate, NULL);
298   }
299
300   GST_M3U8_CLIENT_LOCK (hlsdemux->client);
301   file = GST_M3U8_MEDIA_FILE (hlsdemux->client->current->files->data);
302   current_sequence = file->sequence;
303   current_pos = 0;
304   reverse = rate < 0;
305   target_pos = reverse ? stop : start;
306
307   /* Snap to segment boundary. Improves seek performance on slow machines. */
308   keyunit = ! !(flags & GST_SEEK_FLAG_KEY_UNIT);
309   snap_nearest =
310       (flags & GST_SEEK_FLAG_SNAP_NEAREST) == GST_SEEK_FLAG_SNAP_NEAREST;
311   snap_before = ! !(flags & GST_SEEK_FLAG_SNAP_BEFORE);
312   snap_after = ! !(flags & GST_SEEK_FLAG_SNAP_AFTER);
313
314   /* FIXME: Here we need proper discont handling */
315   for (walk = hlsdemux->client->current->files; walk; walk = walk->next) {
316     file = walk->data;
317
318     current_sequence = file->sequence;
319     current_file = walk;
320     if ((!reverse && snap_after) || snap_nearest) {
321       if (current_pos >= target_pos)
322         break;
323       if (snap_nearest && target_pos - current_pos < file->duration / 2)
324         break;
325     } else if (reverse && snap_after) {
326       /* check if the next fragment is our target, in this case we want to
327        * start from the previous fragment */
328       GstClockTime next_pos = current_pos + file->duration;
329
330       if (next_pos <= target_pos && target_pos < next_pos + file->duration) {
331         break;
332       }
333     } else if (current_pos <= target_pos
334         && target_pos < current_pos + file->duration) {
335       break;
336     }
337     current_pos += file->duration;
338   }
339
340   if (walk == NULL) {
341     GST_DEBUG_OBJECT (demux, "seeking further than track duration");
342     current_sequence++;
343   }
344
345   GST_DEBUG_OBJECT (demux, "seeking to sequence %u", (guint) current_sequence);
346   hlsdemux->reset_pts = TRUE;
347   hlsdemux->client->sequence = current_sequence;
348   hlsdemux->client->current_file =
349       current_file ? current_file : hlsdemux->client->current->files;
350   hlsdemux->client->sequence_position = current_pos;
351   GST_M3U8_CLIENT_UNLOCK (hlsdemux->client);
352
353   /* Play from the end of the current selected segment */
354   if (reverse && (snap_before || snap_after || snap_nearest))
355     current_pos += file->duration;
356
357   if (keyunit || snap_before || snap_after || snap_nearest) {
358     if (!reverse)
359       gst_segment_do_seek (&demux->segment, rate, format, flags, start_type,
360           current_pos, stop_type, stop, NULL);
361     else
362       gst_segment_do_seek (&demux->segment, rate, format, flags, start_type,
363           start, stop_type, current_pos, NULL);
364   }
365
366   return TRUE;
367 }
368
369 static GstFlowReturn
370 gst_hls_demux_update_manifest (GstAdaptiveDemux * demux)
371 {
372   GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (demux);
373   if (!gst_hls_demux_update_playlist (hlsdemux, TRUE, NULL))
374     return GST_FLOW_ERROR;
375
376   return GST_FLOW_OK;
377 }
378
379 static gboolean
380 gst_hls_demux_setup_streams (GstAdaptiveDemux * demux)
381 {
382   GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (demux);
383
384   /* only 1 output supported */
385   gst_adaptive_demux_stream_new (demux, gst_hls_demux_create_pad (hlsdemux));
386
387   hlsdemux->reset_pts = TRUE;
388
389   return TRUE;
390 }
391
392
393 static gboolean
394 gst_hls_demux_process_manifest (GstAdaptiveDemux * demux, GstBuffer * buf)
395 {
396   GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (demux);
397   gchar *playlist = NULL;
398
399   if (hlsdemux->client)
400     gst_m3u8_client_free (hlsdemux->client);
401
402   hlsdemux->client =
403       gst_m3u8_client_new (demux->manifest_uri, demux->manifest_base_uri);
404
405   GST_INFO_OBJECT (demux, "Changed location: %s (base uri: %s)",
406       demux->manifest_uri, GST_STR_NULL (demux->manifest_base_uri));
407
408   playlist = gst_hls_src_buf_to_utf8_playlist (buf);
409   if (playlist == NULL) {
410     GST_WARNING_OBJECT (demux, "Error validating first playlist.");
411     return FALSE;
412   } else if (!gst_m3u8_client_update (hlsdemux->client, playlist)) {
413     /* In most cases, this will happen if we set a wrong url in the
414      * source element and we have received the 404 HTML response instead of
415      * the playlist */
416     GST_ELEMENT_ERROR (demux, STREAM, DECODE, ("Invalid playlist."), (NULL));
417     return FALSE;
418   }
419
420   /* If this playlist is a variant playlist, select the first one
421    * and update it */
422   if (gst_m3u8_client_has_variant_playlist (hlsdemux->client)) {
423     GstM3U8 *child = NULL;
424     GError *err = NULL;
425
426     if (demux->connection_speed == 0) {
427       GST_M3U8_CLIENT_LOCK (hlsdemux->client);
428       child = hlsdemux->client->main->current_variant->data;
429       GST_M3U8_CLIENT_UNLOCK (hlsdemux->client);
430     } else {
431       GList *tmp = gst_m3u8_client_get_playlist_for_bitrate (hlsdemux->client,
432           demux->connection_speed);
433       GST_M3U8_CLIENT_LOCK (hlsdemux->client);
434       hlsdemux->client->main->current_variant = tmp;
435       GST_M3U8_CLIENT_UNLOCK (hlsdemux->client);
436
437       child = GST_M3U8 (tmp->data);
438     }
439
440     gst_m3u8_client_set_current (hlsdemux->client, child);
441     if (!gst_hls_demux_update_playlist (hlsdemux, FALSE, &err)) {
442       GST_ELEMENT_ERROR_FROM_ERROR (demux, "Could not fetch the child playlist",
443           err);
444       return FALSE;
445     }
446   }
447
448   return gst_hls_demux_setup_streams (demux);
449 }
450
451 static GstClockTime
452 gst_hls_demux_get_duration (GstAdaptiveDemux * demux)
453 {
454   GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (demux);
455
456   return gst_m3u8_client_get_duration (hlsdemux->client);
457 }
458
459 static gboolean
460 gst_hls_demux_is_live (GstAdaptiveDemux * demux)
461 {
462   GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (demux);
463
464   return gst_m3u8_client_is_live (hlsdemux->client);
465 }
466
467 static gboolean
468 gst_hls_demux_start_fragment (GstAdaptiveDemux * demux,
469     GstAdaptiveDemuxStream * stream)
470 {
471   GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (demux);
472
473   if (hlsdemux->current_key) {
474     GError *err = NULL;
475     GstFragment *key_fragment;
476     GstBuffer *key_buffer;
477     GstMapInfo key_info;
478
479     /* new key? */
480     if (hlsdemux->key_url
481         && strcmp (hlsdemux->key_url, hlsdemux->current_key) == 0) {
482       key_fragment = g_object_ref (hlsdemux->key_fragment);
483     } else {
484       g_free (hlsdemux->key_url);
485       hlsdemux->key_url = NULL;
486
487       if (hlsdemux->key_fragment)
488         g_object_unref (hlsdemux->key_fragment);
489       hlsdemux->key_fragment = NULL;
490
491       GST_INFO_OBJECT (demux, "Fetching key %s", hlsdemux->current_key);
492       key_fragment =
493           gst_uri_downloader_fetch_uri (demux->downloader,
494           hlsdemux->current_key, hlsdemux->client->main ?
495           hlsdemux->client->main->uri : NULL, FALSE, FALSE,
496           hlsdemux->client->current ? hlsdemux->client->current->
497           allowcache : TRUE, &err);
498       if (key_fragment == NULL)
499         goto key_failed;
500       hlsdemux->key_url = g_strdup (hlsdemux->current_key);
501       hlsdemux->key_fragment = g_object_ref (key_fragment);
502     }
503
504     key_buffer = gst_fragment_get_buffer (key_fragment);
505     gst_buffer_map (key_buffer, &key_info, GST_MAP_READ);
506
507     gst_hls_demux_decrypt_start (hlsdemux, key_info.data, hlsdemux->current_iv);
508
509     gst_buffer_unmap (key_buffer, &key_info);
510     gst_buffer_unref (key_buffer);
511     g_object_unref (key_fragment);
512   }
513
514   return TRUE;
515
516 key_failed:
517   {
518     GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
519         ("Couldn't retrieve key for decryption"), (NULL));
520     GST_WARNING_OBJECT (demux, "Failed to decrypt data");
521     return FALSE;
522   }
523 }
524
525 /* Handles decrypted buffers only */
526 static GstFlowReturn
527 gst_hls_demux_handle_buffer (GstAdaptiveDemux * demux,
528     GstAdaptiveDemuxStream * stream, GstBuffer * buffer, gboolean force)
529 {
530   GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (demux);
531
532   if (G_UNLIKELY (hlsdemux->do_typefind && buffer != NULL)) {
533     GstCaps *caps = NULL;
534     GstMapInfo info;
535     guint buffer_size;
536     GstTypeFindProbability prob = GST_TYPE_FIND_NONE;
537
538     if (hlsdemux->pending_typefind_buffer)
539       buffer = gst_buffer_append (hlsdemux->pending_typefind_buffer, buffer);
540     hlsdemux->pending_typefind_buffer = NULL;
541
542     gst_buffer_map (buffer, &info, GST_MAP_READ);
543     buffer_size = info.size;
544
545     /* Typefind could miss if buffer is too small. In this case we
546      * will retry later */
547     if (buffer_size >= (2 * 1024)) {
548       caps =
549           gst_type_find_helper_for_data (GST_OBJECT_CAST (hlsdemux), info.data,
550           info.size, &prob);
551     }
552     gst_buffer_unmap (buffer, &info);
553
554     if (G_UNLIKELY (!caps)) {
555       /* Only fail typefinding if we already a good amount of data
556        * and we still don't know the type */
557       if (buffer_size > (2 * 1024 * 1024) || force) {
558         GST_ELEMENT_ERROR (hlsdemux, STREAM, TYPE_NOT_FOUND,
559             ("Could not determine type of stream"), (NULL));
560         gst_buffer_unref (buffer);
561         return GST_FLOW_NOT_NEGOTIATED;
562       } else {
563         hlsdemux->pending_typefind_buffer = buffer;
564         return GST_FLOW_OK;
565       }
566     }
567
568     GST_DEBUG_OBJECT (hlsdemux, "Typefind result: %" GST_PTR_FORMAT " prob:%d",
569         caps, prob);
570
571     gst_adaptive_demux_stream_set_caps (stream, caps);
572     hlsdemux->do_typefind = FALSE;
573   }
574
575   g_assert (hlsdemux->pending_typefind_buffer == NULL);
576
577   if (buffer)
578     return gst_adaptive_demux_stream_push_buffer (stream, buffer);
579   return GST_FLOW_OK;
580 }
581
582 static GstFlowReturn
583 gst_hls_demux_finish_fragment (GstAdaptiveDemux * demux,
584     GstAdaptiveDemuxStream * stream)
585 {
586   GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (demux);
587   GstFlowReturn ret = GST_FLOW_OK;
588
589   if (hlsdemux->current_key)
590     gst_hls_demux_decrypt_end (hlsdemux);
591
592   if (stream->last_ret == GST_FLOW_OK) {
593     if (hlsdemux->pending_decrypted_buffer) {
594       if (hlsdemux->current_key) {
595         GstMapInfo info;
596         gssize unpadded_size;
597
598         /* Handle pkcs7 unpadding here */
599         gst_buffer_map (hlsdemux->pending_decrypted_buffer, &info,
600             GST_MAP_READ);
601         unpadded_size = info.size - info.data[info.size - 1];
602         gst_buffer_unmap (hlsdemux->pending_decrypted_buffer, &info);
603
604         gst_buffer_resize (hlsdemux->pending_decrypted_buffer, 0,
605             unpadded_size);
606       }
607
608       ret =
609           gst_hls_demux_handle_buffer (demux, stream,
610           hlsdemux->pending_decrypted_buffer, TRUE);
611       hlsdemux->pending_decrypted_buffer = NULL;
612     }
613   } else {
614     gst_buffer_replace (&hlsdemux->pending_decrypted_buffer, NULL);
615     gst_adapter_clear (hlsdemux->pending_encrypted_data);
616   }
617
618   if (ret == GST_FLOW_OK || ret == GST_FLOW_NOT_LINKED)
619     return gst_adaptive_demux_stream_advance_fragment (demux, stream,
620         stream->fragment.duration);
621   return ret;
622 }
623
624 static GstFlowReturn
625 gst_hls_demux_data_received (GstAdaptiveDemux * demux,
626     GstAdaptiveDemuxStream * stream, GstBuffer * buffer)
627 {
628   GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (demux);
629
630   /* Is it encrypted? */
631   if (hlsdemux->current_key) {
632     GError *err = NULL;
633     gsize size;
634     GstBuffer *tmp_buffer;
635
636     gst_adapter_push (hlsdemux->pending_encrypted_data, buffer);
637     size = gst_adapter_available (hlsdemux->pending_encrypted_data);
638
639     /* must be a multiple of 16 */
640     size = size & (~0xF);
641
642     if (size == 0) {
643       return GST_FLOW_OK;
644     }
645
646     buffer = gst_adapter_take_buffer (hlsdemux->pending_encrypted_data, size);
647     buffer = gst_hls_demux_decrypt_fragment (hlsdemux, buffer, &err);
648     if (buffer == NULL) {
649       GST_ELEMENT_ERROR (demux, STREAM, DECODE, ("Failed to decrypt buffer"),
650           ("decryption failed %s", err->message));
651       g_error_free (err);
652       return GST_FLOW_ERROR;
653     }
654
655     tmp_buffer = hlsdemux->pending_decrypted_buffer;
656     hlsdemux->pending_decrypted_buffer = buffer;
657     buffer = tmp_buffer;
658   }
659
660   return gst_hls_demux_handle_buffer (demux, stream, buffer, FALSE);
661 }
662
663 static gboolean
664 gst_hls_demux_stream_has_next_fragment (GstAdaptiveDemuxStream * stream)
665 {
666   GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (stream->demux);
667
668   return gst_m3u8_client_has_next_fragment (hlsdemux->client,
669       stream->demux->segment.rate > 0);
670 }
671
672 static GstFlowReturn
673 gst_hls_demux_advance_fragment (GstAdaptiveDemuxStream * stream)
674 {
675   GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (stream->demux);
676
677   gst_m3u8_client_advance_fragment (hlsdemux->client,
678       stream->demux->segment.rate > 0);
679   hlsdemux->reset_pts = FALSE;
680   return GST_FLOW_OK;
681 }
682
683 static GstFlowReturn
684 gst_hls_demux_update_fragment_info (GstAdaptiveDemuxStream * stream)
685 {
686   GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (stream->demux);
687   gchar *next_fragment_uri;
688   GstClockTime duration;
689   GstClockTime timestamp;
690   gboolean discont;
691   gint64 range_start, range_end;
692   gchar *key = NULL;
693   guint8 *iv = NULL;
694
695   if (!gst_m3u8_client_get_next_fragment (hlsdemux->client, &discont,
696           &next_fragment_uri, &duration, &timestamp, &range_start, &range_end,
697           &key, &iv, stream->demux->segment.rate > 0)) {
698     GST_INFO_OBJECT (hlsdemux, "This playlist doesn't contain more fragments");
699     return GST_FLOW_EOS;
700   }
701
702   if (stream->discont)
703     discont = TRUE;
704
705   /* set up our source for download */
706   if (hlsdemux->reset_pts || discont || stream->demux->segment.rate < 0.0) {
707     stream->fragment.timestamp = timestamp;
708   } else {
709     stream->fragment.timestamp = GST_CLOCK_TIME_NONE;
710   }
711
712   g_free (hlsdemux->current_key);
713   hlsdemux->current_key = key;
714   g_free (hlsdemux->current_iv);
715   hlsdemux->current_iv = iv;
716   g_free (stream->fragment.uri);
717   stream->fragment.uri = next_fragment_uri;
718   stream->fragment.range_start = range_start;
719   stream->fragment.range_end = range_end;
720   stream->fragment.duration = duration;
721   if (discont)
722     stream->discont = discont;
723
724   return GST_FLOW_OK;
725 }
726
727 static gboolean
728 gst_hls_demux_select_bitrate (GstAdaptiveDemuxStream * stream, guint64 bitrate)
729 {
730   GstAdaptiveDemux *demux = GST_ADAPTIVE_DEMUX_CAST (stream->demux);
731   GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (stream->demux);
732   gboolean changed = FALSE;
733
734   GST_M3U8_CLIENT_LOCK (hlsdemux->client);
735   if (!hlsdemux->client->main->lists) {
736     GST_M3U8_CLIENT_UNLOCK (hlsdemux->client);
737     return FALSE;
738   }
739   GST_M3U8_CLIENT_UNLOCK (hlsdemux->client);
740
741   /* FIXME: Currently several issues have be found when letting bitrate adaptation
742    * happen using trick modes (such as 'All streams finished without buffers') and
743    * the adaptive algorithm does not properly behave. */
744   if (demux->segment.rate != 1.0)
745     return FALSE;
746
747   gst_hls_demux_change_playlist (hlsdemux, bitrate, &changed);
748   if (changed)
749     gst_hls_demux_setup_streams (GST_ADAPTIVE_DEMUX_CAST (hlsdemux));
750   return changed;
751 }
752
753 static void
754 gst_hls_demux_reset (GstAdaptiveDemux * ademux)
755 {
756   GstHLSDemux *demux = GST_HLS_DEMUX_CAST (ademux);
757
758   demux->do_typefind = TRUE;
759   demux->reset_pts = TRUE;
760
761   g_free (demux->key_url);
762   demux->key_url = NULL;
763
764   if (demux->key_fragment)
765     g_object_unref (demux->key_fragment);
766   demux->key_fragment = NULL;
767
768   if (demux->client) {
769     gst_m3u8_client_free (demux->client);
770     demux->client = NULL;
771   }
772   /* TODO recreated on hls only if reset was not for disposing */
773   demux->client = gst_m3u8_client_new ("", NULL);
774
775   demux->srcpad_counter = 0;
776   gst_adapter_clear (demux->pending_encrypted_data);
777   gst_buffer_replace (&demux->pending_decrypted_buffer, NULL);
778   gst_buffer_replace (&demux->pending_typefind_buffer, NULL);
779   if (demux->current_key) {
780     g_free (demux->current_key);
781     demux->current_key = NULL;
782   }
783   if (demux->current_iv) {
784     g_free (demux->current_iv);
785     demux->current_iv = NULL;
786   }
787
788   gst_hls_demux_decrypt_end (demux);
789 }
790
791 static gchar *
792 gst_hls_src_buf_to_utf8_playlist (GstBuffer * buf)
793 {
794   GstMapInfo info;
795   gchar *playlist;
796
797   if (!gst_buffer_map (buf, &info, GST_MAP_READ))
798     goto map_error;
799
800   if (!g_utf8_validate ((gchar *) info.data, info.size, NULL))
801     goto validate_error;
802
803   /* alloc size + 1 to end with a null character */
804   playlist = g_malloc0 (info.size + 1);
805   memcpy (playlist, info.data, info.size);
806
807   gst_buffer_unmap (buf, &info);
808   return playlist;
809
810 validate_error:
811   gst_buffer_unmap (buf, &info);
812 map_error:
813   return NULL;
814 }
815
816 static gboolean
817 gst_hls_demux_update_playlist (GstHLSDemux * demux, gboolean update,
818     GError ** err)
819 {
820   GstAdaptiveDemux *adaptive_demux = GST_ADAPTIVE_DEMUX (demux);
821   GstFragment *download;
822   GstBuffer *buf;
823   gchar *playlist;
824   gboolean main_checked = FALSE, updated = FALSE;
825   gchar *uri, *main_uri;
826
827 retry:
828   uri = gst_m3u8_client_get_current_uri (demux->client);
829   main_uri = gst_m3u8_client_get_uri (demux->client);
830   download =
831       gst_uri_downloader_fetch_uri (adaptive_demux->downloader, uri, main_uri,
832       TRUE, TRUE, TRUE, err);
833   g_free (main_uri);
834   if (download == NULL) {
835     gchar *base_uri;
836
837     if (!update || main_checked
838         || !gst_m3u8_client_has_variant_playlist (demux->client)) {
839       g_free (uri);
840       return FALSE;
841     }
842
843     g_clear_error (err);
844     main_uri = gst_m3u8_client_get_uri (demux->client);
845     GST_INFO_OBJECT (demux,
846         "Updating playlist %s failed, attempt to refresh variant playlist %s",
847         uri, main_uri);
848     download =
849         gst_uri_downloader_fetch_uri (adaptive_demux->downloader,
850         main_uri, NULL, TRUE, TRUE, TRUE, err);
851     g_free (main_uri);
852     if (download == NULL) {
853       g_free (uri);
854       return FALSE;
855     }
856
857     buf = gst_fragment_get_buffer (download);
858     playlist = gst_hls_src_buf_to_utf8_playlist (buf);
859     gst_buffer_unref (buf);
860
861     if (playlist == NULL) {
862       GST_WARNING_OBJECT (demux,
863           "Failed to validate variant playlist encoding");
864       g_free (uri);
865       g_object_unref (download);
866       g_set_error (err, GST_STREAM_ERROR, GST_STREAM_ERROR_WRONG_TYPE,
867           "Couldn't validate playlist encoding");
868       return FALSE;
869     }
870
871     g_free (uri);
872     if (download->redirect_permanent && download->redirect_uri) {
873       uri = download->redirect_uri;
874       base_uri = NULL;
875     } else {
876       uri = download->uri;
877       base_uri = download->redirect_uri;
878     }
879
880     if (!gst_m3u8_client_update_variant_playlist (demux->client, playlist,
881             uri, base_uri)) {
882       GST_WARNING_OBJECT (demux, "Failed to update the variant playlist");
883       g_object_unref (download);
884       g_set_error (err, GST_STREAM_ERROR, GST_STREAM_ERROR_FAILED,
885           "Couldn't update playlist");
886       return FALSE;
887     }
888
889     g_object_unref (download);
890
891     main_checked = TRUE;
892     goto retry;
893   }
894   g_free (uri);
895
896   /* Set the base URI of the playlist to the redirect target if any */
897   GST_M3U8_CLIENT_LOCK (demux->client);
898   g_free (demux->client->current->uri);
899   g_free (demux->client->current->base_uri);
900   if (download->redirect_permanent && download->redirect_uri) {
901     demux->client->current->uri = g_strdup (download->redirect_uri);
902     demux->client->current->base_uri = NULL;
903   } else {
904     demux->client->current->uri = g_strdup (download->uri);
905     demux->client->current->base_uri = g_strdup (download->redirect_uri);
906   }
907   GST_M3U8_CLIENT_UNLOCK (demux->client);
908
909   buf = gst_fragment_get_buffer (download);
910   playlist = gst_hls_src_buf_to_utf8_playlist (buf);
911   gst_buffer_unref (buf);
912   g_object_unref (download);
913
914   if (playlist == NULL) {
915     GST_WARNING_OBJECT (demux, "Couldn't validate playlist encoding");
916     g_set_error (err, GST_STREAM_ERROR, GST_STREAM_ERROR_WRONG_TYPE,
917         "Couldn't validate playlist encoding");
918     return FALSE;
919   }
920
921   updated = gst_m3u8_client_update (demux->client, playlist);
922   if (!updated) {
923     GST_WARNING_OBJECT (demux, "Couldn't update playlist");
924     g_set_error (err, GST_STREAM_ERROR, GST_STREAM_ERROR_FAILED,
925         "Couldn't update playlist");
926     return FALSE;
927   }
928
929   /* If it's a live source, do not let the sequence number go beyond
930    * three fragments before the end of the list */
931   if (update == FALSE && demux->client->current &&
932       gst_m3u8_client_is_live (demux->client)) {
933     gint64 last_sequence, first_sequence;
934
935     GST_M3U8_CLIENT_LOCK (demux->client);
936     last_sequence =
937         GST_M3U8_MEDIA_FILE (g_list_last (demux->client->current->
938             files)->data)->sequence;
939     first_sequence =
940         GST_M3U8_MEDIA_FILE (demux->client->current->files->data)->sequence;
941
942     GST_DEBUG_OBJECT (demux,
943         "sequence:%" G_GINT64_FORMAT " , first_sequence:%" G_GINT64_FORMAT
944         " , last_sequence:%" G_GINT64_FORMAT, demux->client->sequence,
945         first_sequence, last_sequence);
946     if (demux->client->sequence >= last_sequence - 3) {
947       //demux->need_segment = TRUE;
948       /* Make sure we never go below the minimum sequence number */
949       demux->client->sequence = MAX (first_sequence, last_sequence - 3);
950       GST_DEBUG_OBJECT (demux,
951           "Sequence is beyond playlist. Moving back to %" G_GINT64_FORMAT,
952           demux->client->sequence);
953     }
954     GST_M3U8_CLIENT_UNLOCK (demux->client);
955   } else if (demux->client->current && !gst_m3u8_client_is_live (demux->client)) {
956     GstClockTime current_pos, target_pos;
957     guint sequence = 0;
958     GList *walk;
959
960     /* Sequence numbers are not guaranteed to be the same in different
961      * playlists, so get the correct fragment here based on the current
962      * position
963      */
964     GST_M3U8_CLIENT_LOCK (demux->client);
965
966     /* Valid because hlsdemux only has a single output */
967     if (GST_ADAPTIVE_DEMUX_CAST (demux)->streams) {
968       GstAdaptiveDemuxStream *stream =
969           GST_ADAPTIVE_DEMUX_CAST (demux)->streams->data;
970       target_pos = stream->segment.position;
971     } else {
972       target_pos = 0;
973     }
974     if (GST_CLOCK_TIME_IS_VALID (demux->client->sequence_position)) {
975       target_pos = MAX (target_pos, demux->client->sequence_position);
976     }
977
978     GST_LOG_OBJECT (demux, "Looking for sequence position %"
979         GST_TIME_FORMAT " in updated playlist", GST_TIME_ARGS (target_pos));
980
981     current_pos = 0;
982     for (walk = demux->client->current->files; walk; walk = walk->next) {
983       GstM3U8MediaFile *file = walk->data;
984
985       sequence = file->sequence;
986       if (current_pos <= target_pos
987           && target_pos < current_pos + file->duration) {
988         break;
989       }
990       current_pos += file->duration;
991     }
992     /* End of playlist */
993     if (!walk)
994       sequence++;
995     demux->client->sequence = sequence;
996     demux->client->sequence_position = current_pos;
997     GST_M3U8_CLIENT_UNLOCK (demux->client);
998   }
999
1000   return updated;
1001 }
1002
1003 static gboolean
1004 gst_hls_demux_change_playlist (GstHLSDemux * demux, guint max_bitrate,
1005     gboolean * changed)
1006 {
1007   GList *previous_variant, *current_variant;
1008   gint old_bandwidth, new_bandwidth;
1009   GstAdaptiveDemux *adaptive_demux = GST_ADAPTIVE_DEMUX_CAST (demux);
1010   GstAdaptiveDemuxStream *stream;
1011
1012   g_return_val_if_fail (adaptive_demux->streams != NULL, FALSE);
1013
1014   stream = adaptive_demux->streams->data;
1015
1016   previous_variant = demux->client->main->current_variant;
1017   current_variant = gst_m3u8_client_get_playlist_for_bitrate (demux->client,
1018       max_bitrate);
1019
1020   GST_M3U8_CLIENT_LOCK (demux->client);
1021
1022 retry_failover_protection:
1023   old_bandwidth = GST_M3U8 (previous_variant->data)->bandwidth;
1024   new_bandwidth = GST_M3U8 (current_variant->data)->bandwidth;
1025
1026   /* Don't do anything else if the playlist is the same */
1027   if (new_bandwidth == old_bandwidth) {
1028     GST_M3U8_CLIENT_UNLOCK (demux->client);
1029     return TRUE;
1030   }
1031
1032   demux->client->main->current_variant = current_variant;
1033   GST_M3U8_CLIENT_UNLOCK (demux->client);
1034
1035   gst_m3u8_client_set_current (demux->client, current_variant->data);
1036
1037   GST_INFO_OBJECT (demux, "Client was on %dbps, max allowed is %dbps, switching"
1038       " to bitrate %dbps", old_bandwidth, max_bitrate, new_bandwidth);
1039
1040   if (gst_hls_demux_update_playlist (demux, TRUE, NULL)) {
1041     gchar *uri;
1042     gchar *main_uri;
1043     uri = gst_m3u8_client_get_current_uri (demux->client);
1044     main_uri = gst_m3u8_client_get_uri (demux->client);
1045     gst_element_post_message (GST_ELEMENT_CAST (demux),
1046         gst_message_new_element (GST_OBJECT_CAST (demux),
1047             gst_structure_new (GST_ADAPTIVE_DEMUX_STATISTICS_MESSAGE_NAME,
1048                 "manifest-uri", G_TYPE_STRING,
1049                 main_uri, "uri", G_TYPE_STRING,
1050                 uri, "bitrate", G_TYPE_INT, new_bandwidth, NULL)));
1051     g_free (uri);
1052     g_free (main_uri);
1053     if (changed)
1054       *changed = TRUE;
1055     stream->discont = TRUE;
1056   } else {
1057     GList *failover = NULL;
1058
1059     GST_INFO_OBJECT (demux, "Unable to update playlist. Switching back");
1060     GST_M3U8_CLIENT_LOCK (demux->client);
1061
1062     failover = g_list_previous (current_variant);
1063     if (failover && new_bandwidth == GST_M3U8 (failover->data)->bandwidth) {
1064       current_variant = failover;
1065       goto retry_failover_protection;
1066     }
1067
1068     demux->client->main->current_variant = previous_variant;
1069     GST_M3U8_CLIENT_UNLOCK (demux->client);
1070     gst_m3u8_client_set_current (demux->client, previous_variant->data);
1071     /*  Try a lower bitrate (or stop if we just tried the lowest) */
1072     if (GST_M3U8 (previous_variant->data)->iframe && new_bandwidth ==
1073         GST_M3U8 (g_list_first (demux->client->main->iframe_lists)->data)->
1074         bandwidth)
1075       return FALSE;
1076     else if (!GST_M3U8 (previous_variant->data)->iframe && new_bandwidth ==
1077         GST_M3U8 (g_list_first (demux->client->main->lists)->data)->bandwidth)
1078       return FALSE;
1079     else
1080       return gst_hls_demux_change_playlist (demux, new_bandwidth - 1, changed);
1081   }
1082
1083   /* Force typefinding since we might have changed media type */
1084   demux->do_typefind = TRUE;
1085
1086   return TRUE;
1087 }
1088
1089 #if defined(HAVE_OPENSSL)
1090 static gboolean
1091 gst_hls_demux_decrypt_start (GstHLSDemux * demux, const guint8 * key_data,
1092     const guint8 * iv_data)
1093 {
1094   EVP_CIPHER_CTX_init (&demux->aes_ctx);
1095   if (!EVP_DecryptInit_ex (&demux->aes_ctx, EVP_aes_128_cbc (), NULL, key_data,
1096           iv_data))
1097     return FALSE;
1098   EVP_CIPHER_CTX_set_padding (&demux->aes_ctx, 0);
1099   return TRUE;
1100 }
1101
1102 static gboolean
1103 decrypt_fragment (GstHLSDemux * demux, gsize length,
1104     const guint8 * encrypted_data, guint8 * decrypted_data)
1105 {
1106   int len, flen = 0;
1107
1108   if (G_UNLIKELY (length > G_MAXINT || length % 16 != 0))
1109     return FALSE;
1110
1111   len = (int) length;
1112   if (!EVP_DecryptUpdate (&demux->aes_ctx, decrypted_data, &len, encrypted_data,
1113           len))
1114     return FALSE;
1115   EVP_DecryptFinal_ex (&demux->aes_ctx, decrypted_data + len, &flen);
1116   g_return_val_if_fail (len + flen == length, FALSE);
1117   return TRUE;
1118 }
1119
1120 static void
1121 gst_hls_demux_decrypt_end (GstHLSDemux * demux)
1122 {
1123   EVP_CIPHER_CTX_cleanup (&demux->aes_ctx);
1124 }
1125
1126 #elif defined(HAVE_NETTLE)
1127 static gboolean
1128 gst_hls_demux_decrypt_start (GstHLSDemux * demux, const guint8 * key_data,
1129     const guint8 * iv_data)
1130 {
1131   aes_set_decrypt_key (&demux->aes_ctx.ctx, 16, key_data);
1132   CBC_SET_IV (&demux->aes_ctx, iv_data);
1133
1134   return TRUE;
1135 }
1136
1137 static gboolean
1138 decrypt_fragment (GstHLSDemux * demux, gsize length,
1139     const guint8 * encrypted_data, guint8 * decrypted_data)
1140 {
1141   if (length % 16 != 0)
1142     return FALSE;
1143
1144   CBC_DECRYPT (&demux->aes_ctx, aes_decrypt, length, decrypted_data,
1145       encrypted_data);
1146
1147   return TRUE;
1148 }
1149
1150 static void
1151 gst_hls_demux_decrypt_end (GstHLSDemux * demux)
1152 {
1153   /* NOP */
1154 }
1155
1156 #else
1157 static gboolean
1158 gst_hls_demux_decrypt_start (GstHLSDemux * demux, const guint8 * key_data,
1159     const guint8 * iv_data)
1160 {
1161   gcry_error_t err = 0;
1162   gboolean ret = FALSE;
1163
1164   err =
1165       gcry_cipher_open (&demux->aes_ctx, GCRY_CIPHER_AES128,
1166       GCRY_CIPHER_MODE_CBC, 0);
1167   if (err)
1168     goto out;
1169   err = gcry_cipher_setkey (demux->aes_ctx, key_data, 16);
1170   if (err)
1171     goto out;
1172   err = gcry_cipher_setiv (demux->aes_ctx, iv_data, 16);
1173   if (!err)
1174     ret = TRUE;
1175
1176 out:
1177   if (!ret)
1178     if (demux->aes_ctx)
1179       gcry_cipher_close (demux->aes_ctx);
1180
1181   return ret;
1182 }
1183
1184 static gboolean
1185 decrypt_fragment (GstHLSDemux * demux, gsize length,
1186     const guint8 * encrypted_data, guint8 * decrypted_data)
1187 {
1188   gcry_error_t err = 0;
1189
1190   err = gcry_cipher_decrypt (demux->aes_ctx, decrypted_data, length,
1191       encrypted_data, length);
1192
1193   return err == 0;
1194 }
1195
1196 static void
1197 gst_hls_demux_decrypt_end (GstHLSDemux * demux)
1198 {
1199   if (demux->aes_ctx) {
1200     gcry_cipher_close (demux->aes_ctx);
1201     demux->aes_ctx = NULL;
1202   }
1203 }
1204 #endif
1205
1206 static GstBuffer *
1207 gst_hls_demux_decrypt_fragment (GstHLSDemux * demux,
1208     GstBuffer * encrypted_buffer, GError ** err)
1209 {
1210   GstBuffer *decrypted_buffer = NULL;
1211   GstMapInfo encrypted_info, decrypted_info;
1212
1213   decrypted_buffer =
1214       gst_buffer_new_allocate (NULL, gst_buffer_get_size (encrypted_buffer),
1215       NULL);
1216
1217   gst_buffer_map (encrypted_buffer, &encrypted_info, GST_MAP_READ);
1218   gst_buffer_map (decrypted_buffer, &decrypted_info, GST_MAP_WRITE);
1219
1220   if (!decrypt_fragment (demux, encrypted_info.size,
1221           encrypted_info.data, decrypted_info.data))
1222     goto decrypt_error;
1223
1224
1225   gst_buffer_unmap (decrypted_buffer, &decrypted_info);
1226   gst_buffer_unmap (encrypted_buffer, &encrypted_info);
1227
1228   gst_buffer_unref (encrypted_buffer);
1229
1230   return decrypted_buffer;
1231
1232 decrypt_error:
1233   GST_ERROR_OBJECT (demux, "Failed to decrypt fragment");
1234   g_set_error (err, GST_STREAM_ERROR, GST_STREAM_ERROR_DECRYPT,
1235       "Failed to decrypt fragment");
1236
1237   gst_buffer_unmap (decrypted_buffer, &decrypted_info);
1238   gst_buffer_unmap (encrypted_buffer, &encrypted_info);
1239
1240   gst_buffer_unref (encrypted_buffer);
1241   gst_buffer_unref (decrypted_buffer);
1242
1243   return NULL;
1244 }
1245
1246 static gint64
1247 gst_hls_demux_get_manifest_update_interval (GstAdaptiveDemux * demux)
1248 {
1249   GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (demux);
1250
1251   return gst_util_uint64_scale (gst_m3u8_client_get_target_duration
1252       (hlsdemux->client), G_USEC_PER_SEC, GST_SECOND);
1253 }
1254
1255 static gboolean
1256 gst_hls_demux_get_live_seek_range (GstAdaptiveDemux * demux, gint64 * start,
1257     gint64 * stop)
1258 {
1259   GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (demux);
1260
1261   return gst_m3u8_client_get_seek_range (hlsdemux->client, start, stop);
1262 }