[vlc-commits] dash: Handle UrlTemplate in parser.

Hugo Beauzée-Luyssen git at videolan.org
Tue Jan 24 23:22:02 CET 2012


vlc/vlc-1.2 | branch: master | Hugo Beauzée-Luyssen <beauze.h at gmail.com> | Thu Jan  5 17:11:01 2012 +0100| [504bed780c6f46c936f539dfb69d6947b0e061f7] | committer: Jean-Baptiste Kempf

dash: Handle UrlTemplate in parser.

Signed-off-by: Jean-Baptiste Kempf <jb at videolan.org>
(cherry picked from commit c4851d5ce5b5e8d83b4b5135de2d9ee475ce4d3e)

Signed-off-by: Jean-Baptiste Kempf <jb at videolan.org>

> http://git.videolan.org/gitweb.cgi/vlc/vlc-1.2.git/?a=commit;h=504bed780c6f46c936f539dfb69d6947b0e061f7
---

 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;
         };
     }
 }



More information about the vlc-commits mailing list