Commit f8af0beb authored by François Cartegnie's avatar François Cartegnie 🤞

demux: adaptative: change relative playbackoffset to absolute

parent 0b57f64d
...@@ -34,6 +34,7 @@ SegmentTracker::SegmentTracker(AbstractAdaptationLogic *logic_, BaseAdaptationSe ...@@ -34,6 +34,7 @@ SegmentTracker::SegmentTracker(AbstractAdaptationLogic *logic_, BaseAdaptationSe
initializing = true; initializing = true;
index_sent = false; index_sent = false;
init_sent = false; init_sent = false;
sequence_set = false;
prevRepresentation = NULL; prevRepresentation = NULL;
setAdaptationLogic(logic_); setAdaptationLogic(logic_);
adaptationSet = adaptSet; adaptationSet = adaptSet;
...@@ -51,7 +52,7 @@ void SegmentTracker::setAdaptationLogic(AbstractAdaptationLogic *logic_) ...@@ -51,7 +52,7 @@ void SegmentTracker::setAdaptationLogic(AbstractAdaptationLogic *logic_)
void SegmentTracker::resetCounter() void SegmentTracker::resetCounter()
{ {
count = 0; sequence_set = false;
prevRepresentation = NULL; prevRepresentation = NULL;
} }
...@@ -87,6 +88,18 @@ SegmentChunk * SegmentTracker::getNextChunk(bool switch_allowed) ...@@ -87,6 +88,18 @@ SegmentChunk * SegmentTracker::getNextChunk(bool switch_allowed)
/* Ensure content is loaded */ /* Ensure content is loaded */
rep->runLocalUpdates(); rep->runLocalUpdates();
/* If we're starting, set the first segment number to download */
if(!sequence_set)
{
if(! rep->getSegmentNumberByTime( VLC_TS_INVALID, &count ) )
{
msg_Warn( rep->getPlaylist()->getVLCObject(),
"Can't get first segment number for representation %s", rep->getID().str().c_str() );
count = 0;
}
sequence_set = true;
}
if(!init_sent) if(!init_sent)
{ {
init_sent = true; init_sent = true;
...@@ -121,9 +134,9 @@ SegmentChunk * SegmentTracker::getNextChunk(bool switch_allowed) ...@@ -121,9 +134,9 @@ SegmentChunk * SegmentTracker::getNextChunk(bool switch_allowed)
bool SegmentTracker::setPosition(mtime_t time, bool restarted, bool tryonly) bool SegmentTracker::setPosition(mtime_t time, bool restarted, bool tryonly)
{ {
uint64_t segcount; uint64_t segnumber;
if(prevRepresentation && if(prevRepresentation &&
prevRepresentation->getSegmentNumberByTime(time, &segcount)) prevRepresentation->getSegmentNumberByTime(time, &segnumber))
{ {
if(!tryonly) if(!tryonly)
{ {
...@@ -133,7 +146,8 @@ bool SegmentTracker::setPosition(mtime_t time, bool restarted, bool tryonly) ...@@ -133,7 +146,8 @@ bool SegmentTracker::setPosition(mtime_t time, bool restarted, bool tryonly)
index_sent = false; index_sent = false;
init_sent = false; init_sent = false;
} }
count = segcount; count = segnumber;
sequence_set = true;
} }
return true; return true;
} }
...@@ -142,7 +156,7 @@ bool SegmentTracker::setPosition(mtime_t time, bool restarted, bool tryonly) ...@@ -142,7 +156,7 @@ bool SegmentTracker::setPosition(mtime_t time, bool restarted, bool tryonly)
mtime_t SegmentTracker::getSegmentStart() const mtime_t SegmentTracker::getSegmentStart() const
{ {
if(prevRepresentation) if(prevRepresentation && sequence_set)
return prevRepresentation->getPlaybackTimeBySegmentNumber(count); return prevRepresentation->getPlaybackTimeBySegmentNumber(count);
else else
return 0; return 0;
...@@ -151,6 +165,6 @@ mtime_t SegmentTracker::getSegmentStart() const ...@@ -151,6 +165,6 @@ mtime_t SegmentTracker::getSegmentStart() const
void SegmentTracker::pruneFromCurrent() void SegmentTracker::pruneFromCurrent()
{ {
AbstractPlaylist *playlist = adaptationSet->getPlaylist(); AbstractPlaylist *playlist = adaptationSet->getPlaylist();
if(playlist->isLive()) if(playlist->isLive() && sequence_set)
playlist->pruneBySegmentNumber(count); playlist->pruneBySegmentNumber(count);
} }
...@@ -61,6 +61,7 @@ namespace adaptative ...@@ -61,6 +61,7 @@ namespace adaptative
bool initializing; bool initializing;
bool index_sent; bool index_sent;
bool init_sent; bool init_sent;
bool sequence_set;
uint64_t count; uint64_t count;
AbstractAdaptationLogic *logic; AbstractAdaptationLogic *logic;
BaseAdaptationSet *adaptationSet; BaseAdaptationSet *adaptationSet;
......
...@@ -114,7 +114,8 @@ size_t ISegment::getOffset() const ...@@ -114,7 +114,8 @@ size_t ISegment::getOffset() const
void ISegment::debug(vlc_object_t *obj, int indent) const void ISegment::debug(vlc_object_t *obj, int indent) const
{ {
std::stringstream ss; std::stringstream ss;
ss << std::string(indent, ' ') << debugName << " url=" << getUrlSegment().toString(); ss << std::string(indent, ' ') << debugName << " #" << getSequenceNumber();
ss << " url=" << getUrlSegment().toString();
if(startByte!=endByte) if(startByte!=endByte)
ss << " @" << startByte << ".." << endByte; ss << " @" << startByte << ".." << endByte;
msg_Dbg(obj, "%s", ss.str().c_str()); msg_Dbg(obj, "%s", ss.str().c_str());
...@@ -162,6 +163,13 @@ Segment::Segment(ICanonicalUrl *parent) : ...@@ -162,6 +163,13 @@ Segment::Segment(ICanonicalUrl *parent) :
void Segment::addSubSegment(SubSegment *subsegment) void Segment::addSubSegment(SubSegment *subsegment)
{ {
if(!subsegments.empty())
{
/* Use our own sequence number, and since it it now
uneffective, also for next subsegments numbering */
subsegment->setSequenceNumber(getSequenceNumber());
setSequenceNumber(getSequenceNumber());
}
subsegments.push_back(subsegment); subsegments.push_back(subsegment);
} }
......
...@@ -71,6 +71,8 @@ bool SegmentInfoCommon::getSegmentNumberByScaledTime(const std::vector<ISegment ...@@ -71,6 +71,8 @@ bool SegmentInfoCommon::getSegmentNumberByScaledTime(const std::vector<ISegment
if(segments.empty() || (segments.size() > 1 && segments[1]->startTime.Get() == 0) ) if(segments.empty() || (segments.size() > 1 && segments[1]->startTime.Get() == 0) )
return false; return false;
*ret = 0;
std::vector<ISegment *>::const_iterator it = segments.begin(); std::vector<ISegment *>::const_iterator it = segments.begin();
while(it != segments.end()) while(it != segments.end())
{ {
...@@ -83,10 +85,9 @@ bool SegmentInfoCommon::getSegmentNumberByScaledTime(const std::vector<ISegment ...@@ -83,10 +85,9 @@ bool SegmentInfoCommon::getSegmentNumberByScaledTime(const std::vector<ISegment
break; break;
} }
(*ret)++; *ret = seg->getSequenceNumber();
it++; it++;
} }
(*ret)--;
return true; return true;
} }
...@@ -68,10 +68,8 @@ AbstractPlaylist * SegmentInformation::getPlaylist() const ...@@ -68,10 +68,8 @@ AbstractPlaylist * SegmentInformation::getPlaylist() const
return NULL; return NULL;
} }
std::size_t SegmentInformation::getSegments(SegmentInfoType type, std::vector<ISegment *> &retSegments, std::size_t SegmentInformation::getSegments(SegmentInfoType type, std::vector<ISegment *> &retSegments) const
std::size_t *offset) const
{ {
std::size_t off = 0;
switch (type) switch (type)
{ {
case INFOTYPE_INIT: case INFOTYPE_INIT:
...@@ -107,7 +105,6 @@ std::size_t SegmentInformation::getSegments(SegmentInfoType type, std::vector<IS ...@@ -107,7 +105,6 @@ std::size_t SegmentInformation::getSegments(SegmentInfoType type, std::vector<IS
std::vector<ISegment *> list = (*it)->subSegments(); std::vector<ISegment *> list = (*it)->subSegments();
retSegments.insert( retSegments.end(), list.begin(), list.end() ); retSegments.insert( retSegments.end(), list.begin(), list.end() );
} }
off = segmentList->getOffset();
} }
else if( segmentBase ) else if( segmentBase )
{ {
...@@ -137,12 +134,10 @@ std::size_t SegmentInformation::getSegments(SegmentInfoType type, std::vector<IS ...@@ -137,12 +134,10 @@ std::size_t SegmentInformation::getSegments(SegmentInfoType type, std::vector<IS
if( retSegments.empty() && parent ) if( retSegments.empty() && parent )
{ {
return parent->getSegments( type, retSegments, offset ); return parent->getSegments( type, retSegments );
} }
else else
{ {
if( offset )
*offset = off;
return retSegments.size(); return retSegments.size();
} }
} }
...@@ -160,11 +155,8 @@ std::size_t SegmentInformation::getAllSegments(std::vector<ISegment *> &retSegme ...@@ -160,11 +155,8 @@ std::size_t SegmentInformation::getAllSegments(std::vector<ISegment *> &retSegme
ISegment * SegmentInformation::getSegment(SegmentInfoType type, uint64_t pos) const ISegment * SegmentInformation::getSegment(SegmentInfoType type, uint64_t pos) const
{ {
ISegment *segment = NULL;
std::vector<ISegment *> retSegments; std::vector<ISegment *> retSegments;
std::size_t offset = 0; const size_t size = getSegments( type, retSegments );
const size_t size = getSegments( type, retSegments, &offset );
if( size ) if( size )
{ {
/* check if that's a template (fixme: find a better way) */ /* check if that's a template (fixme: find a better way) */
...@@ -175,13 +167,24 @@ ISegment * SegmentInformation::getSegment(SegmentInfoType type, uint64_t pos) co ...@@ -175,13 +167,24 @@ ISegment * SegmentInformation::getSegment(SegmentInfoType type, uint64_t pos) co
templ->segmentTimeline.Get()->maxElementNumber() > pos) templ->segmentTimeline.Get()->maxElementNumber() > pos)
return templ; return templ;
} }
else if( pos < size + offset && pos >= offset ) else
{ {
segment = retSegments[pos - offset]; std::vector<ISegment *>::const_iterator it;
for(it = retSegments.begin(); it != retSegments.end(); ++it)
{
ISegment *seg = *it;
if(seg->getSequenceNumber() >= pos)
{
if(seg->getSequenceNumber() == pos)
return seg;
else
return NULL;
}
}
} }
} }
return segment; return NULL;
} }
bool SegmentInformation::getSegmentNumberByTime(mtime_t time, uint64_t *ret) const bool SegmentInformation::getSegmentNumberByTime(mtime_t time, uint64_t *ret) const
...@@ -190,9 +193,10 @@ bool SegmentInformation::getSegmentNumberByTime(mtime_t time, uint64_t *ret) con ...@@ -190,9 +193,10 @@ bool SegmentInformation::getSegmentNumberByTime(mtime_t time, uint64_t *ret) con
{ {
const uint64_t timescale = mediaSegmentTemplate->inheritTimescale(); const uint64_t timescale = mediaSegmentTemplate->inheritTimescale();
const mtime_t duration = mediaSegmentTemplate->duration.Get(); const mtime_t duration = mediaSegmentTemplate->duration.Get();
*ret = mediaSegmentTemplate->startNumber.Get();
if(duration) if(duration)
{ {
*ret = time / (CLOCK_FREQ * duration / timescale); *ret += time / (CLOCK_FREQ * duration / timescale);
return true; return true;
} }
} }
......
...@@ -88,7 +88,7 @@ namespace adaptative ...@@ -88,7 +88,7 @@ namespace adaptative
protected: protected:
std::size_t getAllSegments(std::vector<ISegment *> &) const; std::size_t getAllSegments(std::vector<ISegment *> &) const;
std::size_t getSegments(SegmentInfoType, std::vector<ISegment *>&, std::size_t * = NULL) const; std::size_t getSegments(SegmentInfoType, std::vector<ISegment *>&) const;
std::vector<SegmentInformation *> childs; std::vector<SegmentInformation *> childs;
SegmentInformation * getChildByID( const ID & ); SegmentInformation * getChildByID( const ID & );
SegmentInformation *parent; SegmentInformation *parent;
......
...@@ -31,7 +31,6 @@ using namespace adaptative::playlist; ...@@ -31,7 +31,6 @@ using namespace adaptative::playlist;
SegmentList::SegmentList( SegmentInformation *parent ): SegmentList::SegmentList( SegmentInformation *parent ):
SegmentInfoCommon( parent ), TimescaleAble( parent ) SegmentInfoCommon( parent ), TimescaleAble( parent )
{ {
pruned = 0;
} }
SegmentList::~SegmentList() SegmentList::~SegmentList()
{ {
...@@ -45,6 +44,24 @@ const std::vector<ISegment*>& SegmentList::getSegments() const ...@@ -45,6 +44,24 @@ const std::vector<ISegment*>& SegmentList::getSegments() const
return segments; return segments;
} }
ISegment * SegmentList::getSegmentByNumber(uint64_t number)
{
std::vector<ISegment *>::const_iterator it = segments.begin();
for(it = segments.begin(); it != segments.end(); ++it)
{
ISegment *seg = *it;
if(seg->getSequenceNumber() == number)
{
return seg;
}
else if (seg->getSequenceNumber() > number)
{
break;
}
}
return NULL;
}
void SegmentList::addSegment(ISegment *seg) void SegmentList::addSegment(ISegment *seg)
{ {
seg->setParent(this); seg->setParent(this);
...@@ -68,54 +85,64 @@ void SegmentList::mergeWith(SegmentList *updated) ...@@ -68,54 +85,64 @@ void SegmentList::mergeWith(SegmentList *updated)
void SegmentList::pruneBySegmentNumber(uint64_t tobelownum) void SegmentList::pruneBySegmentNumber(uint64_t tobelownum)
{ {
if(tobelownum < pruned)
return;
uint64_t current = pruned;
std::vector<ISegment *>::iterator it = segments.begin(); std::vector<ISegment *>::iterator it = segments.begin();
while(it != segments.end() && current < tobelownum) while(it != segments.end())
{ {
ISegment *seg = *it; ISegment *seg = *it;
if(seg->getSequenceNumber() >= tobelownum)
break;
if(seg->chunksuse.Get()) /* can't prune from here, still in use */ if(seg->chunksuse.Get()) /* can't prune from here, still in use */
break; break;
delete *it; delete *it;
it = segments.erase(it); it = segments.erase(it);
current++;
pruned++;
} }
} }
bool SegmentList::getSegmentNumberByScaledTime(stime_t time, uint64_t *ret) const bool SegmentList::getSegmentNumberByScaledTime(stime_t time, uint64_t *ret) const
{ {
*ret = pruned; std::vector<ISegment *> allsubsegments;
return SegmentInfoCommon::getSegmentNumberByScaledTime(segments, time, ret); std::vector<ISegment *>::const_iterator it;
for(it=segments.begin(); it!=segments.end(); ++it)
{
std::vector<ISegment *> list = (*it)->subSegments();
allsubsegments.insert( allsubsegments.end(), list.begin(), list.end() );
}
return SegmentInfoCommon::getSegmentNumberByScaledTime(allsubsegments, time, ret);
} }
mtime_t SegmentList::getPlaybackTimeBySegmentNumber(uint64_t number) mtime_t SegmentList::getPlaybackTimeBySegmentNumber(uint64_t number)
{ {
if(number < pruned || segments.empty()) if(segments.empty())
return VLC_TS_INVALID; return VLC_TS_INVALID;
const uint64_t timescale = inheritTimescale(); const uint64_t timescale = inheritTimescale();
stime_t time = segments.at(0)->startTime.Get(); const ISegment *first = segments.front();
if(first->getSequenceNumber() > number)
if(segments.at(0)->duration.Get()) return VLC_TS_INVALID;
{
number -= pruned;
for(size_t i=0; i<number && i<segments.size(); i++) stime_t time = first->startTime.Get();
time += segments.at(i)->duration.Get(); std::vector<ISegment *>::iterator it = segments.begin();
} for(it = segments.begin(); it != segments.end(); ++it)
else
{ {
time = number * duration.Get(); const ISegment *seg = *it;
/* Assuming there won't be any discontinuity in sequence */
if(seg->getSequenceNumber() == number)
{
break;
}
else if(seg->duration.Get())
{
time += seg->duration.Get();
}
else
{
time += duration.Get();
}
} }
return VLC_TS_0 + CLOCK_FREQ * time / timescale; return VLC_TS_0 + CLOCK_FREQ * time / timescale;
} }
std::size_t SegmentList::getOffset() const
{
return pruned;
}
...@@ -46,16 +46,15 @@ namespace adaptative ...@@ -46,16 +46,15 @@ namespace adaptative
virtual ~SegmentList (); virtual ~SegmentList ();
const std::vector<ISegment *>& getSegments() const; const std::vector<ISegment *>& getSegments() const;
ISegment * getSegmentByNumber(uint64_t);
void addSegment(ISegment *seg); void addSegment(ISegment *seg);
void mergeWith(SegmentList *); void mergeWith(SegmentList *);
void pruneBySegmentNumber(uint64_t); void pruneBySegmentNumber(uint64_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);
std::size_t getOffset() const;
private: private:
std::vector<ISegment *> segments; std::vector<ISegment *> segments;
std::size_t pruned;
}; };
} }
} }
......
...@@ -30,7 +30,6 @@ using namespace adaptative::playlist; ...@@ -30,7 +30,6 @@ using namespace adaptative::playlist;
SegmentTimeline::SegmentTimeline(TimescaleAble *parent) SegmentTimeline::SegmentTimeline(TimescaleAble *parent)
:TimescaleAble(parent) :TimescaleAble(parent)
{ {
pruned = 0;
} }
SegmentTimeline::~SegmentTimeline() SegmentTimeline::~SegmentTimeline()
...@@ -56,7 +55,7 @@ void SegmentTimeline::addElement(uint64_t number, stime_t d, uint64_t r, stime_t ...@@ -56,7 +55,7 @@ void SegmentTimeline::addElement(uint64_t number, stime_t d, uint64_t r, stime_t
uint64_t SegmentTimeline::getElementNumberByScaledPlaybackTime(stime_t scaled) const uint64_t SegmentTimeline::getElementNumberByScaledPlaybackTime(stime_t scaled) const
{ {
uint64_t count = 0; uint64_t prevnumber = 0;
std::list<Element *>::const_iterator it; std::list<Element *>::const_iterator it;
for(it = elements.begin(); it != elements.end(); ++it) for(it = elements.begin(); it != elements.end(); ++it)
{ {
...@@ -64,58 +63,48 @@ uint64_t SegmentTimeline::getElementNumberByScaledPlaybackTime(stime_t scaled) c ...@@ -64,58 +63,48 @@ uint64_t SegmentTimeline::getElementNumberByScaledPlaybackTime(stime_t scaled) c
for(uint64_t repeat = 1 + el->r; repeat; repeat--) for(uint64_t repeat = 1 + el->r; repeat; repeat--)
{ {
if(el->d >= scaled) if(el->d >= scaled)
return count; return prevnumber;
scaled -= el->d; scaled -= el->d;
count++; prevnumber++;
} }
/* might have been discontinuity */
prevnumber = el->number;
} }
count += pruned;
return count; return prevnumber;
} }
stime_t SegmentTimeline::getScaledPlaybackTimeByElementNumber(uint64_t number) const stime_t SegmentTimeline::getScaledPlaybackTimeByElementNumber(uint64_t number) const
{ {
stime_t totalscaledtime = 0; stime_t totalscaledtime = 0;
if(number < pruned)
return 0;
number -= pruned;
std::list<Element *>::const_iterator it; std::list<Element *>::const_iterator it;
for(it = elements.begin(); it != elements.end(); ++it) for(it = elements.begin(); it != elements.end(); ++it)
{ {
const Element *el = *it; const Element *el = *it;
if(number == 0) if(number >= el->number)
{
totalscaledtime = el->t;
break;
}
else if(number <= el->r)
{ {
if(number <= el->number + el->r)
{
return el->t + (number * el->d);
}
totalscaledtime = el->t + (number * el->d); totalscaledtime = el->t + (number * el->d);
break;
}
else
{
number -= el->r + 1;
} }
} }
return totalscaledtime; return totalscaledtime;
} }
size_t SegmentTimeline::maxElementNumber() const uint64_t SegmentTimeline::maxElementNumber() const
{ {
size_t count = 0; if(elements.empty())
return 0;
std::list<Element *>::const_iterator it;
for(it = elements.begin(); it != elements.end(); ++it)
count += (*it)->r + 1;
return pruned + count - 1; const Element *e = elements.back();
return e->number + e->r;
} }
size_t SegmentTimeline::prune(mtime_t time) size_t SegmentTimeline::prune(mtime_t time)
...@@ -135,7 +124,6 @@ size_t SegmentTimeline::prune(mtime_t time) ...@@ -135,7 +124,6 @@ size_t SegmentTimeline::prune(mtime_t time)
break; break;
} }
pruned += prunednow;
return prunednow; return prunednow;
} }
......
...@@ -46,7 +46,7 @@ namespace adaptative ...@@ -46,7 +46,7 @@ namespace adaptative
void addElement(uint64_t, stime_t d, uint64_t r = 0, stime_t t = 0); void addElement(uint64_t, stime_t d, uint64_t r = 0, stime_t t = 0);
uint64_t getElementNumberByScaledPlaybackTime(stime_t) const; uint64_t getElementNumberByScaledPlaybackTime(stime_t) const;
stime_t getScaledPlaybackTimeByElementNumber(uint64_t) const; stime_t getScaledPlaybackTimeByElementNumber(uint64_t) const;
size_t maxElementNumber() const; uint64_t maxElementNumber() const;
size_t prune(mtime_t); size_t prune(mtime_t);
void mergeWith(SegmentTimeline &); void mergeWith(SegmentTimeline &);
mtime_t start() const; mtime_t start() const;
...@@ -54,7 +54,6 @@ namespace adaptative ...@@ -54,7 +54,6 @@ namespace adaptative
private: private:
std::list<Element *> elements; std::list<Element *> elements;
size_t pruned;
class Element class Element
{ {
......
...@@ -395,6 +395,8 @@ size_t IsoffMainParser::parseSegmentList(Node * segListNode, SegmentInformation ...@@ -395,6 +395,8 @@ size_t IsoffMainParser::parseSegmentList(Node * segListNode, SegmentInformation
nzStartTime += list->duration.Get(); nzStartTime += list->duration.Get();
} }
seg->setSequenceNumber(total);
list->addSegment(seg); list->addSegment(seg);
total++; total++;
} }
......
...@@ -89,7 +89,7 @@ void Representation::addDependency(const Representation *dep) ...@@ -89,7 +89,7 @@ void Representation::addDependency(const Representation *dep)
this->dependencies.push_back( dep ); this->dependencies.push_back( dep );
} }
std::string Representation::contextualize(size_t index, const std::string &component, std::string Representation::contextualize(size_t number, const std::string &component,
const BaseSegmentTemplate *basetempl) const const BaseSegmentTemplate *basetempl) const
{ {
std::string ret(component); std::string ret(component);
...@@ -103,7 +103,7 @@ std::string Representation::contextualize(size_t index, const std::string &compo ...@@ -103,7 +103,7 @@ std::string Representation::contextualize(size_t index, const std::string &compo
if(pos != std::string::npos) if(pos != std::string::npos)
{ {
std::stringstream ss; std::stringstream ss;
ss << getScaledTimeBySegmentNumber(index, templ); ss << getScaledTimeBySegmentNumber(number, templ);
ret.replace(pos, std::string("$Time$").length(), ss.str()); ret.replace(pos, std::string("$Time$").length(), ss.str());
} }