vlc | branch: master | Francois Cartegnie <[email protected]> | Tue Oct 27 11:24:56 2020 +0100| [573752cfad0e024806e29ccef23986aaff0166db] | committer: Francois Cartegnie
demux: adaptive: rework attributes inheritance to match siblings first > http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=573752cfad0e024806e29ccef23986aaff0166db --- modules/demux/adaptive/logic/BufferingLogic.cpp | 7 +- .../demux/adaptive/playlist/AbstractPlaylist.cpp | 23 +-- .../demux/adaptive/playlist/AbstractPlaylist.hpp | 12 +- .../demux/adaptive/playlist/BaseRepresentation.cpp | 3 +- modules/demux/adaptive/playlist/Inheritables.cpp | 228 ++++++++++++++++++++- modules/demux/adaptive/playlist/Inheritables.hpp | 104 +++++++++- modules/demux/adaptive/playlist/SegmentBase.cpp | 3 +- .../demux/adaptive/playlist/SegmentBaseType.cpp | 105 +--------- .../demux/adaptive/playlist/SegmentBaseType.hpp | 21 +- .../demux/adaptive/playlist/SegmentInformation.cpp | 138 ++++--------- .../demux/adaptive/playlist/SegmentInformation.hpp | 18 +- modules/demux/adaptive/playlist/SegmentList.cpp | 17 +- modules/demux/adaptive/playlist/SegmentList.h | 1 + .../demux/adaptive/playlist/SegmentTemplate.cpp | 28 +-- .../demux/adaptive/playlist/SegmentTimeline.cpp | 37 +--- modules/demux/adaptive/playlist/SegmentTimeline.h | 4 +- modules/demux/dash/mp4/IndexReader.cpp | 2 +- modules/demux/dash/mpd/IsoffMainParser.cpp | 30 +-- modules/demux/dash/mpd/Representation.cpp | 4 +- modules/demux/hls/playlist/Parser.cpp | 7 +- modules/demux/hls/playlist/Representation.cpp | 4 +- modules/demux/smooth/mp4/IndexReader.cpp | 2 +- modules/demux/smooth/playlist/Manifest.cpp | 4 +- modules/demux/smooth/playlist/Manifest.hpp | 5 +- modules/demux/smooth/playlist/Parser.cpp | 33 +-- 25 files changed, 471 insertions(+), 369 deletions(-) diff --git a/modules/demux/adaptive/logic/BufferingLogic.cpp b/modules/demux/adaptive/logic/BufferingLogic.cpp index a3db24368a..0fd79232cc 100644 --- a/modules/demux/adaptive/logic/BufferingLogic.cpp +++ b/modules/demux/adaptive/logic/BufferingLogic.cpp @@ -214,7 +214,8 @@ uint64_t DefaultBufferingLogic::getLiveStartSegmentNumber(BaseRepresentation *re { /* Else compute, current time and timeshiftdepth based */ uint64_t start = 0; - if(mediaSegmentTemplate->duration.Get()) + stime_t scaledduration = mediaSegmentTemplate->inheritDuration(); + if(scaledduration) { /* Compute playback offset and effective finished segment from wall time */ vlc_tick_t now = vlc_tick_from_sec(time(NULL)); @@ -224,7 +225,7 @@ uint64_t DefaultBufferingLogic::getLiveStartSegmentNumber(BaseRepresentation *re const Timescale timescale = mediaSegmentTemplate->inheritTimescale(); if(!timescale) return startnumber; - const vlc_tick_t duration = timescale.ToTime(mediaSegmentTemplate->inheritDuration()); + const vlc_tick_t duration = timescale.ToTime(scaledduration); if(!duration) return startnumber; @@ -336,6 +337,8 @@ uint64_t DefaultBufferingLogic::getLiveStartSegmentNumber(BaseRepresentation *re return segmentBase->getSequenceNumber(); const Timescale timescale = rep->inheritTimescale(); + if(!timeline->isValid()) + return std::numeric_limits<uint64_t>::max(); const Segment *back = list.back(); const stime_t bufferingstart = back->startTime.Get() + back->duration.Get() - timescale.ToScaled(i_buffering); diff --git a/modules/demux/adaptive/playlist/AbstractPlaylist.cpp b/modules/demux/adaptive/playlist/AbstractPlaylist.cpp index cf1f930140..a1255431c7 100644 --- a/modules/demux/adaptive/playlist/AbstractPlaylist.cpp +++ b/modules/demux/adaptive/playlist/AbstractPlaylist.cpp @@ -34,7 +34,7 @@ using namespace adaptive::playlist; AbstractPlaylist::AbstractPlaylist (vlc_object_t *p_object_) : - ICanonicalUrl(), + ICanonicalUrl(), AttrsNode(Type::PLAYLIST), p_object(p_object_) { playbackStart.Set(0); @@ -71,28 +71,9 @@ void AbstractPlaylist::setPlaylistUrl(const std::string &url) playlistUrl = url; } -void AbstractPlaylist::setAvailabilityTimeOffset(vlc_tick_t t) -{ - availabilityTimeOffset = t; -} - -void AbstractPlaylist::setAvailabilityTimeComplete(bool b) -{ - availabilityTimeComplete = b; -} - -vlc_tick_t AbstractPlaylist::getAvailabilityTimeOffset() const -{ - return availabilityTimeOffset.isSet() ? availabilityTimeOffset.value() : 0; -} - -bool AbstractPlaylist::getAvailabilityTimeComplete() const -{ - return !availabilityTimeComplete.isSet() || availabilityTimeComplete.value(); -} - void AbstractPlaylist::addPeriod(BasePeriod *period) { + period->setParentNode(this); periods.push_back(period); } diff --git a/modules/demux/adaptive/playlist/AbstractPlaylist.hpp b/modules/demux/adaptive/playlist/AbstractPlaylist.hpp index 3d0e3cf66d..f8c665941d 100644 --- a/modules/demux/adaptive/playlist/AbstractPlaylist.hpp +++ b/modules/demux/adaptive/playlist/AbstractPlaylist.hpp @@ -25,6 +25,7 @@ #include <string> #include "ICanonicalUrl.hpp" +#include "Inheritables.hpp" #include "../tools/Properties.hpp" namespace adaptive @@ -34,7 +35,8 @@ namespace adaptive { class BasePeriod; - class AbstractPlaylist : public ICanonicalUrl + class AbstractPlaylist : public ICanonicalUrl, + public AttrsNode { public: AbstractPlaylist(vlc_object_t *); @@ -52,10 +54,6 @@ namespace adaptive void addPeriod (BasePeriod *period); void addBaseUrl (const std::string &); void setPlaylistUrl (const std::string &); - void setAvailabilityTimeOffset(vlc_tick_t); - void setAvailabilityTimeComplete(bool); - vlc_tick_t getAvailabilityTimeOffset() const; - bool getAvailabilityTimeComplete() const; virtual Url getUrlSegment() const; /* impl */ vlc_object_t * getVLCObject() const; @@ -85,10 +83,6 @@ namespace adaptive vlc_tick_t minBufferTime; vlc_tick_t maxBufferTime; bool b_needsUpdates; - - private: - Undef<bool> availabilityTimeComplete; - Undef<vlc_tick_t> availabilityTimeOffset; }; } } diff --git a/modules/demux/adaptive/playlist/BaseRepresentation.cpp b/modules/demux/adaptive/playlist/BaseRepresentation.cpp index e0529705e8..787be04cdd 100644 --- a/modules/demux/adaptive/playlist/BaseRepresentation.cpp +++ b/modules/demux/adaptive/playlist/BaseRepresentation.cpp @@ -215,7 +215,7 @@ bool BaseRepresentation::getMediaPlaybackRange(vlc_tick_t *rangeBegin, return true; } /* Else compute, current time and timeshiftdepth based */ - else if( mediaSegmentTemplate->duration.Get() ) + else if( mediaSegmentTemplate->inheritDuration() ) { *rangeEnd = 0; *rangeBegin = -1 * getPlaylist()->timeShiftBufferDepth.Get(); @@ -229,7 +229,6 @@ bool BaseRepresentation::getMediaPlaybackRange(vlc_tick_t *rangeBegin, { const Timescale timescale = segmentList->inheritTimescale(); const std::vector<Segment *> &list = segmentList->getSegments(); - const ISegment *back = list.back(); const stime_t startTime = list.front()->startTime.Get(); const stime_t endTime = back->startTime.Get() + back->duration.Get(); diff --git a/modules/demux/adaptive/playlist/Inheritables.cpp b/modules/demux/adaptive/playlist/Inheritables.cpp index 4e938cbfe5..dfdf56c4c1 100644 --- a/modules/demux/adaptive/playlist/Inheritables.cpp +++ b/modules/demux/adaptive/playlist/Inheritables.cpp @@ -1,7 +1,7 @@ /***************************************************************************** * Inheritables.cpp ***************************************************************************** - * Copyright (C) 1998-2015 VLC authors and VideoLAN + * Copyright (C) 2016-2020 VideoLabs, VLC authors and VideoLAN * * 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 @@ -23,10 +23,236 @@ #endif #include "Inheritables.hpp" +#include "SegmentBase.h" +#include "SegmentList.h" +#include "SegmentTemplate.h" +#include "SegmentTimeline.h" + +#include <algorithm> using namespace adaptive::playlist; using namespace adaptive; +AbstractAttr::AbstractAttr(Type t) +{ + type = t; + parentNode = NULL; +} + +AbstractAttr::~AbstractAttr() +{ + +} + +AbstractAttr::Type AbstractAttr::getType() const +{ + return type; +} + +AttrsNode::AttrsNode(Type t, AttrsNode *parent_) + : AbstractAttr( t ) +{ + setParentNode(parent_); + is_canonical_root = (t == SEGMENTINFORMATION); +} + +AttrsNode::~AttrsNode() +{ + while(props.front()) + { + delete props.front(); + props.pop_front(); + } +} + +void AttrsNode::addAttribute(AbstractAttr *p) +{ + props.push_front(p); + p->setParentNode(this); +} + +void AttrsNode::replaceAttribute(AbstractAttr *p) +{ + AbstractAttr *old = getAttribute(p->getType()); + if(old) + { + props.remove(old); + delete old; + } + props.push_front(p); + p->setParentNode(this); +} + +AbstractAttr * AttrsNode::inheritAttribute(AbstractAttr::Type type) +{ + AbstractAttr *p = getAttribute(type); + if(p && p->isValid()) + return p; + + /* List our path elements up to pseudo root node */ + AttrsNode *rootNode; + std::list<AbstractAttr::Type> matchingpath; + for(rootNode = this; rootNode; rootNode = rootNode->parentNode) + { + if(rootNode->is_canonical_root) + break; + matchingpath.push_front(rootNode->getType()); + } + + if(rootNode && !matchingpath.empty()) + { + /* Try matching at each sibling level */ + for(;;) + { + /* Try same path on each sibling first */ + for(AttrsNode *node = rootNode->parentNode; node; node = node->parentNode) + { + p = node->getAttribute(type, matchingpath); + if(p && p->isValid()) + return p; + } + + matchingpath.pop_back(); + if(matchingpath.empty()) + break; + } + } + + { + /* Just try anything below */ + for(AttrsNode *node = this->parentNode; node ; node = node->parentNode) + { + p = node->getAttribute(type); + if(p && p->isValid()) + return p; + } + } + + return p; +} + +AbstractAttr * AttrsNode::inheritAttribute(AbstractAttr::Type type) const +{ + return const_cast<AttrsNode *>(this)->inheritAttribute(type); +} + +stime_t AttrsNode::inheritDuration() const +{ + const AbstractAttr *p = inheritAttribute(Type::DURATION); + if(p && p->isValid()) + return (const stime_t &) *(static_cast<const DurationAttr *>(p)); + return 0; +} + +uint64_t AttrsNode::inheritStartNumber() const +{ + const AbstractAttr *p = inheritAttribute(Type::STARTNUMBER); + if(p && p->isValid()) + return (const uint64_t &) *(static_cast<const StartnumberAttr *>(p)); + return std::numeric_limits<uint64_t>::max(); +} + +Timescale AttrsNode::inheritTimescale() const +{ + const AbstractAttr *p = inheritAttribute(Type::TIMESCALE); + if(p && p->isValid()) + return (Timescale) *(static_cast<const TimescaleAttr *>(p)); + else + return Timescale(1); +} + +vlc_tick_t AttrsNode::inheritAvailabilityTimeOffset() const +{ + const AbstractAttr *p = inheritAttribute(Type::AVAILABILITYTTIMEOFFSET); + if(p && p->isValid()) + return (const vlc_tick_t &) *(static_cast<const AvailabilityTimeOffsetAttr *>(p)); + return 0; +} + +bool AttrsNode::inheritAvailabilityTimeComplete() const +{ + const AbstractAttr *p = inheritAttribute(Type::AVAILABILITYTTIMECOMPLETE); + if(p && p->isValid()) + return (const bool &) *(static_cast<const AvailabilityTimeCompleteAttr *>(p)); + return true; +} + +SegmentBase * AttrsNode::inheritSegmentBase() const +{ + AbstractAttr *p = inheritAttribute(Type::SEGMENTBASE); + if(p && p->isValid()) + return static_cast<SegmentBase *>(p); + return NULL; +} + +SegmentList * AttrsNode::inheritSegmentList() const +{ + AbstractAttr *p = inheritAttribute(Type::SEGMENTLIST); + if(p && p->isValid()) + return static_cast<SegmentList *> (p); + return NULL; +} + +SegmentTemplate * AttrsNode::inheritSegmentTemplate() const +{ + AbstractAttr *p = inheritAttribute(Type::SEGMENTTEMPLATE); + if(p && p->isValid()) + return static_cast<SegmentTemplate *> (p); + return NULL; +} + +SegmentTimeline * AttrsNode::inheritSegmentTimeline() const +{ + AbstractAttr *p = inheritAttribute(Type::TIMELINE); + if(p && p->isValid()) + return static_cast<SegmentTimeline *> (p); + return NULL; +} + +AttrsNode * AttrsNode::matchPath(std::list<AbstractAttr::Type>&path) +{ + AttrsNode *pn = this; + std::list<AbstractAttr::Type>::const_iterator it; + for(it = path.begin(); it != path.end(); it++) + { + AbstractAttr *p = pn->getAttribute(*it); + if(!p || !p->isValid()) + return NULL; + pn = dynamic_cast<AttrsNode *>(p); + if(pn == NULL) + return NULL; + } + return pn; +} + +AbstractAttr * AttrsNode::getAttribute(AbstractAttr::Type type) +{ + for(auto it = props.begin(); it != props.end(); ++it) + { + if((*it)->getType() == type) + return *it; + } + return NULL; +} + +AbstractAttr * AttrsNode::getAttribute(AbstractAttr::Type type) const +{ + return const_cast<AttrsNode *>(this)->getAttribute(type); +} + +AbstractAttr * AttrsNode::getAttribute(AbstractAttr::Type type, + std::list<AbstractAttr::Type>&path) +{ + AttrsNode *matched = matchPath(path); + if(matched) + { + AbstractAttr *p = matched->getAttribute(type); + if(p && p->isValid()) + return p; + } + return NULL; +} + TimescaleAble::TimescaleAble(TimescaleAble *parent) { parentTimescaleAble = parent; diff --git a/modules/demux/adaptive/playlist/Inheritables.hpp b/modules/demux/adaptive/playlist/Inheritables.hpp index 593391e056..8fa04f5ad8 100644 --- a/modules/demux/adaptive/playlist/Inheritables.hpp +++ b/modules/demux/adaptive/playlist/Inheritables.hpp @@ -1,7 +1,7 @@ /***************************************************************************** * Inheritables.hpp Nodes inheritables properties ***************************************************************************** - * Copyright (C) 1998-2015 VLC authors and VideoLAN + * Copyright (C) 2016-2020 VideoLabs, VLC authors and VideoLAN * * 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 @@ -20,7 +20,6 @@ #ifndef INHERITABLES_H #define INHERITABLES_H -#include "../tools/Properties.hpp" #include <list> #include <limits> #include <stdint.h> @@ -30,6 +29,107 @@ namespace adaptive { namespace playlist { + class AttrsNode; + class SegmentTimeline; + class SegmentTemplate; + class SegmentList; + class SegmentBase; + + class AbstractAttr + { + public: + enum Type + { + NONE, + PLAYLIST, + SEGMENTINFORMATION, + SEGMENTLIST, + SEGMENTBASE, + SEGMENTTEMPLATE, + TIMESCALE, + TIMELINE, + DURATION, + STARTNUMBER, + AVAILABILITYTTIMEOFFSET, + AVAILABILITYTTIMECOMPLETE, + }; + AbstractAttr(enum Type); + virtual ~AbstractAttr(); + Type getType() const; + bool operator ==(const AbstractAttr &t) const { return type == t.getType(); } + bool operator !=(const AbstractAttr &t) const { return type != t.getType(); } + virtual bool isValid() const { return true; } + void setParentNode(AttrsNode *n) { parentNode = n; } + + protected: + Type type; + AttrsNode *parentNode; + }; + + class AttrsNode : public AbstractAttr + { + public: + AttrsNode( enum Type, AttrsNode * = NULL ); + ~AttrsNode(); + void addAttribute( AbstractAttr * ); + void replaceAttribute( AbstractAttr * ); + AbstractAttr * inheritAttribute(AbstractAttr::Type); + AbstractAttr * inheritAttribute(AbstractAttr::Type) const; + /* helpers */ + uint64_t inheritStartNumber() const; + stime_t inheritDuration() const; + Timescale inheritTimescale() const; + vlc_tick_t inheritAvailabilityTimeOffset() const; + bool inheritAvailabilityTimeComplete() const; + SegmentTimeline * inheritSegmentTimeline() const; + SegmentTemplate * inheritSegmentTemplate() const; + SegmentList * inheritSegmentList() const; + SegmentBase * inheritSegmentBase() const; + + protected: + AttrsNode * matchPath(std::list<AbstractAttr::Type>&); + AbstractAttr * getAttribute(AbstractAttr::Type, + std::list<AbstractAttr::Type>&); + AbstractAttr * getAttribute(AbstractAttr::Type); + AbstractAttr * getAttribute(AbstractAttr::Type) const; + std::list<AbstractAttr *> props; + bool is_canonical_root; + }; + + template<enum AbstractAttr::Type e, typename T> + class AttrWrapper : public AbstractAttr + { + public: + AttrWrapper(T v) : AbstractAttr(e) { value = v; } + virtual ~AttrWrapper() {} + operator const T&() const { return value; } + + protected: + T value; + }; + + typedef AttrWrapper<AbstractAttr::Type::AVAILABILITYTTIMEOFFSET, vlc_tick_t> AvailabilityTimeOffsetAttr; + typedef AttrWrapper<AbstractAttr::Type::AVAILABILITYTTIMECOMPLETE, bool> AvailabilityTimeCompleteAttr; + typedef AttrWrapper<AbstractAttr::Type::STARTNUMBER, uint64_t> StartnumberAttr; + + class TimescaleAttr: + public AttrWrapper<AbstractAttr::Type::TIMESCALE, Timescale> + { + public: + TimescaleAttr(Timescale v) : + AttrWrapper<AbstractAttr::Type::TIMESCALE, Timescale>( v ) {} + virtual bool isValid() const { return value.isValid(); } + }; + + class DurationAttr: + public AttrWrapper<AbstractAttr::Type::DURATION, stime_t> + { + public: + DurationAttr(stime_t v) : + AttrWrapper<AbstractAttr::Type::DURATION, stime_t>( v ) {} + virtual bool isValid() const { return value > 0; } + }; + class TimescaleAble { public: diff --git a/modules/demux/adaptive/playlist/SegmentBase.cpp b/modules/demux/adaptive/playlist/SegmentBase.cpp index 16f3ff1c1f..b28dc72834 100644 --- a/modules/demux/adaptive/playlist/SegmentBase.cpp +++ b/modules/demux/adaptive/playlist/SegmentBase.cpp @@ -33,7 +33,8 @@ using namespace adaptive::playlist; SegmentBase::SegmentBase(SegmentInformation *parent) : - Segment(parent), AbstractSegmentBaseType(parent) + Segment(parent), + AbstractSegmentBaseType(parent, AttrsNode::Type::SEGMENTBASE) { this->parent = parent; } diff --git a/modules/demux/adaptive/playlist/SegmentBaseType.cpp b/modules/demux/adaptive/playlist/SegmentBaseType.cpp index defc491041..1cc85fb474 100644 --- a/modules/demux/adaptive/playlist/SegmentBaseType.cpp +++ b/modules/demux/adaptive/playlist/SegmentBaseType.cpp @@ -65,8 +65,8 @@ uint64_t AbstractSegmentBaseType::findSegmentNumberByScaledTime(const std::vecto return s->getSequenceNumber(); } -AbstractSegmentBaseType::AbstractSegmentBaseType(SegmentInformation *parent) - : TimescaleAble(parent) +AbstractSegmentBaseType::AbstractSegmentBaseType(SegmentInformation *parent, AttrsNode::Type t) + : AttrsNode(t, parent) { this->parent = parent; } @@ -85,30 +85,6 @@ 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()) @@ -117,84 +93,21 @@ void AbstractSegmentBaseType::debug(vlc_object_t *obj, int indent) const indexSegment.Get()->debug(obj, indent); } -AbstractMultipleSegmentBaseType::AbstractMultipleSegmentBaseType(SegmentInformation *parent) - : AbstractSegmentBaseType(parent) +AbstractMultipleSegmentBaseType::AbstractMultipleSegmentBaseType(SegmentInformation *parent, + AttrsNode::Type type) + : AbstractSegmentBaseType(parent, type) { - 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); + SegmentTimeline *local = static_cast<SegmentTimeline *>(getAttribute(Type::TIMELINE)); + SegmentTimeline *other = static_cast<SegmentTimeline *>(updated->getAttribute(Type::TIMELINE)); + if(local && other) + local->updateWith(*other); } diff --git a/modules/demux/adaptive/playlist/SegmentBaseType.hpp b/modules/demux/adaptive/playlist/SegmentBaseType.hpp index 89432bcd41..16c094b69d 100644 --- a/modules/demux/adaptive/playlist/SegmentBaseType.hpp +++ b/modules/demux/adaptive/playlist/SegmentBaseType.hpp @@ -34,10 +34,10 @@ namespace adaptive class AbstractSegmentBaseType : public Initializable<InitSegment>, public Indexable<IndexSegment>, - public TimescaleAble + public AttrsNode { public: - AbstractSegmentBaseType( SegmentInformation * ); + AbstractSegmentBaseType( SegmentInformation *, AttrsNode::Type ); virtual ~AbstractSegmentBaseType(); virtual vlc_tick_t getMinAheadTime(uint64_t) const = 0; @@ -51,15 +51,12 @@ namespace adaptive 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; @@ -68,22 +65,10 @@ namespace adaptive class AbstractMultipleSegmentBaseType : public AbstractSegmentBaseType { public: - AbstractMultipleSegmentBaseType( SegmentInformation * ); + AbstractMultipleSegmentBaseType( SegmentInformation *, AttrsNode::Type ); 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; - }; } } diff --git a/modules/demux/adaptive/playlist/SegmentInformation.cpp b/modules/demux/adaptive/playlist/SegmentInformation.cpp index faae1a7639..c4fe204783 100644 --- a/modules/demux/adaptive/playlist/SegmentInformation.cpp +++ b/modules/demux/adaptive/playlist/SegmentInformation.cpp @@ -39,7 +39,7 @@ using namespace adaptive::playlist; SegmentInformation::SegmentInformation(SegmentInformation *parent_) : ICanonicalUrl( parent_ ), - TimescaleAble( parent_ ) + AttrsNode( AbstractAttr::SEGMENTINFORMATION, parent_ ) { parent = parent_; init(); @@ -47,7 +47,7 @@ SegmentInformation::SegmentInformation(SegmentInformation *parent_) : SegmentInformation::SegmentInformation(AbstractPlaylist * parent_) : ICanonicalUrl(parent_), - TimescaleAble() + AttrsNode( AbstractAttr::SEGMENTINFORMATION, NULL ) { parent = NULL; init(); @@ -56,16 +56,10 @@ SegmentInformation::SegmentInformation(AbstractPlaylist * parent_) : void SegmentInformation::init() { baseUrl.Set(NULL); - segmentBase = NULL; - segmentList = NULL; - mediaSegmentTemplate = NULL; } SegmentInformation::~SegmentInformation() { - delete segmentBase; - delete segmentList; - delete mediaSegmentTemplate; delete baseUrl.Get(); } @@ -136,11 +130,17 @@ SegmentInformation * SegmentInformation::getChildByID(const adaptive::ID &id) void SegmentInformation::updateWith(SegmentInformation *updated) { /* Support Segment List for now */ - if(segmentList && updated->segmentList) - segmentList->updateWith(updated->segmentList); + AbstractAttr *p = getAttribute(Type::SEGMENTLIST); + if(p && p->isValid() && updated->getAttribute(Type::SEGMENTLIST)) + { + inheritSegmentList()->updateWith(updated->inheritSegmentList()); + } - if(mediaSegmentTemplate && updated->mediaSegmentTemplate) - mediaSegmentTemplate->updateWith(updated->mediaSegmentTemplate); + p = getAttribute(Type::SEGMENTTEMPLATE); + if(p && p->isValid() && updated->getAttribute(Type::SEGMENTTEMPLATE)) + { + inheritSegmentTemplate()->updateWith(updated->inheritSegmentTemplate()); + } std::vector<SegmentInformation *>::const_iterator it; for(it=childs.begin(); it!=childs.end(); ++it) @@ -155,11 +155,13 @@ void SegmentInformation::updateWith(SegmentInformation *updated) void SegmentInformation::pruneByPlaybackTime(vlc_tick_t time) { + SegmentList *segmentList = static_cast<SegmentList *>(getAttribute(Type::SEGMENTLIST)); if(segmentList) segmentList->pruneByPlaybackTime(time); - if(mediaSegmentTemplate) - mediaSegmentTemplate->pruneByPlaybackTime(time); + SegmentTemplate *templ = static_cast<SegmentTemplate *>(getAttribute(Type::SEGMENTTEMPLATE)); + if(templ) + templ->pruneByPlaybackTime(time); std::vector<SegmentInformation *>::const_iterator it; for(it=childs.begin(); it!=childs.end(); ++it) @@ -170,11 +172,13 @@ void SegmentInformation::pruneBySegmentNumber(uint64_t num) { assert(dynamic_cast<BaseRepresentation *>(this)); + SegmentList *segmentList = static_cast<SegmentList *>(getAttribute(Type::SEGMENTLIST)); if(segmentList) segmentList->pruneBySegmentNumber(num); - if(mediaSegmentTemplate) - mediaSegmentTemplate->pruneBySequenceNumber(num); + SegmentTemplate *templ = static_cast<SegmentTemplate *>(getAttribute(Type::SEGMENTTEMPLATE)); + if(templ) + templ->pruneBySequenceNumber(num); } const CommonEncryption & SegmentInformation::intheritEncryption() const @@ -205,25 +209,22 @@ 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; + AbstractAttr *p; + if((p = getAttribute(Type::SEGMENTTEMPLATE))) + return (SegmentTemplate *) p; + else if((p = getAttribute(Type::SEGMENTLIST))) + return (SegmentList *) p; + else if((p = getAttribute(Type::SEGMENTBASE))) + return (SegmentBase *) p; + + return NULL; } void SegmentInformation::updateSegmentList(SegmentList *list, bool restamp) { + SegmentList *segmentList = static_cast<SegmentList *>(getAttribute(Type::SEGMENTLIST)); if(segmentList && restamp) { segmentList->updateWith(list, restamp); @@ -231,27 +232,22 @@ void SegmentInformation::updateSegmentList(SegmentList *list, bool restamp) } else { - delete segmentList; - segmentList = list; + replaceAttribute(list); } } -void SegmentInformation::setSegmentBase(SegmentBase *base) -{ - if(segmentBase) - delete segmentBase; - segmentBase = base; -} - void SegmentInformation::setSegmentTemplate(SegmentTemplate *templ) { - if(mediaSegmentTemplate) + SegmentTemplate *local = static_cast<SegmentTemplate *>(getAttribute(Type::SEGMENTTEMPLATE)); + if(local) { - mediaSegmentTemplate->updateWith(templ); + local->updateWith(templ); delete templ; } else - mediaSegmentTemplate = templ; + { + addAttribute(templ); + } } static void insertIntoSegment(std::vector<Segment *> &seglist, size_t start, @@ -323,63 +319,3 @@ Url SegmentInformation::getUrlSegment() const return ret; } } - -SegmentBase * SegmentInformation::inheritSegmentBase() const -{ - if(segmentBase) - return segmentBase; - else if (parent) - return parent->inheritSegmentBase(); - else - return NULL; -} - -SegmentList * SegmentInformation::inheritSegmentList() const -{ - if(segmentList) - return segmentList; - else if (parent) - return parent->inheritSegmentList(); - else - return NULL; -} - -SegmentTemplate * SegmentInformation::inheritSegmentTemplate() const -{ - if(mediaSegmentTemplate) - return mediaSegmentTemplate; - else if (parent) - return parent->inheritSegmentTemplate(); - else - return NULL; -} - -void SegmentInformation::setAvailabilityTimeOffset(vlc_tick_t t) -{ - availabilityTimeOffset = t; -} - -void SegmentInformation::setAvailabilityTimeComplete(bool b) -{ - availabilityTimeComplete = b; -} - -vlc_tick_t SegmentInformation::inheritAvailabilityTimeOffset() const -{ - for(const SegmentInformation *p = this; p; p = p->parent) - { - if(availabilityTimeOffset.isSet()) - return availabilityTimeOffset.value(); - } - return getPlaylist()->getAvailabilityTimeOffset(); -} - -bool SegmentInformation::inheritAvailabilityTimeComplete() const -{ - for(const SegmentInformation *p = this; p; p = p->parent) - { - if(availabilityTimeComplete.isSet()) - return availabilityTimeComplete.value(); - } - return getPlaylist()->getAvailabilityTimeComplete(); -} diff --git a/modules/demux/adaptive/playlist/SegmentInformation.hpp b/modules/demux/adaptive/playlist/SegmentInformation.hpp index 6704c3cca6..66e36d5c6f 100644 --- a/modules/demux/adaptive/playlist/SegmentInformation.hpp +++ b/modules/demux/adaptive/playlist/SegmentInformation.hpp @@ -44,8 +44,8 @@ namespace adaptive /* common segment elements for period/adaptset/rep 5.3.9.1, * with properties inheritance */ class SegmentInformation : public ICanonicalUrl, - public TimescaleAble, - public Unique + public Unique, + public AttrsNode { friend class AbstractMultipleSegmentBaseType; @@ -84,30 +84,16 @@ namespace adaptive SegmentInformation *parent; public: - SegmentInformation *getParent() const; AbstractSegmentBaseType *getProfile() const; void updateSegmentList(SegmentList *, bool = false); - void setSegmentBase(SegmentBase *); 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; - SegmentTemplate * inheritSegmentTemplate() const; - vlc_tick_t inheritAvailabilityTimeOffset() const; - bool inheritAvailabilityTimeComplete() const; private: void init(); - SegmentBase *segmentBase; - SegmentList *segmentList; - SegmentTemplate *mediaSegmentTemplate; CommonEncryption commonEncryption; - Undef<bool> availabilityTimeComplete; - Undef<vlc_tick_t>availabilityTimeOffset; }; } } diff --git a/modules/demux/adaptive/playlist/SegmentList.cpp b/modules/demux/adaptive/playlist/SegmentList.cpp index 211b9ef80c..92d12b56f7 100644 --- a/modules/demux/adaptive/playlist/SegmentList.cpp +++ b/modules/demux/adaptive/playlist/SegmentList.cpp @@ -34,8 +34,8 @@ using namespace adaptive::playlist; -SegmentList::SegmentList( SegmentInformation *parent ): - AbstractMultipleSegmentBaseType( parent ) +SegmentList::SegmentList( SegmentInformation *parent_ ): + AbstractMultipleSegmentBaseType( parent_, AttrsNode::Type::SEGMENTLIST ) { totalLength = 0; } @@ -80,7 +80,7 @@ Segment * SegmentList::getMediaSegment(uint64_t number) const void SegmentList::addSegment(Segment *seg) { - seg->setParent(parent); + seg->setParent(AbstractSegmentBaseType::parent); segments.push_back(seg); totalLength += seg->duration.Get(); } @@ -188,7 +188,7 @@ bool SegmentList::getPlaybackTimeDurationBySegmentNumber(uint64_t number, if(seg->duration.Get()) sduration = seg->duration.Get(); else - sduration = duration.Get(); + sduration = inheritDuration(); /* Assuming there won't be any discontinuity in sequence */ if(seg->getSequenceNumber() == number) @@ -280,9 +280,7 @@ 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(); + const Timescale timescale = timeline->inheritTimescale(); stime_t st = timescale.ToScaled(time); *ret = timeline->getElementNumberByScaledPlaybackTime(st); return true; @@ -302,6 +300,7 @@ void SegmentList::debug(vlc_object_t *obj, int indent) const 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); + const AbstractAttr *p = getAttribute(Type::TIMELINE); + if(p) + ((SegmentTimeline *) p)->debug(obj, indent + 1); } diff --git a/modules/demux/adaptive/playlist/SegmentList.h b/modules/demux/adaptive/playlist/SegmentList.h index f67d64ad8a..28f63e2439 100644 --- a/modules/demux/adaptive/playlist/SegmentList.h +++ b/modules/demux/adaptive/playlist/SegmentList.h @@ -26,6 +26,7 @@ #define SEGMENTLIST_H_ #include "SegmentBaseType.hpp" +#include "Inheritables.hpp" namespace adaptive { diff --git a/modules/demux/adaptive/playlist/SegmentTemplate.cpp b/modules/demux/adaptive/playlist/SegmentTemplate.cpp index f66fe7eb02..d3b7928f31 100644 --- a/modules/demux/adaptive/playlist/SegmentTemplate.cpp +++ b/modules/demux/adaptive/playlist/SegmentTemplate.cpp @@ -52,7 +52,7 @@ void SegmentTemplateSegment::setSourceUrl(const std::string &url) } SegmentTemplate::SegmentTemplate( SegmentInformation *parent ) : - AbstractMultipleSegmentBaseType( NULL ) /* we don't want auto inherit */ + AbstractMultipleSegmentBaseType( parent, AbstractAttr::Type::SEGMENTTEMPLATE ) { initialisationSegment.Set( NULL ); parentSegmentInformation = parent; @@ -71,14 +71,16 @@ void SegmentTemplate::setSourceUrl( const std::string &url ) void SegmentTemplate::pruneByPlaybackTime(vlc_tick_t time) { - if(segmentTimeline) - return segmentTimeline->pruneByPlaybackTime(time); + const AbstractAttr *p = getAttribute(Type::TIMELINE); + if(p) + return ((SegmentTimeline *) p)->pruneByPlaybackTime(time); } size_t SegmentTemplate::pruneBySequenceNumber(uint64_t number) { - if(segmentTimeline) - return segmentTimeline->pruneBySequenceNumber(number); + const AbstractAttr *p = getAttribute(Type::TIMELINE); + if(p) + return ((SegmentTimeline *) p)->pruneBySequenceNumber(number); return 0; } @@ -111,16 +113,18 @@ 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); + const AbstractAttr *p = getAttribute(Type::TIMELINE); + if(p) + ((SegmentTimeline *) p)->debug(obj, indent + 1); } vlc_tick_t SegmentTemplate::getMinAheadTime(uint64_t number) const { - if( segmentTimeline ) + SegmentTimeline *timeline = inheritSegmentTimeline(); + if( timeline ) { - const Timescale timescale = segmentTimeline->inheritTimescale(); - return timescale.ToTime(segmentTimeline->getMinAheadScaledTime(number)); + const Timescale timescale = timeline->inheritTimescale(); + return timescale.ToTime(timeline->getMinAheadScaledTime(number)); } else { @@ -197,9 +201,7 @@ bool SegmentTemplate::getSegmentNumberByTime(vlc_tick_t time, uint64_t *ret) con const SegmentTimeline *timeline = inheritSegmentTimeline(); if(timeline) { - const Timescale timescale = timeline->getTimescale().isValid() - ? timeline->getTimescale() - : inheritTimescale(); + const Timescale timescale = timeline->inheritTimescale(); stime_t st = timescale.ToScaled(time); *ret = timeline->getElementNumberByScaledPlaybackTime(st); return true; diff --git a/modules/demux/adaptive/playlist/SegmentTimeline.cpp b/modules/demux/adaptive/playlist/SegmentTimeline.cpp index a8e60ccc66..51e2873c13 100644 --- a/modules/demux/adaptive/playlist/SegmentTimeline.cpp +++ b/modules/demux/adaptive/playlist/SegmentTimeline.cpp @@ -33,20 +33,12 @@ using namespace adaptive::playlist; SegmentTimeline::SegmentTimeline(AbstractMultipleSegmentBaseType *parent_) - :TimescaleAble(NULL) + : AttrsNode(Type::TIMELINE, parent_) { totalLength = 0; parent = parent_; } -SegmentTimeline::SegmentTimeline(uint64_t scale) - :TimescaleAble(NULL) -{ - setTimescale(scale); - totalLength = 0; - parent = NULL; -} - SegmentTimeline::~SegmentTimeline() { std::list<Element *>::iterator it; @@ -93,33 +85,6 @@ stime_t SegmentTimeline::getMinAheadScaledTime(uint64_t number) const return totalscaledtime; } -Timescale SegmentTimeline::inheritTimescale() const -{ - if(getTimescale().isValid()) - return getTimescale(); - - if(parent && parent->getTimescale().isValid()) - return parent->getTimescale(); - - SegmentInformation *info = NULL; - if(parent && parent->getParent() && parent->getParent()->getParent()) - info = parent->getParent()->getParent(); - else - info = NULL; - - AbstractMultipleSegmentBaseType *bt; - for(; info; info = info->getParent()) - { - bt = dynamic_cast<AbstractMultipleSegmentBaseType *>(info->getProfile()); - if(bt && bt->getSegmentTimeline() && bt->getSegmentTimeline()->getTimescale().isValid()) - return bt->getSegmentTimeline()->getTimescale(); - if(info->getTimescale().isValid()) - return info->getTimescale(); - } - - return Timescale(1); -} - uint64_t SegmentTimeline::getElementNumberByScaledPlaybackTime(stime_t scaled) const { const Element *prevel = NULL; diff --git a/modules/demux/adaptive/playlist/SegmentTimeline.h b/modules/demux/adaptive/playlist/SegmentTimeline.h index 668f7d5389..e56f16437f 100644 --- a/modules/demux/adaptive/playlist/SegmentTimeline.h +++ b/modules/demux/adaptive/playlist/SegmentTimeline.h @@ -34,20 +34,18 @@ namespace adaptive { class AbstractMultipleSegmentBaseType; - class SegmentTimeline : public TimescaleAble + class SegmentTimeline : public AttrsNode { class Element; public: SegmentTimeline(AbstractMultipleSegmentBaseType *); - SegmentTimeline(uint64_t); virtual ~SegmentTimeline(); void addElement(uint64_t, stime_t d, uint64_t r = 0, stime_t t = 0); uint64_t getElementNumberByScaledPlaybackTime(stime_t) const; bool getScaledPlaybackTimeDurationBySegmentNumber(uint64_t, stime_t *, stime_t *) const; stime_t getScaledPlaybackTimeByElementNumber(uint64_t) const; stime_t getMinAheadScaledTime(uint64_t) const; - Timescale inheritTimescale() const; /* reimpl */ stime_t getTotalLength() const; uint64_t maxElementNumber() const; uint64_t minElementNumber() const; diff --git a/modules/demux/dash/mp4/IndexReader.cpp b/modules/demux/dash/mp4/IndexReader.cpp index 5dc8089a6d..4e4312a72d 100644 --- a/modules/demux/dash/mp4/IndexReader.cpp +++ b/modules/demux/dash/mp4/IndexReader.cpp @@ -57,7 +57,7 @@ bool IndexReader::parseIndex(block_t *p_block, BaseRepresentation *rep, uint64_t point.duration = sidx->p_items[i].i_subsegment_duration; point.time += point.duration; } - rep->setTimescale(Timescale(sidx->i_timescale)); + rep->replaceAttribute(new TimescaleAttr(Timescale(sidx->i_timescale))); rep->SplitUsingIndex(splitlist); rep->getPlaylist()->debug(); } diff --git a/modules/demux/dash/mpd/IsoffMainParser.cpp b/modules/demux/dash/mpd/IsoffMainParser.cpp index 6f158a81aa..408c61b567 100644 --- a/modules/demux/dash/mpd/IsoffMainParser.cpp +++ b/modules/demux/dash/mpd/IsoffMainParser.cpp @@ -70,12 +70,12 @@ static void parseAvailability(MPD *mpd, Node *node, T *s) if(node->hasAttribute("availabilityTimeOffset")) { double val = Integer<double>(node->getAttributeValue("availabilityTimeOffset")); - s->setAvailabilityTimeOffset(val * CLOCK_FREQ); + s->addAttribute(new AvailabilityTimeOffsetAttr(val * CLOCK_FREQ)); } if(node->hasAttribute("availabilityTimeComplete")) { bool b = (node->getAttributeValue("availabilityTimeComplete") == "false"); - s->setAvailabilityTimeComplete(!b); + s->addAttribute(new AvailabilityTimeCompleteAttr(!b)); if(b) mpd->setLowLatency(b); } @@ -206,8 +206,10 @@ void IsoffMainParser::parseSegmentBaseType(MPD *, Node *node, } if(node->hasAttribute("timescale")) - base->setTimescale(Integer<uint64_t>(node->getAttributeValue("timescale"))); - + { + TimescaleAttr *prop = new TimescaleAttr(Timescale(Integer<uint64_t>(node->getAttributeValue("timescale")))); + base->addAttribute(prop); + } } void IsoffMainParser::parseMultipleSegmentBaseType(MPD *mpd, Node *node, @@ -217,10 +219,10 @@ void IsoffMainParser::parseMultipleSegmentBaseType(MPD *mpd, Node *node, parseSegmentBaseType(mpd, node, base, parent); if(node->hasAttribute("duration")) - base->duration.Set(Integer<stime_t>(node->getAttributeValue("duration"))); + base->addAttribute(new DurationAttr(Integer<stime_t>(node->getAttributeValue("duration")))); if(node->hasAttribute("startNumber")) - base->setStartNumber(Integer<uint64_t>(node->getAttributeValue("startNumber"))); + base->addAttribute(new StartnumberAttr(Integer<uint64_t>(node->getAttributeValue("startNumber")))); parseTimeline(DOMHelper::getFirstChildElementByName(node, "SegmentTimeline"), base); } @@ -269,7 +271,7 @@ size_t IsoffMainParser::parseSegmentInformation(MPD *mpd, Node *node, total += parseSegmentList(mpd, DOMHelper::getFirstChildElementByName(node, "SegmentList"), info); total += parseSegmentTemplate(mpd, DOMHelper::getFirstChildElementByName(node, "SegmentTemplate" ), info); if(node->hasAttribute("timescale")) - info->setTimescale(Integer<uint64_t>(node->getAttributeValue("timescale"))); + info->addAttribute(new TimescaleAttr(Timescale(Integer<uint64_t>(node->getAttributeValue("timescale"))))); parseAvailability<SegmentInformation>(mpd, node, info); @@ -394,7 +396,7 @@ void IsoffMainParser::parseRepresentations (MPD *mpd, Node *adaptationSetNode { SegmentBase *base = new (std::nothrow) SegmentBase(currentRepresentation); if(base) - currentRepresentation->setSegmentBase(base); + currentRepresentation->addAttribute(base); } adaptationSet->addRepresentation(currentRepresentation); @@ -419,7 +421,7 @@ size_t IsoffMainParser::parseSegmentBase(MPD *mpd, Node * segmentBaseNode, Segme base->initialisationSegment.Set(initSeg); } - info->setSegmentBase(base); + info->addAttribute(base); return 1; } @@ -458,11 +460,12 @@ size_t IsoffMainParser::parseSegmentList(MPD *mpd, Node * segListNode, SegmentIn seg->setByteRange(atoi(range.substr(0, pos).c_str()), atoi(range.substr(pos + 1, range.size()).c_str())); } - if(list->duration.Get()) + stime_t duration = list->inheritDuration(); + if(duration) { seg->startTime.Set(nzStartTime); - seg->duration.Set(list->duration.Get()); - nzStartTime += list->duration.Get(); + seg->duration.Set(duration); + nzStartTime += duration; } seg->setSequenceNumber(total); @@ -534,7 +537,8 @@ void IsoffMainParser::parseTimeline(Node *node, AbstractMultipleSegmentBaseType number += (1 + r); } - base->setSegmentTimeline(timeline); + //base->setSegmentTimeline(timeline); + base->addAttribute(timeline); } } diff --git a/modules/demux/dash/mpd/Representation.cpp b/modules/demux/dash/mpd/Representation.cpp index 9f936fe4ef..e0026e3902 100644 --- a/modules/demux/dash/mpd/Representation.cpp +++ b/modules/demux/dash/mpd/Representation.cpp @@ -109,9 +109,9 @@ stime_t Representation::getScaledTimeBySegmentNumber(uint64_t index, const Segme { time = tl->getScaledPlaybackTimeByElementNumber(index); } - else if(templ->duration.Get()) + else if(templ->inheritDuration()) { - time = templ->duration.Get() * index; + time = templ->inheritDuration() * index; } return time; } diff --git a/modules/demux/hls/playlist/Parser.cpp b/modules/demux/hls/playlist/Parser.cpp index 5a6de6049d..e2e1aaefe4 100644 --- a/modules/demux/hls/playlist/Parser.cpp +++ b/modules/demux/hls/playlist/Parser.cpp @@ -209,7 +209,8 @@ void M3U8Parser::parseSegments(vlc_object_t *, Representation *rep, const std::l { SegmentList *segmentList = new (std::nothrow) SegmentList(rep); - rep->setTimescale(100); + Timescale timescale(100); + rep->addAttribute(new TimescaleAttr(timescale)); rep->b_loaded = true; vlc_tick_t totalduration = 0; @@ -266,8 +267,8 @@ void M3U8Parser::parseSegments(vlc_object_t *, Representation *rep, const std::l nzDuration = vlc_tick_from_sec(durAttribute->floatingPoint()); ctx_extinf = NULL; } - segment->duration.Set(rep->getTimescale().ToScaled(nzDuration)); - segment->startTime.Set(rep->getTimescale().ToScaled(nzStartTime)); + segment->duration.Set(timescale.ToScaled(nzDuration)); + segment->startTime.Set(timescale.ToScaled(nzStartTime)); nzStartTime += nzDuration; totalduration += nzDuration; if(absReferenceTime != VLC_TICK_INVALID) diff --git a/modules/demux/hls/playlist/Representation.cpp b/modules/demux/hls/playlist/Representation.cpp index 08f7b40249..4103478f46 100644 --- a/modules/demux/hls/playlist/Representation.cpp +++ b/modules/demux/hls/playlist/Representation.cpp @@ -169,8 +169,10 @@ uint64_t Representation::translateSegmentNumber(uint64_t num, const BaseRepresen HLSSegment *fromHlsSeg = dynamic_cast<HLSSegment *>(fromSeg); if(!fromHlsSeg) return 1; + + const Timescale timescale = inheritTimescale(); const vlc_tick_t utcTime = fromHlsSeg->getUTCTime() + - getTimescale().ToTime(fromHlsSeg->duration.Get()) / 2; + timescale.ToTime(fromHlsSeg->duration.Get()) / 2; const std::vector<Segment *> &list = inheritSegmentList()->getSegments(); std::vector<Segment *>::const_iterator it; diff --git a/modules/demux/smooth/mp4/IndexReader.cpp b/modules/demux/smooth/mp4/IndexReader.cpp index ef3e363030..597918a9e5 100644 --- a/modules/demux/smooth/mp4/IndexReader.cpp +++ b/modules/demux/smooth/mp4/IndexReader.cpp @@ -60,7 +60,7 @@ bool IndexReader::parseIndex(block_t *p_block, BaseRepresentation *rep) if(!uuid_box) return false; - SegmentTimeline *timelineadd = new (std::nothrow) SegmentTimeline(rep->inheritTimescale()); + SegmentTimeline *timelineadd = new (std::nothrow) SegmentTimeline(NULL); if (timelineadd) { const MP4_Box_data_tfrf_t *p_tfrfdata = uuid_box->data.p_tfrf; diff --git a/modules/demux/smooth/playlist/Manifest.cpp b/modules/demux/smooth/playlist/Manifest.cpp index 5538bc644f..c967feb29f 100644 --- a/modules/demux/smooth/playlist/Manifest.cpp +++ b/modules/demux/smooth/playlist/Manifest.cpp @@ -29,10 +29,10 @@ using namespace smooth::playlist; Manifest::Manifest (vlc_object_t *p_object) : - AbstractPlaylist(p_object), TimescaleAble() + AbstractPlaylist(p_object) { minUpdatePeriod.Set( VLC_TICK_FROM_SEC(5) ); - setTimescale( 10000000 ); // 100ns + addAttribute(new TimescaleAttr(Timescale(10000000))); // 100ns b_live = false; } diff --git a/modules/demux/smooth/playlist/Manifest.hpp b/modules/demux/smooth/playlist/Manifest.hpp index 94facfd503..b0e0e6a3f7 100644 --- a/modules/demux/smooth/playlist/Manifest.hpp +++ b/modules/demux/smooth/playlist/Manifest.hpp @@ -21,8 +21,6 @@ #define MANIFEST_HPP #include "../../adaptive/playlist/AbstractPlaylist.hpp" -#include "../../adaptive/playlist/Inheritables.hpp" -#include "../../adaptive/Time.hpp" namespace smooth { @@ -30,8 +28,7 @@ namespace smooth { using namespace adaptive::playlist; - class Manifest : public AbstractPlaylist, - public TimescaleAble + class Manifest : public AbstractPlaylist { friend class ManifestParser; diff --git a/modules/demux/smooth/playlist/Parser.cpp b/modules/demux/smooth/playlist/Parser.cpp index 4ca85add22..08b68188be 100644 --- a/modules/demux/smooth/playlist/Parser.cpp +++ b/modules/demux/smooth/playlist/Parser.cpp @@ -52,9 +52,9 @@ ManifestParser::~ManifestParser() { } -static SegmentTimeline *createTimeline(Node *streamIndexNode, uint64_t timescale) +static SegmentTimeline *createTimeline(Node *streamIndexNode) { - SegmentTimeline *timeline = new (std::nothrow) SegmentTimeline(timescale); + SegmentTimeline *timeline = new (std::nothrow) SegmentTimeline(NULL); if(timeline) { std::vector<Node *> chunks = DOMHelper::getElementByTagName(streamIndexNode, "c", true); @@ -143,7 +143,8 @@ static SegmentTimeline *createTimeline(Node *streamIndexNode, uint64_t timescale return timeline; } -static void ParseQualityLevel(BaseAdaptationSet *adaptSet, Node *qualNode, const std::string &type, unsigned id, unsigned trackid) +static void ParseQualityLevel(BaseAdaptationSet *adaptSet, Node *qualNode, const std::string &type, + unsigned id, unsigned trackid, const Timescale ×cale) { Representation *rep = new (std::nothrow) Representation(adaptSet); if(rep) @@ -168,7 +169,7 @@ static void ParseQualityLevel(BaseAdaptationSet *adaptSet, Node *qualNode, const ForgedInitSegment *initSegment = new (std::nothrow) ForgedInitSegment(rep, type, - adaptSet->inheritTimescale(), + timescale, adaptSet->getPlaylist()->duration.Get()); if(initSegment) { @@ -225,8 +226,12 @@ static void ParseStreamIndex(BasePeriod *period, Node *streamIndexNode, unsigned if(streamIndexNode->hasAttribute("Name")) adaptSet->description.Set(streamIndexNode->getAttributeValue("Name")); + Timescale timescale(10000000); if(streamIndexNode->hasAttribute("TimeScale")) - adaptSet->setTimescale(Integer<uint64_t>(streamIndexNode->getAttributeValue("TimeScale"))); + { + timescale = Timescale(Integer<uint64_t>(streamIndexNode->getAttributeValue("TimeScale"))); + adaptSet->addAttribute(new TimescaleAttr(timescale)); + } const std::string url = streamIndexNode->getAttributeValue("Url"); if(!url.empty()) @@ -236,8 +241,8 @@ static void ParseStreamIndex(BasePeriod *period, Node *streamIndexNode, unsigned if(templ) { templ->setSourceUrl(url); - SegmentTimeline *timeline = createTimeline(streamIndexNode, adaptSet->inheritTimescale()); - templ->setSegmentTimeline(timeline); + SegmentTimeline *timeline = createTimeline(streamIndexNode); + templ->addAttribute(timeline); adaptSet->setSegmentTemplate(templ); } @@ -246,7 +251,7 @@ static void ParseStreamIndex(BasePeriod *period, Node *streamIndexNode, unsigned std::vector<Node *> qualLevels = DOMHelper::getElementByTagName(streamIndexNode, "QualityLevel", true); std::vector<Node *>::const_iterator it; for(it = qualLevels.begin(); it != qualLevels.end(); ++it) - ParseQualityLevel(adaptSet, *it, type, nextid++, id); + ParseQualityLevel(adaptSet, *it, type, nextid++, id, timescale); } if(!adaptSet->getRepresentations().empty()) period->addAdaptationSet(adaptSet); @@ -263,19 +268,24 @@ Manifest * ManifestParser::parse() manifest->setPlaylistUrl(Helper::getDirectoryPath(playlisturl).append("/")); + Timescale timescale(10000000); + if(root->hasAttribute("TimeScale")) - manifest->setTimescale(Integer<uint64_t>(root->getAttributeValue("TimeScale"))); + { + timescale = Timescale(Integer<uint64_t>(root->getAttributeValue("TimeScale"))); + manifest->addAttribute(new TimescaleAttr(timescale)); + } if(root->hasAttribute("Duration")) { stime_t time = Integer<stime_t>(root->getAttributeValue("Duration")); - manifest->duration.Set(manifest->getTimescale().ToTime(time)); + manifest->duration.Set(timescale.ToTime(time)); } if(root->hasAttribute("DVRWindowLength")) { stime_t time = Integer<stime_t>(root->getAttributeValue("DVRWindowLength")); - manifest->timeShiftBufferDepth.Set(manifest->getTimescale().ToTime(time)); + manifest->timeShiftBufferDepth.Set(timescale.ToTime(time)); } if(root->hasAttribute("IsLive") && root->getAttributeValue("IsLive") == "TRUE") @@ -285,7 +295,6 @@ Manifest * ManifestParser::parse() BasePeriod *period = new (std::nothrow) BasePeriod(manifest); if(period) { - period->setTimescale(manifest->getTimescale()); period->duration.Set(manifest->duration.Get()); unsigned nextid = 1; std::vector<Node *> streamIndexes = DOMHelper::getElementByTagName(root, "StreamIndex", true); _______________________________________________ vlc-commits mailing list [email protected] https://mailman.videolan.org/listinfo/vlc-commits
