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