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