vlc | branch: master | Francois Cartegnie <[email protected]> | 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 { _______________________________________________ vlc-commits mailing list [email protected] https://mailman.videolan.org/listinfo/vlc-commits
