Skip to content
Snippets Groups Projects
Commit b15abfbf authored by François Cartegnie's avatar François Cartegnie :fingers_crossed:
Browse files

demux: adaptive: rework profile specific types for global timeline

parent 844f58a8
No related branches found
No related tags found
1 merge request!41WIP D3d12/31 test UWP sample build
Showing
with 866 additions and 662 deletions
......@@ -315,10 +315,10 @@ libadaptive_plugin_la_SOURCES = \
demux/adaptive/playlist/Segment.h \
demux/adaptive/playlist/SegmentBase.cpp \
demux/adaptive/playlist/SegmentBase.h \
demux/adaptive/playlist/SegmentBaseType.cpp \
demux/adaptive/playlist/SegmentBaseType.hpp \
demux/adaptive/playlist/SegmentChunk.cpp \
demux/adaptive/playlist/SegmentChunk.hpp \
demux/adaptive/playlist/SegmentInfoCommon.cpp \
demux/adaptive/playlist/SegmentInfoCommon.h \
demux/adaptive/playlist/SegmentList.cpp \
demux/adaptive/playlist/SegmentList.h \
demux/adaptive/playlist/SegmentTimeline.cpp \
......
......@@ -80,24 +80,8 @@ uint64_t DefaultBufferingLogic::getStartSegmentNumber(BaseRepresentation *rep) c
if(rep->getPlaylist()->isLive())
return getLiveStartSegmentNumber(rep);
const MediaSegmentTemplate *segmentTemplate = rep->inheritSegmentTemplate();
if(segmentTemplate)
{
const SegmentTimeline *timeline = segmentTemplate->inheritSegmentTimeline();
if(timeline)
return timeline->minElementNumber();
return segmentTemplate->inheritStartNumber();
}
const SegmentList *list = rep->inheritSegmentList();
if(list)
return list->getStartIndex();
const SegmentBase *base = rep->inheritSegmentBase();
if(base)
return base->getSequenceNumber();
return 0;
const AbstractSegmentBaseType *profile = rep->inheritSegmentProfile();
return profile ? profile->getStartSegmentNumber() : 0;
}
vlc_tick_t DefaultBufferingLogic::getMinBuffering(const AbstractPlaylist *p) const
......@@ -154,7 +138,7 @@ uint64_t DefaultBufferingLogic::getLiveStartSegmentNumber(BaseRepresentation *re
SegmentList *segmentList = rep->inheritSegmentList();
SegmentBase *segmentBase = rep->inheritSegmentBase();
MediaSegmentTemplate *mediaSegmentTemplate = rep->inheritSegmentTemplate();
SegmentTemplate *mediaSegmentTemplate = rep->inheritSegmentTemplate();
if(mediaSegmentTemplate)
{
uint64_t start = 0;
......@@ -347,8 +331,8 @@ uint64_t DefaultBufferingLogic::getLiveStartSegmentNumber(BaseRepresentation *re
const stime_t bufferingstart = back->startTime.Get() + back->duration.Get() -
timescale.ToScaled(i_buffering);
uint64_t start;
if(!SegmentInfoCommon::getSegmentNumberByScaledTime(list, bufferingstart, &start))
uint64_t start = AbstractSegmentBaseType::findSegmentNumberByScaledTime(list, bufferingstart);
if(start == std::numeric_limits<uint64_t>::max())
return list.front()->getSequenceNumber();
if(segmentBase->getSequenceNumber() + SAFETY_BUFFERING_EDGE_OFFSET <= start)
......
......@@ -137,6 +137,9 @@ void BaseAdaptationSet::debug(vlc_object_t *obj, int indent) const
text.append("BaseAdaptationSet ");
text.append(id.str());
msg_Dbg(obj, "%s", text.c_str());
const AbstractSegmentBaseType *profile = getProfile();
if(profile)
profile->debug(obj, indent + 1);
std::vector<BaseRepresentation *>::const_iterator k;
for(k = representations.begin(); k != representations.end(); ++k)
(*k)->debug(obj, indent + 1);
......
......@@ -28,6 +28,7 @@
#include "BasePeriod.h"
#include "AbstractPlaylist.hpp"
#include "SegmentBaseType.hpp"
#include "../Streams.hpp"
#include <vlc_common.h>
......@@ -90,6 +91,9 @@ void BasePeriod::debug(vlc_object_t *obj, int indent) const
std::string text(indent, ' ');
text.append("Period");
msg_Dbg(obj, "%s", text.c_str());
const AbstractSegmentBaseType *profile = getProfile();
if(profile)
profile->debug(obj, indent + 1);
std::vector<BaseAdaptationSet *>::const_iterator k;
for(k = adaptationSets.begin(); k != adaptationSets.end(); ++k)
(*k)->debug(obj, indent + 1);
......
......@@ -122,34 +122,13 @@ void BaseRepresentation::pruneByPlaybackTime(vlc_tick_t time)
vlc_tick_t BaseRepresentation::getMinAheadTime(uint64_t curnum) const
{
std::vector<Segment *> seglist;
getMediaSegments(seglist);
AbstractSegmentBaseType *profile = inheritSegmentTemplate();
if(!profile)
profile = inheritSegmentList();
if(!profile)
profile = inheritSegmentBase();
if(seglist.size() == 1 && seglist.front()->isTemplate())
{
const MediaSegmentTemplate *templ = dynamic_cast<MediaSegmentTemplate *>(seglist.front());
if(templ)
{
const Timescale timescale = templ->inheritTimescale();
stime_t i_length = templ->getMinAheadScaledTime(curnum);
return timescale.ToTime(i_length);
}
/* should not happen */
return VLC_TICK_FROM_SEC(1);
}
vlc_tick_t minTime = 0;
const Timescale timescale = inheritTimescale();
std::vector<Segment *>::const_iterator it;
for(it = seglist.begin(); it != seglist.end(); ++it)
{
const Segment *seg = *it;
if(seg->getSequenceNumber() > curnum)
minTime += timescale.ToTime(seg->duration.Get());
}
return minTime;
return profile ? profile->getMinAheadTime(curnum) : 0;
}
void BaseRepresentation::debug(vlc_object_t *obj, int indent) const
......@@ -166,20 +145,13 @@ void BaseRepresentation::debug(vlc_object_t *obj, int indent) const
text.append("]");
}
msg_Dbg(obj, "%s", text.c_str());
const ISegment *seg;
if((seg = getInitSegment()))
seg->debug(obj, indent + 1);
if((seg = getIndexSegment()))
seg->debug(obj, indent + 1);
std::vector<Segment *> list;
getMediaSegments(list);
std::vector<Segment *>::const_iterator l;
for(l = list.begin(); l != list.end(); ++l)
(*l)->debug(obj, indent + 1);
const AbstractSegmentBaseType *profile = getProfile();
if(profile)
profile->debug(obj, indent + 1);
}
std::string BaseRepresentation::contextualize(size_t, const std::string &component,
const BaseSegmentTemplate *) const
const SegmentTemplate *) const
{
return component;
}
......@@ -205,64 +177,8 @@ uint64_t BaseRepresentation::translateSegmentNumber(uint64_t num, const BaseRepr
bool BaseRepresentation::getSegmentNumberByTime(vlc_tick_t time, uint64_t *ret) const
{
MediaSegmentTemplate *mediaSegmentTemplate = inheritSegmentTemplate();
if( mediaSegmentTemplate )
{
const SegmentTimeline *timeline = mediaSegmentTemplate->inheritSegmentTimeline();
if(timeline)
{
const Timescale timescale = timeline->getTimescale().isValid()
? timeline->getTimescale()
: mediaSegmentTemplate->inheritTimescale();
stime_t st = timescale.ToScaled(time);
*ret = timeline->getElementNumberByScaledPlaybackTime(st);
return true;
}
const stime_t duration = mediaSegmentTemplate->duration.Get();
if( duration )
{
if( getPlaylist()->isLive() )
{
vlc_tick_t now = vlc_tick_from_sec(::time(NULL));
if(getPlaylist()->availabilityStartTime.Get())
{
if(time >= getPlaylist()->availabilityStartTime.Get() && time < now)
*ret = mediaSegmentTemplate->getLiveTemplateNumber(time, true);
else if(now - getPlaylist()->availabilityStartTime.Get() > time)
*ret = mediaSegmentTemplate->getLiveTemplateNumber(time, false);
}
else return false;
}
else
{
const Timescale timescale = mediaSegmentTemplate->inheritTimescale();
*ret = mediaSegmentTemplate->inheritStartNumber();
*ret += timescale.ToScaled(time) / duration;
}
return true;
}
}
SegmentList *segmentList = inheritSegmentList();
if ( segmentList && !segmentList->getSegments().empty() )
{
const Timescale timescale = segmentList->inheritTimescale();
stime_t st = timescale.ToScaled(time);
return segmentList->getSegmentNumberByScaledTime(st, ret);
}
SegmentBase *segmentBase = inheritSegmentBase();
if( segmentBase )
{
const Timescale timescale = inheritTimescale();
stime_t st = timescale.ToScaled(time);
*ret = 0;
const std::vector<Segment *> &list = segmentBase->subSegments();
return SegmentInfoCommon::getSegmentNumberByScaledTime(list, st, ret);
}
return false;
const AbstractSegmentBaseType *profile = inheritSegmentProfile();
return profile && profile->getSegmentNumberByTime(time, ret);
}
bool BaseRepresentation::getPlaybackTimeDurationBySegmentNumber(uint64_t number,
......@@ -271,56 +187,15 @@ bool BaseRepresentation::getPlaybackTimeDurationBySegmentNumber(uint64_t number,
if(number == std::numeric_limits<uint64_t>::max())
return false;
MediaSegmentTemplate *mediaTemplate = inheritSegmentTemplate();
if( mediaTemplate )
{
const Timescale timescale = mediaTemplate->inheritTimescale();
const SegmentTimeline * timeline = mediaTemplate->inheritSegmentTimeline();
stime_t stime, sduration;
if(timeline)
{
if(!timeline->getScaledPlaybackTimeDurationBySegmentNumber(number, &stime, &sduration))
return false;
}
else
{
uint64_t startNumber = mediaTemplate->inheritStartNumber();
if(number < startNumber)
return false;
sduration = mediaTemplate->inheritDuration();
stime = (number - startNumber) * sduration;
}
*time = timescale.ToTime(stime);
*duration = timescale.ToTime(sduration);
return true;
}
SegmentList *segList = inheritSegmentList();
if ( segList )
{
return segList->getPlaybackTimeDurationBySegmentNumber(number, time, duration);
}
else
{
const Timescale timescale = inheritTimescale();
const ISegment *segment = getMediaSegment(number);
if( segment )
{
*time = timescale.ToTime(segment->startTime.Get());
*duration = timescale.ToTime(segment->duration.Get());
return true;
}
}
return false;
const AbstractSegmentBaseType *profile = inheritSegmentProfile();
return profile && profile->getPlaybackTimeDurationBySegmentNumber(number, time, duration);
}
bool BaseRepresentation::getMediaPlaybackRange(vlc_tick_t *rangeBegin,
vlc_tick_t *rangeEnd,
vlc_tick_t *rangeLength) const
{
MediaSegmentTemplate *mediaSegmentTemplate = inheritSegmentTemplate();
SegmentTemplate *mediaSegmentTemplate = inheritSegmentTemplate();
if( mediaSegmentTemplate )
{
const Timescale timescale = mediaSegmentTemplate->inheritTimescale();
......
......@@ -40,7 +40,7 @@ namespace adaptive
{
class BaseAdaptationSet;
class AbstractPlaylist;
class BaseSegmentTemplate;
class SegmentTemplateSegment;
class BaseRepresentation : public CommonAttributesElements,
public SegmentInformation
......@@ -74,7 +74,7 @@ namespace adaptive
/* for segment templates */
virtual std::string contextualize(size_t, const std::string &,
const BaseSegmentTemplate *) const;
const SegmentTemplate *) const;
static bool bwCompare(const BaseRepresentation *a,
const BaseRepresentation *b);
......
......@@ -283,14 +283,4 @@ SubSegment::SubSegment(Segment *main, size_t start, size_t end) :
classId = CLASSID_SUBSEGMENT;
}
SegmentChunk* SubSegment::createChunk(AbstractChunkSource *source, BaseRepresentation *rep)
{
/* act as factory */
return new (std::nothrow) SegmentChunk(source, rep);
}
Url SubSegment::getUrlSegment() const
{
return getParentUrlSegment();
}
......@@ -47,6 +47,7 @@ namespace adaptive
{
class BaseRepresentation;
class SubSegment;
class Segment;
class SegmentChunk;
using namespace http;
......@@ -131,8 +132,6 @@ namespace adaptive
{
public:
SubSegment(Segment *, size_t start, size_t end);
virtual SegmentChunk* createChunk(AbstractChunkSource *, BaseRepresentation *); /* impl */
virtual Url getUrlSegment() const; /* impl */
static const int CLASSID_SUBSEGMENT = 4;
};
}
......
......@@ -26,13 +26,107 @@
#endif
#include "SegmentBase.h"
#include "SegmentInformation.hpp"
#include <limits>
using namespace adaptive::playlist;
SegmentBase::SegmentBase(ICanonicalUrl *parent) :
Segment(parent)
SegmentBase::SegmentBase(SegmentInformation *parent) :
Segment(parent), AbstractSegmentBaseType(parent)
{
this->parent = parent;
}
SegmentBase::~SegmentBase ()
{
}
vlc_tick_t SegmentBase::getMinAheadTime(uint64_t curnum) const
{
const std::vector<Segment *> &segments = subSegments();
vlc_tick_t minTime = 0;
const Timescale timescale = inheritTimescale();
std::vector<Segment *>::const_iterator it;
for(it = segments.begin(); it != segments.end(); ++it)
{
const Segment *seg = *it;
if(seg->getSequenceNumber() > curnum)
minTime += timescale.ToTime(seg->duration.Get());
}
return minTime;
}
Segment * SegmentBase::getMediaSegment(uint64_t pos) const
{
std::vector<Segment *>::const_iterator it;
for(it = subsegments.begin(); it != subsegments.end(); ++it)
{
Segment *seg = *it;
if(seg->getSequenceNumber() >= pos)
{
if(seg->getSequenceNumber() == pos)
return seg;
else
return NULL;
}
}
return NULL;
}
Segment * SegmentBase::getNextMediaSegment(uint64_t i_pos,uint64_t *pi_newpos,
bool *pb_gap) const
{
std::vector<Segment *>::const_iterator it;
for(it = subsegments.begin(); it != subsegments.end(); ++it)
{
Segment *seg = *it;
if(seg->getSequenceNumber() >= i_pos)
{
*pi_newpos = seg->getSequenceNumber();
*pb_gap = (*pi_newpos != i_pos);
return seg;
}
}
*pb_gap = false;
*pi_newpos = i_pos;
return NULL;
}
uint64_t SegmentBase::getStartSegmentNumber() const
{
return subsegments.empty() ? 0 : subsegments.front()->getSequenceNumber();
}
bool SegmentBase::getSegmentNumberByTime(vlc_tick_t time, uint64_t *ret) const
{
const Timescale timescale = inheritTimescale();
if(!timescale.isValid())
return false;
stime_t st = timescale.ToScaled(time);
*ret = AbstractSegmentBaseType::findSegmentNumberByScaledTime(subsegments, st);
return *ret != std::numeric_limits<uint64_t>::max();
}
bool SegmentBase::getPlaybackTimeDurationBySegmentNumber(uint64_t number,
vlc_tick_t *time,
vlc_tick_t *dur) const
{
const Timescale timescale = inheritTimescale();
const ISegment *segment = getMediaSegment(number);
if( segment )
{
*time = timescale.ToTime(segment->startTime.Get());
*dur = timescale.ToTime(segment->duration.Get());
return true;
}
return false;
}
void SegmentBase::debug(vlc_object_t *obj, int indent) const
{
AbstractSegmentBaseType::debug(obj, indent);
std::vector<Segment *>::const_iterator it;
for(it = subsegments.begin(); it != subsegments.end(); ++it)
(*it)->debug(obj, indent);
}
......@@ -26,21 +26,36 @@
#define SEGMENTBASE_H_
#include "Segment.h"
#include "SegmentInfoCommon.h"
#include "SegmentBaseType.hpp"
#include "../tools/Properties.hpp"
namespace adaptive
{
namespace playlist
{
class SegmentInformation;
/* SegmentBase can contain only one segment */
class SegmentBase : public Segment,
public Initializable<InitSegment>,
public Indexable<IndexSegment>
public AbstractSegmentBaseType
{
public:
SegmentBase (ICanonicalUrl *);
SegmentBase (SegmentInformation * = NULL);
virtual ~SegmentBase ();
virtual vlc_tick_t getMinAheadTime(uint64_t curnum) const; /* impl */
virtual Segment *getMediaSegment(uint64_t number) const; /* impl */
virtual Segment *getNextMediaSegment(uint64_t, uint64_t *, bool *) const; /* impl */
virtual uint64_t getStartSegmentNumber() const; /* impl */
virtual bool getSegmentNumberByTime(vlc_tick_t time, uint64_t *ret) const; /* impl */
virtual bool getPlaybackTimeDurationBySegmentNumber(uint64_t number,
vlc_tick_t *time, vlc_tick_t *duration) const; /* impl */
virtual void debug(vlc_object_t *,int = 0) const; /* reimpl */
protected:
SegmentInformation *parent;
};
}
}
......
/*
* SegmentBaseType.cpp
*****************************************************************************
* Copyright (C) 2020 VideoLabs, VideoLAN and VLC Authors
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "SegmentBaseType.hpp"
#include "SegmentInformation.hpp"
#include "SegmentTemplate.h"
#include "SegmentTimeline.h"
#include <limits>
using namespace adaptive::playlist;
Segment * AbstractSegmentBaseType::findSegmentByScaledTime(const std::vector<Segment *> &segments,
stime_t time)
{
if(segments.empty() || (segments.size() > 1 && segments[1]->startTime.Get() == 0) )
return NULL;
Segment *ret = NULL;
std::vector<Segment *>::const_iterator it = segments.begin();
while(it != segments.end())
{
Segment *seg = *it;
if(seg->startTime.Get() > time)
{
if(it == segments.begin())
return NULL;
else
break;
}
ret = seg;
it++;
}
return ret;
}
uint64_t AbstractSegmentBaseType::findSegmentNumberByScaledTime(const std::vector<Segment *> &segments,
stime_t time)
{
Segment *s = findSegmentByScaledTime(segments, time);
if(!s)
return std::numeric_limits<uint64_t>::max();
return s->getSequenceNumber();
}
AbstractSegmentBaseType::AbstractSegmentBaseType(SegmentInformation *parent)
: TimescaleAble(parent)
{
this->parent = parent;
}
AbstractSegmentBaseType::~AbstractSegmentBaseType()
{
}
InitSegment *AbstractSegmentBaseType::getInitSegment() const
{
return initialisationSegment.Get();
}
IndexSegment *AbstractSegmentBaseType::getIndexSegment() const
{
return indexSegment.Get();
}
Timescale AbstractSegmentBaseType::inheritTimescale() const
{
if(getTimescale().isValid())
return getTimescale();
if(parent)
{
if(parent->getTimescale().isValid())
return parent->getTimescale();
if(parent->getParent())
{
AbstractSegmentBaseType *bt =
dynamic_cast<AbstractSegmentBaseType *>(parent->getParent()->getProfile());
if(bt)
return bt->inheritTimescale();
}
}
return Timescale(1);
}
SegmentInformation *AbstractSegmentBaseType::getParent() const
{
return parent;
}
void AbstractSegmentBaseType::debug(vlc_object_t *obj, int indent) const
{
if(initialisationSegment.Get())
initialisationSegment.Get()->debug(obj, indent);
if(indexSegment.Get())
indexSegment.Get()->debug(obj, indent);
}
AbstractMultipleSegmentBaseType::AbstractMultipleSegmentBaseType(SegmentInformation *parent)
: AbstractSegmentBaseType(parent)
{
startNumber = std::numeric_limits<uint64_t>::max();
segmentTimeline = NULL;
duration.Set(0);
}
AbstractMultipleSegmentBaseType::~AbstractMultipleSegmentBaseType()
{
delete segmentTimeline;
}
void AbstractMultipleSegmentBaseType::setSegmentTimeline( SegmentTimeline *v )
{
delete segmentTimeline;
segmentTimeline = v;
}
SegmentTimeline * AbstractMultipleSegmentBaseType::inheritSegmentTimeline() const
{
if( segmentTimeline )
return segmentTimeline;
const SegmentInformation *ulevel = parent ? parent->getParent() : NULL;
for( ; ulevel ; ulevel = ulevel->getParent() )
{
AbstractMultipleSegmentBaseType *bt =
dynamic_cast<AbstractMultipleSegmentBaseType *>(ulevel->getProfile());
if( bt && bt->segmentTimeline )
return bt->segmentTimeline;
}
return NULL;
}
SegmentTimeline * AbstractMultipleSegmentBaseType::getSegmentTimeline() const
{
return segmentTimeline;
}
void AbstractMultipleSegmentBaseType::setStartNumber( uint64_t v )
{
startNumber = v;
}
uint64_t AbstractMultipleSegmentBaseType::inheritStartNumber() const
{
if( startNumber != std::numeric_limits<uint64_t>::max() )
return startNumber;
const SegmentInformation *ulevel = parent ? parent->getParent() : NULL;
for( ; ulevel ; ulevel = ulevel->parent )
{
AbstractMultipleSegmentBaseType *bt =
dynamic_cast<AbstractMultipleSegmentBaseType *>(ulevel->getProfile());
if( bt && bt->startNumber != std::numeric_limits<uint64_t>::max() )
return bt->startNumber;
}
return std::numeric_limits<uint64_t>::max();
}
stime_t AbstractMultipleSegmentBaseType::inheritDuration() const
{
if(duration.Get() > 0)
return duration.Get();
const SegmentInformation *ulevel = parent ? parent->getParent() : NULL;
for( ; ulevel ; ulevel = ulevel->parent )
{
AbstractMultipleSegmentBaseType *bt =
dynamic_cast<AbstractMultipleSegmentBaseType *>(ulevel->getProfile());
if( bt && bt->duration.Get() > 0 )
return bt->duration.Get();
}
return 0;
}
void AbstractMultipleSegmentBaseType::updateWith(AbstractMultipleSegmentBaseType *updated,
bool)
{
if(segmentTimeline && updated->segmentTimeline)
segmentTimeline->updateWith(*updated->segmentTimeline);
}
/*
* SegmentBaseType.hpp
*****************************************************************************
* Copyright (C) 2020 VideoLabs, VideoLAN and VLC Authors
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#ifndef SEGMENTBASETYPE_H_
#define SEGMENTBASETYPE_H_
#include "Segment.h"
#include "Inheritables.hpp"
#include "Templates.hpp"
#include "../tools/Properties.hpp"
namespace adaptive
{
namespace playlist
{
class SegmentInformation;
class SegmentTimeline;
class AbstractSegmentBaseType : public Initializable<InitSegment>,
public Indexable<IndexSegment>,
public TimescaleAble
{
public:
AbstractSegmentBaseType( SegmentInformation * );
virtual ~AbstractSegmentBaseType();
virtual vlc_tick_t getMinAheadTime(uint64_t) const = 0;
virtual Segment *getMediaSegment(uint64_t pos) const = 0;
virtual InitSegment *getInitSegment() const;
virtual IndexSegment *getIndexSegment() const;
virtual Segment *getNextMediaSegment(uint64_t, uint64_t *, bool *) const = 0;
virtual uint64_t getStartSegmentNumber() const = 0;
virtual bool getSegmentNumberByTime(vlc_tick_t time, uint64_t *ret) const = 0;
virtual bool getPlaybackTimeDurationBySegmentNumber(uint64_t number,
vlc_tick_t *time, vlc_tick_t *duration) const = 0;
Timescale inheritTimescale() const; /* reimpl */
virtual void debug(vlc_object_t *, int = 0) const;
static Segment * findSegmentByScaledTime(const std::vector<Segment *> &,
stime_t);
static uint64_t findSegmentNumberByScaledTime(const std::vector<Segment *> &,
stime_t);
SegmentInformation * getParent() const;
protected:
SegmentInformation *parent;
};
class AbstractMultipleSegmentBaseType : public AbstractSegmentBaseType
{
public:
AbstractMultipleSegmentBaseType( SegmentInformation * );
virtual ~AbstractMultipleSegmentBaseType();
void setSegmentTimeline( SegmentTimeline * );
SegmentTimeline * inheritSegmentTimeline() const;
SegmentTimeline * getSegmentTimeline() const;
void setStartNumber( uint64_t );
uint64_t inheritStartNumber() const;
stime_t inheritDuration() const;
virtual void updateWith(AbstractMultipleSegmentBaseType *, bool = false);
Property<stime_t> duration;
protected:
uint64_t startNumber;
SegmentTimeline *segmentTimeline;
};
}
}
#endif /* SEGMENTBASETYPE_H_ */
/*****************************************************************************
* SegmentInfoCommon.cpp: Implement the common part for both SegmentInfoDefault
* and SegmentInfo
*****************************************************************************
* Copyright (C) 1998-2007 VLC authors and VideoLAN
*
* Authors: Hugo Beauzée-Luyssen <hugo@beauzee.fr>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "SegmentInfoCommon.h"
using namespace adaptive::playlist;
SegmentInfoCommon::SegmentInfoCommon( ICanonicalUrl *parent ) :
ICanonicalUrl( parent ),
startIndex( 0 )
{
duration.Set(0);
}
SegmentInfoCommon::~SegmentInfoCommon()
{
}
int SegmentInfoCommon::getStartIndex() const
{
return this->startIndex;
}
void SegmentInfoCommon::setStartIndex(int startIndex)
{
if ( startIndex >= 0 )
this->startIndex = startIndex;
}
void SegmentInfoCommon::appendBaseURL(const std::string &url)
{
this->baseURLs.push_back( url );
}
Url SegmentInfoCommon::getUrlSegment() const
{
Url ret = getParentUrlSegment();
if (!baseURLs.empty())
ret.append(baseURLs.front());
return ret;
}
bool SegmentInfoCommon::getSegmentNumberByScaledTime(const std::vector<Segment *> &segments,
stime_t time, uint64_t *ret)
{
if(segments.empty() || (segments.size() > 1 && segments[1]->startTime.Get() == 0) )
return false;
*ret = 0;
std::vector<Segment *>::const_iterator it = segments.begin();
while(it != segments.end())
{
const Segment *seg = *it;
if(seg->startTime.Get() > time)
{
if(it == segments.begin())
return false;
else
break;
}
*ret = seg->getSequenceNumber();
it++;
}
return true;
}
/*****************************************************************************
* SegmentInfoCommon.h: Implement the common part for both SegmentInfoDefault
* and SegmentInfo
*****************************************************************************
* Copyright (C) 1998-2007 VLC authors and VideoLAN
*
* Authors: Hugo Beauzée-Luyssen <hugo@beauzee.fr>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#ifndef SEGMENTINFOCOMMON_H
#define SEGMENTINFOCOMMON_H
#include <string>
#include <list>
#include "Inheritables.hpp"
#include "Templates.hpp"
#include "Segment.h"
#include "ICanonicalUrl.hpp"
#include "../tools/Properties.hpp"
namespace adaptive
{
namespace playlist
{
class Segment;
class SegmentInfoCommon : public ICanonicalUrl,
public Initializable<InitSegment>,
public Indexable<IndexSegment>
{
public:
SegmentInfoCommon( ICanonicalUrl *parent = NULL );
virtual ~SegmentInfoCommon();
int getStartIndex() const;
void setStartIndex( int startIndex );
void appendBaseURL( const std::string& url );
virtual Url getUrlSegment() const; /* impl */
Property<stime_t> duration;
static bool getSegmentNumberByScaledTime(const std::vector<Segment *> &,
stime_t, uint64_t *);
private:
int startIndex;
std::list<std::string> baseURLs;
};
}
}
#endif // SEGMENTINFOCOMMON_H
......@@ -81,7 +81,7 @@ std::size_t SegmentInformation::getMediaSegments(std::vector<Segment *> &retSegm
{
if( mediaSegmentTemplate )
{
retSegments.push_back( mediaSegmentTemplate );
retSegments.push_back( mediaSegmentTemplate->getMediaSegment(0) );
}
else if ( segmentList && !segmentList->getSegments().empty() )
{
......@@ -100,144 +100,49 @@ std::size_t SegmentInformation::getMediaSegments(std::vector<Segment *> &retSegm
return retSegments.size();
}
const AbstractSegmentBaseType * SegmentInformation::inheritSegmentProfile() const
{
const AbstractSegmentBaseType *profile = inheritSegmentTemplate();
if(!profile)
profile = inheritSegmentList();
if(!profile)
profile = inheritSegmentBase();
return profile;
}
/* Returns wanted segment, or next in sequence if not found */
Segment * SegmentInformation::getNextMediaSegment(uint64_t i_pos,uint64_t *pi_newpos,
bool *pb_gap) const
{
*pb_gap = false;
*pi_newpos = i_pos;
std::vector<Segment *> retSegments;
const size_t size = getMediaSegments( retSegments );
if( size )
{
std::vector<Segment *>::const_iterator it;
for(it = retSegments.begin(); it != retSegments.end(); ++it)
{
Segment *seg = *it;
if(seg->isTemplate()) /* we don't care about seq number */
{
/* Check if we don't exceed timeline */
MediaSegmentTemplate *templ = dynamic_cast<MediaSegmentTemplate*>(retSegments[0]);
const SegmentTimeline *timeline = (templ) ? templ->inheritSegmentTimeline() : NULL;
if(timeline)
{
*pi_newpos = std::max(timeline->minElementNumber(), i_pos);
if(timeline->maxElementNumber() < i_pos)
return NULL;
}
else
{
/* check template upper bound */
if(!getPlaylist()->isLive())
{
const Timescale timescale = templ->inheritTimescale();
const stime_t segmentduration = templ->inheritDuration();
vlc_tick_t totalduration = getPeriodDuration();
if(totalduration == 0)
totalduration = getPlaylist()->duration.Get();
if(totalduration && segmentduration)
{
uint64_t endnum = templ->inheritStartNumber() +
(timescale.ToScaled(totalduration) + segmentduration - 1) / segmentduration;
if(i_pos >= endnum)
{
*pi_newpos = i_pos;
return NULL;
}
}
}
*pi_newpos = i_pos;
/* start number */
*pi_newpos = std::max(templ->inheritStartNumber(), i_pos);
}
return seg;
}
else if(seg->getSequenceNumber() >= i_pos)
{
*pi_newpos = seg->getSequenceNumber();
*pb_gap = (*pi_newpos != i_pos);
return seg;
}
}
}
return NULL;
const AbstractSegmentBaseType *profile = inheritSegmentProfile();
if(!profile)
return NULL;
return profile->getNextMediaSegment(i_pos, pi_newpos, pb_gap);
}
InitSegment * SegmentInformation::getInitSegment() const
{
if( segmentBase && segmentBase->initialisationSegment.Get() )
{
return segmentBase->initialisationSegment.Get();
}
else if( segmentList && segmentList->initialisationSegment.Get() )
{
return segmentList->initialisationSegment.Get();
}
else if( mediaSegmentTemplate && mediaSegmentTemplate->initialisationSegment.Get() )
{
return mediaSegmentTemplate->initialisationSegment.Get();
}
else if( parent )
{
return parent->getInitSegment();
}
else return NULL;
const AbstractSegmentBaseType *profile = inheritSegmentProfile();
if(!profile)
return NULL;
return profile->getInitSegment();
}
IndexSegment *SegmentInformation::getIndexSegment() const
{
if( segmentBase && segmentBase->indexSegment.Get() )
{
return segmentBase->indexSegment.Get();
}
else if( segmentList && segmentList->indexSegment.Get() )
{
return segmentList->indexSegment.Get();
}
else if( parent )
{
return parent->getIndexSegment();
}
else return NULL;
const AbstractSegmentBaseType *profile = inheritSegmentProfile();
if(!profile)
return NULL;
return profile->getIndexSegment();
}
Segment * SegmentInformation::getMediaSegment(uint64_t pos) const
{
if( mediaSegmentTemplate )
{
const SegmentTimeline *tl = mediaSegmentTemplate->inheritSegmentTimeline();
if(tl == NULL || tl->maxElementNumber() > pos)
return mediaSegmentTemplate;
}
else if( segmentList )
{
return segmentList->getSegmentByNumber( pos );
}
else if( segmentBase )
{
/* FIXME add getSegmentByNumber */
const std::vector<Segment *> &retSegments = segmentBase->subSegments();
std::vector<Segment *>::const_iterator it;
for(it = retSegments.begin(); it != retSegments.end(); ++it)
{
Segment *seg = *it;
if(seg->getSequenceNumber() >= pos)
{
if(seg->getSequenceNumber() == pos)
return seg;
else
return NULL;
}
}
const AbstractSegmentBaseType *profile = inheritSegmentProfile();
if(!profile)
return NULL;
}
else if( parent )
{
return parent->getMediaSegment(pos);
}
return NULL;
return profile->getMediaSegment(pos);
}
SegmentInformation * SegmentInformation::getChildByID(const adaptive::ID &id)
......@@ -271,17 +176,6 @@ void SegmentInformation::updateWith(SegmentInformation *updated)
/* FIXME: handle difference */
}
void SegmentInformation::mergeWithTimeline(SegmentTimeline *updated)
{
MediaSegmentTemplate *templ = inheritSegmentTemplate();
if(templ)
{
SegmentTimeline *timeline = templ->inheritSegmentTimeline();
if(timeline)
timeline->updateWith(*updated);
}
}
void SegmentInformation::pruneByPlaybackTime(vlc_tick_t time)
{
if(segmentList)
......@@ -334,6 +228,23 @@ vlc_tick_t SegmentInformation::getPeriodDuration() const
return 0;
}
SegmentInformation * SegmentInformation::getParent() const
{
return parent;
}
AbstractSegmentBaseType * SegmentInformation::getProfile() const
{
if(mediaSegmentTemplate)
return mediaSegmentTemplate;
else if(segmentList)
return segmentList;
else if(segmentBase)
return segmentBase;
else
return NULL;
}
void SegmentInformation::updateSegmentList(SegmentList *list, bool restamp)
{
if(segmentList && restamp)
......@@ -355,7 +266,7 @@ void SegmentInformation::setSegmentBase(SegmentBase *base)
segmentBase = base;
}
void SegmentInformation::setSegmentTemplate(MediaSegmentTemplate *templ)
void SegmentInformation::setSegmentTemplate(SegmentTemplate *templ)
{
if(mediaSegmentTemplate)
{
......@@ -456,7 +367,7 @@ SegmentList * SegmentInformation::inheritSegmentList() const
return NULL;
}
MediaSegmentTemplate * SegmentInformation::inheritSegmentTemplate() const
SegmentTemplate * SegmentInformation::inheritSegmentTemplate() const
{
if(mediaSegmentTemplate)
return mediaSegmentTemplate;
......
......@@ -21,9 +21,10 @@
#define SEGMENTINFORMATION_HPP
#include "ICanonicalUrl.hpp"
#include "Inheritables.hpp"
#include "Segment.h"
#include "../tools/Properties.hpp"
#include "../encryption/CommonEncryption.hpp"
#include "SegmentInfoCommon.h"
#include <vlc_common.h>
#include <vector>
......@@ -31,11 +32,12 @@ namespace adaptive
{
namespace playlist
{
class AbstractSegmentBaseType;
class SegmentBase;
class SegmentList;
class SegmentTimeline;
class SegmentTemplate;
class MediaSegmentTemplate;
class SegmentTemplate;
class AbstractPlaylist;
class ISegment;
......@@ -45,7 +47,8 @@ namespace adaptive
public TimescaleAble,
public Unique
{
friend class MediaSegmentTemplate;
friend class AbstractMultipleSegmentBaseType;
public:
SegmentInformation( SegmentInformation * = 0 );
explicit SegmentInformation( AbstractPlaylist * );
......@@ -70,7 +73,6 @@ namespace adaptive
virtual Segment * getNextMediaSegment(uint64_t, uint64_t *, bool *) const;
virtual void updateWith(SegmentInformation *);
virtual void mergeWithTimeline(SegmentTimeline *); /* ! don't use with global merge */
virtual void pruneBySegmentNumber(uint64_t);
virtual void pruneByPlaybackTime(vlc_tick_t);
void setEncryption(const CommonEncryption &);
......@@ -83,16 +85,19 @@ namespace adaptive
SegmentInformation *parent;
public:
SegmentInformation *getParent() const;
AbstractSegmentBaseType *getProfile() const;
void updateSegmentList(SegmentList *, bool = false);
void setSegmentBase(SegmentBase *);
void setSegmentTemplate(MediaSegmentTemplate *);
void setSegmentTemplate(SegmentTemplate *);
virtual Url getUrlSegment() const; /* impl */
Property<Url *> baseUrl;
void setAvailabilityTimeOffset(vlc_tick_t);
void setAvailabilityTimeComplete(bool);
const AbstractSegmentBaseType * inheritSegmentProfile() const;
SegmentBase * inheritSegmentBase() const;
SegmentList * inheritSegmentList() const;
MediaSegmentTemplate * inheritSegmentTemplate() const;
SegmentTemplate * inheritSegmentTemplate() const;
vlc_tick_t inheritAvailabilityTimeOffset() const;
bool inheritAvailabilityTimeComplete() const;
......@@ -100,7 +105,7 @@ namespace adaptive
void init();
SegmentBase *segmentBase;
SegmentList *segmentList;
MediaSegmentTemplate *mediaSegmentTemplate;
SegmentTemplate *mediaSegmentTemplate;
CommonEncryption commonEncryption;
Undef<bool> availabilityTimeComplete;
Undef<vlc_tick_t>availabilityTimeOffset;
......
......@@ -28,11 +28,14 @@
#include "SegmentList.h"
#include "Segment.h"
#include "SegmentInformation.hpp"
#include "SegmentTimeline.h"
#include <limits>
using namespace adaptive::playlist;
SegmentList::SegmentList( SegmentInformation *parent ):
SegmentInfoCommon( parent ), TimescaleAble( parent )
AbstractMultipleSegmentBaseType( parent )
{
totalLength = 0;
}
......@@ -48,8 +51,17 @@ const std::vector<Segment*>& SegmentList::getSegments() const
return segments;
}
Segment * SegmentList::getSegmentByNumber(uint64_t number)
Segment * SegmentList::getMediaSegment(uint64_t number) const
{
const SegmentTimeline *timeline = inheritSegmentTimeline();
if(timeline)
{
uint64_t listindex = timeline->getElementIndexBySequence(number);
if(listindex >= segments.size())
return NULL;
return segments.at(listindex);
}
std::vector<Segment *>::const_iterator it = segments.begin();
for(it = segments.begin(); it != segments.end(); ++it)
{
......@@ -68,19 +80,23 @@ Segment * SegmentList::getSegmentByNumber(uint64_t number)
void SegmentList::addSegment(Segment *seg)
{
seg->setParent(this);
seg->setParent(parent);
segments.push_back(seg);
totalLength += seg->duration.Get();
}
void SegmentList::updateWith(SegmentList *updated, bool b_restamp)
void SegmentList::updateWith(AbstractMultipleSegmentBaseType *updated_,
bool b_restamp)
{
const Segment * lastSegment = (segments.empty()) ? NULL : segments.back();
const Segment * prevSegment = lastSegment;
AbstractMultipleSegmentBaseType::updateWith(updated_);
if(updated->segments.empty())
SegmentList *updated = dynamic_cast<SegmentList *>(updated_);
if(!updated || updated->segments.empty())
return;
const Segment * lastSegment = (segments.empty()) ? NULL : segments.back();
const Segment * prevSegment = lastSegment;
uint64_t firstnumber = updated->segments.front()->getSequenceNumber();
std::vector<Segment *>::iterator it;
......@@ -111,9 +127,9 @@ void SegmentList::updateWith(SegmentList *updated, bool b_restamp)
void SegmentList::pruneByPlaybackTime(vlc_tick_t time)
{
uint64_t num;
const Timescale timescale = inheritTimescale();
if(getSegmentNumberByScaledTime(timescale.ToScaled(time), &num))
uint64_t num = findSegmentNumberByScaledTime(segments, timescale.ToScaled(time));
if(num != std::numeric_limits<uint64_t>::max())
pruneBySegmentNumber(num);
}
......@@ -133,56 +149,159 @@ void SegmentList::pruneBySegmentNumber(uint64_t tobelownum)
}
}
bool SegmentList::getSegmentNumberByScaledTime(stime_t time, uint64_t *ret) const
bool SegmentList::getPlaybackTimeDurationBySegmentNumber(uint64_t number,
vlc_tick_t *time, vlc_tick_t *dur) const
{
return SegmentInfoCommon::getSegmentNumberByScaledTime(segments, time, ret);
if(number == std::numeric_limits<uint64_t>::max())
return false;
Timescale timescale;
stime_t stime, sduration;
const SegmentTimeline * timeline = inheritSegmentTimeline();
if(timeline)
{
timescale = timeline->inheritTimescale();
if(!timeline->getScaledPlaybackTimeDurationBySegmentNumber(number, &stime, &sduration))
return false;
}
else
{
*time = *dur = VLC_TICK_INVALID;
timescale = inheritTimescale();
if(segments.empty())
return false;
const ISegment *first = segments.front();
if(first->getSequenceNumber() > number)
return false;
bool found = false;
stime_t stime = first->startTime.Get();
stime_t sduration = 0;
std::vector<Segment *>::const_iterator it = segments.begin();
for(it = segments.begin(); it != segments.end(); ++it)
{
const Segment *seg = *it;
if(seg->duration.Get())
sduration = seg->duration.Get();
else
sduration = duration.Get();
/* Assuming there won't be any discontinuity in sequence */
if(seg->getSequenceNumber() == number)
{
found = true;
break;
}
stime += sduration;
}
if(!found)
return false;
}
*time = VLC_TICK_0 + timescale.ToTime(stime);
*dur = VLC_TICK_0 + timescale.ToTime(sduration);
return true;
}
bool SegmentList::getPlaybackTimeDurationBySegmentNumber(uint64_t number,
vlc_tick_t *time, vlc_tick_t *dur) const
stime_t SegmentList::getTotalLength() const
{
*time = *dur = VLC_TICK_INVALID;
const SegmentTimeline *timeline = inheritSegmentTimeline();
if(timeline)
return timeline->getTotalLength();
return totalLength;
}
if(segments.empty())
return false;
vlc_tick_t SegmentList::getMinAheadTime(uint64_t curnum) const
{
const SegmentTimeline *timeline = inheritSegmentTimeline();
if( timeline )
{
const Timescale timescale = timeline->inheritTimescale();
return timescale.ToTime(timeline->getMinAheadScaledTime(curnum));
}
vlc_tick_t minTime = 0;
const Timescale timescale = inheritTimescale();
const ISegment *first = segments.front();
if(first->getSequenceNumber() > number)
return false;
bool found = false;
stime_t seg_start = first->startTime.Get();
stime_t seg_dura = 0;
std::vector<Segment *>::const_iterator it = segments.begin();
std::vector<Segment *>::const_iterator it;
for(it = segments.begin(); it != segments.end(); ++it)
{
const Segment *seg = *it;
if(seg->getSequenceNumber() > curnum)
minTime += timescale.ToTime(seg->duration.Get());
}
return minTime;
}
if(seg->duration.Get())
seg_dura = seg->duration.Get();
else
seg_dura = duration.Get();
Segment * SegmentList::getNextMediaSegment(uint64_t i_pos,uint64_t *pi_newpos,
bool *pb_gap) const
{
*pb_gap = false;
*pi_newpos = i_pos;
/* Assuming there won't be any discontinuity in sequence */
if(seg->getSequenceNumber() == number)
const SegmentTimeline *timeline = inheritSegmentTimeline();
if(timeline)
{
uint64_t listindex = timeline->getElementIndexBySequence(i_pos);
if(listindex >= segments.size())
return NULL;
return segments.at(listindex);
}
std::vector<Segment *>::const_iterator it;
for(it = segments.begin(); it != segments.end(); ++it)
{
Segment *seg = *it;
if(seg->getSequenceNumber() >= i_pos)
{
found = true;
break;
*pi_newpos = seg->getSequenceNumber();
*pb_gap = (*pi_newpos != i_pos);
return seg;
}
}
return NULL;
}
uint64_t SegmentList::getStartSegmentNumber() const
{
const SegmentTimeline *timeline = inheritSegmentTimeline();
if( timeline )
return timeline->minElementNumber();
return !segments.empty() ? segments.front()->getSequenceNumber() : inheritStartNumber();
}
seg_start += seg_dura;
bool SegmentList::getSegmentNumberByTime(vlc_tick_t time, uint64_t *ret) const
{
const SegmentTimeline *timeline = inheritSegmentTimeline();
if(timeline)
{
const Timescale timescale = timeline->getTimescale().isValid()
? timeline->getTimescale()
: inheritTimescale();
stime_t st = timescale.ToScaled(time);
*ret = timeline->getElementNumberByScaledPlaybackTime(st);
return true;
}
if(!found)
const Timescale timescale = inheritTimescale();
if(!timescale.isValid())
return false;
*time = VLC_TICK_0 + timescale.ToTime(seg_start);
*dur = VLC_TICK_0 + timescale.ToTime(seg_dura);
return true;
stime_t st = timescale.ToScaled(time);
*ret = AbstractSegmentBaseType::findSegmentNumberByScaledTime(segments, st);
return *ret != std::numeric_limits<uint64_t>::max();
}
stime_t SegmentList::getTotalLength() const
void SegmentList::debug(vlc_object_t *obj, int indent) const
{
return totalLength;
AbstractSegmentBaseType::debug(obj, indent);
std::vector<Segment *>::const_iterator it;
for(it = segments.begin(); it != segments.end(); ++it)
(*it)->debug(obj, indent);
if(segmentTimeline)
segmentTimeline->debug(obj, indent + 1);
}
......@@ -25,7 +25,7 @@
#ifndef SEGMENTLIST_H_
#define SEGMENTLIST_H_
#include "SegmentInfoCommon.h"
#include "SegmentBaseType.hpp"
namespace adaptive
{
......@@ -34,23 +34,30 @@ namespace adaptive
class SegmentInformation;
class Segment;
class SegmentList : public SegmentInfoCommon,
public TimescaleAble
class SegmentList : public AbstractMultipleSegmentBaseType
{
public:
SegmentList ( SegmentInformation * = NULL );
virtual ~SegmentList ();
const std::vector<Segment *>& getSegments() const;
Segment * getSegmentByNumber(uint64_t);
void addSegment(Segment *seg);
void updateWith(SegmentList *, bool = false);
virtual void updateWith(AbstractMultipleSegmentBaseType *,
bool = false); /* reimpl */
void pruneBySegmentNumber(uint64_t);
void pruneByPlaybackTime(vlc_tick_t);
bool getSegmentNumberByScaledTime(stime_t, uint64_t *) const;
bool getPlaybackTimeDurationBySegmentNumber(uint64_t, vlc_tick_t *, vlc_tick_t *) const;
stime_t getTotalLength() const;
virtual vlc_tick_t getMinAheadTime(uint64_t) const; /* impl */
virtual Segment * getMediaSegment(uint64_t pos) const; /* impl */
virtual Segment * getNextMediaSegment(uint64_t, uint64_t *, bool *) const; /* impl */
virtual uint64_t getStartSegmentNumber() const; /* impl */
virtual bool getSegmentNumberByTime(vlc_tick_t time, uint64_t *ret) const; /* impl */
virtual bool getPlaybackTimeDurationBySegmentNumber(uint64_t number,
vlc_tick_t *time, vlc_tick_t *duration) const; /* impl */
virtual void debug(vlc_object_t *, int = 0) const; /* reimpl */
private:
std::vector<Segment *> segments;
stime_t totalLength;
......
......@@ -31,127 +31,58 @@
using namespace adaptive::playlist;
BaseSegmentTemplate::BaseSegmentTemplate( ICanonicalUrl *parent ) :
SegmentTemplateSegment::SegmentTemplateSegment( SegmentTemplate *templ_,
ICanonicalUrl *parent ) :
Segment( parent )
{
debugName = "SegmentTemplateSegment";
classId = Segment::CLASSID_SEGMENT;
templated = true;
templ = templ_;
}
BaseSegmentTemplate::~BaseSegmentTemplate()
SegmentTemplateSegment::~SegmentTemplateSegment()
{
}
void BaseSegmentTemplate::setSourceUrl(const std::string &url)
void SegmentTemplateSegment::setSourceUrl(const std::string &url)
{
sourceUrl = Url(Url::Component(url, this));
sourceUrl = Url(Url::Component(url, templ));
}
MediaSegmentTemplate::MediaSegmentTemplate( SegmentInformation *parent ) :
BaseSegmentTemplate( parent ),
TimescaleAble( NULL ) /* we don't want auto inherit */
SegmentTemplate::SegmentTemplate( SegmentInformation *parent ) :
AbstractMultipleSegmentBaseType( NULL ) /* we don't want auto inherit */
{
debugName = "SegmentTemplate";
classId = Segment::CLASSID_SEGMENT;
startNumber = std::numeric_limits<uint64_t>::max();
segmentTimeline = NULL;
initialisationSegment.Set( NULL );
templated = true;
parentSegmentInformation = parent;
segments.push_back( new SegmentTemplateSegment( this, parent ) );
}
MediaSegmentTemplate::~MediaSegmentTemplate()
SegmentTemplate::~SegmentTemplate()
{
delete segmentTimeline;
delete *segments.begin();
}
void MediaSegmentTemplate::updateWith(MediaSegmentTemplate *updated)
void SegmentTemplate::setSourceUrl( const std::string &url )
{
SegmentTimeline *timeline = segmentTimeline;
if(timeline && updated->segmentTimeline)
{
timeline->updateWith(*updated->segmentTimeline);
/*if(prunebarrier)
{
const Timescale timescale = timeline->inheritTimescale();
const uint64_t number =
timeline->getElementNumberByScaledPlaybackTime(timescale.ToScaled(prunebarrier));
timeline->pruneBySequenceNumber(number);
}*/
}
(*segments.begin())->setSourceUrl(url);
}
void MediaSegmentTemplate::pruneByPlaybackTime(vlc_tick_t time)
void SegmentTemplate::pruneByPlaybackTime(vlc_tick_t time)
{
if(segmentTimeline)
return segmentTimeline->pruneByPlaybackTime(time);
}
size_t MediaSegmentTemplate::pruneBySequenceNumber(uint64_t number)
size_t SegmentTemplate::pruneBySequenceNumber(uint64_t number)
{
if(segmentTimeline)
return segmentTimeline->pruneBySequenceNumber(number);
return 0;
}
uint64_t MediaSegmentTemplate::inheritStartNumber() const
{
if( startNumber != std::numeric_limits<uint64_t>::max() )
return startNumber;
const SegmentInformation *ulevel = parentSegmentInformation ? parentSegmentInformation
: NULL;
for( ; ulevel ; ulevel = ulevel->parent )
{
if( ulevel->mediaSegmentTemplate &&
ulevel->mediaSegmentTemplate->startNumber !=
std::numeric_limits<uint64_t>::max() )
return ulevel->mediaSegmentTemplate->startNumber;
}
return 1;
}
Timescale MediaSegmentTemplate::inheritTimescale() const
{
const SegmentInformation *ulevel = parentSegmentInformation ? parentSegmentInformation
: NULL;
for( ; ulevel ; ulevel = ulevel->parent )
{
if( ulevel->mediaSegmentTemplate &&
ulevel->mediaSegmentTemplate->getTimescale().isValid() )
return ulevel->mediaSegmentTemplate->getTimescale();
if( ulevel->getTimescale().isValid() )
return ulevel->getTimescale();
}
return Timescale(1);
}
stime_t MediaSegmentTemplate::inheritDuration() const
{
const SegmentInformation *ulevel = parentSegmentInformation ? parentSegmentInformation
: NULL;
for( ; ulevel ; ulevel = ulevel->parent )
{
if( ulevel->mediaSegmentTemplate &&
ulevel->mediaSegmentTemplate->duration.Get() > 0 )
return ulevel->mediaSegmentTemplate->duration.Get();
}
return 0;
}
SegmentTimeline * MediaSegmentTemplate::inheritSegmentTimeline() const
{
const SegmentInformation *ulevel = parentSegmentInformation ? parentSegmentInformation
: NULL;
for( ; ulevel ; ulevel = ulevel->parent )
{
if( ulevel->mediaSegmentTemplate &&
ulevel->mediaSegmentTemplate->segmentTimeline )
return ulevel->mediaSegmentTemplate->segmentTimeline;
}
return NULL;
}
uint64_t MediaSegmentTemplate::getLiveTemplateNumber(vlc_tick_t playbacktime, bool abs) const
uint64_t SegmentTemplate::getLiveTemplateNumber(vlc_tick_t playbacktime, bool abs) const
{
uint64_t number = inheritStartNumber();
/* live streams / templated */
......@@ -176,53 +107,181 @@ uint64_t MediaSegmentTemplate::getLiveTemplateNumber(vlc_tick_t playbacktime, bo
return number;
}
stime_t MediaSegmentTemplate::getMinAheadScaledTime(uint64_t number) const
void SegmentTemplate::debug(vlc_object_t *obj, int indent) const
{
AbstractSegmentBaseType::debug(obj, indent);
(*segments.begin())->debug(obj, indent);
if(segmentTimeline)
segmentTimeline->debug(obj, indent + 1);
}
vlc_tick_t SegmentTemplate::getMinAheadTime(uint64_t number) const
{
if( segmentTimeline )
return segmentTimeline->getMinAheadScaledTime(number);
{
const Timescale timescale = segmentTimeline->inheritTimescale();
return timescale.ToTime(segmentTimeline->getMinAheadScaledTime(number));
}
else
{
const Timescale timescale = inheritTimescale();
uint64_t current = getLiveTemplateNumber(vlc_tick_from_sec(time(NULL)));
stime_t i_length = (current - number) * inheritDuration();
return timescale.ToTime(i_length);
}
}
uint64_t current = getLiveTemplateNumber(vlc_tick_from_sec(time(NULL)));
return (current - number) * inheritDuration();
Segment * SegmentTemplate::getMediaSegment(uint64_t number) const
{
const SegmentTimeline *tl = inheritSegmentTimeline();
if(tl == NULL || tl->maxElementNumber() > number)
return *segments.begin();
return NULL;
}
uint64_t MediaSegmentTemplate::getSequenceNumber() const
InitSegment * SegmentTemplate::getInitSegment() const
{
return inheritStartNumber();
return initialisationSegment.Get();
}
void MediaSegmentTemplate::setStartNumber( uint64_t v )
Segment * SegmentTemplate::getNextMediaSegment(uint64_t i_pos,uint64_t *pi_newpos,
bool *pb_gap) const
{
startNumber = v;
*pb_gap = false;
*pi_newpos = i_pos;
/* Check if we don't exceed timeline */
const SegmentTimeline *timeline = inheritSegmentTimeline();
if(timeline)
{
*pi_newpos = std::max(timeline->minElementNumber(), i_pos);
if (timeline->maxElementNumber() < i_pos)
return NULL;
}
else
{
/* check template upper bound */
const AbstractPlaylist *playlist = parentSegmentInformation->getPlaylist();
if(!playlist->isLive())
{
const Timescale timescale = inheritTimescale();
const stime_t segmentduration = inheritDuration();
vlc_tick_t totalduration = parentSegmentInformation->getPeriodDuration();
if(totalduration == 0)
totalduration = playlist->duration.Get();
if(totalduration && segmentduration)
{
uint64_t endnum = inheritStartNumber() +
(timescale.ToScaled(totalduration) + segmentduration - 1) / segmentduration;
if(i_pos >= endnum)
{
*pi_newpos = i_pos;
return NULL;
}
}
}
*pi_newpos = i_pos;
/* start number */
*pi_newpos = std::max(inheritStartNumber(), i_pos);
}
return *segments.begin();
}
void MediaSegmentTemplate::setSegmentTimeline( SegmentTimeline *v )
uint64_t SegmentTemplate::getStartSegmentNumber() const
{
delete segmentTimeline;
segmentTimeline = v;
const SegmentTimeline *timeline = inheritSegmentTimeline();
return timeline ? timeline->minElementNumber() : inheritStartNumber();
}
void MediaSegmentTemplate::debug(vlc_object_t *obj, int indent) const
bool SegmentTemplate::getSegmentNumberByTime(vlc_tick_t time, uint64_t *ret) const
{
Segment::debug(obj, indent);
if(segmentTimeline)
segmentTimeline->debug(obj, indent + 1);
const SegmentTimeline *timeline = inheritSegmentTimeline();
if(timeline)
{
const Timescale timescale = timeline->getTimescale().isValid()
? timeline->getTimescale()
: inheritTimescale();
stime_t st = timescale.ToScaled(time);
*ret = timeline->getElementNumberByScaledPlaybackTime(st);
return true;
}
const stime_t duration = inheritDuration();
if( duration && parent )
{
AbstractPlaylist *playlist = parent->getPlaylist();
if( playlist->isLive() )
{
vlc_tick_t now = vlc_tick_from_sec(::time(NULL));
if(playlist->availabilityStartTime.Get())
{
if(time >= playlist->availabilityStartTime.Get() && time < now)
*ret = getLiveTemplateNumber(time, true);
else if(now - playlist->availabilityStartTime.Get() > time)
*ret = getLiveTemplateNumber(time, false);
}
else return false;
}
else
{
const Timescale timescale = inheritTimescale();
*ret = inheritStartNumber();
*ret += timescale.ToScaled(time) / duration;
}
return true;
}
return false;
}
bool SegmentTemplate::getPlaybackTimeDurationBySegmentNumber(uint64_t number,
vlc_tick_t *time,
vlc_tick_t *duration) const
{
if(number == std::numeric_limits<uint64_t>::max())
return false;
Timescale timescale;
stime_t stime, sduration;
const SegmentTimeline * timeline = inheritSegmentTimeline();
if(timeline)
{
timescale = timeline->inheritTimescale();
if(!timeline->getScaledPlaybackTimeDurationBySegmentNumber(number, &stime, &sduration))
return false;
}
else
{
timescale = inheritTimescale();
uint64_t startNumber = inheritStartNumber();
if(number < startNumber)
return false;
sduration = inheritDuration();
stime = (number - startNumber) * sduration;
}
*time = timescale.ToTime(stime);
*duration = timescale.ToTime(sduration);
return true;
}
InitSegmentTemplate::InitSegmentTemplate( ICanonicalUrl *parent,
MediaSegmentTemplate *templ ) :
SegmentTemplateInit::SegmentTemplateInit( SegmentTemplate *templ_,
ICanonicalUrl *parent ) :
InitSegment(parent)
{
debugName = "InitSegmentTemplate";
classId = InitSegment::CLASSID_INITSEGMENT;
maintempl = templ;
templ = templ_;
}
InitSegmentTemplate::~InitSegmentTemplate()
SegmentTemplateInit::~SegmentTemplateInit()
{
}
void InitSegmentTemplate::setSourceUrl(const std::string &url)
void SegmentTemplateInit::setSourceUrl(const std::string &url)
{
sourceUrl = Url(Url::Component(url, maintempl));
sourceUrl = Url(Url::Component(url, templ));
}
......@@ -25,61 +25,64 @@
#include "Segment.h"
#include "../tools/Properties.hpp"
#include "SegmentInfoCommon.h"
#include "SegmentBaseType.hpp"
namespace adaptive
{
namespace playlist
{
class ICanonicalUrl;
class InitSegmentTemplate;
class SegmentTemplateInit;
class SegmentInformation;
class SegmentTimeline;
class SegmentTemplate;
class BaseSegmentTemplate : public Segment
class SegmentTemplateSegment : public Segment
{
public:
BaseSegmentTemplate( ICanonicalUrl * = NULL );
virtual ~BaseSegmentTemplate();
SegmentTemplateSegment( SegmentTemplate *, ICanonicalUrl * = NULL );
virtual ~SegmentTemplateSegment();
virtual void setSourceUrl( const std::string &url ); /* reimpl */
protected:
const SegmentTemplate *templ;
};
class MediaSegmentTemplate : public BaseSegmentTemplate,
public Initializable<InitSegmentTemplate>,
public TimescaleAble
class SegmentTemplate : public AbstractMultipleSegmentBaseType
{
public:
MediaSegmentTemplate( SegmentInformation * = NULL );
virtual ~MediaSegmentTemplate();
void setStartNumber( uint64_t );
void setSegmentTimeline( SegmentTimeline * );
void updateWith( MediaSegmentTemplate * );
virtual uint64_t getSequenceNumber() const; /* reimpl */
SegmentTemplate( SegmentInformation * = NULL );
virtual ~SegmentTemplate();
void setSourceUrl( const std::string &url );
uint64_t getLiveTemplateNumber(vlc_tick_t, bool = true) const;
stime_t getMinAheadScaledTime(uint64_t) const;
void pruneByPlaybackTime(vlc_tick_t);
size_t pruneBySequenceNumber(uint64_t);
virtual Timescale inheritTimescale() const; /* reimpl */
virtual uint64_t inheritStartNumber() const;
stime_t inheritDuration() const;
SegmentTimeline * inheritSegmentTimeline() const;
virtual vlc_tick_t getMinAheadTime(uint64_t curnum) const; /* impl */
virtual Segment * getMediaSegment(uint64_t number) const; /* impl */
virtual Segment * getNextMediaSegment(uint64_t, uint64_t *, bool *) const; /* impl */
virtual InitSegment *getInitSegment() const;/* reimpl */
virtual uint64_t getStartSegmentNumber() const; /* impl */
virtual bool getSegmentNumberByTime(vlc_tick_t time, uint64_t *ret) const; /* impl */
virtual bool getPlaybackTimeDurationBySegmentNumber(uint64_t number,
vlc_tick_t *time, vlc_tick_t *duration) const; /* impl */
virtual void debug(vlc_object_t *, int = 0) const; /* reimpl */
protected:
uint64_t startNumber;
SegmentTimeline *segmentTimeline;
SegmentInformation *parentSegmentInformation;
std::vector<SegmentTemplateSegment *> segments; /* should have only 1 */
};
class InitSegmentTemplate : public InitSegment
class SegmentTemplateInit : public InitSegment
{
public:
InitSegmentTemplate( ICanonicalUrl * = NULL, MediaSegmentTemplate * = NULL );
virtual ~InitSegmentTemplate();
SegmentTemplateInit( SegmentTemplate *, ICanonicalUrl * = NULL );
virtual ~SegmentTemplateInit();
virtual void setSourceUrl( const std::string &url ); /* reimpl */
protected:
const MediaSegmentTemplate *maintempl;
const SegmentTemplate *templ;
};
}
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment