vlc | branch: master | Hugo Beauzée-Luyssen <[email protected]> | Thu Jan 5 17:11:01 2012 +0100| [c4851d5ce5b5e8d83b4b5135de2d9ee475ce4d3e] | committer: Jean-Baptiste Kempf
dash: Handle UrlTemplate in parser. Signed-off-by: Jean-Baptiste Kempf <[email protected]> > http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=c4851d5ce5b5e8d83b4b5135de2d9ee475ce4d3e --- modules/stream_filter/dash/mpd/BasicCMParser.cpp | 106 ++++++++++++++++++++-- modules/stream_filter/dash/mpd/BasicCMParser.h | 6 +- 2 files changed, 100 insertions(+), 12 deletions(-) diff --git a/modules/stream_filter/dash/mpd/BasicCMParser.cpp b/modules/stream_filter/dash/mpd/BasicCMParser.cpp index 7590f1d..ccfead6 100644 --- a/modules/stream_filter/dash/mpd/BasicCMParser.cpp +++ b/modules/stream_filter/dash/mpd/BasicCMParser.cpp @@ -28,10 +28,12 @@ #include "BasicCMParser.h" #include "mpd/ContentDescription.h" #include "mpd/SegmentInfoDefault.h" +#include "mpd/SegmentTemplate.h" #include "mpd/SegmentTimeline.h" #include <cstdlib> #include <sstream> +#include <sstream> #include <vlc_common.h> #include <vlc_stream.h> @@ -43,7 +45,8 @@ using namespace dash::xml; BasicCMParser::BasicCMParser( Node *root, stream_t *p_stream ) : root( root ), mpd( NULL ), - p_stream( p_stream ) + p_stream( p_stream ), + currentRepresentation( NULL ) { this->url = p_stream->psz_access; this->url += "://"; @@ -297,6 +300,7 @@ void BasicCMParser::setRepresentations (Node *root, Group *group) Representation *rep = new Representation; rep->setParentGroup( group ); + this->currentRepresentation = rep; if ( this->parseCommonAttributesElements( representations.at( i ), rep, group ) == false ) { delete rep; @@ -374,21 +378,39 @@ bool BasicCMParser::setSegmentInfo (Node *root, Representation *rep) return false; } -bool BasicCMParser::parseSegment(Segment *seg, const std::map<std::string, std::string>& attr ) +Segment* BasicCMParser::parseSegment( Node* node ) { + const std::map<std::string, std::string> attr = node->getAttributes(); std::map<std::string, std::string>::const_iterator it; + bool isTemplate = false; + Segment* seg = NULL; + + if ( node->getName() == "UrlTemplate" ) + isTemplate = true; it = attr.find( "sourceURL" ); //FIXME: When not present, the sourceUrl attribute should be computed //using BaseURL and the range attribute. if ( it != attr.end() ) { std::string url = it->second; + bool runtimeToken = false; + if ( isTemplate == true ) + { + if ( this->resolveUrlTemplates( url, runtimeToken ) == false ) + { + std::cerr << "Failed to substitute URLTemplate identifier." << std::endl; + return NULL; + } + seg = new SegmentTemplate( runtimeToken, this->currentRepresentation ); + } + else + seg = new Segment; if ( url.find( this->p_stream->psz_access ) != 0 ) //Relative url url = this->url + url; seg->setSourceUrl( url ); } - return true; + return seg; } ProgramInformation* BasicCMParser::parseProgramInformation() @@ -423,28 +445,92 @@ void BasicCMParser::setInitSegment (Node *root, SegmentInfoCommon *info " other InitialisationSegmentURL will be dropped." << std::endl; if ( initSeg.size() == 1 ) { - Segment *seg = new Segment(); - parseSegment( seg, initSeg.at(0)->getAttributes() ); - info->setInitialisationSegment( seg ); + Segment *seg = parseSegment( initSeg.at(0) ); + if ( seg != NULL ) + info->setInitialisationSegment( seg ); } } bool BasicCMParser::setSegments (Node *root, SegmentInfo *info) { - std::vector<Node *> segments = DOMHelper::getElementByTagName(root, "Url", false); + std::vector<Node *> segments = DOMHelper::getElementByTagName( root, "Url", false ); + std::vector<Node *> segmentsTemplates = DOMHelper::getElementByTagName( root, "UrlTemplate", false ); - if ( segments.size() == 0 ) + if ( segments.size() == 0 && segmentsTemplates.size() == 0 ) return false; + segments.insert( segments.end(), segmentsTemplates.begin(), segmentsTemplates.end() ); for(size_t i = 0; i < segments.size(); i++) { - Segment *seg = new Segment(); - parseSegment( seg, segments.at(i)->getAttributes() ); + Segment* seg = parseSegment( segments.at( i ) ); + if ( seg == NULL ) + continue ; if ( seg->getSourceUrl().empty() == false ) info->addSegment(seg); } return true; } +bool BasicCMParser::resolveUrlTemplates( std::string &url, bool &containRuntimeToken ) +{ + size_t it = url.find( '$' ); + containRuntimeToken = false; + + while ( it != std::string::npos ) + { + size_t closing = url.find( '$', it + 1 ); + if ( closing == std::string::npos ) + { + std::cerr << "Unmatched '$' in url template: " << url << std::endl; + return false; + } + std::string token = std::string( url, it, closing - it + 1 ); + if ( token == "$$" ) + { + url.replace( it, token.length(), "$" ); + it = closing + 1; + } + else if ( token == "$RepresentationID$" ) + { + if ( this->currentRepresentation->getId().empty() == false ) + { + std::cerr << "Representation doesn't have an ID. Can't substitute" + " identifier $RepresentationID$" << std::endl; + return false; + } + url.replace( it, token.length(), this->currentRepresentation->getId() ); + it = it + this->currentRepresentation->getId().length(); + } + else if ( token == "$Bandwidth$" ) + { + if ( this->currentRepresentation->getBandwidth() < 0 ) + { + std::cerr << "Representation doesn't have a valid bandwidth. " + "Can't substitute tag $Bandwidth$" << std::endl; + return false; + } + std::ostringstream oss; + oss << this->currentRepresentation->getBandwidth(); + url.replace( it, token.length(), oss.str() ); + it = it + oss.str().length(); + } + else + { + if ( token == "$Index$" || token == "$Time$" ) + { + containRuntimeToken = true; + it = it + token.length(); + } + else + { + std::cout << "Unhandled token " << token << std::endl; + return false; + } + } + it = url.find( '$', it ); + } + return true; +} + MPD* BasicCMParser::getMPD() { return this->mpd; diff --git a/modules/stream_filter/dash/mpd/BasicCMParser.h b/modules/stream_filter/dash/mpd/BasicCMParser.h index 07de212..816da13 100644 --- a/modules/stream_filter/dash/mpd/BasicCMParser.h +++ b/modules/stream_filter/dash/mpd/BasicCMParser.h @@ -65,7 +65,8 @@ namespace dash void setRepresentations (dash::xml::Node *root, Group *group); bool setSegmentInfo (dash::xml::Node *root, Representation *rep); void setInitSegment (dash::xml::Node *root, SegmentInfoCommon *info); - bool setSegments (dash::xml::Node *root, SegmentInfo *info); + bool setSegments (dash::xml::Node *root, SegmentInfo *info ); + bool resolveUrlTemplates( std::string &url, bool &containRuntimeToken ); void setMPDBaseUrl (dash::xml::Node *root); void parseContentDescriptor( xml::Node *node, const std::string &name, void (CommonAttributesElements::*addPtr)(ContentDescription*), @@ -73,7 +74,7 @@ namespace dash bool parseCommonAttributesElements( dash::xml::Node *node, CommonAttributesElements *common, CommonAttributesElements *parent ) const; - bool parseSegment( Segment *seg, const std::map<std::string, std::string> &attr ); + Segment* parseSegment( xml::Node* node ); ProgramInformation* parseProgramInformation(); private: @@ -81,6 +82,7 @@ namespace dash MPD *mpd; std::string url; stream_t *p_stream; + Representation *currentRepresentation; }; } } _______________________________________________ vlc-commits mailing list [email protected] http://mailman.videolan.org/listinfo/vlc-commits
