bool PlaylistManager::setupPeriod() { if(!currentPeriod) return false; if(!logic && !(logic = createLogic(logicType, conManager))) return false; std::vector<BaseAdaptationSet*> sets = currentPeriod->getAdaptationSets(); std::vector<BaseAdaptationSet*>::iterator it; for(it=sets.begin();it!=sets.end();++it) { BaseAdaptationSet *set = *it; if(set && streamFactory) { SegmentTracker *tracker = new (std::nothrow) SegmentTracker(logic, set); if(!tracker) continue; AbstractStream *st = streamFactory->create(p_demux, set->getStreamFormat(), tracker, conManager); if(!st) { delete tracker; continue; } streams.push_back(st); /* Generate stream description */ std::list<std::string> languages; if(!set->getLang().empty()) { languages = set->getLang(); } else if(!set->getRepresentations().empty()) { languages = set->getRepresentations().front()->getLang(); } if(!languages.empty()) st->setLanguage(languages.front()); if(!set->description.Get().empty()) st->setDescription(set->description.Get()); } } return true; }
bool M3U8::isLive() const { std::vector<BasePeriod *>::const_iterator itp; for(itp = periods.begin(); itp != periods.end(); ++itp) { const BasePeriod *period = *itp; std::vector<BaseAdaptationSet *>::const_iterator ita; for(ita = period->getAdaptationSets().begin(); ita != period->getAdaptationSets().end(); ++ita) { BaseAdaptationSet *adaptSet = *ita; std::vector<BaseRepresentation *>::iterator itr; for(itr = adaptSet->getRepresentations().begin(); itr != adaptSet->getRepresentations().end(); ++itr) { const Representation *rep = dynamic_cast<const Representation *>(*itr); if(rep->initialized() && rep->isLive()) return true; } } } return false; }
void Representation::localMergeWithPlaylist(M3U8 *updated, mtime_t prunebarrier) { BasePeriod *period = updated->getFirstPeriod(); if(!period) return; BaseAdaptationSet *adapt = period->getAdaptationSets().front(); if(!adapt) return; BaseRepresentation *rep = adapt->getRepresentations().front(); if(!rep) return; this->mergeWith( rep, prunebarrier ); }
M3U8 * M3U8Parser::parse(vlc_object_t *p_object, stream_t *p_stream, const std::string &playlisturl) { char *psz_line = vlc_stream_ReadLine(p_stream); if(!psz_line || strcmp(psz_line, "#EXTM3U")) { free(psz_line); return NULL; } free(psz_line); M3U8 *playlist = new (std::nothrow) M3U8(p_object); if(!playlist) return NULL; if(!playlisturl.empty()) playlist->setPlaylistUrl( Helper::getDirectoryPath(playlisturl).append("/") ); BasePeriod *period = new (std::nothrow) BasePeriod( playlist ); if(!period) return playlist; std::list<Tag *> tagslist = parseEntries(p_stream); 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 *> 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 */ Representation *rep = createRepresentation(adaptSet, tag); if(rep) { adaptSet->addRepresentation(rep); } } } } 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; Representation *rep = createRepresentation(altAdaptSet, pair.second); if(rep) { altAdaptSet->addRepresentation(rep); } if(pair.second->getAttributeByName("NAME")) altAdaptSet->description.Set(pair.second->getAttributeByName("NAME")->quotedString()); /* Subtitles unsupported for now */ if(pair.second->getAttributeByName("TYPE")->value != "AUDIO" && pair.second->getAttributeByName("TYPE")->value != "VIDEO") { rep->streamFormat = StreamFormat(StreamFormat::UNSUPPORTED); } if(pair.second->getAttributeByName("LANGUAGE")) { std::string lang = pair.second->getAttributeByName("LANGUAGE")->quotedString(); std::size_t pos = lang.find_first_of('-'); if(pos != std::string::npos && pos > 0) altAdaptSet->addLang(lang.substr(0, pos)); else if (lang.size() < 4) altAdaptSet->addLang(lang); } if(!altAdaptSet->getRepresentations().empty()) period->addAdaptationSet(altAdaptSet); else delete altAdaptSet; } } } else /* Non master playlist (opened directly subplaylist or HLS v1) */ { BaseAdaptationSet *adaptSet = new (std::nothrow) BaseAdaptationSet(period); if(adaptSet) { period->addAdaptationSet(adaptSet); AttributesTag *tag = new AttributesTag(AttributesTag::EXTXSTREAMINF, ""); tag->addAttribute(new Attribute("URI", playlisturl)); createAndFillRepresentation(p_object, adaptSet, tag, tagslist); delete tag; } } playlist->addPeriod(period); releaseTagsList(tagslist); playlist->debug(); return playlist; }