Commit f8af0beb authored by Francois Cartegnie's avatar Francois Cartegnie

demux: adaptative: change relative playbackoffset to absolute

parent 0b57f64d
......@@ -34,6 +34,7 @@ SegmentTracker::SegmentTracker(AbstractAdaptationLogic *logic_, BaseAdaptationSe
initializing = true;
index_sent = false;
init_sent = false;
sequence_set = false;
prevRepresentation = NULL;
setAdaptationLogic(logic_);
adaptationSet = adaptSet;
......@@ -51,7 +52,7 @@ void SegmentTracker::setAdaptationLogic(AbstractAdaptationLogic *logic_)
void SegmentTracker::resetCounter()
{
count = 0;
sequence_set = false;
prevRepresentation = NULL;
}
......@@ -87,6 +88,18 @@ SegmentChunk * SegmentTracker::getNextChunk(bool switch_allowed)
/* Ensure content is loaded */
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)
{
init_sent = true;
......@@ -121,9 +134,9 @@ SegmentChunk * SegmentTracker::getNextChunk(bool switch_allowed)
bool SegmentTracker::setPosition(mtime_t time, bool restarted, bool tryonly)
{
uint64_t segcount;
uint64_t segnumber;
if(prevRepresentation &&
prevRepresentation->getSegmentNumberByTime(time, &segcount))
prevRepresentation->getSegmentNumberByTime(time, &segnumber))
{
if(!tryonly)
{
......@@ -133,7 +146,8 @@ bool SegmentTracker::setPosition(mtime_t time, bool restarted, bool tryonly)
index_sent = false;
init_sent = false;
}
count = segcount;
count = segnumber;
sequence_set = true;
}
return true;
}
......@@ -142,7 +156,7 @@ bool SegmentTracker::setPosition(mtime_t time, bool restarted, bool tryonly)
mtime_t SegmentTracker::getSegmentStart() const
{
if(prevRepresentation)
if(prevRepresentation && sequence_set)
return prevRepresentation->getPlaybackTimeBySegmentNumber(count);
else
return 0;
......@@ -151,6 +165,6 @@ mtime_t SegmentTracker::getSegmentStart() const
void SegmentTracker::pruneFromCurrent()
{
AbstractPlaylist *playlist = adaptationSet->getPlaylist();
if(playlist->isLive())
if(playlist->isLive() && sequence_set)
playlist->pruneBySegmentNumber(count);
}
......@@ -61,6 +61,7 @@ namespace adaptative
bool initializing;
bool index_sent;
bool init_sent;
bool sequence_set;
uint64_t count;
AbstractAdaptationLogic *logic;
BaseAdaptationSet *adaptationSet;
......
......@@ -114,7 +114,8 @@ size_t ISegment::getOffset() const
void ISegment::debug(vlc_object_t *obj, int indent) const
{
std::stringstream ss;
ss << std::string(indent, ' ') << debugName << " url=" << getUrlSegment().toString();
ss << std::string(indent, ' ') << debugName << " #" << getSequenceNumber();
ss << " url=" << getUrlSegment().toString();
if(startByte!=endByte)
ss << " @" << startByte << ".." << endByte;
msg_Dbg(obj, "%s", ss.str().c_str());
......@@ -162,6 +163,13 @@ Segment::Segment(ICanonicalUrl *parent) :
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);
}
......
......@@ -71,6 +71,8 @@ bool SegmentInfoCommon::getSegmentNumberByScaledTime(const std::vector<ISegment
if(segments.empty() || (segments.size() > 1 && segments[1]->startTime.Get() == 0) )
return false;
*ret = 0;
std::vector<ISegment *>::const_iterator it = segments.begin();
while(it != segments.end())
{
......@@ -83,10 +85,9 @@ bool SegmentInfoCommon::getSegmentNumberByScaledTime(const std::vector<ISegment
break;
}
(*ret)++;
*ret = seg->getSequenceNumber();
it++;
}
(*ret)--;
return true;
}
......@@ -68,10 +68,8 @@ AbstractPlaylist * SegmentInformation::getPlaylist() const
return NULL;
}
std::size_t SegmentInformation::getSegments(SegmentInfoType type, std::vector<ISegment *> &retSegments,
std::size_t *offset) const
std::size_t SegmentInformation::getSegments(SegmentInfoType type, std::vector<ISegment *> &retSegments) const
{
std::size_t off = 0;
switch (type)
{
case INFOTYPE_INIT:
......@@ -107,7 +105,6 @@ std::size_t SegmentInformation::getSegments(SegmentInfoType type, std::vector<IS
std::vector<ISegment *> list = (*it)->subSegments();
retSegments.insert( retSegments.end(), list.begin(), list.end() );
}
off = segmentList->getOffset();
}
else if( segmentBase )
{
......@@ -137,12 +134,10 @@ std::size_t SegmentInformation::getSegments(SegmentInfoType type, std::vector<IS
if( retSegments.empty() && parent )
{
return parent->getSegments( type, retSegments, offset );
return parent->getSegments( type, retSegments );
}
else
{
if( offset )
*offset = off;
return retSegments.size();
}
}
......@@ -160,11 +155,8 @@ std::size_t SegmentInformation::getAllSegments(std::vector<ISegment *> &retSegme
ISegment * SegmentInformation::getSegment(SegmentInfoType type, uint64_t pos) const
{
ISegment *segment = NULL;
std::vector<ISegment *> retSegments;
std::size_t offset = 0;
const size_t size = getSegments( type, retSegments, &offset );
const size_t size = getSegments( type, retSegments );
if( size )
{
/* check if that's a template (fixme: find a better way) */
......@@ -175,13 +167,24 @@ ISegment * SegmentInformation::getSegment(SegmentInfoType type, uint64_t pos) co
templ->segmentTimeline.Get()->maxElementNumber() > pos)
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
......@@ -190,9 +193,10 @@ bool SegmentInformation::getSegmentNumberByTime(mtime_t time, uint64_t *ret) con
{
const uint64_t timescale = mediaSegmentTemplate->inheritTimescale();
const mtime_t duration = mediaSegmentTemplate->duration.Get();
*ret = mediaSegmentTemplate->startNumber.Get();
if(duration)
{
*ret = time / (CLOCK_FREQ * duration / timescale);
*ret += time / (CLOCK_FREQ * duration / timescale);
return true;
}
}
......
......@@ -88,7 +88,7 @@ namespace adaptative
protected:
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;
SegmentInformation * getChildByID( const ID & );
SegmentInformation *parent;
......
......@@ -31,7 +31,6 @@ using namespace adaptative::playlist;
SegmentList::SegmentList( SegmentInformation *parent ):
SegmentInfoCommon( parent ), TimescaleAble( parent )
{
pruned = 0;
}
SegmentList::~SegmentList()
{
......@@ -45,6 +44,24 @@ const std::vector<ISegment*>& SegmentList::getSegments() const
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)
{
seg->setParent(this);
......@@ -68,54 +85,64 @@ void SegmentList::mergeWith(SegmentList *updated)
void SegmentList::pruneBySegmentNumber(uint64_t tobelownum)
{
if(tobelownum < pruned)
return;
uint64_t current = pruned;
std::vector<ISegment *>::iterator it = segments.begin();
while(it != segments.end() && current < tobelownum)
while(it != segments.end())
{
ISegment *seg = *it;
if(seg->getSequenceNumber() >= tobelownum)
break;
if(seg->chunksuse.Get()) /* can't prune from here, still in use */
break;
delete *it;
it = segments.erase(it);
current++;
pruned++;
}
}
bool SegmentList::getSegmentNumberByScaledTime(stime_t time, uint64_t *ret) const
{
*ret = pruned;
return SegmentInfoCommon::getSegmentNumberByScaledTime(segments, time, ret);
std::vector<ISegment *> allsubsegments;
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)
{
if(number < pruned || segments.empty())
if(segments.empty())
return VLC_TS_INVALID;
const uint64_t timescale = inheritTimescale();
stime_t time = segments.at(0)->startTime.Get();
if(segments.at(0)->duration.Get())
{
number -= pruned;
const ISegment *first = segments.front();
if(first->getSequenceNumber() > number)
return VLC_TS_INVALID;
for(size_t i=0; i<number && i<segments.size(); i++)
time += segments.at(i)->duration.Get();
}
else
stime_t time = first->startTime.Get();
std::vector<ISegment *>::iterator it = segments.begin();
for(it = segments.begin(); it != segments.end(); ++it)
{
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;
}
std::size_t SegmentList::getOffset() const
{
return pruned;
}
......@@ -46,16 +46,15 @@ namespace adaptative
virtual ~SegmentList ();
const std::vector<ISegment *>& getSegments() const;
ISegment * getSegmentByNumber(uint64_t);
void addSegment(ISegment *seg);
void mergeWith(SegmentList *);
void pruneBySegmentNumber(uint64_t);
bool getSegmentNumberByScaledTime(stime_t, uint64_t *) const;
mtime_t getPlaybackTimeBySegmentNumber(uint64_t);
std::size_t getOffset() const;
private:
std::vector<ISegment *> segments;
std::size_t pruned;
};
}
}
......
......@@ -30,7 +30,6 @@ using namespace adaptative::playlist;
SegmentTimeline::SegmentTimeline(TimescaleAble *parent)
:TimescaleAble(parent)
{
pruned = 0;
}
SegmentTimeline::~SegmentTimeline()
......@@ -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 count = 0;
uint64_t prevnumber = 0;
std::list<Element *>::const_iterator it;
for(it = elements.begin(); it != elements.end(); ++it)
{
......@@ -64,58 +63,48 @@ uint64_t SegmentTimeline::getElementNumberByScaledPlaybackTime(stime_t scaled) c
for(uint64_t repeat = 1 + el->r; repeat; repeat--)
{
if(el->d >= scaled)
return count;
return prevnumber;
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 totalscaledtime = 0;
if(number < pruned)
return 0;
number -= pruned;
std::list<Element *>::const_iterator it;
for(it = elements.begin(); it != elements.end(); ++it)
{
const Element *el = *it;
if(number == 0)
{
totalscaledtime = el->t;
break;
}
else if(number <= el->r)
if(number >= el->number)
{
if(number <= el->number + el->r)
{
return el->t + (number * el->d);
}
totalscaledtime = el->t + (number * el->d);
break;
}
else
{
number -= el->r + 1;
}
}
return totalscaledtime;
}
size_t SegmentTimeline::maxElementNumber() const
uint64_t SegmentTimeline::maxElementNumber() const
{
size_t count = 0;
std::list<Element *>::const_iterator it;
for(it = elements.begin(); it != elements.end(); ++it)
count += (*it)->r + 1;
if(elements.empty())
return 0;
return pruned + count - 1;
const Element *e = elements.back();
return e->number + e->r;
}
size_t SegmentTimeline::prune(mtime_t time)
......@@ -135,7 +124,6 @@ size_t SegmentTimeline::prune(mtime_t time)
break;
}
pruned += prunednow;
return prunednow;
}
......
......@@ -46,7 +46,7 @@ namespace adaptative
void addElement(uint64_t, stime_t d, uint64_t r = 0, stime_t t = 0);
uint64_t getElementNumberByScaledPlaybackTime(stime_t) const;
stime_t getScaledPlaybackTimeByElementNumber(uint64_t) const;
size_t maxElementNumber() const;
uint64_t maxElementNumber() const;
size_t prune(mtime_t);
void mergeWith(SegmentTimeline &);
mtime_t start() const;
......@@ -54,7 +54,6 @@ namespace adaptative
private:
std::list<Element *> elements;
size_t pruned;
class Element
{
......
......@@ -395,6 +395,8 @@ size_t IsoffMainParser::parseSegmentList(Node * segListNode, SegmentInformation
nzStartTime += list->duration.Get();
}
seg->setSequenceNumber(total);
list->addSegment(seg);
total++;
}
......
......@@ -89,7 +89,7 @@ void Representation::addDependency(const Representation *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
{
std::string ret(component);
......@@ -103,7 +103,7 @@ std::string Representation::contextualize(size_t index, const std::string &compo
if(pos != std::string::npos)
{
std::stringstream ss;
ss << getScaledTimeBySegmentNumber(index, templ);
ss << getScaledTimeBySegmentNumber(number, templ);
ret.replace(pos, std::string("$Time$").length(), ss.str());
}
......@@ -111,7 +111,7 @@ std::string Representation::contextualize(size_t index, const std::string &compo
if(pos != std::string::npos)
{
std::stringstream ss;
ss << getSegmentNumber(index, templ);
ss << getLiveTemplateNumberOffset(number, templ);
ret.replace(pos, std::string("$Number$").length(), ss.str());
}
else
......@@ -134,7 +134,7 @@ std::string Representation::contextualize(size_t index, const std::string &compo
std::stringstream oss;
oss.width(width); /* set format string length */
oss.fill('0');
oss << getSegmentNumber(index, templ);
oss << getLiveTemplateNumberOffset(number, templ);
ret.replace(pos, fmtend - pos + 1, oss.str());
} catch(int) {}
}
......@@ -157,7 +157,7 @@ std::string Representation::contextualize(size_t index, const std::string &compo
return ret;
}
mtime_t Representation::getScaledTimeBySegmentNumber(size_t index, const MediaSegmentTemplate *templ) const
mtime_t Representation::getScaledTimeBySegmentNumber(uint64_t index, const MediaSegmentTemplate *templ) const
{
mtime_t time = 0;
if(templ->segmentTimeline.Get())
......@@ -171,9 +171,8 @@ mtime_t Representation::getScaledTimeBySegmentNumber(size_t index, const MediaSe
return time;
}
size_t Representation::getSegmentNumber(size_t index, const MediaSegmentTemplate *templ) const
uint64_t Representation::getLiveTemplateNumberOffset(uint64_t index, const MediaSegmentTemplate *templ) const
{
index += templ->startNumber.Get();
/* live streams / templated */
if(getPlaylist()->isLive())
{
......@@ -183,13 +182,13 @@ size_t Representation::getSegmentNumber(size_t index, const MediaSegmentTemplate
}
else if(templ->duration.Get())
{
const mtime_t playbackstart = getPlaylist()->playbackStart.Get() * CLOCK_FREQ;
mtime_t streamstart = getPlaylist()->availabilityStartTime.Get() * CLOCK_FREQ;
const time_t playbackstart = getPlaylist()->playbackStart.Get();
time_t streamstart = getPlaylist()->availabilityStartTime.Get();
streamstart += getPeriodStart();
const stime_t duration = templ->duration.Get();
const uint64_t timescale = templ->inheritTimescale();
if(duration && timescale)
index += (playbackstart - streamstart) * timescale * duration / CLOCK_FREQ;
index += (playbackstart - streamstart) * CLOCK_FREQ / (timescale * duration);
}
}
return index;
......
......@@ -71,8 +71,8 @@ namespace dash
TrickModeType *trickModeType;
/* for contextualize() */
mtime_t getScaledTimeBySegmentNumber(size_t, const MediaSegmentTemplate *) const;
size_t getSegmentNumber(size_t, const MediaSegmentTemplate *) const;
mtime_t getScaledTimeBySegmentNumber(uint64_t, const MediaSegmentTemplate *) const;
uint64_t getLiveTemplateNumberOffset(uint64_t, const MediaSegmentTemplate *) const;
};
}
}
......
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