Commit 673cd4db authored by Francois Cartegnie's avatar Francois Cartegnie

demux: adaptative: fix time units and update times

Since we're dealing with 3 different units (time, mtime and scaled time)
things have gone wrong when merging hls and dash code.

Should fix the crazy manifest/playlist updates
parent 5073078a
...@@ -307,6 +307,7 @@ libadaptative_plugin_la_SOURCES = \ ...@@ -307,6 +307,7 @@ libadaptative_plugin_la_SOURCES = \
demux/adaptative/Streams.cpp \ demux/adaptative/Streams.cpp \
demux/adaptative/Streams.hpp \ demux/adaptative/Streams.hpp \
demux/adaptative/StreamsType.hpp \ demux/adaptative/StreamsType.hpp \
demux/adaptative/Time.hpp \
demux/adaptative/tools/Helper.cpp \ demux/adaptative/tools/Helper.cpp \
demux/adaptative/tools/Helper.h \ demux/adaptative/tools/Helper.h \
demux/adaptative/tools/Properties.hpp \ demux/adaptative/tools/Properties.hpp \
......
...@@ -85,7 +85,7 @@ namespace adaptative ...@@ -85,7 +85,7 @@ namespace adaptative
AbstractStreamOutputFactory *streamOutputFactory; AbstractStreamOutputFactory *streamOutputFactory;
demux_t *p_demux; demux_t *p_demux;
std::vector<Stream *> streams; std::vector<Stream *> streams;
mtime_t nextPlaylistupdate; time_t nextPlaylistupdate;
mtime_t i_nzpcr; mtime_t i_nzpcr;
BasePeriod *currentPeriod; BasePeriod *currentPeriod;
}; };
......
/*****************************************************************************
* Time.hpp: Adaptative streaming time definitions
*****************************************************************************
* Copyright © 2015 - 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 TIME_HPP
#define TIME_HPP
/* Scaled time */
typedef int64_t stime_t;
#endif // TIME_HPP
...@@ -39,7 +39,7 @@ AbstractPlaylist::AbstractPlaylist (stream_t *stream_) : ...@@ -39,7 +39,7 @@ AbstractPlaylist::AbstractPlaylist (stream_t *stream_) :
availabilityStartTime.Set( 0 ); availabilityStartTime.Set( 0 );
availabilityEndTime.Set( 0 ); availabilityEndTime.Set( 0 );
duration.Set( 0 ); duration.Set( 0 );
minUpdatePeriod.Set( 2 ); minUpdatePeriod.Set( 2 * CLOCK_FREQ );
maxSegmentDuration.Set( 0 ); maxSegmentDuration.Set( 0 );
minBufferTime.Set( 0 ); minBufferTime.Set( 0 );
timeShiftBufferDepth.Set( 0 ); timeShiftBufferDepth.Set( 0 );
......
...@@ -62,10 +62,10 @@ namespace adaptative ...@@ -62,10 +62,10 @@ namespace adaptative
Property<time_t> playbackStart; Property<time_t> playbackStart;
Property<time_t> availabilityEndTime; Property<time_t> availabilityEndTime;
Property<time_t> availabilityStartTime; Property<time_t> availabilityStartTime;
Property<time_t> minUpdatePeriod; Property<mtime_t> minUpdatePeriod;
Property<mtime_t> maxSegmentDuration; Property<mtime_t> maxSegmentDuration;
Property<time_t> minBufferTime; Property<mtime_t> minBufferTime;
Property<time_t> timeShiftBufferDepth; Property<mtime_t> timeShiftBufferDepth;
protected: protected:
stream_t *stream; stream_t *stream;
......
...@@ -118,7 +118,7 @@ int ISegment::compare(ISegment *other) const ...@@ -118,7 +118,7 @@ int ISegment::compare(ISegment *other) const
{ {
if(duration.Get()) if(duration.Get())
{ {
int64_t diff = startTime.Get() - other->startTime.Get(); stime_t diff = startTime.Get() - other->startTime.Get();
if(diff) if(diff)
return diff / diff; return diff / diff;
} }
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include "ICanonicalUrl.hpp" #include "ICanonicalUrl.hpp"
#include "../http/Chunk.h" #include "../http/Chunk.h"
#include "../tools/Properties.hpp" #include "../tools/Properties.hpp"
#include "Time.hpp"
namespace adaptative namespace adaptative
{ {
...@@ -61,8 +62,8 @@ namespace adaptative ...@@ -61,8 +62,8 @@ namespace adaptative
virtual bool contains (size_t byte) const; virtual bool contains (size_t byte) const;
virtual int compare (ISegment *) const; virtual int compare (ISegment *) const;
int getClassId () const; int getClassId () const;
Property<mtime_t> startTime; Property<stime_t> startTime;
Property<mtime_t> duration; Property<stime_t> duration;
Property<unsigned> chunksuse; Property<unsigned> chunksuse;
static const int CLASSID_ISEGMENT = 0; static const int CLASSID_ISEGMENT = 0;
......
...@@ -65,8 +65,8 @@ Url SegmentInfoCommon::getUrlSegment() const ...@@ -65,8 +65,8 @@ Url SegmentInfoCommon::getUrlSegment() const
return ret; return ret;
} }
bool SegmentInfoCommon::getSegmentNumberByTime(const std::vector<ISegment *> &segments, bool SegmentInfoCommon::getSegmentNumberByScaledTime(const std::vector<ISegment *> &segments,
mtime_t time, uint64_t *ret) stime_t time, uint64_t *ret)
{ {
if(segments.empty() || (segments.size() > 1 && segments[1]->startTime.Get() == 0) ) if(segments.empty() || (segments.size() > 1 && segments[1]->startTime.Get() == 0) )
return false; return false;
......
...@@ -50,9 +50,9 @@ namespace adaptative ...@@ -50,9 +50,9 @@ namespace adaptative
void setStartIndex( int startIndex ); void setStartIndex( int startIndex );
void appendBaseURL( const std::string& url ); void appendBaseURL( const std::string& url );
virtual Url getUrlSegment() const; /* impl */ virtual Url getUrlSegment() const; /* impl */
Property<uint64_t> duration; Property<stime_t> duration;
static bool getSegmentNumberByTime(const std::vector<ISegment *> &, static bool getSegmentNumberByScaledTime(const std::vector<ISegment *> &,
mtime_t, uint64_t *); stime_t, uint64_t *);
private: private:
int startIndex; int startIndex;
......
...@@ -198,7 +198,9 @@ bool SegmentInformation::getSegmentNumberByTime(mtime_t time, uint64_t *ret) con ...@@ -198,7 +198,9 @@ bool SegmentInformation::getSegmentNumberByTime(mtime_t time, uint64_t *ret) con
} }
else if ( segmentList && !segmentList->getSegments().empty() ) else if ( segmentList && !segmentList->getSegments().empty() )
{ {
return segmentList->getSegmentNumberByTime(time, ret); const uint64_t timescale = segmentList->inheritTimescale();
time = time * timescale / CLOCK_FREQ;
return segmentList->getSegmentNumberByScaledTime(time, ret);
} }
else if( segmentBase ) else if( segmentBase )
{ {
...@@ -206,7 +208,7 @@ bool SegmentInformation::getSegmentNumberByTime(mtime_t time, uint64_t *ret) con ...@@ -206,7 +208,7 @@ bool SegmentInformation::getSegmentNumberByTime(mtime_t time, uint64_t *ret) con
time = time * timescale / CLOCK_FREQ; time = time * timescale / CLOCK_FREQ;
*ret = 0; *ret = 0;
const std::vector<ISegment *> list = segmentBase->subSegments(); const std::vector<ISegment *> list = segmentBase->subSegments();
return SegmentInfoCommon::getSegmentNumberByTime(list, time, ret); return SegmentInfoCommon::getSegmentNumberByScaledTime(list, time, ret);
} }
if(parent) if(parent)
...@@ -261,7 +263,7 @@ void SegmentInformation::getDurationsRange(mtime_t *min, mtime_t *max) const ...@@ -261,7 +263,7 @@ void SegmentInformation::getDurationsRange(mtime_t *min, mtime_t *max) const
mtime_t total = 0; mtime_t total = 0;
for(it = seglist.begin(); it != seglist.end(); ++it) for(it = seglist.begin(); it != seglist.end(); ++it)
{ {
const mtime_t duration = (*it)->duration.Get(); const mtime_t duration = (*it)->duration.Get() * CLOCK_FREQ / inheritTimescale();
if(duration) if(duration)
{ {
total += duration; total += duration;
...@@ -334,7 +336,7 @@ void SegmentInformation::setSegmentTemplate(MediaSegmentTemplate *templ) ...@@ -334,7 +336,7 @@ void SegmentInformation::setSegmentTemplate(MediaSegmentTemplate *templ)
} }
static void insertIntoSegment(std::vector<ISegment *> &seglist, size_t start, static void insertIntoSegment(std::vector<ISegment *> &seglist, size_t start,
size_t end, mtime_t time) size_t end, stime_t time)
{ {
std::vector<ISegment *>::iterator segIt; std::vector<ISegment *>::iterator segIt;
for(segIt = seglist.begin(); segIt < seglist.end(); ++segIt) for(segIt = seglist.begin(); segIt < seglist.end(); ++segIt)
...@@ -360,6 +362,7 @@ void SegmentInformation::SplitUsingIndex(std::vector<SplitPoint> &splitlist) ...@@ -360,6 +362,7 @@ void SegmentInformation::SplitUsingIndex(std::vector<SplitPoint> &splitlist)
std::vector<SplitPoint>::const_iterator splitIt; std::vector<SplitPoint>::const_iterator splitIt;
size_t start = 0, end = 0; size_t start = 0, end = 0;
mtime_t time = 0; mtime_t time = 0;
const uint64_t i_timescale = inheritTimescale();
for(splitIt = splitlist.begin(); splitIt < splitlist.end(); ++splitIt) for(splitIt = splitlist.begin(); splitIt < splitlist.end(); ++splitIt)
{ {
...@@ -369,7 +372,7 @@ void SegmentInformation::SplitUsingIndex(std::vector<SplitPoint> &splitlist) ...@@ -369,7 +372,7 @@ void SegmentInformation::SplitUsingIndex(std::vector<SplitPoint> &splitlist)
if(splitIt == splitlist.begin() && split.offset == 0) if(splitIt == splitlist.begin() && split.offset == 0)
continue; continue;
time = split.time; time = split.time;
insertIntoSegment(seglist, start, end, time); insertIntoSegment(seglist, start, end, time * i_timescale / CLOCK_FREQ);
end++; end++;
} }
...@@ -377,7 +380,7 @@ void SegmentInformation::SplitUsingIndex(std::vector<SplitPoint> &splitlist) ...@@ -377,7 +380,7 @@ void SegmentInformation::SplitUsingIndex(std::vector<SplitPoint> &splitlist)
{ {
start = end; start = end;
end = 0; end = 0;
insertIntoSegment(seglist, start, end, time); insertIntoSegment(seglist, start, end, time * i_timescale / CLOCK_FREQ);
} }
} }
......
...@@ -86,12 +86,10 @@ void SegmentList::pruneBySegmentNumber(uint64_t tobelownum) ...@@ -86,12 +86,10 @@ void SegmentList::pruneBySegmentNumber(uint64_t tobelownum)
} }
} }
bool SegmentList::getSegmentNumberByTime(mtime_t time, uint64_t *ret) const bool SegmentList::getSegmentNumberByScaledTime(stime_t time, uint64_t *ret) const
{ {
const uint64_t timescale = inheritTimescale();
time = time * timescale / CLOCK_FREQ;
*ret = pruned; *ret = pruned;
return SegmentInfoCommon::getSegmentNumberByTime(segments, time, ret); return SegmentInfoCommon::getSegmentNumberByScaledTime(segments, time, ret);
} }
mtime_t SegmentList::getPlaybackTimeBySegmentNumber(uint64_t number) mtime_t SegmentList::getPlaybackTimeBySegmentNumber(uint64_t number)
...@@ -99,8 +97,8 @@ mtime_t SegmentList::getPlaybackTimeBySegmentNumber(uint64_t number) ...@@ -99,8 +97,8 @@ mtime_t SegmentList::getPlaybackTimeBySegmentNumber(uint64_t number)
if(number < pruned || segments.empty()) if(number < pruned || segments.empty())
return VLC_TS_INVALID; return VLC_TS_INVALID;
uint64_t timescale = inheritTimescale(); const uint64_t timescale = inheritTimescale();
mtime_t time = segments.at(0)->startTime.Get(); stime_t time = segments.at(0)->startTime.Get();
if(segments.at(0)->duration.Get()) if(segments.at(0)->duration.Get())
{ {
......
...@@ -49,7 +49,7 @@ namespace adaptative ...@@ -49,7 +49,7 @@ namespace adaptative
void addSegment(ISegment *seg); void addSegment(ISegment *seg);
void mergeWith(SegmentList *); void mergeWith(SegmentList *);
void pruneBySegmentNumber(uint64_t); void pruneBySegmentNumber(uint64_t);
bool getSegmentNumberByTime(mtime_t, uint64_t *) const; bool getSegmentNumberByScaledTime(stime_t, uint64_t *) const;
mtime_t getPlaybackTimeBySegmentNumber(uint64_t); mtime_t getPlaybackTimeBySegmentNumber(uint64_t);
std::size_t getOffset() const; std::size_t getOffset() const;
......
...@@ -40,7 +40,7 @@ SegmentTimeline::~SegmentTimeline() ...@@ -40,7 +40,7 @@ SegmentTimeline::~SegmentTimeline()
delete *it; delete *it;
} }
void SegmentTimeline::addElement(mtime_t d, uint64_t r, mtime_t t) void SegmentTimeline::addElement(stime_t d, uint64_t r, stime_t t)
{ {
Element *element = new (std::nothrow) Element(d, r, t); Element *element = new (std::nothrow) Element(d, r, t);
if(element) if(element)
...@@ -54,7 +54,7 @@ void SegmentTimeline::addElement(mtime_t d, uint64_t r, mtime_t t) ...@@ -54,7 +54,7 @@ void SegmentTimeline::addElement(mtime_t d, uint64_t r, mtime_t t)
} }
} }
uint64_t SegmentTimeline::getElementNumberByScaledPlaybackTime(time_t scaled) const uint64_t SegmentTimeline::getElementNumberByScaledPlaybackTime(stime_t scaled) const
{ {
uint64_t count = 0; uint64_t count = 0;
std::list<Element *>::const_iterator it; std::list<Element *>::const_iterator it;
...@@ -74,9 +74,9 @@ uint64_t SegmentTimeline::getElementNumberByScaledPlaybackTime(time_t scaled) co ...@@ -74,9 +74,9 @@ uint64_t SegmentTimeline::getElementNumberByScaledPlaybackTime(time_t scaled) co
return count; return count;
} }
mtime_t SegmentTimeline::getScaledPlaybackTimeByElementNumber(uint64_t number) const stime_t SegmentTimeline::getScaledPlaybackTimeByElementNumber(uint64_t number) const
{ {
mtime_t totalscaledtime = 0; stime_t totalscaledtime = 0;
if(number < pruned) if(number < pruned)
return 0; return 0;
...@@ -120,12 +120,12 @@ size_t SegmentTimeline::maxElementNumber() const ...@@ -120,12 +120,12 @@ size_t SegmentTimeline::maxElementNumber() const
size_t SegmentTimeline::prune(mtime_t time) size_t SegmentTimeline::prune(mtime_t time)
{ {
mtime_t scaled = time * inheritTimescale() / CLOCK_FREQ; stime_t scaled = time * inheritTimescale() / CLOCK_FREQ;
size_t prunednow = 0; size_t prunednow = 0;
while(elements.size()) while(elements.size())
{ {
Element *el = elements.front(); Element *el = elements.front();
if(el->t + (el->d * (mtime_t)(el->r + 1)) < scaled) if(el->t + (el->d * (stime_t)(el->r + 1)) < scaled)
{ {
prunednow += el->r + 1; prunednow += el->r + 1;
delete el; delete el;
...@@ -163,7 +163,7 @@ void SegmentTimeline::mergeWith(SegmentTimeline &other) ...@@ -163,7 +163,7 @@ void SegmentTimeline::mergeWith(SegmentTimeline &other)
} }
else if(el->t > last->t) /* Did not exist in previous list */ else if(el->t > last->t) /* Did not exist in previous list */
{ {
if( el->t - last->t >= last->d * (mtime_t)(last->r + 1) ) if( el->t - last->t >= last->d * (stime_t)(last->r + 1) )
{ {
elements.push_back(el); elements.push_back(el);
last = el; last = el;
...@@ -191,7 +191,7 @@ mtime_t SegmentTimeline::start() const ...@@ -191,7 +191,7 @@ mtime_t SegmentTimeline::start() const
{ {
if(elements.empty()) if(elements.empty())
return 0; return 0;
return CLOCK_FREQ * elements.front()->t / inheritTimescale(); return elements.front()->t * CLOCK_FREQ / inheritTimescale();
} }
mtime_t SegmentTimeline::end() const mtime_t SegmentTimeline::end() const
...@@ -199,11 +199,11 @@ mtime_t SegmentTimeline::end() const ...@@ -199,11 +199,11 @@ mtime_t SegmentTimeline::end() const
if(elements.empty()) if(elements.empty())
return 0; return 0;
const Element *last = elements.back(); const Element *last = elements.back();
mtime_t scaled = last->t + last->d * (last->r + 1); stime_t scaled = last->t + last->d * (last->r + 1);
return CLOCK_FREQ * scaled / inheritTimescale(); return scaled * CLOCK_FREQ / inheritTimescale();
} }
SegmentTimeline::Element::Element(mtime_t d_, uint64_t r_, mtime_t t_) SegmentTimeline::Element::Element(stime_t d_, uint64_t r_, stime_t t_)
{ {
d = d_; d = d_;
t = t_; t = t_;
......
...@@ -43,9 +43,9 @@ namespace adaptative ...@@ -43,9 +43,9 @@ namespace adaptative
public: public:
SegmentTimeline(TimescaleAble * = NULL); SegmentTimeline(TimescaleAble * = NULL);
virtual ~SegmentTimeline(); virtual ~SegmentTimeline();
void addElement(mtime_t d, uint64_t r = 0, mtime_t t = 0); void addElement(stime_t d, uint64_t r = 0, stime_t t = 0);
uint64_t getElementNumberByScaledPlaybackTime(time_t) const; uint64_t getElementNumberByScaledPlaybackTime(stime_t) const;
mtime_t getScaledPlaybackTimeByElementNumber(uint64_t) const; stime_t getScaledPlaybackTimeByElementNumber(uint64_t) const;
size_t maxElementNumber() const; size_t maxElementNumber() const;
size_t prune(mtime_t); size_t prune(mtime_t);
void mergeWith(SegmentTimeline &); void mergeWith(SegmentTimeline &);
...@@ -59,9 +59,9 @@ namespace adaptative ...@@ -59,9 +59,9 @@ namespace adaptative
class Element class Element
{ {
public: public:
Element(mtime_t, uint64_t, mtime_t); Element(stime_t, uint64_t, stime_t);
mtime_t t; stime_t t;
mtime_t d; stime_t d;
uint64_t r; uint64_t r;
}; };
}; };
......
...@@ -78,7 +78,7 @@ bool DASHManager::updatePlaylist() ...@@ -78,7 +78,7 @@ bool DASHManager::updatePlaylist()
if(!playlist->isLive() || !playlist->minUpdatePeriod.Get()) if(!playlist->isLive() || !playlist->minUpdatePeriod.Get())
return true; return true;
mtime_t now = time(NULL); time_t now = time(NULL);
if(nextPlaylistupdate && now < nextPlaylistupdate) if(nextPlaylistupdate && now < nextPlaylistupdate)
return true; return true;
...@@ -98,7 +98,7 @@ bool DASHManager::updatePlaylist() ...@@ -98,7 +98,7 @@ bool DASHManager::updatePlaylist()
if(!mpdstream) if(!mpdstream)
{ {
free(p_data); free(p_data);
nextPlaylistupdate = now + playlist->minUpdatePeriod.Get(); nextPlaylistupdate = now + playlist->minUpdatePeriod.Get() / CLOCK_FREQ;
return false; return false;
} }
...@@ -106,7 +106,7 @@ bool DASHManager::updatePlaylist() ...@@ -106,7 +106,7 @@ bool DASHManager::updatePlaylist()
if(!parser.parse()) if(!parser.parse())
{ {
stream_Delete(mpdstream); stream_Delete(mpdstream);
nextPlaylistupdate = now + playlist->minUpdatePeriod.Get(); nextPlaylistupdate = now + playlist->minUpdatePeriod.Get() / CLOCK_FREQ;
return false; return false;
} }
...@@ -134,19 +134,20 @@ bool DASHManager::updatePlaylist() ...@@ -134,19 +134,20 @@ bool DASHManager::updatePlaylist()
mtime_t mininterval = 0; mtime_t mininterval = 0;
mtime_t maxinterval = 0; mtime_t maxinterval = 0;
playlist->getTimeLinesBoundaries(&mininterval, &maxinterval); playlist->getTimeLinesBoundaries(&mininterval, &maxinterval);
if(maxinterval > mininterval)
maxinterval = (maxinterval - mininterval);
else
maxinterval = 60 * CLOCK_FREQ;
maxinterval = std::max(maxinterval, (mtime_t)60 * CLOCK_FREQ);
mininterval = std::max(playlist->minUpdatePeriod.Get() * CLOCK_FREQ, if(playlist->minUpdatePeriod.Get() > mininterval)
playlist->maxSegmentDuration.Get()); mininterval = playlist->minUpdatePeriod.Get();
nextPlaylistupdate = now + (maxinterval - mininterval) / (2 * CLOCK_FREQ); if(mininterval < 5 * CLOCK_FREQ)
mininterval = 5 * CLOCK_FREQ;
if(maxinterval < mininterval)
maxinterval = mininterval;
nextPlaylistupdate = now + (mininterval + (maxinterval - mininterval) / 2) / CLOCK_FREQ;
msg_Dbg(p_demux, "Updated MPD, next update in %" PRId64 "s (%" PRId64 "..%" PRId64 ")", msg_Dbg(p_demux, "Updated MPD, next update in %" PRId64 "s (%" PRId64 "..%" PRId64 ")",
nextPlaylistupdate - now, mininterval, maxinterval ); nextPlaylistupdate - now, mininterval/ CLOCK_FREQ, maxinterval/ CLOCK_FREQ );
return true; return true;
} }
......
...@@ -101,12 +101,12 @@ void IsoffMainParser::setMPDAttributes () ...@@ -101,12 +101,12 @@ void IsoffMainParser::setMPDAttributes ()
it = attr.find("minBufferTime"); it = attr.find("minBufferTime");
if(it != attr.end()) if(it != attr.end())
this->mpd->minBufferTime.Set(IsoTime(it->second)); this->mpd->minBufferTime.Set(IsoTime(it->second) * CLOCK_FREQ);
it = attr.find("minimumUpdatePeriod"); it = attr.find("minimumUpdatePeriod");
if(it != attr.end()) if(it != attr.end())
{ {
mtime_t minupdate = IsoTime(it->second); mtime_t minupdate = IsoTime(it->second) * CLOCK_FREQ;
if(minupdate > 0) if(minupdate > 0)
mpd->minUpdatePeriod.Set(minupdate); mpd->minUpdatePeriod.Set(minupdate);
} }
...@@ -125,7 +125,7 @@ void IsoffMainParser::setMPDAttributes () ...@@ -125,7 +125,7 @@ void IsoffMainParser::setMPDAttributes ()
it = attr.find("timeShiftBufferDepth"); it = attr.find("timeShiftBufferDepth");
if(it != attr.end()) if(it != attr.end())
mpd->timeShiftBufferDepth.Set(IsoTime(it->second)); mpd->timeShiftBufferDepth.Set(IsoTime(it->second) * CLOCK_FREQ);
} }
void IsoffMainParser::parsePeriods(Node *root) void IsoffMainParser::parsePeriods(Node *root)
...@@ -140,9 +140,9 @@ void IsoffMainParser::parsePeriods(Node *root) ...@@ -140,9 +140,9 @@ void IsoffMainParser::parsePeriods(Node *root)
continue; continue;
parseSegmentInformation(*it, period); parseSegmentInformation(*it, period);
if((*it)->hasAttribute("start")) if((*it)->hasAttribute("start"))
period->startTime.Set(IsoTime((*it)->getAttributeValue("start"))); period->startTime.Set(IsoTime((*it)->getAttributeValue("start")) * CLOCK_FREQ);
if((*it)->hasAttribute("duration")) if((*it)->hasAttribute("duration"))
period->duration.Set(IsoTime((*it)->getAttributeValue("duration"))); period->duration.Set(IsoTime((*it)->getAttributeValue("duration")) * CLOCK_FREQ);
if((*it)->hasAttribute("id")) if((*it)->hasAttribute("id"))
period->setId((*it)->getAttributeValue("id")); period->setId((*it)->getAttributeValue("id"));
std::vector<Node *> baseUrls = DOMHelper::getChildElementByTagName(*it, "BaseURL"); std::vector<Node *> baseUrls = DOMHelper::getChildElementByTagName(*it, "BaseURL");
...@@ -169,12 +169,12 @@ size_t IsoffMainParser::parseSegmentTemplate(Node *templateNode, SegmentInformat ...@@ -169,12 +169,12 @@ size_t IsoffMainParser::parseSegmentTemplate(Node *templateNode, SegmentInformat
if(templateNode->hasAttribute("startNumber")) if(templateNode->hasAttribute("startNumber"))
mediaTemplate->startNumber.Set(Integer<uint64_t>(templateNode->getAttributeValue("startNumber"))); mediaTemplate->startNumber.Set(Integer<uint64_t>(templateNode->getAttributeValue("startNumber")));
if(templateNode->hasAttribute("duration"))
mediaTemplate->duration.Set(Integer<mtime_t>(templateNode->getAttributeValue("duration")));
if(templateNode->hasAttribute("timescale")) if(templateNode->hasAttribute("timescale"))
mediaTemplate->timescale.Set(Integer<uint64_t>(templateNode->getAttributeValue("timescale"))); mediaTemplate->timescale.Set(Integer<uint64_t>(templateNode->getAttributeValue("timescale")));
if(templateNode->hasAttribute("duration"))
mediaTemplate->duration.Set(Integer<stime_t>(templateNode->getAttributeValue("duration")));
InitSegmentTemplate *initTemplate = NULL; InitSegmentTemplate *initTemplate = NULL;
if(templateNode->hasAttribute("initialization")) if(templateNode->hasAttribute("initialization"))
...@@ -346,7 +346,7 @@ size_t IsoffMainParser::parseSegmentList(Node * segListNode, SegmentInformation ...@@ -346,7 +346,7 @@ size_t IsoffMainParser::parseSegmentList(Node * segListNode, SegmentInformation
parseInitSegment(DOMHelper::getFirstChildElementByName(segListNode, "Initialization"), list, info); parseInitSegment(DOMHelper::getFirstChildElementByName(segListNode, "Initialization"), list, info);
if(segListNode->hasAttribute("duration")) if(segListNode->hasAttribute("duration"))
list->duration.Set(Integer<uint64_t>(segListNode->getAttributeValue("duration"))); list->duration.Set(Integer<stime_t>(segListNode->getAttributeValue("duration")));
if(segListNode->hasAttribute("timescale")) if(segListNode->hasAttribute("timescale"))
list->timescale.Set(Integer<uint64_t>(segListNode->getAttributeValue("timescale"))); list->timescale.Set(Integer<uint64_t>(segListNode->getAttributeValue("timescale")));
...@@ -422,13 +422,13 @@ void IsoffMainParser::parseTimeline(Node *node, MediaSegmentTemplate *templ) ...@@ -422,13 +422,13 @@ void IsoffMainParser::parseTimeline(Node *node, MediaSegmentTemplate *templ)
const Node *s = *it; const Node *s = *it;
if(!s->hasAttribute("d")) /* Mandatory */ if(!s->hasAttribute("d")) /* Mandatory */
continue; continue;
mtime_t d = Integer<mtime_t>(s->getAttributeValue("d")); stime_t d = Integer<stime_t>(s->getAttributeValue("d"));
mtime_t r = 0; // never repeats by default uint64_t r = 0; // never repeats by default
if(s->hasAttribute("r")) if(s->hasAttribute("r"))
r = Integer<uint64_t>(s->getAttributeValue("r")); r = Integer<uint64_t>(s->getAttributeValue("r"));
if(s->hasAttribute("t")) if(s->hasAttribute("t"))
{ {
mtime_t t = Integer<mtime_t>(s->getAttributeValue("t")); stime_t t = Integer<stime_t>(s->getAttributeValue("t"));
timeline->addElement(d, r, t); timeline->addElement(d, r, t);
} }
else timeline->addElement(d, r); else timeline->addElement(d, r);
...@@ -470,7 +470,7 @@ IsoTime::IsoTime(const std::string &str) ...@@ -470,7 +470,7 @@ IsoTime::IsoTime(const std::string &str)
time = str_duration(str.c_str()); time = str_duration(str.c_str());
} }
IsoTime::operator mtime_t () const IsoTime::operator time_t () const
{ {
return time; return time;
} }
...@@ -543,7 +543,7 @@ UTCTime::UTCTime(const std::string &str) ...@@ -543,7 +543,7 @@ UTCTime::UTCTime(const std::string &str)
} }
} }
UTCTime::operator mtime_t () const UTCTime::operator time_t () const
{ {
return time; return time;
} }
...@@ -94,20 +94,20 @@ namespace dash ...@@ -94,20 +94,20 @@ namespace dash
{ {
public: public:
IsoTime(const std::string&); IsoTime(const std::string&);
operator mtime_t() const; operator time_t() const;
private: private:
mtime_t time; time_t time;
}; };
class UTCTime class UTCTime
{ {
public: public:
UTCTime(const std::string&); UTCTime(const std::string&);
operator mtime_t() const; operator time_t() const;
private: private:
mtime_t time; time_t time;
}; };
template<typename T> class Integer template<typename T> class Integer
......
...@@ -103,7 +103,7 @@ std::string Representation::contextualize(size_t index, const std::string &compo ...@@ -103,7 +103,7 @@ std::string Representation::contextualize(size_t index, const std::string &compo
if(pos != std::string::npos) if(pos != std::string::npos)
{ {
std::stringstream ss; std::stringstream ss;
ss << getScaledTimeBySegmentNumber(index, templ); ss << (getScaledTimeBySegmentNumber(index, templ) * CLOCK_FREQ / templ->inheritTimescale());
ret.replace(pos, std::string("$Time$").length(), ss.str()); ret.replace(pos, std::string("$Time$").length(), ss.str());
} }
...@@ -187,13 +187,13 @@ size_t Representation::getSegmentNumber(size_t index, const MediaSegmentTemplate ...@@ -187,13 +187,13 @@ size_t Representation::getSegmentNumber(size_t index, const MediaSegmentTemplate
} }
else if(templ->duration.Get()) else if(templ->duration.Get())
{ {
mtime_t playbackstart = getPlaylist()->playbackStart.Get(); const mtime_t playbackstart = getPlaylist()->playbackStart.Get() * CLOCK_FREQ;
mtime_t streamstart = getPlaylist()->availabilityStartTime.Get(); mtime_t streamstart = getPlaylist()->availabilityStartTime.Get() * CLOCK_FREQ;
streamstart += getPeriodStart(); streamstart += getPeriodStart();
mtime_t duration = templ->duration.Get(); const stime_t duration = templ->duration.Get();
uint64_t timescale = templ->inheritTimescale(); const uint64_t timescale = templ->inheritTimescale();
if(duration && timescale) if(duration && timescale)
index += (playbackstart - streamstart) * timescale / duration; index += (playbackstart - streamstart) * timescale * duration / CLOCK_FREQ;
} }
} }
return index; return index;
......
...@@ -128,7 +128,7 @@ bool HLSManager::updatePlaylist() ...@@ -128,7 +128,7 @@ bool HLSManager::updatePlaylist()
if(!playlist->isLive() || !playlist->minUpdatePeriod.Get()) if(!playlist->isLive() || !playlist->minUpdatePeriod.Get())
return true; return true;
mtime_t now = time(NULL); time_t now = time(NULL);
if(nextPlaylistupdate && now < nextPlaylistupdate) if(nextPlaylistupdate && now < nextPlaylistupdate)
return true; return true;
...@@ -150,7 +150,7 @@ bool HLSManager::updatePlaylist() ...@@ -150,7 +150,7 @@ bool HLSManager::updatePlaylist()
if(!updatestream) if(!updatestream)
{ {
free(p_data); free(p_data);
nextPlaylistupdate = now + playlist->minUpdatePeriod.Get(); nextPlaylistupdate = now + playlist->minUpdatePeriod.Get() / CLOCK_FREQ;
return false; return false;
} }
...@@ -159,7 +159,7 @@ bool HLSManager::updatePlaylist() ...@@ -159,7 +159,7 @@ bool HLSManager::updatePlaylist()
if(!updatedplaylist) if(!updatedplaylist)
{ {
stream_Delete(updatestream); stream_Delete(updatestream);
nextPlaylistupdate = now + playlist->minUpdatePeriod.Get(); nextPlaylistupdate = now + playlist->minUpdatePeriod.Get() / CLOCK_FREQ;
return false; return false;
} }
...@@ -189,17 +189,19 @@ bool HLSManager::updatePlaylist() ...@@ -189,17 +189,19 @@ bool HLSManager::updatePlaylist()
playlist->getPlaylistDurationsRange(&mininterval, &maxinterval); playlist->getPlaylistDurationsRange(&mininterval, &maxinterval);
} }
if(playlist->minUpdatePeriod.Get() * CLOCK_FREQ > mininterval) if(playlist->minUpdatePeriod.Get() > mininterval)
mininterval = playlist->minUpdatePeriod.Get() * CLOCK_FREQ; mininterval = playlist->minUpdatePeriod.Get();
if(mininterval < 5 * CLOCK_FREQ)
mininterval = 5 * CLOCK_FREQ;
if(maxinterval < mininterval) if(maxinterval < mininterval)
maxinterval = mininterval; maxinterval = mininterval;
nextPlaylistupdate = now + (mininterval + maxinterval) / (2 * CLOCK_FREQ); nextPlaylistupdate = now + (mininterval + (maxinterval - mininterval) / 2) / CLOCK_FREQ;
msg_Dbg(p_demux, "Updated playlist, next update in %" PRId64 "s " msg_Dbg(p_demux, "Updated playlist, next update in %" PRId64 "s (""%" PRId64 "..%" PRId64 ")",
"%" PRId64 " %" PRId64, nextPlaylistupdate - now, mininterval, nextPlaylistupdate - now, mininterval/ CLOCK_FREQ, maxinterval/ CLOCK_FREQ);
maxinterval);
return true; return true;
} }
...@@ -34,7 +34,7 @@ using namespace hls::playlist; ...@@ -34,7 +34,7 @@ using namespace hls::playlist;
M3U8::M3U8 (stream_t *stream_) : M3U8::M3U8 (stream_t *stream_) :
AbstractPlaylist(stream_) AbstractPlaylist(stream_)
{ {
minUpdatePeriod.Set( 5 ); minUpdatePeriod.Set( 5 * CLOCK_FREQ );
} }
M3U8::~M3U8() M3U8::~M3U8()
......
...@@ -186,8 +186,8 @@ void Parser::parseSegments(Representation *rep, const std::list<Tag *> &tagslist ...@@ -186,8 +186,8 @@ void Parser::parseSegments(Representation *rep, const std::list<Tag *> &tagslist
rep->timescale.Set(100); rep->timescale.Set(100);
int64_t totalduration = 0; stime_t totalduration = 0;
int64_t nzStartTime = 0; stime_t nzStartTime = 0;
uint64_t sequenceNumber = 0; uint64_t sequenceNumber = 0;
std::size_t prevbyterangeoffset = 0; std::size_t prevbyterangeoffset = 0;
const SingleValueTag *ctx_byterange = NULL; const SingleValueTag *ctx_byterange = NULL;
...@@ -298,9 +298,9 @@ void Parser::parseSegments(Representation *rep, const std::list<Tag *> &tagslist ...@@ -298,9 +298,9 @@ void Parser::parseSegments(Representation *rep, const std::list<Tag *> &tagslist
{ {
rep->getPlaylist()->duration.Set(0); rep->getPlaylist()->duration.Set(0);
} }
else if(totalduration > rep->getPlaylist()->duration.Get()) else if(totalduration * CLOCK_FREQ / rep->timescale.Get() > rep->getPlaylist()->duration.Get())
{ {
rep->getPlaylist()->duration.Set(CLOCK_FREQ * totalduration / rep->timescale.Get()); rep->getPlaylist()->duration.Set(totalduration * CLOCK_FREQ / rep->timescale.Get());
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment