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.
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Library General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Library General Public License for more details.
20 * You should have received a copy of the GNU Library General Public
21 * License along with this library; if not, write to the
22 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23 * Boston, MA 02111-1307, USA.
26 * SECTION:element-hlsdemux
28 * HTTP Live Streaming demuxer element.
31 * <title>Example launch line</title>
33 * gst-launch souphttpsrc location=http://devimages.apple.com/iphone/samples/bipbop/gear4/prog_index.m3u8 ! hlsdemux ! decodebin2 ! ffmpegcolorspace ! videoscale ! autovideosink
37 * Last reviewed on 2010-10-07
44 /* FIXME 0.11: suppress warnings for deprecated API such as GStaticRecMutex
45 * with newer GLib versions (>= 2.31.0) */
46 #define GLIB_DISABLE_DEPRECATION_WARNINGS
49 #include <gst/base/gsttypefindhelper.h>
50 #include <gst/glib-compat-private.h>
51 #include "gsthlsdemux.h"
53 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src%d",
58 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
61 GST_STATIC_CAPS ("application/x-hls"));
63 GST_DEBUG_CATEGORY_STATIC (gst_hls_demux_debug);
64 #define GST_CAT_DEFAULT gst_hls_demux_debug
72 PROP_CONNECTION_SPEED,
77 #ifdef GST_EXT_HLS_MODIFICATION
78 #define GST_HLS_DEMUX_DUMP
79 #define DEFAULT_FRAGMENTS_CACHE 2
80 #define DEFAULT_FAILED_COUNT 3
81 #define DEFAULT_BITRATE_LIMIT 0.8
82 #define DEFAULT_CONNECTION_SPEED 0
84 #define DEFAULT_FRAGMENTS_CACHE 3
85 #define DEFAULT_FAILED_COUNT 3
86 #define DEFAULT_BITRATE_LIMIT 0.8
87 #define DEFAULT_CONNECTION_SPEED 0
90 #define UPDATE_FACTOR_DEFAULT 1
91 #define UPDATE_FACTOR_RETRY 0.5
93 #ifdef GST_HLS_DEMUX_DUMP
100 static gint _dump_status = 0;
101 static gchar *_dump_dir_path = NULL;
105 static void gst_hls_demux_set_property (GObject * object, guint prop_id,
106 const GValue * value, GParamSpec * pspec);
107 static void gst_hls_demux_get_property (GObject * object, guint prop_id,
108 GValue * value, GParamSpec * pspec);
109 static void gst_hls_demux_dispose (GObject * obj);
112 static GstStateChangeReturn
113 gst_hls_demux_change_state (GstElement * element, GstStateChange transition);
116 static GstFlowReturn gst_hls_demux_chain (GstPad * pad, GstBuffer * buf);
117 static gboolean gst_hls_demux_sink_event (GstPad * pad, GstEvent * event);
118 static gboolean gst_hls_demux_src_event (GstPad * pad, GstEvent * event);
119 static gboolean gst_hls_demux_src_query (GstPad * pad, GstQuery * query);
120 static void gst_hls_demux_stream_loop (GstHLSDemux * demux);
121 static void gst_hls_demux_updates_loop (GstHLSDemux * demux);
122 static void gst_hls_demux_stop (GstHLSDemux * demux);
123 static gboolean gst_hls_demux_cache_fragments (GstHLSDemux * demux);
124 static gboolean gst_hls_demux_schedule (GstHLSDemux * demux, gboolean updated);
125 static gboolean gst_hls_demux_switch_playlist (GstHLSDemux * demux,
126 GstFragment *fragment);
127 static gboolean gst_hls_demux_get_next_fragment (GstHLSDemux * demux,
129 static gboolean gst_hls_demux_update_playlist (GstHLSDemux * demux,
131 static void gst_hls_demux_reset (GstHLSDemux * demux, gboolean dispose);
132 static gboolean gst_hls_demux_set_location (GstHLSDemux * demux,
134 static gchar *gst_hls_src_buf_to_utf8_playlist (GstBuffer * buf);
136 #ifdef GST_HLS_DEMUX_DUMP
138 gst_hls_demux_init_dump (void)
140 const gchar *env_dump;
143 env_dump = g_getenv("GST_HLS_DUMP");
144 if (env_dump && *env_dump != '\0') {
145 if (g_strrstr(env_dump, "ts"))
146 _dump_status |= DUMP_TS;
147 if (g_strrstr(env_dump, "ts_join"))
148 _dump_status |= DUMP_TS_JOIN;
149 if (g_strrstr(env_dump, "key"))
150 _dump_status |= DUMP_KEY;
151 if (g_strrstr(env_dump, "m3u8"))
152 _dump_status |= DUMP_M3U8;
155 if (_dump_status > 0) {
156 time = g_date_time_new_now_local ();
157 _dump_dir_path = g_date_time_format (time, "/tmp/hls_%Y%m%d_%H%M%S");
158 g_mkdir_with_parents (_dump_dir_path, 0777);
159 g_date_time_unref (time);
164 gst_hls_demux_fini_dump (void)
166 if (_dump_status > 0) {
167 if (_dump_dir_path) {
168 g_free(_dump_dir_path);
169 _dump_dir_path = NULL;
176 gst_hls_demux_dump_fragment (GstBufferList * buffer_list, gchar * fragment_uri,
177 const gchar * prefix)
179 gchar *dump_path, *file_name;
181 GstBufferListIterator *it;
184 if (_dump_status & DUMP_TS_JOIN) {
185 file_name = g_strrstr (_dump_dir_path, "hls_") + 4;
186 dump_path = g_strjoin (NULL, _dump_dir_path, "/", prefix, file_name, ".ts",
189 file_name = g_strrstr (fragment_uri, "/") + 1;
190 dump_path = g_strjoin (NULL, _dump_dir_path, "/", prefix, file_name, NULL);
192 fp = fopen (dump_path, "wa+");
194 it = gst_buffer_list_iterate (buffer_list);
195 gst_buffer_list_iterator_next_group (it);
196 while (buf = gst_buffer_list_iterator_next (it)) {
197 fwrite (GST_BUFFER_DATA (buf), 1, GST_BUFFER_SIZE (buf), fp);
205 gst_hls_demux_dump_key (GstBuffer * buf, gchar * key_uri)
207 gchar *dump_path, *file_name;
210 file_name = g_strrstr (key_uri, "/") + 1;
211 dump_path = g_strjoin (NULL, _dump_dir_path, "/", file_name, NULL);
212 fp = fopen (dump_path, "w+");
213 fwrite (GST_BUFFER_DATA (buf), 1, GST_BUFFER_SIZE (buf), fp);
219 gst_hls_demux_dump_playlist (GstBuffer * buf, gchar * playlist_uri)
222 gchar *prefix, *dump_path, *file_name;
225 time = g_date_time_new_now_local ();
226 prefix = g_date_time_format (time, "%Y%m%d_%H%M%S_");
227 file_name = g_strrstr (playlist_uri, "/") + 1;
228 dump_path = g_strjoin (NULL, _dump_dir_path, "/", prefix, file_name, NULL);
229 fp = fopen (dump_path, "w+");
230 fwrite (GST_BUFFER_DATA (buf), 1, GST_BUFFER_SIZE (buf), fp);
232 g_date_time_unref (time);
239 _do_init (GType type)
241 GST_DEBUG_CATEGORY_INIT (gst_hls_demux_debug, "hlsdemux", 0,
245 GST_BOILERPLATE_FULL (GstHLSDemux, gst_hls_demux, GstElement,
246 GST_TYPE_ELEMENT, _do_init);
249 gst_hls_demux_base_init (gpointer g_class)
251 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
253 gst_element_class_add_static_pad_template (element_class, &srctemplate);
255 gst_element_class_add_static_pad_template (element_class, &sinktemplate);
257 gst_element_class_set_details_simple (element_class,
260 "HTTP Live Streaming demuxer",
261 "Marc-Andre Lureau <marcandre.lureau@gmail.com>\n"
262 "Andoni Morales Alastruey <ylatuya@gmail.com>");
266 gst_hls_demux_dispose (GObject * obj)
268 GstHLSDemux *demux = GST_HLS_DEMUX (obj);
270 if (demux->stream_task) {
271 if (GST_TASK_STATE (demux->stream_task) != GST_TASK_STOPPED) {
272 GST_DEBUG_OBJECT (demux, "Leaving streaming task");
273 gst_task_stop (demux->stream_task);
275 g_static_rec_mutex_lock (&demux->stream_lock);
276 g_static_rec_mutex_unlock (&demux->stream_lock);
277 gst_task_join (demux->stream_task);
278 gst_object_unref (demux->stream_task);
279 g_static_rec_mutex_free (&demux->stream_lock);
280 demux->stream_task = NULL;
283 if (demux->updates_task) {
284 if (GST_TASK_STATE (demux->updates_task) != GST_TASK_STOPPED) {
285 GST_DEBUG_OBJECT (demux, "Leaving updates task");
286 gst_task_stop (demux->updates_task);
288 GST_TASK_SIGNAL (demux->updates_task);
289 g_static_rec_mutex_lock (&demux->updates_lock);
290 g_static_rec_mutex_unlock (&demux->updates_lock);
291 gst_task_join (demux->updates_task);
292 gst_object_unref (demux->updates_task);
293 g_mutex_free (demux->updates_timed_lock);
294 g_static_rec_mutex_free (&demux->updates_lock);
295 demux->updates_task = NULL;
298 if (demux->downloader != NULL) {
299 g_object_unref (demux->downloader);
300 demux->downloader = NULL;
303 gst_hls_demux_reset (demux, TRUE);
305 g_queue_free (demux->queue);
307 G_OBJECT_CLASS (parent_class)->dispose (obj);
311 gst_hls_demux_class_init (GstHLSDemuxClass * klass)
313 GObjectClass *gobject_class;
314 GstElementClass *gstelement_class;
316 gobject_class = (GObjectClass *) klass;
317 gstelement_class = (GstElementClass *) klass;
319 gobject_class->set_property = gst_hls_demux_set_property;
320 gobject_class->get_property = gst_hls_demux_get_property;
321 gobject_class->dispose = gst_hls_demux_dispose;
323 g_object_class_install_property (gobject_class, PROP_FRAGMENTS_CACHE,
324 g_param_spec_uint ("fragments-cache", "Fragments cache",
325 "Number of fragments needed to be cached to start playing",
326 2, G_MAXUINT, DEFAULT_FRAGMENTS_CACHE,
327 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
329 g_object_class_install_property (gobject_class, PROP_BITRATE_LIMIT,
330 g_param_spec_float ("bitrate-limit",
331 "Bitrate limit in %",
332 "Limit of the available bitrate to use when switching to alternates.",
333 0, 1, DEFAULT_BITRATE_LIMIT,
334 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
336 g_object_class_install_property (gobject_class, PROP_CONNECTION_SPEED,
337 g_param_spec_uint ("connection-speed", "Connection Speed",
338 "Network connection speed in kbps (0 = unknown)",
339 0, G_MAXUINT / 1000, DEFAULT_CONNECTION_SPEED,
340 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
342 gstelement_class->change_state =
343 GST_DEBUG_FUNCPTR (gst_hls_demux_change_state);
347 gst_hls_demux_init (GstHLSDemux * demux, GstHLSDemuxClass * klass)
351 demux->sinkpad = gst_pad_new_from_static_template (&sinktemplate, "sink");
352 gst_pad_set_chain_function (demux->sinkpad,
353 GST_DEBUG_FUNCPTR (gst_hls_demux_chain));
354 gst_pad_set_event_function (demux->sinkpad,
355 GST_DEBUG_FUNCPTR (gst_hls_demux_sink_event));
356 gst_element_add_pad (GST_ELEMENT (demux), demux->sinkpad);
359 demux->downloader = gst_uri_downloader_new ();
361 demux->do_typefind = TRUE;
364 demux->fragments_cache = DEFAULT_FRAGMENTS_CACHE;
365 demux->bitrate_limit = DEFAULT_BITRATE_LIMIT;
366 demux->connection_speed = DEFAULT_CONNECTION_SPEED;
368 demux->queue = g_queue_new ();
371 g_static_rec_mutex_init (&demux->updates_lock);
372 demux->updates_task =
373 gst_task_create ((GstTaskFunction) gst_hls_demux_updates_loop, demux);
374 gst_task_set_lock (demux->updates_task, &demux->updates_lock);
375 demux->updates_timed_lock = g_mutex_new ();
378 g_static_rec_mutex_init (&demux->stream_lock);
380 gst_task_create ((GstTaskFunction) gst_hls_demux_stream_loop, demux);
381 gst_task_set_lock (demux->stream_task, &demux->stream_lock);
385 gst_hls_demux_set_property (GObject * object, guint prop_id,
386 const GValue * value, GParamSpec * pspec)
388 GstHLSDemux *demux = GST_HLS_DEMUX (object);
391 case PROP_FRAGMENTS_CACHE:
392 demux->fragments_cache = g_value_get_uint (value);
394 case PROP_BITRATE_LIMIT:
395 demux->bitrate_limit = g_value_get_float (value);
397 case PROP_CONNECTION_SPEED:
398 demux->connection_speed = g_value_get_uint (value) * 1000;
401 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
407 gst_hls_demux_get_property (GObject * object, guint prop_id, GValue * value,
410 GstHLSDemux *demux = GST_HLS_DEMUX (object);
413 case PROP_FRAGMENTS_CACHE:
414 g_value_set_uint (value, demux->fragments_cache);
416 case PROP_BITRATE_LIMIT:
417 g_value_set_float (value, demux->bitrate_limit);
419 case PROP_CONNECTION_SPEED:
420 g_value_set_uint (value, demux->connection_speed / 1000);
423 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
428 static GstStateChangeReturn
429 gst_hls_demux_change_state (GstElement * element, GstStateChange transition)
431 GstStateChangeReturn ret;
432 GstHLSDemux *demux = GST_HLS_DEMUX (element);
434 switch (transition) {
435 #ifdef GST_HLS_DEMUX_DUMP
436 case GST_STATE_CHANGE_NULL_TO_READY:
437 gst_hls_demux_init_dump ();
440 case GST_STATE_CHANGE_READY_TO_PAUSED:
441 gst_hls_demux_reset (demux, FALSE);
443 case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
444 /* Start the streaming loop in paused only if we already received
445 the main playlist. It might have been stopped if we were in PAUSED
446 state and we filled our queue with enough cached fragments
448 if (gst_m3u8_client_get_uri (demux->client)[0] != '\0')
449 gst_task_start (demux->updates_task);
455 ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
457 switch (transition) {
458 case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
459 gst_task_stop (demux->updates_task);
461 case GST_STATE_CHANGE_PAUSED_TO_READY:
462 demux->cancelled = TRUE;
463 gst_hls_demux_stop (demux);
464 gst_task_join (demux->stream_task);
465 gst_hls_demux_reset (demux, FALSE);
467 #ifdef GST_HLS_DEMUX_DUMP
468 case GST_STATE_CHANGE_READY_TO_NULL:
469 gst_hls_demux_fini_dump ();
479 gst_hls_demux_src_event (GstPad * pad, GstEvent * event)
483 demux = GST_HLS_DEMUX (gst_pad_get_element_private (pad));
485 switch (event->type) {
491 GstSeekType start_type, stop_type;
494 GstClockTime position, current_pos, target_pos;
495 gint current_sequence;
496 GstM3U8MediaFile *file;
498 GST_INFO_OBJECT (demux, "Received GST_EVENT_SEEK");
500 if (gst_m3u8_client_is_live (demux->client)) {
501 GST_WARNING_OBJECT (demux, "Received seek event for live stream");
505 gst_event_parse_seek (event, &rate, &format, &flags, &start_type, &start,
508 if (format != GST_FORMAT_TIME)
511 GST_DEBUG_OBJECT (demux, "seek event, rate: %f start: %" GST_TIME_FORMAT
512 " stop: %" GST_TIME_FORMAT, rate, GST_TIME_ARGS (start),
513 GST_TIME_ARGS (stop));
515 GST_M3U8_CLIENT_LOCK (demux->client);
516 file = GST_M3U8_MEDIA_FILE (demux->client->current->files->data);
517 current_sequence = file->sequence;
519 target_pos = (GstClockTime) start;
520 for (walk = demux->client->current->files; walk; walk = walk->next) {
523 current_sequence = file->sequence;
524 if (current_pos <= target_pos
525 && target_pos < current_pos + file->duration) {
528 current_pos += file->duration;
530 GST_M3U8_CLIENT_UNLOCK (demux->client);
533 GST_WARNING_OBJECT (demux, "Could not find seeked fragment");
537 if (flags & GST_SEEK_FLAG_FLUSH) {
538 GST_DEBUG_OBJECT (demux, "sending flush start");
539 gst_pad_push_event (demux->srcpad, gst_event_new_flush_start ());
542 demux->cancelled = TRUE;
543 gst_task_pause (demux->stream_task);
544 gst_uri_downloader_cancel (demux->downloader);
545 gst_task_stop (demux->updates_task);
546 gst_task_pause (demux->stream_task);
548 /* wait for streaming to finish */
549 g_static_rec_mutex_lock (&demux->stream_lock);
551 demux->need_cache = TRUE;
552 while (!g_queue_is_empty (demux->queue)) {
553 GstBufferList *buf_list = g_queue_pop_head (demux->queue);
554 gst_buffer_list_unref (buf_list);
556 g_queue_clear (demux->queue);
558 GST_M3U8_CLIENT_LOCK (demux->client);
559 GST_DEBUG_OBJECT (demux, "seeking to sequence %d", current_sequence);
560 demux->client->sequence = current_sequence;
561 gst_m3u8_client_get_current_position (demux->client, &position);
562 demux->position_shift = start - position;
563 demux->need_segment = TRUE;
564 GST_M3U8_CLIENT_UNLOCK (demux->client);
567 if (flags & GST_SEEK_FLAG_FLUSH) {
568 GST_DEBUG_OBJECT (demux, "sending flush stop");
569 gst_pad_push_event (demux->srcpad, gst_event_new_flush_stop ());
572 demux->cancelled = FALSE;
573 gst_task_start (demux->stream_task);
574 g_static_rec_mutex_unlock (&demux->stream_lock);
582 return gst_pad_event_default (pad, event);
586 gst_hls_demux_sink_event (GstPad * pad, GstEvent * event)
593 demux = GST_HLS_DEMUX (gst_pad_get_parent (pad));
595 switch (event->type) {
597 gchar *playlist = NULL;
598 #ifdef GST_EXT_HLS_MODIFICATION
599 GstElement *parent = GST_ELEMENT (demux);
600 gboolean done = FALSE;
602 /* get properties from http src plugin */
603 while (parent = GST_ELEMENT_PARENT (parent)) {
605 GstIteratorResult ires;
607 gchar *user_agent = NULL, **cookies = NULL, *cookies_str = NULL;
609 it = gst_bin_iterate_sources (GST_BIN (parent));
611 ires = gst_iterator_next (it, &item);
613 case GST_ITERATOR_OK:
614 g_object_get (G_OBJECT (item), "user-agent", &user_agent, NULL);
615 g_object_get (G_OBJECT (item), "cookies", &cookies, NULL);
617 gst_uri_downloader_set_user_agent (demux->downloader, user_agent);
618 GST_INFO_OBJECT(demux, "get user-agent:%s", user_agent);
621 gst_uri_downloader_set_cookies (demux->downloader, cookies);
622 cookies_str = g_strjoinv (NULL, cookies);
623 GST_INFO_OBJECT(demux, "get cookies:%s");
624 g_free (cookies_str);
628 case GST_ITERATOR_RESYNC:
629 gst_iterator_resync (it);
634 } while (ires == GST_ITERATOR_OK || ires == GST_ITERATOR_RESYNC);
635 gst_iterator_free (it);
641 if (demux->playlist == NULL) {
642 GST_WARNING_OBJECT (demux, "Received EOS without a playlist.");
646 GST_DEBUG_OBJECT (demux,
647 "Got EOS on the sink pad: main playlist fetched");
649 query = gst_query_new_uri ();
650 ret = gst_pad_peer_query (demux->sinkpad, query);
652 gst_query_parse_uri (query, &uri);
653 gst_hls_demux_set_location (demux, uri);
656 gst_query_unref (query);
658 #ifdef GST_HLS_DEMUX_DUMP
659 if (_dump_status & DUMP_M3U8)
660 gst_hls_demux_dump_playlist (demux->playlist, demux->client->main->uri);
662 playlist = gst_hls_src_buf_to_utf8_playlist (demux->playlist);
663 demux->playlist = NULL;
664 if (playlist == NULL) {
665 GST_WARNING_OBJECT (demux, "Error validating first playlist.");
666 } else if (!gst_m3u8_client_update (demux->client, playlist)) {
667 /* In most cases, this will happen if we set a wrong url in the
668 * source element and we have received the 404 HTML response instead of
670 GST_ELEMENT_ERROR (demux, STREAM, DECODE, ("Invalid playlist."),
672 gst_object_unref (demux);
676 if (!ret && gst_m3u8_client_is_live (demux->client)) {
677 GST_ELEMENT_ERROR (demux, RESOURCE, NOT_FOUND,
678 ("Failed querying the playlist uri, "
679 "required for live sources."), (NULL));
680 gst_object_unref (demux);
684 gst_task_start (demux->stream_task);
685 gst_event_unref (event);
686 gst_object_unref (demux);
689 case GST_EVENT_NEWSEGMENT:
690 /* Swallow newsegments, we'll push our own */
691 gst_event_unref (event);
692 gst_object_unref (demux);
698 gst_object_unref (demux);
700 return gst_pad_event_default (pad, event);
704 gst_hls_demux_src_query (GstPad * pad, GstQuery * query)
706 GstHLSDemux *hlsdemux;
707 gboolean ret = FALSE;
712 hlsdemux = GST_HLS_DEMUX (gst_pad_get_element_private (pad));
714 switch (query->type) {
715 case GST_QUERY_DURATION:{
716 GstClockTime duration = -1;
719 gst_query_parse_duration (query, &fmt, NULL);
720 if (fmt == GST_FORMAT_TIME) {
721 duration = gst_m3u8_client_get_duration (hlsdemux->client);
722 if (GST_CLOCK_TIME_IS_VALID (duration) && duration > 0) {
723 gst_query_set_duration (query, GST_FORMAT_TIME, duration);
727 GST_LOG_OBJECT (hlsdemux, "GST_QUERY_DURATION returns %s with duration %"
728 GST_TIME_FORMAT, ret ? "TRUE" : "FALSE", GST_TIME_ARGS (duration));
732 if (hlsdemux->client) {
733 /* FIXME: Do we answer with the variant playlist, with the current
734 * playlist or the the uri of the least downlowaded fragment? */
735 gst_query_set_uri (query, gst_m3u8_client_get_uri (hlsdemux->client));
739 case GST_QUERY_SEEKING:{
743 gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
744 GST_INFO_OBJECT (hlsdemux, "Received GST_QUERY_SEEKING with format %d",
746 if (fmt == GST_FORMAT_TIME) {
747 GstClockTime duration;
749 duration = gst_m3u8_client_get_duration (hlsdemux->client);
750 if (GST_CLOCK_TIME_IS_VALID (duration) && duration > 0)
753 gst_query_set_seeking (query, fmt,
754 !gst_m3u8_client_is_live (hlsdemux->client), 0, stop);
756 GST_INFO_OBJECT (hlsdemux, "GST_QUERY_SEEKING returning with stop : %"
757 GST_TIME_FORMAT, GST_TIME_ARGS (stop));
762 /* Don't fordward queries upstream because of the special nature of this
763 * "demuxer", which relies on the upstream element only to be fed with the
772 gst_hls_demux_chain (GstPad * pad, GstBuffer * buf)
774 GstHLSDemux *demux = GST_HLS_DEMUX (gst_pad_get_parent (pad));
776 if (demux->playlist == NULL)
777 demux->playlist = buf;
779 demux->playlist = gst_buffer_join (demux->playlist, buf);
781 gst_object_unref (demux);
787 gst_hls_demux_stop (GstHLSDemux * demux)
789 gst_uri_downloader_cancel (demux->downloader);
791 if (demux->updates_task
792 && GST_TASK_STATE (demux->updates_task) != GST_TASK_STOPPED) {
793 demux->stop_stream_task = TRUE;
794 gst_task_stop (demux->updates_task);
795 GST_TASK_SIGNAL (demux->updates_task);
798 if (demux->stream_task
799 && GST_TASK_STATE (demux->stream_task) != GST_TASK_STOPPED)
800 gst_task_stop (demux->stream_task);
804 switch_pads (GstHLSDemux * demux, GstCaps * newcaps)
806 GstPad *oldpad = demux->srcpad;
808 GST_DEBUG ("Switching pads (oldpad:%p) with caps: %" GST_PTR_FORMAT, oldpad,
811 /* FIXME: This is a workaround for a bug in playsink.
812 * If we're switching from an audio-only or video-only fragment
813 * to an audio-video segment, the new sink doesn't know about
814 * the current running time and audio/video will go out of sync.
816 * This should be fixed in playsink by distributing the
817 * current running time to newly created sinks and is
818 * fixed in 0.11 with the new segments.
821 gst_pad_push_event (demux->srcpad, gst_event_new_flush_stop ());
823 /* First create and activate new pad */
824 demux->srcpad = gst_pad_new_from_static_template (&srctemplate, NULL);
825 gst_pad_set_event_function (demux->srcpad,
826 GST_DEBUG_FUNCPTR (gst_hls_demux_src_event));
827 gst_pad_set_query_function (demux->srcpad,
828 GST_DEBUG_FUNCPTR (gst_hls_demux_src_query));
829 gst_pad_set_element_private (demux->srcpad, demux);
830 gst_pad_set_active (demux->srcpad, TRUE);
831 gst_pad_set_caps (demux->srcpad, newcaps);
832 gst_element_add_pad (GST_ELEMENT (demux), demux->srcpad);
834 gst_element_no_more_pads (GST_ELEMENT (demux));
838 gst_pad_push_event (oldpad, gst_event_new_eos ());
839 gst_pad_set_active (oldpad, FALSE);
840 gst_element_remove_pad (GST_ELEMENT (demux), oldpad);
845 gst_hls_demux_stream_loop (GstHLSDemux * demux)
847 GstFragment *fragment;
848 GstBufferList *buffer_list;
852 /* Loop for the source pad task. The task is started when we have
853 * received the main playlist from the source element. It tries first to
854 * cache the first fragments and then it waits until it has more data in the
855 * queue. This task is woken up when we push a new fragment to the queue or
856 * when we reached the end of the playlist */
858 if (G_UNLIKELY (demux->need_cache)) {
859 if (!gst_hls_demux_cache_fragments (demux))
862 /* we can start now the updates thread (only if on playing) */
863 if (GST_STATE (demux) == GST_STATE_PLAYING)
864 gst_task_start (demux->updates_task);
865 GST_INFO_OBJECT (demux, "First fragments cached successfully");
868 if (g_queue_is_empty (demux->queue)) {
869 if (demux->end_of_playlist)
870 goto end_of_playlist;
875 fragment = g_queue_pop_head (demux->queue);
876 buffer_list = gst_fragment_get_buffer_list (fragment);
877 /* Work with the first buffer of the list */
878 buf = gst_buffer_list_get (buffer_list, 0, 0);
880 /* Figure out if we need to create/switch pads */
881 if (G_UNLIKELY (!demux->srcpad
882 #ifdef GST_EXT_HLS_MODIFICATION
883 || ((GST_BUFFER_CAPS (buf))
884 && (!gst_caps_is_equal_fixed (GST_BUFFER_CAPS (buf),
885 GST_PAD_CAPS (demux->srcpad))))
887 || !gst_caps_is_equal_fixed (GST_BUFFER_CAPS (buf),
888 GST_PAD_CAPS (demux->srcpad))
890 || demux->need_segment)) {
891 switch_pads (demux, GST_BUFFER_CAPS (buf));
892 demux->need_segment = TRUE;
894 g_object_unref (fragment);
896 if (demux->need_segment) {
897 GstClockTime start = GST_BUFFER_TIMESTAMP (buf);
899 start += demux->position_shift;
900 /* And send a newsegment */
901 GST_DEBUG_OBJECT (demux, "Sending new-segment. segment start:%"
902 GST_TIME_FORMAT, GST_TIME_ARGS (start));
903 gst_pad_push_event (demux->srcpad,
904 gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME,
905 start, GST_CLOCK_TIME_NONE, start));
906 demux->need_segment = FALSE;
907 demux->position_shift = 0;
910 ret = gst_pad_push_list (demux->srcpad, buffer_list);
911 if (ret != GST_FLOW_OK)
918 GST_DEBUG_OBJECT (demux, "Reached end of playlist, sending EOS");
919 gst_pad_push_event (demux->srcpad, gst_event_new_eos ());
920 gst_hls_demux_stop (demux);
926 if (GST_TASK_STATE (demux->stream_task) != GST_TASK_STOPPED) {
927 gst_task_pause (demux->stream_task);
929 if (!demux->cancelled) {
930 GST_ELEMENT_ERROR (demux, RESOURCE, NOT_FOUND,
931 ("Could not cache the first fragments"), (NULL));
932 gst_hls_demux_stop (demux);
939 /* FIXME: handle error */
940 GST_DEBUG_OBJECT (demux, "Error pushing buffer: %s... stopping task",
941 gst_flow_get_name (ret));
942 gst_hls_demux_stop (demux);
948 if (GST_TASK_STATE (demux->stream_task) != GST_TASK_STOPPED) {
949 gst_task_pause (demux->stream_task);
956 gst_hls_demux_reset (GstHLSDemux * demux, gboolean dispose)
958 demux->need_cache = TRUE;
959 demux->end_of_playlist = FALSE;
960 demux->do_typefind = TRUE;
962 if (demux->input_caps) {
963 gst_caps_unref (demux->input_caps);
964 demux->input_caps = NULL;
967 if (demux->playlist) {
968 gst_buffer_unref (demux->playlist);
969 demux->playlist = NULL;
973 gst_m3u8_client_free (demux->client);
974 demux->client = NULL;
978 demux->client = gst_m3u8_client_new ("");
979 demux->cancelled = FALSE;
982 while (!g_queue_is_empty (demux->queue)) {
983 GstFragment *fragment = g_queue_pop_head (demux->queue);
984 g_object_unref (fragment);
986 g_queue_clear (demux->queue);
988 demux->position_shift = 0;
989 demux->need_segment = TRUE;
993 gst_hls_demux_set_location (GstHLSDemux * demux, const gchar * uri)
996 gst_m3u8_client_free (demux->client);
997 demux->client = gst_m3u8_client_new (uri);
998 GST_INFO_OBJECT (demux, "Changed location: %s", uri);
1003 gst_hls_demux_updates_loop (GstHLSDemux * demux)
1005 /* Loop for the updates. It's started when the first fragments are cached and
1006 * schedules the next update of the playlist (for lives sources) and the next
1007 * update of fragments. When a new fragment is downloaded, it compares the
1008 * download time with the next scheduled update to check if we can or should
1009 * switch to a different bitrate */
1011 g_mutex_lock (demux->updates_timed_lock);
1012 GST_DEBUG_OBJECT (demux, "Started updates task");
1014 /* block until the next scheduled update or the signal to quit this thread */
1015 if (demux->cancelled
1016 || (g_cond_timed_wait (GST_TASK_GET_COND (demux->updates_task),
1017 demux->updates_timed_lock, &demux->next_update))) {
1020 /* update the playlist for live sources */
1021 if (gst_m3u8_client_is_live (demux->client)) {
1022 if (!gst_hls_demux_update_playlist (demux, TRUE)) {
1023 /* if the playlist couldn't be updated, try again */
1024 if (demux->client->update_failed_count < DEFAULT_FAILED_COUNT) {
1025 /* schedule the next update */
1026 gst_hls_demux_schedule (demux, FALSE);
1027 if (demux->client->update_failed_count > 0) {
1028 GST_WARNING_OBJECT (demux, "Could not update the playlist");
1032 GST_ELEMENT_ERROR (demux, RESOURCE, NOT_FOUND,
1033 ("Could not update the playlist"), (NULL));
1039 if (demux->cancelled)
1042 /* schedule the next update */
1043 gst_hls_demux_schedule (demux, TRUE);
1045 /* fetch the next fragment */
1046 if (g_queue_is_empty (demux->queue)) {
1047 if (!gst_hls_demux_get_next_fragment (demux, FALSE)) {
1048 if (!demux->end_of_playlist && !demux->cancelled) {
1049 if (demux->client->update_failed_count < DEFAULT_FAILED_COUNT) {
1050 GST_WARNING_OBJECT (demux, "Could not fetch the next fragment");
1053 GST_ELEMENT_ERROR (demux, RESOURCE, NOT_FOUND,
1054 ("Could not fetch the next fragment"), (NULL));
1059 demux->client->update_failed_count = 0;
1066 GST_DEBUG_OBJECT (demux, "Stopped updates task");
1067 gst_hls_demux_stop (demux);
1068 g_mutex_unlock (demux->updates_timed_lock);
1073 gst_hls_demux_cache_fragments (GstHLSDemux * demux)
1077 /* If this playlist is a variant playlist, select the first one
1079 if (gst_m3u8_client_has_variant_playlist (demux->client)) {
1080 GstM3U8 *child = NULL;
1082 if (demux->connection_speed == 0) {
1084 GST_M3U8_CLIENT_LOCK (demux->client);
1085 child = demux->client->main->current_variant->data;
1086 GST_M3U8_CLIENT_UNLOCK (demux->client);
1088 GList *tmp = gst_m3u8_client_get_playlist_for_bitrate (demux->client,
1089 demux->connection_speed);
1091 child = GST_M3U8 (tmp->data);
1094 gst_m3u8_client_set_current (demux->client, child);
1095 if (!gst_hls_demux_update_playlist (demux, FALSE)) {
1096 GST_ERROR_OBJECT (demux, "Could not fetch the child playlist %s",
1102 /* If it's a live source, set the sequence number to the end of the list
1103 * and substract the 'fragmets_cache' to start from the last fragment*/
1104 if (gst_m3u8_client_is_live (demux->client)) {
1105 #ifndef GST_EXT_HLS_MODIFICATION
1106 GST_M3U8_CLIENT_LOCK (demux->client);
1107 demux->client->sequence += g_list_length (demux->client->current->files);
1108 if (demux->client->sequence >= demux->fragments_cache)
1109 demux->client->sequence -= demux->fragments_cache;
1111 demux->client->sequence = 0;
1112 GST_M3U8_CLIENT_UNLOCK (demux->client);
1115 GstClockTime duration = gst_m3u8_client_get_duration (demux->client);
1117 GST_DEBUG_OBJECT (demux, "Sending duration message : %" GST_TIME_FORMAT,
1118 GST_TIME_ARGS (duration));
1119 if (duration != GST_CLOCK_TIME_NONE)
1120 gst_element_post_message (GST_ELEMENT (demux),
1121 gst_message_new_duration (GST_OBJECT (demux),
1122 GST_FORMAT_TIME, duration));
1125 /* Cache the first fragments */
1126 for (i = 0; i < demux->fragments_cache; i++) {
1127 gst_element_post_message (GST_ELEMENT (demux),
1128 gst_message_new_buffering (GST_OBJECT (demux),
1129 100 * i / demux->fragments_cache));
1130 g_get_current_time (&demux->next_update);
1131 if (!gst_hls_demux_get_next_fragment (demux, TRUE)) {
1132 if (demux->end_of_playlist)
1134 if (!demux->cancelled)
1135 GST_ERROR_OBJECT (demux, "Error caching the first fragments");
1138 /* make sure we stop caching fragments if something cancelled it */
1139 if (demux->cancelled)
1142 gst_element_post_message (GST_ELEMENT (demux),
1143 gst_message_new_buffering (GST_OBJECT (demux), 100));
1145 g_get_current_time (&demux->next_update);
1147 demux->need_cache = FALSE;
1153 gst_hls_src_buf_to_utf8_playlist (GstBuffer * buf)
1159 data = (gchar *) GST_BUFFER_DATA (buf);
1160 size = GST_BUFFER_SIZE (buf);
1162 if (!g_utf8_validate (data, size, NULL))
1163 goto validate_error;
1165 /* alloc size + 1 to end with a null character */
1166 playlist = g_malloc0 (size + 1);
1167 memcpy (playlist, data, size);
1169 gst_buffer_unref (buf);
1173 gst_buffer_unref (buf);
1178 gst_hls_demux_update_playlist (GstHLSDemux * demux, gboolean update)
1180 GstFragment *download;
1181 GstBufferListIterator *it;
1184 gboolean updated = FALSE;
1186 const gchar *uri = gst_m3u8_client_get_current_uri (demux->client);
1188 download = gst_uri_downloader_fetch_uri (demux->downloader, uri);
1190 if (download == NULL)
1193 /* Merge all the buffers in the list to build a unique buffer with the
1195 it = gst_buffer_list_iterate (gst_fragment_get_buffer_list (download));
1196 gst_buffer_list_iterator_next_group (it);
1197 buf = gst_buffer_list_iterator_merge_group (it);
1198 #ifdef GST_HLS_DEMUX_DUMP
1199 if (_dump_status & DUMP_M3U8)
1200 gst_hls_demux_dump_playlist (buf, uri);
1202 playlist = gst_hls_src_buf_to_utf8_playlist (buf);
1203 gst_buffer_list_iterator_free (it);
1204 g_object_unref (download);
1206 if (playlist == NULL) {
1207 GST_WARNING_OBJECT (demux, "Couldn't not validate playlist encoding");
1211 updated = gst_m3u8_client_update (demux->client, playlist);
1212 #ifndef GST_EXT_HLS_MODIFICATION
1213 /* If it's a live source, do not let the sequence number go beyond
1214 * three fragments before the end of the list */
1215 if (updated && update == FALSE && demux->client->current &&
1216 gst_m3u8_client_is_live (demux->client)) {
1217 guint last_sequence;
1219 GST_M3U8_CLIENT_LOCK (demux->client);
1221 GST_M3U8_MEDIA_FILE (g_list_last (demux->client->current->
1222 files)->data)->sequence;
1224 if (demux->client->sequence >= last_sequence - 3) {
1225 GST_DEBUG_OBJECT (demux, "Sequence is beyond playlist. Moving back to %d",
1227 demux->need_segment = TRUE;
1228 demux->client->sequence = last_sequence - 3;
1230 GST_M3U8_CLIENT_UNLOCK (demux->client);
1237 gst_hls_demux_change_playlist (GstHLSDemux * demux, guint max_bitrate)
1239 GList *previous_variant, *current_variant;
1240 gint old_bandwidth, new_bandwidth;
1242 /* If user specifies a connection speed never use a playlist with a bandwidth
1243 * superior than it */
1244 if (demux->connection_speed != 0 && max_bitrate > demux->connection_speed)
1245 max_bitrate = demux->connection_speed;
1247 previous_variant = demux->client->main->current_variant;
1248 current_variant = gst_m3u8_client_get_playlist_for_bitrate (demux->client,
1251 retry_failover_protection:
1252 old_bandwidth = GST_M3U8 (previous_variant->data)->bandwidth;
1253 new_bandwidth = GST_M3U8 (current_variant->data)->bandwidth;
1255 /* Don't do anything else if the playlist is the same */
1256 if (new_bandwidth == old_bandwidth) {
1260 demux->client->main->current_variant = current_variant;
1261 GST_M3U8_CLIENT_UNLOCK (demux->client);
1263 gst_m3u8_client_set_current (demux->client, current_variant->data);
1265 GST_INFO_OBJECT (demux, "Client was on %dbps, max allowed is %dbps, switching"
1266 " to bitrate %dbps", old_bandwidth, max_bitrate, new_bandwidth);
1268 if (gst_hls_demux_update_playlist (demux, FALSE)) {
1271 s = gst_structure_new ("playlist",
1272 "uri", G_TYPE_STRING, gst_m3u8_client_get_current_uri (demux->client),
1273 "bitrate", G_TYPE_INT, new_bandwidth, NULL);
1274 gst_element_post_message (GST_ELEMENT_CAST (demux),
1275 gst_message_new_element (GST_OBJECT_CAST (demux), s));
1277 GList *failover = NULL;
1279 GST_INFO_OBJECT (demux, "Unable to update playlist. Switching back");
1280 GST_M3U8_CLIENT_LOCK (demux->client);
1282 failover = g_list_previous (current_variant);
1283 if (failover && new_bandwidth == GST_M3U8 (failover->data)->bandwidth) {
1284 current_variant = failover;
1285 goto retry_failover_protection;
1288 demux->client->main->current_variant = previous_variant;
1289 GST_M3U8_CLIENT_UNLOCK (demux->client);
1290 gst_m3u8_client_set_current (demux->client, previous_variant->data);
1291 /* Try a lower bitrate (or stop if we just tried the lowest) */
1292 if (new_bandwidth ==
1293 GST_M3U8 (g_list_first (demux->client->main->lists)->data)->bandwidth)
1296 return gst_hls_demux_change_playlist (demux, new_bandwidth - 1);
1299 /* Force typefinding since we might have changed media type */
1300 demux->do_typefind = TRUE;
1306 gst_hls_demux_schedule (GstHLSDemux * demux, gboolean updated)
1308 gfloat update_factor;
1310 /* As defined in §6.3.4. Reloading the Playlist file:
1311 * "If the client reloads a Playlist file and finds that it has not
1312 * changed then it MUST wait for a period of one-half the target
1313 * duration before retrying."
1315 if (demux->client->update_failed_count > 0) {
1316 g_get_current_time (&demux->next_update);
1318 update_factor = (updated) ? UPDATE_FACTOR_DEFAULT : UPDATE_FACTOR_RETRY;
1320 /* schedule the next update using the target duration field of the
1322 g_time_val_add (&demux->next_update,
1323 gst_m3u8_client_get_target_duration (demux->client)
1324 / GST_SECOND * G_USEC_PER_SEC * update_factor);
1326 GST_DEBUG_OBJECT (demux, "Next update scheduled at %s",
1327 g_time_val_to_iso8601 (&demux->next_update));
1333 gst_hls_demux_switch_playlist (GstHLSDemux * demux, GstFragment *fragment)
1335 #ifndef GST_EXT_HLS_MODIFICATION
1342 GST_M3U8_CLIENT_LOCK (demux->client);
1343 if (!demux->client->main->lists) {
1344 GST_M3U8_CLIENT_UNLOCK (demux->client);
1347 GST_M3U8_CLIENT_UNLOCK (demux->client);
1349 /* compare the time when the fragment was downloaded with the time when it was
1351 #ifdef GST_EXT_HLS_MODIFICATION
1352 diff = fragment->download_stop_time - fragment->download_start_time;
1354 g_get_current_time (&now);
1355 diff = (GST_TIMEVAL_TO_TIME (now) - GST_TIMEVAL_TO_TIME (demux->next_update));
1357 size = gst_fragment_get_total_size (fragment);
1358 bitrate = (size * 8) / ((double) diff / GST_SECOND);
1360 GST_DEBUG ("Downloaded %d bytes in %" GST_TIME_FORMAT ". Bitrate is : %d",
1361 size, GST_TIME_ARGS (diff), bitrate);
1363 return gst_hls_demux_change_playlist (demux, bitrate * demux->bitrate_limit);
1367 gst_hls_demux_decrypt_buffer_list (GstHLSDemux * demux,
1368 GstBufferList * buffer_list)
1370 GstBufferListIterator *it;
1372 GstBuffer *buf, *remained_buf, *in_buf, *out_buf;
1373 gint in_size, out_size;
1375 remained_buf = NULL;
1376 it = gst_buffer_list_iterate (buffer_list);
1377 gst_buffer_list_iterator_next_group (it);
1378 while (buf = gst_buffer_list_iterator_next (it)) {
1380 in_buf = gst_buffer_merge (remained_buf, buf);
1381 gst_buffer_unref (remained_buf);
1382 remained_buf = NULL;
1387 in_size = GST_BUFFER_SIZE (in_buf);
1388 remain_size = in_size % GST_HLS_DEMUX_AES_BLOCK_SIZE;
1390 if (remain_size > 0) {
1391 remained_buf = gst_buffer_new_and_alloc (remain_size);
1392 memcpy (GST_BUFFER_DATA (remained_buf),
1393 GST_BUFFER_DATA (in_buf) + in_size - remain_size, remain_size);
1396 out_size = in_size - remain_size + GST_HLS_DEMUX_AES_BLOCK_SIZE;
1397 out_buf = gst_buffer_new_and_alloc (out_size);
1398 gst_buffer_copy_metadata (out_buf, in_buf, GST_BUFFER_COPY_FLAGS);
1400 if (!gst_m3u8_client_decrypt_update (demux->client, GST_BUFFER_DATA (out_buf),
1401 &out_size, GST_BUFFER_DATA (in_buf), in_size - remain_size)) {
1402 gst_buffer_unref (in_buf);
1403 gst_buffer_unref (out_buf);
1404 gst_buffer_list_iterator_free (it);
1408 gst_buffer_unref (in_buf);
1410 if (gst_buffer_list_iterator_n_buffers (it) == 0) {
1412 GST_WARNING_OBJECT (demux, "remained buffer should be empty!");
1413 gst_buffer_unref (remained_buf);
1415 remained_buf = gst_buffer_new_and_alloc (GST_HLS_DEMUX_AES_BLOCK_SIZE);
1416 if (gst_m3u8_client_decrypt_final (demux->client, GST_BUFFER_DATA (remained_buf),
1418 out_buf = gst_buffer_join (out_buf, remained_buf);
1419 out_size += remain_size;
1422 GST_BUFFER_SIZE (out_buf) = out_size;
1423 GST_BUFFER_TIMESTAMP (out_buf) = GST_CLOCK_TIME_NONE;
1424 GST_BUFFER_DURATION (out_buf) = GST_CLOCK_TIME_NONE;
1426 gst_buffer_list_iterator_take (it, out_buf);
1428 gst_buffer_list_iterator_free (it);
1434 gst_hls_demux_get_next_fragment (GstHLSDemux * demux, gboolean caching)
1436 GstFragment *download;
1437 const gchar *next_fragment_uri;
1438 GstM3U8Key *next_fragment_key;
1439 GstClockTime duration;
1440 GstClockTime timestamp;
1441 GstBufferList *buffer_list;
1442 GstBufferListIterator *it;
1446 if (!gst_m3u8_client_get_next_fragment (demux->client, &discont,
1447 &next_fragment_uri, &duration, ×tamp, &next_fragment_key)) {
1448 GST_INFO_OBJECT (demux, "This playlist doesn't contain more fragments");
1449 if (!gst_m3u8_client_is_live (demux->client))
1450 demux->end_of_playlist = TRUE;
1451 gst_task_start (demux->stream_task);
1455 if (next_fragment_key) {
1456 if (next_fragment_key->data == NULL) {
1457 GST_INFO_OBJECT (demux, "Fetching next fragment key %s",
1458 next_fragment_key->uri);
1460 download = gst_uri_downloader_fetch_uri (demux->downloader,
1461 next_fragment_key->uri);
1463 if (download == NULL)
1466 buffer_list = gst_fragment_get_buffer_list (download);
1467 it = gst_buffer_list_iterate (buffer_list);
1468 gst_buffer_list_iterator_next_group (it);
1469 buf = gst_buffer_list_iterator_merge_group (it);
1470 #ifdef GST_HLS_DEMUX_DUMP
1471 if (_dump_status & DUMP_KEY)
1472 gst_hls_demux_dump_key (buf, next_fragment_key->uri);
1474 next_fragment_key->data = GST_BUFFER_DATA (buf);
1475 gst_buffer_list_iterator_free (it);
1476 gst_buffer_list_unref (buffer_list);
1478 gst_m3u8_client_decrypt_init (demux->client, next_fragment_key);
1481 GST_INFO_OBJECT (demux, "Fetching next fragment %s", next_fragment_uri);
1483 download = gst_uri_downloader_fetch_uri (demux->downloader,
1486 if (download == NULL)
1489 buffer_list = gst_fragment_get_buffer_list (download);
1491 if (next_fragment_key && next_fragment_key->data) {
1492 #ifdef GST_HLS_DEMUX_DUMP
1493 if ((_dump_status & DUMP_TS) && (_dump_status & DUMP_KEY))
1494 gst_hls_demux_dump_fragment (buffer_list, next_fragment_uri, "enc_");
1496 if (!gst_hls_demux_decrypt_buffer_list (demux, buffer_list))
1499 #ifdef GST_HLS_DEMUX_DUMP
1500 if (_dump_status & DUMP_TS)
1501 gst_hls_demux_dump_fragment (buffer_list, next_fragment_uri, "");
1504 buf = gst_buffer_list_get (buffer_list, 0, 0);
1505 GST_BUFFER_DURATION (buf) = duration;
1506 GST_BUFFER_TIMESTAMP (buf) = timestamp;
1508 /* We actually need to do this every time we switch bitrate */
1509 if (G_UNLIKELY (demux->do_typefind)) {
1510 GstCaps *caps = gst_type_find_helper_for_buffer (NULL, buf, NULL);
1512 if (!demux->input_caps || !gst_caps_is_equal (caps, demux->input_caps)) {
1513 gst_caps_replace (&demux->input_caps, caps);
1514 /* gst_pad_set_caps (demux->srcpad, demux->input_caps); */
1515 GST_INFO_OBJECT (demux, "Input source caps: %" GST_PTR_FORMAT,
1517 demux->do_typefind = FALSE;
1519 gst_caps_unref (caps);
1521 gst_buffer_set_caps (buf, demux->input_caps);
1524 GST_DEBUG_OBJECT (demux, "Marking fragment as discontinuous");
1525 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
1528 /* try to switch to another bitrate if needed */
1529 gst_hls_demux_switch_playlist (demux, download);
1531 g_queue_push_tail (demux->queue, download);
1532 gst_buffer_list_unref (buffer_list);
1534 GST_TASK_SIGNAL (demux->updates_task);
1535 gst_task_start (demux->stream_task);
1541 gst_hls_demux_stop (demux);