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