Commit a03587d3 authored by Francois Cartegnie's avatar Francois Cartegnie

stream_filter: dash: add support for templates/live profile

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