[vlc-commits] demux: hls: handle alternative audio/groups

Francois Cartegnie git at videolan.org
Fri Jul 24 15:09:27 CEST 2015


vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Wed Jul 22 23:43:06 2015 +0200| [d8f1184ed876e3def6a180965f3d2225d68d517d] | committer: Francois Cartegnie

demux: hls: handle alternative audio/groups

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

 modules/demux/hls/playlist/Parser.cpp |   95 +++++++++++++++++++++++++++------
 1 file changed, 80 insertions(+), 15 deletions(-)

diff --git a/modules/demux/hls/playlist/Parser.cpp b/modules/demux/hls/playlist/Parser.cpp
index 6053d15..97d3342 100644
--- a/modules/demux/hls/playlist/Parser.cpp
+++ b/modules/demux/hls/playlist/Parser.cpp
@@ -35,6 +35,7 @@
 #include <vlc_stream.h>
 #include <cstdio>
 #include <sstream>
+#include <map>
 
 using namespace adaptative;
 using namespace adaptative::playlist;
@@ -78,12 +79,21 @@ void Parser::parseAdaptationSet(BasePeriod *period, const AttributesTag *)
     }
 }
 
-void Parser::parseRepresentation(BaseAdaptationSet *adaptSet, const AttributesTag * streaminftag)
+void Parser::parseRepresentation(BaseAdaptationSet *adaptSet, const AttributesTag * tag)
 {
-    if(!streaminftag->getAttributeByName("URI"))
+    if(!tag->getAttributeByName("URI"))
         return;
 
-    Url url = Url(streaminftag->getAttributeByName("URI")->value);
+    Url url;
+    if(tag->getType() == AttributesTag::EXTXMEDIA)
+    {
+        url = Url(tag->getAttributeByName("URI")->quotedString());
+    }
+    else
+    {
+        url = Url(tag->getAttributeByName("URI")->value);
+    }
+
     if(!url.hasScheme())
         url = url.prepend(adaptSet->getUrlSegment());
 
@@ -97,28 +107,37 @@ void Parser::parseRepresentation(BaseAdaptationSet *adaptSet, const AttributesTa
             std::list<Tag *> tagslist = parseEntries(substream);
             stream_Delete(substream);
 
-            parseRepresentation(adaptSet, streaminftag, tagslist);
+            parseRepresentation(adaptSet, tag, tagslist);
 
             releaseTagsList(tagslist);
         }
     }
 }
 
-void Parser::parseRepresentation(BaseAdaptationSet *adaptSet, const AttributesTag * streaminftag,
+void Parser::parseRepresentation(BaseAdaptationSet *adaptSet, const AttributesTag * tag,
                                  const std::list<Tag *> &tagslist)
 {
-    const Attribute *uriAttr = streaminftag->getAttributeByName("URI");
-    const Attribute *bwAttr = streaminftag->getAttributeByName("BANDWIDTH");
-    const Attribute *codecsAttr = streaminftag->getAttributeByName("CODECS");
+    const Attribute *uriAttr = tag->getAttributeByName("URI");
+    const Attribute *bwAttr = tag->getAttributeByName("BANDWIDTH");
+    const Attribute *codecsAttr = tag->getAttributeByName("CODECS");
 
     Representation *rep = new (std::nothrow) Representation(adaptSet);
     if(rep)
     {
         if(uriAttr)
         {
-            size_t pos = uriAttr->value.find_last_of('/');
+            std::string uri;
+            if(tag->getType() == AttributesTag::EXTXMEDIA)
+            {
+                uri = uriAttr->quotedString();
+            }
+            else
+            {
+                uri = uriAttr->value;
+            }
+            size_t pos = uri.find_last_of('/');
             if(pos != std::string::npos)
-                rep->baseUrl.Set(new Url(uriAttr->value.substr(0, pos+1)));
+                rep->baseUrl.Set(new Url(uri.substr(0, pos+1)));
         }
 
         if(bwAttr)
@@ -287,15 +306,61 @@ M3U8 * Parser::parse(const std::string &playlisturl)
     bool b_masterplaylist = !getTagsFromList(tagslist, AttributesTag::EXTXSTREAMINF).empty();
     if(b_masterplaylist)
     {
+        std::list<Tag *>::const_iterator it;
+        std::map<std::string, AttributesTag *> groupsmap;
+
+        /* We'll need to create an adaptation set for each media group / alternative rendering
+         * we create a list of playlist being and alternative/group */
+        std::list<Tag *> mediainfotags = getTagsFromList(tagslist, AttributesTag::EXTXMEDIA);
+        for(it = mediainfotags.begin(); it != mediainfotags.end(); ++it)
+        {
+            AttributesTag *tag = dynamic_cast<AttributesTag *>(*it);
+            if(tag && tag->getAttributeByName("URI"))
+            {
+                std::pair<std::string, AttributesTag *> pair(tag->getAttributeByName("URI")->quotedString(), tag);
+                groupsmap.insert(pair);
+            }
+        }
+
+        /* Then we parse all playlists uri and add them, except when alternative */
         BaseAdaptationSet *adaptSet = new (std::nothrow) BaseAdaptationSet(period);
         if(adaptSet)
         {
-            std::list<Tag *> mediainfotags = getTagsFromList(tagslist, AttributesTag::EXTXSTREAMINF);
-            std::list<Tag *>::const_iterator it;
-            for(it = mediainfotags.begin(); it != mediainfotags.end(); ++it)
-                parseRepresentation(adaptSet, dynamic_cast<AttributesTag *>(*it));
-            period->addAdaptationSet(adaptSet);
+            std::list<Tag *> streaminfotags = getTagsFromList(tagslist, AttributesTag::EXTXSTREAMINF);
+            for(it = streaminfotags.begin(); it != streaminfotags.end(); ++it)
+            {
+                AttributesTag *tag = dynamic_cast<AttributesTag *>(*it);
+                if(tag && tag->getAttributeByName("URI"))
+                {
+                    if(groupsmap.find(tag->getAttributeByName("URI")->value) == groupsmap.end())
+                    {
+                        /* not a group, belong to default adaptation set */
+                        parseRepresentation(adaptSet, tag);
+                    }
+                }
+            }
+            if(!adaptSet->getRepresentations().empty())
+                period->addAdaptationSet(adaptSet);
+            else
+                delete adaptSet;
         }
+
+        /* Finally add all groups */
+        std::map<std::string, AttributesTag *>::const_iterator groupsit;
+        for(groupsit = groupsmap.begin(); groupsit != groupsmap.end(); ++groupsit)
+        {
+            BaseAdaptationSet *altAdaptSet = new (std::nothrow) BaseAdaptationSet(period);
+            if(altAdaptSet)
+            {
+                std::pair<std::string, AttributesTag *> pair = *groupsit;
+                parseRepresentation(altAdaptSet, pair.second);
+                if(!altAdaptSet->getRepresentations().empty())
+                    period->addAdaptationSet(altAdaptSet);
+                else
+                    delete altAdaptSet;
+            }
+        }
+
     }
     else
     {



More information about the vlc-commits mailing list