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