[vlc-devel] upgrade MPEG DASH handling of relative URLs

Christopher Müller christopher.mueller at itec.uni-klu.ac.at
Tue Feb 14 23:11:10 CET 2012


> Von: vlc-devel-bounces at videolan.org [mailto:vlc-devel-
> bounces at videolan.org] Im Auftrag von Robert Forsman
> Gesendet: Dienstag, 14. Februar 2012 22:09
> An: vlc-devel at videolan.org
> Betreff: [vlc-devel] upgrade MPEG DASH handling of relative URLs
> 
> 
> I started with
> commit 1a459c1ccb0d617580ec97bae992f01a799a5e9b
> and applied the "download and buffer" patches for DASH
> 
> http://www-itec.uni-klu.ac.at/dash/?p=434
> 
> although I'm not sure which of the items on
> http://www-itec.uni-klu.ac.at/dash/?page_id=6 is the download and
> buffer patches, maybe they got retracted.
> 
> Anyway, I decided that VLC's DASH plugin was a little too inflexible in
> resolving URLs for media files, so I rehacked things a little.  I added
> logic to fall back on the URL of the MPD file in case the MPD had no
> <BaseURL> tags (which I anticipate will be 99% of MPDs in the future).

BaseUrls are very useful and I think that they will be very heavily used in
the future, also each example in the standard uses baseulrs and Netflix will
use them too ;).

Anyway your patch will break any MPD without a baseurl and absolute HTTP
urls in the segments.

