Commit 414de08e authored by François Cartegnie's avatar François Cartegnie 🤞

demux: adaptative: fix live pruning

Pruning by time was removed a while ago, but
pruning by segment number only can't work for pruning the whole
playlist as that number can be inconsistent across representations
and streams/adaptation sets.

Pruning by number should only occur merging/at representations level.
parent 03a564d9
......@@ -282,6 +282,24 @@ bool PlaylistManager::updatePlaylist()
return true;
}
void PlaylistManager::pruneLiveStream()
{
mtime_t minValidPos = 0;
std::vector<AbstractStream *>::const_iterator it;
for(it=streams.begin(); it!=streams.end(); it++)
{
const AbstractStream *st = *it;
if(st->isDisabled() || !st->isSelected() || st->isEOF())
continue;
const mtime_t t = st->getPlaybackTime();
if(minValidPos == 0 || t < minValidPos)
minValidPos = t;
}
if(minValidPos)
playlist->pruneByPlaybackTime(minValidPos);
}
bool PlaylistManager::reactivateStream(AbstractStream *stream)
{
return stream->reactivate(getPCR());
......
......@@ -73,6 +73,7 @@ namespace adaptative
virtual int doControl(int, va_list);
virtual int doDemux(int64_t);
void pruneLiveStream();
virtual bool reactivateStream(AbstractStream *);
bool setupPeriod();
void unsetPeriod();
......
......@@ -122,7 +122,7 @@ SegmentChunk * SegmentTracker::getNextChunk(bool switch_allowed, HTTPConnectionM
bool b_updated = false;
/* Ensure ephemere content is updated/loaded */
if(rep->needsUpdate())
b_updated = rep->runLocalUpdates(getSegmentStart(), count, false);
b_updated = rep->runLocalUpdates(getPlaybackTime(), count, false);
if(prevRep && !rep->consistentSegmentNumber())
{
......@@ -222,7 +222,7 @@ void SegmentTracker::setPositionByNumber(uint64_t segnumber, bool restarted)
count = segnumber;
}
mtime_t SegmentTracker::getSegmentStart() const
mtime_t SegmentTracker::getPlaybackTime() const
{
if(curRepresentation)
return curRepresentation->getPlaybackTimeBySegmentNumber(count);
......@@ -245,18 +245,11 @@ void SegmentTracker::registerListener(SegmentTrackerListenerInterface *listener)
listeners.push_back(listener);
}
void SegmentTracker::pruneFromCurrent()
{
AbstractPlaylist *playlist = adaptationSet->getPlaylist();
if(playlist->isLive())
playlist->pruneBySegmentNumber(count);
}
void SegmentTracker::updateSelected()
{
if(curRepresentation && curRepresentation->needsUpdate())
{
curRepresentation->runLocalUpdates(getSegmentStart(), count, true);
curRepresentation->runLocalUpdates(getPlaybackTime(), count, true);
curRepresentation->scheduleNextUpdate(count);
}
}
......
......@@ -99,10 +99,9 @@ namespace adaptative
SegmentChunk* getNextChunk(bool, HTTPConnectionManager *);
bool setPositionByTime(mtime_t, bool, bool);
void setPositionByNumber(uint64_t, bool);
mtime_t getSegmentStart() const;
mtime_t getPlaybackTime() const; /* Current segment start time if selected */
mtime_t getMinAheadTime() const;
void registerListener(SegmentTrackerListenerInterface *);
void pruneFromCurrent();
void updateSelected();
private:
......
......@@ -351,14 +351,9 @@ bool AbstractStream::setPosition(mtime_t time, bool tryonly)
return ret;
}
mtime_t AbstractStream::getPosition() const
mtime_t AbstractStream::getPlaybackTime() const
{
return segmentTracker->getSegmentStart();
}
void AbstractStream::prune()
{
segmentTracker->pruneFromCurrent();
return segmentTracker->getPlaybackTime();
}
void AbstractStream::runUpdates()
......
......@@ -76,8 +76,7 @@ namespace adaptative
typedef enum {status_eof, status_eop, status_dis, status_buffering, status_demuxed} status;
status demux(mtime_t, bool);
virtual bool setPosition(mtime_t, bool);
mtime_t getPosition() const;
void prune();
mtime_t getPlaybackTime() const;
void runUpdates();
virtual block_t *readNextBlock(); /* impl */
......
......@@ -117,14 +117,6 @@ BasePeriod* AbstractPlaylist::getNextPeriod(BasePeriod *period)
return NULL;
}
void AbstractPlaylist::getPlaylistDurationsRange(mtime_t *min, mtime_t *max) const
{
*min = *max = 0;
for(size_t i = 0; i < periods.size(); i++)
periods.at(i)->getDurationsRange(min, max);
}
void AbstractPlaylist::mergeWith(AbstractPlaylist *updatedAbstractPlaylist, mtime_t prunebarrier)
{
availabilityEndTime.Set(updatedAbstractPlaylist->availabilityEndTime.Get());
......@@ -133,9 +125,9 @@ void AbstractPlaylist::mergeWith(AbstractPlaylist *updatedAbstractPlaylist, mtim
periods.at(i)->mergeWith(updatedAbstractPlaylist->periods.at(i), prunebarrier);
}
void AbstractPlaylist::pruneBySegmentNumber(uint64_t num)
void AbstractPlaylist::pruneByPlaybackTime(mtime_t time)
{
for(size_t i = 0; i < periods.size(); i++)
periods.at(i)->pruneBySegmentNumber(num);
periods.at(i)->pruneByPlaybackTime(time);
}
......@@ -56,8 +56,7 @@ namespace adaptative
virtual BasePeriod* getNextPeriod(BasePeriod *period);
void mergeWith(AbstractPlaylist *, mtime_t = 0);
void pruneBySegmentNumber(uint64_t);
void getPlaylistDurationsRange(mtime_t *, mtime_t *) const;
void pruneByPlaybackTime(mtime_t);
Property<mtime_t> duration;
Property<time_t> playbackStart;
......
......@@ -93,6 +93,13 @@ bool BaseRepresentation::consistentSegmentNumber() const
return b_consistent;
}
void BaseRepresentation::pruneByPlaybackTime(mtime_t time)
{
uint64_t num;
if(getSegmentNumberByTime(time, &num))
pruneBySegmentNumber(num);
}
mtime_t BaseRepresentation::getMinAheadTime(uint64_t curnum) const
{
std::vector<ISegment *> seglist;
......
......@@ -59,6 +59,7 @@ namespace adaptative
const std::list<std::string> & getCodecs () const;
void addCodec (const std::string &);
bool consistentSegmentNumber () const;
virtual void pruneByPlaybackTime (mtime_t);
virtual mtime_t getMinAheadTime (uint64_t) const;
virtual bool needsUpdate () const;
......
......@@ -25,8 +25,10 @@
#include "SegmentTemplate.h"
#include "SegmentTimeline.h"
#include "AbstractPlaylist.hpp"
#include "BaseRepresentation.h"
#include <algorithm>
#include <cassert>
using namespace adaptative::playlist;
......@@ -349,44 +351,6 @@ mtime_t SegmentInformation::getPlaybackTimeBySegmentNumber(uint64_t number) cons
return time;
}
void SegmentInformation::getDurationsRange(mtime_t *min, mtime_t *max) const
{
/* FIXME: cache stuff in segment holders */
std::vector<ISegment *> seglist;
getSegments(INFOTYPE_MEDIA, seglist);
std::vector<ISegment *>::const_iterator it;
mtime_t total = 0;
for(it = seglist.begin(); it != seglist.end(); ++it)
{
const mtime_t duration = (*it)->duration.Get() * CLOCK_FREQ / inheritTimescale();
if(duration)
{
total += duration;
if (!*min || duration < *min)
*min = duration;
}
}
if(total > *max)
*max = total;
if(mediaSegmentTemplate && mediaSegmentTemplate->segmentTimeline.Get())
{
const mtime_t duration = mediaSegmentTemplate->segmentTimeline.Get()->end() -
mediaSegmentTemplate->segmentTimeline.Get()->start();
*min = 0; /* fixme: get minimum ? */
if(duration > *max)
*max = duration;
}
for(size_t i=0; i<childs.size(); i++)
childs.at(i)->getDurationsRange(min, max);
}
SegmentInformation * SegmentInformation::getChildByID(const ID &id)
{
std::vector<SegmentInformation *>::const_iterator it;
......@@ -429,16 +393,28 @@ void SegmentInformation::mergeWithTimeline(SegmentTimeline *updated)
}
}
void SegmentInformation::pruneByPlaybackTime(mtime_t time)
{
if(segmentList)
segmentList->pruneByPlaybackTime(time);
if(mediaSegmentTemplate)
mediaSegmentTemplate->pruneByPlaybackTime(time);
std::vector<SegmentInformation *>::const_iterator it;
for(it=childs.begin(); it!=childs.end(); ++it)
(*it)->pruneByPlaybackTime(time);
}
void SegmentInformation::pruneBySegmentNumber(uint64_t num)
{
assert(dynamic_cast<BaseRepresentation *>(this));
if(segmentList)
segmentList->pruneBySegmentNumber(num);
if(mediaSegmentTemplate && mediaSegmentTemplate->segmentTimeline.Get())
mediaSegmentTemplate->segmentTimeline.Get()->pruneBySequenceNumber(num);
for(size_t i=0; i<childs.size(); i++)
childs.at(i)->pruneBySegmentNumber(num);
if(mediaSegmentTemplate)
mediaSegmentTemplate->pruneBySequenceNumber(num);
}
uint64_t SegmentInformation::translateSegmentNumber(uint64_t num, const SegmentInformation *from) const
......
......@@ -83,10 +83,10 @@ namespace adaptative
bool getSegmentNumberByTime(mtime_t, uint64_t *) const;
mtime_t getPlaybackTimeBySegmentNumber(uint64_t) const;
uint64_t getLiveStartSegmentNumber(uint64_t) const;
virtual void getDurationsRange(mtime_t *, mtime_t *) const;
virtual void mergeWith(SegmentInformation *, mtime_t);
virtual void mergeWithTimeline(SegmentTimeline *); /* ! don't use with global merge */
virtual void pruneBySegmentNumber(uint64_t);
virtual void pruneByPlaybackTime(mtime_t);
virtual uint64_t translateSegmentNumber(uint64_t, const SegmentInformation *) const;
protected:
......
......@@ -83,6 +83,14 @@ void SegmentList::mergeWith(SegmentList *updated)
updated->segments.clear();
}
void SegmentList::pruneByPlaybackTime(mtime_t time)
{
uint64_t num;
const uint64_t timescale = inheritTimescale();
if(getSegmentNumberByScaledTime(time * timescale / CLOCK_FREQ, &num))
pruneBySegmentNumber(num);
}
void SegmentList::pruneBySegmentNumber(uint64_t tobelownum)
{
std::vector<ISegment *>::iterator it = segments.begin();
......
......@@ -50,6 +50,7 @@ namespace adaptative
void addSegment(ISegment *seg);
void mergeWith(SegmentList *);
void pruneBySegmentNumber(uint64_t);
void pruneByPlaybackTime(mtime_t);
bool getSegmentNumberByScaledTime(stime_t, uint64_t *) const;
mtime_t getPlaybackTimeBySegmentNumber(uint64_t);
......
......@@ -62,6 +62,12 @@ void MediaSegmentTemplate::mergeWith(MediaSegmentTemplate *updated, mtime_t prun
}
}
void MediaSegmentTemplate::pruneByPlaybackTime(mtime_t time)
{
if(segmentTimeline.Get())
return segmentTimeline.Get()->pruneByPlaybackTime(time);
}
size_t MediaSegmentTemplate::pruneBySequenceNumber(uint64_t number)
{
if(segmentTimeline.Get())
......
......@@ -52,6 +52,7 @@ namespace adaptative
virtual void setSourceUrl( const std::string &url ); /* reimpl */
void mergeWith( MediaSegmentTemplate *, mtime_t );
virtual uint64_t getSequenceNumber() const; /* reimpl */
void pruneByPlaybackTime(mtime_t);
size_t pruneBySequenceNumber(uint64_t);
virtual void debug(vlc_object_t *, int = 0) const; /* reimpl */
Property<size_t> startNumber;
......
......@@ -155,6 +155,13 @@ uint64_t SegmentTimeline::minElementNumber() const
return elements.front()->number;
}
void SegmentTimeline::pruneByPlaybackTime(mtime_t time)
{
const uint64_t timescale = inheritTimescale();
uint64_t num = getElementNumberByScaledPlaybackTime(time * timescale / CLOCK_FREQ);
pruneBySequenceNumber(num);
}
size_t SegmentTimeline::pruneBySequenceNumber(uint64_t number)
{
size_t prunednow = 0;
......
......@@ -50,6 +50,7 @@ namespace adaptative
stime_t getMinAheadScaledTime(uint64_t) const;
uint64_t maxElementNumber() const;
uint64_t minElementNumber() const;
void pruneByPlaybackTime(mtime_t);
size_t pruneBySequenceNumber(uint64_t);
void mergeWith(SegmentTimeline &);
mtime_t start() const;
......
......@@ -125,7 +125,7 @@ bool DASHManager::updatePlaylist()
std::vector<AbstractStream *>::iterator it;
for(it=streams.begin(); it!=streams.end(); it++)
{
mtime_t segmentTime = (*it)->getPosition();
mtime_t segmentTime = (*it)->getPlaybackTime();
if(!minsegmentTime || segmentTime < minsegmentTime)
minsegmentTime = segmentTime;
}
......
......@@ -154,13 +154,6 @@ bool Representation::runLocalUpdates(mtime_t, uint64_t number, bool prune)
return true;
}
void Representation::getDurationsRange(mtime_t *min, mtime_t *max) const
{
if(!b_loaded)
return;
BaseRepresentation::getDurationsRange(min, max);
}
uint64_t Representation::translateSegmentNumber(uint64_t num, const SegmentInformation *from) const
{
if(consistentSegmentNumber())
......
......@@ -51,7 +51,6 @@ namespace hls
virtual bool needsUpdate() const; /* reimpl */
virtual void debug(vlc_object_t *, int) const; /* reimpl */
virtual bool runLocalUpdates(mtime_t, uint64_t, bool); /* reimpl */
virtual void getDurationsRange(mtime_t *, mtime_t *) const; /* reimpl */
virtual uint64_t translateSegmentNumber(uint64_t, const SegmentInformation *) const; /* reimpl */
private:
......
......@@ -131,10 +131,6 @@ bool SmoothManager::updatePlaylist(bool forcemanifest)
{
/* FIXME: do update from manifest after resuming from pause */
std::vector<AbstractStream *>::iterator it;
for(it=streams.begin(); it!=streams.end(); it++)
(*it)->prune();
/* Timelines updates should be inlined in tfrf atoms.
We'll just care about pruning live timeline then. */
......@@ -146,9 +142,6 @@ bool SmoothManager::updatePlaylist(bool forcemanifest)
playlist->mergeWith(newManifest, 0);
delete newManifest;
std::vector<AbstractStream *>::iterator it;
for(it=streams.begin(); it!=streams.end(); it++)
(*it)->prune();
#ifdef NDEBUG
playlist->debug();
#endif
......@@ -156,6 +149,8 @@ bool SmoothManager::updatePlaylist(bool forcemanifest)
else return false;
}
pruneLiveStream();
return true;
}
......
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