#endif
#include <limits.h>
+#include <errno.h>
#include <vlc_common.h>
#include <vlc_plugin.h>
}
/* HTTP Live Streaming */
-static hls_stream_t *hls_New(vlc_array_t *hls_stream, int id, uint64_t bw, char *uri)
+static hls_stream_t *hls_New(vlc_array_t *hls_stream, const int id, const uint64_t bw, const char *uri)
{
hls_stream_t *hls = (hls_stream_t *)malloc(sizeof(hls_stream_t));
if (hls == NULL) return NULL;
hls = NULL;
}
-static hls_stream_t *hls_Get(vlc_array_t *hls_stream, int wanted)
+static hls_stream_t *hls_Get(vlc_array_t *hls_stream, const int wanted)
{
int count = vlc_array_count(hls_stream);
if (count <= 0)
}
/* Segment */
-static segment_t *segment_New(hls_stream_t* hls, int duration, char *uri)
+static segment_t *segment_New(hls_stream_t* hls, const int duration, const char *uri)
{
segment_t *segment = (segment_t *)malloc(sizeof(segment_t));
if (segment == NULL)
segment = NULL;
}
-static segment_t *segment_GetSegment(hls_stream_t *hls, int wanted)
+static segment_t *segment_GetSegment(hls_stream_t *hls, const int wanted)
{
assert(hls);
return (segment_t *) vlc_array_item_at_index(hls->segments, wanted);
}
-static segment_t *segment_Find(hls_stream_t *hls, int sequence)
+static segment_t *segment_Find(hls_stream_t *hls, const int sequence)
{
assert(hls);
return NULL;
}
-static int ChooseSegment(stream_t *s, int current)
+static int ChooseSegment(stream_t *s, const int current)
{
stream_sys_t *p_sys = (stream_sys_t *)s->p_sys;
hls_stream_t *hls = hls_Get(p_sys->hls_stream, current);
return psz_url;
}
-static int parse_SegmentInformation(stream_t *s, hls_stream_t *hls, char *p_read, char *uri)
+static int parse_SegmentInformation(hls_stream_t *hls, char *p_read, int *duration)
{
assert(hls);
assert(p_read);
token = strtok_r(NULL, ",", &p_next);
if (token == NULL)
return VLC_EGENERIC;
- int duration = atoi(token);
+
+ int value;
+ if (hls->version < 3)
+ {
+ value = strtol(token, NULL, 10);
+ if (errno == ERANGE)
+ {
+ *duration = -1;
+ return VLC_EGENERIC;
+ }
+ *duration = value;
+ }
+ else
+ {
+ double d = strtod(token, (char **) NULL);
+ if (errno == ERANGE)
+ {
+ *duration = -1;
+ return VLC_EGENERIC;
+ }
+ if ((d) - ((int)d) >= 0.5)
+ value = ((int)d) + 1;
+ else
+ value = ((int)d);
+ }
/* Ignore the rest of the line */
+ return VLC_SUCCESS;
+}
+
+static int parse_AddSegment(stream_t *s, hls_stream_t *hls, const int duration, const char *uri)
+{
+ assert(hls);
+ assert(uri);
+
/* Store segment information */
char *psz_path = NULL;
if (hls->url.psz_path != NULL)
}
static int parse_StreamInformation(stream_t *s, vlc_array_t **hls_stream,
- hls_stream_t **hls, char *p_read, char *uri)
+ hls_stream_t **hls, char *p_read, const char *uri)
{
int id;
uint64_t bw;
* ALLOW-CACHE, EXT-X-STREAM-INF, EXT-X-ENDLIST, EXT-X-DISCONTINUITY,
* and EXT-X-VERSION.
*/
-static int parse_M3U8(stream_t *s, vlc_array_t *streams, uint8_t *buffer, ssize_t len)
+static int parse_M3U8(stream_t *s, vlc_array_t *streams, uint8_t *buffer, const ssize_t len)
{
stream_sys_t *p_sys = s->p_sys;
uint8_t *p_read, *p_begin, *p_end;
assert(hls);
/* */
+ int segment_duration = -1;
do
{
/* Next line */
p_begin = p_read;
if (strncmp(line, "#EXTINF", 7) == 0)
- {
- char *uri = ReadLine(p_begin, &p_read, p_end - p_begin);
- if (uri == NULL)
- err = VLC_EGENERIC;
- else
- {
- err = parse_SegmentInformation(s, hls, line, uri);
- free(uri);
- }
- p_begin = p_read;
- }
+ err = parse_SegmentInformation(hls, line, &segment_duration);
else if (strncmp(line, "#EXT-X-TARGETDURATION", 21) == 0)
err = parse_TargetDuration(s, hls, line);
else if (strncmp(line, "#EXT-X-MEDIA-SEQUENCE", 21) == 0)
err = parse_Version(s, hls, line);
else if (strncmp(line, "#EXT-X-ENDLIST", 14) == 0)
err = parse_EndList(s, hls);
+ else if (strncmp(line, "#", 1) != 0)
+ {
+ err = parse_AddSegment(s, hls, segment_duration, line);
+ segment_duration = -1; /* reset duration */
+ }
free(line);
line = NULL;
return size;
}
-static char *ReadLine(uint8_t *buffer, uint8_t **pos, size_t len)
+static char *ReadLine(uint8_t *buffer, uint8_t **pos, const size_t len)
{
assert(buffer);
return size;
}
-static int segment_Seek(stream_t *s, uint64_t pos)
+static int segment_Seek(stream_t *s, const uint64_t pos)
{
stream_sys_t *p_sys = s->p_sys;