[hls] Fixed code for HTTP live streaming service stabilization
[framework/multimedia/gst-plugins-bad0.10.git] / gst / hls / gsthlsdemux.c
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  *
8  * Gsthlsdemux.c:
9  *
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.
14  *
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.
19  *
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.
24  */
25 /**
26  * SECTION:element-hlsdemux
27  *
28  * HTTP Live Streaming demuxer element.
29  *
30  * <refsect2>
31  * <title>Example launch line</title>
32  * |[
33  * gst-launch souphttpsrc location=http://devimages.apple.com/iphone/samples/bipbop/gear4/prog_index.m3u8 ! hlsdemux ! decodebin2 ! ffmpegcolorspace ! videoscale ! autovideosink
34  * ]|
35  * </refsect2>
36  *
37  * Last reviewed on 2010-10-07
38  */
39
40 #ifdef HAVE_CONFIG_H
41 #  include "config.h"
42 #endif
43
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
47
48 #include <string.h>
49 #include <gst/base/gsttypefindhelper.h>
50 #include <gst/glib-compat-private.h>
51 #include "gsthlsdemux.h"
52
53 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src%d",
54     GST_PAD_SRC,
55     GST_PAD_SOMETIMES,
56     GST_STATIC_CAPS_ANY);
57
58 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
59     GST_PAD_SINK,
60     GST_PAD_ALWAYS,
61     GST_STATIC_CAPS ("application/x-hls"));
62
63 GST_DEBUG_CATEGORY_STATIC (gst_hls_demux_debug);
64 #define GST_CAT_DEFAULT gst_hls_demux_debug
65
66 enum
67 {
68   PROP_0,
69
70   PROP_FRAGMENTS_CACHE,
71   PROP_BITRATE_LIMIT,
72   PROP_CONNECTION_SPEED,
73   PROP_LAST
74 };
75
76
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
83 #else
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
88 #endif
89
90 #define UPDATE_FACTOR_DEFAULT 1
91 #define UPDATE_FACTOR_RETRY 0.5
92
93 #ifdef GST_HLS_DEMUX_DUMP
94 enum {
95   DUMP_TS = 0x01,
96   DUMP_TS_JOIN = 0x02,
97   DUMP_KEY = 0x04,
98   DUMP_M3U8 = 0x08,
99 };
100 static gint _dump_status = 0;
101 static gchar *_dump_dir_path = NULL;
102 #endif
103
104 /* GObject */
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);
110
111 /* GstElement */
112 static GstStateChangeReturn
113 gst_hls_demux_change_state (GstElement * element, GstStateChange transition);
114
115 /* GstHLSDemux */
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,
128     gboolean caching);
129 static gboolean gst_hls_demux_update_playlist (GstHLSDemux * demux,
130     gboolean update);
131 static void gst_hls_demux_reset (GstHLSDemux * demux, gboolean dispose);
132 static gboolean gst_hls_demux_set_location (GstHLSDemux * demux,
133     const gchar * uri);
134 static gchar *gst_hls_src_buf_to_utf8_playlist (GstBuffer * buf);
135
136 #ifdef GST_HLS_DEMUX_DUMP
137 static void
138 gst_hls_demux_init_dump (void)
139 {
140   const gchar *env_dump;
141   GDateTime *time;
142
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;
153   }
154
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);
160   }
161 }
162
163 static void
164 gst_hls_demux_fini_dump (void)
165 {
166   if (_dump_status > 0) {
167     if (_dump_dir_path) {
168       g_free(_dump_dir_path);
169       _dump_dir_path = NULL;
170     }
171     _dump_status = 0;
172   }
173 }
174
175 static void
176 gst_hls_demux_dump_fragment (GstBufferList * buffer_list, gchar * fragment_uri,
177     const gchar * prefix)
178 {
179   gchar *dump_path, *file_name;
180   FILE *fp;
181   GstBufferListIterator *it;
182   GstBuffer *buf;
183
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",
187         NULL);
188   } else {
189     file_name = g_strrstr (fragment_uri, "/") + 1;
190     dump_path = g_strjoin (NULL, _dump_dir_path, "/", prefix, file_name, NULL);
191   }
192   fp = fopen (dump_path, "wa+");
193
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);
198   }
199
200   fclose (fp);
201   g_free (dump_path);
202 }
203
204 static void
205 gst_hls_demux_dump_key (GstBuffer * buf, gchar * key_uri)
206 {
207   gchar *dump_path, *file_name;
208   FILE *fp;
209
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);
214   fclose (fp);
215   g_free (dump_path);
216 }
217
218 static void
219 gst_hls_demux_dump_playlist (GstBuffer * buf, gchar * playlist_uri)
220 {
221   GDateTime *time;
222   gchar *prefix, *dump_path, *file_name;
223   FILE *fp;
224
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);
231   g_free (prefix);
232   g_date_time_unref (time);
233   fclose (fp);
234   g_free (dump_path);
235 }
236 #endif
237
238 static void
239 _do_init (GType type)
240 {
241   GST_DEBUG_CATEGORY_INIT (gst_hls_demux_debug, "hlsdemux", 0,
242       "hlsdemux element");
243 }
244
245 GST_BOILERPLATE_FULL (GstHLSDemux, gst_hls_demux, GstElement,
246     GST_TYPE_ELEMENT, _do_init);
247
248 static void
249 gst_hls_demux_base_init (gpointer g_class)
250 {
251   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
252
253   gst_element_class_add_static_pad_template (element_class, &srctemplate);
254
255   gst_element_class_add_static_pad_template (element_class, &sinktemplate);
256
257   gst_element_class_set_details_simple (element_class,
258       "HLS Demuxer",
259       "Demuxer/URIList",
260       "HTTP Live Streaming demuxer",
261       "Marc-Andre Lureau <marcandre.lureau@gmail.com>\n"
262       "Andoni Morales Alastruey <ylatuya@gmail.com>");
263 }
264
265 static void
266 gst_hls_demux_dispose (GObject * obj)
267 {
268   GstHLSDemux *demux = GST_HLS_DEMUX (obj);
269
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);
274     }
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;
281   }
282
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);
287     }
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;
296   }
297
298   if (demux->downloader != NULL) {
299     g_object_unref (demux->downloader);
300     demux->downloader = NULL;
301   }
302
303   gst_hls_demux_reset (demux, TRUE);
304
305   g_queue_free (demux->queue);
306
307   G_OBJECT_CLASS (parent_class)->dispose (obj);
308 }
309
310 static void
311 gst_hls_demux_class_init (GstHLSDemuxClass * klass)
312 {
313   GObjectClass *gobject_class;
314   GstElementClass *gstelement_class;
315
316   gobject_class = (GObjectClass *) klass;
317   gstelement_class = (GstElementClass *) klass;
318
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;
322
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));
328
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));
335
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));
341
342   gstelement_class->change_state =
343       GST_DEBUG_FUNCPTR (gst_hls_demux_change_state);
344 }
345
346 static void
347 gst_hls_demux_init (GstHLSDemux * demux, GstHLSDemuxClass * klass)
348 {
349
350   /* sink pad */
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);
357
358   /* Downloader */
359   demux->downloader = gst_uri_downloader_new ();
360
361   demux->do_typefind = TRUE;
362
363   /* Properties */
364   demux->fragments_cache = DEFAULT_FRAGMENTS_CACHE;
365   demux->bitrate_limit = DEFAULT_BITRATE_LIMIT;
366   demux->connection_speed = DEFAULT_CONNECTION_SPEED;
367
368   demux->queue = g_queue_new ();
369
370   /* Updates task */
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 ();
376
377   /* Streaming task */
378   g_static_rec_mutex_init (&demux->stream_lock);
379   demux->stream_task =
380       gst_task_create ((GstTaskFunction) gst_hls_demux_stream_loop, demux);
381   gst_task_set_lock (demux->stream_task, &demux->stream_lock);
382 }
383
384 static void
385 gst_hls_demux_set_property (GObject * object, guint prop_id,
386     const GValue * value, GParamSpec * pspec)
387 {
388   GstHLSDemux *demux = GST_HLS_DEMUX (object);
389
390   switch (prop_id) {
391     case PROP_FRAGMENTS_CACHE:
392       demux->fragments_cache = g_value_get_uint (value);
393       break;
394     case PROP_BITRATE_LIMIT:
395       demux->bitrate_limit = g_value_get_float (value);
396       break;
397     case PROP_CONNECTION_SPEED:
398       demux->connection_speed = g_value_get_uint (value) * 1000;
399       break;
400     default:
401       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
402       break;
403   }
404 }
405
406 static void
407 gst_hls_demux_get_property (GObject * object, guint prop_id, GValue * value,
408     GParamSpec * pspec)
409 {
410   GstHLSDemux *demux = GST_HLS_DEMUX (object);
411
412   switch (prop_id) {
413     case PROP_FRAGMENTS_CACHE:
414       g_value_set_uint (value, demux->fragments_cache);
415       break;
416     case PROP_BITRATE_LIMIT:
417       g_value_set_float (value, demux->bitrate_limit);
418       break;
419     case PROP_CONNECTION_SPEED:
420       g_value_set_uint (value, demux->connection_speed / 1000);
421       break;
422     default:
423       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
424       break;
425   }
426 }
427
428 static GstStateChangeReturn
429 gst_hls_demux_change_state (GstElement * element, GstStateChange transition)
430 {
431   GstStateChangeReturn ret;
432   GstHLSDemux *demux = GST_HLS_DEMUX (element);
433
434   switch (transition) {
435 #ifdef GST_HLS_DEMUX_DUMP
436     case GST_STATE_CHANGE_NULL_TO_READY:
437       gst_hls_demux_init_dump ();
438       break;
439 #endif
440     case GST_STATE_CHANGE_READY_TO_PAUSED:
441       gst_hls_demux_reset (demux, FALSE);
442       break;
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
447        */
448       if (gst_m3u8_client_get_uri (demux->client)[0] != '\0')
449         gst_task_start (demux->updates_task);
450       break;
451     default:
452       break;
453   }
454
455   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
456
457   switch (transition) {
458     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
459       gst_task_stop (demux->updates_task);
460       break;
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);
466       break;
467 #ifdef GST_HLS_DEMUX_DUMP
468     case GST_STATE_CHANGE_READY_TO_NULL:
469       gst_hls_demux_fini_dump ();
470       break;
471 #endif
472     default:
473       break;
474   }
475   return ret;
476 }
477
478 static gboolean
479 gst_hls_demux_src_event (GstPad * pad, GstEvent * event)
480 {
481   GstHLSDemux *demux;
482
483   demux = GST_HLS_DEMUX (gst_pad_get_element_private (pad));
484
485   switch (event->type) {
486     case GST_EVENT_SEEK:
487     {
488       gdouble rate;
489       GstFormat format;
490       GstSeekFlags flags;
491       GstSeekType start_type, stop_type;
492       gint64 start, stop;
493       GList *walk;
494       GstClockTime position, current_pos, target_pos;
495       gint current_sequence;
496       GstM3U8MediaFile *file;
497
498       GST_INFO_OBJECT (demux, "Received GST_EVENT_SEEK");
499
500       if (gst_m3u8_client_is_live (demux->client)) {
501         GST_WARNING_OBJECT (demux, "Received seek event for live stream");
502         return FALSE;
503       }
504
505       gst_event_parse_seek (event, &rate, &format, &flags, &start_type, &start,
506           &stop_type, &stop);
507
508       if (format != GST_FORMAT_TIME)
509         return FALSE;
510
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));
514
515       GST_M3U8_CLIENT_LOCK (demux->client);
516       file = GST_M3U8_MEDIA_FILE (demux->client->current->files->data);
517       current_sequence = file->sequence;
518       current_pos = 0;
519       target_pos = (GstClockTime) start;
520       for (walk = demux->client->current->files; walk; walk = walk->next) {
521         file = walk->data;
522
523         current_sequence = file->sequence;
524         if (current_pos <= target_pos
525             && target_pos < current_pos + file->duration) {
526           break;
527         }
528         current_pos += file->duration;
529       }
530       GST_M3U8_CLIENT_UNLOCK (demux->client);
531
532       if (walk == NULL) {
533         GST_WARNING_OBJECT (demux, "Could not find seeked fragment");
534         return FALSE;
535       }
536
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 ());
540       }
541
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);
547
548       /* wait for streaming to finish */
549       g_static_rec_mutex_lock (&demux->stream_lock);
550
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);
555       }
556       g_queue_clear (demux->queue);
557
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);
565
566
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 ());
570       }
571
572       demux->cancelled = FALSE;
573       gst_task_start (demux->stream_task);
574       g_static_rec_mutex_unlock (&demux->stream_lock);
575
576       return TRUE;
577     }
578     default:
579       break;
580   }
581
582   return gst_pad_event_default (pad, event);
583 }
584
585 static gboolean
586 gst_hls_demux_sink_event (GstPad * pad, GstEvent * event)
587 {
588   GstHLSDemux *demux;
589   GstQuery *query;
590   gboolean ret;
591   gchar *uri;
592
593   demux = GST_HLS_DEMUX (gst_pad_get_parent (pad));
594
595   switch (event->type) {
596     case GST_EVENT_EOS:{
597       gchar *playlist = NULL;
598 #ifdef GST_EXT_HLS_MODIFICATION
599       GstElement *parent = GST_ELEMENT (demux);
600       gboolean done = FALSE;
601
602       /* get properties from http src plugin */
603       while (parent = GST_ELEMENT_PARENT (parent)) {
604         GstIterator *it;
605         GstIteratorResult ires;
606         gpointer item;
607         gchar *user_agent = NULL, **cookies = NULL, *cookies_str = NULL;
608
609         it = gst_bin_iterate_sources (GST_BIN (parent));
610         do {
611           ires = gst_iterator_next (it, &item);
612            switch (ires) {
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);
616               if (user_agent) {
617                 gst_uri_downloader_set_user_agent (demux->downloader, user_agent);
618                 GST_INFO_OBJECT(demux, "get user-agent:%s", user_agent);
619               }
620               if (cookies) {
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);
625               }
626               done = TRUE;
627               break;
628             case GST_ITERATOR_RESYNC:
629               gst_iterator_resync (it);
630               break;
631             default:
632                break;
633           }
634         } while (ires == GST_ITERATOR_OK || ires == GST_ITERATOR_RESYNC);
635         gst_iterator_free (it);
636         if (done)
637           break;
638       }
639 #endif
640
641       if (demux->playlist == NULL) {
642         GST_WARNING_OBJECT (demux, "Received EOS without a playlist.");
643         break;
644       }
645
646       GST_DEBUG_OBJECT (demux,
647           "Got EOS on the sink pad: main playlist fetched");
648
649       query = gst_query_new_uri ();
650       ret = gst_pad_peer_query (demux->sinkpad, query);
651       if (ret) {
652         gst_query_parse_uri (query, &uri);
653         gst_hls_demux_set_location (demux, uri);
654         g_free (uri);
655       }
656       gst_query_unref (query);
657
658 #ifdef GST_HLS_DEMUX_DUMP
659   if (_dump_status & DUMP_M3U8)
660     gst_hls_demux_dump_playlist (demux->playlist, demux->client->main->uri);
661 #endif
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
669          * the playlist */
670         GST_ELEMENT_ERROR (demux, STREAM, DECODE, ("Invalid playlist."),
671             (NULL));
672         gst_object_unref (demux);
673         return FALSE;
674       }
675
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);
681         return FALSE;
682       }
683
684       gst_task_start (demux->stream_task);
685       gst_event_unref (event);
686       gst_object_unref (demux);
687       return TRUE;
688     }
689     case GST_EVENT_NEWSEGMENT:
690       /* Swallow newsegments, we'll push our own */
691       gst_event_unref (event);
692       gst_object_unref (demux);
693       return TRUE;
694     default:
695       break;
696   }
697
698   gst_object_unref (demux);
699
700   return gst_pad_event_default (pad, event);
701 }
702
703 static gboolean
704 gst_hls_demux_src_query (GstPad * pad, GstQuery * query)
705 {
706   GstHLSDemux *hlsdemux;
707   gboolean ret = FALSE;
708
709   if (query == NULL)
710     return FALSE;
711
712   hlsdemux = GST_HLS_DEMUX (gst_pad_get_element_private (pad));
713
714   switch (query->type) {
715     case GST_QUERY_DURATION:{
716       GstClockTime duration = -1;
717       GstFormat fmt;
718
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);
724           ret = TRUE;
725         }
726       }
727       GST_LOG_OBJECT (hlsdemux, "GST_QUERY_DURATION returns %s with duration %"
728           GST_TIME_FORMAT, ret ? "TRUE" : "FALSE", GST_TIME_ARGS (duration));
729       break;
730     }
731     case GST_QUERY_URI:
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));
736         ret = TRUE;
737       }
738       break;
739     case GST_QUERY_SEEKING:{
740       GstFormat fmt;
741       gint64 stop = -1;
742
743       gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
744       GST_INFO_OBJECT (hlsdemux, "Received GST_QUERY_SEEKING with format %d",
745           fmt);
746       if (fmt == GST_FORMAT_TIME) {
747         GstClockTime duration;
748
749         duration = gst_m3u8_client_get_duration (hlsdemux->client);
750         if (GST_CLOCK_TIME_IS_VALID (duration) && duration > 0)
751           stop = duration;
752
753         gst_query_set_seeking (query, fmt,
754             !gst_m3u8_client_is_live (hlsdemux->client), 0, stop);
755         ret = TRUE;
756         GST_INFO_OBJECT (hlsdemux, "GST_QUERY_SEEKING returning with stop : %"
757             GST_TIME_FORMAT, GST_TIME_ARGS (stop));
758       }
759       break;
760     }
761     default:
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
764        * first playlist */
765       break;
766   }
767
768   return ret;
769 }
770
771 static GstFlowReturn
772 gst_hls_demux_chain (GstPad * pad, GstBuffer * buf)
773 {
774   GstHLSDemux *demux = GST_HLS_DEMUX (gst_pad_get_parent (pad));
775
776   if (demux->playlist == NULL)
777     demux->playlist = buf;
778   else
779     demux->playlist = gst_buffer_join (demux->playlist, buf);
780
781   gst_object_unref (demux);
782
783   return GST_FLOW_OK;
784 }
785
786 static void
787 gst_hls_demux_stop (GstHLSDemux * demux)
788 {
789   gst_uri_downloader_cancel (demux->downloader);
790
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);
796   }
797
798   if (demux->stream_task
799       && GST_TASK_STATE (demux->stream_task) != GST_TASK_STOPPED)
800     gst_task_stop (demux->stream_task);
801 }
802
803 static void
804 switch_pads (GstHLSDemux * demux, GstCaps * newcaps)
805 {
806   GstPad *oldpad = demux->srcpad;
807
808   GST_DEBUG ("Switching pads (oldpad:%p) with caps: %" GST_PTR_FORMAT, oldpad,
809       newcaps);
810
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.
815    *
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.
819    */
820   if (demux->srcpad)
821     gst_pad_push_event (demux->srcpad, gst_event_new_flush_stop ());
822
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);
833
834   gst_element_no_more_pads (GST_ELEMENT (demux));
835
836   if (oldpad) {
837     /* Push out EOS */
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);
841   }
842 }
843
844 static void
845 gst_hls_demux_stream_loop (GstHLSDemux * demux)
846 {
847   GstFragment *fragment;
848   GstBufferList *buffer_list;
849   GstBuffer *buf;
850   GstFlowReturn ret;
851
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  */
857
858   if (G_UNLIKELY (demux->need_cache)) {
859     if (!gst_hls_demux_cache_fragments (demux))
860       goto cache_error;
861
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");
866   }
867
868   if (g_queue_is_empty (demux->queue)) {
869     if (demux->end_of_playlist)
870       goto end_of_playlist;
871
872     goto pause_task;
873   }
874
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);
879
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))))
886 #else
887           || !gst_caps_is_equal_fixed (GST_BUFFER_CAPS (buf),
888               GST_PAD_CAPS (demux->srcpad))
889 #endif
890           || demux->need_segment)) {
891     switch_pads (demux, GST_BUFFER_CAPS (buf));
892     demux->need_segment = TRUE;
893   }
894   g_object_unref (fragment);
895
896   if (demux->need_segment) {
897     GstClockTime start = GST_BUFFER_TIMESTAMP (buf);
898
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;
908   }
909
910   ret = gst_pad_push_list (demux->srcpad, buffer_list);
911   if (ret != GST_FLOW_OK)
912     goto error_pushing;
913
914   return;
915
916 end_of_playlist:
917   {
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);
921     return;
922   }
923
924 cache_error:
925   {
926     if (GST_TASK_STATE (demux->stream_task) != GST_TASK_STOPPED) {
927       gst_task_pause (demux->stream_task);
928     }
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);
933     }
934     return;
935   }
936
937 error_pushing:
938   {
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);
943     return;
944   }
945
946 pause_task:
947   {
948     if (GST_TASK_STATE (demux->stream_task) != GST_TASK_STOPPED) {
949       gst_task_pause (demux->stream_task);
950     }
951     return;
952   }
953 }
954
955 static void
956 gst_hls_demux_reset (GstHLSDemux * demux, gboolean dispose)
957 {
958   demux->need_cache = TRUE;
959   demux->end_of_playlist = FALSE;
960   demux->do_typefind = TRUE;
961
962   if (demux->input_caps) {
963     gst_caps_unref (demux->input_caps);
964     demux->input_caps = NULL;
965   }
966
967   if (demux->playlist) {
968     gst_buffer_unref (demux->playlist);
969     demux->playlist = NULL;
970   }
971
972   if (demux->client) {
973     gst_m3u8_client_free (demux->client);
974     demux->client = NULL;
975   }
976
977   if (!dispose) {
978     demux->client = gst_m3u8_client_new ("");
979     demux->cancelled = FALSE;
980   }
981
982   while (!g_queue_is_empty (demux->queue)) {
983     GstFragment *fragment = g_queue_pop_head (demux->queue);
984     g_object_unref (fragment);
985   }
986   g_queue_clear (demux->queue);
987
988   demux->position_shift = 0;
989   demux->need_segment = TRUE;
990 }
991
992 static gboolean
993 gst_hls_demux_set_location (GstHLSDemux * demux, const gchar * uri)
994 {
995   if (demux->client)
996     gst_m3u8_client_free (demux->client);
997   demux->client = gst_m3u8_client_new (uri);
998   GST_INFO_OBJECT (demux, "Changed location: %s", uri);
999   return TRUE;
1000 }
1001
1002 void
1003 gst_hls_demux_updates_loop (GstHLSDemux * demux)
1004 {
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 */
1010
1011   g_mutex_lock (demux->updates_timed_lock);
1012   GST_DEBUG_OBJECT (demux, "Started updates task");
1013   while (TRUE) {
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))) {
1018       goto quit;
1019     }
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");
1029           }
1030           continue;
1031         } else {
1032           GST_ELEMENT_ERROR (demux, RESOURCE, NOT_FOUND,
1033               ("Could not update the playlist"), (NULL));
1034           goto quit;
1035         }
1036       }
1037     }
1038
1039     if (demux->cancelled)
1040       goto quit;
1041
1042     /* schedule the next update */
1043     gst_hls_demux_schedule (demux, TRUE);
1044
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");
1051             continue;
1052           } else {
1053             GST_ELEMENT_ERROR (demux, RESOURCE, NOT_FOUND,
1054                 ("Could not fetch the next fragment"), (NULL));
1055             goto quit;
1056           }
1057         }
1058       } else {
1059         demux->client->update_failed_count = 0;
1060       }
1061     }
1062   }
1063
1064 quit:
1065   {
1066     GST_DEBUG_OBJECT (demux, "Stopped updates task");
1067     gst_hls_demux_stop (demux);
1068     g_mutex_unlock (demux->updates_timed_lock);
1069   }
1070 }
1071
1072 static gboolean
1073 gst_hls_demux_cache_fragments (GstHLSDemux * demux)
1074 {
1075   gint i;
1076
1077   /* If this playlist is a variant playlist, select the first one
1078    * and update it */
1079   if (gst_m3u8_client_has_variant_playlist (demux->client)) {
1080     GstM3U8 *child = NULL;
1081
1082     if (demux->connection_speed == 0) {
1083
1084       GST_M3U8_CLIENT_LOCK (demux->client);
1085       child = demux->client->main->current_variant->data;
1086       GST_M3U8_CLIENT_UNLOCK (demux->client);
1087     } else {
1088       GList *tmp = gst_m3u8_client_get_playlist_for_bitrate (demux->client,
1089           demux->connection_speed);
1090
1091       child = GST_M3U8 (tmp->data);
1092     }
1093
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",
1097           child->uri);
1098       return FALSE;
1099     }
1100   }
1101
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;
1110     else
1111       demux->client->sequence = 0;
1112     GST_M3U8_CLIENT_UNLOCK (demux->client);
1113 #endif
1114   } else {
1115     GstClockTime duration = gst_m3u8_client_get_duration (demux->client);
1116
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));
1123   }
1124
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)
1133         break;
1134       if (!demux->cancelled)
1135         GST_ERROR_OBJECT (demux, "Error caching the first fragments");
1136       return FALSE;
1137     }
1138     /* make sure we stop caching fragments if something cancelled it */
1139     if (demux->cancelled)
1140       return FALSE;
1141   }
1142   gst_element_post_message (GST_ELEMENT (demux),
1143       gst_message_new_buffering (GST_OBJECT (demux), 100));
1144
1145   g_get_current_time (&demux->next_update);
1146
1147   demux->need_cache = FALSE;
1148   return TRUE;
1149
1150 }
1151
1152 static gchar *
1153 gst_hls_src_buf_to_utf8_playlist (GstBuffer * buf)
1154 {
1155   gint size;
1156   gchar *data;
1157   gchar *playlist;
1158
1159   data = (gchar *) GST_BUFFER_DATA (buf);
1160   size = GST_BUFFER_SIZE (buf);
1161
1162   if (!g_utf8_validate (data, size, NULL))
1163     goto validate_error;
1164
1165   /* alloc size + 1 to end with a null character */
1166   playlist = g_malloc0 (size + 1);
1167   memcpy (playlist, data, size);
1168
1169   gst_buffer_unref (buf);
1170   return playlist;
1171
1172 validate_error:
1173   gst_buffer_unref (buf);
1174   return NULL;
1175 }
1176
1177 static gboolean
1178 gst_hls_demux_update_playlist (GstHLSDemux * demux, gboolean update)
1179 {
1180   GstFragment *download;
1181   GstBufferListIterator *it;
1182   GstBuffer *buf;
1183   gchar *playlist;
1184   gboolean updated = FALSE;
1185
1186   const gchar *uri = gst_m3u8_client_get_current_uri (demux->client);
1187
1188   download = gst_uri_downloader_fetch_uri (demux->downloader, uri);
1189
1190   if (download == NULL)
1191     return FALSE;
1192
1193   /* Merge all the buffers in the list to build a unique buffer with the
1194    * playlist */
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);
1201 #endif
1202   playlist = gst_hls_src_buf_to_utf8_playlist (buf);
1203   gst_buffer_list_iterator_free (it);
1204   g_object_unref (download);
1205
1206   if (playlist == NULL) {
1207     GST_WARNING_OBJECT (demux, "Couldn't not validate playlist encoding");
1208     return FALSE;
1209   }
1210
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;
1218
1219     GST_M3U8_CLIENT_LOCK (demux->client);
1220     last_sequence =
1221         GST_M3U8_MEDIA_FILE (g_list_last (demux->client->current->
1222             files)->data)->sequence;
1223
1224     if (demux->client->sequence >= last_sequence - 3) {
1225       GST_DEBUG_OBJECT (demux, "Sequence is beyond playlist. Moving back to %d",
1226           last_sequence - 3);
1227       demux->need_segment = TRUE;
1228       demux->client->sequence = last_sequence - 3;
1229     }
1230     GST_M3U8_CLIENT_UNLOCK (demux->client);
1231   }
1232 #endif
1233   return updated;
1234 }
1235
1236 static gboolean
1237 gst_hls_demux_change_playlist (GstHLSDemux * demux, guint max_bitrate)
1238 {
1239   GList *previous_variant, *current_variant;
1240   gint old_bandwidth, new_bandwidth;
1241
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;
1246
1247   previous_variant = demux->client->main->current_variant;
1248   current_variant = gst_m3u8_client_get_playlist_for_bitrate (demux->client,
1249       max_bitrate);
1250
1251 retry_failover_protection:
1252   old_bandwidth = GST_M3U8 (previous_variant->data)->bandwidth;
1253   new_bandwidth = GST_M3U8 (current_variant->data)->bandwidth;
1254
1255   /* Don't do anything else if the playlist is the same */
1256   if (new_bandwidth == old_bandwidth) {
1257     return TRUE;
1258   }
1259
1260   demux->client->main->current_variant = current_variant;
1261   GST_M3U8_CLIENT_UNLOCK (demux->client);
1262
1263   gst_m3u8_client_set_current (demux->client, current_variant->data);
1264
1265   GST_INFO_OBJECT (demux, "Client was on %dbps, max allowed is %dbps, switching"
1266       " to bitrate %dbps", old_bandwidth, max_bitrate, new_bandwidth);
1267
1268   if (gst_hls_demux_update_playlist (demux, FALSE)) {
1269     GstStructure *s;
1270
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));
1276   } else {
1277     GList *failover = NULL;
1278
1279     GST_INFO_OBJECT (demux, "Unable to update playlist. Switching back");
1280     GST_M3U8_CLIENT_LOCK (demux->client);
1281
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;
1286     }
1287
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)
1294       return FALSE;
1295     else
1296       return gst_hls_demux_change_playlist (demux, new_bandwidth - 1);
1297   }
1298
1299   /* Force typefinding since we might have changed media type */
1300   demux->do_typefind = TRUE;
1301
1302   return TRUE;
1303 }
1304
1305 static gboolean
1306 gst_hls_demux_schedule (GstHLSDemux * demux, gboolean updated)
1307 {
1308   gfloat update_factor;
1309
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."
1314    */
1315   if (demux->client->update_failed_count > 0) {
1316     g_get_current_time (&demux->next_update);
1317   } else {
1318     update_factor = (updated) ? UPDATE_FACTOR_DEFAULT : UPDATE_FACTOR_RETRY;
1319
1320     /* schedule the next update using the target duration field of the
1321      * playlist */
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);
1325   }
1326   GST_DEBUG_OBJECT (demux, "Next update scheduled at %s",
1327       g_time_val_to_iso8601 (&demux->next_update));
1328
1329   return TRUE;
1330 }
1331
1332 static gboolean
1333 gst_hls_demux_switch_playlist (GstHLSDemux * demux, GstFragment *fragment)
1334 {
1335 #ifndef GST_EXT_HLS_MODIFICATION
1336   GTimeVal now;
1337 #endif
1338   GstClockTime diff;
1339   gsize size;
1340   gint bitrate;
1341
1342   GST_M3U8_CLIENT_LOCK (demux->client);
1343   if (!demux->client->main->lists) {
1344     GST_M3U8_CLIENT_UNLOCK (demux->client);
1345     return TRUE;
1346   }
1347   GST_M3U8_CLIENT_UNLOCK (demux->client);
1348
1349   /* compare the time when the fragment was downloaded with the time when it was
1350    * scheduled */
1351 #ifdef GST_EXT_HLS_MODIFICATION
1352   diff = fragment->download_stop_time - fragment->download_start_time;
1353 #else
1354   g_get_current_time (&now);
1355   diff = (GST_TIMEVAL_TO_TIME (now) - GST_TIMEVAL_TO_TIME (demux->next_update));
1356 #endif
1357   size = gst_fragment_get_total_size (fragment);
1358   bitrate = (size * 8) / ((double) diff / GST_SECOND);
1359
1360   GST_DEBUG ("Downloaded %d bytes in %" GST_TIME_FORMAT ". Bitrate is : %d",
1361       size, GST_TIME_ARGS (diff), bitrate);
1362
1363   return gst_hls_demux_change_playlist (demux, bitrate * demux->bitrate_limit);
1364 }
1365
1366 static gboolean
1367 gst_hls_demux_decrypt_buffer_list (GstHLSDemux * demux,
1368     GstBufferList * buffer_list)
1369 {
1370   GstBufferListIterator *it;
1371   gint remain_size;
1372   GstBuffer *buf, *remained_buf, *in_buf, *out_buf;
1373   gint in_size, out_size;
1374
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)) {
1379     if (remained_buf) {
1380       in_buf = gst_buffer_merge (remained_buf, buf);
1381       gst_buffer_unref (remained_buf);
1382       remained_buf = NULL;
1383     } else {
1384       in_buf = buf;
1385     }
1386
1387     in_size = GST_BUFFER_SIZE (in_buf);
1388     remain_size = in_size % GST_HLS_DEMUX_AES_BLOCK_SIZE;
1389
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);
1394     }
1395
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);
1399
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);
1405       return FALSE;
1406     }
1407     if (in_buf != buf)
1408       gst_buffer_unref (in_buf);
1409
1410     if (gst_buffer_list_iterator_n_buffers (it) == 0) {
1411       if (remained_buf) {
1412         GST_WARNING_OBJECT (demux, "remained buffer should be empty!");
1413         gst_buffer_unref (remained_buf);
1414       }
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),
1417           &remain_size)) {
1418         out_buf = gst_buffer_join (out_buf, remained_buf);
1419         out_size += remain_size;
1420       }
1421     }
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;
1425
1426     gst_buffer_list_iterator_take (it, out_buf);
1427   }
1428   gst_buffer_list_iterator_free (it);
1429
1430   return TRUE;
1431 }
1432
1433 static gboolean
1434 gst_hls_demux_get_next_fragment (GstHLSDemux * demux, gboolean caching)
1435 {
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;
1443   GstBuffer *buf;
1444   gboolean discont;
1445
1446   if (!gst_m3u8_client_get_next_fragment (demux->client, &discont,
1447           &next_fragment_uri, &duration, &timestamp, &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);
1452     return FALSE;
1453   }
1454
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);
1459
1460       download = gst_uri_downloader_fetch_uri (demux->downloader,
1461           next_fragment_key->uri);
1462
1463       if (download == NULL)
1464         goto error;
1465
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);
1473 #endif
1474       next_fragment_key->data = GST_BUFFER_DATA (buf);
1475       gst_buffer_list_iterator_free (it);
1476       gst_buffer_list_unref (buffer_list);
1477     }
1478     gst_m3u8_client_decrypt_init (demux->client, next_fragment_key);
1479   }
1480
1481   GST_INFO_OBJECT (demux, "Fetching next fragment %s", next_fragment_uri);
1482
1483   download = gst_uri_downloader_fetch_uri (demux->downloader,
1484       next_fragment_uri);
1485
1486   if (download == NULL)
1487     goto error;
1488
1489   buffer_list = gst_fragment_get_buffer_list (download);
1490
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_");
1495 #endif
1496     if (!gst_hls_demux_decrypt_buffer_list (demux, buffer_list))
1497       goto error;
1498   }
1499 #ifdef GST_HLS_DEMUX_DUMP
1500   if (_dump_status & DUMP_TS)
1501     gst_hls_demux_dump_fragment (buffer_list, next_fragment_uri, "");
1502 #endif
1503
1504   buf = gst_buffer_list_get (buffer_list, 0, 0);
1505   GST_BUFFER_DURATION (buf) = duration;
1506   GST_BUFFER_TIMESTAMP (buf) = timestamp;
1507
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);
1511
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,
1516           demux->input_caps);
1517       demux->do_typefind = FALSE;
1518     }
1519     gst_caps_unref (caps);
1520   }
1521   gst_buffer_set_caps (buf, demux->input_caps);
1522
1523   if (discont) {
1524     GST_DEBUG_OBJECT (demux, "Marking fragment as discontinuous");
1525     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
1526   }
1527
1528   /* try to switch to another bitrate if needed */
1529   gst_hls_demux_switch_playlist (demux, download);
1530
1531   g_queue_push_tail (demux->queue, download);
1532   gst_buffer_list_unref (buffer_list);
1533   if (!caching) {
1534     GST_TASK_SIGNAL (demux->updates_task);
1535     gst_task_start (demux->stream_task);
1536   }
1537   return TRUE;
1538
1539 error:
1540   {
1541     gst_hls_demux_stop (demux);
1542     return FALSE;
1543   }
1544 }