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