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

demux: adaptive: use scaled time helper

avoids overflows
parent 13b50747
......@@ -20,8 +20,37 @@
#ifndef TIME_HPP
#define TIME_HPP
#include <vlc_common.h>
/* Scaled time */
typedef int64_t stime_t;
class Timescale
{
public:
Timescale(uint64_t v = 0) : scale(v) {}
mtime_t ToTime(stime_t t) const
{
if( !scale ) return 0;
stime_t v = t / scale;
stime_t r = t % scale;
return v * 1000000 + r * 1000000 / scale;
}
stime_t ToScaled(mtime_t t) const
{
mtime_t v = t / 1000000;
mtime_t r = t % 1000000;
return v * scale + r * scale / 1000000;
}
bool isValid() const { return !!scale; }
operator uint64_t() const { return scale; }
private:
uint64_t scale;
};
#endif // TIME_HPP
......@@ -110,9 +110,9 @@ mtime_t BaseRepresentation::getMinAheadTime(uint64_t curnum) const
const MediaSegmentTemplate *templ = dynamic_cast<MediaSegmentTemplate *>(seglist.front());
if(templ)
{
const uint64_t timescale = templ->inheritTimescale();
const Timescale timescale = templ->inheritTimescale();
stime_t i_length = templ->getMinAheadScaledTime(curnum);
return i_length * CLOCK_FREQ / timescale;
return timescale.ToTime(i_length);
}
/* should not happen */
......@@ -120,12 +120,13 @@ mtime_t BaseRepresentation::getMinAheadTime(uint64_t curnum) const
}
mtime_t minTime = 0;
const Timescale timescale = inheritTimescale();
std::vector<ISegment *>::const_iterator it;
for(it = seglist.begin(); it != seglist.end(); ++it)
{
const ISegment *seg = *it;
if(seg->getSequenceNumber() > curnum)
minTime += seg->duration.Get() * CLOCK_FREQ / inheritTimescale();
minTime += timescale.ToTime(seg->duration.Get());
}
return minTime;
......
......@@ -39,27 +39,41 @@ Timelineable::~Timelineable()
TimescaleAble::TimescaleAble(TimescaleAble *parent)
{
timescale.Set(0);
parentTimescale = parent;
parentTimescaleAble = parent;
}
TimescaleAble::~TimescaleAble()
{
}
void TimescaleAble::setParentTimescale(TimescaleAble *parent)
void TimescaleAble::setParentTimescaleAble(TimescaleAble *parent)
{
parentTimescale = parent;
parentTimescaleAble = parent;
}
uint64_t TimescaleAble::inheritTimescale() const
Timescale TimescaleAble::inheritTimescale() const
{
if(timescale.Get())
return timescale.Get();
else if(parentTimescale)
return parentTimescale->inheritTimescale();
if(timescale.isValid())
return timescale;
else if(parentTimescaleAble)
return parentTimescaleAble->inheritTimescale();
else
return 1;
return Timescale(1);
}
void TimescaleAble::setTimescale(const Timescale & t)
{
timescale = t;
}
void TimescaleAble::setTimescale(uint64_t t)
{
timescale = Timescale(t);
}
const Timescale & TimescaleAble::getTimescale() const
{
return timescale;
}
const ID & Unique::getID() const
......
......@@ -24,6 +24,7 @@
#include <string>
#include <stdint.h>
#include "ID.hpp"
#include "../Time.hpp"
namespace adaptive
{
......@@ -44,12 +45,17 @@ namespace adaptive
public:
TimescaleAble( TimescaleAble * = NULL );
~TimescaleAble();
void setParentTimescale( TimescaleAble * );
uint64_t inheritTimescale() const;
Property<uint64_t> timescale;
void setParentTimescaleAble( TimescaleAble * );
Timescale inheritTimescale() const;
void setTimescale( const Timescale & );
void setTimescale( uint64_t );
const Timescale & getTimescale() const;
protected:
TimescaleAble *parentTimescale;
TimescaleAble *parentTimescaleAble;
private:
Timescale timescale;
};
class Unique
......
......@@ -290,34 +290,34 @@ bool SegmentInformation::getSegmentNumberByTime(mtime_t time, uint64_t *ret) con
{
if( mediaSegmentTemplate )
{
const uint64_t timescale = mediaSegmentTemplate->inheritTimescale();
const Timescale timescale = mediaSegmentTemplate->inheritTimescale();
SegmentTimeline *timeline = mediaSegmentTemplate->segmentTimeline.Get();
if(timeline)
{
time = time * timescale / CLOCK_FREQ;
time = timescale.ToScaled(time);
*ret = timeline->getElementNumberByScaledPlaybackTime(time);
return true;
}
const mtime_t duration = mediaSegmentTemplate->duration.Get();
const stime_t duration = mediaSegmentTemplate->duration.Get();
*ret = mediaSegmentTemplate->startNumber.Get();
if(duration)
{
*ret += time / (CLOCK_FREQ * duration / timescale);
*ret += timescale.ToScaled(time) / duration;
return true;
}
}
else if ( segmentList && !segmentList->getSegments().empty() )
{
const uint64_t timescale = segmentList->inheritTimescale();
time = time * timescale / CLOCK_FREQ;
const Timescale timescale = segmentList->inheritTimescale();
time = timescale.ToScaled(time);
return segmentList->getSegmentNumberByScaledTime(time, ret);
}
else if( segmentBase )
{
const uint64_t timescale = inheritTimescale();
time = time * timescale / CLOCK_FREQ;
const Timescale timescale = inheritTimescale();
time = timescale.ToScaled(time);
*ret = 0;
const std::vector<ISegment *> list = segmentBase->subSegments();
return SegmentInfoCommon::getSegmentNumberByScaledTime(list, time, ret);
......@@ -337,7 +337,8 @@ bool SegmentInformation::getPlaybackTimeDurationBySegmentNumber(uint64_t number,
if( (mediaTemplate = inheritSegmentTemplate()) )
{
uint64_t timescale = mediaTemplate->inheritTimescale();
const Timescale timescale = mediaTemplate->inheritTimescale();
stime_t stime, sduration;
if(mediaTemplate->segmentTimeline.Get())
{
......@@ -349,8 +350,8 @@ bool SegmentInformation::getPlaybackTimeDurationBySegmentNumber(uint64_t number,
stime = number * mediaTemplate->duration.Get();
sduration = mediaTemplate->duration.Get();
}
*time = CLOCK_FREQ * stime / timescale;
*duration = CLOCK_FREQ * sduration / timescale;
*time = timescale.ToTime(stime);
*duration = timescale.ToTime(sduration);
return true;
}
else if ( (segList = inheritSegmentList()) )
......@@ -359,12 +360,12 @@ bool SegmentInformation::getPlaybackTimeDurationBySegmentNumber(uint64_t number,
}
else
{
const uint64_t timescale = inheritTimescale();
const Timescale timescale = inheritTimescale();
const ISegment *segment = getSegment(SegmentInfoType::INFOTYPE_MEDIA, number);
if( segment )
{
*time = segment->startTime.Get() * CLOCK_FREQ / timescale;
*duration = segment->duration.Get() * CLOCK_FREQ / timescale;
*time = timescale.ToTime(segment->startTime.Get());
*duration = timescale.ToTime(segment->duration.Get());
return true;
}
}
......@@ -518,7 +519,7 @@ void SegmentInformation::SplitUsingIndex(std::vector<SplitPoint> &splitlist)
getSegments(INFOTYPE_MEDIA, seglist);
size_t prevstart = 0;
stime_t prevtime = 0;
const uint64_t i_timescale = inheritTimescale();
const Timescale timescale = inheritTimescale();
SplitPoint split = {0,0,0};
std::vector<SplitPoint>::const_iterator splitIt;
......@@ -528,21 +529,21 @@ void SegmentInformation::SplitUsingIndex(std::vector<SplitPoint> &splitlist)
if(splitIt != splitlist.begin())
{
/* do previous splitpoint */
const stime_t duration = (split.duration * i_timescale / CLOCK_FREQ);
const stime_t duration = timescale.ToScaled(split.duration);
insertIntoSegment(seglist, prevstart, split.offset - 1, prevtime, duration);
}
prevstart = split.offset;
prevtime = split.time * i_timescale / CLOCK_FREQ;
prevtime = timescale.ToScaled(split.time);
}
if(splitlist.size() == 1)
{
const stime_t duration = (split.duration * i_timescale / CLOCK_FREQ);
const stime_t duration = timescale.ToScaled(split.duration);
insertIntoSegment(seglist, prevstart, 0, prevtime, duration);
}
else if(splitlist.size() > 1)
{
const stime_t duration = (split.duration * i_timescale / CLOCK_FREQ);
const stime_t duration = timescale.ToScaled(split.duration);
insertIntoSegment(seglist, prevstart, split.offset - 1, prevtime, duration);
}
}
......
......@@ -89,8 +89,8 @@ void SegmentList::mergeWith(SegmentList *updated)
void SegmentList::pruneByPlaybackTime(mtime_t time)
{
uint64_t num;
const uint64_t timescale = inheritTimescale();
if(getSegmentNumberByScaledTime(time * timescale / CLOCK_FREQ, &num))
const Timescale timescale = inheritTimescale();
if(getSegmentNumberByScaledTime(timescale.ToScaled(time), &num))
pruneBySegmentNumber(num);
}
......@@ -133,7 +133,7 @@ bool SegmentList::getPlaybackTimeDurationBySegmentNumber(uint64_t number,
if(segments.empty())
return false;
const uint64_t timescale = inheritTimescale();
const Timescale timescale = inheritTimescale();
const ISegment *first = segments.front();
if(first->getSequenceNumber() > number)
return false;
......@@ -160,7 +160,7 @@ bool SegmentList::getPlaybackTimeDurationBySegmentNumber(uint64_t number,
}
}
*time = VLC_TS_0 + CLOCK_FREQ * *time / timescale;
*dur = VLC_TS_0 + CLOCK_FREQ * *dur / timescale;
*time = VLC_TS_0 + timescale.ToTime( *time );
*dur = VLC_TS_0 + timescale.ToTime( *dur );
return true;
}
......@@ -54,9 +54,9 @@ void MediaSegmentTemplate::mergeWith(MediaSegmentTemplate *updated, mtime_t prun
timeline->mergeWith(*updated->segmentTimeline.Get());
if(prunebarrier)
{
const uint64_t timescale = timeline->inheritTimescale();
const Timescale timescale = timeline->inheritTimescale();
const uint64_t number =
timeline->getElementNumberByScaledPlaybackTime(prunebarrier * timescale / CLOCK_FREQ);
timeline->getElementNumberByScaledPlaybackTime(timescale.ToScaled(prunebarrier));
timeline->pruneBySequenceNumber(number);
}
}
......
......@@ -38,7 +38,7 @@ SegmentTimeline::SegmentTimeline(TimescaleAble *parent)
SegmentTimeline::SegmentTimeline(uint64_t scale)
:TimescaleAble(NULL)
{
timescale.Set(scale);
setTimescale(scale);
}
SegmentTimeline::~SegmentTimeline()
......@@ -173,8 +173,8 @@ uint64_t SegmentTimeline::minElementNumber() const
void SegmentTimeline::pruneByPlaybackTime(mtime_t time)
{
const uint64_t timescale = inheritTimescale();
uint64_t num = getElementNumberByScaledPlaybackTime(time * timescale / CLOCK_FREQ);
const Timescale timescale = inheritTimescale();
uint64_t num = getElementNumberByScaledPlaybackTime(timescale.ToScaled(time));
pruneBySequenceNumber(num);
}
......@@ -249,7 +249,7 @@ mtime_t SegmentTimeline::start() const
{
if(elements.empty())
return 0;
return elements.front()->t * CLOCK_FREQ / inheritTimescale();
return inheritTimescale().ToTime(elements.front()->t);
}
mtime_t SegmentTimeline::end() const
......@@ -258,7 +258,7 @@ mtime_t SegmentTimeline::end() const
return 0;
const Element *last = elements.back();
stime_t scaled = last->t + last->d * (last->r + 1);
return scaled * CLOCK_FREQ / inheritTimescale();
return inheritTimescale().ToTime(scaled);
}
void SegmentTimeline::debug(vlc_object_t *obj, int indent) const
......
......@@ -167,7 +167,7 @@ size_t IsoffMainParser::parseSegmentTemplate(Node *templateNode, SegmentInformat
mediaTemplate->startNumber.Set(Integer<uint64_t>(templateNode->getAttributeValue("startNumber")));
if(templateNode->hasAttribute("timescale"))
mediaTemplate->timescale.Set(Integer<uint64_t>(templateNode->getAttributeValue("timescale")));
mediaTemplate->setTimescale(Integer<uint64_t>(templateNode->getAttributeValue("timescale")));
if(templateNode->hasAttribute("duration"))
mediaTemplate->duration.Set(Integer<stime_t>(templateNode->getAttributeValue("duration")));
......@@ -207,7 +207,7 @@ size_t IsoffMainParser::parseSegmentInformation(Node *node, SegmentInformation *
info->setSwitchPolicy(SegmentInformation::SWITCH_UNAVAILABLE);
}
if(node->hasAttribute("timescale"))
info->timescale.Set(Integer<uint64_t>(node->getAttributeValue("timescale")));
info->setTimescale(Integer<uint64_t>(node->getAttributeValue("timescale")));
if(node->hasAttribute("id"))
info->setID(node->getAttributeValue("id"));
......@@ -373,7 +373,7 @@ size_t IsoffMainParser::parseSegmentList(Node * segListNode, SegmentInformation
list->duration.Set(Integer<stime_t>(segListNode->getAttributeValue("duration")));
if(segListNode->hasAttribute("timescale"))
list->timescale.Set(Integer<uint64_t>(segListNode->getAttributeValue("timescale")));
list->setTimescale(Integer<uint64_t>(segListNode->getAttributeValue("timescale")));
uint64_t nzStartTime = 0;
std::vector<Node *>::const_iterator it;
......
......@@ -190,9 +190,9 @@ uint64_t Representation::getLiveTemplateNumberOffset(uint64_t index, const Media
time_t streamstart = getPlaylist()->availabilityStartTime.Get();
streamstart += getPeriodStart();
const stime_t duration = templ->duration.Get();
const uint64_t timescale = templ->inheritTimescale();
if(duration && timescale)
index += (playbackstart - streamstart) * timescale / duration;
const Timescale timescale = templ->inheritTimescale();
if(duration)
index += timescale.ToScaled(CLOCK_FREQ * (playbackstart - streamstart)) / duration;
}
}
return index;
......
......@@ -210,7 +210,7 @@ void M3U8Parser::parseSegments(vlc_object_t *p_obj, Representation *rep, const s
{
SegmentList *segmentList = new (std::nothrow) SegmentList(rep);
rep->timescale.Set(100);
rep->setTimescale(100);
rep->b_loaded = true;
mtime_t totalduration = 0;
......@@ -265,8 +265,8 @@ void M3U8Parser::parseSegments(vlc_object_t *p_obj, Representation *rep, const s
if(ctx_extinf->getAttributeByName("DURATION"))
{
const mtime_t nzDuration = CLOCK_FREQ * ctx_extinf->getAttributeByName("DURATION")->floatingPoint();
segment->duration.Set(ctx_extinf->getAttributeByName("DURATION")->floatingPoint() * rep->timescale.Get());
segment->startTime.Set(nzStartTime * rep->timescale.Get() / CLOCK_FREQ);
segment->duration.Set(ctx_extinf->getAttributeByName("DURATION")->floatingPoint() * (uint64_t) rep->getTimescale());
segment->startTime.Set(rep->getTimescale().ToScaled(nzStartTime));
nzStartTime += nzDuration;
totalduration += nzDuration;
......
......@@ -49,7 +49,7 @@ ForgedInitSegment::ForgedInitSegment(ICanonicalUrl *parent,
duration.Set(duration_);
extradata = NULL;
i_extradata = 0;
timescale.Set(timescale_);
setTimescale(timescale_);
formatex.cbSize = 0;
formatex.nAvgBytesPerSec = 0;
formatex.nBlockAlign = 0;
......@@ -210,7 +210,7 @@ block_t * ForgedInitSegment::buildMoovBox()
mp4mux_trackinfo_Init(&trackinfo);
trackinfo.i_track_id = 0x01; /* Will always be 1st and unique track; tfhd patched on block read */
trackinfo.i_timescale = timescale.Get();
trackinfo.i_timescale = inheritTimescale();
trackinfo.i_read_duration = duration.Get();
trackinfo.i_trex_default_length = 1;
trackinfo.i_trex_default_size = 1;
......
......@@ -29,10 +29,10 @@
using namespace smooth::playlist;
Manifest::Manifest (vlc_object_t *p_object) :
AbstractPlaylist(p_object)
AbstractPlaylist(p_object), TimescaleAble()
{
minUpdatePeriod.Set( 5 * CLOCK_FREQ );
timescale.Set( 10000000 );
setTimescale( 10000000 );
b_live = false;
}
......
......@@ -21,6 +21,8 @@
#define MANIFEST_HPP
#include "../adaptive/playlist/AbstractPlaylist.hpp"
#include "../adaptive/playlist/Inheritables.hpp"
#include "../adaptive/Time.hpp"
namespace smooth
{
......@@ -28,7 +30,8 @@ namespace smooth
{
using namespace adaptive::playlist;
class Manifest : public AbstractPlaylist
class Manifest : public AbstractPlaylist,
public TimescaleAble
{
friend class ManifestParser;
......@@ -40,7 +43,6 @@ namespace smooth
virtual void debug();
private:
Property<uint64_t> timescale;
bool b_live;
};
}
......
......@@ -223,7 +223,7 @@ static void ParseStreamIndex(BasePeriod *period, Node *streamIndexNode, unsigned
adaptSet->addLang(streamIndexNode->getAttributeValue("Language"));
if(streamIndexNode->hasAttribute("TimeScale"))
adaptSet->timescale.Set(Integer<uint64_t>(streamIndexNode->getAttributeValue("TimeScale")));
adaptSet->setTimescale(Integer<uint64_t>(streamIndexNode->getAttributeValue("TimeScale")));
const std::string url = streamIndexNode->getAttributeValue("Url");
if(!url.empty())
......@@ -258,16 +258,12 @@ Manifest * ManifestParser::parse()
manifest->setPlaylistUrl(Helper::getDirectoryPath(playlisturl).append("/"));
if(root->hasAttribute("TimeScale"))
manifest->timescale.Set(Integer<uint64_t>(root->getAttributeValue("TimeScale")));
manifest->setTimescale(Integer<uint64_t>(root->getAttributeValue("TimeScale")));
if(root->hasAttribute("Duration"))
{
mtime_t time = Integer<mtime_t>(root->getAttributeValue("Duration"));
if(manifest->timescale.Get() > CLOCK_FREQ)
time /= (manifest->timescale.Get() / CLOCK_FREQ);
else
time = time * CLOCK_FREQ / manifest->timescale.Get();
manifest->duration.Set(time);
stime_t time = Integer<stime_t>(root->getAttributeValue("Duration"));
manifest->duration.Set(manifest->getTimescale().ToTime(time));
}
if(root->hasAttribute("IsLive") && root->getAttributeValue("IsLive") == "TRUE")
......@@ -277,7 +273,7 @@ Manifest * ManifestParser::parse()
BasePeriod *period = new (std::nothrow) BasePeriod(manifest);
if(period)
{
period->timescale.Set(manifest->timescale.Get());
period->setTimescale(manifest->getTimescale());
period->duration.Set(manifest->duration.Get());
unsigned nextid = 1;
std::vector<Node *> streamIndexes = DOMHelper::getElementByTagName(root, "StreamIndex", true);
......
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