]> git.sesse.net Git - vlc/blob - modules/stream_filter/httplive.c
stream_filter/httplive.c: signal download thread on successfull index reload (live...
[vlc] / modules / stream_filter / httplive.c
1 /*****************************************************************************
2  * httplive.c: HTTP Live Streaming stream filter
3  *****************************************************************************
4  * Copyright (C) 2010-2011 M2X BV
5  * $Id$
6  *
7  * Author: Jean-Paul Saman <jpsaman _AT_ videolan _DOT_ org>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #include <limits.h>
32 #include <errno.h>
33
34 #include <vlc_common.h>
35 #include <vlc_plugin.h>
36
37 #include <assert.h>
38
39 #include <vlc_threads.h>
40 #include <vlc_arrays.h>
41 #include <vlc_stream.h>
42 #include <vlc_url.h>
43 #include <vlc_memory.h>
44
45 /*****************************************************************************
46  * Module descriptor
47  *****************************************************************************/
48 static int  Open (vlc_object_t *);
49 static void Close(vlc_object_t *);
50
51 vlc_module_begin()
52     set_category(CAT_INPUT)
53     set_subcategory(SUBCAT_INPUT_STREAM_FILTER)
54     set_description(N_("Http Live Streaming stream filter"))
55     set_capability("stream_filter", 20)
56     set_callbacks(Open, Close)
57 vlc_module_end()
58
59 /*****************************************************************************
60  *
61  *****************************************************************************/
62 typedef struct segment_s
63 {
64     int         sequence;   /* unique sequence number */
65     int         duration;   /* segment duration (seconds) */
66     uint64_t    size;       /* segment size in bytes */
67     uint64_t    bandwidth;  /* bandwidth usage of segments (bits per second)*/
68
69     vlc_url_t   url;
70     vlc_mutex_t lock;
71     block_t     *data;      /* data */
72 } segment_t;
73
74 typedef struct hls_stream_s
75 {
76     int         id;         /* program id */
77     int         version;    /* protocol version should be 1 */
78     int         sequence;   /* media sequence number */
79     int         duration;   /* maximum duration per segment (ms) */
80     uint64_t    bandwidth;  /* bandwidth usage of segments (bits per second)*/
81     uint64_t    size;       /* stream length (segment->duration * hls->bandwidth/8) */
82
83     vlc_array_t *segments;  /* list of segments */
84     vlc_url_t   url;        /* uri to m3u8 */
85     vlc_mutex_t lock;
86     bool        b_cache;    /* allow caching */
87 } hls_stream_t;
88
89 struct stream_sys_t
90 {
91     vlc_url_t     m3u8;         /* M3U8 url */
92     vlc_thread_t  reload;       /* HLS m3u8 reload thread */
93     vlc_thread_t  thread;       /* HLS segment download thread */
94
95     block_t      *peeked;
96
97     /* */
98     vlc_array_t  *hls_stream;   /* bandwidth adaptation */
99     uint64_t      bandwidth;    /* measured bandwidth (bits per second) */
100
101     /* Download */
102     struct hls_download_s
103     {
104         int         stream;     /* current hls_stream  */
105         int         segment;    /* current segment for downloading */
106         int         seek;       /* segment requested by seek (default -1) */
107         vlc_mutex_t lock_wait;  /* protect segment download counter */
108         vlc_cond_t  wait;       /* some condition to wait on */
109     } download;
110
111     /* Playback */
112     struct hls_playback_s
113     {
114         uint64_t    offset;     /* current offset in media */
115         int         stream;     /* current hls_stream  */
116         int         segment;    /* current segment for playback */
117     } playback;
118
119     /* Playlist */
120     struct hls_playlist_s
121     {
122         mtime_t     last;       /* playlist last loaded */
123         mtime_t     wakeup;     /* next reload time */
124         int         tries;      /* times it was not changed */
125     } playlist;
126
127     /* state */
128     bool        b_cache;    /* can cache files */
129     bool        b_meta;     /* meta playlist */
130     bool        b_live;     /* live stream? or vod? */
131     bool        b_error;    /* parsing error */
132 };
133
134 /****************************************************************************
135  * Local prototypes
136  ****************************************************************************/
137 static int  Read   (stream_t *, void *p_read, unsigned int i_read);
138 static int  Peek   (stream_t *, const uint8_t **pp_peek, unsigned int i_peek);
139 static int  Control(stream_t *, int i_query, va_list);
140
141 static ssize_t read_M3U8_from_stream(stream_t *s, uint8_t **buffer);
142 static ssize_t read_M3U8_from_url(stream_t *s, vlc_url_t *url, uint8_t **buffer);
143 static char *ReadLine(uint8_t *buffer, uint8_t **pos, size_t len);
144
145 static int hls_Download(stream_t *s, segment_t *segment);
146
147 static void* hls_Thread(void *);
148 static void* hls_Reload(void *);
149
150 static segment_t *segment_GetSegment(hls_stream_t *hls, int wanted);
151 static void segment_Free(segment_t *segment);
152
153 /****************************************************************************
154  *
155  ****************************************************************************/
156 static const char *const ext[] = {
157     "#EXT-X-TARGETDURATION",
158     "#EXT-X-MEDIA-SEQUENCE",
159     "#EXT-X-KEY",
160     "#EXT-X-ALLOW-CACHE",
161     "#EXT-X-ENDLIST",
162     "#EXT-X-STREAM-INF",
163     "#EXT-X-DISCONTINUITY",
164     "#EXT-X-VERSION"
165 };
166
167 static bool isHTTPLiveStreaming(stream_t *s)
168 {
169     const uint8_t *peek, *peek_end;
170
171     int64_t i_size = stream_Peek(s->p_source, &peek, 46);
172     if (i_size < 1)
173         return false;
174
175     if (strncasecmp((const char*)peek, "#EXTM3U", 7) != 0)
176         return false;
177
178     /* Parse stream and search for
179      * EXT-X-TARGETDURATION or EXT-X-STREAM-INF tag, see
180      * http://tools.ietf.org/html/draft-pantos-http-live-streaming-04#page-8 */
181     peek_end = peek + i_size;
182     while(peek <= peek_end)
183     {
184         if (*peek == '#')
185         {
186             for (unsigned int i = 0; i < ARRAY_SIZE(ext); i++)
187             {
188                 char *p = strstr((const char*)peek, ext[i]);
189                 if (p != NULL)
190                     return true;
191             }
192         }
193         peek++;
194     };
195
196     return false;
197 }
198
199 /* HTTP Live Streaming */
200 static hls_stream_t *hls_New(vlc_array_t *hls_stream, const int id, const uint64_t bw, const char *uri)
201 {
202     hls_stream_t *hls = (hls_stream_t *)malloc(sizeof(hls_stream_t));
203     if (hls == NULL) return NULL;
204
205     hls->id = id;
206     hls->bandwidth = bw;
207     hls->duration = -1;/* unknown */
208     hls->size = 0;
209     hls->sequence = 0; /* default is 0 */
210     hls->version = 1;  /* default protocol version */
211     hls->b_cache = true;
212     vlc_UrlParse(&hls->url, uri, 0);
213     hls->segments = vlc_array_new();
214     vlc_array_append(hls_stream, hls);
215     vlc_mutex_init(&hls->lock);
216     return hls;
217 }
218
219 static void hls_Free(hls_stream_t *hls)
220 {
221     vlc_mutex_destroy(&hls->lock);
222
223     if (hls->segments)
224     {
225         for (int n = 0; n < vlc_array_count(hls->segments); n++)
226         {
227             segment_t *segment = (segment_t *)vlc_array_item_at_index(hls->segments, n);
228             if (segment) segment_Free(segment);
229         }
230         vlc_array_destroy(hls->segments);
231     }
232
233     vlc_UrlClean(&hls->url);
234     free(hls);
235     hls = NULL;
236 }
237
238 static hls_stream_t *hls_Get(vlc_array_t *hls_stream, const int wanted)
239 {
240     int count = vlc_array_count(hls_stream);
241     if (count <= 0)
242         return NULL;
243     if ((wanted < 0) || (wanted >= count))
244         return NULL;
245     return (hls_stream_t *) vlc_array_item_at_index(hls_stream, wanted);
246 }
247
248 static inline hls_stream_t *hls_GetFirst(vlc_array_t *hls_stream)
249 {
250     return (hls_stream_t*) hls_Get(hls_stream, 0);
251 }
252
253 static hls_stream_t *hls_GetLast(vlc_array_t *hls_stream)
254 {
255     int count = vlc_array_count(hls_stream);
256     if (count <= 0)
257         return NULL;
258     count--;
259     return (hls_stream_t *) hls_Get(hls_stream, count);
260 }
261
262 static hls_stream_t *hls_Find(vlc_array_t *hls_stream, hls_stream_t *hls_new)
263 {
264     int count = vlc_array_count(hls_stream);
265     for (int n = 0; n < count; n++)
266     {
267         hls_stream_t *hls = vlc_array_item_at_index(hls_stream, n);
268         if (hls)
269         {
270             /* compare */
271             if ((hls->id == hls_new->id) &&
272                 (hls->bandwidth == hls_new->bandwidth))
273                 return hls;
274         }
275     }
276     return NULL;
277 }
278
279 static uint64_t hls_GetStreamSize(hls_stream_t *hls)
280 {
281     /* NOTE: Stream size is calculated based on segment duration and
282      * HLS stream bandwidth from the .m3u8 file. If these are not correct
283      * then the deviation from exact byte size will be big and the seek/
284      * progressbar will not behave entirely as one expects. */
285     uint64_t size = 0UL;
286     int count = vlc_array_count(hls->segments);
287     for (int n = 0; n < count; n++)
288     {
289         segment_t *segment = segment_GetSegment(hls, n);
290         if (segment)
291         {
292             size += (segment->duration * (hls->bandwidth / 8));
293         }
294     }
295     return size;
296 }
297
298 /* Segment */
299 static segment_t *segment_New(hls_stream_t* hls, const int duration, const char *uri)
300 {
301     segment_t *segment = (segment_t *)malloc(sizeof(segment_t));
302     if (segment == NULL)
303         return NULL;
304
305     segment->duration = duration; /* seconds */
306     segment->size = 0; /* bytes */
307     segment->sequence = 0;
308     segment->bandwidth = 0;
309     vlc_UrlParse(&segment->url, uri, 0);
310     segment->data = NULL;
311     vlc_array_append(hls->segments, segment);
312     vlc_mutex_init(&segment->lock);
313     return segment;
314 }
315
316 static void segment_Free(segment_t *segment)
317 {
318     vlc_mutex_destroy(&segment->lock);
319
320     vlc_UrlClean(&segment->url);
321     if (segment->data)
322         block_Release(segment->data);
323     free(segment);
324     segment = NULL;
325 }
326
327 static segment_t *segment_GetSegment(hls_stream_t *hls, const int wanted)
328 {
329     assert(hls);
330
331     int count = vlc_array_count(hls->segments);
332     if (count <= 0)
333         return NULL;
334     if ((wanted < 0) || (wanted >= count))
335         return NULL;
336     return (segment_t *) vlc_array_item_at_index(hls->segments, wanted);
337 }
338
339 static segment_t *segment_Find(hls_stream_t *hls, const int sequence)
340 {
341     assert(hls);
342
343     int count = vlc_array_count(hls->segments);
344     if (count <= 0) return NULL;
345     for (int n = 0; n < count; n++)
346     {
347         segment_t *segment = vlc_array_item_at_index(hls->segments, n);
348         if (segment == NULL) break;
349         if (segment->sequence == sequence)
350             return segment;
351     }
352     return NULL;
353 }
354
355 static int ChooseSegment(stream_t *s, const int current)
356 {
357     stream_sys_t *p_sys = (stream_sys_t *)s->p_sys;
358     hls_stream_t *hls = hls_Get(p_sys->hls_stream, current);
359     if (hls == NULL) return 0;
360
361     /* Choose a segment to start which is no closer than
362      * 3 times the target duration from the end of the playlist.
363      */
364     int wanted = 0;
365     int duration = 0;
366     int sequence = 0;
367     int count = vlc_array_count(hls->segments);
368     int i = p_sys->b_live ? count - 1 : 0;
369
370     while((i >= 0) && (i < count) && vlc_object_alive(s))
371     {
372         segment_t *segment = segment_GetSegment(hls, i);
373         assert(segment);
374
375         if (segment->duration > hls->duration)
376         {
377             msg_Err(s, "EXTINF:%d duration is larger than EXT-X-TARGETDURATION:%d",
378                     segment->duration, hls->duration);
379         }
380
381         duration += segment->duration;
382         if (duration >= 3 * hls->duration)
383         {
384             /* Start point found */
385             wanted = p_sys->b_live ? i : 0;
386             sequence = segment->sequence;
387             break;
388         }
389
390         if (p_sys->b_live)
391             i-- ;
392         else
393           i++;
394     }
395
396     msg_Info(s, "Choose segment %d/%d (sequence=%d)", wanted, count, sequence);
397     return wanted;
398 }
399
400 /* Parsing */
401 static char *parse_Attributes(const char *line, const char *attr)
402 {
403     char *p;
404     char *begin = (char *) line;
405     char *end = begin + strlen(line);
406
407     /* Find start of attributes */
408     if ((p = strchr(begin, ':' )) == NULL)
409         return NULL;
410
411     begin = p;
412     do
413     {
414         if (strncasecmp(begin, attr, strlen(attr)) == 0)
415         {
416             /* <attr>=<value>[,]* */
417             p = strchr(begin, ',');
418             begin += strlen(attr) + 1;
419             if (begin >= end)
420                 return NULL;
421             if (p == NULL) /* last attribute */
422                 return strndup(begin, end - begin);
423             /* copy till ',' */
424             return strndup(begin, p - begin);
425         }
426         begin++;
427     } while(begin < end);
428
429     return NULL;
430 }
431
432 static char *relative_URI(stream_t *s, const char *uri, const char *path)
433 {
434     stream_sys_t *p_sys = s->p_sys;
435
436     char *p = strchr(uri, ':');
437     if (p != NULL)
438         return NULL;
439
440     if (p_sys->m3u8.psz_path == NULL)
441         return NULL;
442
443     char *psz_path = strdup(p_sys->m3u8.psz_path);
444     if (psz_path == NULL) return NULL;
445     p = strrchr(psz_path, '/');
446     if (p) *p = '\0';
447
448     char *psz_uri = NULL;
449     if (p_sys->m3u8.psz_password || p_sys->m3u8.psz_username)
450     {
451         if (asprintf(&psz_uri, "%s://%s:%s@%s:%d%s/%s", p_sys->m3u8.psz_protocol,
452                      p_sys->m3u8.psz_username, p_sys->m3u8.psz_password,
453                      p_sys->m3u8.psz_host, p_sys->m3u8.i_port,
454                      path ? path : psz_path, uri) < 0)
455             goto fail;
456     }
457     else
458     {
459         if (asprintf(&psz_uri, "%s://%s:%d%s/%s", p_sys->m3u8.psz_protocol,
460                      p_sys->m3u8.psz_host, p_sys->m3u8.i_port,
461                      path ? path : psz_path, uri) < 0)
462            goto fail;
463     }
464     free(psz_path);
465     return psz_uri;
466
467 fail:
468     free(psz_path);
469     return NULL;
470 }
471
472 static char *ConstructUrl(vlc_url_t *url)
473 {
474     if ((url->psz_protocol == NULL) ||
475         (url->psz_path == NULL))
476         return NULL;
477
478     if (url->i_port <= 0)
479     {
480         if (strncmp(url->psz_protocol, "https", 5) == 0)
481             url->i_port = 443;
482         else
483             url->i_port = 80;
484     }
485
486     char *psz_url = NULL;
487     if (url->psz_password || url->psz_username)
488     {
489         if (asprintf(&psz_url, "%s://%s:%s@%s:%d%s",
490                      url->psz_protocol,
491                      url->psz_username, url->psz_password,
492                      url->psz_host, url->i_port, url->psz_path) < 0)
493             return NULL;
494     }
495     else
496     {
497         if (asprintf(&psz_url, "%s://%s:%d%s",
498                      url->psz_protocol,
499                      url->psz_host, url->i_port, url->psz_path) < 0)
500             return NULL;
501     }
502
503     return psz_url;
504 }
505
506 static int parse_SegmentInformation(hls_stream_t *hls, char *p_read, int *duration)
507 {
508     assert(hls);
509     assert(p_read);
510
511     /* strip of #EXTINF: */
512     char *p_next = NULL;
513     char *token = strtok_r(p_read, ":", &p_next);
514     if (token == NULL)
515         return VLC_EGENERIC;
516
517     /* read duration */
518     token = strtok_r(NULL, ",", &p_next);
519     if (token == NULL)
520         return VLC_EGENERIC;
521
522     int value;
523     if (hls->version < 3)
524     {
525        value = strtol(token, NULL, 10);
526        if (errno == ERANGE)
527        {
528            *duration = -1;
529            return VLC_EGENERIC;
530        }
531        *duration = value;
532     }
533     else
534     {
535         double d = strtod(token, (char **) NULL);
536         if (errno == ERANGE)
537         {
538             *duration = -1;
539             return VLC_EGENERIC;
540         }
541         if ((d) - ((int)d) >= 0.5)
542             value = ((int)d) + 1;
543         else
544             value = ((int)d);
545     }
546
547     /* Ignore the rest of the line */
548
549     return VLC_SUCCESS;
550 }
551
552 static int parse_AddSegment(stream_t *s, hls_stream_t *hls, const int duration, const char *uri)
553 {
554     assert(hls);
555     assert(uri);
556
557     /* Store segment information */
558     char *psz_path = NULL;
559     if (hls->url.psz_path != NULL)
560     {
561         psz_path = strdup(hls->url.psz_path);
562         if (psz_path == NULL)
563             return VLC_ENOMEM;
564         char *p = strrchr(psz_path, '/');
565         if (p) *p = '\0';
566     }
567     char *psz_uri = relative_URI(s, uri, psz_path);
568     free(psz_path);
569
570     vlc_mutex_lock(&hls->lock);
571     segment_t *segment = segment_New(hls, duration, psz_uri ? psz_uri : uri);
572     if (segment)
573         segment->sequence = hls->sequence + vlc_array_count(hls->segments) - 1;
574     vlc_mutex_unlock(&hls->lock);
575
576     free(psz_uri);
577     return segment ? VLC_SUCCESS : VLC_ENOMEM;
578 }
579
580 static int parse_TargetDuration(stream_t *s, hls_stream_t *hls, char *p_read)
581 {
582     assert(hls);
583
584     int duration = -1;
585     int ret = sscanf(p_read, "#EXT-X-TARGETDURATION:%d", &duration);
586     if (ret != 1)
587     {
588         msg_Err(s, "expected #EXT-X-TARGETDURATION:<s>");
589         return VLC_EGENERIC;
590     }
591
592     hls->duration = duration; /* seconds */
593     return VLC_SUCCESS;
594 }
595
596 static int parse_StreamInformation(stream_t *s, vlc_array_t **hls_stream,
597                                    hls_stream_t **hls, char *p_read, const char *uri)
598 {
599     int id;
600     uint64_t bw;
601     char *attr;
602
603     assert(*hls == NULL);
604
605     attr = parse_Attributes(p_read, "PROGRAM-ID");
606     if (attr == NULL)
607     {
608         msg_Err(s, "#EXT-X-STREAM-INF: expected PROGRAM-ID=<value>");
609         return VLC_EGENERIC;
610     }
611     id = atol(attr);
612     free(attr);
613
614     attr = parse_Attributes(p_read, "BANDWIDTH");
615     if (attr == NULL)
616     {
617         msg_Err(s, "#EXT-X-STREAM-INF: expected BANDWIDTH=<value>");
618         return VLC_EGENERIC;
619     }
620     bw = atoll(attr);
621     free(attr);
622
623     if (bw == 0)
624     {
625         msg_Err(s, "#EXT-X-STREAM-INF: bandwidth cannot be 0");
626         return VLC_EGENERIC;
627     }
628
629     msg_Info(s, "bandwidth adaptation detected (program-id=%d, bandwidth=%"PRIu64").", id, bw);
630
631     char *psz_uri = relative_URI(s, uri, NULL);
632
633     *hls = hls_New(*hls_stream, id, bw, psz_uri ? psz_uri : uri);
634
635     free(psz_uri);
636
637     return (*hls == NULL) ? VLC_ENOMEM : VLC_SUCCESS;
638 }
639
640 static int parse_MediaSequence(stream_t *s, hls_stream_t *hls, char *p_read)
641 {
642     assert(hls);
643
644     int sequence;
645     int ret = sscanf(p_read, "#EXT-X-MEDIA-SEQUENCE:%d", &sequence);
646     if (ret != 1)
647     {
648         msg_Err(s, "expected #EXT-X-MEDIA-SEQUENCE:<s>");
649         return VLC_EGENERIC;
650     }
651
652     if (hls->sequence > 0)
653         msg_Err(s, "EXT-X-MEDIA-SEQUENCE already present in playlist (new=%d, old=%d)",
654                     sequence, hls->sequence);
655
656     hls->sequence = sequence;
657     return VLC_SUCCESS;
658 }
659
660 static int parse_Key(stream_t *s, hls_stream_t *hls, char *p_read)
661 {
662     assert(hls);
663
664     /* #EXT-X-KEY:METHOD=<method>[,URI="<URI>"][,IV=<IV>] */
665     int err = VLC_SUCCESS;
666     char *attr = parse_Attributes(p_read, "METHOD");
667     if (attr == NULL)
668     {
669         msg_Err(s, "#EXT-X-KEY: expected METHOD=<value>");
670         return err;
671     }
672
673     if (strncasecmp(attr, "NONE", 4) == 0)
674     {
675
676         char *uri = parse_Attributes(p_read, "URI");
677         if (uri != NULL)
678         {
679             msg_Err(s, "#EXT-X-KEY: URI not expected");
680             err = VLC_EGENERIC;
681         }
682         free(uri);
683         /* IV is only supported in version 2 and above */
684         if (hls->version >= 2)
685         {
686             char *iv = parse_Attributes(p_read, "IV");
687             if (iv != NULL)
688             {
689                 msg_Err(s, "#EXT-X-KEY: IV not expected");
690                 err = VLC_EGENERIC;
691             }
692             free(iv);
693         }
694     }
695     else
696     {
697         msg_Warn(s, "playback of encrypted HTTP Live media is not supported.");
698         err = VLC_EGENERIC;
699     }
700     free(attr);
701     return err;
702 }
703
704 static int parse_ProgramDateTime(stream_t *s, hls_stream_t *hls, char *p_read)
705 {
706     VLC_UNUSED(hls);
707     msg_Dbg(s, "tag not supported: #EXT-X-PROGRAM-DATE-TIME %s", p_read);
708     return VLC_SUCCESS;
709 }
710
711 static int parse_AllowCache(stream_t *s, hls_stream_t *hls, char *p_read)
712 {
713     assert(hls);
714
715     char answer[4] = "\0";
716     int ret = sscanf(p_read, "#EXT-X-ALLOW-CACHE:%3s", answer);
717     if (ret != 1)
718     {
719         msg_Err(s, "#EXT-X-ALLOW-CACHE, ignoring ...");
720         return VLC_EGENERIC;
721     }
722
723     hls->b_cache = (strncmp(answer, "NO", 2) != 0);
724     return VLC_SUCCESS;
725 }
726
727 static int parse_Version(stream_t *s, hls_stream_t *hls, char *p_read)
728 {
729     assert(hls);
730
731     int version;
732     int ret = sscanf(p_read, "#EXT-X-VERSION:%d", &version);
733     if (ret != 1)
734     {
735         msg_Err(s, "#EXT-X-VERSION: no protocol version found, should be version 1.");
736         return VLC_EGENERIC;
737     }
738
739     /* Check version */
740     hls->version = version;
741     if (hls->version != 1)
742     {
743         msg_Err(s, "#EXT-X-VERSION should be version 1 iso %d", version);
744         return VLC_EGENERIC;
745     }
746     return VLC_SUCCESS;
747 }
748
749 static int parse_EndList(stream_t *s, hls_stream_t *hls)
750 {
751     assert(hls);
752
753     s->p_sys->b_live = false;
754     msg_Info(s, "video on demand (vod) mode");
755     return VLC_SUCCESS;
756 }
757
758 static int parse_Discontinuity(stream_t *s, hls_stream_t *hls, char *p_read)
759 {
760     assert(hls);
761
762     /* FIXME: Do we need to act on discontinuity ?? */
763     msg_Dbg(s, "#EXT-X-DISCONTINUITY %s", p_read);
764     return VLC_SUCCESS;
765 }
766
767 /* The http://tools.ietf.org/html/draft-pantos-http-live-streaming-04#page-8
768  * document defines the following new tags: EXT-X-TARGETDURATION,
769  * EXT-X-MEDIA-SEQUENCE, EXT-X-KEY, EXT-X-PROGRAM-DATE-TIME, EXT-X-
770  * ALLOW-CACHE, EXT-X-STREAM-INF, EXT-X-ENDLIST, EXT-X-DISCONTINUITY,
771  * and EXT-X-VERSION.
772  */
773 static int parse_M3U8(stream_t *s, vlc_array_t *streams, uint8_t *buffer, const ssize_t len)
774 {
775     stream_sys_t *p_sys = s->p_sys;
776     uint8_t *p_read, *p_begin, *p_end;
777
778     assert(streams);
779     assert(buffer);
780
781     msg_Dbg(s, "parse_M3U8\n%s", buffer);
782     p_begin = buffer;
783     p_end = p_begin + len;
784
785     char *line = ReadLine(p_begin, &p_read, p_end - p_begin);
786     if (line == NULL)
787         return VLC_ENOMEM;
788     p_begin = p_read;
789
790     if (strncmp(line, "#EXTM3U", 7) != 0)
791     {
792         msg_Err(s, "missing #EXTM3U tag .. aborting");
793         free(line);
794         return VLC_EGENERIC;
795     }
796
797     free(line);
798     line = NULL;
799
800     /* What is the version ? */
801     int version = 1;
802     uint8_t *p = (uint8_t *)strstr((const char *)buffer, "#EXT-X-VERSION:");
803     if (p != NULL)
804     {
805         uint8_t *tmp = NULL;
806         char *psz_version = ReadLine(p, &tmp, p_end - p);
807         if (psz_version == NULL)
808             return VLC_ENOMEM;
809         int ret = sscanf((const char*)psz_version, "#EXT-X-VERSION:%d", &version);
810         if (ret != 1)
811         {
812             msg_Warn(s, "#EXT-X-VERSION: no protocol version found, assuming version 1.");
813             version = 1;
814         }
815         free(psz_version);
816         p = NULL;
817     }
818
819     /* Is it a live stream ? */
820     p_sys->b_live = (strstr((const char *)buffer, "#EXT-X-ENDLIST") == NULL) ? true : false;
821
822     /* Is it a meta index file ? */
823     bool b_meta = (strstr((const char *)buffer, "#EXT-X-STREAM-INF") == NULL) ? false : true;
824
825     int err = VLC_SUCCESS;
826
827     if (b_meta)
828     {
829         msg_Info(s, "Meta playlist");
830
831         /* M3U8 Meta Index file */
832         do {
833             /* Next line */
834             line = ReadLine(p_begin, &p_read, p_end - p_begin);
835             if (line == NULL)
836                 break;
837             p_begin = p_read;
838
839             /* */
840             if (strncmp(line, "#EXT-X-STREAM-INF", 17) == 0)
841             {
842                 p_sys->b_meta = true;
843                 char *uri = ReadLine(p_begin, &p_read, p_end - p_begin);
844                 if (uri == NULL)
845                     err = VLC_ENOMEM;
846                 else
847                 {
848                     hls_stream_t *hls = NULL;
849                     err = parse_StreamInformation(s, &streams, &hls, line, uri);
850                     free(uri);
851
852                     /* Download playlist file from server */
853                     uint8_t *buf = NULL;
854                     ssize_t len = read_M3U8_from_url(s, &hls->url, &buf);
855                     if (len < 0)
856                         err = VLC_EGENERIC;
857                     else
858                     {
859                         /* Parse HLS m3u8 content. */
860                         err = parse_M3U8(s, streams, buf, len);
861                         free(buf);
862                     }
863
864                     if (hls)
865                     {
866                         hls->version = version;
867                         if (!p_sys->b_live)
868                             hls->size = hls_GetStreamSize(hls); /* Stream size (approximate) */
869                     }
870                 }
871                 p_begin = p_read;
872             }
873
874             free(line);
875             line = NULL;
876
877             if (p_begin >= p_end)
878                 break;
879
880         } while ((err == VLC_SUCCESS) && vlc_object_alive(s));
881
882     }
883     else
884     {
885         msg_Info(s, "%s Playlist HLS protocol version: %d", p_sys->b_live ? "Live": "VOD", version);
886
887         hls_stream_t *hls = NULL;
888         if (p_sys->b_meta)
889             hls = hls_GetLast(streams);
890         else
891         {
892             /* No Meta playlist used */
893             hls = hls_New(streams, 0, -1, NULL);
894             if (hls)
895             {
896                 /* Get TARGET-DURATION first */
897                 p = (uint8_t *)strstr((const char *)buffer, "#EXT-X-TARGETDURATION:");
898                 if (p)
899                 {
900                     uint8_t *p_rest = NULL;
901                     char *psz_duration = ReadLine(p, &p_rest,  p_end - p);
902                     if (psz_duration == NULL)
903                         return VLC_EGENERIC;
904                     err = parse_TargetDuration(s, hls, psz_duration);
905                     free(psz_duration);
906                     p = NULL;
907                 }
908
909                 /* Store version */
910                 hls->version = version;
911             }
912             else return VLC_ENOMEM;
913         }
914         assert(hls);
915
916         /* */
917         int segment_duration = -1;
918         do
919         {
920             /* Next line */
921             line = ReadLine(p_begin, &p_read, p_end - p_begin);
922             if (line == NULL)
923                 break;
924             p_begin = p_read;
925
926             if (strncmp(line, "#EXTINF", 7) == 0)
927                 err = parse_SegmentInformation(hls, line, &segment_duration);
928             else if (strncmp(line, "#EXT-X-TARGETDURATION", 21) == 0)
929                 err = parse_TargetDuration(s, hls, line);
930             else if (strncmp(line, "#EXT-X-MEDIA-SEQUENCE", 21) == 0)
931                 err = parse_MediaSequence(s, hls, line);
932             else if (strncmp(line, "#EXT-X-KEY", 10) == 0)
933                 err = parse_Key(s, hls, line);
934             else if (strncmp(line, "#EXT-X-PROGRAM-DATE-TIME", 24) == 0)
935                 err = parse_ProgramDateTime(s, hls, line);
936             else if (strncmp(line, "#EXT-X-ALLOW-CACHE", 18) == 0)
937                 err = parse_AllowCache(s, hls, line);
938             else if (strncmp(line, "#EXT-X-DISCONTINUITY", 20) == 0)
939                 err = parse_Discontinuity(s, hls, line);
940             else if (strncmp(line, "#EXT-X-VERSION", 14) == 0)
941                 err = parse_Version(s, hls, line);
942             else if (strncmp(line, "#EXT-X-ENDLIST", 14) == 0)
943                 err = parse_EndList(s, hls);
944             else if ((strncmp(line, "#", 1) != 0) && (*line != '\0') )
945             {
946                 err = parse_AddSegment(s, hls, segment_duration, line);
947                 segment_duration = -1; /* reset duration */
948             }
949
950             free(line);
951             line = NULL;
952
953             if (p_begin >= p_end)
954                 break;
955
956         } while ((err == VLC_SUCCESS) && vlc_object_alive(s));
957
958         free(line);
959     }
960
961     return err;
962 }
963
964 static int get_HTTPLiveMetaPlaylist(stream_t *s, vlc_array_t **streams)
965 {
966     stream_sys_t *p_sys = s->p_sys;
967     assert(*streams);
968
969     /* Download new playlist file from server */
970     uint8_t *buffer = NULL;
971     ssize_t len = read_M3U8_from_url(s, &p_sys->m3u8, &buffer);
972     if (len < 0)
973         return VLC_EGENERIC;
974
975     /* Parse HLS m3u8 content. */
976     int err = parse_M3U8(s, *streams, buffer, len);
977     free(buffer);
978
979     return err;
980 }
981
982 /* Reload playlist */
983 static int hls_UpdatePlaylist(stream_t *s, hls_stream_t *hls_new, hls_stream_t **hls)
984 {
985     int count = vlc_array_count(hls_new->segments);
986
987     msg_Info(s, "updating hls stream (program-id=%d, bandwidth=%"PRIu64") has %d segments",
988              hls_new->id, hls_new->bandwidth, count);
989     for (int n = 0; n < count; n++)
990     {
991         segment_t *p = segment_GetSegment(hls_new, n);
992         if (p == NULL) return VLC_EGENERIC;
993
994         vlc_mutex_lock(&(*hls)->lock);
995         segment_t *segment = segment_Find(*hls, p->sequence);
996         if (segment)
997         {
998             /* they should be the same */
999             if ((p->sequence != segment->sequence) ||
1000                 (p->duration != segment->duration) ||
1001                 (strcmp(p->url.psz_path, segment->url.psz_path) != 0))
1002             {
1003                 msg_Err(s, "existing segment found with different content - resetting");
1004                 msg_Err(s, "- sequence: new=%d, old=%d", p->sequence, segment->sequence);
1005                 msg_Err(s, "- duration: new=%d, old=%d", p->duration, segment->duration);
1006                 msg_Err(s, "- file: new=%s", p->url.psz_path);
1007                 msg_Err(s, "        old=%s", segment->url.psz_path);
1008
1009                 /* Resetting content */
1010                 segment->sequence = p->sequence;
1011                 segment->duration = p->duration;
1012                 vlc_UrlClean(&segment->url);
1013                 vlc_UrlParse(&segment->url, p->url.psz_buffer, 0);
1014                 segment_Free(p);
1015             }
1016         }
1017         else
1018         {
1019             int last = vlc_array_count((*hls)->segments) - 1;
1020             segment_t *l = segment_GetSegment(*hls, last);
1021             if (l == NULL) goto fail_and_unlock;
1022
1023             if ((l->sequence + 1) != p->sequence)
1024             {
1025                 msg_Err(s, "gap in sequence numbers found: new=%d expected %d",
1026                         p->sequence, l->sequence+1);
1027             }
1028             vlc_array_append((*hls)->segments, p);
1029             msg_Info(s, "- segment %d appended", p->sequence);
1030         }
1031         vlc_mutex_unlock(&(*hls)->lock);
1032     }
1033     return VLC_SUCCESS;
1034
1035 fail_and_unlock:
1036     vlc_mutex_unlock(&(*hls)->lock);
1037     return VLC_EGENERIC;
1038 }
1039
1040 static int hls_ReloadPlaylist(stream_t *s)
1041 {
1042     stream_sys_t *p_sys = s->p_sys;
1043
1044     vlc_array_t *hls_streams = vlc_array_new();
1045     if (hls_streams == NULL)
1046         return VLC_ENOMEM;
1047
1048     msg_Info(s, "Reloading HLS live meta playlist");
1049
1050     if (get_HTTPLiveMetaPlaylist(s, &hls_streams) != VLC_SUCCESS)
1051     {
1052         /* Free hls streams */
1053         for (int i = 0; i < vlc_array_count(hls_streams); i++)
1054         {
1055             hls_stream_t *hls;
1056             hls = (hls_stream_t *)vlc_array_item_at_index(hls_streams, i);
1057             if (hls) hls_Free(hls);
1058         }
1059         vlc_array_destroy(hls_streams);
1060
1061         msg_Err(s, "reloading playlist failed");
1062         return VLC_EGENERIC;
1063     }
1064
1065     /* merge playlists */
1066     int count = vlc_array_count(hls_streams);
1067     for (int n = 0; n < count; n++)
1068     {
1069         hls_stream_t *hls_new = hls_Get(hls_streams, n);
1070         if (hls_new == NULL)
1071             continue;
1072
1073         hls_stream_t *hls_old = hls_Find(p_sys->hls_stream, hls_new);
1074         if (hls_old == NULL)
1075         {   /* new hls stream - append */
1076             vlc_array_append(p_sys->hls_stream, hls_new);
1077             msg_Info(s, "new HLS stream appended (id=%d, bandwidth=%"PRIu64")",
1078                      hls_new->id, hls_new->bandwidth);
1079         }
1080         else
1081         {
1082             if ((hls_UpdatePlaylist(s, hls_new, &hls_old) == VLC_SUCCESS) &&
1083                     (s->p_sys->download.stream == n))
1084             {
1085                 /* wake up download thread */
1086                 vlc_mutex_lock(&s->p_sys->download.lock_wait);
1087                 vlc_cond_signal(&s->p_sys->download.wait);
1088                 vlc_mutex_unlock(&s->p_sys->download.lock_wait);
1089             }
1090             else
1091                 msg_Info(s, "failed updating HLS stream (id=%d, bandwidth=%"PRIu64")",
1092                              hls_new->id, hls_new->bandwidth);
1093         }
1094     }
1095
1096     vlc_array_destroy(hls_streams);
1097     return VLC_SUCCESS;
1098 }
1099
1100 /****************************************************************************
1101  * hls_Thread
1102  ****************************************************************************/
1103 static int BandwidthAdaptation(stream_t *s, int progid, uint64_t *bandwidth)
1104 {
1105     stream_sys_t *p_sys = s->p_sys;
1106     int candidate = -1;
1107     uint64_t bw = *bandwidth;
1108     uint64_t bw_candidate = 0;
1109
1110     int count = vlc_array_count(p_sys->hls_stream);
1111     for (int n = 0; n < count; n++)
1112     {
1113         /* Select best bandwidth match */
1114         hls_stream_t *hls = hls_Get(p_sys->hls_stream, n);
1115         if (hls == NULL) break;
1116
1117         /* only consider streams with the same PROGRAM-ID */
1118         if (hls->id == progid)
1119         {
1120             if ((bw >= hls->bandwidth) && (bw_candidate < hls->bandwidth))
1121             {
1122                 msg_Dbg(s, "candidate %d bandwidth (bits/s) %"PRIu64" >= %"PRIu64,
1123                          n, bw, hls->bandwidth); /* bits / s */
1124                 bw_candidate = hls->bandwidth;
1125                 candidate = n; /* possible candidate */
1126             }
1127         }
1128     }
1129     *bandwidth = bw_candidate;
1130     return candidate;
1131 }
1132
1133 static int Download(stream_t *s, hls_stream_t *hls, segment_t *segment, int *cur_stream)
1134 {
1135     stream_sys_t *p_sys = s->p_sys;
1136
1137     assert(hls);
1138     assert(segment);
1139
1140     vlc_mutex_lock(&segment->lock);
1141     if (segment->data != NULL)
1142     {
1143         /* Segment already downloaded */
1144         vlc_mutex_unlock(&segment->lock);
1145         return VLC_SUCCESS;
1146     }
1147
1148     /* sanity check - can we download this segment on time? */
1149     if ((p_sys->bandwidth > 0) && (hls->bandwidth > 0))
1150     {
1151         uint64_t size = (segment->duration * hls->bandwidth); /* bits */
1152         int estimated = (int)(size / p_sys->bandwidth);
1153         if (estimated > segment->duration)
1154         {
1155             msg_Warn(s,"downloading of segment %d takes %ds, which is longer than its playback (%ds)",
1156                         segment->sequence, estimated, segment->duration);
1157         }
1158     }
1159
1160     mtime_t start = mdate();
1161     if (hls_Download(s, segment) != VLC_SUCCESS)
1162     {
1163         vlc_mutex_unlock(&segment->lock);
1164         return VLC_EGENERIC;
1165     }
1166     mtime_t duration = mdate() - start;
1167
1168     vlc_mutex_unlock(&segment->lock);
1169
1170     msg_Info(s, "downloaded segment %d from stream %d",
1171                 segment->sequence, *cur_stream);
1172
1173     /* check for division by zero */
1174     double ms = (double)duration / 1000.0; /* ms */
1175     if (ms <= 0.0)
1176         return VLC_SUCCESS;
1177
1178     uint64_t bw = ((double)(segment->size * 8) / ms) * 1000; /* bits / s */
1179     p_sys->bandwidth = bw;
1180     if (p_sys->b_meta && (hls->bandwidth != bw))
1181     {
1182         int newstream = BandwidthAdaptation(s, hls->id, &bw);
1183
1184         /* FIXME: we need an average here */
1185         if ((newstream >= 0) && (newstream != *cur_stream))
1186         {
1187             msg_Info(s, "detected %s bandwidth (%"PRIu64") stream",
1188                      (bw >= hls->bandwidth) ? "faster" : "lower", bw);
1189             *cur_stream = newstream;
1190         }
1191     }
1192     return VLC_SUCCESS;
1193 }
1194
1195 static void* hls_Thread(void *p_this)
1196 {
1197     stream_t *s = (stream_t *)p_this;
1198     stream_sys_t *p_sys = s->p_sys;
1199
1200     int canc = vlc_savecancel();
1201
1202     while (vlc_object_alive(s))
1203     {
1204         hls_stream_t *hls = hls_Get(p_sys->hls_stream, p_sys->download.stream);
1205         assert(hls);
1206
1207         /* Sliding window (~60 seconds worth of movie) */
1208         vlc_mutex_lock(&hls->lock);
1209         int count = vlc_array_count(hls->segments);
1210         vlc_mutex_unlock(&hls->lock);
1211
1212         /* Is there a new segment to process? */
1213         if ((!p_sys->b_live && (p_sys->playback.segment < (count - 6))) ||
1214             (p_sys->download.segment >= count))
1215         {
1216             /* wait */
1217             vlc_mutex_lock(&p_sys->download.lock_wait);
1218             while (((p_sys->download.segment - p_sys->playback.segment > 6) ||
1219                     (p_sys->download.segment >= count)) &&
1220                    (p_sys->download.seek == -1))
1221             {
1222                 vlc_cond_wait(&p_sys->download.wait, &p_sys->download.lock_wait);
1223                 if (p_sys->b_live /*&& (mdate() >= p_sys->playlist.wakeup)*/)
1224                     break;
1225                 if (!vlc_object_alive(s))
1226                     break;
1227             }
1228             /* */
1229             if (p_sys->download.seek >= 0)
1230             {
1231                 p_sys->download.segment = p_sys->download.seek;
1232                 p_sys->download.seek = -1;
1233             }
1234             vlc_mutex_unlock(&p_sys->download.lock_wait);
1235         }
1236
1237         if (!vlc_object_alive(s)) break;
1238
1239         vlc_mutex_lock(&hls->lock);
1240         segment_t *segment = segment_GetSegment(hls, p_sys->download.segment);
1241         vlc_mutex_unlock(&hls->lock);
1242
1243         if ((segment != NULL) &&
1244             (Download(s, hls, segment, &p_sys->download.stream) != VLC_SUCCESS))
1245         {
1246             if (!vlc_object_alive(s)) break;
1247
1248             if (!p_sys->b_live)
1249             {
1250                 p_sys->b_error = true;
1251                 break;
1252             }
1253         }
1254
1255         /* download succeeded */
1256         /* determine next segment to download */
1257         vlc_mutex_lock(&p_sys->download.lock_wait);
1258         if (p_sys->download.seek >= 0)
1259         {
1260             p_sys->download.segment = p_sys->download.seek;
1261             p_sys->download.seek = -1;
1262         }
1263         else if (p_sys->download.segment < count)
1264             p_sys->download.segment++;
1265         vlc_cond_signal(&p_sys->download.wait);
1266         vlc_mutex_unlock(&p_sys->download.lock_wait);
1267     }
1268
1269     vlc_restorecancel(canc);
1270     return NULL;
1271 }
1272
1273 static void* hls_Reload(void *p_this)
1274 {
1275     stream_t *s = (stream_t *)p_this;
1276     stream_sys_t *p_sys = s->p_sys;
1277
1278     assert(p_sys->b_live);
1279
1280     int canc = vlc_savecancel();
1281
1282     double wait = 0.5;
1283     while (vlc_object_alive(s))
1284     {
1285         mtime_t now = mdate();
1286         if (now >= p_sys->playlist.wakeup)
1287         {
1288             /* reload the m3u8 */
1289             if (hls_ReloadPlaylist(s) != VLC_SUCCESS)
1290             {
1291                 /* No change in playlist, then backoff */
1292                 p_sys->playlist.tries++;
1293                 if (p_sys->playlist.tries == 1) wait = 0.5;
1294                 else if (p_sys->playlist.tries == 2) wait = 1;
1295                 else if (p_sys->playlist.tries >= 3) wait = 3;
1296             }
1297             else
1298             {
1299                 p_sys->playlist.tries = 0;
1300                 wait = 0.5;
1301             }
1302
1303             hls_stream_t *hls = hls_Get(p_sys->hls_stream, p_sys->download.stream);
1304             assert(hls);
1305
1306             /* determine next time to update playlist */
1307             p_sys->playlist.last = now;
1308             p_sys->playlist.wakeup = now + ((mtime_t)(hls->duration * wait)
1309                                                    * (mtime_t)1000000);
1310         }
1311
1312         mwait(p_sys->playlist.wakeup);
1313     }
1314
1315     vlc_restorecancel(canc);
1316     return NULL;
1317 }
1318
1319 static int Prefetch(stream_t *s, int *current)
1320 {
1321     stream_sys_t *p_sys = s->p_sys;
1322     int stream;
1323
1324     /* Try to pick best matching stream */;
1325 again:
1326     stream = *current;
1327
1328     hls_stream_t *hls = hls_Get(p_sys->hls_stream, *current);
1329     if (hls == NULL)
1330         return VLC_EGENERIC;
1331
1332     segment_t *segment = segment_GetSegment(hls, p_sys->download.segment);
1333     if (segment == NULL )
1334         return VLC_EGENERIC;
1335
1336     if (Download(s, hls, segment, current) != VLC_SUCCESS)
1337         return VLC_EGENERIC;
1338
1339     /* Found better bandwidth match, try again */
1340     if (*current != stream)
1341         goto again;
1342
1343     /* Download first 2 segments of this HLS stream */
1344     stream = *current;
1345     for (int i = 0; i < 2; i++)
1346     {
1347         segment_t *segment = segment_GetSegment(hls, p_sys->download.segment);
1348         if (segment == NULL )
1349             return VLC_EGENERIC;
1350
1351         if (segment->data)
1352         {
1353             p_sys->download.segment++;
1354             continue;
1355         }
1356
1357         if (Download(s, hls, segment, current) != VLC_SUCCESS)
1358             return VLC_EGENERIC;
1359
1360         p_sys->download.segment++;
1361
1362         /* adapt bandwidth? */
1363         if (*current != stream)
1364         {
1365             hls_stream_t *hls = hls_Get(p_sys->hls_stream, *current);
1366             if (hls == NULL)
1367                 return VLC_EGENERIC;
1368
1369              stream = *current;
1370         }
1371     }
1372
1373     return VLC_SUCCESS;
1374 }
1375
1376 /****************************************************************************
1377  *
1378  ****************************************************************************/
1379 static int hls_Download(stream_t *s, segment_t *segment)
1380 {
1381     assert(segment);
1382
1383     /* Construct URL */
1384     char *psz_url = ConstructUrl(&segment->url);
1385     if (psz_url == NULL)
1386            return VLC_ENOMEM;
1387
1388     stream_t *p_ts = stream_UrlNew(s, psz_url);
1389     free(psz_url);
1390     if (p_ts == NULL)
1391         return VLC_EGENERIC;
1392
1393     segment->size = stream_Size(p_ts);
1394     assert(segment->size > 0);
1395
1396     segment->data = block_Alloc(segment->size);
1397     if (segment->data == NULL)
1398     {
1399         stream_Delete(p_ts);
1400         return VLC_ENOMEM;
1401     }
1402
1403     assert(segment->data->i_buffer == segment->size);
1404
1405     ssize_t length = 0, curlen = 0;
1406     uint64_t size;
1407     do
1408     {
1409         size = stream_Size(p_ts);
1410         if (size > segment->size)
1411         {
1412             msg_Dbg(s, "size changed %"PRIu64, segment->size);
1413             segment->data = block_Realloc(segment->data, 0, size);
1414             if (segment->data == NULL)
1415             {
1416                 stream_Delete(p_ts);
1417                 return VLC_ENOMEM;
1418             }
1419             segment->size = size;
1420             assert(segment->data->i_buffer == segment->size);
1421         }
1422         length = stream_Read(p_ts, segment->data->p_buffer + curlen, segment->size - curlen);
1423         if (length <= 0)
1424             break;
1425         curlen += length;
1426     } while (vlc_object_alive(s));
1427
1428     stream_Delete(p_ts);
1429     return VLC_SUCCESS;
1430 }
1431
1432 /* Read M3U8 file */
1433 static ssize_t read_M3U8_from_stream(stream_t *s, uint8_t **buffer)
1434 {
1435     int64_t total_bytes = 0;
1436     int64_t total_allocated = 0;
1437     uint8_t *p = NULL;
1438
1439     while (1)
1440     {
1441         char buf[4096];
1442         int64_t bytes;
1443
1444         bytes = stream_Read(s, buf, sizeof(buf));
1445         if (bytes == 0)
1446             break;      /* EOF ? */
1447         else if (bytes < 0)
1448             return bytes;
1449
1450         if ( (total_bytes + bytes + 1) > total_allocated )
1451         {
1452             if (total_allocated)
1453                 total_allocated *= 2;
1454             else
1455                 total_allocated = __MIN(bytes+1, sizeof(buf));
1456
1457             p = realloc_or_free(p, total_allocated);
1458             if (p == NULL)
1459                 return VLC_ENOMEM;
1460         }
1461
1462         memcpy(p+total_bytes, buf, bytes);
1463         total_bytes += bytes;
1464     }
1465
1466     if (total_allocated == 0)
1467         return VLC_EGENERIC;
1468
1469     p[total_bytes] = '\0';
1470     *buffer = p;
1471
1472     return total_bytes;
1473 }
1474
1475 static ssize_t read_M3U8_from_url(stream_t *s, vlc_url_t *url, uint8_t **buffer)
1476 {
1477     assert(*buffer == NULL);
1478
1479     /* Construct URL */
1480     char *psz_url = ConstructUrl(url);
1481     if (psz_url == NULL)
1482            return VLC_ENOMEM;
1483
1484     stream_t *p_m3u8 = stream_UrlNew(s, psz_url);
1485     free(psz_url);
1486     if (p_m3u8 == NULL)
1487         return VLC_EGENERIC;
1488
1489     ssize_t size = read_M3U8_from_stream(p_m3u8, buffer);
1490     stream_Delete(p_m3u8);
1491
1492     return size;
1493 }
1494
1495 static char *ReadLine(uint8_t *buffer, uint8_t **pos, const size_t len)
1496 {
1497     assert(buffer);
1498
1499     char *line = NULL;
1500     uint8_t *begin = buffer;
1501     uint8_t *p = begin;
1502     uint8_t *end = p + len;
1503
1504     while (p < end)
1505     {
1506         if ((*p == '\n') || (*p == '\0'))
1507             break;
1508         p++;
1509     }
1510
1511     /* copy line excluding \n or \0 */
1512     line = strndup((char *)begin, p - begin);
1513
1514     if (*p == '\0')
1515         *pos = end;
1516     else
1517     {
1518         /* next pass start after \n */
1519         p++;
1520         *pos = p;
1521     }
1522
1523     return line;
1524 }
1525
1526 /****************************************************************************
1527  * Open
1528  ****************************************************************************/
1529 static int Open(vlc_object_t *p_this)
1530 {
1531     stream_t *s = (stream_t*)p_this;
1532     stream_sys_t *p_sys;
1533
1534     if (!isHTTPLiveStreaming(s))
1535         return VLC_EGENERIC;
1536
1537     msg_Info(p_this, "HTTP Live Streaming (%s)", s->psz_path);
1538
1539     /* */
1540     s->p_sys = p_sys = calloc(1, sizeof(*p_sys));
1541     if (p_sys == NULL)
1542         return VLC_ENOMEM;
1543
1544     char *psz_uri = NULL;
1545     if (asprintf(&psz_uri,"%s://%s", s->psz_access, s->psz_path) < 0)
1546     {
1547         free(p_sys);
1548         return VLC_ENOMEM;
1549     }
1550     vlc_UrlParse(&p_sys->m3u8, psz_uri, 0);
1551     free(psz_uri);
1552
1553     p_sys->bandwidth = -1;
1554     p_sys->b_live = true;
1555     p_sys->b_meta = false;
1556     p_sys->b_error = false;
1557
1558     p_sys->hls_stream = vlc_array_new();
1559     if (p_sys->hls_stream == NULL)
1560     {
1561         vlc_UrlClean(&p_sys->m3u8);
1562         free(p_sys);
1563         return VLC_ENOMEM;
1564     }
1565
1566     /* */
1567     s->pf_read = Read;
1568     s->pf_peek = Peek;
1569     s->pf_control = Control;
1570
1571     /* Parse HLS m3u8 content. */
1572     uint8_t *buffer = NULL;
1573     ssize_t len = read_M3U8_from_stream(s->p_source, &buffer);
1574     if (len < 0)
1575         goto fail;
1576     if (parse_M3U8(s, p_sys->hls_stream, buffer, len) != VLC_SUCCESS)
1577     {
1578         free(buffer);
1579         goto fail;
1580     }
1581     free(buffer);
1582
1583     /* Choose first HLS stream to start with */
1584     int current = p_sys->playback.stream = 0;
1585     p_sys->playback.segment = p_sys->download.segment = ChooseSegment(s, current);
1586
1587     if (p_sys->b_live && (p_sys->playback.segment < 0))
1588     {
1589         msg_Warn(s, "less data than 3 times 'target duration' available for live playback, playback may stall");
1590     }
1591
1592     if (Prefetch(s, &current) != VLC_SUCCESS)
1593     {
1594         msg_Err(s, "fetching first segment failed.");
1595         goto fail;
1596     }
1597
1598
1599     p_sys->download.stream = current;
1600     p_sys->playback.stream = current;
1601     p_sys->download.seek = -1;
1602
1603     vlc_mutex_init(&p_sys->download.lock_wait);
1604     vlc_cond_init(&p_sys->download.wait);
1605
1606     /* Initialize HLS live stream */
1607     if (p_sys->b_live)
1608     {
1609         hls_stream_t *hls = hls_Get(p_sys->hls_stream, current);
1610         p_sys->playlist.last = mdate();
1611         p_sys->playlist.wakeup = p_sys->playlist.last +
1612                 ((mtime_t)hls->duration * UINT64_C(1000000));
1613
1614         if (vlc_clone(&p_sys->reload, hls_Reload, s, VLC_THREAD_PRIORITY_LOW))
1615         {
1616             goto fail_thread;
1617         }
1618     }
1619
1620     if (vlc_clone(&p_sys->thread, hls_Thread, s, VLC_THREAD_PRIORITY_INPUT))
1621     {
1622         if (p_sys->b_live)
1623             vlc_join(p_sys->reload, NULL);
1624         goto fail_thread;
1625     }
1626
1627     return VLC_SUCCESS;
1628
1629 fail_thread:
1630     vlc_mutex_destroy(&p_sys->download.lock_wait);
1631     vlc_cond_destroy(&p_sys->download.wait);
1632
1633 fail:
1634     /* Free hls streams */
1635     for (int i = 0; i < vlc_array_count(p_sys->hls_stream); i++)
1636     {
1637         hls_stream_t *hls;
1638         hls = (hls_stream_t *)vlc_array_item_at_index(p_sys->hls_stream, i);
1639         if (hls) hls_Free(hls);
1640     }
1641     vlc_array_destroy(p_sys->hls_stream);
1642
1643     /* */
1644     vlc_UrlClean(&p_sys->m3u8);
1645     free(p_sys);
1646     return VLC_EGENERIC;
1647 }
1648
1649 /****************************************************************************
1650  * Close
1651  ****************************************************************************/
1652 static void Close(vlc_object_t *p_this)
1653 {
1654     stream_t *s = (stream_t*)p_this;
1655     stream_sys_t *p_sys = s->p_sys;
1656
1657     assert(p_sys->hls_stream);
1658
1659     /* */
1660     vlc_mutex_lock(&p_sys->download.lock_wait);
1661     vlc_cond_signal(&p_sys->download.wait);
1662     vlc_mutex_unlock(&p_sys->download.lock_wait);
1663
1664     /* */
1665     if (p_sys->b_live)
1666         vlc_join(p_sys->reload, NULL);
1667     vlc_join(p_sys->thread, NULL);
1668     vlc_mutex_destroy(&p_sys->download.lock_wait);
1669     vlc_cond_destroy(&p_sys->download.wait);
1670
1671     /* Free hls streams */
1672     for (int i = 0; i < vlc_array_count(p_sys->hls_stream); i++)
1673     {
1674         hls_stream_t *hls;
1675         hls = (hls_stream_t *)vlc_array_item_at_index(p_sys->hls_stream, i);
1676         if (hls) hls_Free(hls);
1677     }
1678     vlc_array_destroy(p_sys->hls_stream);
1679
1680     /* */
1681     vlc_UrlClean(&p_sys->m3u8);
1682     if (p_sys->peeked)
1683         block_Release (p_sys->peeked);
1684     free(p_sys);
1685 }
1686
1687 /****************************************************************************
1688  * Stream filters functions
1689  ****************************************************************************/
1690 static segment_t *GetSegment(stream_t *s)
1691 {
1692     stream_sys_t *p_sys = s->p_sys;
1693     segment_t *segment = NULL;
1694
1695     /* Is this segment of the current HLS stream ready? */
1696     hls_stream_t *hls = hls_Get(p_sys->hls_stream, p_sys->playback.stream);
1697     if (hls != NULL)
1698     {
1699         vlc_mutex_lock(&hls->lock);
1700         segment = segment_GetSegment(hls, p_sys->playback.segment);
1701         if (segment != NULL)
1702         {
1703             /* This segment is ready? */
1704             if (segment->data != NULL)
1705             {
1706                 p_sys->b_cache = hls->b_cache;
1707                 vlc_mutex_unlock(&hls->lock);
1708                 goto check;
1709             }
1710         }
1711         vlc_mutex_unlock(&hls->lock);
1712     }
1713
1714     /* Was the HLS stream changed to another bitrate? */
1715     int i_stream = 0;
1716     segment = NULL;
1717     while(vlc_object_alive(s))
1718     {
1719         /* Is the next segment ready */
1720         hls_stream_t *hls = hls_Get(p_sys->hls_stream, i_stream);
1721         if (hls == NULL)
1722             return NULL;
1723
1724         vlc_mutex_lock(&hls->lock);
1725         segment = segment_GetSegment(hls, p_sys->playback.segment);
1726         if (segment == NULL)
1727         {
1728             vlc_mutex_unlock(&hls->lock);
1729             break;
1730         }
1731
1732         vlc_mutex_lock(&p_sys->download.lock_wait);
1733         int i_segment = p_sys->download.segment;
1734         vlc_mutex_unlock(&p_sys->download.lock_wait);
1735
1736         /* This segment is ready? */
1737         if ((segment->data != NULL) &&
1738             (p_sys->playback.segment < i_segment))
1739         {
1740             p_sys->playback.stream = i_stream;
1741             p_sys->b_cache = hls->b_cache;
1742             vlc_mutex_unlock(&hls->lock);
1743             goto check;
1744         }
1745         vlc_mutex_unlock(&hls->lock);
1746
1747         if (!p_sys->b_meta)
1748             break;
1749
1750         /* Was the stream changed to another bitrate? */
1751         i_stream++;
1752         if (i_stream >= vlc_array_count(p_sys->hls_stream))
1753             break;
1754     }
1755     /* */
1756     return NULL;
1757
1758 check:
1759     /* sanity check */
1760     if (segment->data->i_buffer == 0)
1761     {
1762         vlc_mutex_lock(&hls->lock);
1763         int count = vlc_array_count(hls->segments);
1764         vlc_mutex_unlock(&hls->lock);
1765
1766         if ((p_sys->download.segment - p_sys->playback.segment == 0) &&
1767             ((count != p_sys->download.segment) || p_sys->b_live))
1768             msg_Err(s, "playback will stall");
1769         else if ((p_sys->download.segment - p_sys->playback.segment < 3) &&
1770                  ((count != p_sys->download.segment) || p_sys->b_live))
1771             msg_Warn(s, "playback in danger of stalling");
1772     }
1773     return segment;
1774 }
1775
1776 static ssize_t hls_Read(stream_t *s, uint8_t *p_read, unsigned int i_read)
1777 {
1778     stream_sys_t *p_sys = s->p_sys;
1779     ssize_t copied = 0;
1780
1781     do
1782     {
1783         /* Determine next segment to read. If this is a meta playlist and
1784          * bandwidth conditions changed, then the stream might have switched
1785          * to another bandwidth. */
1786         segment_t *segment = GetSegment(s);
1787         if (segment == NULL)
1788             break;
1789
1790         vlc_mutex_lock(&segment->lock);
1791         if (segment->data->i_buffer == 0)
1792         {
1793             if (!p_sys->b_cache || p_sys->b_live)
1794             {
1795                 block_Release(segment->data);
1796                 segment->data = NULL;
1797             }
1798             else
1799             {   /* reset playback pointer to start of buffer */
1800                 uint64_t size = segment->size - segment->data->i_buffer;
1801                 if (size > 0)
1802                 {
1803                     segment->data->i_buffer += size;
1804                     segment->data->p_buffer -= size;
1805                 }
1806             }
1807             p_sys->playback.segment++;
1808             vlc_mutex_unlock(&segment->lock);
1809
1810             /* signal download thread */
1811             vlc_mutex_lock(&p_sys->download.lock_wait);
1812             vlc_cond_signal(&p_sys->download.wait);
1813             vlc_mutex_unlock(&p_sys->download.lock_wait);
1814             continue;
1815         }
1816
1817         if (segment->size == segment->data->i_buffer)
1818             msg_Info(s, "playing segment %d from stream %d",
1819                      segment->sequence, p_sys->playback.stream);
1820
1821         ssize_t len = -1;
1822         if (i_read <= segment->data->i_buffer)
1823             len = i_read;
1824         else if (i_read > segment->data->i_buffer)
1825             len = segment->data->i_buffer;
1826
1827         if (len > 0)
1828         {
1829             memcpy(p_read + copied, segment->data->p_buffer, len);
1830             segment->data->i_buffer -= len;
1831             segment->data->p_buffer += len;
1832             copied += len;
1833             i_read -= len;
1834         }
1835         vlc_mutex_unlock(&segment->lock);
1836
1837     } while ((i_read > 0) && vlc_object_alive(s));
1838
1839     return copied;
1840 }
1841
1842 static int Read(stream_t *s, void *buffer, unsigned int i_read)
1843 {
1844     stream_sys_t *p_sys = s->p_sys;
1845     ssize_t length = 0;
1846
1847     assert(p_sys->hls_stream);
1848
1849     if (p_sys->b_error)
1850         return 0;
1851
1852     if (buffer == NULL)
1853     {
1854         /* caller skips data, get big enough buffer */
1855         msg_Warn(s, "buffer is NULL (allocate %d)", i_read);
1856         buffer = calloc(1, i_read);
1857         if (buffer == NULL)
1858             return 0; /* NO MEMORY left*/
1859     }
1860
1861     length = hls_Read(s, (uint8_t*) buffer, i_read);
1862     if (length < 0)
1863         return 0;
1864
1865     p_sys->playback.offset += length;
1866     return length;
1867 }
1868
1869 static int Peek(stream_t *s, const uint8_t **pp_peek, unsigned int i_peek)
1870 {
1871     stream_sys_t *p_sys = s->p_sys;
1872     segment_t *segment;
1873     unsigned int len = i_peek;
1874
1875     segment = GetSegment(s);
1876     if (segment == NULL)
1877     {
1878         msg_Err(s, "segment %d should have been available (stream %d)",
1879                 p_sys->playback.segment, p_sys->playback.stream);
1880         return 0; /* eof? */
1881     }
1882
1883     vlc_mutex_lock(&segment->lock);
1884
1885     size_t i_buff = segment->data->i_buffer;
1886     uint8_t *p_buff = segment->data->p_buffer;
1887
1888     if (i_peek < i_buff)
1889     {
1890         *pp_peek = p_buff;
1891         vlc_mutex_unlock(&segment->lock);
1892         return i_peek;
1893     }
1894
1895     else /* This will seldom be run */
1896     {
1897         /* remember segment to read */
1898         int peek_segment = p_sys->playback.segment;
1899         size_t curlen = 0;
1900         segment_t *nsegment;
1901         p_sys->playback.segment++;
1902         block_t *peeked = p_sys->peeked;
1903
1904         if (peeked == NULL)
1905             peeked = block_Alloc (i_peek);
1906         else if (peeked->i_buffer < i_peek)
1907             peeked = block_Realloc (peeked, 0, i_peek);
1908         if (peeked == NULL)
1909             return 0;
1910
1911         memcpy(peeked->p_buffer, p_buff, i_buff);
1912         curlen = i_buff;
1913         len -= i_buff;
1914         vlc_mutex_unlock(&segment->lock);
1915
1916         i_buff = peeked->i_buffer;
1917         p_buff = peeked->p_buffer;
1918         *pp_peek = p_buff;
1919
1920         while ((curlen < i_peek) && vlc_object_alive(s))
1921         {
1922             nsegment = GetSegment(s);
1923             if (nsegment == NULL)
1924             {
1925                 msg_Err(s, "segment %d should have been available (stream %d)",
1926                         p_sys->playback.segment, p_sys->playback.stream);
1927                 /* restore segment to read */
1928                 p_sys->playback.segment = peek_segment;
1929                 return curlen; /* eof? */
1930             }
1931
1932             vlc_mutex_lock(&nsegment->lock);
1933
1934             if (len < nsegment->data->i_buffer)
1935             {
1936                 memcpy(p_buff + curlen, nsegment->data->p_buffer, len);
1937                 curlen += len;
1938             }
1939             else
1940             {
1941                 size_t i_nbuff = nsegment->data->i_buffer;
1942                 memcpy(p_buff + curlen, nsegment->data->p_buffer, i_nbuff);
1943                 curlen += i_nbuff;
1944                 len -= i_nbuff;
1945
1946                 p_sys->playback.segment++;
1947             }
1948
1949             vlc_mutex_unlock(&nsegment->lock);
1950         }
1951
1952         /* restore segment to read */
1953         p_sys->playback.segment = peek_segment;
1954         return curlen;
1955     }
1956 }
1957
1958 static bool hls_MaySeek(stream_t *s)
1959 {
1960     stream_sys_t *p_sys = s->p_sys;
1961
1962     if (p_sys->hls_stream == NULL)
1963         return false;
1964
1965     hls_stream_t *hls = hls_Get(p_sys->hls_stream, p_sys->playback.stream);
1966     if (hls == NULL) return false;
1967
1968     if (p_sys->b_live)
1969     {
1970         vlc_mutex_lock(&hls->lock);
1971         int count = vlc_array_count(hls->segments);
1972         vlc_mutex_unlock(&hls->lock);
1973
1974         vlc_mutex_lock(&p_sys->download.lock_wait);
1975         bool may_seek = (p_sys->download.segment < (count - 2));
1976         vlc_mutex_unlock(&p_sys->download.lock_wait);
1977         return may_seek;
1978     }
1979     return true;
1980 }
1981
1982 static uint64_t GetStreamSize(stream_t *s)
1983 {
1984     stream_sys_t *p_sys = s->p_sys;
1985
1986     if (p_sys->b_live)
1987         return 0;
1988
1989     hls_stream_t *hls = hls_Get(p_sys->hls_stream, p_sys->playback.stream);
1990     if (hls == NULL) return 0;
1991
1992     vlc_mutex_lock(&hls->lock);
1993     uint64_t size = hls->size;
1994     vlc_mutex_unlock(&hls->lock);
1995
1996     return size;
1997 }
1998
1999 static int segment_Seek(stream_t *s, const uint64_t pos)
2000 {
2001     stream_sys_t *p_sys = s->p_sys;
2002
2003     hls_stream_t *hls = hls_Get(p_sys->hls_stream, p_sys->playback.stream);
2004     if (hls == NULL)
2005         return VLC_EGENERIC;
2006
2007     vlc_mutex_lock(&hls->lock);
2008
2009     bool b_found = false;
2010     uint64_t length = 0;
2011     uint64_t size = hls->size;
2012     int count = vlc_array_count(hls->segments);
2013
2014     for (int n = 0; n < count; n++)
2015     {
2016         segment_t *segment = vlc_array_item_at_index(hls->segments, n);
2017         if (segment == NULL)
2018         {
2019             vlc_mutex_unlock(&hls->lock);
2020             return VLC_EGENERIC;
2021         }
2022
2023         vlc_mutex_lock(&segment->lock);
2024         length += segment->duration * (hls->bandwidth/8);
2025         vlc_mutex_unlock(&segment->lock);
2026
2027         if (!b_found && (pos <= length))
2028         {
2029             if (count - n >= 3)
2030             {
2031                 p_sys->playback.segment = n;
2032                 b_found = true;
2033                 break;
2034             }
2035             /* Do not search in last 3 segments */
2036             vlc_mutex_unlock(&hls->lock);
2037             return VLC_EGENERIC;
2038         }
2039     }
2040
2041     /* */
2042     if (!b_found && (pos >= size))
2043     {
2044         p_sys->playback.segment = count - 1;
2045         b_found = true;
2046     }
2047
2048     /* */
2049     if (b_found)
2050     {
2051         /* restore segment to start position */
2052         segment_t *segment = segment_GetSegment(hls, p_sys->playback.segment);
2053         if (segment == NULL)
2054         {
2055             vlc_mutex_unlock(&hls->lock);
2056             return VLC_EGENERIC;
2057         }
2058
2059         vlc_mutex_lock(&segment->lock);
2060         if (segment->data)
2061         {
2062             uint64_t size = segment->size -segment->data->i_buffer;
2063             if (size > 0)
2064             {
2065                 segment->data->i_buffer += size;
2066                 segment->data->p_buffer -= size;
2067             }
2068         }
2069         vlc_mutex_unlock(&segment->lock);
2070
2071         /* start download at current playback segment */
2072         vlc_mutex_unlock(&hls->lock);
2073
2074         /* Wake up download thread */
2075         vlc_mutex_lock(&p_sys->download.lock_wait);
2076         p_sys->download.seek = p_sys->playback.segment;
2077         vlc_cond_signal(&p_sys->download.wait);
2078         vlc_mutex_unlock(&p_sys->download.lock_wait);
2079
2080         /* Wait for download to be finished */
2081         vlc_mutex_lock(&p_sys->download.lock_wait);
2082         msg_Info(s, "seek to segment %d", p_sys->playback.segment);
2083         while (((p_sys->download.seek != -1) ||
2084                 (p_sys->download.segment - p_sys->playback.segment < 3)) &&
2085                 (p_sys->download.segment < (count - 6)))
2086         {
2087             vlc_cond_wait(&p_sys->download.wait, &p_sys->download.lock_wait);
2088             if (!vlc_object_alive(s) || s->b_error) break;
2089         }
2090         vlc_mutex_unlock(&p_sys->download.lock_wait);
2091
2092         return VLC_SUCCESS;
2093     }
2094     vlc_mutex_unlock(&hls->lock);
2095
2096     return b_found ? VLC_SUCCESS : VLC_EGENERIC;
2097 }
2098
2099 static int Control(stream_t *s, int i_query, va_list args)
2100 {
2101     stream_sys_t *p_sys = s->p_sys;
2102
2103     switch (i_query)
2104     {
2105         case STREAM_CAN_SEEK:
2106         case STREAM_CAN_FASTSEEK:
2107             *(va_arg (args, bool *)) = hls_MaySeek(s);
2108             break;
2109         case STREAM_GET_POSITION:
2110             *(va_arg (args, uint64_t *)) = p_sys->playback.offset;
2111             break;
2112         case STREAM_SET_POSITION:
2113             if (hls_MaySeek(s))
2114             {
2115                 uint64_t pos = (uint64_t)va_arg(args, uint64_t);
2116                 if (segment_Seek(s, pos) == VLC_SUCCESS)
2117                 {
2118                     p_sys->playback.offset = pos;
2119                     break;
2120                 }
2121             }
2122             return VLC_EGENERIC;
2123         case STREAM_GET_SIZE:
2124             *(va_arg (args, uint64_t *)) = GetStreamSize(s);
2125             break;
2126         default:
2127             return VLC_EGENERIC;
2128     }
2129     return VLC_SUCCESS;
2130 }