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