[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