[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 c...

Steven Liu lingjiujianke at gmail.com
Wed Dec 6 04:39:45 EET 2017


2017-12-06 9:42 GMT+08:00 Colin NG <colin_ng at hotmail.com>:
> ---
>  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() / 1000000;
>  }
>
> +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 was a HTTP request, the offset
> -     * should already be where want it to, but this allows e.g. local testing
> -     * without a HTTP server. */
> -    if (!ret && seg->url_offset) {
> -        int64_t seekret = avio_seek(pls->input, seg->url_offset, SEEK_SET);
> -        if (seekret < 0) {
> -            av_log(pls->parent, AV_LOG_ERROR, "Unable to seek to offset %"PRId64" of DASH fragment '%s'\n", seg->url_offset, seg->url);
> -            ret = (int) seekret;
> -            ff_format_io_close(pls->parent, &pls->input);
> -        }
> -    }
> -
>  cleanup:
>      av_dict_free(&opts);
>      pls->cur_seg_offset = 0;
> --
> 2.7.4
>

As Derek Buitenhuis suggestion, you can fix the "mix declarations and
code", for example, move the declarations to the top of the function,
and make the name clearly.
And check the xml functions call return value.



Thanks

Steven


More information about the ffmpeg-devel mailing list