/* * SmoothManager.cpp ***************************************************************************** * Copyright © 2015 - VideoLAN and VLC authors * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ #ifdef HAVE_CONFIG_H # include "config.h" #endif #include #include #include "SmoothManager.hpp" #include "../adaptive/SharedResources.hpp" #include "../adaptive/tools/Retrieve.hpp" #include "playlist/SmoothParser.hpp" #include "../adaptive/xml/DOMParser.h" #include #include #include #include using namespace adaptive; using namespace adaptive::logic; using namespace smooth; using namespace smooth::playlist; SmoothManager::SmoothManager(demux_t *demux_, SharedResources *res, Manifest *playlist, AbstractStreamFactory *factory, AbstractAdaptationLogic::LogicType type) : PlaylistManager(demux_, res, playlist, factory, type) { } SmoothManager::~SmoothManager() { } Manifest * SmoothManager::fetchManifest() { std::string playlisturl(p_demux->psz_access); playlisturl.append("://"); playlisturl.append(p_demux->psz_location); block_t *p_block = Retrieve::HTTP(resources, ChunkType::Playlist, playlisturl); if(!p_block) return nullptr; stream_t *memorystream = vlc_stream_MemoryNew(p_demux, p_block->p_buffer, p_block->i_buffer, true); if(!memorystream) { block_Release(p_block); return nullptr; } xml::DOMParser parser(memorystream); if(!parser.parse(true)) { vlc_stream_Delete(memorystream); block_Release(p_block); return nullptr; } Manifest *manifest = nullptr; ManifestParser *manifestParser = new (std::nothrow) ManifestParser(parser.getRootNode(), VLC_OBJECT(p_demux), memorystream, playlisturl); if(manifestParser) { manifest = manifestParser->parse(); delete manifestParser; } vlc_stream_Delete(memorystream); block_Release(p_block); return manifest; } bool SmoothManager::updatePlaylist() { bool b_playlist_empty = false; /* Trigger full playlist update in case we cannot get next segment from atom */ std::vector::const_iterator it; for(it=streams.begin(); it!=streams.end(); ++it) { const AbstractStream *st = *it; const vlc_tick_t m = st->getMinAheadTime(); if(!st->isValid() || st->isDisabled() || !st->isSelected()) { continue; } else if(m < 1) { b_playlist_empty = true; break; } } return updatePlaylist(b_playlist_empty); } void SmoothManager::scheduleNextUpdate() { time_t now = time(nullptr); vlc_tick_t minbuffer = getMinAheadTime() / 2; if(playlist->minUpdatePeriod.Get() > minbuffer) minbuffer = playlist->minUpdatePeriod.Get(); if(minbuffer < 5 * CLOCK_FREQ) minbuffer = 5 * CLOCK_FREQ; nextPlaylistupdate = now + minbuffer / CLOCK_FREQ; msg_Dbg(p_demux, "Updated playlist, next update in %" PRId64 "s", (vlc_tick_t) nextPlaylistupdate - now ); } bool SmoothManager::needsUpdate() const { if(nextPlaylistupdate && time(nullptr) < nextPlaylistupdate) return false; return PlaylistManager::needsUpdate(); } bool SmoothManager::updatePlaylist(bool forcemanifest) { /* FIXME: do update from manifest after resuming from pause */ /* Timelines updates should be inlined in tfrf atoms. We'll just care about pruning live timeline then. */ if(forcemanifest && nextPlaylistupdate) { Manifest *newManifest = fetchManifest(); if(newManifest) { playlist->updateWith(newManifest); delete newManifest; #ifdef NDEBUG playlist->debug(); #endif } else return false; } return true; } bool SmoothManager::reactivateStream(AbstractStream *stream) { if(playlist->isLive()) updatePlaylist(true); return PlaylistManager::reactivateStream(stream); } bool SmoothManager::isSmoothStreaming(xml::Node *root) { return root->getName() == "SmoothStreamingMedia"; } bool SmoothManager::mimeMatched(const std::string &mime) { return (mime == "application/vnd.ms-sstr+xml"); }