Re: [FFmpeg-devel] [PATCH] libavformat/dashdec: Fix for ticket 6658 (Dash demuxer segfault)

2018-01-04 Thread Moritz Barsnick
On Thu, Jan 04, 2018 at 00:42:43 +, Colin NG wrote:
> @@ -1315,6 +1426,7 @@ static int read_from_url(struct representation *pls, 
> struct fragment *seg,
>  } else {
>  ret = avio_read(pls->input, buf, buf_size);
>  }
> +
>  if (ret > 0)
>  pls->cur_seg_offset += ret;
>  

Spurious change.

Moritz
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Re: [FFmpeg-devel] [PATCH] libavformat/dashdec: Fix for ticket 6658 (Dash demuxer segfault)

2018-01-03 Thread 刘歧

> On 4 Jan 2018, at 08:42, Colin NG  wrote:
> 
> - Add function 'resolve_content_path' to propagate the baseURL from upper 
> level nodes.
> * if no baseURL is available, the path of mpd file will be set as the baseURL.
> - Remove checking for newly established connection.
> - Establish the communication protocol in each connection rather than 
> applying one protocol to all connection.
> ---
> libavformat/dashdec.c | 126 --
> 1 file changed, 113 insertions(+), 13 deletions(-)
> 
> diff --git a/libavformat/dashdec.c b/libavformat/dashdec.c
> index 3798649..5345f91 100644
> --- a/libavformat/dashdec.c
> +++ b/libavformat/dashdec.c
> @@ -148,6 +148,11 @@ static uint64_t get_current_time_in_sec(void)
> return  av_gettime() / 100;
> }
> 
> +static int ishttp(char *url) {
> +const char *proto_name = avio_find_protocol_name(url);
> +return av_strstart(proto_name, "http", NULL);
> +}
> +
> static uint64_t get_utc_date_time_insec(AVFormatContext *s, const char 
> *datetime)
> {
> struct tm timeinfo;
> @@ -392,7 +397,8 @@ static int open_url(AVFormatContext *s, AVIOContext **pb, 
> const char *url,
> else if (strcmp(proto_name, "file") || !strncmp(url, "file,", 5))
> return AVERROR_INVALIDDATA;
> 
> -ret = s->io_open(s, pb, url, AVIO_FLAG_READ, &tmp);
> +av_freep(pb);
> +ret = avio_open2(pb, url, AVIO_FLAG_READ, c->interrupt_callback, &tmp);
> if (ret >= 0) {
> // update cookies on http response with setcookies.
> char *new_cookies = NULL;
> @@ -639,6 +645,103 @@ static int 
> parse_manifest_segmenttimeline(AVFormatContext *s, struct representat
> return 0;
> }
> 
> +static int resolve_content_path(AVFormatContext *s, const char *url, 
> xmlNodePtr *baseurl_nodes, int n_baseurl_nodes) {
> +
> +char *tmp_str = NULL;
> +char *path = NULL;
> +char *mpdName = NULL;
> +xmlNodePtr node = NULL;
> +char *baseurl = NULL;
> +char *root_url = NULL;
> +char *text = NULL;
> +
> +int isRootHttp = 0;
> +char token ='/';
> +int start =  0;
> +int rootId = 0;
> +int updated = 0;
> +int size = 0;
> +int i;
> +int max_url_size = strlen(url);
> +
> +for (i = n_baseurl_nodes-1; i >= 0 ; i--) {
> +text = xmlNodeGetContent(baseurl_nodes[i]);
> +if (!text)
> +continue;
> +max_url_size += strlen(text);
> +if (ishttp(text)) {
> +xmlFree(text);
> +break;
> +}
> +xmlFree(text);
> +}
> +
> +text = av_mallocz(max_url_size);
> +if (!text) {
> +updated = AVERROR(ENOMEM);
> +goto end;
> +}
> +av_strlcpy(text, url, strlen(url)+1);
> +while (mpdName = av_strtok(text, "/", &text))  {
> +size = strlen(mpdName);
> +}
> +
> +path = av_mallocz(max_url_size);
> +tmp_str = av_mallocz(max_url_size);
> +if (!tmp_str || !path) {
> +updated = AVERROR(ENOMEM);
> +goto end;
> +}
> +
> +av_strlcpy (path, url, strlen(url) - size + 1);
> +for (rootId = n_baseurl_nodes - 1; rootId > 0; rootId --) {
> +if (!(node = baseurl_nodes[rootId])) {
> +continue;
> +}
> +if (ishttp(xmlNodeGetContent(node))) {
> +break;
> +}
> +}
> +
> +node = baseurl_nodes[rootId];
> +baseurl = xmlNodeGetContent(node);
> +root_url = (av_strcasecmp(baseurl, "")) ? baseurl : path;
> +if (node) {
> +xmlNodeSetContent(node, root_url);
> +}
> +
> +size = strlen(root_url);
> +isRootHttp = ishttp(root_url);
> +
> +if (root_url[size - 1] != token) {
> +av_strlcat(root_url, "/", size + 2);
> +size += 2;
> +}
> +
> +for (i = 0; i < n_baseurl_nodes; ++i) {
> +if (i == rootId) {
> +continue;
> +}
> +text = xmlNodeGetContent(baseurl_nodes[i]);
> +if (text) {
> +memset(tmp_str, 0, strlen(tmp_str));
> +if (!ishttp(text) && isRootHttp) {
> +av_strlcpy(tmp_str, root_url, size + 1);
> +}
> +start = (text[0] == token);
> +av_strlcat(tmp_str, text + start, max_url_size);
> +xmlNodeSetContent(baseurl_nodes[i], tmp_str);
> +updated = 1;
> +xmlFree(text);
> +}
> +}
> +
> +end:
> +av_free(path);
> +av_free(tmp_str);
> +return updated;
> +
> +}
> static int parse_manifest_representation(AVFormatContext *s, const char *url,
>  xmlNodePtr node,
>  xmlNodePtr adaptionset_node,
> @@ -698,6 +801,11 @@ static int parse_manifest_representation(AVFormatContext 
> *s, const char *url,
> baseurl_nodes[2] = adaptionset_baseurl_node;
> baseurl_nodes[3] = representation_baseurl_node;
> 
> +ret = resolve_content_path(s, url, baseurl_nodes, 4);
> +if (ret == AVERROR(ENOMEM) 

[FFmpeg-devel] [PATCH] libavformat/dashdec: Fix for ticket 6658 (Dash demuxer segfault)

2018-01-03 Thread Colin NG
- Add function 'resolve_content_path' to propagate the baseURL from upper level 
nodes.
 * if no baseURL is available, the path of mpd file will be set as the baseURL.
- Remove checking for newly established connection.
- Establish the communication protocol in each connection rather than applying 
one protocol to all connection.
---
 libavformat/dashdec.c | 126 --
 1 file changed, 113 insertions(+), 13 deletions(-)

diff --git a/libavformat/dashdec.c b/libavformat/dashdec.c
index 3798649..5345f91 100644
--- a/libavformat/dashdec.c
+++ b/libavformat/dashdec.c
@@ -148,6 +148,11 @@ static uint64_t get_current_time_in_sec(void)
 return  av_gettime() / 100;
 }
 
+static int ishttp(char *url) {
+const char *proto_name = avio_find_protocol_name(url);
+return av_strstart(proto_name, "http", NULL);
+}
+
 static uint64_t get_utc_date_time_insec(AVFormatContext *s, const char 
*datetime)
 {
 struct tm timeinfo;
@@ -392,7 +397,8 @@ static int open_url(AVFormatContext *s, AVIOContext **pb, 
const char *url,
 else if (strcmp(proto_name, "file") || !strncmp(url, "file,", 5))
 return AVERROR_INVALIDDATA;
 
-ret = s->io_open(s, pb, url, AVIO_FLAG_READ, &tmp);
+av_freep(pb);
+ret = avio_open2(pb, url, AVIO_FLAG_READ, c->interrupt_callback, &tmp);
 if (ret >= 0) {
 // update cookies on http response with setcookies.
 char *new_cookies = NULL;
@@ -639,6 +645,103 @@ static int parse_manifest_segmenttimeline(AVFormatContext 
*s, struct representat
 return 0;
 }
 
+static int resolve_content_path(AVFormatContext *s, const char *url, 
xmlNodePtr *baseurl_nodes, int n_baseurl_nodes) {
+
+char *tmp_str = NULL;
+char *path = NULL;
+char *mpdName = NULL;
+xmlNodePtr node = NULL;
+char *baseurl = NULL;
+char *root_url = NULL;
+char *text = NULL;
+
+int isRootHttp = 0;
+char token ='/';
+int start =  0;
+int rootId = 0;
+int updated = 0;
+int size = 0;
+int i;
+int max_url_size = strlen(url);
+
+for (i = n_baseurl_nodes-1; i >= 0 ; i--) {
+text = xmlNodeGetContent(baseurl_nodes[i]);
+if (!text)
+continue;
+max_url_size += strlen(text);
+if (ishttp(text)) {
+xmlFree(text);
+break;
+}
+xmlFree(text);
+}
+
+text = av_mallocz(max_url_size);
+if (!text) {
+updated = AVERROR(ENOMEM);
+goto end;
+}
+av_strlcpy(text, url, strlen(url)+1);
+while (mpdName = av_strtok(text, "/", &text))  {
+size = strlen(mpdName);
+}
+
+path = av_mallocz(max_url_size);
+tmp_str = av_mallocz(max_url_size);
+if (!tmp_str || !path) {
+updated = AVERROR(ENOMEM);
+goto end;
+}
+
+av_strlcpy (path, url, strlen(url) - size + 1);
+for (rootId = n_baseurl_nodes - 1; rootId > 0; rootId --) {
+if (!(node = baseurl_nodes[rootId])) {
+continue;
+}
+if (ishttp(xmlNodeGetContent(node))) {
+break;
+}
+}
+
+node = baseurl_nodes[rootId];
+baseurl = xmlNodeGetContent(node);
+root_url = (av_strcasecmp(baseurl, "")) ? baseurl : path;
+if (node) {
+xmlNodeSetContent(node, root_url);
+}
+
+size = strlen(root_url);
+isRootHttp = ishttp(root_url);
+
+if (root_url[size - 1] != token) {
+av_strlcat(root_url, "/", size + 2);
+size += 2;
+}
+
+for (i = 0; i < n_baseurl_nodes; ++i) {
+if (i == rootId) {
+continue;
+}
+text = xmlNodeGetContent(baseurl_nodes[i]);
+if (text) {
+memset(tmp_str, 0, strlen(tmp_str));
+if (!ishttp(text) && isRootHttp) {
+av_strlcpy(tmp_str, root_url, size + 1);
+}
+start = (text[0] == token);
+av_strlcat(tmp_str, text + start, max_url_size);
+xmlNodeSetContent(baseurl_nodes[i], tmp_str);
+updated = 1;
+xmlFree(text);
+}
+}
+
+end:
+av_free(path);
+av_free(tmp_str);
+return updated;
+
+}
 static int parse_manifest_representation(AVFormatContext *s, const char *url,
  xmlNodePtr node,
  xmlNodePtr adaptionset_node,
@@ -698,6 +801,11 @@ static int parse_manifest_representation(AVFormatContext 
*s, const char *url,
 baseurl_nodes[2] = adaptionset_baseurl_node;
 baseurl_nodes[3] = representation_baseurl_node;
 
+ret = resolve_content_path(s, url, baseurl_nodes, 4);
+if (ret == AVERROR(ENOMEM) || ret == 0) {
+goto end;
+}
+
 if (representation_segmenttemplate_node || fragment_template_node) {
 fragment_timeline_node = NULL;
 fragment_templates_tab[0] = representation_segmenttemplate_node;
@@ -993,6 +1101,9 @@ static int parse_manifest(AVFormatContext *s, const ch

Re: [FFmpeg-devel] [PATCH] libavformat/dashdec: Fix for ticket 6658 (Dash demuxer segfault)

2017-12-26 Thread Tomas Härdin
tis 2017-12-26 klockan 01:12 + skrev Colin NG:
> +static int resolve_content_path(AVFormatContext *s, const char *url, 
> xmlNodePtr *baseurl_nodes, int n_baseurl_nodes) {
> +
> +char *tmp_str = av_mallocz(MAX_URL_SIZE);
> +char *path = av_mallocz(MAX_URL_SIZE);
> +char *mpdName = NULL;
> +xmlNodePtr  node = NULL;
> +char *baseurl = NULL;
> +char *root_url = NULL;
> +char *text = NULL;
> +
> +int isRootHttp = 0;
> +char token ='/';
> +int start =  0;
> +int rootId = 0;
> +int updated = 0;
> +int size = 0;
> +int i;
> +
> +if (!tmp_str || !path) {
> +updated = AVERROR(ENOMEM);
> +goto end;
> +}
> +
> +av_strlcpy(tmp_str, url, strlen(url) + 1);

MAX_URL_SIZE maybe? Is there some way url can be too long?

> +mpdName = strtok (tmp_str, "/");
> +while (mpdName = strtok (NULL, "/")) {
> +size = strlen(mpdName);
> +}

strtok() isn't thread safe. I forget if we guarantee thread safeness at
this stage in lavf

> +
> +av_strlcpy (path, url, strlen(url) - size + 1);

Similarly here. Plus strlen(url) being computed again

> +for (rootId = n_baseurl_nodes - 1; rootId > 0; rootId --) {
> +if (!(node = baseurl_nodes[rootId])) {
> +continue;
> +}
> +if (ishttp(xmlNodeGetContent(node))) {
> +break;
> +}
> +}
> +
> +node = baseurl_nodes[rootId];
> +baseurl = xmlNodeGetContent(node);
> +root_url = (av_strcasecmp(baseurl, "")) ? baseurl : path;
> +if (node) {
> +xmlNodeSetContent(node, root_url);
> +}
> +
> +size = strlen(root_url);
> +isRootHttp = ishttp(root_url);
> +
> +if (root_url[size - 1] == token) {
> +av_strlcat(root_url, "/", size + 2);
> +size += 2;
> +}
> +
> +for (i = 0; i < n_baseurl_nodes; ++i) {
> +if (i == rootId) {
> +continue;
> +}
> +text = xmlNodeGetContent(baseurl_nodes[i]);
> +if (text) {
> +memset(tmp_str, 0, strlen(tmp_str));
> +if (!ishttp(text) && isRootHttp) {
> +av_strlcpy(tmp_str, root_url, size + 1);
> +}
> +start = (text[0] == token);
> +av_strlcat(tmp_str, text + start, MAX_URL_SIZE);
> +xmlNodeSetContent(baseurl_nodes[i], tmp_str);
> +updated = 1;
> +xmlFree(text);
> +}
> +}
> +
> +end:
> +av_free(path);
> +av_free(tmp_str);
> +return updated;
> +
> +}

I don't really like lavf doing URL parsing/manipulation like this when
there's (supposedly) mature libraries to do it. Especially after this
year's Blackhat revelations of exploits making use of how whitespace,
unicode, slashes, percent encoding etc are handled differently in every
library [1]. But I'm also not familiar with DASH so can't say what
would be the typical thing to do

/Tomas

[1] https://www.blackhat.com/docs/us-17/thursday/us-17-Tsai-A-New-Era-O
f-SSRF-Exploiting-URL-Parser-In-Trending-Programming-Languages.pdf


signature.asc
Description: This is a digitally signed message part
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH] libavformat/dashdec: Fix for ticket 6658 (Dash demuxer segfault)

2017-12-25 Thread Colin NG
- Add function 'resolve_content_path' to propagate the baseURL from upper level 
nodes.
 * if no baseURL is available, the path of mpd file will be set as the baseURL.
- Remove checking for newly established connection.
- Establish the communication protocol in each connection rather than applying 
one protocol to all connection.
---
 libavformat/dashdec.c | 107 --
 1 file changed, 94 insertions(+), 13 deletions(-)

diff --git a/libavformat/dashdec.c b/libavformat/dashdec.c
index 3798649..e41ba96 100644
--- a/libavformat/dashdec.c
+++ b/libavformat/dashdec.c
@@ -148,6 +148,11 @@ static uint64_t get_current_time_in_sec(void)
 return  av_gettime() / 100;
 }
 
+static int ishttp(char *url) {
+const char *proto_name = avio_find_protocol_name(url);
+return av_strstart(proto_name, "http", NULL);
+}
+
 static uint64_t get_utc_date_time_insec(AVFormatContext *s, const char 
*datetime)
 {
 struct tm timeinfo;
@@ -392,7 +397,8 @@ static int open_url(AVFormatContext *s, AVIOContext **pb, 
const char *url,
 else if (strcmp(proto_name, "file") || !strncmp(url, "file,", 5))
 return AVERROR_INVALIDDATA;
 
-ret = s->io_open(s, pb, url, AVIO_FLAG_READ, &tmp);
+av_freep(pb);
+ret = avio_open2(pb, url, AVIO_FLAG_READ, c->interrupt_callback, &tmp);
 if (ret >= 0) {
 // update cookies on http response with setcookies.
 char *new_cookies = NULL;
@@ -639,6 +645,84 @@ static int parse_manifest_segmenttimeline(AVFormatContext 
*s, struct representat
 return 0;
 }
 
+static int resolve_content_path(AVFormatContext *s, const char *url, 
xmlNodePtr *baseurl_nodes, int n_baseurl_nodes) {
+
+char *tmp_str = av_mallocz(MAX_URL_SIZE);
+char *path = av_mallocz(MAX_URL_SIZE);
+char *mpdName = NULL;
+xmlNodePtr  node = NULL;
+char *baseurl = NULL;
+char *root_url = NULL;
+char *text = NULL;
+
+int isRootHttp = 0;
+char token ='/';
+int start =  0;
+int rootId = 0;
+int updated = 0;
+int size = 0;
+int i;
+
+if (!tmp_str || !path) {
+updated = AVERROR(ENOMEM);
+goto end;
+}
+
+av_strlcpy(tmp_str, url, strlen(url) + 1);
+mpdName = strtok (tmp_str, "/");
+while (mpdName = strtok (NULL, "/")) {
+size = strlen(mpdName);
+}
+
+av_strlcpy (path, url, strlen(url) - size + 1);
+for (rootId = n_baseurl_nodes - 1; rootId > 0; rootId --) {
+if (!(node = baseurl_nodes[rootId])) {
+continue;
+}
+if (ishttp(xmlNodeGetContent(node))) {
+break;
+}
+}
+
+node = baseurl_nodes[rootId];
+baseurl = xmlNodeGetContent(node);
+root_url = (av_strcasecmp(baseurl, "")) ? baseurl : path;
+if (node) {
+xmlNodeSetContent(node, root_url);
+}
+
+size = strlen(root_url);
+isRootHttp = ishttp(root_url);
+
+if (root_url[size - 1] == token) {
+av_strlcat(root_url, "/", size + 2);
+size += 2;
+}
+
+for (i = 0; i < n_baseurl_nodes; ++i) {
+if (i == rootId) {
+continue;
+}
+text = xmlNodeGetContent(baseurl_nodes[i]);
+if (text) {
+memset(tmp_str, 0, strlen(tmp_str));
+if (!ishttp(text) && isRootHttp) {
+av_strlcpy(tmp_str, root_url, size + 1);
+}
+start = (text[0] == token);
+av_strlcat(tmp_str, text + start, MAX_URL_SIZE);
+xmlNodeSetContent(baseurl_nodes[i], tmp_str);
+updated = 1;
+xmlFree(text);
+}
+}
+
+end:
+av_free(path);
+av_free(tmp_str);
+return updated;
+
+}
 static int parse_manifest_representation(AVFormatContext *s, const char *url,
  xmlNodePtr node,
  xmlNodePtr adaptionset_node,
@@ -698,6 +782,11 @@ static int parse_manifest_representation(AVFormatContext 
*s, const char *url,
 baseurl_nodes[2] = adaptionset_baseurl_node;
 baseurl_nodes[3] = representation_baseurl_node;
 
+ret = resolve_content_path(s, url, baseurl_nodes, 4);
+if (ret == AVERROR(ENOMEM) || ret == 0) {
+goto end;
+}
+
 if (representation_segmenttemplate_node || fragment_template_node) {
 fragment_timeline_node = NULL;
 fragment_templates_tab[0] = representation_segmenttemplate_node;
@@ -993,6 +1082,9 @@ static int parse_manifest(AVFormatContext *s, const char 
*url, AVIOContext *in)
 }
 
 mpd_baseurl_node = find_child_node_by_name(node, "BaseURL");
+if (!mpd_baseurl_node) {
+mpd_baseurl_node = xmlNewNode(NULL, "BaseURL");
+}
 
 // at now we can handle only one period, with the longest duration
 node = xmlFirstElementChild(node);
@@ -1315,6 +1407,7 @@ static int read_from_url(struct representation *pls, 
struct fragment *seg,
 } else {
 ret = av

Re: [FFmpeg-devel] [PATCH] libavformat/dashdec: Fix for ticket 6658 (Dash demuxer segfault) - Add function 'resolve_content_path' to propagate the baseURL from upper level nodes. * if no baseURL is av

2017-12-25 Thread Moritz Barsnick
On Sat, Dec 23, 2017 at 21:47:05 +, Colin NG wrote:

> Subject: [FFmpeg-devel] [PATCH] libavformat/dashdec: Fix for ticket 6658 
> (Dash demuxer segfault) - Add function 'resolve_content_path' to propagate 
> the baseURL from upper level 
> nodes. * if no baseURL is available, the path of mpd file will be set 
> as the baseURL. - Remove chec...

In the commit message, you need to separate the subsequent lines from
the first line with an empty line, otherwise everything gets wrapped
into one subject line.

> +static int resolve_content_path(AVFormatContext *s, const char *url,  
> xmlNodePtr *baseurl_nodes,  int n_baseurl_nodes) {

ffmpeg functions have their opening bracket on the first column of a
new line.

> +av_strlcpy (path, url, strlen(url) - size + 1);
[...]
> +root_url = (av_strcasecmp(baseurl, ""))? baseurl: path;
[...]
> +if (root_url[size-1]==token) {
> +av_strlcat(root_url, "/", size+2);
> +size+=2;

There are still quite a few style issues in your code. Have a look at
the ffmpeg contribution info for details:
https://ffmpeg.org/developer.html#Code-formatting-conventions

The operators "?" and ":" also need to be surrounded by whitespace, as
do "==", "+", "+=", and so on. On the other hand, the function name
such as av_strlcpy isn't separated by a space from its bracket.

> +start = (text[0] == token) ? 1: 0;

start = (text[0] == token);
is sufficient.

Moritz
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Re: [FFmpeg-devel] [PATCH] libavformat/dashdec: Fix for ticket 6658 (Dash demuxer segfault) - Add function 'resolve_content_path' to propagate the baseURL from upper level nodes. * if no baseURL is av

2017-12-23 Thread Michael Niedermayer
On Sat, Dec 23, 2017 at 09:47:05PM +, Colin NG wrote:
> ---
>  libavformat/dashdec.c | 110 
> --
>  1 file changed, 97 insertions(+), 13 deletions(-)

seems my git doesnt like this patch:

Applying: libavformat/dashdec: Fix for ticket 6658 (Dash demuxer segfault) - 
Add function 'resolve_content_path' to propagate the baseURL from upper level 
nodes. * if no baseURL is available, the path of mpd file will be set as the 
baseURL. - Remove che...
error: corrupt patch at line 20
error: could not build fake ancestor
Patch failed at 0001 libavformat/dashdec: Fix for ticket 6658 (Dash demuxer 
segfault) - Add function 'resolve_content_path' to propagate the baseURL from 
upper level nodes. * if no baseURL is available, the path of mpd file will be 
set as the baseURL. - Remove che...
The copy of the patch that failed is found in: .git/rebase-apply/patch
When you have resolved this problem, run "git am --continue".
If you prefer to skip this patch, run "git am --skip" instead.
To restore the original branch and stop patching, run "git am --abort".


[...]
-- 
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

"You are 36 times more likely to die in a bathtub than at the hands of a
terrorist. Also, you are 2.5 times more likely to become a president and
2 times more likely to become an astronaut, than to die in a terrorist
attack." -- Thoughty2



signature.asc
Description: PGP signature
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH] libavformat/dashdec: Fix for ticket 6658 (Dash demuxer segfault) - Add function 'resolve_content_path' to propagate the baseURL from upper level nodes. * if no baseURL is availa

2017-12-23 Thread Colin NG
---
 libavformat/dashdec.c | 110 --
 1 file changed, 97 insertions(+), 13 deletions(-)

diff --git a/libavformat/dashdec.c b/libavformat/dashdec.c
index 3798649..6574e56 100644
--- a/libavformat/dashdec.c
+++ b/libavformat/dashdec.c
@@ -148,6 +148,11 @@ static uint64_t get_current_time_in_sec(void)
 return  av_gettime() / 100;
 }
 
+static int ishttp(char *url) {
+const char *proto_name = avio_find_protocol_name(url);
+return av_strstart(proto_name, "http", NULL);
+}
 static uint64_t get_utc_date_time_insec(AVFormatContext *s, const char 
*datetime)
 {
 struct tm timeinfo;
@@ -392,7 +397,9 @@ static int open_url(AVFormatContext *s, AVIOContext **pb, 
const char *url,
 else if (strcmp(proto_name, "file") || !strncmp(url, "file,", 5))
 return AVERROR_INVALIDDATA;
 
-ret = s->io_open(s, pb, url, AVIO_FLAG_READ, &tmp);
+av_freep(pb);
+ret = avio_open2(pb, url, AVIO_FLAG_READ, c->interrupt_callback, &tmp);
 if (ret >= 0) {
 // update cookies on http response with setcookies.
 char *new_cookies = NULL;
@@ -639,6 +646,85 @@ static int parse_manifest_segmenttimeline(AVFormatContext 
*s, struct representat
 return 0;
 }
 
+static int resolve_content_path(AVFormatContext *s, const char *url,  
xmlNodePtr *baseurl_nodes,  int n_baseurl_nodes) {
+
+char *tmp_str = av_mallocz(MAX_URL_SIZE);
+char *path = av_mallocz(MAX_URL_SIZE);
+char *mpdName = NULL;
+xmlNodePtr  node = NULL;
+char *baseurl = NULL;
+char *root_url = NULL;
+char *text = NULL;
+
+int isRootHttp = 0;
+char token ='/';
+int start =  0;
+int rootId = 0;
+int updated = 0;
+int size = 0;
+int i;
+
+if (!tmp_str || !path) {
+updated = AVERROR(ENOMEM);
+goto end;
+}
+
+av_strlcpy(tmp_str, url, strlen(url) + 1);
+mpdName = strtok (tmp_str, "/");
+while (mpdName = strtok (NULL, "/")) {
+size = strlen(mpdName);
+}
+
+av_strlcpy (path, url, strlen(url) - size + 1);
+
+for (rootId = n_baseurl_nodes - 1; rootId > 0; rootId--) {
+if (!(node = baseurl_nodes[rootId])) {
+continue;
+}
+if (ishttp(xmlNodeGetContent(node))) {
+break;
+}
+}
+
+node = baseurl_nodes[rootId];
+baseurl = xmlNodeGetContent(node);
+root_url = (av_strcasecmp(baseurl, ""))? baseurl: path;
+if (node) {
+xmlNodeSetContent(node, root_url);
+}
+
+size = strlen(root_url);
+isRootHttp= ishttp(root_url);
+
+if (root_url[size-1]==token) {
+av_strlcat(root_url, "/", size+2);
+size+=2;
+}
+
+for (i = 0; i < n_baseurl_nodes; ++i) {
+if (i == rootId) {
+continue;
+}
+text = xmlNodeGetContent(baseurl_nodes[i]);
+if (text) {
+memset(tmp_str, 0, strlen(tmp_str));
+if (!ishttp(text) && isRootHttp) {
+av_strlcpy(tmp_str, root_url, size + 1);
+}
+start = (text[0] == token) ? 1: 0;
+av_strlcat(tmp_str, text + start, MAX_URL_SIZE);
+xmlNodeSetContent(baseurl_nodes[i], tmp_str);
+updated = 1;
+xmlFree(text);
+}
+}
+
+end:
+av_free(path);
+av_free(tmp_str);
+return updated;
+
+}
 static int parse_manifest_representation(AVFormatContext *s, const char *url,
  xmlNodePtr node,
  xmlNodePtr adaptionset_node,
@@ -698,6 +784,12 @@ static int parse_manifest_representation(AVFormatContext 
*s, const char *url,
 baseurl_nodes[2] = adaptionset_baseurl_node;
 baseurl_nodes[3] = representation_baseurl_node;
 
+ret = resolve_content_path(s, url, baseurl_nodes, 4);
+if (ret == AVERROR(ENOMEM) || ret == 0) {
+goto end;
+}
+
 if (representation_segmenttemplate_node || fragment_template_node) {
 fragment_timeline_node = NULL;
 fragment_templates_tab[0] = representation_segmenttemplate_node;
@@ -993,6 +1085,9 @@ static int parse_manifest(AVFormatContext *s, const char 
*url, AVIOContext *in)
 }
 
 mpd_baseurl_node = find_child_node_by_name(node, "BaseURL");
+if (!mpd_baseurl_node) {
+mpd_baseurl_node = xmlNewNode(NULL, "BaseURL");
+}
 
 // at now we can handle only one period, with the longest duration
 node = xmlFirstElementChild(node);
@@ -1315,6 +1410,7 @@ static int read_from_url(struct representation *pls, 
struct fragment *seg,
 } else {
 ret = avio_read(pls->input, buf, buf_size);
 }
 if (ret > 0)
 pls->cur_seg_offset += ret;
 
@@ -1343,18 +1439,6 @@ static int open_input(DASHContext *c, struct 
representation *pls, struct fragmen
 goto cleanup;
 }
 
-/* Seek to the requested position. If this was a HTTP request, the offset
- * should alre

Re: [FFmpeg-devel] [PATCH] libavformat/dashdec: Fix for ticket 6658 (Dash demuxer segfault) - Add function 'resolve_content_path' to propagate the baseURL from upper level nodes. * if no baseURL is av

2017-12-20 Thread 刘歧

> On 21 Dec 2017, at 10:39, Colin NG  wrote:
> 
> ---
> libavformat/dashdec.c | 116 --
> 1 file changed, 103 insertions(+), 13 deletions(-)
> 
> diff --git a/libavformat/dashdec.c b/libavformat/dashdec.c
> index 3798649..cdb9f67 100644
> --- a/libavformat/dashdec.c
> +++ b/libavformat/dashdec.c
> @@ -148,6 +148,11 @@ static uint64_t get_current_time_in_sec(void)
> return  av_gettime() / 100;
> }
> 
> +static int ishttp(char *url) {
> +const char *proto_name = avio_find_protocol_name(url);
> +return av_strstart(proto_name, "http", NULL);
> +}
> +
> static uint64_t get_utc_date_time_insec(AVFormatContext *s, const char 
> *datetime)
> {
> struct tm timeinfo;
> @@ -392,7 +397,9 @@ static int open_url(AVFormatContext *s, AVIOContext **pb, 
> const char *url,
> else if (strcmp(proto_name, "file") || !strncmp(url, "file,", 5))
> return AVERROR_INVALIDDATA;
> 
> -ret = s->io_open(s, pb, url, AVIO_FLAG_READ, &tmp);
> +av_freep(pb);
> +ret = avio_open2(pb, url, AVIO_FLAG_READ, c->interrupt_callback, &tmp);
> +
> if (ret >= 0) {
> // update cookies on http response with setcookies.
> char *new_cookies = NULL;
> @@ -639,6 +646,91 @@ static int 
> parse_manifest_segmenttimeline(AVFormatContext *s, struct representat
> return 0;
> }
> 
> +static int resolve_content_path(AVFormatContext *s, const char *url,  
> xmlNodePtr *baseurl_nodes,  int n_baseurl_nodes) {
> +
> +char *tmp_str = av_mallocz(MAX_URL_SIZE);
> +char *tmp_str_2= av_mallocz(MAX_URL_SIZE);
> +char *path = av_mallocz(MAX_URL_SIZE);
> +char *mpdName = NULL;
> +xmlNodePtr  node = NULL;
> +char *baseurl = NULL;
> +char *root_url = NULL;
> +char *text = NULL;
> +
> +int isRootHttp = 0;
> +char token ='/';
> +int start =  0;
> +int rootId = 0;
> +int updated = 0;
> +int size = 0;
> +int i;
> +
> +if (!tmp_str || !tmp_str_2 || !path) {
> +updated = AVERROR(ENOMEM);
> +goto end;
> +}
> +
> +av_strlcpy(tmp_str, url, strlen(url)+1);
space code style
> +mpdName = strtok (tmp_str," /");
> +
> +while ((mpdName =strtok (NULL, "/"))) {
> +size = strlen(mpdName);
> +}
> +
> +av_strlcpy (path, url, strlen(url)-size+1);
strlen(url) -  size + 1;  *space code style*,
> +
> +for (rootId = n_baseurl_nodes-1; rootId >0; rootId--) {
> +if (!(node = baseurl_nodes[rootId])) {
> +continue;
> +}
> +if (ishttp(xmlNodeGetContent(node))) {
> +break;
> +}
> +}
> +
> +node = baseurl_nodes[rootId];
> +baseurl = xmlNodeGetContent(node);
> +root_url = (!av_strcasecmp(baseurl, ""))? path: baseurl;
root_url = av_strcasecmp(baseurl, “") ? baseurl : path;

> +
> +if (node) {
> +xmlNodeSetContent(node, root_url);
> +}
> +
> +size = strlen(root_url);
> +isRootHttp= ishttp(root_url);
> +
> +if (root_url[size-1]==token) {

if (root_url[size - 1] == token) {

> +av_strlcat(root_url, "/", size+2);
> +size+=2;
av_strlcat(root_url, “/“, size + 2);
size += 2;

> +}
> +
> +for (i = 0; i < n_baseurl_nodes; ++i) {
> +if (i==rootId) {
i == rootId

> +continue;
> +}
> +text = xmlNodeGetContent(baseurl_nodes[i]);
> +if (text) {
> +memset(tmp_str, 0, strlen(tmp_str));
this line maybe no need, because you have use av_mallocz, that can memset the 
tmp_str to 0;

> +
> +if (!ishttp(text) && isRootHttp) {
> +av_strlcpy(tmp_str, root_url, size+1);
> +}
> +start = (text[0]==token) ? 1: 0;
> +memset(tmp_str_2, 0, strlen(tmp_str_2));
ditto.

> +av_strlcat(tmp_str, text+start, MAX_URL_SIZE);
> +xmlNodeSetContent(baseurl_nodes[i], tmp_str);
> +updated = 1;
> +xmlFree(text);
> +}
> +}
> +
> +end:
> +av_free(path);
> +av_free(tmp_str);
> +av_free(tmp_str_2);
> +return updated;
> +
> +}
> static int parse_manifest_representation(AVFormatContext *s, const char *url,
>  xmlNodePtr node,
>  xmlNodePtr adaptionset_node,
> @@ -698,6 +790,12 @@ static int parse_manifest_representation(AVFormatContext 
> *s, const char *url,
> baseurl_nodes[2] = adaptionset_baseurl_node;
> baseurl_nodes[3] = representation_baseurl_node;
> 
> +ret = resolve_content_path(s, url, baseurl_nodes, 4);
> +
> +if (ret == AVERROR(ENOMEM) || ret == 0) {
can this use if (ret <= 0) { ?
> +goto end;
> +}
> +
> if (representation_segmenttemplate_node || fragment_template_node) {
> fragment_timeline_node = NULL;
> fragment_templates_tab[0] = representation_segmenttemplate_node;
> @@ -993,6 +1091,9 @@ static int parse_manifest(AVFormatContext *s, const char 

[FFmpeg-devel] [PATCH] libavformat/dashdec: Fix for ticket 6658 (Dash demuxer segfault) - Add function 'resolve_content_path' to propagate the baseURL from upper level nodes. * if no baseURL is availa

2017-12-20 Thread Colin NG
---
 libavformat/dashdec.c | 116 --
 1 file changed, 103 insertions(+), 13 deletions(-)

diff --git a/libavformat/dashdec.c b/libavformat/dashdec.c
index 3798649..cdb9f67 100644
--- a/libavformat/dashdec.c
+++ b/libavformat/dashdec.c
@@ -148,6 +148,11 @@ static uint64_t get_current_time_in_sec(void)
 return  av_gettime() / 100;
 }
 
+static int ishttp(char *url) {
+const char *proto_name = avio_find_protocol_name(url);
+return av_strstart(proto_name, "http", NULL);
+}
+
 static uint64_t get_utc_date_time_insec(AVFormatContext *s, const char 
*datetime)
 {
 struct tm timeinfo;
@@ -392,7 +397,9 @@ static int open_url(AVFormatContext *s, AVIOContext **pb, 
const char *url,
 else if (strcmp(proto_name, "file") || !strncmp(url, "file,", 5))
 return AVERROR_INVALIDDATA;
 
-ret = s->io_open(s, pb, url, AVIO_FLAG_READ, &tmp);
+av_freep(pb);
+ret = avio_open2(pb, url, AVIO_FLAG_READ, c->interrupt_callback, &tmp);
+
 if (ret >= 0) {
 // update cookies on http response with setcookies.
 char *new_cookies = NULL;
@@ -639,6 +646,91 @@ static int parse_manifest_segmenttimeline(AVFormatContext 
*s, struct representat
 return 0;
 }
 
+static int resolve_content_path(AVFormatContext *s, const char *url,  
xmlNodePtr *baseurl_nodes,  int n_baseurl_nodes) {
+
+char *tmp_str = av_mallocz(MAX_URL_SIZE);
+char *tmp_str_2= av_mallocz(MAX_URL_SIZE);
+char *path = av_mallocz(MAX_URL_SIZE);
+char *mpdName = NULL;
+xmlNodePtr  node = NULL;
+char *baseurl = NULL;
+char *root_url = NULL;
+char *text = NULL;
+
+int isRootHttp = 0;
+char token ='/';
+int start =  0;
+int rootId = 0;
+int updated = 0;
+int size = 0;
+int i;
+
+if (!tmp_str || !tmp_str_2 || !path) {
+updated = AVERROR(ENOMEM);
+goto end;
+}
+
+av_strlcpy(tmp_str, url, strlen(url)+1);
+mpdName = strtok (tmp_str," /");
+
+while ((mpdName =strtok (NULL, "/"))) {
+size = strlen(mpdName);
+}
+
+av_strlcpy (path, url, strlen(url)-size+1);
+
+for (rootId = n_baseurl_nodes-1; rootId >0; rootId--) {
+if (!(node = baseurl_nodes[rootId])) {
+continue;
+}
+if (ishttp(xmlNodeGetContent(node))) {
+break;
+}
+}
+
+node = baseurl_nodes[rootId];
+baseurl = xmlNodeGetContent(node);
+root_url = (!av_strcasecmp(baseurl, ""))? path: baseurl;
+
+if (node) {
+xmlNodeSetContent(node, root_url);
+}
+
+size = strlen(root_url);
+isRootHttp= ishttp(root_url);
+
+if (root_url[size-1]==token) {
+av_strlcat(root_url, "/", size+2);
+size+=2;
+}
+
+for (i = 0; i < n_baseurl_nodes; ++i) {
+if (i==rootId) {
+continue;
+}
+text = xmlNodeGetContent(baseurl_nodes[i]);
+if (text) {
+memset(tmp_str, 0, strlen(tmp_str));
+
+if (!ishttp(text) && isRootHttp) {
+av_strlcpy(tmp_str, root_url, size+1);
+}
+start = (text[0]==token) ? 1: 0;
+memset(tmp_str_2, 0, strlen(tmp_str_2));
+av_strlcat(tmp_str, text+start, MAX_URL_SIZE);
+xmlNodeSetContent(baseurl_nodes[i], tmp_str);
+updated = 1;
+xmlFree(text);
+}
+}
+
+end:
+av_free(path);
+av_free(tmp_str);
+av_free(tmp_str_2);
+return updated;
+
+}
 static int parse_manifest_representation(AVFormatContext *s, const char *url,
  xmlNodePtr node,
  xmlNodePtr adaptionset_node,
@@ -698,6 +790,12 @@ static int parse_manifest_representation(AVFormatContext 
*s, const char *url,
 baseurl_nodes[2] = adaptionset_baseurl_node;
 baseurl_nodes[3] = representation_baseurl_node;
 
+ret = resolve_content_path(s, url, baseurl_nodes, 4);
+
+if (ret == AVERROR(ENOMEM) || ret == 0) {
+goto end;
+}
+
 if (representation_segmenttemplate_node || fragment_template_node) {
 fragment_timeline_node = NULL;
 fragment_templates_tab[0] = representation_segmenttemplate_node;
@@ -993,6 +1091,9 @@ static int parse_manifest(AVFormatContext *s, const char 
*url, AVIOContext *in)
 }
 
 mpd_baseurl_node = find_child_node_by_name(node, "BaseURL");
+if (!mpd_baseurl_node) {
+mpd_baseurl_node = xmlNewNode(NULL, "BaseURL");
+}
 
 // at now we can handle only one period, with the longest duration
 node = xmlFirstElementChild(node);
@@ -1315,6 +1416,7 @@ static int read_from_url(struct representation *pls, 
struct fragment *seg,
 } else {
 ret = avio_read(pls->input, buf, buf_size);
 }
+
 if (ret > 0)
 pls->cur_seg_offset += ret;
 
@@ -1343,18 +1445,6 @@ static int open_input(DASHContext *c, struct 
representation *pls, stru

Re: [FFmpeg-devel] [PATCH] libavformat/dashdec: Fix for ticket 6658 (Dash demuxer segfault) - Add function 'resolve_content_path' to propagate the baseURL from upper level nodes. * if no baseURL is av

2017-12-05 Thread Steven Liu
2017-12-06 9:42 GMT+08:00 Colin NG :
> ---
>  libavformat/dashdec.c | 111 
> --
>  1 file changed, 98 insertions(+), 13 deletions(-)
>
> diff --git a/libavformat/dashdec.c b/libavformat/dashdec.c
> index 3798649..6e35e91 100644
> --- a/libavformat/dashdec.c
> +++ b/libavformat/dashdec.c
> @@ -148,6 +148,11 @@ static uint64_t get_current_time_in_sec(void)
>  return  av_gettime() / 100;
>  }
>
> +static char * ishttp(char *url) {
> +char *proto_name = avio_find_protocol_name(url);
> +return av_strstart(proto_name, "http", NULL);
> +}
> +
>  static uint64_t get_utc_date_time_insec(AVFormatContext *s, const char 
> *datetime)
>  {
>  struct tm timeinfo;
> @@ -392,7 +397,9 @@ static int open_url(AVFormatContext *s, AVIOContext **pb, 
> const char *url,
>  else if (strcmp(proto_name, "file") || !strncmp(url, "file,", 5))
>  return AVERROR_INVALIDDATA;
>
> -ret = s->io_open(s, pb, url, AVIO_FLAG_READ, &tmp);
> +av_freep(pb);
> +ret = avio_open2(pb, url, AVIO_FLAG_READ, c->interrupt_callback, &tmp);
> +
>  if (ret >= 0) {
>  // update cookies on http response with setcookies.
>  char *new_cookies = NULL;
> @@ -639,6 +646,86 @@ static int 
> parse_manifest_segmenttimeline(AVFormatContext *s, struct representat
>  return 0;
>  }
>
> +static int resolve_content_path(AVFormatContext *s, const char *url,  
> xmlNodePtr *baseurl_nodes,  int n_baseurl_nodes) {
> +
> +int i;
> +char *text;
> +char *tmp_str = av_mallocz(MAX_URL_SIZE);
> +char *tmp_str_2= av_mallocz(MAX_URL_SIZE);
> +
> +char *path = av_mallocz(MAX_URL_SIZE);
> +int nameSize = 0;
> +int updated = 0;
> +
> +if (!tmp_str || !tmp_str_2 || !path) {
> +updated = AVERROR(ENOMEM);
> +goto end;
> +}
> +
> +av_strlcpy(tmp_str, url, strlen(url)+1);
> +char *mpdName = strtok (tmp_str," /");
> +
> +while ((mpdName =strtok (NULL, "/"))) {
> +nameSize = strlen(mpdName);
> +}
> +
> +av_strlcpy (path, url, strlen(url)-nameSize+1);
> +
> +int rootId = 0;
> +xmlNodePtr  *node = NULL;
> +for (rootId = n_baseurl_nodes-1; rootId >0; rootId--) {
> +if (!(node = baseurl_nodes[rootId])) {
> +continue;
> +}
> +if (ishttp(xmlNodeGetContent(node))) {
> +break;
> +}
> +}
> +
> +node = baseurl_nodes[rootId];
> +char *baseurl = xmlNodeGetContent(node);
> +char *root_url = (!av_strcasecmp(baseurl, ""))? path: baseurl;
> +
> +if (node) {
> +xmlNodeSetContent(node, root_url);
> +}
> +
> +int size = strlen(root_url);
> +char *isRootHttp = ishttp(root_url);
> +
> +char token ='/';
> +if (root_url[size] == token) {
> +av_strlcat(root_url, "/", size+2);
> +size+=2;
> +}
> +
> +for (i = 0; i < n_baseurl_nodes; ++i) {
> +if (i == rootId) {
> +continue;
> +}
> +text = xmlNodeGetContent(baseurl_nodes[i]);
> +if (text) {
> +memset(tmp_str, 0, strlen(tmp_str));
> +
> +if (!ishttp(text) && isRootHttp) {
> +av_strlcpy(tmp_str, root_url, size+1);
> +}
> +int start = (text[0]==token) ? 1: 0;
> +memset(tmp_str_2, 0, strlen(tmp_str_2));
> +av_strlcat(tmp_str, text+start, MAX_URL_SIZE);
> +xmlFree(text);
> +xmlNodeSetContent(baseurl_nodes[i], tmp_str);
> +updated = 1;
> +}
> +}
> +
> +end:
> +av_free(path);
> +av_free(tmp_str);
> +av_free(tmp_str_2);
> +return updated;
> +
> +}
>  static int parse_manifest_representation(AVFormatContext *s, const char *url,
>   xmlNodePtr node,
>   xmlNodePtr adaptionset_node,
> @@ -698,6 +785,12 @@ static int parse_manifest_representation(AVFormatContext 
> *s, const char *url,
>  baseurl_nodes[2] = adaptionset_baseurl_node;
>  baseurl_nodes[3] = representation_baseurl_node;
>
> +ret = resolve_content_path(s, url, baseurl_nodes, 4);
> +
> +if (ret == AVERROR(ENOMEM) || ret == 0) {
> +goto end;
> +}
> +
>  if (representation_segmenttemplate_node || fragment_template_node) {
>  fragment_timeline_node = NULL;
>  fragment_templates_tab[0] = representation_segmenttemplate_node;
> @@ -993,6 +1086,9 @@ static int parse_manifest(AVFormatContext *s, const char 
> *url, AVIOContext *in)
>  }
>
>  mpd_baseurl_node = find_child_node_by_name(node, "BaseURL");
> +if (!mpd_baseurl_node) {
> +mpd_baseurl_node = xmlNewNode(node, "BaseURL");
> +}
>
>  // at now we can handle only one period, with the longest duration
>  node = xmlFirstElementChild(node);
> @@ -1315,6 +1411,7 @@ static int read_from_url(struct representation *pls, 
> struct fragment

[FFmpeg-devel] [PATCH] libavformat/dashdec: Fix for ticket 6658 (Dash demuxer segfault) - Add function 'resolve_content_path' to propagate the baseURL from upper level nodes. * if no baseURL is availa

2017-12-05 Thread Colin NG
---
 libavformat/dashdec.c | 111 --
 1 file changed, 98 insertions(+), 13 deletions(-)

diff --git a/libavformat/dashdec.c b/libavformat/dashdec.c
index 3798649..6e35e91 100644
--- a/libavformat/dashdec.c
+++ b/libavformat/dashdec.c
@@ -148,6 +148,11 @@ static uint64_t get_current_time_in_sec(void)
 return  av_gettime() / 100;
 }
 
+static char * ishttp(char *url) {
+char *proto_name = avio_find_protocol_name(url);
+return av_strstart(proto_name, "http", NULL);
+}
+
 static uint64_t get_utc_date_time_insec(AVFormatContext *s, const char 
*datetime)
 {
 struct tm timeinfo;
@@ -392,7 +397,9 @@ static int open_url(AVFormatContext *s, AVIOContext **pb, 
const char *url,
 else if (strcmp(proto_name, "file") || !strncmp(url, "file,", 5))
 return AVERROR_INVALIDDATA;
 
-ret = s->io_open(s, pb, url, AVIO_FLAG_READ, &tmp);
+av_freep(pb);
+ret = avio_open2(pb, url, AVIO_FLAG_READ, c->interrupt_callback, &tmp);
+
 if (ret >= 0) {
 // update cookies on http response with setcookies.
 char *new_cookies = NULL;
@@ -639,6 +646,86 @@ static int parse_manifest_segmenttimeline(AVFormatContext 
*s, struct representat
 return 0;
 }
 
+static int resolve_content_path(AVFormatContext *s, const char *url,  
xmlNodePtr *baseurl_nodes,  int n_baseurl_nodes) {
+
+int i;
+char *text;
+char *tmp_str = av_mallocz(MAX_URL_SIZE);
+char *tmp_str_2= av_mallocz(MAX_URL_SIZE);
+
+char *path = av_mallocz(MAX_URL_SIZE);
+int nameSize = 0;
+int updated = 0;
+
+if (!tmp_str || !tmp_str_2 || !path) {
+updated = AVERROR(ENOMEM);
+goto end;
+}
+
+av_strlcpy(tmp_str, url, strlen(url)+1);
+char *mpdName = strtok (tmp_str," /");
+
+while ((mpdName =strtok (NULL, "/"))) {
+nameSize = strlen(mpdName);
+}
+
+av_strlcpy (path, url, strlen(url)-nameSize+1);
+
+int rootId = 0;
+xmlNodePtr  *node = NULL;
+for (rootId = n_baseurl_nodes-1; rootId >0; rootId--) {
+if (!(node = baseurl_nodes[rootId])) {
+continue;
+}
+if (ishttp(xmlNodeGetContent(node))) {
+break;
+}
+}
+
+node = baseurl_nodes[rootId];
+char *baseurl = xmlNodeGetContent(node);
+char *root_url = (!av_strcasecmp(baseurl, ""))? path: baseurl;
+
+if (node) {
+xmlNodeSetContent(node, root_url);
+}
+
+int size = strlen(root_url);
+char *isRootHttp = ishttp(root_url);
+
+char token ='/';
+if (root_url[size] == token) {
+av_strlcat(root_url, "/", size+2);
+size+=2;
+}
+
+for (i = 0; i < n_baseurl_nodes; ++i) {
+if (i == rootId) {
+continue;
+}
+text = xmlNodeGetContent(baseurl_nodes[i]);
+if (text) {
+memset(tmp_str, 0, strlen(tmp_str));
+
+if (!ishttp(text) && isRootHttp) {
+av_strlcpy(tmp_str, root_url, size+1);
+}
+int start = (text[0]==token) ? 1: 0;
+memset(tmp_str_2, 0, strlen(tmp_str_2));
+av_strlcat(tmp_str, text+start, MAX_URL_SIZE);
+xmlFree(text);
+xmlNodeSetContent(baseurl_nodes[i], tmp_str);
+updated = 1;
+}
+}
+
+end:
+av_free(path);
+av_free(tmp_str);
+av_free(tmp_str_2);
+return updated;
+
+}
 static int parse_manifest_representation(AVFormatContext *s, const char *url,
  xmlNodePtr node,
  xmlNodePtr adaptionset_node,
@@ -698,6 +785,12 @@ static int parse_manifest_representation(AVFormatContext 
*s, const char *url,
 baseurl_nodes[2] = adaptionset_baseurl_node;
 baseurl_nodes[3] = representation_baseurl_node;
 
+ret = resolve_content_path(s, url, baseurl_nodes, 4);
+
+if (ret == AVERROR(ENOMEM) || ret == 0) {
+goto end;
+}
+
 if (representation_segmenttemplate_node || fragment_template_node) {
 fragment_timeline_node = NULL;
 fragment_templates_tab[0] = representation_segmenttemplate_node;
@@ -993,6 +1086,9 @@ static int parse_manifest(AVFormatContext *s, const char 
*url, AVIOContext *in)
 }
 
 mpd_baseurl_node = find_child_node_by_name(node, "BaseURL");
+if (!mpd_baseurl_node) {
+mpd_baseurl_node = xmlNewNode(node, "BaseURL");
+}
 
 // at now we can handle only one period, with the longest duration
 node = xmlFirstElementChild(node);
@@ -1315,6 +1411,7 @@ static int read_from_url(struct representation *pls, 
struct fragment *seg,
 } else {
 ret = avio_read(pls->input, buf, buf_size);
 }
+
 if (ret > 0)
 pls->cur_seg_offset += ret;
 
@@ -1343,18 +1440,6 @@ static int open_input(DASHContext *c, struct 
representation *pls, struct fragmen
 goto cleanup;
 }
 
-/* Seek to the requested position. If this 

Re: [FFmpeg-devel] [PATCH] libavformat/dashdec: Fix for ticket 6658 (Dash demuxer segfault)

2017-12-05 Thread Colin NG


From: ffmpeg-devel  on behalf of Steven Liu 

Sent: December 4, 2017 4:52 AM
To: FFmpeg development discussions and patches
Subject: Re: [FFmpeg-devel] [PATCH] libavformat/dashdec: Fix for ticket 6658 
(Dash demuxer segfault)

2017-12-04 12:28 GMT+08:00 Colin NG :
> ---
>  libavformat/dashdec.c | 112 
> --
>  1 file changed, 99 insertions(+), 13 deletions(-)
>
> diff --git a/libavformat/dashdec.c b/libavformat/dashdec.c
> index 3798649..d04bec0 100644
> --- a/libavformat/dashdec.c
> +++ b/libavformat/dashdec.c
> @@ -148,6 +148,11 @@ static uint64_t get_current_time_in_sec(void)
>  return  av_gettime() / 100;
>  }
>
> +static char * ishttp(char *url) {
> +char *proto_name = avio_find_protocol_name(url);
> +return av_strstart(proto_name, "http", NULL);
> +}
> +
>  static uint64_t get_utc_date_time_insec(AVFormatContext *s, const char 
> *datetime)
>  {
>  struct tm timeinfo;
> @@ -392,7 +397,9 @@ static int open_url(AVFormatContext *s, AVIOContext **pb, 
> const char *url,
>  else if (strcmp(proto_name, "file") || !strncmp(url, "file,", 5))
>  return AVERROR_INVALIDDATA;
>
> -ret = s->io_open(s, pb, url, AVIO_FLAG_READ, &tmp);
> +av_freep(pb);
> +ret = avio_open2(pb, url, AVIO_FLAG_READ, c->interrupt_callback, &tmp);
> +
>  if (ret >= 0) {
>  // update cookies on http response with setcookies.
>  char *new_cookies = NULL;
> @@ -639,6 +646,87 @@ static int 
> parse_manifest_segmenttimeline(AVFormatContext *s, struct representat
>  return 0;
>  }
>
> +static int resolve_content_path(AVFormatContext *s, const char *url,  
> xmlNodePtr *baseurl_nodes,  int n_baseurl_nodes) {
> +
> +int i;
> +char *text;
> +char *tmp_str = av_mallocz(MAX_URL_SIZE);
> +char *tmp_str_2= av_mallocz(MAX_URL_SIZE);
> +
> +char *path = av_mallocz(MAX_URL_SIZE);
> +int nameSize = 0;
> +int updated = 0;
> +
> +if (!tmp_str || !tmp_str_2 || !path) {
> +updated = AVERROR(ENOMEM);
> +goto end;
> +}
> +
> +av_strlcpy(tmp_str, url, strlen(url)+1);
> +char *mpdName = strtok (tmp_str," /");
> +
> +while ((mpdName =strtok (NULL, "/"))) {
What dose this do?
The above instruction will split the url (i.e. url of the mpd file) elements 
with "/" separator in between.

> +nameSize = strlen(mpdName);
> +}
> +
> +av_strlcpy (path, url, strlen(url)-nameSize+1);
> +
> +int rootId = 0;
> +xmlNodePtr  *node = NULL;
> +for (rootId = n_baseurl_nodes-1; rootId >0; rootId--) {
> +if (!(node = baseurl_nodes[rootId])) {
> +continue;
> +}
> +if (ishttp(xmlNodeGetContent(node))) {
> +break;
> +}
> +}
> +
> +node = baseurl_nodes[rootId];
> +char *baseurl = xmlNodeGetContent(node);
> +char *root_url = (!av_strcasecmp(baseurl, ""))? path: baseurl;
> +
> +if (node) {
> +xmlNodeSetContent(node, root_url);
> +}
> +
> +int size = strlen(root_url);
> +char *isRootHttp= ishttp(root_url);
> +
> +char token ='/';
> +//if (root_url[size-1]==token) {
> +if (av_strncasecmp(&root_url[size-1],&token, 1) != 0) {
If this only compare 1 char, why don't use root_url[size-1] == token ?
> +av_strlcat(root_url, "/", size+2);
> +size+=2;
> +}
> +
> +for (i = 0; i < n_baseurl_nodes; ++i) {
> +if (i==rootId) {
> +continue;
> +}
> +text = xmlNodeGetContent(baseurl_nodes[i]);
> +if (text) {
> +memset(tmp_str, 0, strlen(tmp_str));
> +
> +if (!ishttp(text) && isRootHttp) {
> +av_strlcpy(tmp_str, root_url, size+1);
> +}
> +int start = (text[0]==token) ? 1: 0;
> +memset(tmp_str_2, 0, strlen(tmp_str_2));
> +av_strlcat(tmp_str, text+start, MAX_URL_SIZE);
> +xmlFree(text);
> +xmlNodeSetContent(baseurl_nodes[i], tmp_str);
> +updated = 1;
> +}
> +}
> +
> +end:
> +av_free(path);
> +av_free(tmp_str);
> +av_free(tmp_str_2);
> +return updated;
> +
> +}
>  static int parse_manifest_representation(AVFormatContext *s, const char *url,
>   xmlNodePtr node,
>   xmlNodePtr adaptionset_node,
> @@ -698,6 +786,12 @@ static int parse_manifest_r

Re: [FFmpeg-devel] [PATCH] libavformat/dashdec: Fix for ticket 6658 (Dash demuxer segfault)

2017-12-04 Thread Derek Buitenhuis
On 12/4/2017 4:28 AM, Colin NG wrote:
> ---
>  libavformat/dashdec.c | 112 
> --
>  1 file changed, 99 insertions(+), 13 deletions(-)

Please describe what is actually being changed, and why, in the
commit message. It is both hard to review with no description,
and incredibly annoying to git blame later, without a proper
commit message. For example, a bunch of these changes seem
pretty disparate, hence my 'Why?' after several.

> +static char * ishttp(char *url) {
> +char *proto_name = avio_find_protocol_name(url);
> +return av_strstart(proto_name, "http", NULL);
> +}

Is the URL guaranteed to have a known, and enabled (in avforma) protocol?
If not, then this can crash, because avio_find_procotol_name will return
NULL.

> -ret = s->io_open(s, pb, url, AVIO_FLAG_READ, &tmp);
> +av_freep(pb);
> +ret = avio_open2(pb, url, AVIO_FLAG_READ, c->interrupt_callback, &tmp);

Why?
 
> +static int resolve_content_path(AVFormatContext *s, const char *url,  
> xmlNodePtr *baseurl_nodes,  int n_baseurl_nodes) {
> +
> +int i;
> +char *text;
> +char *tmp_str = av_mallocz(MAX_URL_SIZE);
> +char *tmp_str_2= av_mallocz(MAX_URL_SIZE);
> +
> +char *path = av_mallocz(MAX_URL_SIZE);

If the size is known (and not massive), why are these heap allocations?

> +int nameSize = 0;
> +int updated = 0;
> +
> +if (!tmp_str || !tmp_str_2 || !path) {
> +updated = AVERROR(ENOMEM);
> +goto end;
> +}
> +
> +av_strlcpy(tmp_str, url, strlen(url)+1);
> +char *mpdName = strtok (tmp_str," /");

Don't mix declarations and code.

> +
> +while ((mpdName =strtok (NULL, "/"))) {
> +nameSize = strlen(mpdName);
> +}
> +
> +av_strlcpy (path, url, strlen(url)-nameSize+1);
> +
> +int rootId = 0;
> +xmlNodePtr  *node = NULL;

Ditto.

> +for (rootId = n_baseurl_nodes-1; rootId >0; rootId--) {
> +if (!(node = baseurl_nodes[rootId])) {
> +continue;
> +}
> +if (ishttp(xmlNodeGetContent(node))) {
> +break;
> +}
> +}
> +
> +node = baseurl_nodes[rootId];
> +char *baseurl = xmlNodeGetContent(node);
> +char *root_url = (!av_strcasecmp(baseurl, ""))? path: baseurl;

Ditto.

Also should all of these calls to the XML lib have checks? My gut says 'yes'.

> +
> +if (node) {
> +xmlNodeSetContent(node, root_url);
> +}
> +
> +int size = strlen(root_url);
> +char *isRootHttp= ishttp(root_url);
> +
> +char token ='/';

Ditto.

> +//if (root_url[size-1]==token) {
> +if (av_strncasecmp(&root_url[size-1],&token, 1) != 0) {
> +av_strlcat(root_url, "/", size+2);
> +size+=2;
> +}
> +
> +for (i = 0; i < n_baseurl_nodes; ++i) {
> +if (i==rootId) {
> +continue;
> +}
> +text = xmlNodeGetContent(baseurl_nodes[i]);
> +if (text) {
> +memset(tmp_str, 0, strlen(tmp_str));
> +
> +if (!ishttp(text) && isRootHttp) {
> +av_strlcpy(tmp_str, root_url, size+1);
> +}
> +int start = (text[0]==token) ? 1: 0;

Mixed code and variable declarations. Also, redundant ternary operation.

> +memset(tmp_str_2, 0, strlen(tmp_str_2));
> +av_strlcat(tmp_str, text+start, MAX_URL_SIZE);
> +xmlFree(text);
> +xmlNodeSetContent(baseurl_nodes[i], tmp_str);
> +updated = 1;

What's with the odd 0/1 return values, which are not even
checked anywhere?

> +}
> +}
> +
> +end:
> +av_free(path);
> +av_free(tmp_str);
> +av_free(tmp_str_2);
> +return updated;
> +
> +}
>  static int parse_manifest_representation(AVFormatContext *s, const char *url,
>   xmlNodePtr node,
>   xmlNodePtr adaptionset_node,
> @@ -698,6 +786,12 @@ static int parse_manifest_representation(AVFormatContext 
> *s, const char *url,
>  baseurl_nodes[2] = adaptionset_baseurl_node;
>  baseurl_nodes[3] = representation_baseurl_node;
>  
> +ret = resolve_content_path(s, url, baseurl_nodes, 4);
> +
> +if (ret == AVERROR(ENOMEM)) {
> +goto end;
> +}

This kind of check seems very wrong. Check for ret < 0.

>  mpd_baseurl_node = find_child_node_by_name(node, "BaseURL");
> +if (!mpd_baseurl_node) {
> +mpd_baseurl_node = xmlNewNode(node, "BaseURL");
> +}

Why? Also missing check for xmlNewNode ret value?

>  
>  // at now we can handle only one period, with the longest duration
>  node = xmlFirstElementChild(node);
> @@ -1315,6 +1412,7 @@ static int read_from_url(struct representation *pls, 
> struct fragment *seg,
>  } else {
>  ret = avio_read(pls->input, buf, buf_size);
>  }
> +
>  if (ret > 0)

Stray change.

> -/* Seek to the requested position. If this was a HTTP request, the of

Re: [FFmpeg-devel] [PATCH] libavformat/dashdec: Fix for ticket 6658 (Dash demuxer segfault)

2017-12-04 Thread Steven Liu
2017-12-04 12:28 GMT+08:00 Colin NG :
> ---
>  libavformat/dashdec.c | 112 
> --
>  1 file changed, 99 insertions(+), 13 deletions(-)
>
> diff --git a/libavformat/dashdec.c b/libavformat/dashdec.c
> index 3798649..d04bec0 100644
> --- a/libavformat/dashdec.c
> +++ b/libavformat/dashdec.c
> @@ -148,6 +148,11 @@ static uint64_t get_current_time_in_sec(void)
>  return  av_gettime() / 100;
>  }
>
> +static char * ishttp(char *url) {
> +char *proto_name = avio_find_protocol_name(url);
> +return av_strstart(proto_name, "http", NULL);
> +}
> +
>  static uint64_t get_utc_date_time_insec(AVFormatContext *s, const char 
> *datetime)
>  {
>  struct tm timeinfo;
> @@ -392,7 +397,9 @@ static int open_url(AVFormatContext *s, AVIOContext **pb, 
> const char *url,
>  else if (strcmp(proto_name, "file") || !strncmp(url, "file,", 5))
>  return AVERROR_INVALIDDATA;
>
> -ret = s->io_open(s, pb, url, AVIO_FLAG_READ, &tmp);
> +av_freep(pb);
> +ret = avio_open2(pb, url, AVIO_FLAG_READ, c->interrupt_callback, &tmp);
> +
>  if (ret >= 0) {
>  // update cookies on http response with setcookies.
>  char *new_cookies = NULL;
> @@ -639,6 +646,87 @@ static int 
> parse_manifest_segmenttimeline(AVFormatContext *s, struct representat
>  return 0;
>  }
>
> +static int resolve_content_path(AVFormatContext *s, const char *url,  
> xmlNodePtr *baseurl_nodes,  int n_baseurl_nodes) {
> +
> +int i;
> +char *text;
> +char *tmp_str = av_mallocz(MAX_URL_SIZE);
> +char *tmp_str_2= av_mallocz(MAX_URL_SIZE);
> +
> +char *path = av_mallocz(MAX_URL_SIZE);
> +int nameSize = 0;
> +int updated = 0;
> +
> +if (!tmp_str || !tmp_str_2 || !path) {
> +updated = AVERROR(ENOMEM);
> +goto end;
> +}
> +
> +av_strlcpy(tmp_str, url, strlen(url)+1);
> +char *mpdName = strtok (tmp_str," /");
> +
> +while ((mpdName =strtok (NULL, "/"))) {
What dose this do?

> +nameSize = strlen(mpdName);
> +}
> +
> +av_strlcpy (path, url, strlen(url)-nameSize+1);
> +
> +int rootId = 0;
> +xmlNodePtr  *node = NULL;
> +for (rootId = n_baseurl_nodes-1; rootId >0; rootId--) {
> +if (!(node = baseurl_nodes[rootId])) {
> +continue;
> +}
> +if (ishttp(xmlNodeGetContent(node))) {
> +break;
> +}
> +}
> +
> +node = baseurl_nodes[rootId];
> +char *baseurl = xmlNodeGetContent(node);
> +char *root_url = (!av_strcasecmp(baseurl, ""))? path: baseurl;
> +
> +if (node) {
> +xmlNodeSetContent(node, root_url);
> +}
> +
> +int size = strlen(root_url);
> +char *isRootHttp= ishttp(root_url);
> +
> +char token ='/';
> +//if (root_url[size-1]==token) {
> +if (av_strncasecmp(&root_url[size-1],&token, 1) != 0) {
If this only compare 1 char, why don't use root_url[size-1] == token ?
> +av_strlcat(root_url, "/", size+2);
> +size+=2;
> +}
> +
> +for (i = 0; i < n_baseurl_nodes; ++i) {
> +if (i==rootId) {
> +continue;
> +}
> +text = xmlNodeGetContent(baseurl_nodes[i]);
> +if (text) {
> +memset(tmp_str, 0, strlen(tmp_str));
> +
> +if (!ishttp(text) && isRootHttp) {
> +av_strlcpy(tmp_str, root_url, size+1);
> +}
> +int start = (text[0]==token) ? 1: 0;
> +memset(tmp_str_2, 0, strlen(tmp_str_2));
> +av_strlcat(tmp_str, text+start, MAX_URL_SIZE);
> +xmlFree(text);
> +xmlNodeSetContent(baseurl_nodes[i], tmp_str);
> +updated = 1;
> +}
> +}
> +
> +end:
> +av_free(path);
> +av_free(tmp_str);
> +av_free(tmp_str_2);
> +return updated;
> +
> +}
>  static int parse_manifest_representation(AVFormatContext *s, const char *url,
>   xmlNodePtr node,
>   xmlNodePtr adaptionset_node,
> @@ -698,6 +786,12 @@ static int parse_manifest_representation(AVFormatContext 
> *s, const char *url,
>  baseurl_nodes[2] = adaptionset_baseurl_node;
>  baseurl_nodes[3] = representation_baseurl_node;
>
> +ret = resolve_content_path(s, url, baseurl_nodes, 4);
> +
> +if (ret == AVERROR(ENOMEM)) {
What about ret < 0 ?
> +goto end;
> +}
> +
>  if (representation_segmenttemplate_node || fragment_template_node) {
>  fragment_timeline_node = NULL;
>  fragment_templates_tab[0] = representation_segmenttemplate_node;
> @@ -993,6 +1087,9 @@ static int parse_manifest(AVFormatContext *s, const char 
> *url, AVIOContext *in)
>  }
>
>  mpd_baseurl_node = find_child_node_by_name(node, "BaseURL");
> +if (!mpd_baseurl_node) {
> +mpd_baseurl_node = xmlNewNode(node, "BaseURL");
> +}
>
>  // at now we can handle only one period, with

[FFmpeg-devel] [PATCH] libavformat/dashdec: Fix for ticket 6658 (Dash demuxer segfault)

2017-12-03 Thread Colin NG
---
 libavformat/dashdec.c | 112 --
 1 file changed, 99 insertions(+), 13 deletions(-)

diff --git a/libavformat/dashdec.c b/libavformat/dashdec.c
index 3798649..d04bec0 100644
--- a/libavformat/dashdec.c
+++ b/libavformat/dashdec.c
@@ -148,6 +148,11 @@ static uint64_t get_current_time_in_sec(void)
 return  av_gettime() / 100;
 }
 
+static char * ishttp(char *url) {
+char *proto_name = avio_find_protocol_name(url);
+return av_strstart(proto_name, "http", NULL);
+}
+
 static uint64_t get_utc_date_time_insec(AVFormatContext *s, const char 
*datetime)
 {
 struct tm timeinfo;
@@ -392,7 +397,9 @@ static int open_url(AVFormatContext *s, AVIOContext **pb, 
const char *url,
 else if (strcmp(proto_name, "file") || !strncmp(url, "file,", 5))
 return AVERROR_INVALIDDATA;
 
-ret = s->io_open(s, pb, url, AVIO_FLAG_READ, &tmp);
+av_freep(pb);
+ret = avio_open2(pb, url, AVIO_FLAG_READ, c->interrupt_callback, &tmp);
+
 if (ret >= 0) {
 // update cookies on http response with setcookies.
 char *new_cookies = NULL;
@@ -639,6 +646,87 @@ static int parse_manifest_segmenttimeline(AVFormatContext 
*s, struct representat
 return 0;
 }
 
+static int resolve_content_path(AVFormatContext *s, const char *url,  
xmlNodePtr *baseurl_nodes,  int n_baseurl_nodes) {
+
+int i;
+char *text;
+char *tmp_str = av_mallocz(MAX_URL_SIZE);
+char *tmp_str_2= av_mallocz(MAX_URL_SIZE);
+
+char *path = av_mallocz(MAX_URL_SIZE);
+int nameSize = 0;
+int updated = 0;
+
+if (!tmp_str || !tmp_str_2 || !path) {
+updated = AVERROR(ENOMEM);
+goto end;
+}
+
+av_strlcpy(tmp_str, url, strlen(url)+1);
+char *mpdName = strtok (tmp_str," /");
+
+while ((mpdName =strtok (NULL, "/"))) {
+nameSize = strlen(mpdName);
+}
+
+av_strlcpy (path, url, strlen(url)-nameSize+1);
+
+int rootId = 0;
+xmlNodePtr  *node = NULL;
+for (rootId = n_baseurl_nodes-1; rootId >0; rootId--) {
+if (!(node = baseurl_nodes[rootId])) {
+continue;
+}
+if (ishttp(xmlNodeGetContent(node))) {
+break;
+}
+}
+
+node = baseurl_nodes[rootId];
+char *baseurl = xmlNodeGetContent(node);
+char *root_url = (!av_strcasecmp(baseurl, ""))? path: baseurl;
+
+if (node) {
+xmlNodeSetContent(node, root_url);
+}
+
+int size = strlen(root_url);
+char *isRootHttp= ishttp(root_url);
+
+char token ='/';
+//if (root_url[size-1]==token) {
+if (av_strncasecmp(&root_url[size-1],&token, 1) != 0) {
+av_strlcat(root_url, "/", size+2);
+size+=2;
+}
+
+for (i = 0; i < n_baseurl_nodes; ++i) {
+if (i==rootId) {
+continue;
+}
+text = xmlNodeGetContent(baseurl_nodes[i]);
+if (text) {
+memset(tmp_str, 0, strlen(tmp_str));
+
+if (!ishttp(text) && isRootHttp) {
+av_strlcpy(tmp_str, root_url, size+1);
+}
+int start = (text[0]==token) ? 1: 0;
+memset(tmp_str_2, 0, strlen(tmp_str_2));
+av_strlcat(tmp_str, text+start, MAX_URL_SIZE);
+xmlFree(text);
+xmlNodeSetContent(baseurl_nodes[i], tmp_str);
+updated = 1;
+}
+}
+
+end:
+av_free(path);
+av_free(tmp_str);
+av_free(tmp_str_2);
+return updated;
+
+}
 static int parse_manifest_representation(AVFormatContext *s, const char *url,
  xmlNodePtr node,
  xmlNodePtr adaptionset_node,
@@ -698,6 +786,12 @@ static int parse_manifest_representation(AVFormatContext 
*s, const char *url,
 baseurl_nodes[2] = adaptionset_baseurl_node;
 baseurl_nodes[3] = representation_baseurl_node;
 
+ret = resolve_content_path(s, url, baseurl_nodes, 4);
+
+if (ret == AVERROR(ENOMEM)) {
+goto end;
+}
+
 if (representation_segmenttemplate_node || fragment_template_node) {
 fragment_timeline_node = NULL;
 fragment_templates_tab[0] = representation_segmenttemplate_node;
@@ -993,6 +1087,9 @@ static int parse_manifest(AVFormatContext *s, const char 
*url, AVIOContext *in)
 }
 
 mpd_baseurl_node = find_child_node_by_name(node, "BaseURL");
+if (!mpd_baseurl_node) {
+mpd_baseurl_node = xmlNewNode(node, "BaseURL");
+}
 
 // at now we can handle only one period, with the longest duration
 node = xmlFirstElementChild(node);
@@ -1315,6 +1412,7 @@ static int read_from_url(struct representation *pls, 
struct fragment *seg,
 } else {
 ret = avio_read(pls->input, buf, buf_size);
 }
+
 if (ret > 0)
 pls->cur_seg_offset += ret;
 
@@ -1343,18 +1441,6 @@ static int open_input(DASHContext *c, struct 
representation *pls, struct fragmen
 goto cleanup;
 }