> 
> 
> This is my first patch for VLC, and my first C++ in years, so you'll
> want to give it a shakedown.
> 
> 
> diff --git a/modules/stream_filter/dash/Modules.am
> b/modules/stream_filter/dash/Modules.am
> index 749dc52..c17d348 100644
> --- a/modules/stream_filter/dash/Modules.am
> +++ b/modules/stream_filter/dash/Modules.am
> @@ -22,6 +22,7 @@ SOURCES_stream_filter_dash = \
>      http/IHTTPConnection.h \
>      mpd/AdaptationSet.cpp \
>      mpd/AdaptationSet.h \
> +    mpd/BaseUrl.cpp \
>      mpd/BaseUrl.h \
>      mpd/BasicCMManager.cpp \
>      mpd/BasicCMManager.h \
> diff --git
> a/modules/stream_filter/dash/exceptions/MalformedURLException.h
> b/modules/stream_filter/dash/exceptions/MalformedURLException.h
> new file mode 100644
> index 0000000..41e989f
> --- /dev/null
> +++ b/modules/stream_filter/dash/exceptions/MalformedURLException.h
> @@ -0,0 +1,21 @@
> +
> +#ifndef MALFORMEDURLEXCEPTION_H_
> +#define MALFORMEDURLEXCEPTION_H_
> +
> +#include <stdexcept>
> +
> +namespace dash
> +{
> +    namespace exception
> +    {
> +        class MalformedURLException : public std::exception
> +	    {
> +		const char *message;
> +            public:
> +		MalformedURLException(const char *msg)  { message=msg; }
> +		const char * what() const throw() { return message; }
> +	    };
> +    }
> +}
> +
> +#endif /* MALFORMEDURLEXCEPTION_H_ */
> diff --git a/modules/stream_filter/dash/mpd/BaseUrl.cpp
> b/modules/stream_filter/dash/mpd/BaseUrl.cpp
> new file mode 100644
> index 0000000..bf07804
> --- /dev/null
> +++ b/modules/stream_filter/dash/mpd/BaseUrl.cpp
> @@ -0,0 +1,53 @@
> +#include "../exceptions/MalformedURLException.h"
> +#include "BaseUrl.h"
> +
> +
> +std::string  dash::mpd::BaseUrl::maybeRelative(std::string spec) const
> +{
> +    if (spec[0] == '/') {
> +	return protoHostPort()+spec;
> +
> +    } else if (hasProtocol(spec)) {
> +	return spec;
> +
> +    } else {
> +	int idx = url.rfind('/');
> +	if (idx<0)
> +	    throw dash::exception::MalformedURLException(url.c_str());
> +
> +	return url.substr(0, idx+1) + spec;
> +    }
> +}
> +
> +/**
> +returns the http://host:port without a trailing /  */ std::string
> +dash::mpd::BaseUrl::protoHostPort() const {
> +    int i1 = url.find("://");
> +    if (i1<0)
> +	throw dash::exception::MalformedURLException(url.c_str());
> +    int i2 = url.find('/', i1+3);
> +    if (i2<0)
> +	throw dash::exception::MalformedURLException(url.c_str());
> +
> +    return url.substr(0, i2);
> +}
> +
> +/**
> +   if spec matches /^[a-z]+:/ then it has a "protocol" on the front
> */
> +bool dash::mpd::BaseUrl::hasProtocol(const std::string &spec) {
> +    for (int i=0; i<spec.length(); i++) {
> +	char ch = spec[i];
> +	// yeah, I'm just faking it.  Maybe read the RFC later.
> +	if (ch == ':') {
> +	    return i>0;
> +	} else if ((ch<'a' || ch > 'z') && (ch < 'A' || ch > 'Z')) {
> +	    return false;
> +	}
> +    }
> +
> +    return false;
> +}
> diff --git a/modules/stream_filter/dash/mpd/BaseUrl.h
> b/modules/stream_filter/dash/mpd/BaseUrl.h
> index f7b5548..da1ef84 100644
> --- a/modules/stream_filter/dash/mpd/BaseUrl.h
> +++ b/modules/stream_filter/dash/mpd/BaseUrl.h
> @@ -38,7 +38,11 @@ namespace dash
>                  virtual ~BaseUrl()                  {}
> 
>                  const std::string& getUrl() const { return this->url;
> }
> +		std::string maybeRelative(std::string spec) const;
> 
> +		std::string protoHostPort() const;
> +
> +		static bool hasProtocol(const std::string&);
>              private:
>                  std::string url;
>          };
> diff --git a/modules/stream_filter/dash/mpd/BasicCMParser.cpp
> b/modules/stream_filter/dash/mpd/BasicCMParser.cpp
> index fc0b0ea..146eebc 100644
> --- a/modules/stream_filter/dash/mpd/BasicCMParser.cpp
> +++ b/modules/stream_filter/dash/mpd/BasicCMParser.cpp
> @@ -147,10 +147,18 @@ void    BasicCMParser::setMPDBaseUrl        (Node
> *root)
>  {
>      std::vector<Node *> baseUrls =
> DOMHelper::getChildElementByTagName(root, "BaseURL");
> 
> -    for(size_t i = 0; i < baseUrls.size(); i++)
> -    {
> -        BaseUrl *url = new BaseUrl(baseUrls.at(i)->getText());
> -        this->mpd->addBaseUrl(url);
> +    if (baseUrls.size() >0) {
> +
> +	for(size_t i = 0; i < baseUrls.size(); i++)
> +	    {
> +		BaseUrl *url = new BaseUrl(baseUrls.at(i)->getText());
> +		this->mpd->addBaseUrl(url);
> +	    }
> +    } else {
> +	std::string url_ = std::string(p_stream-
> >psz_access)+"://"+p_stream->psz_path;
> +	//url_ = url_.substr(0, url_.rfind('/')+1);
> +	BaseUrl *url = new BaseUrl(url_);
> +	this->mpd->addBaseUrl(url);
>      }
>  }
> 
> @@ -224,7 +232,15 @@ void BasicCMParser::parseSegmentInfoCommon(Node
> *node, SegmentInfoCommon *segmen
>              segmentInfo->appendBaseURL( (*it)->getText() );
>              ++it;
>          }
> +    } else {
> +	std::vector<BaseUrl*> inherited = mpd->getBaseUrls();
> +	std::vector<BaseUrl*>::const_iterator it = inherited.begin();
> +	std::vector<BaseUrl*>::const_iterator end = inherited.end();
> +	while (it != end) {
> +	    segmentInfo->appendBaseURL((*it)->getUrl());
> +	}
>      }
> +
>      std::map<std::string, std::string>::const_iterator  it =
> attr.begin();
> 
>      this->setInitSegment( node, segmentInfo ); diff --git
> a/modules/stream_filter/dash/mpd/IsoffMainParser.cpp
> b/modules/stream_filter/dash/mpd/IsoffMainParser.cpp
> index 888c347..87e3bcd 100644
> --- a/modules/stream_filter/dash/mpd/IsoffMainParser.cpp
> +++ b/modules/stream_filter/dash/mpd/IsoffMainParser.cpp
> @@ -79,10 +79,18 @@ void    IsoffMainParser::setMPDBaseUrl      ()
>  {
>      std::vector<Node *> baseUrls =
> DOMHelper::getChildElementByTagName(this->root, "BaseURL");
> 
> -    for(size_t i = 0; i < baseUrls.size(); i++)
> -    {
> -        BaseUrl *url = new BaseUrl(baseUrls.at(i)->getText());
> -        this->mpd->addBaseUrl(url);
> +    if (baseUrls.size() >0) {
> +
> +	for(size_t i = 0; i < baseUrls.size(); i++)
> +	    {
> +		BaseUrl *url = new BaseUrl(baseUrls.at(i)->getText());
> +		this->mpd->addBaseUrl(url);
> +	    }
> +    } else {
> +	std::string url_ = std::string(p_stream-
> >psz_access)+"://"+p_stream->psz_path;
> +	//url_ = url_.substr(0, url_.rfind('/')+1);
> +	BaseUrl *url = new BaseUrl(url_);
> +	this->mpd->addBaseUrl(url);
>      }
>  }
>  void    IsoffMainParser::setPeriods         ()
> diff --git a/modules/stream_filter/dash/mpd/Segment.cpp
> b/modules/stream_filter/dash/mpd/Segment.cpp
> index aa0f834..0959be4 100644
> --- a/modules/stream_filter/dash/mpd/Segment.cpp
> +++ b/modules/stream_filter/dash/mpd/Segment.cpp
> @@ -97,16 +97,13 @@ dash::http::Chunk*      Segment::toChunk        ()
> 
>      if(this->baseUrls.size() > 0)
>      {
> -        std::stringstream ss;
> -        ss << this->baseUrls.at(0)->getUrl() << this->sourceUrl;
> -        chunk->setUrl(ss.str());
> -        ss.clear();
> +	std::string resolved = this->baseUrls.at(0) ->maybeRelative(this-
> >sourceUrl) ;
> +        chunk->setUrl(resolved);
> 
>          for(size_t i = 1; i < this->baseUrls.size(); i++)
>          {
> -            ss << this->baseUrls.at(i)->getUrl() << this->sourceUrl;
> -            chunk->addOptionalUrl(ss.str());
> -            ss.clear();
> +	    resolved = this->baseUrls.at(i) ->maybeRelative(this-
> >sourceUrl);
> +            chunk->addOptionalUrl(resolved);
>          }
>      }
>      else
> _______________________________________________
> vlc-devel mailing list
> To unsubscribe or modify your subscription options:
> http://mailman.videolan.org/listinfo/vlc-devel





More information about the vlc-devel mailing list