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

stream_filter: dash: add support for templates/live profile

parent 070ce589
......@@ -56,20 +56,31 @@ Chunk* AbstractAdaptationLogic::getNextChunk(Streams::Type type)
return NULL;
std::vector<ISegment *> segments = rep->getSegments();
if ( count == segments.size() )
ISegment *first = segments.empty() ? NULL : segments.front();
bool b_templated = (first && !first->isSingleShot());
if (count == segments.size() && !b_templated)
{
currentPeriod = mpd->getNextPeriod(currentPeriod);
count = 0;
return getNextChunk(type);
}
ISegment *seg = NULL;
if ( segments.size() > count )
{
ISegment *seg = segments.at( count );
Chunk *chunk = seg->toChunk();
//In case of UrlTemplate, we must stay on the same segment.
if ( seg->isSingleShot() == true )
count++;
seg = segments.at( count );
}
else if(b_templated)
{
seg = segments.back();
}
if(seg)
{
Chunk *chunk = seg->toChunk(count, rep);
count++;
seg->done();
return chunk;
}
......
......@@ -31,6 +31,7 @@
#include <vlc_common.h>
#include <vlc_arrays.h>
#include "SegmentTemplate.h"
#include "SegmentInfoDefault.h"
#include "Period.h"
......@@ -40,7 +41,9 @@ AdaptationSet::AdaptationSet(Period *period) :
ICanonicalUrl( period ),
subsegmentAlignmentFlag( false ),
segmentInfoDefault( NULL ),
isBitstreamSwitching( false )
isBitstreamSwitching( false ),
mediaTemplate( NULL ),
initTemplate( NULL )
{
}
......@@ -48,6 +51,8 @@ AdaptationSet::~AdaptationSet ()
{
delete this->segmentInfoDefault;
vlc_delete_all( this->representations );
delete mediaTemplate;
delete initTemplate;
}
const std::string& AdaptationSet::getMimeType() const
......@@ -103,6 +108,24 @@ void AdaptationSet::addRepresentation (Represe
this->representations.push_back(rep);
}
void AdaptationSet::setTemplates(SegmentTemplate *media, SegmentTemplate *init)
{
mediaTemplate = media;
initTemplate = init;
}
std::vector<SegmentTemplate *> AdaptationSet::getTemplates() const
{
std::vector<SegmentTemplate *> ret;
if(mediaTemplate)
{
if(initTemplate)
ret.push_back(initTemplate);
ret.push_back(mediaTemplate);
}
return ret;
}
void AdaptationSet::setBitstreamSwitching (bool value)
{
this->isBitstreamSwitching = value;
......
......@@ -39,6 +39,7 @@ namespace dash
{
class SegmentInfoDefault;
class Period;
class SegmentTemplate;
class AdaptationSet : public CommonAttributesElements, public ICanonicalUrl
{
......@@ -54,6 +55,8 @@ namespace dash
const SegmentInfoDefault* getSegmentInfoDefault() const;
void setSegmentInfoDefault( const SegmentInfoDefault* seg );
void setBitstreamSwitching(bool value);
void setTemplates( SegmentTemplate *, SegmentTemplate * = NULL );
std::vector<SegmentTemplate *> getTemplates() const;
bool getBitstreamSwitching() const;
void addRepresentation( Representation *rep );
virtual Url getUrlSegment() const; /* reimpl */
......@@ -63,6 +66,8 @@ namespace dash
std::vector<Representation *> representations;
const SegmentInfoDefault* segmentInfoDefault;
bool isBitstreamSwitching;
SegmentTemplate * mediaTemplate;
SegmentTemplate * initTemplate;
};
}
}
......
......@@ -265,7 +265,6 @@ void BasicCMParser::setRepresentations (Node *root, AdaptationSet *group)
const std::map<std::string, std::string> attributes = representations.at(i)->getAttributes();
Representation *rep = new Representation(group, getMPD());
rep->setParentGroup( group );
this->currentRepresentation = rep;
if ( this->parseCommonAttributesElements( representations.at( i ), rep, group ) == false )
{
......@@ -366,7 +365,7 @@ Segment* BasicCMParser::parseSegment( Node* node, bool init )
msg_Err( p_stream, "Failed to substitute URLTemplate identifier." );
return NULL;
}
seg = new SegmentTemplate( runtimeToken, this->currentRepresentation );
seg = new SegmentTemplate( currentRepresentation );
}
else
{
......
......@@ -27,10 +27,13 @@
#endif
#include "IsoffMainParser.h"
#include "SegmentTemplate.h"
#include "SegmentInfoDefault.h"
#include "xml/DOMHelper.h"
#include <vlc_strings.h>
#include <vlc_stream.h>
#include <cstdio>
#include <sstream>
using namespace dash::mpd;
using namespace dash::xml;
......@@ -72,6 +75,45 @@ void IsoffMainParser::setMPDAttributes ()
mpd->setType(it->second);
}
void IsoffMainParser::parseTemplate(Node *templateNode, AdaptationSet *set)
{
if (templateNode == NULL || !templateNode->hasAttribute("media"))
return;
std::string mediaurl = templateNode->getAttributeValue("media");
SegmentTemplate *mediaTemplate = NULL;
if(mediaurl.empty() || !(mediaTemplate = new (std::nothrow) SegmentTemplate(set)) )
return;
mediaTemplate->setSourceUrl(mediaurl);
if(templateNode->hasAttribute("startNumber"))
{
std::istringstream in(templateNode->getAttributeValue("startNumber"));
size_t i;
in >> i;
mediaTemplate->setStartIndex(i);
}
if(templateNode->hasAttribute("duration"))
{
std::istringstream in(templateNode->getAttributeValue("duration"));
size_t i;
in >> i;
mediaTemplate->setDuration(i);
}
InitSegmentTemplate *initTemplate = NULL;
if(templateNode->hasAttribute("initialization"))
{
std::string initurl = templateNode->getAttributeValue("initialization");
if(!initurl.empty() && (initTemplate = new (std::nothrow) InitSegmentTemplate(set)))
initTemplate->setSourceUrl(initurl);
}
set->setTemplates(mediaTemplate, initTemplate);
}
void IsoffMainParser::setAdaptationSets (Node *periodNode, Period *period)
{
std::vector<Node *> adaptationSets = DOMHelper::getElementByTagName(periodNode, "AdaptationSet", false);
......@@ -84,6 +126,9 @@ void IsoffMainParser::setAdaptationSets (Node *periodNode, Period *period)
continue;
if((*it)->hasAttribute("mimeType"))
adaptationSet->setMimeType((*it)->getAttributeValue("mimeType"));
parseTemplate(DOMHelper::getFirstChildElementByName( *it, "SegmentTemplate" ), adaptationSet);
setRepresentations((*it), adaptationSet);
period->addAdaptationSet(adaptationSet);
}
......@@ -122,7 +167,7 @@ void IsoffMainParser::setRepresentations (Node *adaptationSetNode, Adaptation
setSegmentBase(segmentBase, currentRepresentation);
setSegmentList(segmentList, currentRepresentation);
if(segmentBase.empty() && segmentList.empty())
if(segmentBase.empty() && segmentList.empty() && adaptationSet->getTemplates().empty())
{
/* unranged & segment less representation, add fake segment */
SegmentList *list = new SegmentList();
......
......@@ -57,6 +57,7 @@ namespace dash
void setSegmentList (std::vector<xml::Node *> &, Representation *rep);
void setInitSegment (dash::xml::Node *segBaseNode, SegmentBase *base);
void setSegments (dash::xml::Node *segListNode, SegmentList *list);
void parseTemplate (dash::xml::Node *templateNode, AdaptationSet *);
};
}
}
......
......@@ -42,6 +42,7 @@ MPD* MPDFactory::create (dash::xml::Node *root, stream_t *p_stream,
break;
case Profile::ISOOnDemand:
case Profile::ISOMain:
case Profile::ISOLive:
parser = new IsoffMainParser(root, p_stream);
default:
break;
......
......@@ -30,17 +30,18 @@
#include "Representation.h"
#include "mpd/AdaptationSet.h"
#include "mpd/MPD.h"
#include "mpd/SegmentTemplate.h"
using namespace dash::mpd;
Representation::Representation ( AdaptationSet *set, MPD *mpd_ ) :
ICanonicalUrl ( set ),
mpd ( mpd_ ),
adaptationSet ( set ),
bandwidth (0),
qualityRanking ( -1 ),
segmentInfo ( NULL ),
trickModeType ( NULL ),
parentGroup ( NULL ),
segmentBase ( NULL ),
segmentList ( NULL ),
baseUrl ( NULL ),
......@@ -94,17 +95,6 @@ void Representation::setTrickMode (TrickModeType *trickMod
this->trickModeType = trickModeType;
}
const AdaptationSet *Representation::getParentGroup() const
{
return this->parentGroup;
}
void Representation::setParentGroup(const AdaptationSet *group)
{
if ( group != NULL )
this->parentGroup = group;
}
void Representation::setSegmentInfo (SegmentInfo *info)
{
this->segmentInfo = info;
......@@ -171,6 +161,12 @@ std::vector<ISegment *> Representation::getSegments() const
}
}
if(retSegments.empty())
{
std::vector<SegmentTemplate *> list = adaptationSet->getTemplates();
retSegments.insert( retSegments.end(), list.begin(), list.end() );
}
return retSegments;
}
......
......@@ -73,8 +73,6 @@ namespace dash
void setSegmentInfo( SegmentInfo *info );
void setTrickMode( TrickModeType *trickModeType );
const AdaptationSet* getParentGroup() const;
void setParentGroup( const AdaptationSet *group );
std::vector<ISegment*> getSegments ()const;
void setSegmentList (SegmentList *list);
......@@ -99,13 +97,13 @@ namespace dash
private:
MPD *mpd;
AdaptationSet *adaptationSet;
uint64_t bandwidth;
std::string id;
int qualityRanking;
std::list<const Representation*> dependencies;
SegmentInfo *segmentInfo;
TrickModeType *trickModeType;
const AdaptationSet *parentGroup;
SegmentBase *segmentBase;
SegmentList *segmentList;
BaseUrl *baseUrl;
......
......@@ -53,12 +53,12 @@ dash::http::Chunk * ISegment::getChunk(const std::string &url)
return new (std::nothrow) SegmentChunk(this, url);
}
dash::http::Chunk* ISegment::toChunk()
dash::http::Chunk* ISegment::toChunk(size_t index, const Representation *ctxrep)
{
Chunk *chunk;
try
{
chunk = getChunk(getUrlSegment());
chunk = getChunk(getUrlSegment().toString(index, ctxrep));
if (!chunk)
return NULL;
}
......@@ -149,12 +149,19 @@ void ISegment::SegmentChunk::onDownload(void *, size_t)
}
Segment::Segment(ICanonicalUrl *parent) :
ISegment(parent),
parentRepresentation( NULL )
{
size = -1;
classId = CLASSID_SEGMENT;
}
Segment::Segment(Representation *parent) :
ISegment(parent),
parentRepresentation( parent )
{
assert( parent != NULL );
if ( parent->getSegmentInfo() != NULL && parent->getSegmentInfo()->getDuration() >= 0 )
if ( parent && parent->getSegmentInfo() != NULL && parent->getSegmentInfo()->getDuration() >= 0 )
this->size = parent->getBandwidth() * parent->getSegmentInfo()->getDuration();
else
this->size = -1;
......@@ -203,18 +210,18 @@ std::string Segment::toString() const
}
}
std::string Segment::getUrlSegment() const
Url Segment::getUrlSegment() const
{
std::string ret = getParentUrlSegment();
Url ret = getParentUrlSegment();
if (!sourceUrl.empty())
ret.append(sourceUrl);
return ret;
}
dash::http::Chunk* Segment::toChunk()
dash::http::Chunk* Segment::toChunk(size_t index, const Representation *ctxrep)
{
Chunk *chunk = ISegment::toChunk();
if (chunk)
Chunk *chunk = ISegment::toChunk(index, ctxrep);
if (chunk && parentRepresentation)
chunk->setBitrate(parentRepresentation->getBandwidth());
return chunk;
}
......
......@@ -51,7 +51,7 @@ namespace dash
*/
virtual bool isSingleShot () const;
virtual void done ();
virtual dash::http::Chunk* toChunk ();
virtual dash::http::Chunk* toChunk (size_t, const Representation * = NULL);
virtual void setByteRange (size_t start, size_t end);
virtual void setStartTime (mtime_t ztime);
virtual mtime_t getStartTime () const;
......@@ -95,7 +95,7 @@ namespace dash
~Segment();
virtual void setSourceUrl( const std::string &url );
virtual Url getUrlSegment() const; /* impl */
virtual dash::http::Chunk* toChunk();
virtual dash::http::Chunk* toChunk(size_t, const Representation * = NULL);
virtual std::vector<ISegment*> subSegments();
virtual Representation* getRepresentation() const;
virtual std::string toString() const;
......
......@@ -32,43 +32,32 @@
using namespace dash::mpd;
SegmentTemplate::SegmentTemplate( bool containRuntimeIdentifier,
Representation* representation ) :
Segment( representation ),
containRuntimeIdentifier( containRuntimeIdentifier ),
currentSegmentIndex( 0 )
SegmentTemplate::SegmentTemplate( ICanonicalUrl *parent ) :
Segment( parent ),
startIndex( 0 )
{
debugName = "SegmentTemplate";
classId = Segment::CLASSID_SEGMENT;
}
std::string SegmentTemplate::getUrlSegment() const
Url SegmentTemplate::getUrlSegment() const
{
std::string res = Segment::getUrlSegment();
if ( !containRuntimeIdentifier )
return res;
size_t beginTime = res.find( "$Time$" );
// size_t beginIndex = res.find( "$Index$" );
if ( beginTime != std::string::npos )
Url ret = getParentUrlSegment();
if (!sourceUrl.empty())
{
//FIXME: This should use the current representation SegmentInfo
//which "inherits" the SegmentInfoDefault values.
if ( parentRepresentation->getParentGroup()->getSegmentInfoDefault() != NULL &&
parentRepresentation->getParentGroup()->getSegmentInfoDefault()->getSegmentTimeline() != NULL )
{
const SegmentTimeline::Element *el = parentRepresentation->getParentGroup()->
getSegmentInfoDefault()->getSegmentTimeline()->getElement( currentSegmentIndex );
if ( el != NULL )
{
std::ostringstream oss;
oss << el->t;
res.replace( beginTime, strlen("$Time$"), oss.str() );
}
}
ret.append(Url::Component(sourceUrl, this));
}
return ret;
}
return res;
size_t SegmentTemplate::getStartIndex() const
{
return startIndex;
}
void SegmentTemplate::setStartIndex(size_t i)
{
startIndex = i;
}
bool SegmentTemplate::isSingleShot() const
......@@ -76,8 +65,9 @@ bool SegmentTemplate::isSingleShot() const
return false;
}
void SegmentTemplate::done()
InitSegmentTemplate::InitSegmentTemplate( ICanonicalUrl *parent ) :
SegmentTemplate(parent)
{
this->currentSegmentIndex++;
debugName = "InitSegmentTemplate";
classId = InitSegment::CLASSID_INITSEGMENT;
}
......@@ -30,18 +30,25 @@ namespace dash
{
namespace mpd
{
class Representation;
class ICanonicalUrl;
class SegmentTemplate : public Segment
{
public:
SegmentTemplate( bool containRuntimeIdentifier, Representation *rep );
virtual std::string getUrlSegment() const; /* reimpl */
SegmentTemplate( ICanonicalUrl * = NULL );
virtual Url getUrlSegment() const; /* reimpl */
virtual bool isSingleShot() const;
virtual void done();
size_t getStartIndex() const;
void setStartIndex(size_t);
private:
bool containRuntimeIdentifier;
int currentSegmentIndex;
size_t startIndex;
};
class InitSegmentTemplate : public SegmentTemplate
{
public:
InitSegmentTemplate( ICanonicalUrl * = NULL );
};
}
}
......
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