Commit 2860a192 authored by François Cartegnie's avatar François Cartegnie 🤞

demux: dash: handle live stream numbered template

($Number$ must be calculated from streaming start time)
parent 6ee46f4b
......@@ -81,6 +81,8 @@ bool DASHManager::start(demux_t *demux)
if(!conManager)
return false;
mpd->playbackStart.Set(time(NULL));
return true;
}
......
......@@ -33,16 +33,21 @@ using namespace dash::http;
AbstractAdaptationLogic::AbstractAdaptationLogic (MPD *mpd_) :
mpd (mpd_),
currentPeriod (mpd->getFirstPeriod()),
count (0),
prevRepresentation (NULL)
currentPeriod (mpd->getFirstPeriod())
{
reset();
}
AbstractAdaptationLogic::~AbstractAdaptationLogic ()
{
}
void AbstractAdaptationLogic::reset()
{
count = 0;
prevRepresentation = NULL;
}
Chunk* AbstractAdaptationLogic::getNextChunk(Streams::Type type)
{
if(!currentPeriod)
......@@ -72,8 +77,7 @@ Chunk* AbstractAdaptationLogic::getNextChunk(Streams::Type type)
if (count == segments.size() && !b_templated)
{
currentPeriod = mpd->getNextPeriod(currentPeriod);
prevRepresentation = NULL;
count = 0;
reset();
return getNextChunk(type);
}
......
......@@ -42,6 +42,7 @@ namespace dash
public:
AbstractAdaptationLogic (mpd::MPD *mpd);
virtual ~AbstractAdaptationLogic ();
virtual void reset ();
virtual dash::http::Chunk* getNextChunk (Streams::Type);
......
......@@ -74,6 +74,14 @@ void IsoffMainParser::setMPDAttributes ()
it = attr.find("type");
if(it != attr.end())
mpd->setType(it->second);
it = attr.find("availabilityStartTime");
if(it != attr.end())
mpd->setAvailabilityStartTime(UTCTime(it->second));
it = attr.find("timeShiftBufferDepth");
if(it != attr.end())
mpd->setTimeShiftBufferDepth(IsoTime(it->second));
}
void IsoffMainParser::parsePeriods(Node *root)
......@@ -87,6 +95,8 @@ void IsoffMainParser::parsePeriods(Node *root)
if (!period)
continue;
parseSegmentInformation(*it, period);
if((*it)->hasAttribute("start"))
period->startTime.Set(IsoTime((*it)->getAttributeValue("start")));
setAdaptationSets(*it, period);
mpd->addPeriod(period);
}
......@@ -117,7 +127,15 @@ size_t IsoffMainParser::parseSegmentTemplate(Node *templateNode, SegmentInformat
std::istringstream in(templateNode->getAttributeValue("duration"));
size_t i;
in >> i;
mediaTemplate->setDuration(i);
mediaTemplate->duration.Set(i);
}
if(templateNode->hasAttribute("timescale"))
{
std::istringstream in(templateNode->getAttributeValue("timescale"));
size_t i;
in >> i;
mediaTemplate->timescale.Set(i);
}
InitSegmentTemplate *initTemplate = NULL;
......@@ -145,6 +163,13 @@ size_t IsoffMainParser::parseSegmentInformation(Node *node, SegmentInformation *
total += parseSegmentTemplate(DOMHelper::getFirstChildElementByName(node, "SegmentTemplate" ), info);
if(node->hasAttribute("bitstreamSwitching"))
info->setBitstreamSwitching(node->getAttributeValue("bitstreamSwitching") == "true");
if(node->hasAttribute("timescale"))
{
std::istringstream in(node->getAttributeValue("timescale"));
uint64_t i;
in >> i;
info->timescale.Set(i);
}
return total;
}
......@@ -356,3 +381,76 @@ IsoTime::operator mtime_t () const
{
return time;
}
/* i_year: year - 1900 i_month: 0-11 i_mday: 1-31 i_hour: 0-23 i_minute: 0-59 i_second: 0-59 */
static int64_t vlc_timegm( int i_year, int i_month, int i_mday, int i_hour, int i_minute, int i_second )
{
static const int pn_day[12+1] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
int64_t i_day;
if( i_year < 70 ||
i_month < 0 || i_month > 11 || i_mday < 1 || i_mday > 31 ||
i_hour < 0 || i_hour > 23 || i_minute < 0 || i_minute > 59 || i_second < 0 || i_second > 59 )
return -1;
/* Count the number of days */
i_day = 365 * (i_year-70) + pn_day[i_month] + i_mday - 1;
#define LEAP(y) ( ((y)%4) == 0 && (((y)%100) != 0 || ((y)%400) == 0) ? 1 : 0)
for( int i = 70; i < i_year; i++ )
i_day += LEAP(1900+i);
if( i_month > 1 )
i_day += LEAP(1900+i_year);
#undef LEAP
/**/
return ((24*i_day + i_hour)*60 + i_minute)*60 + i_second;
}
UTCTime::UTCTime(const std::string &str)
{
enum { YEAR = 0, MON, DAY, HOUR, MIN, SEC, TZ };
int values[7] = {0};
std::istringstream in(str);
try
{
/* Date */
for(int i=YEAR;i<=DAY && !in.eof();i++)
{
if(i!=YEAR)
in.ignore(1);
in >> values[i];
}
/* Time */
if (!in.eof() && in.peek() == 'T')
{
for(int i=HOUR;i<=SEC && !in.eof();i++)
{
in.ignore(1);
in >> values[i];
}
}
/* Timezone */
if (!in.eof() && in.peek() == 'Z')
{
in.ignore(1);
while(!in.eof())
{
if(in.peek() == '+')
continue;
in >> values[TZ];
break;
}
}
time = vlc_timegm( values[YEAR] - 1900, values[MON] - 1, values[DAY],
values[HOUR], values[MIN], values[SEC] );
time += values[TZ] * 3600;
} catch(int) {
time = 0;
}
}
UTCTime::operator mtime_t () const
{
return time;
}
......@@ -70,6 +70,16 @@ namespace dash
private:
mtime_t time;
};
class UTCTime
{
public:
UTCTime(const std::string&);
operator mtime_t() const;
private:
mtime_t time;
};
}
}
......
......@@ -37,14 +37,15 @@ MPD::MPD (stream_t *stream_, Profile profile_) :
ICanonicalUrl(),
stream(stream_),
profile( profile_ ),
availabilityStartTime( -1 ),
availabilityEndTime( -1 ),
duration( -1 ),
availabilityStartTime( 0 ),
availabilityEndTime( 0 ),
duration( 0 ),
minUpdatePeriod( -1 ),
minBufferTime( -1 ),
timeShiftBufferDepth( -1 ),
minBufferTime( 0 ),
timeShiftBufferDepth( 0 ),
programInfo( NULL )
{
playbackStart.Set(0);
}
MPD::~MPD ()
......
......@@ -34,6 +34,7 @@
#include "mpd/ICanonicalUrl.hpp"
#include "mpd/ProgramInformation.h"
#include "mpd/Profile.hpp"
#include "Properties.hpp"
namespace dash
{
......@@ -73,6 +74,8 @@ namespace dash
virtual Period* getFirstPeriod() const;
virtual Period* getNextPeriod(Period *period);
Property<time_t> playbackStart;
private:
stream_t *stream;
Profile profile;
......
......@@ -37,6 +37,8 @@ using namespace dash::mpd;
Period::Period(MPD *mpd) :
SegmentInformation( mpd )
{
duration.Set(0);
startTime.Set(0);
}
Period::~Period ()
......@@ -97,3 +99,8 @@ std::vector<std::string> Period::toString(int indent) const
}
return ret;
}
mtime_t Period::getPeriodStart() const
{
return startTime.Get();
}
......@@ -30,6 +30,7 @@
#include "mpd/AdaptationSet.h"
#include "mpd/ICanonicalUrl.hpp"
#include "mpd/SegmentInformation.hpp"
#include "Properties.hpp"
#include "Streams.hpp"
namespace dash
......@@ -51,6 +52,10 @@ namespace dash
std::vector<std::string> toString (int = 0) const;
virtual Url getUrlSegment() const; /* reimpl */
virtual mtime_t getPeriodStart() const; /* reimpl */
Property<mtime_t> duration;
Property<mtime_t> startTime;
private:
std::vector<AdaptationSet *> adaptationSets;
......
......@@ -40,12 +40,12 @@ using namespace dash::http;
ISegment::ISegment(const ICanonicalUrl *parent):
ICanonicalUrl( parent ),
startByte (0),
endByte (0),
startTime (VLC_TS_INVALID),
duration (0)
endByte (0)
{
debugName = "Segment";
classId = CLASSID_ISEGMENT;
startTime.Set(VLC_TS_INVALID);
duration.Set(0);
}
dash::http::Chunk * ISegment::getChunk(const std::string &url)
......@@ -91,26 +91,6 @@ void ISegment::setByteRange(size_t start, size_t end)
endByte = end;
}
void ISegment::setStartTime(mtime_t ztime)
{
startTime = ztime;
}
mtime_t ISegment::getStartTime() const
{
return startTime;
}
mtime_t ISegment::getDuration() const
{
return duration;
}
void ISegment::setDuration(mtime_t d)
{
duration = d;
}
size_t ISegment::getOffset() const
{
return startByte;
......
......@@ -31,6 +31,7 @@
#include "mpd/BaseUrl.h"
#include "mpd/ICanonicalUrl.hpp"
#include "http/Chunk.h"
#include "Properties.hpp"
namespace dash
{
......@@ -54,25 +55,21 @@ namespace dash
virtual void done ();
virtual dash::http::Chunk* toChunk (size_t, Representation * = NULL);
virtual void setByteRange (size_t start, size_t end);
virtual void setStartTime (mtime_t ztime);
virtual mtime_t getStartTime () const;
virtual mtime_t getDuration () const;
virtual void setDuration (mtime_t);
virtual size_t getOffset () const;
virtual std::vector<ISegment*> subSegments () = 0;
virtual std::string toString (int = 0) const;
virtual bool contains (size_t byte) const;
int getClassId () const;
Property<mtime_t> startTime;
Property<mtime_t> duration;
static const int CLASSID_ISEGMENT = 0;
protected:
size_t startByte;
size_t endByte;
mtime_t startTime;
std::string debugName;
int classId;
mtime_t duration;
class SegmentChunk : public dash::http::Chunk
{
......
......@@ -36,6 +36,7 @@ SegmentInformation::SegmentInformation(SegmentInformation *parent_) :
for(int i=0; i<InfoTypeCount; i++)
segmentTemplate[i] = NULL;
bitswitch_policy = BITSWITCH_INHERIT;
timescale.Set(0);
}
SegmentInformation::SegmentInformation(ICanonicalUrl * parent_) :
......@@ -47,6 +48,7 @@ SegmentInformation::SegmentInformation(ICanonicalUrl * parent_) :
for(int i=0; i<InfoTypeCount; i++)
segmentTemplate[i] = NULL;
bitswitch_policy = BITSWITCH_INHERIT;
timescale.Set(0);
}
SegmentInformation::~SegmentInformation()
......@@ -104,6 +106,24 @@ bool SegmentInformation::canBitswitch() const
return (bitswitch_policy == BITSWITCH_YES);
}
uint64_t SegmentInformation::getTimescale() const
{
if (timescale.Get())
return timescale.Get();
else if (parent)
return parent->getTimescale();
else
return 1;
}
mtime_t SegmentInformation::getPeriodStart() const
{
if(parent)
return parent->getPeriodStart();
else
return 0;
}
void SegmentInformation::setSegmentList(SegmentList *list)
{
segmentList = list;
......@@ -133,7 +153,7 @@ static void insertIntoSegment(std::vector<Segment *> &seglist, size_t start,
start + segment->getOffset(),
end + segment->getOffset());
segment->addSubSegment(subsegment);
segment->setStartTime(time);
segment->startTime.Set(time);
break;
}
}
......
......@@ -25,6 +25,7 @@
#endif
#include "ICanonicalUrl.hpp"
#include "Properties.hpp"
#include <vlc_common.h>
#include <vector>
......@@ -49,6 +50,8 @@ namespace dash
virtual ~SegmentInformation();
std::vector<ISegment *> getSegments() const;
bool canBitswitch() const;
uint64_t getTimescale() const;
virtual mtime_t getPeriodStart() const;
class SplitPoint
{
......@@ -87,6 +90,8 @@ namespace dash
BITSWITCH_YES,
BITSWITCH_NO
} bitswitch_policy;
Property<uint64_t> timescale;
};
}
}
......
......@@ -38,6 +38,8 @@ SegmentTemplate::SegmentTemplate( ICanonicalUrl *parent ) :
{
debugName = "SegmentTemplate";
classId = Segment::CLASSID_SEGMENT;
duration.Set(0);
timescale.Set(0);
}
Url SegmentTemplate::getUrlSegment() const
......
......@@ -25,6 +25,7 @@
#define SEGMENTTEMPLATE_H
#include "mpd/Segment.h"
#include "Properties.hpp"
namespace dash
{
......@@ -40,6 +41,8 @@ namespace dash
virtual bool isSingleShot() const;
size_t getStartIndex() const;
void setStartIndex(size_t);
Property<mtime_t> duration;
Property<uint64_t> timescale;
private:
size_t startIndex;
......
......@@ -20,6 +20,7 @@
#include "Url.hpp"
#include "Representation.h"
#include "SegmentTemplate.h"
#include "MPD.h"
#include <sstream>
using namespace dash::mpd;
......@@ -95,22 +96,28 @@ std::string Url::Component::contextualize(size_t index, const Representation *re
if(pos != std::string::npos)
{
std::stringstream ss;
ss << (templ->getDuration() * index);
ss << (templ->duration.Get() * index);
ret.replace(pos, std::string("$Time$").length(), ss.str());
}
pos = ret.find("$Index$");
if(pos != std::string::npos)
{
std::stringstream ss;
ss << index;
ret.replace(pos, std::string("$Index$").length(), ss.str());
}
pos = ret.find("$Number$");
if(pos != std::string::npos)
{
std::stringstream ss;
/* live streams / templated */
if(templ && rep->getMPD()->isLive() && templ->duration.Get())
{
mtime_t playbackstart = rep->getMPD()->playbackStart.Get();
mtime_t streamstart = rep->getMPD()->getAvailabilityStartTime();
streamstart += rep->getPeriodStart();
mtime_t duration = templ->duration.Get();
uint64_t timescale = templ->timescale.Get() ?
templ->timescale.Get() :
rep->getTimescale();
if(duration && timescale)
index += (playbackstart - streamstart) * timescale / duration;
}
ss << index;
ret.replace(pos, std::string("$Number$").length(), ss.str());
}
......
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