aboutsummaryrefslogtreecommitdiffstats
path: root/MPD/MPDWrapper.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'MPD/MPDWrapper.cpp')
-rw-r--r--MPD/MPDWrapper.cpp1098
1 files changed, 1098 insertions, 0 deletions
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<IAdaptationSet *> 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<IAdaptationSet *> 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<IRepresentation *> 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<IRepresentation *> 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<dash::mpd::IRepresentation *, IRepresentationStream *> *representations = NULL;
+ EnterCriticalSection(&this->monitorMutex);
+
+ switch(type)
+ {
+ case viper::managers::StreamType::AUDIO:
+ if(this->audioRepresentations == NULL)
+ this->audioRepresentations = new std::map<dash::mpd::IRepresentation *, IRepresentationStream *>();
+ 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<dash::mpd::IRepresentation *, IRepresentationStream *>();
+ 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<dash::mpd::IRepresentation *, IRepresentationStream *> *representations = NULL;
+
+ switch(type)
+ {
+ case viper::managers::StreamType::AUDIO:
+ if(this->audioRepresentations == NULL)
+ this->audioRepresentations = new std::map<dash::mpd::IRepresentation *, IRepresentationStream *>();
+ 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<dash::mpd::IRepresentation *, IRepresentationStream *>();
+ 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<dash::mpd::IRepresentation *, IRepresentationStream *> *representations = NULL;
+
+ switch(type)
+ {
+ case viper::managers::StreamType::AUDIO:
+ if(this->audioRepresentations == NULL)
+ this->audioRepresentations = new std::map<dash::mpd::IRepresentation *, IRepresentationStream *>();
+ 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<dash::mpd::IRepresentation *, IRepresentationStream *>();
+ 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<dash::mpd::IRepresentation *, IRepresentationStream *> *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<IRepresentation *, IRepresentationStream *>::iterator iter;
+ for (iter = representations->begin(); iter != representations->end(); ++iter)
+ {
+ delete(iter->second);
+ }
+ representations->clear();
+}
+
+std::vector<dash::mpd::IBaseUrl *> MPDWrapper::resolveBaseUrl (viper::managers::StreamType type, size_t mpdBaseUrl, size_t periodBaseUrl, size_t adaptationSetBaseUrl)
+{
+
+ IAdaptationSet *adaptationSet = NULL;
+ std::vector<dash::mpd::IBaseUrl *> 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<dash::mpd::IBaseUrl *> MPDWrapper::resolveBaseUrl (viper::managers::StreamType type, size_t mpdBaseUrl, size_t periodBaseUrl, size_t adaptationSetBaseUrl, IMPD* mpd)
+{
+
+ IAdaptationSet *adaptationSet = NULL;
+ std::vector<dash::mpd::IBaseUrl *> 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<dash::mpd::IRepresentation *, IRepresentationStream *> *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<dash::mpd::IRepresentation *, IRepresentationStream *> *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<dash::mpd::IRepresentation *, IRepresentationStream *> *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<dash::mpd::IRepresentation *, IRepresentationStream *> *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<IRepresentation *> MPDWrapper::getRepresentations (viper::managers::StreamType type)
+{
+ std::vector<IRepresentation *> 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<dash::mpd::IRepresentation *, IRepresentationStream *> *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<IAdaptationSet *> videoAdaptationSets = AdaptationSetHelper::getVideoAdaptationSets(this->period);
+ std::vector<IAdaptationSet *> 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);
+}