From a644414fd2c3a3f7f41e716b6875a78981e4cfe1 Mon Sep 17 00:00:00 2001 From: jacko Date: Fri, 23 Jun 2017 16:12:18 +0200 Subject: adding mpd live handling + automatic mpd fetching Change-Id: I2c05bdf6a4d940ad22bb8632268f4b63a08a80a8 Signed-off-by: jacko --- MPD/AbstractRepresentationStream.cpp | 32 +- MPD/AbstractRepresentationStream.h | 18 +- MPD/AdaptationSetStream.cpp | 111 ++-- MPD/AdaptationSetStream.h | 18 +- MPD/BaseUrlResolver.cpp | 13 +- MPD/BaseUrlResolver.h | 6 +- MPD/IMPDWrapper.h | 46 ++ MPD/IRepresentationStream.h | 3 + MPD/MPDWrapper.cpp | 1098 ++++++++++++++++++++++++++++++++++ MPD/MPDWrapper.h | 134 +++++ MPD/RepresentationStreamFactory.cpp | 26 +- MPD/RepresentationStreamFactory.h | 7 +- MPD/SegmentListStream.cpp | 22 +- MPD/SegmentListStream.h | 11 +- MPD/SegmentTemplateStream.cpp | 55 +- MPD/SegmentTemplateStream.h | 7 +- MPD/SingleMediaSegmentStream.cpp | 12 +- MPD/SingleMediaSegmentStream.h | 5 +- 18 files changed, 1510 insertions(+), 114 deletions(-) create mode 100644 MPD/IMPDWrapper.h create mode 100644 MPD/MPDWrapper.cpp create mode 100644 MPD/MPDWrapper.h (limited to 'MPD') diff --git a/MPD/AbstractRepresentationStream.cpp b/MPD/AbstractRepresentationStream.cpp index 346938f4..e02f65cb 100644 --- a/MPD/AbstractRepresentationStream.cpp +++ b/MPD/AbstractRepresentationStream.cpp @@ -14,8 +14,9 @@ using namespace libdash::framework::mpd; using namespace dash::mpd; -AbstractRepresentationStream::AbstractRepresentationStream(IMPD *mpd, IPeriod *period, IAdaptationSet *adaptationSet, IRepresentation *representation) : - mpd (mpd), +AbstractRepresentationStream::AbstractRepresentationStream(viper::managers::StreamType type, IMPDWrapper *mpdWrapper, IPeriod *period, IAdaptationSet *adaptationSet, IRepresentation *representation) : + type (type), + mpdWrapper (mpdWrapper), period (period), adaptationSet (adaptationSet), representation (representation) @@ -40,12 +41,12 @@ uint32_t AbstractRepresentationStream::getSize() uint32_t AbstractRepresentationStream::getFirstSegmentNumber() { - if (this->mpd->GetType() == "dynamic") + if (this->mpdWrapper->getTypeWithoutLock() == "dynamic") { uint32_t currTime = TimeResolver::getCurrentTimeInSec(); - uint32_t availStT = TimeResolver::getUTCDateTimeInSec(this->mpd->GetAvailabilityStarttime()); + uint32_t availStT = TimeResolver::getUTCDateTimeInSec(this->mpdWrapper->getAvailabilityStarttime()); uint32_t duration = this->getAverageSegmentDuration(); - uint32_t timeshift = TimeResolver::getDurationInSec(this->mpd->GetTimeShiftBufferDepth()); + uint32_t timeshift = TimeResolver::getDurationInSec(this->mpdWrapper->getTimeShiftBufferDepth()); uint32_t timescale = this->getTimescale(); return (double)((double)currTime - (double)availStT - (double)timeshift ) < 0? 0 : (currTime - availStT - timeshift ); } @@ -54,11 +55,11 @@ uint32_t AbstractRepresentationStream::getFirstSegmentNumber() uint32_t AbstractRepresentationStream::getCurrentSegmentNumber() { - if (this->mpd->GetType() == "dynamic") + if (this->mpdWrapper->getTypeWithoutLock() == "dynamic") { uint32_t currTime = TimeResolver::getCurrentTimeInSec(); uint32_t duration = this->getAverageSegmentDuration(); - uint32_t availStT = TimeResolver::getUTCDateTimeInSec(this->mpd->GetAvailabilityStarttime()); + uint32_t availStT = TimeResolver::getUTCDateTimeInSec(this->mpdWrapper->getAvailabilityStarttime()); return (double)((double)currTime - (double)availStT) < 0 ? 0 : (currTime - availStT); // return (currTime - duration - availStT) / duration; @@ -68,13 +69,13 @@ uint32_t AbstractRepresentationStream::getCurrentSegmentNumber() uint32_t AbstractRepresentationStream::getLastSegmentNumber () { - if (this->mpd->GetType() == "dynamic") + if (this->mpdWrapper->getTypeWithoutLock() == "dynamic") { uint32_t currTime = TimeResolver::getCurrentTimeInSec(); uint32_t duration = this->getAverageSegmentDuration(); - uint32_t availStT = TimeResolver::getUTCDateTimeInSec(this->mpd->GetAvailabilityStarttime()); - uint32_t checkTime = mpd->GetFetchTime() + - TimeResolver::getDurationInSec(this->mpd->GetMinimumUpdatePeriod()); + uint32_t availStT = TimeResolver::getUTCDateTimeInSec(this->mpdWrapper->getAvailabilityStarttime()); + uint32_t checkTime = mpdWrapper->getFetchTime() + + TimeResolver::getDurationInSec(this->mpdWrapper->getMinimumUpdatePeriodWithoutLock()); return ( ((checkTime > currTime) ? currTime : checkTime) - duration - availStT) / duration; } return 0; @@ -92,3 +93,12 @@ void AbstractRepresentationStream::setSegmentOffset (uint32_t offset) { this->segmentOffset = offset; } + +uint32_t AbstractRepresentationStream::getTime(size_t segmentNumber) +{ + return 0; +} +size_t AbstractRepresentationStream::getSegmentNumber(uint32_t time) +{ + return 0; +} diff --git a/MPD/AbstractRepresentationStream.h b/MPD/AbstractRepresentationStream.h index 4728e366..87400c0c 100644 --- a/MPD/AbstractRepresentationStream.h +++ b/MPD/AbstractRepresentationStream.h @@ -12,15 +12,22 @@ #ifndef LIBDASH_FRAMEWORK_MPD_ABSTRACTREPRESENTATIONSTREAM_H_ #define LIBDASH_FRAMEWORK_MPD_ABSTRACTREPRESENTATIONSTREAM_H_ +#include "../MPD/IMPDWrapper.h" #include "IRepresentationStream.h" #include "IBaseUrl.h" #include "IRepresentation.h" #include "IAdaptationSet.h" -#include "IMPD.h" #include "IPeriod.h" #include "BaseUrlResolver.h" #include "TimeResolver.h" +namespace viper +{ +namespace managers +{ +enum StreamType; +} +} namespace libdash { namespace framework @@ -30,7 +37,7 @@ namespace mpd class AbstractRepresentationStream : public IRepresentationStream { public: - AbstractRepresentationStream(dash::mpd::IMPD *mpd, dash::mpd::IPeriod *period, dash::mpd::IAdaptationSet *adaptationSet, + AbstractRepresentationStream(viper::managers::StreamType type, libdash::framework::mpd::IMPDWrapper *mpdWrapper, dash::mpd::IPeriod *period, dash::mpd::IAdaptationSet *adaptationSet, dash::mpd::IRepresentation *representation); virtual ~AbstractRepresentationStream(); @@ -47,17 +54,20 @@ public: virtual uint32_t getAverageSegmentDuration(); virtual uint32_t getTimescale(); - virtual void setSegmentOffset(uint32_t offset); + virtual void setSegmentOffset(uint32_t offset); + virtual uint32_t getTime(size_t segmentNumber); + virtual size_t getSegmentNumber(uint32_t time); protected: virtual void setBaseUrls(const std::vector baseurls); std::vector baseUrls; - dash::mpd::IMPD *mpd; + libdash::framework::mpd::IMPDWrapper *mpdWrapper; dash::mpd::IPeriod *period; dash::mpd::IAdaptationSet *adaptationSet; dash::mpd::IRepresentation *representation; uint32_t segmentOffset; + viper::managers::StreamType type; }; } } diff --git a/MPD/AdaptationSetStream.cpp b/MPD/AdaptationSetStream.cpp index 62bc1912..94f97df9 100644 --- a/MPD/AdaptationSetStream.cpp +++ b/MPD/AdaptationSetStream.cpp @@ -14,69 +14,72 @@ using namespace libdash::framework::mpd; using namespace dash::mpd; -AdaptationSetStream::AdaptationSetStream(IMPD *mpd, IPeriod *period, IAdaptationSet *adaptationSet) : - mpd (mpd), - period (period), - adaptationSet (adaptationSet) +AdaptationSetStream::AdaptationSetStream(viper::managers::StreamType type, MPDWrapper *mpdWrapper) : + mpdWrapper (mpdWrapper), + type (type) +// period (period), +// adaptationSet (adaptationSet) { initialize(); } AdaptationSetStream::~AdaptationSetStream() { - std::map::iterator iter; - for (iter = representations.begin(); iter != representations.end(); ++iter) - { - delete(iter->second); - } + this->mpdWrapper->destroyAdaptationSetStream(type); +// std::map::iterator iter; +// for (iter = representations.begin(); iter != representations.end(); ++iter) +// { +// delete(iter->second); +// } } -IRepresentationStream* AdaptationSetStream::getRepresentationStream(IRepresentation *representation) -{ - return this->representations.find(representation)->second; -} - -RepresentationStreamType AdaptationSetStream::determineRepresentationStreamType (IRepresentation *representation) -{ - /* check on Representation Level */ - if (representation->GetSegmentList()) - return libdash::framework::mpd::SegmentList; - - if (representation->GetSegmentTemplate()) - return libdash::framework::mpd::SegmentTemplate; - - if (representation->GetSegmentBase() || representation->GetBaseURLs().size() > 0) - return libdash::framework::mpd::SingleMediaSegment; - - /* check on AdaptationSet Level */ - if (this->adaptationSet->GetSegmentList()) - return libdash::framework::mpd::SegmentList; - - if (this->adaptationSet->GetSegmentTemplate()) - return libdash::framework::mpd::SegmentTemplate; - - if (this->adaptationSet->GetSegmentBase()) - return libdash::framework::mpd::SingleMediaSegment; - - /* check on Period Level */ - if (this->period->GetSegmentList()) - return libdash::framework::mpd::SegmentList; - - if (this->period->GetSegmentTemplate()) - return libdash::framework::mpd::SegmentTemplate; - - if (this->period->GetSegmentBase()) - return libdash::framework::mpd::SingleMediaSegment; - - return libdash::framework::mpd::UNDEFINED; -} +//IRepresentationStream* AdaptationSetStream::getRepresentationStream(IRepresentation *representation) +//{ +// return this->representations.find(representation)->second; +//} + +//RepresentationStreamType AdaptationSetStream::determineRepresentationStreamType (IRepresentation *representation) +//{ +// /* check on Representation Level */ +// if (representation->GetSegmentList()) +// return libdash::framework::mpd::SegmentList; +// +// if (representation->GetSegmentTemplate()) +// return libdash::framework::mpd::SegmentTemplate; +// +// if (representation->GetSegmentBase() || representation->GetBaseURLs().size() > 0) +// return libdash::framework::mpd::SingleMediaSegment; +// +// /* check on AdaptationSet Level */ +// if (this->adaptationSet->GetSegmentList()) +// return libdash::framework::mpd::SegmentList; +// +// if (this->adaptationSet->GetSegmentTemplate()) +// return libdash::framework::mpd::SegmentTemplate; +// +// if (this->adaptationSet->GetSegmentBase()) +// return libdash::framework::mpd::SingleMediaSegment; +// +// /* check on Period Level */ +// if (this->period->GetSegmentList()) +// return libdash::framework::mpd::SegmentList; +// +// if (this->period->GetSegmentTemplate()) +// return libdash::framework::mpd::SegmentTemplate; +// +// if (this->period->GetSegmentBase()) +// return libdash::framework::mpd::SingleMediaSegment; +// +// return libdash::framework::mpd::UNDEFINED; +//} void AdaptationSetStream::initialize() { - for (size_t i = 0; i < adaptationSet->GetRepresentation().size(); i++) - { - IRepresentation *representation = adaptationSet->GetRepresentation().at(i); - RepresentationStreamType type = determineRepresentationStreamType(representation); - representations[representation] = RepresentationStreamFactory::create(type, mpd, period, adaptationSet, representation); - } + this->mpdWrapper->initializeAdaptationSetStream(type); +// for (size_t i = 0; i < adaptationSet->GetRepresentation().size(); i++) +// { +// IRepresentation *representation = adaptationSet->GetRepresentation().at(i); +// RepresentationStreamType type = determineRepresentationStreamType(representation); +// representations[representation] = RepresentationStreamFactory::create(type, mpd, period, adaptationSet, representation); +// } } diff --git a/MPD/AdaptationSetStream.h b/MPD/AdaptationSetStream.h index 3ad9788f..d38c1388 100644 --- a/MPD/AdaptationSetStream.h +++ b/MPD/AdaptationSetStream.h @@ -14,7 +14,7 @@ #include "IRepresentationStream.h" #include "IRepresentation.h" -#include "IMPD.h" +#include "MPDWrapper.h" #include "IPeriod.h" #include "IAdaptationSet.h" #include "RepresentationStreamFactory.h" @@ -29,19 +29,21 @@ namespace mpd class AdaptationSetStream { public: - AdaptationSetStream(dash::mpd::IMPD *mpd, dash::mpd::IPeriod *period, dash::mpd::IAdaptationSet *adaptationSet); +// AdaptationSetStream(dash::mpd::IMPD *mpd, dash::mpd::IPeriod *period, dash::mpd::IAdaptationSet *adaptationSet); + AdaptationSetStream(viper::managers::StreamType type, libdash::framework::mpd::MPDWrapper *mpdWrapper); virtual ~AdaptationSetStream(); - IRepresentationStream* getRepresentationStream(dash::mpd::IRepresentation *representation); +// IRepresentationStream* getRepresentationStream(dash::mpd::IRepresentation *representation); private: - RepresentationStreamType determineRepresentationStreamType(dash::mpd::IRepresentation *representation); +// RepresentationStreamType determineRepresentationStreamType(dash::mpd::IRepresentation *representation); void initialize(); - std::map representations; - dash::mpd::IMPD *mpd; - dash::mpd::IPeriod *period; - dash::mpd::IAdaptationSet *adaptationSet; +// std::map representations; + libdash::framework::mpd::MPDWrapper *mpdWrapper; + viper::managers::StreamType type; +// dash::mpd::IPeriod *period; +// dash::mpd::IAdaptationSet *adaptationSet; }; } diff --git a/MPD/BaseUrlResolver.cpp b/MPD/BaseUrlResolver.cpp index 54b586cd..4340840d 100644 --- a/MPD/BaseUrlResolver.cpp +++ b/MPD/BaseUrlResolver.cpp @@ -14,10 +14,10 @@ using namespace dash::mpd; using namespace libdash::framework::mpd; -std::vector BaseUrlResolver::resolveBaseUrl(IMPD *mpd, IPeriod *period, IAdaptationSet *adaptationSet, - size_t mpdBaseUrl, size_t periodBaseUrl, size_t adaptationSetBaseUrl) +std::vector BaseUrlResolver::resolveBaseUrl(viper::managers::StreamType type, IMPDWrapper *mpdWrapper, size_t mpdBaseUrl, size_t periodBaseUrl, size_t adaptationSetBaseUrl) { - std::vector urls; + return mpdWrapper->resolveBaseUrl(type, mpdBaseUrl, periodBaseUrl, adaptationSetBaseUrl); +/* std::vector urls; if (mpd->GetBaseUrls().size() > 0) { @@ -60,5 +60,10 @@ std::vector BaseUrlResolver::resolveBaseUrl(IMPD *mpd, IP urls.push_back(mpd->GetMPDPathBaseUrl()); } - return urls; + return urls; */ +} + +std::vector BaseUrlResolver::resolveBaseUrl(viper::managers::StreamType type, IMPDWrapper *mpdWrapper, size_t mpdBaseUrl, size_t periodBaseUrl, size_t adaptationSetBaseUrl, IMPD* mpd) +{ + return mpdWrapper->resolveBaseUrl(type, mpdBaseUrl, periodBaseUrl, adaptationSetBaseUrl, mpd); } diff --git a/MPD/BaseUrlResolver.h b/MPD/BaseUrlResolver.h index 6956a00e..b2513f05 100644 --- a/MPD/BaseUrlResolver.h +++ b/MPD/BaseUrlResolver.h @@ -12,7 +12,7 @@ #ifndef LIBDASH_FRAMEWORK_MPD_BASEURLRESOLVER_H_ #define LIBDASH_FRAMEWORK_MPD_BASEURLRESOLVER_H_ -#include "IMPD.h" +#include "IMPDWrapper.h" namespace libdash { @@ -23,8 +23,10 @@ namespace mpd class BaseUrlResolver { public: - static std::vector resolveBaseUrl(dash::mpd::IMPD *mpd, dash::mpd::IPeriod *period, dash::mpd::IAdaptationSet *adaptationSet, + static std::vector resolveBaseUrl(viper::managers::StreamType type, libdash::framework::mpd::IMPDWrapper *mpdWrapper, size_t mpdBaseUrl, size_t periodBaseUrl, size_t adaptationSetBaseUrl); + static std::vector resolveBaseUrl(viper::managers::StreamType type, libdash::framework::mpd::IMPDWrapper *mpdWrapper, + size_t mpdBaseUrl, size_t periodBaseUrl, size_t adaptationSetBaseUrl, dash::mpd::IMPD* mpd); }; } } diff --git a/MPD/IMPDWrapper.h b/MPD/IMPDWrapper.h new file mode 100644 index 00000000..7390494e --- /dev/null +++ b/MPD/IMPDWrapper.h @@ -0,0 +1,46 @@ +/* + * MPDWrapper.h + ***************************************************************************** + * Copyright (C) 2017, Cisco Systems France + * + * Email: cicn-dev@lists.fd.io + * + * This source code and its use and distribution, is subject to the terms + * and conditions of the applicable license agreement. + *****************************************************************************/ + + +#ifndef LIBDASH_FRAMEWORK_MPD_IMPDWRAPPER_H_ +#define LIBDASH_FRAMEWORK_MPD_IMPDWRAPPER_H_ + +#include "../Managers/IStreamObserver.h" +//#include +//#include +#include "IMPD.h" +#include "../Managers/IStreamObserver.h" + +namespace libdash +{ +namespace framework +{ +namespace mpd +{ +class IMPDWrapper +{ +public: + virtual std::string getAvailabilityStarttime() = 0; + virtual std::string getTimeShiftBufferDepth() = 0; + virtual std::string getTypeWithoutLock() = 0; + virtual uint32_t getFetchTime() = 0; + virtual std::string getMinimumUpdatePeriodWithoutLock() = 0; + virtual std::vector resolveBaseUrl(viper::managers::StreamType type, size_t mpdBaseUrl, size_t periodBaseUrl, size_t adaptationSetBaseUrl) = 0; + virtual std::vector resolveBaseUrl(viper::managers::StreamType type, size_t mpdBaseUrl, size_t periodBaseUrl, size_t adaptationSetBaseUrl, dash::mpd::IMPD* mpd) = 0; + virtual void releaseLock() = 0; + virtual std::string getMediaPresentationDuration() = 0; +}; +} +} +} + +#endif /* LIBDASH_FRAMEWORK_MPD_IMPDWRAPPER_H_ */ + diff --git a/MPD/IRepresentationStream.h b/MPD/IRepresentationStream.h index 31f83d54..5734c4cf 100644 --- a/MPD/IRepresentationStream.h +++ b/MPD/IRepresentationStream.h @@ -44,6 +44,9 @@ public: virtual uint32_t getLastSegmentNumber() = 0; virtual uint32_t getAverageSegmentDuration() = 0; virtual void setSegmentOffset(uint32_t offset) = 0; + virtual uint32_t getTime(size_t segmentNumber) = 0; + virtual size_t getSegmentNumber(uint32_t time) = 0; + }; } diff --git a/MPD/MPDWrapper.cpp b/MPD/MPDWrapper.cpp new file mode 100644 index 00000000..4c8baa6b --- /dev/null +++ b/MPD/MPDWrapper.cpp @@ -0,0 +1,1098 @@ +/* + * MPDWrapper.cpp + ***************************************************************************** + * Copyright (C) 2017, Cisco Systems France + * + * Email: libdash-dev@vicky.bitmovin.net + * + * This source code and its use and distribution, is subject to the terms + * and conditions of the applicable license agreement. + *****************************************************************************/ + +#include "MPDWrapper.h" + +using namespace dash::mpd; +using namespace libdash::framework::mpd; +using namespace libdash::framework::input; +using namespace viper::managers; + +MPDWrapper::MPDWrapper(IMPD *mpd): + mpd (mpd), + period (NULL), + videoAdaptationSet (NULL), + videoRepresentation (NULL), + audioAdaptationSet (NULL), + audioRepresentation (NULL), + videoRepresentations(NULL), + audioRepresentations(NULL), + videoSegmentOffset (0), + audioSegmentOffset (0), + videoSegmentNumber (0), + audioSegmentNumber (0) +{ + InitializeConditionVariable (&this->mpdUpdate); + InitializeCriticalSection(&this->monitorMutex); +} + +MPDWrapper::~MPDWrapper() +{ + DeleteCriticalSection(&this->monitorMutex); + DeleteConditionVariable(&this->mpdUpdate); +} + +IMPD* MPDWrapper::getMPD () +{ + return this->mpd; +} + +void MPDWrapper::updateMPD (IMPD* mpd) +{ +//Assumptions here: +// *only one period in the MPD +// *only triggered if using SegmentTimeline dynamic MPD + EnterCriticalSection(&this->monitorMutex); + this->period = mpd->GetPeriods().at(0); + this->findVideoAdaptationSet(mpd); + this->findAudioAdaptationSet(mpd); + this->findVideoRepresentation(mpd); + this->findAudioRepresentation(mpd); + delete(this->mpd); + this->mpd = mpd; + WakeAllConditionVariable(&this->mpdUpdate); + LeaveCriticalSection(&this->monitorMutex); +} + +void MPDWrapper::findVideoAdaptationSet (IMPD* mpd) +{ + std::vector adaptationSets = AdaptationSetHelper::getVideoAdaptationSets(mpd->GetPeriods().at(0)); + if(!(adaptationSets.empty()) && this->videoAdaptationSet) + { + for(size_t i = 0; i < adaptationSets.size(); i++) + { + if(adaptationSets.at(i)->GetId() == this->videoAdaptationSet->GetId()) + { + this->videoAdaptationSet = adaptationSets.at(i); + return; + } + } + //Not found in the new set of adaptation logc => select the first one + this->videoAdaptationSet = adaptationSets.at(0); + } + else + { + if(!adaptationSets.empty()) + { + this->videoAdaptationSet = adaptationSets.at(0); + return; + } + this->videoAdaptationSet = NULL; + } +} + +void MPDWrapper::findAudioAdaptationSet (IMPD* mpd) +{ + std::vector adaptationSets = AdaptationSetHelper::getAudioAdaptationSets(mpd->GetPeriods().at(0)); + if(!(adaptationSets.empty()) && this->audioAdaptationSet) + { + for(size_t i = 0; i < adaptationSets.size(); i++) + { + if(adaptationSets.at(i)->GetId() == this->audioAdaptationSet->GetId()) + { + this->audioAdaptationSet = adaptationSets.at(i); + return; + } + } + //Not found in the new set of adaptation logc => select the first one + this->audioAdaptationSet = adaptationSets.at(0); + + } + else + { + if(!adaptationSets.empty()) + { + this->audioAdaptationSet = adaptationSets.at(0); + return; + } + this->audioAdaptationSet = NULL; + } +} + +void MPDWrapper::findVideoRepresentation (IMPD* mpd) +{ + if(this->videoAdaptationSet) + { + std::vector representations = this->videoAdaptationSet->GetRepresentation(); + if(this->videoRepresentation) + { + uint32_t time = this->videoRepresentations->find(this->videoRepresentation)->second->getTime(this->videoSegmentNumber); + uint32_t id = std::stoi(this->videoRepresentation->GetId()); + for(size_t i = 0; i < representations.size(); i++) + { + if(id == std::stoi(representations.at(i)->GetId())) + { + this->videoRepresentation = representations.at(i); + this->destroyAdaptationSetStream(viper::managers::StreamType::VIDEO); + this->initializeAdaptationSetStreamWithoutLock(viper::managers::StreamType::VIDEO, mpd); + this->videoSegmentNumber = this->videoRepresentations->find(this->videoRepresentation)->second->getSegmentNumber(time); + return; + } + } + this->destroyAdaptationSetStream(viper::managers::StreamType::VIDEO); + } + this->videoRepresentation = representations.at(0); + this->initializeAdaptationSetStreamWithoutLock(viper::managers::StreamType::VIDEO, mpd); + this->videoSegmentNumber = this->videoRepresentations->find(this->videoRepresentation)->second->getSegmentNumber(time); + } + else + { + this->videoRepresentation = NULL; + } +} + +void MPDWrapper::findAudioRepresentation (IMPD* mpd) +{ + if(this->audioAdaptationSet) + { + std::vector representations = this->audioAdaptationSet->GetRepresentation(); + if(this->audioRepresentation) + { + uint32_t time = this->audioRepresentations->find(this->audioRepresentation)->second->getTime(this->audioSegmentNumber); + uint32_t id = std::stoi(this->audioRepresentation->GetId()); + for(size_t i = 0; i < representations.size(); i++) + { + if(id == std::stoi(representations.at(i)->GetId())) + { + this->videoRepresentation = representations.at(i); + this->destroyAdaptationSetStream(viper::managers::StreamType::AUDIO); + this->initializeAdaptationSetStreamWithoutLock(viper::managers::StreamType::AUDIO, mpd); + this->audioSegmentNumber = this->audioRepresentations->find(this->audioRepresentation)->second->getSegmentNumber(time); + return; + } + } + this->destroyAdaptationSetStream(viper::managers::StreamType::AUDIO); + } + this->audioRepresentation = representations.at(0); + this->initializeAdaptationSetStreamWithoutLock(viper::managers::StreamType::AUDIO,mpd); + this->audioSegmentNumber = this->audioRepresentations->find(this->audioRepresentation)->second->getSegmentNumber(time); + } + else + { + this->audioRepresentation = NULL; + } +} + +std::string MPDWrapper::getType () +{ + std::string type; + EnterCriticalSection(&this->monitorMutex); + type = this->mpd->GetType(); + LeaveCriticalSection(&this->monitorMutex); + return type; +} + + +void MPDWrapper::reInit (viper::managers::StreamType type) +{ + EnterCriticalSection(&this->monitorMutex); + switch(type) + { + case viper::managers::StreamType::VIDEO: + { + this->period = NULL; + this->videoAdaptationSet = NULL; + this->videoRepresentation = NULL; + break; + } + case viper::managers::StreamType::AUDIO: + { + this->period = NULL; + this->audioAdaptationSet = NULL; + this->audioRepresentation = NULL; + break; + } + default: + break; + } + LeaveCriticalSection(&this->monitorMutex); +} + +bool MPDWrapper::hasVideoAdaptationSetAndVideoRepresentation () +{ + EnterCriticalSection(&this->monitorMutex); + if(this->videoAdaptationSet && this->videoRepresentation) + { + LeaveCriticalSection(&this->monitorMutex); + return 1; + } + LeaveCriticalSection(&this->monitorMutex); + return 0; +} + +bool MPDWrapper::hasAudioAdaptationSetAndAudioRepresentation () +{ + EnterCriticalSection(&this->monitorMutex); + if(this->audioAdaptationSet && this->audioRepresentation) + { + LeaveCriticalSection(&this->monitorMutex); + return 1; + } + LeaveCriticalSection(&this->monitorMutex); + return 0; +} + +RepresentationStreamType MPDWrapper::determineRepresentationStreamType (IRepresentation *representation, IAdaptationSet *adaptationSet, IPeriod* period) +{ + /* check on Representation Level */ + if (representation->GetSegmentList()) + return libdash::framework::mpd::SegmentList; + + if (representation->GetSegmentTemplate()) + return libdash::framework::mpd::SegmentTemplate; + + if (representation->GetSegmentBase() || representation->GetBaseURLs().size() > 0) + return libdash::framework::mpd::SingleMediaSegment; + + /* check on AdaptationSet Level */ + if (adaptationSet->GetSegmentList()) + return libdash::framework::mpd::SegmentList; + + if (adaptationSet->GetSegmentTemplate()) + return libdash::framework::mpd::SegmentTemplate; + + if (adaptationSet->GetSegmentBase()) + return libdash::framework::mpd::SingleMediaSegment; + + /* check on Period Level */ + if (period->GetSegmentList()) + return libdash::framework::mpd::SegmentList; + + if (period->GetSegmentTemplate()) + return libdash::framework::mpd::SegmentTemplate; + + if (period->GetSegmentBase()) + return libdash::framework::mpd::SingleMediaSegment; + + return libdash::framework::mpd::UNDEFINED; +} + +void MPDWrapper::initializeAdaptationSetStream (viper::managers::StreamType type) +{ + IAdaptationSet *adaptationSet = NULL; + std::map *representations = NULL; + EnterCriticalSection(&this->monitorMutex); + + switch(type) + { + case viper::managers::StreamType::AUDIO: + if(this->audioRepresentations == NULL) + this->audioRepresentations = new std::map(); + if(this->audioAdaptationSet == NULL) + return; + adaptationSet = this->audioAdaptationSet; + representations = this->audioRepresentations; + break; + case viper::managers::StreamType::VIDEO: + if(this->videoRepresentations == NULL) + this->videoRepresentations = new std::map(); + if(this->videoAdaptationSet == NULL) + return; + adaptationSet = this->videoAdaptationSet; + representations = this->videoRepresentations; + break; + default: + return; + } + + for (size_t i = 0; i < adaptationSet->GetRepresentation().size(); i++) + { + IRepresentation *representation = adaptationSet->GetRepresentation().at(i); + RepresentationStreamType typeR = determineRepresentationStreamType(representation, adaptationSet, this->period); + (*representations)[representation] = RepresentationStreamFactory::create(type, typeR, this, period, adaptationSet, representation); + } + LeaveCriticalSection(&this->monitorMutex); +} + +void MPDWrapper::initializeAdaptationSetStreamWithoutLock (viper::managers::StreamType type) +{ + IAdaptationSet *adaptationSet = NULL; + std::map *representations = NULL; + + switch(type) + { + case viper::managers::StreamType::AUDIO: + if(this->audioRepresentations == NULL) + this->audioRepresentations = new std::map(); + if(this->audioAdaptationSet == NULL) + return; + adaptationSet = this->audioAdaptationSet; + representations = this->audioRepresentations; + break; + case viper::managers::StreamType::VIDEO: + if(this->videoRepresentations == NULL) + this->videoRepresentations = new std::map(); + if(this->videoAdaptationSet == NULL) + return; + adaptationSet = this->videoAdaptationSet; + representations = this->videoRepresentations; + break; + default: + return; + } + for (size_t i = 0; i < adaptationSet->GetRepresentation().size(); i++) + { + IRepresentation *representation = adaptationSet->GetRepresentation().at(i); + RepresentationStreamType typeR = determineRepresentationStreamType(representation, adaptationSet, this->period); + (*representations)[representation] = RepresentationStreamFactory::create(type, typeR, this, period, adaptationSet, representation); + } +} + +void MPDWrapper::initializeAdaptationSetStreamWithoutLock (viper::managers::StreamType type, IMPD* mpd) +{ + IAdaptationSet *adaptationSet = NULL; + std::map *representations = NULL; + + switch(type) + { + case viper::managers::StreamType::AUDIO: + if(this->audioRepresentations == NULL) + this->audioRepresentations = new std::map(); + if(this->audioAdaptationSet == NULL) + return; + adaptationSet = this->audioAdaptationSet; + representations = this->audioRepresentations; + break; + case viper::managers::StreamType::VIDEO: + if(this->videoRepresentations == NULL) + this->videoRepresentations = new std::map(); + if(this->videoAdaptationSet == NULL) + return; + adaptationSet = this->videoAdaptationSet; + representations = this->videoRepresentations; + break; + default: + return; + } + for (size_t i = 0; i < adaptationSet->GetRepresentation().size(); i++) + { + IRepresentation *representation = adaptationSet->GetRepresentation().at(i); + RepresentationStreamType typeR = determineRepresentationStreamType(representation, adaptationSet, this->period); + (*representations)[representation] = RepresentationStreamFactory::create(type, typeR, this, period, adaptationSet, representation, mpd); + } +} + +void MPDWrapper::destroyAdaptationSetStream (viper::managers::StreamType type) +{ + std::map *representations = NULL; + + switch(type) + { + case viper::managers::StreamType::AUDIO: + representations = this->audioRepresentations; + break; + case viper::managers::StreamType::VIDEO: + representations = this->videoRepresentations; + break; + default: + return; + } + + std::map::iterator iter; + for (iter = representations->begin(); iter != representations->end(); ++iter) + { + delete(iter->second); + } + representations->clear(); +} + +std::vector MPDWrapper::resolveBaseUrl (viper::managers::StreamType type, size_t mpdBaseUrl, size_t periodBaseUrl, size_t adaptationSetBaseUrl) +{ + + IAdaptationSet *adaptationSet = NULL; + std::vector urls; + + switch(type) + { + case viper::managers::StreamType::AUDIO: + adaptationSet = this->audioAdaptationSet; + break; + case viper::managers::StreamType::VIDEO: + adaptationSet = this->videoAdaptationSet; + break; + default: + return urls; + } + + if(adaptationSet == NULL) + return urls; + + if (mpd->GetBaseUrls().size() > 0) + { + if (mpd->GetBaseUrls().size() > mpdBaseUrl) + urls.push_back(mpd->GetBaseUrls().at(mpdBaseUrl)); + else + urls.push_back(mpd->GetBaseUrls().at(0)); + } + if (period->GetBaseURLs().size() > 0) + { + if (period->GetBaseURLs().size() > periodBaseUrl) + urls.push_back(period->GetBaseURLs().at(periodBaseUrl)); + else + urls.push_back(period->GetBaseURLs().at(0)); + } + if (adaptationSet->GetBaseURLs().size() > 0) + { + if (adaptationSet->GetBaseURLs().size() > adaptationSetBaseUrl) + urls.push_back(adaptationSet->GetBaseURLs().at(adaptationSetBaseUrl)); + else + urls.push_back(adaptationSet->GetBaseURLs().at(0)); + } + + if (urls.size() > 0) + { + if (urls.at(0)->GetUrl().substr(0,7) != "http://" && urls.at(0)->GetUrl().substr(0,8) != "https://") + { + urls.push_back(mpd->GetMPDPathBaseUrl()); + size_t lastPos = urls.size() - 1; + IBaseUrl *absoluteUrl = urls.at(lastPos); + for (size_t i = lastPos; i > 0; i--) + { + urls[i] = urls[i-1]; + } + urls[0] = absoluteUrl; + } + } + else + { + urls.push_back(mpd->GetMPDPathBaseUrl()); + } + + return urls; +} + +std::vector MPDWrapper::resolveBaseUrl (viper::managers::StreamType type, size_t mpdBaseUrl, size_t periodBaseUrl, size_t adaptationSetBaseUrl, IMPD* mpd) +{ + + IAdaptationSet *adaptationSet = NULL; + std::vector urls; + + switch(type) + { + case viper::managers::StreamType::AUDIO: + adaptationSet = this->audioAdaptationSet; + break; + case viper::managers::StreamType::VIDEO: + adaptationSet = this->videoAdaptationSet; + break; + default: + return urls; + } + + if(adaptationSet == NULL) + return urls; + + if (mpd->GetBaseUrls().size() > 0) + { + if (mpd->GetBaseUrls().size() > mpdBaseUrl) + urls.push_back(mpd->GetBaseUrls().at(mpdBaseUrl)); + else + urls.push_back(mpd->GetBaseUrls().at(0)); + } + if (period->GetBaseURLs().size() > 0) + { + if (period->GetBaseURLs().size() > periodBaseUrl) + urls.push_back(period->GetBaseURLs().at(periodBaseUrl)); + else + urls.push_back(period->GetBaseURLs().at(0)); + } + if (adaptationSet->GetBaseURLs().size() > 0) + { + if (adaptationSet->GetBaseURLs().size() > adaptationSetBaseUrl) + urls.push_back(adaptationSet->GetBaseURLs().at(adaptationSetBaseUrl)); + else + urls.push_back(adaptationSet->GetBaseURLs().at(0)); + } + + if (urls.size() > 0) + { + if (urls.at(0)->GetUrl().substr(0,7) != "http://" && urls.at(0)->GetUrl().substr(0,8) != "https://") + { + urls.push_back(mpd->GetMPDPathBaseUrl()); + size_t lastPos = urls.size() - 1; + IBaseUrl *absoluteUrl = urls.at(lastPos); + for (size_t i = lastPos; i > 0; i--) + { + urls[i] = urls[i-1]; + } + urls[0] = absoluteUrl; + } + } + else + { + urls.push_back(mpd->GetMPDPathBaseUrl()); + } + + return urls; +} + +void MPDWrapper::acquireLock () +{ + EnterCriticalSection(&this->monitorMutex); +} + + +void MPDWrapper::releaseLock () +{ + LeaveCriticalSection(&this->monitorMutex); +} + +void MPDWrapper::setSegmentOffset(viper::managers::StreamType type, uint32_t segmentOffset) +{ + EnterCriticalSection(&this->monitorMutex); + switch(type) + { + case viper::managers::StreamType::AUDIO: + this->audioSegmentOffset = segmentOffset; + this->audioRepresentations->find(this->audioRepresentation)->second->setSegmentOffset(segmentOffset); + break; + case viper::managers::StreamType::VIDEO: + this->videoSegmentOffset = segmentOffset; + this->videoRepresentations->find(this->videoRepresentation)->second->setSegmentOffset(segmentOffset); + break; + default: + break; + } + LeaveCriticalSection(&this->monitorMutex); +} + +MediaObject* MPDWrapper::getNextSegment (viper::managers::StreamType type, bool isLooping, uint32_t &segmentNumber, bool withFeedBack) +{ + IRepresentation* representation; + std::map *representations; + + EnterCriticalSection(&this->monitorMutex); + switch(type) + { + case viper::managers::StreamType::AUDIO: + representation = this->audioRepresentation; + representations = this->audioRepresentations; + break; + case viper::managers::StreamType::VIDEO: + representation = this->videoRepresentation; + representations = this->videoRepresentations; + break; + default: + LeaveCriticalSection(&this->monitorMutex); + return NULL; + } + + ISegment* seg = NULL; + IRepresentationStream* representationStream = representations->find(representation)->second; + + if(!strcmp(this->mpd->GetType().c_str(), "static")) + { + if(segmentNumber >= representationStream->getSize()) + { + if(isLooping) + { + segmentNumber = 0; + } + else + { + switch(type) + { + case viper::managers::StreamType::AUDIO: + this->audioSegmentNumber = segmentNumber; + break; + case viper::managers::StreamType::VIDEO: + this->videoSegmentNumber = segmentNumber; + break; + default: + break; + } + LeaveCriticalSection(&this->monitorMutex); + return NULL; + } + } + } + else + { + while((this->isStopping == false) && segmentNumber >= representationStream->getSize()) + { + SleepConditionVariableCS(&this->mpdUpdate, &this->monitorMutex, INFINITE); + + if(this->isStopping) + { + LeaveCriticalSection(&this->monitorMutex); + return NULL; + } + + //Need to update representationStream here as it was updated with the mpd: + switch(type) + { + case viper::managers::StreamType::AUDIO: + representation = this->audioRepresentation; + representations = this->audioRepresentations; + break; + case viper::managers::StreamType::VIDEO: + representation = this->videoRepresentation; + representations = this->videoRepresentations; + break; + default: + break; + } + representationStream = representations->find(representation)->second; + } + } + seg = representationStream->getMediaSegment(segmentNumber); + if(seg != NULL) + { + MediaObject *media = new MediaObject(seg, representation, withFeedBack); + segmentNumber++; + switch(type) + { + case viper::managers::StreamType::AUDIO: + this->audioSegmentNumber = segmentNumber; + break; + case viper::managers::StreamType::VIDEO: + this->videoSegmentNumber = segmentNumber; + break; + default: + break; + } + LeaveCriticalSection(&this->monitorMutex); + return media; + } + LeaveCriticalSection(&this->monitorMutex); + return NULL; +} + +MediaObject* MPDWrapper::getSegment (viper::managers::StreamType type, uint32_t segNum) +{ + IRepresentation* representation; + std::map *representations; + EnterCriticalSection(&this->monitorMutex); + + switch(type) + { + case viper::managers::StreamType::AUDIO: + representation = this->audioRepresentation; + representations = this->audioRepresentations; + break; + case viper::managers::StreamType::VIDEO: + representation = this->videoRepresentation; + representations = this->videoRepresentations; + break; + default: + LeaveCriticalSection(&this->monitorMutex); + return NULL; + } + + ISegment* seg = NULL; + IRepresentationStream* representationStream = representations->find(representation)->second; + if(segNum >= representationStream->getSize()) + { + LeaveCriticalSection(&this->monitorMutex); + return NULL; + } + seg = representationStream->getMediaSegment(segNum); + if(seg != NULL) + { + MediaObject *media = new MediaObject(seg, representation); + LeaveCriticalSection(&this->monitorMutex); + return media; + } + LeaveCriticalSection(&this->monitorMutex); + return NULL; +} + +MediaObject* MPDWrapper::getInitSegment (viper::managers::StreamType type) +{ + IRepresentation* representation; + std::map *representations; + EnterCriticalSection(&this->monitorMutex); + + switch(type) + { + case viper::managers::StreamType::AUDIO: + representation = this->audioRepresentation; + representations = this->audioRepresentations; + break; + case viper::managers::StreamType::VIDEO: + representation = this->videoRepresentation; + representations = this->videoRepresentations; + break; + default: + LeaveCriticalSection(&this->monitorMutex); + return NULL; + } + + ISegment* seg = NULL; + IRepresentationStream* representationStream = representations->find(representation)->second; + seg = representationStream->getInitializationSegment(); + + if(seg != NULL) + { + MediaObject *media = new MediaObject(seg, representation); + LeaveCriticalSection(&this->monitorMutex); + return media; + } + LeaveCriticalSection(&this->monitorMutex); + return NULL; +} + +void MPDWrapper::setQuality(viper::managers::StreamType type, IPeriod* period, IAdaptationSet *adaptationSet, IRepresentation *representation) +{ + switch(type) + { + case viper::managers::StreamType::AUDIO: + this->setAudioQuality(period, adaptationSet, representation); + break; + case viper::managers::StreamType::VIDEO: + this->setVideoQuality(period, adaptationSet, representation); + break; + default: + return; + } +} + +void MPDWrapper::setAudioQuality (IPeriod *period, IAdaptationSet *adaptationSet, IRepresentation *representation) +{ + bool periodChanged = false; + if (this->audioRepresentation == representation) + { + LeaveCriticalSection(&this->monitorMutex); + return; + } + + this->audioRepresentation = representation; + + if (this->audioAdaptationSet != adaptationSet) + { + this->audioAdaptationSet = adaptationSet; + + if (this->period != period) + { + this->period = period; + periodChanged = true; + } + + this->destroyAdaptationSetStream(viper::managers::StreamType::AUDIO); + this->initializeAdaptationSetStreamWithoutLock(viper::managers::StreamType::AUDIO); + } +} + +void MPDWrapper::setVideoQuality (IPeriod *period, IAdaptationSet *adaptationSet, IRepresentation *representation) +{ + bool periodChanged = false; + if (this->videoRepresentation == representation) + { + LeaveCriticalSection(&this->monitorMutex); + return; + } + + this->videoRepresentation = representation; + + if (this->videoAdaptationSet != adaptationSet) + { + this->videoAdaptationSet = adaptationSet; + + if (this->period != period) + { + this->period = period; + periodChanged = true; + } + + this->destroyAdaptationSetStream(viper::managers::StreamType::VIDEO); + this->initializeAdaptationSetStreamWithoutLock(viper::managers::StreamType::VIDEO); + } +} + +uint32_t MPDWrapper::calculateSegmentOffset (viper::managers::StreamType type, uint32_t bufferSize) +{ + IRepresentation* representation; + std::map *representations; + EnterCriticalSection(&this->monitorMutex); + + switch(type) + { + case viper::managers::StreamType::AUDIO: + representation = this->audioRepresentation; + representations = this->audioRepresentations; + break; + case viper::managers::StreamType::VIDEO: + representation = this->videoRepresentation; + representations = this->videoRepresentations; + break; + default: + LeaveCriticalSection(&this->monitorMutex); + return 0; + } + + if(!(strcmp(this->mpd->GetType().c_str(), "static"))) + { + LeaveCriticalSection(&this->monitorMutex); + return 0; + } + IRepresentationStream* representationStream = representations->find(representation)->second; + uint32_t firstSegNum = representationStream->getFirstSegmentNumber(); + uint32_t currSegNum = representationStream->getCurrentSegmentNumber(); + uint32_t startSegNum = currSegNum - 2*bufferSize; + + LeaveCriticalSection(&this->monitorMutex); + return (startSegNum > firstSegNum) ? startSegNum : firstSegNum; +} + +std::string MPDWrapper::getRepresentationID (viper::managers::StreamType type) +{ + std::string id = ""; + EnterCriticalSection(&this->monitorMutex); + + switch(type) + { + case viper::managers::StreamType::AUDIO: + id = this->audioRepresentation->GetId(); + break; + case viper::managers::StreamType::VIDEO: + id = this->videoRepresentation->GetId(); + break; + default: + break; + } + LeaveCriticalSection(&this->monitorMutex); + return id; +} + +std::string MPDWrapper::getPublishTime () +{ + EnterCriticalSection(&this->monitorMutex); + std::string pubTime = this->mpd->GetPublishTime(); + LeaveCriticalSection(&this->monitorMutex); + return pubTime; +} + +std::string MPDWrapper::getMinimumUpdatePeriod () +{ + EnterCriticalSection(&this->monitorMutex); + std::string res = this->mpd->GetMinimumUpdatePeriod(); + LeaveCriticalSection(&this->monitorMutex); + return res; +} + + +/******************************************* +******************************************** +***** CAREFUL ***** +***** These functions should be called ***** +***** only if the lock was acquired!!! ***** +***** ***** +******************************************** +*******************************************/ + +std::vector MPDWrapper::getRepresentations (viper::managers::StreamType type) +{ + std::vector rep; + switch(type) + { + case viper::managers::StreamType::AUDIO: + if(this->audioAdaptationSet) + return this->audioAdaptationSet->GetRepresentation(); + return rep; + case viper::managers::StreamType::VIDEO: + if(this->videoAdaptationSet) + return this->videoAdaptationSet->GetRepresentation(); + return rep; + default: + return rep; + } +} + +std::string MPDWrapper::getMediaPresentationDuration () +{ + return this->mpd->GetMediaPresentationDuration(); +} + +IRepresentation* MPDWrapper::getRepresentationAt (viper::managers::StreamType type, int index) +{ + switch(type) + { + case viper::managers::StreamType::AUDIO: + if(this->audioAdaptationSet) + return this->audioAdaptationSet->GetRepresentation().at(index); + return NULL; + case viper::managers::StreamType::VIDEO: + if(this->videoAdaptationSet) + return this->videoAdaptationSet->GetRepresentation().at(index); + return NULL; + default: + return NULL; + } +} + +void MPDWrapper::setRepresentation (viper::managers::StreamType type, IRepresentation* rep) +{ + switch(type) + { + case viper::managers::StreamType::AUDIO: + this->audioRepresentation = rep; + return; + case viper::managers::StreamType::VIDEO: + this->videoRepresentation = rep; + return; + default: + break; + } +} + +std::string MPDWrapper::getRepresentationIDWithoutLock (viper::managers::StreamType type) +{ + std::string id = ""; + switch(type) + { + case viper::managers::StreamType::AUDIO: + id = this->audioRepresentation->GetId(); + break; + case viper::managers::StreamType::VIDEO: + id = this->videoRepresentation->GetId(); + break; + default: + break; + } + return id; +} + +MediaObject* MPDWrapper::getInitSegmentWithoutLock (viper::managers::StreamType type) +{ + IRepresentation* representation; + std::map *representations; + + switch(type) + { + case viper::managers::StreamType::AUDIO: + representation = this->audioRepresentation; + representations = this->audioRepresentations; + break; + case viper::managers::StreamType::VIDEO: + representation = this->videoRepresentation; + representations = this->videoRepresentations; + break; + default: + return NULL; + } + ISegment* seg = NULL; + IRepresentationStream* representationStream = representations->find(representation)->second; + seg = representationStream->getInitializationSegment(); + + if(seg != NULL) + { + MediaObject *media = new MediaObject(seg, representation); + return media; + } + return NULL; +} + +std::string MPDWrapper::getAvailabilityStarttime () +{ + return this->mpd->GetAvailabilityStarttime(); +} + +std::string MPDWrapper::getTimeShiftBufferDepth () +{ + return this->mpd->GetTimeShiftBufferDepth(); +} + +std::string MPDWrapper::getTypeWithoutLock () +{ + return this->mpd->GetType(); +} + +std::string MPDWrapper::getMinimumUpdatePeriodWithoutLock () +{ + return this->mpd->GetMinimumUpdatePeriod(); +} + +uint32_t MPDWrapper::getFetchTime () +{ + return this->mpd->GetFetchTime(); +} + +void MPDWrapper::settingsChanged (int period, int videoAdaptationSet, int videoRepresentation, int audioAdaptationSet, int audioRepresentation) +{ + EnterCriticalSection(&this->monitorMutex); + this->period = this->mpd->GetPeriods().at(period); + std::vector videoAdaptationSets = AdaptationSetHelper::getVideoAdaptationSets(this->period); + std::vector audioAdaptationSets = AdaptationSetHelper::getAudioAdaptationSets(this->period); + if (videoAdaptationSet >= 0 && videoRepresentation >= 0 && !videoAdaptationSets.empty()) + { + this->videoAdaptationSet = videoAdaptationSets.at(videoAdaptationSet); + this->videoRepresentation = this->videoAdaptationSet->GetRepresentation().at(videoRepresentation); + } + else + { + this->videoAdaptationSet = NULL; + this->videoRepresentation = NULL; + } + if (audioAdaptationSet >= 0 && audioRepresentation >= 0 && !audioAdaptationSets.empty()) + { + this->audioAdaptationSet = audioAdaptationSets.at(audioAdaptationSet); + this->audioRepresentation = this->audioAdaptationSet->GetRepresentation().at(audioRepresentation); + } + else + { + this->audioAdaptationSet = NULL; + this->audioRepresentation = NULL; + } + LeaveCriticalSection(&this->monitorMutex); +} + +//Returns the segmentDuration +float MPDWrapper::onFirstDownloadMPD (viper::IViperGui *gui) +{ + float segmentDuration = 0.0; + EnterCriticalSection(&this->monitorMutex); + IRepresentation *representation = this->videoAdaptationSet->GetRepresentation().at(0); + if(!strcmp(this->mpd->GetType().c_str(), "static")) // VOD MPD + { + if(representation->GetSegmentList()) + { + uint32_t duration = representation->GetSegmentList()->GetDuration(); + uint32_t timescale = representation->GetSegmentList()->GetTimescale(); + segmentDuration = 1.0*duration/(1.0*timescale) * 1000; + if(gui) + { + gui->setListSegmentSize(representation->GetSegmentList()->GetSegmentURLs().size()); + gui->setSegmentDuration(segmentDuration); + } + } + else //SegmentTemplate + { + uint32_t duration = representation->GetSegmentTemplate()->GetDuration(); + uint32_t timescale = representation->GetSegmentTemplate()->GetTimescale(); + segmentDuration = 1.0*duration/(1.0*timescale) * 1000; + if(gui) + { + gui->setSegmentDuration(segmentDuration); + gui->setListSegmentSize(TimeResolver::getDurationInSec(period->GetDuration())*1000/segmentDuration + 1); + } + } + } + else //Live MPD + { + //Assuming here that the segment duration doesn't change. If so, need to do an average over all segments. + uint32_t duration = representation->GetSegmentTemplate()->GetSegmentTimeline()->GetTimelines().at(0)->GetDuration(); + uint32_t timescale = representation->GetSegmentTemplate()->GetTimescale(); + segmentDuration = 1.0*duration/(1.0*timescale) * 1000; + if(gui) + { + gui->setSegmentDuration(segmentDuration); + gui->setListSegmentSize(0); + } + } + LeaveCriticalSection(&this->monitorMutex); + return segmentDuration; +} + +void MPDWrapper::setIsStopping (bool isStopping) +{ + this->isStopping = isStopping; + WakeAllConditionVariable(&this->mpdUpdate); +} diff --git a/MPD/MPDWrapper.h b/MPD/MPDWrapper.h new file mode 100644 index 00000000..902fa3dc --- /dev/null +++ b/MPD/MPDWrapper.h @@ -0,0 +1,134 @@ +/* + * MPDWrapper.h + ***************************************************************************** + * Copyright (C) 2017, Cisco Systems France + * + * Email: cicn-dev@lists.fd.io + * + * This source code and its use and distribution, is subject to the terms + * and conditions of the applicable license agreement. + *****************************************************************************/ + + +#ifndef LIBDASH_FRAMEWORK_MPD_MPDWRAPPER_H_ +#define LIBDASH_FRAMEWORK_MPD_MPDWRAPPER_H_ +//TODO: fix the circular includes +namespace viper +{ +class ViperGui; +} +namespace libdash +{ +namespace framework +{ +namespace mpd +{ +class MPDWrapper; +} +namespace input +{ +class MediaObject; +class DASHReceiver; +} +namespace adaptation +{ +class IAdaptationLogic; +} +} +} +#include "IMPD.h" +#include "IMPDWrapper.h" +#include "../Portable/MultiThreading.h" +#include "../Managers/IStreamObserver.h" +#include "../UI/IViperGui.h" +#include "IRepresentationStream.h" +#include "IRepresentation.h" +#include "IPeriod.h" +#include "IAdaptationSet.h" +#include "RepresentationStreamFactory.h" +#include "../Input/MediaObject.h" +#include "AdaptationSetHelper.h" + + +namespace libdash +{ +namespace framework +{ +namespace mpd +{ +class MPDWrapper : public IMPDWrapper +{ +public: + MPDWrapper(dash::mpd::IMPD *mpd); + ~MPDWrapper(); + + dash::mpd::IMPD* getMPD(); + void updateMPD(dash::mpd::IMPD* mpd); + std::string getType(); + void reInit(viper::managers::StreamType type); + void setVideoQuality(dash::mpd::IPeriod* period, dash::mpd::IAdaptationSet* adaptationSet, dash::mpd::IRepresentation* representation); + void setAudioQuality(dash::mpd::IPeriod* period, dash::mpd::IAdaptationSet* adaptationSet, dash::mpd::IRepresentation* representation); + bool hasAudioAdaptationSetAndAudioRepresentation(); + bool hasVideoAdaptationSetAndVideoRepresentation(); + void initializeAdaptationSetStream(viper::managers::StreamType type); +// void initializeAdaptationSetStream(viper::managers::StreamType type, dash::mpd::IMPD* mpd); + void destroyAdaptationSetStream(viper::managers::StreamType type); + void acquireLock(); + void releaseLock(); + void setSegmentOffset(viper::managers::StreamType type, uint32_t segmentOffset); + void findVideoAdaptationSet(dash::mpd::IMPD* mpd); + void findAudioAdaptationSet(dash::mpd::IMPD* mpd); + void findVideoRepresentation(dash::mpd::IMPD* mpd); + void findAudioRepresentation(dash::mpd::IMPD* mpd); + void initializeAdaptationSetStreamWithoutLock(viper::managers::StreamType type); + void initializeAdaptationSetStreamWithoutLock(viper::managers::StreamType type, dash::mpd::IMPD* mpd); + std::vector resolveBaseUrl(viper::managers::StreamType type, size_t mpdBaseUrl, size_t periodBaseUrl, size_t adaptationSetBaseUrl); + std::vector resolveBaseUrl(viper::managers::StreamType type, size_t mpdBaseUrl, size_t periodBaseUrl, size_t adaptationSetBaseUrl, dash::mpd::IMPD* mpd); + libdash::framework::input::MediaObject* getNextSegment(viper::managers::StreamType type, bool isLooping, uint32_t &segmentNumber, bool withFeedBack); + libdash::framework::input::MediaObject* getSegment(viper::managers::StreamType type, uint32_t segNum); + libdash::framework::input::MediaObject* getInitSegment(viper::managers::StreamType type); + void setQuality(viper::managers::StreamType type, dash::mpd::IPeriod* period, dash::mpd::IAdaptationSet *adaptationSet, dash::mpd::IRepresentation *representation); + uint32_t calculateSegmentOffset(viper::managers::StreamType type, uint32_t bufferSize); + std::string getRepresentationID(viper::managers::StreamType type); + std::string getPublishTime(); + std::string getMinimumUpdatePeriod(); + std::vector getRepresentations(viper::managers::StreamType type); + std::string getMediaPresentationDuration(); + dash::mpd::IRepresentation* getRepresentationAt(viper::managers::StreamType type, int index); + void setRepresentation(viper::managers::StreamType type, dash::mpd::IRepresentation* rep); + std::string getRepresentationIDWithoutLock(viper::managers::StreamType type); + libdash::framework::input::MediaObject* getInitSegmentWithoutLock(viper::managers::StreamType type); + std::string getAvailabilityStarttime(); + std::string getTimeShiftBufferDepth(); + std::string getTypeWithoutLock(); + std::string getMinimumUpdatePeriodWithoutLock(); + uint32_t getFetchTime(); + void settingsChanged(int period, int videoAdaptationSet, int videoRepresentation, int audioAdaptationSet, int audioRepresentation); + float onFirstDownloadMPD(viper::IViperGui *gui); + void setIsStopping(bool isStopping); + +private: + RepresentationStreamType determineRepresentationStreamType(dash::mpd::IRepresentation *representation, dash::mpd::IAdaptationSet* adaptationSet, dash::mpd::IPeriod* period); + + dash::mpd::IMPD *mpd; + mutable CRITICAL_SECTION monitorMutex; + mutable CONDITION_VARIABLE mpdUpdate; + dash::mpd::IPeriod *period; + dash::mpd::IAdaptationSet *videoAdaptationSet; + dash::mpd::IRepresentation *videoRepresentation; + dash::mpd::IAdaptationSet *audioAdaptationSet; + dash::mpd::IRepresentation *audioRepresentation; + std::map *videoRepresentations; + std::map *audioRepresentations; + uint32_t videoSegmentOffset; + uint32_t audioSegmentOffset; + size_t videoSegmentNumber; + size_t audioSegmentNumber; + bool isStopping; +}; +} +} +} + +#endif /* LIBDASH_FRAMEWORK_MPD_MPDWRAPPER_H_ */ + diff --git a/MPD/RepresentationStreamFactory.cpp b/MPD/RepresentationStreamFactory.cpp index b84bf558..e5c57ddd 100644 --- a/MPD/RepresentationStreamFactory.cpp +++ b/MPD/RepresentationStreamFactory.cpp @@ -14,14 +14,28 @@ using namespace libdash::framework::mpd; using namespace dash::mpd; -IRepresentationStream* RepresentationStreamFactory::create(RepresentationStreamType type, IMPD *mpd, IPeriod *period, IAdaptationSet *adaptationSet, IRepresentation *representation) +IRepresentationStream* RepresentationStreamFactory::create(viper::managers::StreamType streamType, libdash::framework::mpd::RepresentationStreamType type, libdash::framework::mpd::MPDWrapper *mpdWrapper, dash::mpd::IPeriod *period, dash::mpd::IAdaptationSet *adaptationSet, dash::mpd::IRepresentation *representation, dash::mpd::IMPD* mpd) { - switch(type) + if(mpd) { - case SingleMediaSegment: return new SingleMediaSegmentStream(mpd, period, adaptationSet, representation); - case SegmentList: return new SegmentListStream (mpd, period, adaptationSet, representation); - case SegmentTemplate: return new SegmentTemplateStream (mpd, period, adaptationSet, representation); + switch(type) + { + case SingleMediaSegment: return new SingleMediaSegmentStream(streamType, mpdWrapper, period, adaptationSet, representation,mpd); + case SegmentList: return new SegmentListStream (streamType, mpdWrapper, period, adaptationSet, representation,mpd); + case SegmentTemplate: return new SegmentTemplateStream (streamType, mpdWrapper, period, adaptationSet, representation,mpd); - default: return NULL; + default: return NULL; + } + } + else + { + switch(type) + { + case SingleMediaSegment: return new SingleMediaSegmentStream(streamType, mpdWrapper, period, adaptationSet, representation); + case SegmentList: return new SegmentListStream (streamType, mpdWrapper, period, adaptationSet, representation); + case SegmentTemplate: return new SegmentTemplateStream (streamType, mpdWrapper, period, adaptationSet, representation); + + default: return NULL; + } } } diff --git a/MPD/RepresentationStreamFactory.h b/MPD/RepresentationStreamFactory.h index 22c70b96..e3eb137c 100644 --- a/MPD/RepresentationStreamFactory.h +++ b/MPD/RepresentationStreamFactory.h @@ -12,6 +12,8 @@ #ifndef LIBDASH_FRAMEWORK_MPD_RERPRESENTATIONSTREAMFACTORY_H_ #define LIBDASH_FRAMEWORK_MPD_RERPRESENTATIONSTREAMFACTORY_H_ + +#include "../MPD/MPDWrapper.h" #include "IRepresentationStream.h" #include "SingleMediaSegmentStream.h" #include "SegmentListStream.h" @@ -27,8 +29,9 @@ namespace mpd class RepresentationStreamFactory { public: - static IRepresentationStream* create(libdash::framework::mpd::RepresentationStreamType type, dash::mpd::IMPD *mpd, dash::mpd::IPeriod *period, - dash::mpd::IAdaptationSet *adaptationSet, dash::mpd::IRepresentation *representation); + static IRepresentationStream* create(viper::managers::StreamType streamType, libdash::framework::mpd::RepresentationStreamType type, libdash::framework::mpd::MPDWrapper *mpdWrapper, dash::mpd::IPeriod *period, + dash::mpd::IAdaptationSet *adaptationSet, dash::mpd::IRepresentation *representation, dash::mpd::IMPD* mpd = NULL); +// static IRepresentationStream* create(viper::managers::StreamType streamType, libdash::framework::mpd::RepresentationStreamType type, dash::mpd::MPDWrapper *mpdWrapper); }; } diff --git a/MPD/SegmentListStream.cpp b/MPD/SegmentListStream.cpp index 3a475e71..c3530086 100644 --- a/MPD/SegmentListStream.cpp +++ b/MPD/SegmentListStream.cpp @@ -14,10 +14,19 @@ using namespace dash::mpd; using namespace libdash::framework::mpd; -SegmentListStream::SegmentListStream(IMPD *mpd, IPeriod *period, IAdaptationSet *adaptationSet, IRepresentation *representation) : - AbstractRepresentationStream (mpd, period, adaptationSet, representation) +SegmentListStream::SegmentListStream(viper::managers::StreamType type, MPDWrapper *mpdWrapper, dash::mpd::IPeriod *period, dash::mpd::IAdaptationSet *adaptationSet, dash::mpd::IRepresentation *representation) : + AbstractRepresentationStream (type, mpdWrapper, period, adaptationSet, representation) { - this->baseUrls = BaseUrlResolver::resolveBaseUrl(mpd, period, adaptationSet, 0, 0, 0); + this->baseUrls = BaseUrlResolver::resolveBaseUrl(type, mpdWrapper, 0, 0, 0); +// this->baseUrls = mpdWrapper->resolveBaseUrl(type, mpdWrapper, 0, 0, 0); + this->segmentList = findSegmentList(); +} + +SegmentListStream::SegmentListStream(viper::managers::StreamType type, MPDWrapper *mpdWrapper, dash::mpd::IPeriod *period, dash::mpd::IAdaptationSet *adaptationSet, dash::mpd::IRepresentation *representation, dash::mpd::IMPD* mpd) : + AbstractRepresentationStream (type, mpdWrapper, period, adaptationSet, representation) +{ + this->baseUrls = BaseUrlResolver::resolveBaseUrl(type, mpdWrapper, 0, 0, 0, mpd); +// this->baseUrls = mpdWrapper->resolveBaseUrl(type, mpdWrapper, 0, 0, 0); this->segmentList = findSegmentList(); } @@ -28,16 +37,19 @@ SegmentListStream::~SegmentListStream() ISegment* SegmentListStream::getInitializationSegment() { if (this->segmentList->GetInitialization()) + { return this->segmentList->GetInitialization()->ToSegment(this->baseUrls); - + } return NULL; } ISegment* SegmentListStream::getIndexSegment(size_t segmentNumber) { if (this->segmentList->GetSegmentURLs().size() > segmentNumber) + { + this->mpdWrapper->releaseLock(); return this->segmentList->GetSegmentURLs().at(segmentNumber)->ToIndexSegment(this->baseUrls); - + } return NULL; } diff --git a/MPD/SegmentListStream.h b/MPD/SegmentListStream.h index 323852f0..264ac9cc 100644 --- a/MPD/SegmentListStream.h +++ b/MPD/SegmentListStream.h @@ -12,7 +12,7 @@ #ifndef LIBDASH_FRAMEWORK_MPD_SEGMENTLISTSTREAM_H_ #define LIBDASH_FRAMEWORK_MPD_SEGMENTLISTSTREAM_H_ -#include "IMPD.h" +#include "MPDWrapper.h" #include "AbstractRepresentationStream.h" #include "ISegment.h" #include "ISegmentList.h" @@ -26,7 +26,9 @@ namespace mpd class SegmentListStream: public AbstractRepresentationStream { public: - SegmentListStream(dash::mpd::IMPD *mpd, dash::mpd::IPeriod *period, dash::mpd::IAdaptationSet *adaptationSet, dash::mpd::IRepresentation *representation); + SegmentListStream(viper::managers::StreamType type, MPDWrapper *mpdWrapper, dash::mpd::IPeriod *period, dash::mpd::IAdaptationSet *adaptationSet, dash::mpd::IRepresentation *representation); + SegmentListStream(viper::managers::StreamType type, MPDWrapper *mpdWrapper, dash::mpd::IPeriod *period, dash::mpd::IAdaptationSet *adaptationSet, dash::mpd::IRepresentation *representation, dash::mpd::IMPD* mpd); +// SegmentListStream(viper::managers::StreamType type, dash::mpd::MPDWrapper *mpdWrapper); virtual ~SegmentListStream(); virtual dash::mpd::ISegment* getInitializationSegment(); @@ -38,8 +40,9 @@ public: virtual uint32_t getAverageSegmentDuration(); private: - dash::mpd::ISegmentList* findSegmentList(); - dash::mpd::ISegmentList *segmentList; + dash::mpd::ISegmentList *findSegmentList(); + + dash::mpd::ISegmentList *segmentList; }; } diff --git a/MPD/SegmentTemplateStream.cpp b/MPD/SegmentTemplateStream.cpp index 66004294..a62a9bab 100644 --- a/MPD/SegmentTemplateStream.cpp +++ b/MPD/SegmentTemplateStream.cpp @@ -14,15 +14,28 @@ using namespace dash::mpd; using namespace libdash::framework::mpd; -SegmentTemplateStream::SegmentTemplateStream(IMPD *mpd, IPeriod *period, IAdaptationSet *adaptationSet, IRepresentation *representation) : - AbstractRepresentationStream (mpd, period, adaptationSet, representation) +SegmentTemplateStream::SegmentTemplateStream(viper::managers::StreamType type, MPDWrapper *mpdWrapper, IPeriod *period, IAdaptationSet *adaptationSet, IRepresentation *representation) : + AbstractRepresentationStream (type, mpdWrapper, period, adaptationSet, representation) { - this->baseUrls = BaseUrlResolver::resolveBaseUrl(mpd, period, adaptationSet, 0, 0, 0); +// this->baseUrls = BaseUrlResolver::resolveBaseUrl(mpd, period, adaptationSet, 0, 0, 0); + this->baseUrls = BaseUrlResolver::resolveBaseUrl(type, mpdWrapper, 0, 0, 0); this->segmentTemplate = findSegmentTemplate(); this->inSync = false; this->currentSegment = 0; calculateSegmentStartTimes(); } + +SegmentTemplateStream::SegmentTemplateStream(viper::managers::StreamType type, MPDWrapper *mpdWrapper, IPeriod *period, IAdaptationSet *adaptationSet, IRepresentation *representation, IMPD* mpd) : + AbstractRepresentationStream (type, mpdWrapper, period, adaptationSet, representation) +{ +// this->baseUrls = BaseUrlResolver::resolveBaseUrl(mpd, period, adaptationSet, 0, 0, 0); + this->baseUrls = BaseUrlResolver::resolveBaseUrl(type, mpdWrapper, 0, 0, 0, mpd); + this->segmentTemplate = findSegmentTemplate(); + this->inSync = false; + this->currentSegment = 0; + calculateSegmentStartTimes(); +} + SegmentTemplateStream::~SegmentTemplateStream() { } @@ -55,7 +68,14 @@ ISegment* SegmentTemplateStream::getMediaSegment(size_t segmentNumber) { /* time-based template */ if (this->segmentTemplate->GetSegmentTimeline()) - { + {//Get the one at segmentNumber + if(this->segmentStartTimes.size() > segmentNumber) + return this->segmentTemplate->GetMediaSegmentFromTime(baseUrls, representation->GetId(), representation->GetBandwidth(), this->segmentStartTimes.at(segmentNumber)); + else + return NULL; + +//The following is to be used if you wish to start directly from the right time +/* { if(this->inSync) { this->currentSegment++; @@ -86,7 +106,7 @@ ISegment* SegmentTemplateStream::getMediaSegment(size_t segmentNumber) this->currentSegment = segNumber; return this->segmentTemplate->GetMediaSegmentFromTime(baseUrls, representation->GetId(), representation->GetBandwidth(), this->segmentStartTimes.at(this->currentSegment)); } - return NULL; + return NULL; */ } /* number-based template */ @@ -115,9 +135,9 @@ uint32_t SegmentTemplateStream::getSize() uint32_t numberOfSegments = 0; double mediaPresentationDuration = 0; - if (this->mpd->GetType() == "static") + if (this->mpdWrapper->getTypeWithoutLock() == "static") { - mediaPresentationDuration = TimeResolver::getDurationInSec(this->mpd->GetMediaPresentationDuration()); + mediaPresentationDuration = TimeResolver::getDurationInSec(this->mpdWrapper->getMediaPresentationDuration()); numberOfSegments = (uint32_t) ceil(mediaPresentationDuration / (this->segmentTemplate->GetDuration() / this->segmentTemplate->GetTimescale())); } else @@ -194,3 +214,24 @@ void SegmentTemplateStream::calculateSegmentStartTimes() } this->averageDuration = totalDuration / numOfTimelines; } + +uint32_t SegmentTemplateStream::getTime(size_t segmentNumber) +{ + if(segmentNumber < this->segmentStartTimes.size()) + return this->segmentStartTimes.at(segmentNumber); + else + return 0; +} + +size_t SegmentTemplateStream::getSegmentNumber(uint32_t time) +{ + size_t i; + for(i = 0; i < this->segmentStartTimes.size(); i ++) + { + if(time <= this->segmentStartTimes.at(i)) + { + break; + } + } + return i; +} diff --git a/MPD/SegmentTemplateStream.h b/MPD/SegmentTemplateStream.h index f27b77fb..68d4f848 100644 --- a/MPD/SegmentTemplateStream.h +++ b/MPD/SegmentTemplateStream.h @@ -14,7 +14,7 @@ #include -#include "IMPD.h" +#include "MPDWrapper.h" #include "AbstractRepresentationStream.h" #include "ISegment.h" #include "ISegmentTemplate.h" @@ -28,7 +28,8 @@ namespace mpd class SegmentTemplateStream: public AbstractRepresentationStream { public: - SegmentTemplateStream(dash::mpd::IMPD *mpd, dash::mpd::IPeriod *period, dash::mpd::IAdaptationSet *adaptationSet, dash::mpd::IRepresentation *representation); + SegmentTemplateStream(viper::managers::StreamType type, libdash::framework::mpd::MPDWrapper *mpdWrapper, dash::mpd::IPeriod *period, dash::mpd::IAdaptationSet *adaptationSet, dash::mpd::IRepresentation *representation); + SegmentTemplateStream(viper::managers::StreamType type, libdash::framework::mpd::MPDWrapper *mpdWrapper, dash::mpd::IPeriod *period, dash::mpd::IAdaptationSet *adaptationSet, dash::mpd::IRepresentation *representation, dash::mpd::IMPD* mpd); virtual ~SegmentTemplateStream(); virtual dash::mpd::ISegment* getInitializationSegment(); @@ -39,6 +40,8 @@ public: virtual uint32_t getSize(); virtual uint32_t getAverageSegmentDuration(); virtual uint32_t getTimescale(); + virtual uint32_t getTime(size_t segmentNumber); + virtual size_t getSegmentNumber(uint32_t time); private: dash::mpd::ISegmentTemplate* findSegmentTemplate(); diff --git a/MPD/SingleMediaSegmentStream.cpp b/MPD/SingleMediaSegmentStream.cpp index ff4540e2..39301928 100644 --- a/MPD/SingleMediaSegmentStream.cpp +++ b/MPD/SingleMediaSegmentStream.cpp @@ -14,10 +14,16 @@ using namespace dash::mpd; using namespace libdash::framework::mpd; -SingleMediaSegmentStream::SingleMediaSegmentStream(IMPD *mpd, IPeriod *period, IAdaptationSet *adaptationSet, IRepresentation *representation) : - AbstractRepresentationStream (mpd, period, adaptationSet, representation) +SingleMediaSegmentStream::SingleMediaSegmentStream(viper::managers::StreamType type, MPDWrapper *mpdWrapper, IPeriod *period, IAdaptationSet *adaptationSet, IRepresentation *representation) : + AbstractRepresentationStream (type, mpdWrapper, period, adaptationSet, representation) { - this->baseUrls = BaseUrlResolver::resolveBaseUrl(mpd, period, adaptationSet, 0, 0, 0); + this->baseUrls = BaseUrlResolver::resolveBaseUrl(type, mpdWrapper, 0, 0, 0); +} + +SingleMediaSegmentStream::SingleMediaSegmentStream(viper::managers::StreamType type, MPDWrapper *mpdWrapper, IPeriod *period, IAdaptationSet *adaptationSet, IRepresentation *representation, IMPD* mpd) : + AbstractRepresentationStream (type, mpdWrapper, period, adaptationSet, representation) +{ + this->baseUrls = BaseUrlResolver::resolveBaseUrl(type, mpdWrapper, 0, 0, 0, mpd); } SingleMediaSegmentStream::~SingleMediaSegmentStream() { diff --git a/MPD/SingleMediaSegmentStream.h b/MPD/SingleMediaSegmentStream.h index afc919ee..e619a7f8 100644 --- a/MPD/SingleMediaSegmentStream.h +++ b/MPD/SingleMediaSegmentStream.h @@ -12,7 +12,7 @@ #ifndef LIBDASH_FRAMEWORK_MPD_SINGLEMEDIASEGMENTSTREAM_H_ #define LIBDASH_FRAMEWORK_MPD_SINGLEMEDIASEGMENTSTREAM_H_ -#include "IMPD.h" +#include "MPDWrapper.h" #include "AbstractRepresentationStream.h" #include "ISegment.h" @@ -25,7 +25,8 @@ namespace mpd class SingleMediaSegmentStream: public AbstractRepresentationStream { public: - SingleMediaSegmentStream(dash::mpd::IMPD *mpd, dash::mpd::IPeriod *period, dash::mpd::IAdaptationSet *adaptationSet, dash::mpd::IRepresentation *representation); + SingleMediaSegmentStream(viper::managers::StreamType type, libdash::framework::mpd::MPDWrapper *mpdWrapper, dash::mpd::IPeriod *period, dash::mpd::IAdaptationSet *adaptationSet, dash::mpd::IRepresentation *representation); + SingleMediaSegmentStream(viper::managers::StreamType type, libdash::framework::mpd::MPDWrapper *mpdWrapper, dash::mpd::IPeriod *period, dash::mpd::IAdaptationSet *adaptationSet, dash::mpd::IRepresentation *representation, dash::mpd::IMPD* mpd); virtual ~SingleMediaSegmentStream(); virtual dash::mpd::ISegment* getInitializationSegment(); -- cgit 1.2.3-korg