Commit bb9def29 authored by Jean-Paul Saman's avatar Jean-Paul Saman

stream_filter: httplive.c: parse attributes in #EXT-<tag> tags.

Implement an attribute parsing function that does not depend on fixed position of attributes in a HTTP live streaming m3u8 file.
The function returns a copy of the attributes value. Do not forget to free the copy otherwise it will result in a memory leak.
parent 6ba5cde7
......@@ -76,7 +76,7 @@ typedef struct hls_stream_s
{
int id; /* program id */
uint64_t bandwidth; /* bandwidth usage of segments (kbps)*/
int version;
int version; /* protocol version should be 1 */
int sequence; /* media sequence number */
uint64_t duration; /* maximum duration per segment (ms) */
int segment; /* current segment downloading */
......@@ -525,6 +525,37 @@ static inline void FreeAllSegments(hls_stream_t *hls)
}
/* Parsing */
static char *parse_Attributes(const char *line, const char *attr)
{
char *p;
char *begin = (char *) line;
char *end = begin + strlen(line);
/* Find start of attributes */
if ((p = strchr(begin, ':' )) == NULL)
return NULL;
begin = p;
do
{
if (strncasecmp(begin, attr, strlen(attr)) == 0)
{
/* <attr>=<value>[,]* */
p = strchr(begin, ',');
begin += strlen(attr) + 1;
if (begin >= end)
return NULL;
if (p == NULL) /* last attribute */
return strndup(begin, end - begin);
/* copy till ',' */
return strndup(begin, p - begin);
}
begin++;
} while(begin < end);
return NULL;
}
static void parse_SegmentInformation(stream_t *s, hls_stream_t *hls, char *p_read, char *uri)
{
stream_sys_t *p_sys = s->p_sys;
......@@ -535,7 +566,7 @@ static void parse_SegmentInformation(stream_t *s, hls_stream_t *hls, char *p_rea
int ret = sscanf(p_read, "#EXTINF:%d,", &duration);
if (ret != 1)
{
msg_Err(s, "Parsing #EXTINF:<s>,");
msg_Err(s, "expected #EXTINF:<s>,");
p_sys->b_error = true;
}
else
......@@ -557,7 +588,7 @@ static void parse_TargetDuration(stream_t *s, char *p_read)
int ret = sscanf(p_read, "#EXT-X-TARGETDURATION:%d", &duration);
if (ret != 1)
{
msg_Err(s, "Parsing #EXT-X-TARGETDURATION:<s>");
msg_Err(s, "expected #EXT-X-TARGETDURATION:<s>");
p_sys->b_error = true;
}
else
......@@ -575,41 +606,56 @@ static void parse_StreamInformation(stream_t *s, char *p_read, char *uri)
{
stream_sys_t *p_sys = s->p_sys;
/* FIXME: proper attribute parsing
* The current method only parses the most common attribute ordering, but
* does not allow other ordering. The specification does not specify the
* exact attribute ordering. */
int id, bw;
int ret = sscanf(p_read, "#EXT-X-STREAM-INF:PROGRAM-ID=%d,BANDWIDTH=%d", &id, &bw);
if (ret != 2)
char *attr;
attr = parse_Attributes(p_read, "PROGRAM-ID");
if (attr == NULL)
{
msg_Err(s, "error parsing: #EXT-X-STREAM-INF, ignoring ...");
msg_Err(s, "#EXT-X-STREAM-INF: expected PROGRAM-ID=<value>");
p_sys->b_error = true;
return;
}
else
id = atol(attr);
free(attr);
attr = parse_Attributes(p_read, "BANDWIDTH");
if (attr == NULL)
{
msg_Info(s, "Bandwidth adaption detected (program-id=%d, bandwidth=%d).", id, bw);
msg_Err(s, "#EXT-X-STREAM-INF: expected BANDWIDTH=<value>");
p_sys->b_error = true;
return;
}
bw = atoll(attr);
free(attr);
if (bw == 0)
{
msg_Err(s, "#EXT-X-STREAM-INF: bandwidth cannot be 0");
p_sys->b_error = true;
return;
}
msg_Info(s, "Bandwidth adaption detected (program-id=%d, bandwidth=%d).", id, bw);
#if 1
/* FIXME: WORKAROUND FOR BUG IN ANEVIA m3u8 */
char *psz_uri = NULL;
if (asprintf(&psz_uri,"http://%s/%s","demo.anevia.com/0", uri) == -1)
{
msg_Err(s, "Failed workaround");
p_sys->b_error = true;
}
/* FIXME: WORKAROUND FOR BUG IN ANEVIA m3u8 */
char *psz_uri = NULL;
if (asprintf(&psz_uri,"http://%s/%s","demo.anevia.com/0", uri) == -1)
{
msg_Err(s, "Failed workaround");
p_sys->b_error = true;
}
#endif
if (psz_uri != NULL)
{
msg_Info(s, "Playlist Location: %s", psz_uri);
hls_stream_t *hls = hls_New(p_sys->hls_stream, id, bw, psz_uri);
if (hls == NULL)
{
free(psz_uri);
msg_Err(s, "Could not allocate new HTTP Live Stream.");
p_sys->b_error = true;
}
if (psz_uri != NULL)
{
hls_stream_t *hls = hls_New(p_sys->hls_stream, id, bw, psz_uri);
if (hls == NULL)
{
free(psz_uri);
msg_Err(s, "Could not allocate new HTTP Live Stream.");
p_sys->b_error = true;
}
}
}
......@@ -622,7 +668,7 @@ static void parse_MediaSequence(stream_t *s, char *p_read)
int ret = sscanf(p_read, "#EXT-X-MEDIA-SEQUENCE:%d", &sequence);
if (ret != 1)
{
msg_Err(s, "Parsing #EXT-X-MEDIA-SEQUENCE:<s>");
msg_Err(s, "expected #EXT-X-MEDIA-SEQUENCE:<s>");
p_sys->b_error = true;
}
else
......@@ -644,10 +690,34 @@ static void parse_MediaSequence(stream_t *s, char *p_read)
static void parse_Key(stream_t *s, char *p_read)
{
stream_sys_t *p_sys = s->p_sys;
VLC_UNUSED(p_read);
msg_Warn(s, "Playback of encrypted HTTP Live Streaming media is not supported.");
p_sys->b_error = true;
/* #EXT-X-KEY:METHOD=<method>[,URI="<URI>"][,IV=<IV>] */
char *attr;
attr = parse_Attributes(p_read, "METHOD");
if (attr == NULL)
{
msg_Err(s, "#EXT-X-KEY: expected METHOD=<value>");
p_sys->b_error = true;
}
else if (strncasecmp(attr, "NONE", 4) == 0)
{
char *uri = parse_Attributes(p_read, "URI");
char *iv = parse_Attributes(p_read, "IV");
if ((iv != NULL) || (uri != NULL))
{
msg_Err(s, "#EXT-X-KEY: URI and IV not expected");
p_sys->b_error = true;
free(iv);
free(uri);
}
}
else
{
msg_Warn(s, "Playback of encrypted HTTP Live Streaming media is not supported.");
p_sys->b_error = true;
}
free(attr);
}
static void parse_ProgramDateTime(stream_t *s, char *p_read)
......@@ -663,7 +733,7 @@ static void parse_AllowCache(stream_t *s, char *p_read)
int ret = sscanf(p_read, "#EXT-X-ALLOW-CACHE:%3s", answer);
if (ret != 1)
{
msg_Err(s, "error parsing: #EXT-X-ALLOW-CACHE, ignoring ...");
msg_Err(s, "#EXT-X-ALLOW-CACHE, ignoring ...");
p_sys->b_error = true;
}
else
......@@ -682,15 +752,21 @@ static void parse_Version(stream_t *s, char *p_read)
int ret = sscanf(p_read, "#EXT-X-VERSION:%d", &version);
if (ret != 1)
{
msg_Err(s, "error parsing: #EXT-X-VERSION, defaulting to protocol version 1.");
msg_Err(s, "#EXT-X-VERSION: no protocol version found, should be version 1.");
p_sys->b_error = true;
return;
}
else
hls_stream_t *hls = hls_GetLast(p_sys->hls_stream);
if (hls)
{
hls_stream_t *hls = hls_GetLast(p_sys->hls_stream);
if (hls)
hls->version = version;
/* FIXME: check if this version is supported else abort */
hls->version = version;
/* Check version */
if (hls->version != 1)
{
msg_Err(s, "#EXT-X-VERSION should be version 1 iso %d", version);
p_sys->b_error = true;
}
}
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment