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  * Gsthlsdemux.c:
11  *
12  * This library is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU Library General Public
14  * License as published by the Free Software Foundation; either
15  * version 2 of the License, or (at your option) any later version.
16  *
17  * This library is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20  * Library General Public License for more details.
21  *
22  * You should have received a copy of the GNU Library General Public
23  * License along with this library; if not, write to the
24  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
25  * Boston, MA 02110-1301, USA.
26  */
27 /**
28  * SECTION:element-hlsdemux
29  * @title: hlsdemux
30  *
31  * HTTP Live Streaming demuxer element.
32  *
33  * ## Example launch line
34  * |[
35  * gst-launch-1.0 souphttpsrc location=http://devimages.apple.com/iphone/samples/bipbop/gear4/prog_index.m3u8 ! hlsdemux ! decodebin ! videoconvert ! videoscale ! autovideosink
36  * ]|
37  *
38  */
39 
40 #ifdef HAVE_CONFIG_H
41 #  include "config.h"
42 #endif
43 
44 #include <string.h>
45 #include <gst/base/gsttypefindhelper.h>
46 #include "gsthlsdemux.h"
47 
48 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src_%u",
49     GST_PAD_SRC,
50     GST_PAD_SOMETIMES,
51     GST_STATIC_CAPS_ANY);
52 
53 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
54     GST_PAD_SINK,
55     GST_PAD_ALWAYS,
56     GST_STATIC_CAPS ("application/x-hls"));
57 
58 GST_DEBUG_CATEGORY (gst_hls_demux_debug);
59 #define GST_CAT_DEFAULT gst_hls_demux_debug
60 
61 #define GST_M3U8_CLIENT_LOCK(l) /* FIXME */
62 #define GST_M3U8_CLIENT_UNLOCK(l)       /* FIXME */
63 
64 /* GObject */
65 static void gst_hls_demux_finalize (GObject * obj);
66 
67 /* GstElement */
68 static GstStateChangeReturn
69 gst_hls_demux_change_state (GstElement * element, GstStateChange transition);
70 
71 /* GstHLSDemux */
72 static gboolean gst_hls_demux_update_playlist (GstHLSDemux * demux,
73     gboolean update, GError ** err);
74 static gchar *gst_hls_src_buf_to_utf8_playlist (GstBuffer * buf);
75 
76 /* FIXME: the return value is never used? */
77 static gboolean gst_hls_demux_change_playlist (GstHLSDemux * demux,
78     guint max_bitrate, gboolean * changed);
79 static GstBuffer *gst_hls_demux_decrypt_fragment (GstHLSDemux * demux,
80     GstHLSDemuxStream * stream, GstBuffer * encrypted_buffer, GError ** err);
81 static gboolean
82 gst_hls_demux_stream_decrypt_start (GstHLSDemuxStream * stream,
83     const guint8 * key_data, const guint8 * iv_data);
84 static void gst_hls_demux_stream_decrypt_end (GstHLSDemuxStream * stream);
85 
86 static gboolean gst_hls_demux_is_live (GstAdaptiveDemux * demux);
87 static GstClockTime gst_hls_demux_get_duration (GstAdaptiveDemux * demux);
88 static gint64 gst_hls_demux_get_manifest_update_interval (GstAdaptiveDemux *
89     demux);
90 static gboolean gst_hls_demux_process_manifest (GstAdaptiveDemux * demux,
91     GstBuffer * buf);
92 static GstFlowReturn gst_hls_demux_update_manifest (GstAdaptiveDemux * demux);
93 static gboolean gst_hls_demux_seek (GstAdaptiveDemux * demux, GstEvent * seek);
94 static GstFlowReturn gst_hls_demux_stream_seek (GstAdaptiveDemuxStream *
95     stream, gboolean forward, GstSeekFlags flags, GstClockTime ts,
96     GstClockTime * final_ts);
97 static gboolean
98 gst_hls_demux_start_fragment (GstAdaptiveDemux * demux,
99     GstAdaptiveDemuxStream * stream);
100 static GstFlowReturn gst_hls_demux_finish_fragment (GstAdaptiveDemux * demux,
101     GstAdaptiveDemuxStream * stream);
102 static GstFlowReturn gst_hls_demux_data_received (GstAdaptiveDemux * demux,
103     GstAdaptiveDemuxStream * stream, GstBuffer * buffer);
104 static void gst_hls_demux_stream_free (GstAdaptiveDemuxStream * stream);
105 static gboolean gst_hls_demux_stream_has_next_fragment (GstAdaptiveDemuxStream *
106     stream);
107 static GstFlowReturn gst_hls_demux_advance_fragment (GstAdaptiveDemuxStream *
108     stream);
109 static GstFlowReturn gst_hls_demux_update_fragment_info (GstAdaptiveDemuxStream
110     * stream);
111 static gboolean gst_hls_demux_select_bitrate (GstAdaptiveDemuxStream * stream,
112     guint64 bitrate);
113 static void gst_hls_demux_reset (GstAdaptiveDemux * demux);
114 static gboolean gst_hls_demux_get_live_seek_range (GstAdaptiveDemux * demux,
115     gint64 * start, gint64 * stop);
116 static GstM3U8 *gst_hls_demux_stream_get_m3u8 (GstHLSDemuxStream * hls_stream);
117 static void gst_hls_demux_set_current_variant (GstHLSDemux * hlsdemux,
118     GstHLSVariantStream * variant);
119 
120 #define gst_hls_demux_parent_class parent_class
121 G_DEFINE_TYPE (GstHLSDemux, gst_hls_demux, GST_TYPE_ADAPTIVE_DEMUX);
122 
123 static void
gst_hls_demux_finalize(GObject * obj)124 gst_hls_demux_finalize (GObject * obj)
125 {
126   GstHLSDemux *demux = GST_HLS_DEMUX (obj);
127 
128   gst_hls_demux_reset (GST_ADAPTIVE_DEMUX_CAST (demux));
129   g_mutex_clear (&demux->keys_lock);
130   if (demux->keys) {
131     g_hash_table_unref (demux->keys);
132     demux->keys = NULL;
133   }
134 
135   G_OBJECT_CLASS (parent_class)->finalize (obj);
136 }
137 
138 static void
gst_hls_demux_class_init(GstHLSDemuxClass * klass)139 gst_hls_demux_class_init (GstHLSDemuxClass * klass)
140 {
141   GObjectClass *gobject_class;
142   GstElementClass *element_class;
143   GstAdaptiveDemuxClass *adaptivedemux_class;
144 
145   gobject_class = (GObjectClass *) klass;
146   element_class = (GstElementClass *) klass;
147   adaptivedemux_class = (GstAdaptiveDemuxClass *) klass;
148 
149   gobject_class->finalize = gst_hls_demux_finalize;
150 
151   element_class->change_state = GST_DEBUG_FUNCPTR (gst_hls_demux_change_state);
152 
153   gst_element_class_add_static_pad_template (element_class, &srctemplate);
154   gst_element_class_add_static_pad_template (element_class, &sinktemplate);
155 
156   gst_element_class_set_static_metadata (element_class,
157       "HLS Demuxer",
158       "Codec/Demuxer/Adaptive",
159       "HTTP Live Streaming demuxer",
160       "Marc-Andre Lureau <marcandre.lureau@gmail.com>\n"
161       "Andoni Morales Alastruey <ylatuya@gmail.com>");
162 
163   adaptivedemux_class->is_live = gst_hls_demux_is_live;
164   adaptivedemux_class->get_live_seek_range = gst_hls_demux_get_live_seek_range;
165   adaptivedemux_class->get_duration = gst_hls_demux_get_duration;
166   adaptivedemux_class->get_manifest_update_interval =
167       gst_hls_demux_get_manifest_update_interval;
168   adaptivedemux_class->process_manifest = gst_hls_demux_process_manifest;
169   adaptivedemux_class->update_manifest = gst_hls_demux_update_manifest;
170   adaptivedemux_class->reset = gst_hls_demux_reset;
171   adaptivedemux_class->seek = gst_hls_demux_seek;
172   adaptivedemux_class->stream_seek = gst_hls_demux_stream_seek;
173   adaptivedemux_class->stream_has_next_fragment =
174       gst_hls_demux_stream_has_next_fragment;
175   adaptivedemux_class->stream_advance_fragment = gst_hls_demux_advance_fragment;
176   adaptivedemux_class->stream_update_fragment_info =
177       gst_hls_demux_update_fragment_info;
178   adaptivedemux_class->stream_select_bitrate = gst_hls_demux_select_bitrate;
179   adaptivedemux_class->stream_free = gst_hls_demux_stream_free;
180 
181   adaptivedemux_class->start_fragment = gst_hls_demux_start_fragment;
182   adaptivedemux_class->finish_fragment = gst_hls_demux_finish_fragment;
183   adaptivedemux_class->data_received = gst_hls_demux_data_received;
184 
185   GST_DEBUG_CATEGORY_INIT (gst_hls_demux_debug, "hlsdemux", 0,
186       "hlsdemux element");
187 }
188 
189 static void
gst_hls_demux_init(GstHLSDemux * demux)190 gst_hls_demux_init (GstHLSDemux * demux)
191 {
192   gst_adaptive_demux_set_stream_struct_size (GST_ADAPTIVE_DEMUX_CAST (demux),
193       sizeof (GstHLSDemuxStream));
194 
195   demux->keys = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
196   g_mutex_init (&demux->keys_lock);
197 }
198 
199 static GstStateChangeReturn
gst_hls_demux_change_state(GstElement * element,GstStateChange transition)200 gst_hls_demux_change_state (GstElement * element, GstStateChange transition)
201 {
202   GstStateChangeReturn ret;
203   GstHLSDemux *demux = GST_HLS_DEMUX (element);
204 
205   switch (transition) {
206     case GST_STATE_CHANGE_READY_TO_PAUSED:
207       gst_hls_demux_reset (GST_ADAPTIVE_DEMUX_CAST (demux));
208       break;
209     default:
210       break;
211   }
212 
213   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
214 
215   switch (transition) {
216     case GST_STATE_CHANGE_PAUSED_TO_READY:
217       gst_hls_demux_reset (GST_ADAPTIVE_DEMUX_CAST (demux));
218       g_hash_table_remove_all (demux->keys);
219       break;
220     default:
221       break;
222   }
223   return ret;
224 }
225 
226 static GstPad *
gst_hls_demux_create_pad(GstHLSDemux * hlsdemux)227 gst_hls_demux_create_pad (GstHLSDemux * hlsdemux)
228 {
229   gchar *name;
230   GstPad *pad;
231 
232   name = g_strdup_printf ("src_%u", hlsdemux->srcpad_counter++);
233   pad = gst_pad_new_from_static_template (&srctemplate, name);
234   g_free (name);
235 
236   return pad;
237 }
238 
239 static guint64
gst_hls_demux_get_bitrate(GstHLSDemux * hlsdemux)240 gst_hls_demux_get_bitrate (GstHLSDemux * hlsdemux)
241 {
242   GstAdaptiveDemux *demux = GST_ADAPTIVE_DEMUX_CAST (hlsdemux);
243 
244   /* Valid because hlsdemux only has a single output */
245   if (demux->streams) {
246     GstAdaptiveDemuxStream *stream = demux->streams->data;
247     return stream->current_download_rate;
248   }
249 
250   return 0;
251 }
252 
253 static void
gst_hls_demux_stream_clear_pending_data(GstHLSDemuxStream * hls_stream)254 gst_hls_demux_stream_clear_pending_data (GstHLSDemuxStream * hls_stream)
255 {
256   if (hls_stream->pending_encrypted_data)
257     gst_adapter_clear (hls_stream->pending_encrypted_data);
258   gst_buffer_replace (&hls_stream->pending_decrypted_buffer, NULL);
259   gst_buffer_replace (&hls_stream->pending_typefind_buffer, NULL);
260   gst_buffer_replace (&hls_stream->pending_pcr_buffer, NULL);
261   hls_stream->current_offset = -1;
262   gst_hls_demux_stream_decrypt_end (hls_stream);
263 }
264 
265 static void
gst_hls_demux_clear_all_pending_data(GstHLSDemux * hlsdemux)266 gst_hls_demux_clear_all_pending_data (GstHLSDemux * hlsdemux)
267 {
268   GstAdaptiveDemux *demux = (GstAdaptiveDemux *) hlsdemux;
269   GList *walk;
270 
271   for (walk = demux->streams; walk != NULL; walk = walk->next) {
272     GstHLSDemuxStream *hls_stream = GST_HLS_DEMUX_STREAM_CAST (walk->data);
273     gst_hls_demux_stream_clear_pending_data (hls_stream);
274   }
275 }
276 
277 #if 0
278 static void
279 gst_hls_demux_set_current (GstHLSDemux * self, GstM3U8 * m3u8)
280 {
281   GST_M3U8_CLIENT_LOCK (self);
282   if (m3u8 != self->current) {
283     self->current = m3u8;
284     self->current->duration = GST_CLOCK_TIME_NONE;
285     self->current->current_file = NULL;
286 
287 #if 0
288     // FIXME: this makes no sense after we just set self->current=m3u8 above (tpm)
289     // also, these values don't necessarily align between different lists
290     m3u8->current_file_duration = self->current->current_file_duration;
291     m3u8->sequence = self->current->sequence;
292     m3u8->sequence_position = self->current->sequence_position;
293     m3u8->highest_sequence_number = self->current->highest_sequence_number;
294     m3u8->first_file_start = self->current->first_file_start;
295     m3u8->last_file_end = self->current->last_file_end;
296 #endif
297   }
298   GST_M3U8_CLIENT_UNLOCK (self);
299 }
300 #endif
301 
302 #define SEEK_UPDATES_PLAY_POSITION(r, start_type, stop_type) \
303   ((r >= 0 && start_type != GST_SEEK_TYPE_NONE) || \
304    (r < 0 && stop_type != GST_SEEK_TYPE_NONE))
305 
306 #define IS_SNAP_SEEK(f) (f & (GST_SEEK_FLAG_SNAP_BEFORE |	  \
307                               GST_SEEK_FLAG_SNAP_AFTER |	  \
308                               GST_SEEK_FLAG_SNAP_NEAREST |	  \
309 			      GST_SEEK_FLAG_TRICKMODE_KEY_UNITS | \
310 			      GST_SEEK_FLAG_KEY_UNIT))
311 
312 static gboolean
gst_hls_demux_seek(GstAdaptiveDemux * demux,GstEvent * seek)313 gst_hls_demux_seek (GstAdaptiveDemux * demux, GstEvent * seek)
314 {
315   GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (demux);
316   GstFormat format;
317   GstSeekFlags flags;
318   GstSeekType start_type, stop_type;
319   gint64 start, stop;
320   gdouble rate, old_rate;
321   GList *walk;
322   GstClockTime current_pos, target_pos, final_pos;
323   guint64 bitrate;
324 
325   gst_event_parse_seek (seek, &rate, &format, &flags, &start_type, &start,
326       &stop_type, &stop);
327 
328   if (!SEEK_UPDATES_PLAY_POSITION (rate, start_type, stop_type)) {
329     /* nothing to do if we don't have to update the current position */
330     return TRUE;
331   }
332 
333   old_rate = demux->segment.rate;
334 
335   bitrate = gst_hls_demux_get_bitrate (hlsdemux);
336 
337   /* Use I-frame variants for trick modes */
338   if (hlsdemux->master->iframe_variants != NULL
339       && rate < -1.0 && old_rate >= -1.0 && old_rate <= 1.0) {
340     GError *err = NULL;
341 
342     /* Switch to I-frame variant */
343     gst_hls_demux_set_current_variant (hlsdemux,
344         hlsdemux->master->iframe_variants->data);
345     gst_uri_downloader_reset (demux->downloader);
346     if (!gst_hls_demux_update_playlist (hlsdemux, FALSE, &err)) {
347       GST_ELEMENT_ERROR_FROM_ERROR (hlsdemux, "Could not switch playlist", err);
348       return FALSE;
349     }
350     //hlsdemux->discont = TRUE;
351 
352     gst_hls_demux_change_playlist (hlsdemux, bitrate / ABS (rate), NULL);
353   } else if (rate > -1.0 && rate <= 1.0 && (old_rate < -1.0 || old_rate > 1.0)) {
354     GError *err = NULL;
355     /* Switch to normal variant */
356     gst_hls_demux_set_current_variant (hlsdemux,
357         hlsdemux->master->variants->data);
358     gst_uri_downloader_reset (demux->downloader);
359     if (!gst_hls_demux_update_playlist (hlsdemux, FALSE, &err)) {
360       GST_ELEMENT_ERROR_FROM_ERROR (hlsdemux, "Could not switch playlist", err);
361       return FALSE;
362     }
363     //hlsdemux->discont = TRUE;
364     /* TODO why not continue using the same? that was being used up to now? */
365     gst_hls_demux_change_playlist (hlsdemux, bitrate, NULL);
366   }
367 
368   target_pos = rate < 0 ? stop : start;
369   final_pos = target_pos;
370 
371   /* properly cleanup pending decryption status */
372   if (flags & GST_SEEK_FLAG_FLUSH) {
373     gst_hls_demux_clear_all_pending_data (hlsdemux);
374   }
375 
376   for (walk = demux->streams; walk; walk = g_list_next (walk)) {
377     GstAdaptiveDemuxStream *stream =
378         GST_ADAPTIVE_DEMUX_STREAM_CAST (walk->data);
379 
380     gst_hls_demux_stream_seek (stream, rate >= 0, flags, target_pos,
381         &current_pos);
382 
383     /* FIXME: use minimum position always ? */
384     if (final_pos > current_pos)
385       final_pos = current_pos;
386   }
387 
388   if (IS_SNAP_SEEK (flags)) {
389     if (rate >= 0)
390       gst_segment_do_seek (&demux->segment, rate, format, flags, start_type,
391           final_pos, stop_type, stop, NULL);
392     else
393       gst_segment_do_seek (&demux->segment, rate, format, flags, start_type,
394           start, stop_type, final_pos, NULL);
395   }
396 
397   return TRUE;
398 }
399 
400 static GstFlowReturn
gst_hls_demux_stream_seek(GstAdaptiveDemuxStream * stream,gboolean forward,GstSeekFlags flags,GstClockTime ts,GstClockTime * final_ts)401 gst_hls_demux_stream_seek (GstAdaptiveDemuxStream * stream, gboolean forward,
402     GstSeekFlags flags, GstClockTime ts, GstClockTime * final_ts)
403 {
404   GstHLSDemuxStream *hls_stream = GST_HLS_DEMUX_STREAM_CAST (stream);
405   GList *walk;
406   GstClockTime current_pos;
407   gint64 current_sequence;
408   gboolean snap_after, snap_nearest;
409   GstM3U8MediaFile *file = NULL;
410 
411   current_sequence = 0;
412   current_pos = gst_m3u8_is_live (hls_stream->playlist) ?
413       hls_stream->playlist->first_file_start : 0;
414 
415   /* Snap to segment boundary. Improves seek performance on slow machines. */
416   snap_nearest =
417       (flags & GST_SEEK_FLAG_SNAP_NEAREST) == GST_SEEK_FLAG_SNAP_NEAREST;
418   snap_after = ! !(flags & GST_SEEK_FLAG_SNAP_AFTER);
419 
420   GST_M3U8_CLIENT_LOCK (hlsdemux->client);
421   /* FIXME: Here we need proper discont handling */
422   for (walk = hls_stream->playlist->files; walk; walk = walk->next) {
423     file = walk->data;
424 
425     current_sequence = file->sequence;
426     if ((forward && snap_after) || snap_nearest) {
427       if (current_pos >= ts)
428         break;
429       if (snap_nearest && ts - current_pos < file->duration / 2)
430         break;
431     } else if (!forward && snap_after) {
432       /* check if the next fragment is our target, in this case we want to
433        * start from the previous fragment */
434       GstClockTime next_pos = current_pos + file->duration;
435 
436       if (next_pos <= ts && ts < next_pos + file->duration) {
437         break;
438       }
439     } else if (current_pos <= ts && ts < current_pos + file->duration) {
440       break;
441     }
442     current_pos += file->duration;
443   }
444 
445   if (walk == NULL) {
446     GST_DEBUG_OBJECT (stream->pad, "seeking further than track duration");
447     current_sequence++;
448   }
449 
450   GST_DEBUG_OBJECT (stream->pad, "seeking to sequence %u",
451       (guint) current_sequence);
452   hls_stream->reset_pts = TRUE;
453   hls_stream->playlist->sequence = current_sequence;
454   hls_stream->playlist->current_file = walk;
455   hls_stream->playlist->sequence_position = current_pos;
456   GST_M3U8_CLIENT_UNLOCK (hlsdemux->client);
457 
458   /* Play from the end of the current selected segment */
459   if (file) {
460     if (!forward && IS_SNAP_SEEK (flags))
461       current_pos += file->duration;
462   }
463 
464   /* update stream's segment position */
465   stream->segment.position = current_pos;
466 
467   if (final_ts)
468     *final_ts = current_pos;
469 
470   return GST_FLOW_OK;
471 }
472 
473 static GstFlowReturn
gst_hls_demux_update_manifest(GstAdaptiveDemux * demux)474 gst_hls_demux_update_manifest (GstAdaptiveDemux * demux)
475 {
476   GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (demux);
477   if (!gst_hls_demux_update_playlist (hlsdemux, TRUE, NULL))
478     return GST_FLOW_ERROR;
479 
480   return GST_FLOW_OK;
481 }
482 
483 static void
create_stream_for_playlist(GstAdaptiveDemux * demux,GstM3U8 * playlist,gboolean is_primary_playlist,gboolean selected)484 create_stream_for_playlist (GstAdaptiveDemux * demux, GstM3U8 * playlist,
485     gboolean is_primary_playlist, gboolean selected)
486 {
487   GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (demux);
488   GstHLSDemuxStream *hlsdemux_stream;
489   GstAdaptiveDemuxStream *stream;
490 
491   if (!selected) {
492     /* FIXME: Later, create the stream but mark not-selected */
493     GST_LOG_OBJECT (demux, "Ignoring not-selected stream");
494     return;
495   }
496 
497   stream = gst_adaptive_demux_stream_new (demux,
498       gst_hls_demux_create_pad (hlsdemux));
499 
500   hlsdemux_stream = GST_HLS_DEMUX_STREAM_CAST (stream);
501 
502   hlsdemux_stream->stream_type = GST_HLS_TSREADER_NONE;
503 
504   hlsdemux_stream->playlist = gst_m3u8_ref (playlist);
505   hlsdemux_stream->is_primary_playlist = is_primary_playlist;
506 
507   hlsdemux_stream->do_typefind = TRUE;
508   hlsdemux_stream->reset_pts = TRUE;
509 }
510 
511 static gboolean
gst_hls_demux_setup_streams(GstAdaptiveDemux * demux)512 gst_hls_demux_setup_streams (GstAdaptiveDemux * demux)
513 {
514   GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (demux);
515   GstHLSVariantStream *playlist = hlsdemux->current_variant;
516   gint i;
517 
518   if (playlist == NULL) {
519     GST_WARNING_OBJECT (demux, "Can't configure streams - no variant selected");
520     return FALSE;
521   }
522 
523   gst_hls_demux_clear_all_pending_data (hlsdemux);
524 
525   /* 1 output for the main playlist */
526   create_stream_for_playlist (demux, playlist->m3u8, TRUE, TRUE);
527 
528   for (i = 0; i < GST_HLS_N_MEDIA_TYPES; ++i) {
529     GList *mlist = playlist->media[i];
530     while (mlist != NULL) {
531       GstHLSMedia *media = mlist->data;
532 
533       if (media->uri == NULL /* || media->mtype != GST_HLS_MEDIA_TYPE_AUDIO */ ) {
534         /* No uri means this is a placeholder for a stream
535          * contained in another mux */
536         GST_LOG_OBJECT (demux, "Skipping stream %s type %d with no URI",
537             media->name, media->mtype);
538         mlist = mlist->next;
539         continue;
540       }
541       GST_LOG_OBJECT (demux, "media of type %d - %s, uri: %s", i,
542           media->name, media->uri);
543       create_stream_for_playlist (demux, media->playlist, FALSE,
544           (media->mtype == GST_HLS_MEDIA_TYPE_VIDEO ||
545               media->mtype == GST_HLS_MEDIA_TYPE_AUDIO));
546 
547       mlist = mlist->next;
548     }
549   }
550 
551   return TRUE;
552 }
553 
554 static const gchar *
gst_adaptive_demux_get_manifest_ref_uri(GstAdaptiveDemux * d)555 gst_adaptive_demux_get_manifest_ref_uri (GstAdaptiveDemux * d)
556 {
557   return d->manifest_base_uri ? d->manifest_base_uri : d->manifest_uri;
558 }
559 
560 static void
gst_hls_demux_set_current_variant(GstHLSDemux * hlsdemux,GstHLSVariantStream * variant)561 gst_hls_demux_set_current_variant (GstHLSDemux * hlsdemux,
562     GstHLSVariantStream * variant)
563 {
564   if (hlsdemux->current_variant == variant || variant == NULL)
565     return;
566 
567   if (hlsdemux->current_variant != NULL) {
568     gint i;
569 
570     //#warning FIXME: Synching fragments across variants
571     //  should be done based on media timestamps, and
572     //  discont-sequence-numbers not sequence numbers.
573     variant->m3u8->sequence_position =
574         hlsdemux->current_variant->m3u8->sequence_position;
575     variant->m3u8->sequence = hlsdemux->current_variant->m3u8->sequence;
576 
577     GST_DEBUG_OBJECT (hlsdemux,
578         "Switching Variant. Copying over sequence %" G_GINT64_FORMAT
579         " and sequence_pos %" GST_TIME_FORMAT, variant->m3u8->sequence,
580         GST_TIME_ARGS (variant->m3u8->sequence_position));
581 
582     for (i = 0; i < GST_HLS_N_MEDIA_TYPES; ++i) {
583       GList *mlist = hlsdemux->current_variant->media[i];
584 
585       while (mlist != NULL) {
586         GstHLSMedia *old_media = mlist->data;
587         GstHLSMedia *new_media =
588             gst_hls_variant_find_matching_media (variant, old_media);
589 
590         if (new_media) {
591           new_media->playlist->sequence = old_media->playlist->sequence;
592           new_media->playlist->sequence_position =
593               old_media->playlist->sequence_position;
594         }
595         mlist = mlist->next;
596       }
597     }
598 
599     gst_hls_variant_stream_unref (hlsdemux->current_variant);
600   }
601 
602   hlsdemux->current_variant = gst_hls_variant_stream_ref (variant);
603 
604 }
605 
606 static gboolean
gst_hls_demux_process_manifest(GstAdaptiveDemux * demux,GstBuffer * buf)607 gst_hls_demux_process_manifest (GstAdaptiveDemux * demux, GstBuffer * buf)
608 {
609   GstHLSVariantStream *variant;
610   GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (demux);
611   gchar *playlist = NULL;
612 
613   GST_INFO_OBJECT (demux, "Initial playlist location: %s (base uri: %s)",
614       demux->manifest_uri, demux->manifest_base_uri);
615 
616   playlist = gst_hls_src_buf_to_utf8_playlist (buf);
617   if (playlist == NULL) {
618     GST_WARNING_OBJECT (demux, "Error validating initial playlist");
619     return FALSE;
620   }
621 
622   GST_M3U8_CLIENT_LOCK (self);
623   hlsdemux->master = gst_hls_master_playlist_new_from_data (playlist,
624       gst_adaptive_demux_get_manifest_ref_uri (demux));
625 
626   if (hlsdemux->master == NULL || hlsdemux->master->variants == NULL) {
627     /* In most cases, this will happen if we set a wrong url in the
628      * source element and we have received the 404 HTML response instead of
629      * the playlist */
630     GST_ELEMENT_ERROR (demux, STREAM, DECODE, ("Invalid playlist."),
631         ("Could not parse playlist. Check if the URL is correct."));
632     GST_M3U8_CLIENT_UNLOCK (self);
633     return FALSE;
634   }
635 
636   /* select the initial variant stream */
637   if (demux->connection_speed == 0) {
638     variant = hlsdemux->master->default_variant;
639   } else {
640     variant =
641         gst_hls_master_playlist_get_variant_for_bitrate (hlsdemux->master,
642         NULL, demux->connection_speed);
643   }
644 
645   if (variant) {
646     GST_INFO_OBJECT (hlsdemux, "selected %s", variant->name);
647     gst_hls_demux_set_current_variant (hlsdemux, variant);      // FIXME: inline?
648   }
649 
650   /* get the selected media playlist (unless the inital list was one already) */
651   if (!hlsdemux->master->is_simple) {
652     GError *err = NULL;
653 
654     if (!gst_hls_demux_update_playlist (hlsdemux, FALSE, &err)) {
655       GST_ELEMENT_ERROR_FROM_ERROR (demux, "Could not fetch media playlist",
656           err);
657       GST_M3U8_CLIENT_UNLOCK (self);
658       return FALSE;
659     }
660   }
661   GST_M3U8_CLIENT_UNLOCK (self);
662 
663   return gst_hls_demux_setup_streams (demux);
664 }
665 
666 static GstClockTime
gst_hls_demux_get_duration(GstAdaptiveDemux * demux)667 gst_hls_demux_get_duration (GstAdaptiveDemux * demux)
668 {
669   GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (demux);
670   GstClockTime duration = GST_CLOCK_TIME_NONE;
671 
672   if (hlsdemux->current_variant != NULL)
673     duration = gst_m3u8_get_duration (hlsdemux->current_variant->m3u8);
674 
675   return duration;
676 }
677 
678 static gboolean
gst_hls_demux_is_live(GstAdaptiveDemux * demux)679 gst_hls_demux_is_live (GstAdaptiveDemux * demux)
680 {
681   GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (demux);
682   gboolean is_live = FALSE;
683 
684   if (hlsdemux->current_variant)
685     is_live = gst_hls_variant_stream_is_live (hlsdemux->current_variant);
686 
687   return is_live;
688 }
689 
690 static const GstHLSKey *
gst_hls_demux_get_key(GstHLSDemux * demux,const gchar * key_url,const gchar * referer,gboolean allow_cache)691 gst_hls_demux_get_key (GstHLSDemux * demux, const gchar * key_url,
692     const gchar * referer, gboolean allow_cache)
693 {
694   GstFragment *key_fragment;
695   GstBuffer *key_buffer;
696   GstHLSKey *key;
697   GError *err = NULL;
698 
699   GST_LOG_OBJECT (demux, "Looking up key for key url %s", key_url);
700 
701   g_mutex_lock (&demux->keys_lock);
702 
703   key = g_hash_table_lookup (demux->keys, key_url);
704 
705   if (key != NULL) {
706     GST_LOG_OBJECT (demux, "Found key for key url %s in key cache", key_url);
707     goto out;
708   }
709 
710   GST_INFO_OBJECT (demux, "Fetching key %s", key_url);
711 
712   key_fragment =
713       gst_uri_downloader_fetch_uri (GST_ADAPTIVE_DEMUX (demux)->downloader,
714       key_url, referer, FALSE, FALSE, allow_cache, &err);
715 
716   if (key_fragment == NULL) {
717     GST_WARNING_OBJECT (demux, "Failed to download key to decrypt data: %s",
718         err ? err->message : "error");
719     g_clear_error (&err);
720     goto out;
721   }
722 
723   key_buffer = gst_fragment_get_buffer (key_fragment);
724 
725   key = g_new0 (GstHLSKey, 1);
726   if (gst_buffer_extract (key_buffer, 0, key->data, 16) < 16)
727     GST_WARNING_OBJECT (demux, "Download decryption key is too short!");
728 
729   g_hash_table_insert (demux->keys, g_strdup (key_url), key);
730 
731   gst_buffer_unref (key_buffer);
732   g_object_unref (key_fragment);
733 
734 out:
735 
736   g_mutex_unlock (&demux->keys_lock);
737 
738   if (key != NULL)
739     GST_MEMDUMP_OBJECT (demux, "Key", key->data, 16);
740 
741   return key;
742 }
743 
744 static gboolean
gst_hls_demux_start_fragment(GstAdaptiveDemux * demux,GstAdaptiveDemuxStream * stream)745 gst_hls_demux_start_fragment (GstAdaptiveDemux * demux,
746     GstAdaptiveDemuxStream * stream)
747 {
748   GstHLSDemuxStream *hls_stream = GST_HLS_DEMUX_STREAM_CAST (stream);
749   GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (demux);
750   const GstHLSKey *key;
751   GstM3U8 *m3u8;
752 
753   gst_hls_demux_stream_clear_pending_data (hls_stream);
754 
755   /* Init the timestamp reader for this fragment */
756   gst_hlsdemux_tsreader_init (&hls_stream->tsreader);
757   /* Reset the stream type if we already know it */
758   gst_hlsdemux_tsreader_set_type (&hls_stream->tsreader,
759       hls_stream->stream_type);
760 
761   /* If no decryption is needed, there's nothing to be done here */
762   if (hls_stream->current_key == NULL)
763     return TRUE;
764 
765   m3u8 = gst_hls_demux_stream_get_m3u8 (hls_stream);
766 
767   key = gst_hls_demux_get_key (hlsdemux, hls_stream->current_key,
768       m3u8->uri, m3u8->allowcache);
769 
770   if (key == NULL)
771     goto key_failed;
772 
773   gst_hls_demux_stream_decrypt_start (hls_stream, key->data,
774       hls_stream->current_iv);
775 
776   return TRUE;
777 
778 key_failed:
779   {
780     GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
781         ("Couldn't retrieve key for decryption"), (NULL));
782     GST_WARNING_OBJECT (demux, "Failed to decrypt data");
783     return FALSE;
784   }
785 }
786 
787 static GstHLSTSReaderType
caps_to_reader(const GstCaps * caps)788 caps_to_reader (const GstCaps * caps)
789 {
790   const GstStructure *s = gst_caps_get_structure (caps, 0);
791 
792   if (gst_structure_has_name (s, "video/mpegts"))
793     return GST_HLS_TSREADER_MPEGTS;
794   if (gst_structure_has_name (s, "application/x-id3"))
795     return GST_HLS_TSREADER_ID3;
796 
797   return GST_HLS_TSREADER_NONE;
798 }
799 
800 static GstFlowReturn
gst_hls_demux_handle_buffer(GstAdaptiveDemux * demux,GstAdaptiveDemuxStream * stream,GstBuffer * buffer,gboolean at_eos)801 gst_hls_demux_handle_buffer (GstAdaptiveDemux * demux,
802     GstAdaptiveDemuxStream * stream, GstBuffer * buffer, gboolean at_eos)
803 {
804   GstHLSDemuxStream *hls_stream = GST_HLS_DEMUX_STREAM_CAST (stream);   // FIXME: pass HlsStream into function
805   GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (demux);
806   GstClockTime first_pcr, last_pcr;
807   GstTagList *tags;
808 
809   if (buffer == NULL)
810     return GST_FLOW_OK;
811 
812   if (G_UNLIKELY (hls_stream->do_typefind)) {
813     GstCaps *caps = NULL;
814     guint buffer_size;
815     GstTypeFindProbability prob = GST_TYPE_FIND_NONE;
816     GstMapInfo info;
817 
818     if (hls_stream->pending_typefind_buffer)
819       buffer = gst_buffer_append (hls_stream->pending_typefind_buffer, buffer);
820     hls_stream->pending_typefind_buffer = NULL;
821 
822     gst_buffer_map (buffer, &info, GST_MAP_READ);
823     buffer_size = info.size;
824 
825     /* Typefind could miss if buffer is too small. In this case we
826      * will retry later */
827     if (buffer_size >= (2 * 1024) || at_eos) {
828       caps =
829           gst_type_find_helper_for_data (GST_OBJECT_CAST (hlsdemux), info.data,
830           info.size, &prob);
831     }
832 
833     if (G_UNLIKELY (!caps)) {
834       /* Won't need this mapping any more all paths return inside this if() */
835       gst_buffer_unmap (buffer, &info);
836 
837       /* Only fail typefinding if we already a good amount of data
838        * and we still don't know the type */
839       if (buffer_size > (2 * 1024 * 1024) || at_eos) {
840         GST_ELEMENT_ERROR (hlsdemux, STREAM, TYPE_NOT_FOUND,
841             ("Could not determine type of stream"), (NULL));
842         gst_buffer_unref (buffer);
843         return GST_FLOW_NOT_NEGOTIATED;
844       }
845 
846       hls_stream->pending_typefind_buffer = buffer;
847 
848       return GST_FLOW_OK;
849     }
850 
851     GST_DEBUG_OBJECT (hlsdemux, "Typefind result: %" GST_PTR_FORMAT " prob:%d",
852         caps, prob);
853 
854     hls_stream->stream_type = caps_to_reader (caps);
855     gst_hlsdemux_tsreader_set_type (&hls_stream->tsreader,
856         hls_stream->stream_type);
857 
858     gst_adaptive_demux_stream_set_caps (stream, caps);
859 
860     hls_stream->do_typefind = FALSE;
861 
862     gst_buffer_unmap (buffer, &info);
863   }
864   g_assert (hls_stream->pending_typefind_buffer == NULL);
865 
866   // Accumulate this buffer
867   if (hls_stream->pending_pcr_buffer) {
868     buffer = gst_buffer_append (hls_stream->pending_pcr_buffer, buffer);
869     hls_stream->pending_pcr_buffer = NULL;
870   }
871 
872   if (!gst_hlsdemux_tsreader_find_pcrs (&hls_stream->tsreader, &buffer,
873           &first_pcr, &last_pcr, &tags)
874       && !at_eos) {
875     // Store this buffer for later
876     hls_stream->pending_pcr_buffer = buffer;
877     return GST_FLOW_OK;
878   }
879 
880   if (tags) {
881     gst_adaptive_demux_stream_set_tags (stream, tags);
882     /* run typefind again on the trimmed buffer */
883     hls_stream->do_typefind = TRUE;
884     return gst_hls_demux_handle_buffer (demux, stream, buffer, at_eos);
885   }
886 
887   if (buffer) {
888     buffer = gst_buffer_make_writable (buffer);
889     GST_BUFFER_OFFSET (buffer) = hls_stream->current_offset;
890     hls_stream->current_offset += gst_buffer_get_size (buffer);
891     GST_BUFFER_OFFSET_END (buffer) = hls_stream->current_offset;
892     return gst_adaptive_demux_stream_push_buffer (stream, buffer);
893   }
894   return GST_FLOW_OK;
895 }
896 
897 static GstFlowReturn
gst_hls_demux_finish_fragment(GstAdaptiveDemux * demux,GstAdaptiveDemuxStream * stream)898 gst_hls_demux_finish_fragment (GstAdaptiveDemux * demux,
899     GstAdaptiveDemuxStream * stream)
900 {
901   GstHLSDemuxStream *hls_stream = GST_HLS_DEMUX_STREAM_CAST (stream);   // FIXME: pass HlsStream into function
902   GstFlowReturn ret = GST_FLOW_OK;
903 
904   if (hls_stream->current_key)
905     gst_hls_demux_stream_decrypt_end (hls_stream);
906 
907   if (stream->last_ret == GST_FLOW_OK) {
908     if (hls_stream->pending_decrypted_buffer) {
909       if (hls_stream->current_key) {
910         GstMapInfo info;
911         gssize unpadded_size;
912 
913         /* Handle pkcs7 unpadding here */
914         gst_buffer_map (hls_stream->pending_decrypted_buffer, &info,
915             GST_MAP_READ);
916         unpadded_size = info.size - info.data[info.size - 1];
917         gst_buffer_unmap (hls_stream->pending_decrypted_buffer, &info);
918 
919         gst_buffer_resize (hls_stream->pending_decrypted_buffer, 0,
920             unpadded_size);
921       }
922 
923       ret =
924           gst_hls_demux_handle_buffer (demux, stream,
925           hls_stream->pending_decrypted_buffer, TRUE);
926       hls_stream->pending_decrypted_buffer = NULL;
927     }
928 
929     if (ret == GST_FLOW_OK || ret == GST_FLOW_NOT_LINKED) {
930       if (G_UNLIKELY (hls_stream->pending_typefind_buffer)) {
931         GstBuffer *buf = hls_stream->pending_typefind_buffer;
932         hls_stream->pending_typefind_buffer = NULL;
933 
934         gst_hls_demux_handle_buffer (demux, stream, buf, TRUE);
935       }
936 
937       if (hls_stream->pending_pcr_buffer) {
938         GstBuffer *buf = hls_stream->pending_pcr_buffer;
939         hls_stream->pending_pcr_buffer = NULL;
940 
941         ret = gst_hls_demux_handle_buffer (demux, stream, buf, TRUE);
942       }
943 
944       GST_LOG_OBJECT (stream,
945           "Fragment PCRs were %" GST_TIME_FORMAT " to %" GST_TIME_FORMAT,
946           GST_TIME_ARGS (hls_stream->tsreader.first_pcr),
947           GST_TIME_ARGS (hls_stream->tsreader.last_pcr));
948     }
949   }
950 
951   gst_hls_demux_stream_clear_pending_data (hls_stream);
952 
953   if (ret == GST_FLOW_OK || ret == GST_FLOW_NOT_LINKED)
954     return gst_adaptive_demux_stream_advance_fragment (demux, stream,
955         stream->fragment.duration);
956   return ret;
957 }
958 
959 static GstFlowReturn
gst_hls_demux_data_received(GstAdaptiveDemux * demux,GstAdaptiveDemuxStream * stream,GstBuffer * buffer)960 gst_hls_demux_data_received (GstAdaptiveDemux * demux,
961     GstAdaptiveDemuxStream * stream, GstBuffer * buffer)
962 {
963   GstHLSDemuxStream *hls_stream = GST_HLS_DEMUX_STREAM_CAST (stream);
964   GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (demux);
965 
966   if (hls_stream->current_offset == -1)
967     hls_stream->current_offset = 0;
968 
969   /* Is it encrypted? */
970   if (hls_stream->current_key) {
971     GError *err = NULL;
972     gsize size;
973     GstBuffer *tmp_buffer;
974 
975     if (hls_stream->pending_encrypted_data == NULL)
976       hls_stream->pending_encrypted_data = gst_adapter_new ();
977 
978     gst_adapter_push (hls_stream->pending_encrypted_data, buffer);
979     size = gst_adapter_available (hls_stream->pending_encrypted_data);
980 
981     /* must be a multiple of 16 */
982     size &= (~0xF);
983 
984     if (size == 0) {
985       return GST_FLOW_OK;
986     }
987 
988     buffer = gst_adapter_take_buffer (hls_stream->pending_encrypted_data, size);
989     buffer =
990         gst_hls_demux_decrypt_fragment (hlsdemux, hls_stream, buffer, &err);
991     if (buffer == NULL) {
992       GST_ELEMENT_ERROR (demux, STREAM, DECODE, ("Failed to decrypt buffer"),
993           ("decryption failed %s", err->message));
994       g_error_free (err);
995       return GST_FLOW_ERROR;
996     }
997 
998     tmp_buffer = hls_stream->pending_decrypted_buffer;
999     hls_stream->pending_decrypted_buffer = buffer;
1000     buffer = tmp_buffer;
1001   }
1002 
1003   return gst_hls_demux_handle_buffer (demux, stream, buffer, FALSE);
1004 }
1005 
1006 static void
gst_hls_demux_stream_free(GstAdaptiveDemuxStream * stream)1007 gst_hls_demux_stream_free (GstAdaptiveDemuxStream * stream)
1008 {
1009   GstHLSDemuxStream *hls_stream = GST_HLS_DEMUX_STREAM_CAST (stream);
1010 
1011   if (hls_stream->playlist) {
1012     gst_m3u8_unref (hls_stream->playlist);
1013     hls_stream->playlist = NULL;
1014   }
1015 
1016   if (hls_stream->pending_encrypted_data)
1017     g_object_unref (hls_stream->pending_encrypted_data);
1018 
1019   gst_buffer_replace (&hls_stream->pending_decrypted_buffer, NULL);
1020   gst_buffer_replace (&hls_stream->pending_typefind_buffer, NULL);
1021   gst_buffer_replace (&hls_stream->pending_pcr_buffer, NULL);
1022 
1023   if (hls_stream->current_key) {
1024     g_free (hls_stream->current_key);
1025     hls_stream->current_key = NULL;
1026   }
1027   if (hls_stream->current_iv) {
1028     g_free (hls_stream->current_iv);
1029     hls_stream->current_iv = NULL;
1030   }
1031   gst_hls_demux_stream_decrypt_end (hls_stream);
1032 }
1033 
1034 static GstM3U8 *
gst_hls_demux_stream_get_m3u8(GstHLSDemuxStream * hlsdemux_stream)1035 gst_hls_demux_stream_get_m3u8 (GstHLSDemuxStream * hlsdemux_stream)
1036 {
1037   GstM3U8 *m3u8;
1038 
1039   m3u8 = hlsdemux_stream->playlist;
1040 
1041   return m3u8;
1042 }
1043 
1044 static gboolean
gst_hls_demux_stream_has_next_fragment(GstAdaptiveDemuxStream * stream)1045 gst_hls_demux_stream_has_next_fragment (GstAdaptiveDemuxStream * stream)
1046 {
1047   gboolean has_next;
1048   GstM3U8 *m3u8;
1049 
1050   m3u8 = gst_hls_demux_stream_get_m3u8 (GST_HLS_DEMUX_STREAM_CAST (stream));
1051 
1052   has_next = gst_m3u8_has_next_fragment (m3u8, stream->demux->segment.rate > 0);
1053 
1054   return has_next;
1055 }
1056 
1057 static GstFlowReturn
gst_hls_demux_advance_fragment(GstAdaptiveDemuxStream * stream)1058 gst_hls_demux_advance_fragment (GstAdaptiveDemuxStream * stream)
1059 {
1060   GstHLSDemuxStream *hlsdemux_stream = GST_HLS_DEMUX_STREAM_CAST (stream);
1061   GstM3U8 *m3u8;
1062 
1063   m3u8 = gst_hls_demux_stream_get_m3u8 (hlsdemux_stream);
1064 
1065   gst_m3u8_advance_fragment (m3u8, stream->demux->segment.rate > 0);
1066   hlsdemux_stream->reset_pts = FALSE;
1067 
1068   return GST_FLOW_OK;
1069 }
1070 
1071 static GstFlowReturn
gst_hls_demux_update_fragment_info(GstAdaptiveDemuxStream * stream)1072 gst_hls_demux_update_fragment_info (GstAdaptiveDemuxStream * stream)
1073 {
1074   GstHLSDemuxStream *hlsdemux_stream = GST_HLS_DEMUX_STREAM_CAST (stream);
1075   GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (stream->demux);
1076   GstM3U8MediaFile *file;
1077   GstClockTime sequence_pos;
1078   gboolean discont, forward;
1079   GstM3U8 *m3u8;
1080 
1081   m3u8 = gst_hls_demux_stream_get_m3u8 (hlsdemux_stream);
1082 
1083   forward = (stream->demux->segment.rate > 0);
1084   file = gst_m3u8_get_next_fragment (m3u8, forward, &sequence_pos, &discont);
1085 
1086   if (file == NULL) {
1087     GST_INFO_OBJECT (hlsdemux, "This playlist doesn't contain more fragments");
1088     return GST_FLOW_EOS;
1089   }
1090 
1091   if (stream->discont)
1092     discont = TRUE;
1093 
1094   /* set up our source for download */
1095   if (hlsdemux_stream->reset_pts || discont
1096       || stream->demux->segment.rate < 0.0) {
1097     stream->fragment.timestamp = sequence_pos;
1098   } else {
1099     stream->fragment.timestamp = GST_CLOCK_TIME_NONE;
1100   }
1101 
1102   g_free (hlsdemux_stream->current_key);
1103   hlsdemux_stream->current_key = g_strdup (file->key);
1104   g_free (hlsdemux_stream->current_iv);
1105   hlsdemux_stream->current_iv = g_memdup (file->iv, sizeof (file->iv));
1106 
1107   g_free (stream->fragment.uri);
1108   stream->fragment.uri = g_strdup (file->uri);
1109 
1110   GST_DEBUG_OBJECT (hlsdemux, "Stream %p URI now %s", stream, file->uri);
1111 
1112   stream->fragment.range_start = file->offset;
1113   if (file->size != -1)
1114     stream->fragment.range_end = file->offset + file->size - 1;
1115   else
1116     stream->fragment.range_end = -1;
1117 
1118   stream->fragment.duration = file->duration;
1119 
1120   if (discont)
1121     stream->discont = TRUE;
1122 
1123   gst_m3u8_media_file_unref (file);
1124 
1125   return GST_FLOW_OK;
1126 }
1127 
1128 static gboolean
gst_hls_demux_select_bitrate(GstAdaptiveDemuxStream * stream,guint64 bitrate)1129 gst_hls_demux_select_bitrate (GstAdaptiveDemuxStream * stream, guint64 bitrate)
1130 {
1131   GstAdaptiveDemux *demux = GST_ADAPTIVE_DEMUX_CAST (stream->demux);
1132   GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (stream->demux);
1133   GstHLSDemuxStream *hls_stream = GST_HLS_DEMUX_STREAM_CAST (stream);
1134 
1135   gboolean changed = FALSE;
1136 
1137   GST_M3U8_CLIENT_LOCK (hlsdemux->client);
1138   if (hlsdemux->master == NULL || hlsdemux->master->is_simple) {
1139     GST_M3U8_CLIENT_UNLOCK (hlsdemux->client);
1140     return FALSE;
1141   }
1142   GST_M3U8_CLIENT_UNLOCK (hlsdemux->client);
1143 
1144   if (hls_stream->is_primary_playlist == FALSE) {
1145     GST_LOG_OBJECT (hlsdemux,
1146         "Stream %p Not choosing new bitrate - not the primary stream", stream);
1147     return FALSE;
1148   }
1149 
1150   gst_hls_demux_change_playlist (hlsdemux, bitrate / MAX (1.0,
1151           ABS (demux->segment.rate)), &changed);
1152   if (changed)
1153     gst_hls_demux_setup_streams (GST_ADAPTIVE_DEMUX_CAST (hlsdemux));
1154   return changed;
1155 }
1156 
1157 static void
gst_hls_demux_reset(GstAdaptiveDemux * ademux)1158 gst_hls_demux_reset (GstAdaptiveDemux * ademux)
1159 {
1160   GstHLSDemux *demux = GST_HLS_DEMUX_CAST (ademux);
1161 
1162   GST_DEBUG_OBJECT (demux, "resetting");
1163 
1164   GST_M3U8_CLIENT_LOCK (hlsdemux->client);
1165   if (demux->master) {
1166     gst_hls_master_playlist_unref (demux->master);
1167     demux->master = NULL;
1168   }
1169   if (demux->current_variant != NULL) {
1170     gst_hls_variant_stream_unref (demux->current_variant);
1171     demux->current_variant = NULL;
1172   }
1173   demux->srcpad_counter = 0;
1174 
1175   gst_hls_demux_clear_all_pending_data (demux);
1176   GST_M3U8_CLIENT_UNLOCK (hlsdemux->client);
1177 }
1178 
1179 static gchar *
gst_hls_src_buf_to_utf8_playlist(GstBuffer * buf)1180 gst_hls_src_buf_to_utf8_playlist (GstBuffer * buf)
1181 {
1182   GstMapInfo info;
1183   gchar *playlist;
1184 
1185   if (!gst_buffer_map (buf, &info, GST_MAP_READ))
1186     goto map_error;
1187 
1188   if (!g_utf8_validate ((gchar *) info.data, info.size, NULL))
1189     goto validate_error;
1190 
1191   /* alloc size + 1 to end with a null character */
1192   playlist = g_malloc0 (info.size + 1);
1193   memcpy (playlist, info.data, info.size);
1194 
1195   gst_buffer_unmap (buf, &info);
1196   return playlist;
1197 
1198 validate_error:
1199   gst_buffer_unmap (buf, &info);
1200 map_error:
1201   return NULL;
1202 }
1203 
1204 static gint
gst_hls_demux_find_variant_match(const GstHLSVariantStream * a,const GstHLSVariantStream * b)1205 gst_hls_demux_find_variant_match (const GstHLSVariantStream * a,
1206     const GstHLSVariantStream * b)
1207 {
1208   if (g_strcmp0 (a->name, b->name) == 0 &&
1209       a->bandwidth == b->bandwidth &&
1210       a->program_id == b->program_id &&
1211       g_strcmp0 (a->codecs, b->codecs) == 0 &&
1212       a->width == b->width &&
1213       a->height == b->height && a->iframe == b->iframe) {
1214     return 0;
1215   }
1216 
1217   return 1;
1218 }
1219 
1220 /* Update the master playlist, which contains the list of available
1221  * variants */
1222 static gboolean
gst_hls_demux_update_variant_playlist(GstHLSDemux * hlsdemux,gchar * data,const gchar * uri,const gchar * base_uri)1223 gst_hls_demux_update_variant_playlist (GstHLSDemux * hlsdemux, gchar * data,
1224     const gchar * uri, const gchar * base_uri)
1225 {
1226   GstHLSMasterPlaylist *new_master, *old;
1227   gboolean ret = FALSE;
1228   GList *l, *unmatched_lists;
1229   GstHLSVariantStream *new_variant;
1230 
1231   new_master = gst_hls_master_playlist_new_from_data (data, base_uri ? base_uri : uri); // FIXME: check which uri to use here
1232 
1233   if (new_master == NULL)
1234     return ret;
1235 
1236   if (new_master->is_simple) {
1237     // FIXME: we should be able to support this though, in the unlikely
1238     // case that it changed?
1239     GST_ERROR
1240         ("Cannot update variant playlist: New playlist is not a variant playlist");
1241     gst_hls_master_playlist_unref (new_master);
1242     return FALSE;
1243   }
1244 
1245   GST_M3U8_CLIENT_LOCK (self);
1246 
1247   if (hlsdemux->master->is_simple) {
1248     GST_ERROR
1249         ("Cannot update variant playlist: Current playlist is not a variant playlist");
1250     gst_hls_master_playlist_unref (new_master);
1251     goto out;
1252   }
1253 
1254   /* Now see if the variant playlist still has the same lists */
1255   unmatched_lists = g_list_copy (hlsdemux->master->variants);
1256   for (l = new_master->variants; l != NULL; l = l->next) {
1257     GList *match = g_list_find_custom (unmatched_lists, l->data,
1258         (GCompareFunc) gst_hls_demux_find_variant_match);
1259 
1260     if (match) {
1261       GstHLSVariantStream *variant = l->data;
1262       GstHLSVariantStream *old = match->data;
1263 
1264       unmatched_lists = g_list_delete_link (unmatched_lists, match);
1265       /* FIXME: Deal with losing position due to missing an update */
1266       variant->m3u8->sequence_position = old->m3u8->sequence_position;
1267       variant->m3u8->sequence = old->m3u8->sequence;
1268     }
1269   }
1270 
1271   if (unmatched_lists != NULL) {
1272     GST_WARNING ("Unable to match all playlists");
1273 
1274     for (l = unmatched_lists; l != NULL; l = l->next) {
1275       if (l->data == hlsdemux->current_variant) {
1276         GST_WARNING ("Unable to match current playlist");
1277       }
1278     }
1279 
1280     g_list_free (unmatched_lists);
1281   }
1282 
1283   /* Switch out the variant playlist */
1284   old = hlsdemux->master;
1285 
1286   // FIXME: check all this and also switch of variants, if anything needs updating
1287   hlsdemux->master = new_master;
1288 
1289   if (hlsdemux->current_variant == NULL) {
1290     new_variant = new_master->default_variant;
1291   } else {
1292     /* Find the same variant in the new playlist */
1293     new_variant =
1294         gst_hls_master_playlist_get_matching_variant (new_master,
1295         hlsdemux->current_variant);
1296   }
1297 
1298   /* Use the function to set the current variant, as it copies over data */
1299   if (new_variant != NULL)
1300     gst_hls_demux_set_current_variant (hlsdemux, new_variant);
1301 
1302   gst_hls_master_playlist_unref (old);
1303 
1304   ret = (hlsdemux->current_variant != NULL);
1305 out:
1306   GST_M3U8_CLIENT_UNLOCK (self);
1307 
1308   return ret;
1309 }
1310 
1311 static gboolean
gst_hls_demux_update_rendition_manifest(GstHLSDemux * demux,GstHLSMedia * media,GError ** err)1312 gst_hls_demux_update_rendition_manifest (GstHLSDemux * demux,
1313     GstHLSMedia * media, GError ** err)
1314 {
1315   GstAdaptiveDemux *adaptive_demux = GST_ADAPTIVE_DEMUX (demux);
1316   GstFragment *download;
1317   GstBuffer *buf;
1318   gchar *playlist;
1319   const gchar *main_uri;
1320   GstM3U8 *m3u8;
1321   gchar *uri = media->uri;
1322 
1323   main_uri = gst_adaptive_demux_get_manifest_ref_uri (adaptive_demux);
1324   download =
1325       gst_uri_downloader_fetch_uri (adaptive_demux->downloader, uri, main_uri,
1326       TRUE, TRUE, TRUE, err);
1327 
1328   if (download == NULL)
1329     return FALSE;
1330 
1331   m3u8 = media->playlist;
1332 
1333   /* Set the base URI of the playlist to the redirect target if any */
1334   if (download->redirect_permanent && download->redirect_uri) {
1335     gst_m3u8_set_uri (m3u8, download->redirect_uri, NULL, media->name);
1336   } else {
1337     gst_m3u8_set_uri (m3u8, download->uri, download->redirect_uri, media->name);
1338   }
1339 
1340   buf = gst_fragment_get_buffer (download);
1341   playlist = gst_hls_src_buf_to_utf8_playlist (buf);
1342   gst_buffer_unref (buf);
1343   g_object_unref (download);
1344 
1345   if (playlist == NULL) {
1346     GST_WARNING_OBJECT (demux, "Couldn't validate playlist encoding");
1347     g_set_error (err, GST_STREAM_ERROR, GST_STREAM_ERROR_WRONG_TYPE,
1348         "Couldn't validate playlist encoding");
1349     return FALSE;
1350   }
1351 
1352   if (!gst_m3u8_update (m3u8, playlist)) {
1353     GST_WARNING_OBJECT (demux, "Couldn't update playlist");
1354     g_set_error (err, GST_STREAM_ERROR, GST_STREAM_ERROR_FAILED,
1355         "Couldn't update playlist");
1356     return FALSE;
1357   }
1358 
1359   return TRUE;
1360 }
1361 
1362 static gboolean
gst_hls_demux_update_playlist(GstHLSDemux * demux,gboolean update,GError ** err)1363 gst_hls_demux_update_playlist (GstHLSDemux * demux, gboolean update,
1364     GError ** err)
1365 {
1366   GstAdaptiveDemux *adaptive_demux = GST_ADAPTIVE_DEMUX (demux);
1367   GstFragment *download;
1368   GstBuffer *buf;
1369   gchar *playlist;
1370   gboolean main_checked = FALSE;
1371   const gchar *main_uri;
1372   GstM3U8 *m3u8;
1373   gchar *uri;
1374   gint i;
1375 
1376 retry:
1377   uri = gst_m3u8_get_uri (demux->current_variant->m3u8);
1378   main_uri = gst_adaptive_demux_get_manifest_ref_uri (adaptive_demux);
1379   download =
1380       gst_uri_downloader_fetch_uri (adaptive_demux->downloader, uri, main_uri,
1381       TRUE, TRUE, TRUE, err);
1382   if (download == NULL) {
1383     gchar *base_uri;
1384 
1385     if (!update || main_checked || demux->master->is_simple
1386         || !gst_adaptive_demux_is_running (GST_ADAPTIVE_DEMUX_CAST (demux))) {
1387       g_free (uri);
1388       return FALSE;
1389     }
1390     g_clear_error (err);
1391     GST_INFO_OBJECT (demux,
1392         "Updating playlist %s failed, attempt to refresh variant playlist %s",
1393         uri, main_uri);
1394     download =
1395         gst_uri_downloader_fetch_uri (adaptive_demux->downloader,
1396         main_uri, NULL, TRUE, TRUE, TRUE, err);
1397     if (download == NULL) {
1398       g_free (uri);
1399       return FALSE;
1400     }
1401 
1402     buf = gst_fragment_get_buffer (download);
1403     playlist = gst_hls_src_buf_to_utf8_playlist (buf);
1404     gst_buffer_unref (buf);
1405 
1406     if (playlist == NULL) {
1407       GST_WARNING_OBJECT (demux,
1408           "Failed to validate variant playlist encoding");
1409       g_free (uri);
1410       g_object_unref (download);
1411       g_set_error (err, GST_STREAM_ERROR, GST_STREAM_ERROR_WRONG_TYPE,
1412           "Couldn't validate playlist encoding");
1413       return FALSE;
1414     }
1415 
1416     g_free (uri);
1417     if (download->redirect_permanent && download->redirect_uri) {
1418       uri = download->redirect_uri;
1419       base_uri = NULL;
1420     } else {
1421       uri = download->uri;
1422       base_uri = download->redirect_uri;
1423     }
1424 
1425     if (!gst_hls_demux_update_variant_playlist (demux, playlist, uri, base_uri)) {
1426       GST_WARNING_OBJECT (demux, "Failed to update the variant playlist");
1427       g_object_unref (download);
1428       g_set_error (err, GST_STREAM_ERROR, GST_STREAM_ERROR_FAILED,
1429           "Couldn't update playlist");
1430       return FALSE;
1431     }
1432 
1433     g_object_unref (download);
1434 
1435     main_checked = TRUE;
1436     goto retry;
1437   }
1438   g_free (uri);
1439 
1440   m3u8 = demux->current_variant->m3u8;
1441 
1442   /* Set the base URI of the playlist to the redirect target if any */
1443   if (download->redirect_permanent && download->redirect_uri) {
1444     gst_m3u8_set_uri (m3u8, download->redirect_uri, NULL,
1445         demux->current_variant->name);
1446   } else {
1447     gst_m3u8_set_uri (m3u8, download->uri, download->redirect_uri,
1448         demux->current_variant->name);
1449   }
1450 
1451   buf = gst_fragment_get_buffer (download);
1452   playlist = gst_hls_src_buf_to_utf8_playlist (buf);
1453   gst_buffer_unref (buf);
1454   g_object_unref (download);
1455 
1456   if (playlist == NULL) {
1457     GST_WARNING_OBJECT (demux, "Couldn't validate playlist encoding");
1458     g_set_error (err, GST_STREAM_ERROR, GST_STREAM_ERROR_WRONG_TYPE,
1459         "Couldn't validate playlist encoding");
1460     return FALSE;
1461   }
1462 
1463   if (!gst_m3u8_update (m3u8, playlist)) {
1464     GST_WARNING_OBJECT (demux, "Couldn't update playlist");
1465     g_set_error (err, GST_STREAM_ERROR, GST_STREAM_ERROR_FAILED,
1466         "Couldn't update playlist");
1467     return FALSE;
1468   }
1469 
1470   for (i = 0; i < GST_HLS_N_MEDIA_TYPES; ++i) {
1471     GList *mlist = demux->current_variant->media[i];
1472 
1473     while (mlist != NULL) {
1474       GstHLSMedia *media = mlist->data;
1475 
1476       if (media->uri == NULL) {
1477         /* No uri means this is a placeholder for a stream
1478          * contained in another mux */
1479         mlist = mlist->next;
1480         continue;
1481       }
1482       GST_LOG_OBJECT (demux,
1483           "Updating playlist for media of type %d - %s, uri: %s", i,
1484           media->name, media->uri);
1485 
1486       if (!gst_hls_demux_update_rendition_manifest (demux, media, err))
1487         return FALSE;
1488 
1489       mlist = mlist->next;
1490     }
1491   }
1492 
1493   /* If it's a live source, do not let the sequence number go beyond
1494    * three fragments before the end of the list */
1495   if (update == FALSE && gst_m3u8_is_live (m3u8)) {
1496     gint64 last_sequence, first_sequence;
1497 
1498     GST_M3U8_CLIENT_LOCK (demux->client);
1499     last_sequence =
1500         GST_M3U8_MEDIA_FILE (g_list_last (m3u8->files)->data)->sequence;
1501     first_sequence =
1502         GST_M3U8_MEDIA_FILE (g_list_first (m3u8->files)->data)->sequence;
1503 
1504     GST_DEBUG_OBJECT (demux,
1505         "sequence:%" G_GINT64_FORMAT " , first_sequence:%" G_GINT64_FORMAT
1506         " , last_sequence:%" G_GINT64_FORMAT, m3u8->sequence,
1507         first_sequence, last_sequence);
1508     if (m3u8->sequence > last_sequence - 3) {
1509       //demux->need_segment = TRUE;
1510       /* Make sure we never go below the minimum sequence number */
1511       m3u8->sequence = MAX (first_sequence, last_sequence - 3);
1512       GST_DEBUG_OBJECT (demux,
1513           "Sequence is beyond playlist. Moving back to %" G_GINT64_FORMAT,
1514           m3u8->sequence);
1515     }
1516     GST_M3U8_CLIENT_UNLOCK (demux->client);
1517   } else if (!gst_m3u8_is_live (m3u8)) {
1518     GstClockTime current_pos, target_pos;
1519     guint sequence = 0;
1520     GList *walk;
1521 
1522     /* Sequence numbers are not guaranteed to be the same in different
1523      * playlists, so get the correct fragment here based on the current
1524      * position
1525      */
1526     GST_M3U8_CLIENT_LOCK (demux->client);
1527 
1528     /* Valid because hlsdemux only has a single output */
1529     if (GST_ADAPTIVE_DEMUX_CAST (demux)->streams) {
1530       GstAdaptiveDemuxStream *stream =
1531           GST_ADAPTIVE_DEMUX_CAST (demux)->streams->data;
1532       target_pos = stream->segment.position;
1533     } else {
1534       target_pos = 0;
1535     }
1536     if (GST_CLOCK_TIME_IS_VALID (m3u8->sequence_position)) {
1537       target_pos = MAX (target_pos, m3u8->sequence_position);
1538     }
1539 
1540     GST_LOG_OBJECT (demux, "Looking for sequence position %"
1541         GST_TIME_FORMAT " in updated playlist", GST_TIME_ARGS (target_pos));
1542 
1543     current_pos = 0;
1544     for (walk = m3u8->files; walk; walk = walk->next) {
1545       GstM3U8MediaFile *file = walk->data;
1546 
1547       sequence = file->sequence;
1548       if (current_pos <= target_pos
1549           && target_pos < current_pos + file->duration) {
1550         break;
1551       }
1552       current_pos += file->duration;
1553     }
1554     /* End of playlist */
1555     if (!walk)
1556       sequence++;
1557     m3u8->sequence = sequence;
1558     m3u8->sequence_position = current_pos;
1559     GST_M3U8_CLIENT_UNLOCK (demux->client);
1560   }
1561 
1562   return TRUE;
1563 }
1564 
1565 static gboolean
gst_hls_demux_change_playlist(GstHLSDemux * demux,guint max_bitrate,gboolean * changed)1566 gst_hls_demux_change_playlist (GstHLSDemux * demux, guint max_bitrate,
1567     gboolean * changed)
1568 {
1569   GstHLSVariantStream *lowest_variant, *lowest_ivariant;
1570   GstHLSVariantStream *previous_variant, *new_variant;
1571   gint old_bandwidth, new_bandwidth;
1572   GstAdaptiveDemux *adaptive_demux = GST_ADAPTIVE_DEMUX_CAST (demux);
1573   GstAdaptiveDemuxStream *stream;
1574 
1575   g_return_val_if_fail (adaptive_demux->streams != NULL, FALSE);
1576 
1577   stream = adaptive_demux->streams->data;
1578 
1579   previous_variant = demux->current_variant;
1580   new_variant =
1581       gst_hls_master_playlist_get_variant_for_bitrate (demux->master,
1582       demux->current_variant, max_bitrate);
1583 
1584   GST_M3U8_CLIENT_LOCK (demux->client);
1585 
1586 retry_failover_protection:
1587   old_bandwidth = previous_variant->bandwidth;
1588   new_bandwidth = new_variant->bandwidth;
1589 
1590   /* Don't do anything else if the playlist is the same */
1591   if (new_bandwidth == old_bandwidth) {
1592     GST_M3U8_CLIENT_UNLOCK (demux->client);
1593     return TRUE;
1594   }
1595 
1596   GST_M3U8_CLIENT_UNLOCK (demux->client);
1597 
1598   gst_hls_demux_set_current_variant (demux, new_variant);
1599 
1600   GST_INFO_OBJECT (demux, "Client was on %dbps, max allowed is %dbps, switching"
1601       " to bitrate %dbps", old_bandwidth, max_bitrate, new_bandwidth);
1602 
1603   if (gst_hls_demux_update_playlist (demux, TRUE, NULL)) {
1604     const gchar *main_uri;
1605     gchar *uri;
1606 
1607     uri = gst_m3u8_get_uri (new_variant->m3u8);
1608     main_uri = gst_adaptive_demux_get_manifest_ref_uri (adaptive_demux);
1609     gst_element_post_message (GST_ELEMENT_CAST (demux),
1610         gst_message_new_element (GST_OBJECT_CAST (demux),
1611             gst_structure_new (GST_ADAPTIVE_DEMUX_STATISTICS_MESSAGE_NAME,
1612                 "manifest-uri", G_TYPE_STRING,
1613                 main_uri, "uri", G_TYPE_STRING,
1614                 uri, "bitrate", G_TYPE_INT, new_bandwidth, NULL)));
1615     g_free (uri);
1616     if (changed)
1617       *changed = TRUE;
1618     stream->discont = TRUE;
1619   } else if (gst_adaptive_demux_is_running (GST_ADAPTIVE_DEMUX_CAST (demux))) {
1620     GstHLSVariantStream *failover_variant = NULL;
1621     GList *failover;
1622 
1623     GST_INFO_OBJECT (demux, "Unable to update playlist. Switching back");
1624     GST_M3U8_CLIENT_LOCK (demux->client);
1625 
1626     /* we find variants by bitrate by going from highest to lowest, so it's
1627      * possible that there's another variant with the same bitrate before the
1628      * one selected which we can use as failover */
1629     failover = g_list_find (demux->master->variants, new_variant);
1630     if (failover != NULL)
1631       failover = failover->prev;
1632     if (failover != NULL)
1633       failover_variant = failover->data;
1634     if (failover_variant && new_bandwidth == failover_variant->bandwidth) {
1635       new_variant = failover_variant;
1636       goto retry_failover_protection;
1637     }
1638 
1639     GST_M3U8_CLIENT_UNLOCK (demux->client);
1640     gst_hls_demux_set_current_variant (demux, previous_variant);
1641     /*  Try a lower bitrate (or stop if we just tried the lowest) */
1642     if (previous_variant->iframe) {
1643       lowest_ivariant = demux->master->iframe_variants->data;
1644       if (new_bandwidth == lowest_ivariant->bandwidth)
1645         return FALSE;
1646     } else {
1647       lowest_variant = demux->master->variants->data;
1648       if (new_bandwidth == lowest_variant->bandwidth)
1649         return FALSE;
1650     }
1651     return gst_hls_demux_change_playlist (demux, new_bandwidth - 1, changed);
1652   }
1653 
1654   return TRUE;
1655 }
1656 
1657 #if defined(HAVE_OPENSSL)
1658 static gboolean
gst_hls_demux_stream_decrypt_start(GstHLSDemuxStream * stream,const guint8 * key_data,const guint8 * iv_data)1659 gst_hls_demux_stream_decrypt_start (GstHLSDemuxStream * stream,
1660     const guint8 * key_data, const guint8 * iv_data)
1661 {
1662   EVP_CIPHER_CTX *ctx;
1663 #if OPENSSL_VERSION_NUMBER < 0x10100000L
1664   EVP_CIPHER_CTX_init (&stream->aes_ctx);
1665   ctx = &stream->aes_ctx;
1666 #else
1667   stream->aes_ctx = EVP_CIPHER_CTX_new ();
1668   ctx = stream->aes_ctx;
1669 #endif
1670   if (!EVP_DecryptInit_ex (ctx, EVP_aes_128_cbc (), NULL, key_data, iv_data))
1671     return FALSE;
1672   EVP_CIPHER_CTX_set_padding (ctx, 0);
1673   return TRUE;
1674 }
1675 
1676 static gboolean
decrypt_fragment(GstHLSDemuxStream * stream,gsize length,const guint8 * encrypted_data,guint8 * decrypted_data)1677 decrypt_fragment (GstHLSDemuxStream * stream, gsize length,
1678     const guint8 * encrypted_data, guint8 * decrypted_data)
1679 {
1680   int len, flen = 0;
1681   EVP_CIPHER_CTX *ctx;
1682 
1683 #if OPENSSL_VERSION_NUMBER < 0x10100000L
1684   ctx = &stream->aes_ctx;
1685 #else
1686   ctx = stream->aes_ctx;
1687 #endif
1688 
1689   if (G_UNLIKELY (length > G_MAXINT || length % 16 != 0))
1690     return FALSE;
1691 
1692   len = (int) length;
1693   if (!EVP_DecryptUpdate (ctx, decrypted_data, &len, encrypted_data, len))
1694     return FALSE;
1695   EVP_DecryptFinal_ex (ctx, decrypted_data + len, &flen);
1696   g_return_val_if_fail (len + flen == length, FALSE);
1697   return TRUE;
1698 }
1699 
1700 static void
gst_hls_demux_stream_decrypt_end(GstHLSDemuxStream * stream)1701 gst_hls_demux_stream_decrypt_end (GstHLSDemuxStream * stream)
1702 {
1703 #if OPENSSL_VERSION_NUMBER < 0x10100000L
1704   EVP_CIPHER_CTX_cleanup (&stream->aes_ctx);
1705 #else
1706   EVP_CIPHER_CTX_free (stream->aes_ctx);
1707   stream->aes_ctx = NULL;
1708 #endif
1709 }
1710 
1711 #elif defined(HAVE_NETTLE)
1712 static gboolean
gst_hls_demux_stream_decrypt_start(GstHLSDemuxStream * stream,const guint8 * key_data,const guint8 * iv_data)1713 gst_hls_demux_stream_decrypt_start (GstHLSDemuxStream * stream,
1714     const guint8 * key_data, const guint8 * iv_data)
1715 {
1716   aes_set_decrypt_key (&stream->aes_ctx.ctx, 16, key_data);
1717   CBC_SET_IV (&stream->aes_ctx, iv_data);
1718 
1719   return TRUE;
1720 }
1721 
1722 static gboolean
decrypt_fragment(GstHLSDemuxStream * stream,gsize length,const guint8 * encrypted_data,guint8 * decrypted_data)1723 decrypt_fragment (GstHLSDemuxStream * stream, gsize length,
1724     const guint8 * encrypted_data, guint8 * decrypted_data)
1725 {
1726   if (length % 16 != 0)
1727     return FALSE;
1728 
1729   CBC_DECRYPT (&stream->aes_ctx, aes_decrypt, length, decrypted_data,
1730       encrypted_data);
1731 
1732   return TRUE;
1733 }
1734 
1735 static void
gst_hls_demux_stream_decrypt_end(GstHLSDemuxStream * stream)1736 gst_hls_demux_stream_decrypt_end (GstHLSDemuxStream * stream)
1737 {
1738   /* NOP */
1739 }
1740 
1741 #elif defined(HAVE_LIBGCRYPT)
1742 static gboolean
gst_hls_demux_stream_decrypt_start(GstHLSDemuxStream * stream,const guint8 * key_data,const guint8 * iv_data)1743 gst_hls_demux_stream_decrypt_start (GstHLSDemuxStream * stream,
1744     const guint8 * key_data, const guint8 * iv_data)
1745 {
1746   gcry_error_t err = 0;
1747   gboolean ret = FALSE;
1748 
1749   err =
1750       gcry_cipher_open (&stream->aes_ctx, GCRY_CIPHER_AES128,
1751       GCRY_CIPHER_MODE_CBC, 0);
1752   if (err)
1753     goto out;
1754   err = gcry_cipher_setkey (stream->aes_ctx, key_data, 16);
1755   if (err)
1756     goto out;
1757   err = gcry_cipher_setiv (stream->aes_ctx, iv_data, 16);
1758   if (!err)
1759     ret = TRUE;
1760 
1761 out:
1762   if (!ret)
1763     if (stream->aes_ctx)
1764       gcry_cipher_close (stream->aes_ctx);
1765 
1766   return ret;
1767 }
1768 
1769 static gboolean
decrypt_fragment(GstHLSDemuxStream * stream,gsize length,const guint8 * encrypted_data,guint8 * decrypted_data)1770 decrypt_fragment (GstHLSDemuxStream * stream, gsize length,
1771     const guint8 * encrypted_data, guint8 * decrypted_data)
1772 {
1773   gcry_error_t err = 0;
1774 
1775   err = gcry_cipher_decrypt (stream->aes_ctx, decrypted_data, length,
1776       encrypted_data, length);
1777 
1778   return err == 0;
1779 }
1780 
1781 static void
gst_hls_demux_stream_decrypt_end(GstHLSDemuxStream * stream)1782 gst_hls_demux_stream_decrypt_end (GstHLSDemuxStream * stream)
1783 {
1784   if (stream->aes_ctx) {
1785     gcry_cipher_close (stream->aes_ctx);
1786     stream->aes_ctx = NULL;
1787   }
1788 }
1789 
1790 #else
1791 /* NO crypto available */
1792 static gboolean
gst_hls_demux_stream_decrypt_start(GstHLSDemuxStream * stream,const guint8 * key_data,const guint8 * iv_data)1793 gst_hls_demux_stream_decrypt_start (GstHLSDemuxStream * stream,
1794     const guint8 * key_data, const guint8 * iv_data)
1795 {
1796   GST_ERROR ("No crypto available");
1797   return FALSE;
1798 }
1799 
1800 static gboolean
decrypt_fragment(GstHLSDemuxStream * stream,gsize length,const guint8 * encrypted_data,guint8 * decrypted_data)1801 decrypt_fragment (GstHLSDemuxStream * stream, gsize length,
1802     const guint8 * encrypted_data, guint8 * decrypted_data)
1803 {
1804   GST_ERROR ("Cannot decrypt fragment, no crypto available");
1805   return FALSE;
1806 }
1807 
1808 static void
gst_hls_demux_stream_decrypt_end(GstHLSDemuxStream * stream)1809 gst_hls_demux_stream_decrypt_end (GstHLSDemuxStream * stream)
1810 {
1811   return;
1812 }
1813 #endif
1814 
1815 static GstBuffer *
gst_hls_demux_decrypt_fragment(GstHLSDemux * demux,GstHLSDemuxStream * stream,GstBuffer * encrypted_buffer,GError ** err)1816 gst_hls_demux_decrypt_fragment (GstHLSDemux * demux, GstHLSDemuxStream * stream,
1817     GstBuffer * encrypted_buffer, GError ** err)
1818 {
1819   GstBuffer *decrypted_buffer = NULL;
1820   GstMapInfo encrypted_info, decrypted_info;
1821 
1822   decrypted_buffer =
1823       gst_buffer_new_allocate (NULL, gst_buffer_get_size (encrypted_buffer),
1824       NULL);
1825 
1826   gst_buffer_map (encrypted_buffer, &encrypted_info, GST_MAP_READ);
1827   gst_buffer_map (decrypted_buffer, &decrypted_info, GST_MAP_WRITE);
1828 
1829   if (!decrypt_fragment (stream, encrypted_info.size,
1830           encrypted_info.data, decrypted_info.data))
1831     goto decrypt_error;
1832 
1833 
1834   gst_buffer_unmap (decrypted_buffer, &decrypted_info);
1835   gst_buffer_unmap (encrypted_buffer, &encrypted_info);
1836 
1837   gst_buffer_unref (encrypted_buffer);
1838 
1839   return decrypted_buffer;
1840 
1841 decrypt_error:
1842   GST_ERROR_OBJECT (demux, "Failed to decrypt fragment");
1843   g_set_error (err, GST_STREAM_ERROR, GST_STREAM_ERROR_DECRYPT,
1844       "Failed to decrypt fragment");
1845 
1846   gst_buffer_unmap (decrypted_buffer, &decrypted_info);
1847   gst_buffer_unmap (encrypted_buffer, &encrypted_info);
1848 
1849   gst_buffer_unref (encrypted_buffer);
1850   gst_buffer_unref (decrypted_buffer);
1851 
1852   return NULL;
1853 }
1854 
1855 static gint64
gst_hls_demux_get_manifest_update_interval(GstAdaptiveDemux * demux)1856 gst_hls_demux_get_manifest_update_interval (GstAdaptiveDemux * demux)
1857 {
1858   GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (demux);
1859   GstClockTime target_duration;
1860 
1861   if (hlsdemux->current_variant) {
1862     target_duration =
1863         gst_m3u8_get_target_duration (hlsdemux->current_variant->m3u8);
1864   } else {
1865     target_duration = 5 * GST_SECOND;
1866   }
1867 
1868   return gst_util_uint64_scale (target_duration, G_USEC_PER_SEC, GST_SECOND);
1869 }
1870 
1871 static gboolean
gst_hls_demux_get_live_seek_range(GstAdaptiveDemux * demux,gint64 * start,gint64 * stop)1872 gst_hls_demux_get_live_seek_range (GstAdaptiveDemux * demux, gint64 * start,
1873     gint64 * stop)
1874 {
1875   GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (demux);
1876   gboolean ret = FALSE;
1877 
1878   if (hlsdemux->current_variant) {
1879     ret =
1880         gst_m3u8_get_seek_range (hlsdemux->current_variant->m3u8, start, stop);
1881   }
1882 
1883   return ret;
1884 }
1885