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