Commit 76bbbcfc authored by François Cartegnie's avatar François Cartegnie 🤞

demux: hls: move updates to local playlists with lazy loading

parent f8af0beb
......@@ -269,6 +269,10 @@ bool PlaylistManager::seekAble() const
bool PlaylistManager::updatePlaylist()
{
std::vector<Stream *>::const_iterator it;
for(it=streams.begin(); it!=streams.end(); ++it)
(*it)->runUpdates();
return true;
}
......@@ -313,8 +317,7 @@ int PlaylistManager::doDemux(int64_t increment)
break;
}
if( !updatePlaylist() )
msg_Warn(p_demux, "Can't update MPD");
updatePlaylist();
return VLC_DEMUXER_SUCCESS;
}
......
......@@ -85,8 +85,9 @@ SegmentChunk * SegmentTracker::getNextChunk(bool switch_allowed)
initializing = true;
}
/* Ensure content is loaded */
rep->runLocalUpdates();
/* Ensure ephemere content is updated/loaded */
if(rep->needsUpdate())
updateSelected();
/* If we're starting, set the first segment number to download */
if(!sequence_set)
......@@ -168,3 +169,9 @@ void SegmentTracker::pruneFromCurrent()
if(playlist->isLive() && sequence_set)
playlist->pruneBySegmentNumber(count);
}
void SegmentTracker::updateSelected()
{
if(prevRepresentation)
prevRepresentation->runLocalUpdates(getSegmentStart(), count);
}
......@@ -56,6 +56,7 @@ namespace adaptative
bool setPosition(mtime_t, bool, bool);
mtime_t getSegmentStart() const;
void pruneFromCurrent();
void updateSelected();
private:
bool initializing;
......
......@@ -313,3 +313,9 @@ void Stream::prune()
{
segmentTracker->pruneFromCurrent();
}
void Stream::runUpdates()
{
if(!isDisabled())
segmentTracker->updateSelected();
}
......@@ -83,6 +83,7 @@ namespace adaptative
bool setPosition(mtime_t, bool);
mtime_t getPosition() const;
void prune();
void runUpdates();
private:
SegmentChunk *getChunk();
......
......@@ -71,6 +71,11 @@ void BaseRepresentation::addCodec(const std::string &codec)
codecs.push_back(codec);
}
bool BaseRepresentation::needsUpdate() const
{
return false;
}
void BaseRepresentation::debug(vlc_object_t *obj, int indent) const
{
std::string text(indent, ' ');
......
......@@ -58,8 +58,9 @@ namespace adaptative
void setBandwidth ( uint64_t bandwidth );
const std::list<std::string> & getCodecs () const;
void addCodec (const std::string &);
virtual bool needsUpdate() const;
void debug (vlc_object_t *,int = 0) const;
virtual void debug (vlc_object_t *,int = 0) const;
/* for segment templates */
virtual std::string contextualize(size_t, const std::string &,
......
......@@ -328,7 +328,7 @@ void SegmentInformation::pruneBySegmentNumber(uint64_t num)
childs.at(i)->pruneBySegmentNumber(num);
}
void SegmentInformation::runLocalUpdates()
void SegmentInformation::runLocalUpdates(mtime_t, uint64_t)
{
}
......
......@@ -81,10 +81,10 @@ namespace adaptative
ISegment * getSegment(SegmentInfoType, uint64_t = 0) const;
bool getSegmentNumberByTime(mtime_t, uint64_t *) const;
mtime_t getPlaybackTimeBySegmentNumber(uint64_t) const;
void getDurationsRange(mtime_t *, mtime_t *) const;
virtual void getDurationsRange(mtime_t *, mtime_t *) const;
virtual void mergeWith(SegmentInformation *, mtime_t);
virtual void pruneBySegmentNumber(uint64_t);
virtual void runLocalUpdates();
virtual void runLocalUpdates(mtime_t, uint64_t);
protected:
std::size_t getAllSegments(std::vector<ISegment *> &) const;
......
......@@ -122,86 +122,3 @@ AbstractAdaptationLogic *HLSManager::createLogic(AbstractAdaptationLogic::LogicT
return PlaylistManager::createLogic(type);
}
}
bool HLSManager::updatePlaylist()
{
if(!playlist->isLive() || !playlist->minUpdatePeriod.Get())
return true;
time_t now = time(NULL);
if(nextPlaylistupdate && now < nextPlaylistupdate)
return true;
M3U8 *updatedplaylist = NULL;
/* do update */
if(nextPlaylistupdate)
{
std::string url(p_demux->psz_access);
url.append("://");
url.append(p_demux->psz_location);
uint8_t *p_data = NULL;
size_t i_data = Retrieve::HTTP(VLC_OBJECT(p_demux->s), url, (void**) &p_data);
if(!p_data)
return false;
stream_t *updatestream = stream_MemoryNew(p_demux->s, p_data, i_data, false);
if(!updatestream)
{
free(p_data);
nextPlaylistupdate = now + playlist->minUpdatePeriod.Get() / CLOCK_FREQ;
return false;
}
M3U8Parser parser;
updatedplaylist = parser.parse(updatestream, url);
if(!updatedplaylist)
{
stream_Delete(updatestream);
nextPlaylistupdate = now + playlist->minUpdatePeriod.Get() / CLOCK_FREQ;
return false;
}
stream_Delete(updatestream);
}
/* Compute new MPD update time */
mtime_t mininterval = 0;
mtime_t maxinterval = 0;
if(updatedplaylist)
{
updatedplaylist->getPlaylistDurationsRange(&mininterval, &maxinterval);
playlist->mergeWith(updatedplaylist);
playlist->debug();
delete updatedplaylist;
/* pruning */
std::vector<Stream *>::iterator it;
for(it=streams.begin(); it!=streams.end(); ++it)
{
(*it)->prune();
}
}
else
{
playlist->getPlaylistDurationsRange(&mininterval, &maxinterval);
}
if(playlist->minUpdatePeriod.Get() > mininterval)
mininterval = playlist->minUpdatePeriod.Get();
if(mininterval < 5 * CLOCK_FREQ)
mininterval = 5 * CLOCK_FREQ;
if(maxinterval < mininterval)
maxinterval = mininterval;
nextPlaylistupdate = now + (mininterval + (maxinterval - mininterval) / 2) / CLOCK_FREQ;
msg_Dbg(p_demux, "Updated playlist, next update in %" PRId64 "s (""%" PRId64 "..%" PRId64 ")",
nextPlaylistupdate - now, mininterval/ CLOCK_FREQ, maxinterval/ CLOCK_FREQ);
return true;
}
......@@ -36,7 +36,6 @@ namespace hls
logic::AbstractAdaptationLogic::LogicType type );
virtual ~HLSManager();
virtual AbstractAdaptationLogic *createLogic(AbstractAdaptationLogic::LogicType);
virtual bool updatePlaylist();
static bool isHTTPLiveStreaming(stream_t *);
};
......
......@@ -148,7 +148,7 @@ void M3U8Parser::createAndFillRepresentation(vlc_object_t *p_obj, BaseAdaptation
}
}
bool M3U8Parser::loadSegmentsFromPlaylistURI(vlc_object_t *p_obj, Representation *rep)
bool M3U8Parser::appendSegmentsFromPlaylistURI(vlc_object_t *p_obj, Representation *rep)
{
void *p_data;
const size_t i_data = Retrieve::HTTP(p_obj, rep->getPlaylistUrl().toString(), &p_data);
......@@ -172,9 +172,9 @@ bool M3U8Parser::loadSegmentsFromPlaylistURI(vlc_object_t *p_obj, Representation
void M3U8Parser::parseSegments(vlc_object_t *p_obj, Representation *rep, const std::list<Tag *> &tagslist)
{
SegmentList *segmentList = new (std::nothrow) SegmentList(rep);
rep->setSegmentList(segmentList);
rep->timescale.Set(100);
rep->b_loaded = true;
stime_t totalduration = 0;
stime_t nzStartTime = 0;
......@@ -308,8 +308,9 @@ void M3U8Parser::parseSegments(vlc_object_t *p_obj, Representation *rep, const s
{
rep->getPlaylist()->duration.Set(totalduration * CLOCK_FREQ / rep->timescale.Get());
}
}
rep->setSegmentList(segmentList);
}
M3U8 * M3U8Parser::parse(stream_t *p_stream, const std::string &playlisturl)
{
char *psz_line = stream_ReadLine(p_stream);
......@@ -368,7 +369,6 @@ M3U8 * M3U8Parser::parse(stream_t *p_stream, const std::string &playlisturl)
if(rep)
{
adaptSet->addRepresentation(rep);
loadSegmentsFromPlaylistURI(VLC_OBJECT(p_stream), rep);
}
}
}
......@@ -391,7 +391,6 @@ M3U8 * M3U8Parser::parse(stream_t *p_stream, const std::string &playlisturl)
if(rep)
{
altAdaptSet->addRepresentation(rep);
loadSegmentsFromPlaylistURI(VLC_OBJECT(p_stream), rep);
}
if(pair.second->getAttributeByName("NAME"))
......
......@@ -60,7 +60,7 @@ namespace hls
virtual ~M3U8Parser ();
M3U8 * parse (stream_t *p_stream, const std::string &);
bool loadSegmentsFromPlaylistURI(vlc_object_t *, Representation *);
bool appendSegmentsFromPlaylistURI(vlc_object_t *, Representation *);
private:
Representation * createRepresentation(BaseAdaptationSet *, const AttributesTag *);
......
......@@ -25,6 +25,7 @@
#include "Representation.hpp"
#include "M3U8.hpp"
#include "Parser.hpp"
#include "../adaptative/playlist/BasePeriod.h"
#include "../adaptative/playlist/BaseAdaptationSet.h"
#include "../adaptative/playlist/SegmentList.h"
......@@ -37,7 +38,9 @@ Representation::Representation ( BaseAdaptationSet *set ) :
BaseRepresentation( set )
{
b_live = true;
b_loaded = false;
switchpolicy = SegmentInformation::SWITCH_SEGMENT_ALIGNED; /* FIXME: based on streamformat */
nextPlaylistupdate = 0;
}
Representation::~Representation ()
......@@ -77,24 +80,61 @@ Url Representation::getPlaylistUrl() const
}
}
void Representation::localMergeWithPlaylist(M3U8 *updated, mtime_t prunebarrier)
void Representation::debug(vlc_object_t *obj, int indent) const
{
BasePeriod *period = updated->getFirstPeriod();
if(!period)
return;
BaseRepresentation::debug(obj, indent);
if(!b_loaded)
{
std::string text(indent + 1, ' ');
text.append(" (not loaded)");
msg_Dbg(obj, "%s", text.c_str());
}
}
BaseAdaptationSet *adapt = period->getAdaptationSets().front();
if(!adapt)
return;
bool Representation::needsUpdate() const
{
return true;
}
BaseRepresentation *rep = adapt->getRepresentations().front();
if(!rep)
return;
void Representation::runLocalUpdates(mtime_t /*currentplaybacktime*/, uint64_t number)
{
const time_t now = time(NULL);
const AbstractPlaylist *playlist = getPlaylist();
if(!b_loaded || (isLive() && nextPlaylistupdate < now))
{
M3U8Parser parser;
parser.appendSegmentsFromPlaylistURI(playlist->getVLCObject(), this);
b_loaded = true;
this->mergeWith( rep, prunebarrier );
pruneBySegmentNumber(number);
/* Compute new update time */
mtime_t mininterval = 0;
mtime_t maxinterval = 0;
getDurationsRange( &mininterval, &maxinterval );
if(playlist->minUpdatePeriod.Get() > mininterval)
mininterval = playlist->minUpdatePeriod.Get();
if(mininterval < 5 * CLOCK_FREQ)
mininterval = 5 * CLOCK_FREQ;
if(maxinterval < mininterval)
maxinterval = mininterval;
nextPlaylistupdate = now + (mininterval + (maxinterval - mininterval) / 2) / CLOCK_FREQ;
msg_Dbg(playlist->getVLCObject(), "Updated playlist ID %s, next update in %" PRId64 "s",
getID().str().c_str(), nextPlaylistupdate - now);
debug(playlist->getVLCObject(), 0);
}
}
void Representation::mergeWith(SegmentInformation *seginfo, mtime_t prunebarrier)
void Representation::getDurationsRange(mtime_t *min, mtime_t *max) const
{
BaseRepresentation::mergeWith(seginfo, prunebarrier);
if(!b_loaded)
return;
BaseRepresentation::getDurationsRange(min, max);
}
......@@ -44,12 +44,16 @@ namespace hls
void setPlaylistUrl(const std::string &);
Url getPlaylistUrl() const;
void localMergeWithPlaylist(M3U8 *, mtime_t);
bool isLive() const;
virtual void mergeWith(SegmentInformation *, mtime_t); /* reimpl */
virtual bool needsUpdate() const; /* reimpl */
virtual void debug(vlc_object_t *, int) const; /* reimpl */
virtual void runLocalUpdates(mtime_t, uint64_t); /* reimpl */
virtual void getDurationsRange(mtime_t *, mtime_t *) const; /* reimpl */
private:
bool b_live;
bool b_loaded;
mtime_t nextPlaylistupdate;
Url playlistUrl;
Property<std::string> audio;
Property<std::string> video;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment