From 872b2e96a111d6da5f821a6dc61b923f9913b3f3 Mon Sep 17 00:00:00 2001 From: Jacques SAMAIN Date: Fri, 1 Jun 2018 19:56:33 +0200 Subject: Several corrections: *effectively take into account live MPD *Fix several bugs Change-Id: I9b925f222653d2d196b09b4e96cb15119ec8af44 Signed-off-by: Jacques SAMAIN --- Adaptation/AdapTech.cpp | 44 ++++++- Adaptation/AdapTech.h | 1 + Adaptation/Panda.cpp | 4 +- Input/DASHManager.cpp | 4 + Input/DASHManager.h | 1 + Input/DASHReceiver.cpp | 41 +++++- Input/DASHReceiver.h | 2 + Input/IDASHManagerObserver.h | 1 + Input/IDASHReceiverObserver.h | 1 + MPD/AbstractRepresentationStream.h | 2 +- MPD/IRepresentationStream.h | 2 +- MPD/MPDWrapper.cpp | 262 ++++++++++++++++++++----------------- MPD/MPDWrapper.h | 9 +- MPD/SegmentListStream.cpp | 8 +- MPD/SegmentListStream.h | 2 +- MPD/SegmentTemplateStream.cpp | 5 +- MPD/SegmentTemplateStream.h | 2 +- MPD/SingleMediaSegmentStream.cpp | 2 +- MPD/SingleMediaSegmentStream.h | 2 +- Managers/IStreamObserver.h | 1 + Managers/MultimediaManager.cpp | 37 +----- Managers/MultimediaManager.h | 2 - Managers/MultimediaStream.cpp | 8 ++ Managers/MultimediaStream.h | 1 + UI/ViperGui.cpp | 4 +- 25 files changed, 255 insertions(+), 193 deletions(-) diff --git a/Adaptation/AdapTech.cpp b/Adaptation/AdapTech.cpp index dc88fae6..6f248b4d 100644 --- a/Adaptation/AdapTech.cpp +++ b/Adaptation/AdapTech.cpp @@ -82,12 +82,6 @@ void AdapTechAdaptation::notifyBitrateChange() this->multimediaManager->setVideoQuality(); else this->multimediaManager->setAudioQuality(); - //Should Abort is done here to avoid race condition with DASHReceiver::DoBuffering() -// if(this->shouldAbort) -// { -// this->multimediaManager->shouldAbort((this->type == viper::managers::StreamType::VIDEO)); -// } -// this->shouldAbort = false; } uint64_t AdapTechAdaptation::getBitrate() @@ -96,6 +90,44 @@ uint64_t AdapTechAdaptation::getBitrate() } void AdapTechAdaptation::setBitrate(uint32_t bufferFill) +{ + std::vector representations; + representations = this->mpdWrapper->getRepresentations(this->type); + bool flagIsSet = this->mpdWrapper->getSegmentIsSetFlag(this->type); + int mySetQuality = this->mpdWrapper->getSegmentQuality(this->type); + + if(flagIsSet) + { + Debug("Adaptech:\tFor %s:\tbuffer_level: %f, instantaneousBw: %lu, AverageBW: %lu,already set: %d\n",(this->type == viper::managers::StreamType::VIDEO) ? "video" : "audio", (double)bufferFill/100, this->instantBw, this->averageBw , this->myQuality); + + if(bufferFill < this->reservoirThreshold) + { + if(mySetQuality == -1) + { + mySetQuality = this->myQuality; + this->myQuality = 0; + this->representation = representations.at(this->myQuality); + Debug("Adaptech:\tFor %s: buffer level too low, going to panic mode, old quality: %d\n",(this->type == viper::managers::StreamType::VIDEO) ? "video" : "audio", mySetQuality); + this->mpdWrapper->setSegmentQuality(this->type, mySetQuality); + } + } + else + { + if(mySetQuality != -1) + { + this->myQuality = mySetQuality; + Debug("AdaptechNA:\tFor %s: buffer level high enough, restoring old computed quality: %d\n",(this->type == viper::managers::StreamType::VIDEO) ? "video" : "audio", mySetQuality); + } + this->representation = representations.at(this->myQuality); + } + } + else + { + this->setBitrateOption1(bufferFill); + this->mpdWrapper->setSegmentIsSetFlag(this->type, true); + } +} +void AdapTechAdaptation::setBitrateOption1(uint32_t bufferFill) { uint32_t phi1, phi2; std::vector representations; diff --git a/Adaptation/AdapTech.h b/Adaptation/AdapTech.h index c7f4e33c..24ae2231 100644 --- a/Adaptation/AdapTech.h +++ b/Adaptation/AdapTech.h @@ -41,6 +41,7 @@ public: virtual void bufferUpdate(uint32_t bufferFill, int maxC); virtual void dLTimeUpdate(double time); void setBitrate(uint32_t bufferFill); + void setBitrateOption1(uint32_t bufferFill); uint64_t getBitrate(); virtual void setMultimediaManager(viper::managers::IMultimediaManagerBase *_mmManager); void notifyBitrateChange(); diff --git a/Adaptation/Panda.cpp b/Adaptation/Panda.cpp index e0c19b27..a8c2d887 100644 --- a/Adaptation/Panda.cpp +++ b/Adaptation/Panda.cpp @@ -64,7 +64,7 @@ PandaAdaptation::PandaAdaptation(StreamType type, MPDWrapper *mpdWrapper, struct // Retrieve the available bitrates this->mpdWrapper->acquireLock(); std::vector representations = this->mpdWrapper->getRepresentations(this->type); - + this->mpdWrapper->releaseLock(); this->availableBitrates.clear(); Debug("PANDA Available Bitrates...\n"); for(size_t i = 0; i < representations.size(); i++) @@ -76,7 +76,7 @@ PandaAdaptation::PandaAdaptation(StreamType type, MPDWrapper *mpdWrapper, struct this->representation = representations.at(0); this->currentBitrate = (uint64_t) this->representation->GetBandwidth(); - Debug("Panda parameters: K= %f, Bmin = %f, alpha = %f, beta = %f, W = %f\n", param_K, param_Bmin, param_Alpha, param_Beta, param_W); + Debug("Panda parameters: K= %f, Bmin = %f, alpha = %f, beta = %f, W = %f \n", param_K, param_Bmin, param_Alpha, param_Beta, param_W); } PandaAdaptation::~PandaAdaptation() { diff --git a/Input/DASHManager.cpp b/Input/DASHManager.cpp index 0c393353..b3ff8305 100644 --- a/Input/DASHManager.cpp +++ b/Input/DASHManager.cpp @@ -160,3 +160,7 @@ void DASHManager::onBufferStateChanged(BufferType type, uint32_t fillstateInPerc if(this->adaptationLogic->isBufferBased()) this->receiver->OnSegmentBufferStateChanged(fillstateInPercent, maxC); } +void DASHManager::fetchMPD() +{ + this->multimediaStream->fetchMPD(); +} diff --git a/Input/DASHManager.h b/Input/DASHManager.h index 3b9bf005..4bd301e7 100644 --- a/Input/DASHManager.h +++ b/Input/DASHManager.h @@ -61,6 +61,7 @@ public: void setTargetDownloadingTime(double); MediaObject* getSegment(); void onBufferStateChanged(BufferType type, uint32_t fillstateInPercent, int maxC); + void fetchMPD(); private: float beta; diff --git a/Input/DASHReceiver.cpp b/Input/DASHReceiver.cpp index 74415bfa..0d77bdf2 100644 --- a/Input/DASHReceiver.cpp +++ b/Input/DASHReceiver.cpp @@ -42,7 +42,8 @@ DASHReceiver::DASHReceiver (viper::managers::StreamType type, MPDWrappe isLooping (false), beta (beta), drop (drop), - bufferingThread (NULL) + bufferingThread (NULL), + mpdFetcherThread (NULL) { readMax = 32768; readBuffer = (uint8_t*)malloc(sizeof(uint8_t)*readMax); @@ -95,6 +96,15 @@ bool DASHReceiver::Start () this->isBuffering = false; return false; } + //if dynamic, set up the fetching loop + if(!strcmp(this->mpdWrapper->getType().c_str(), "dynamic")) + { + this->mpdFetcherThread = createThreadPortable(DoMPDFetching, this); + if(this->mpdFetcherThread == NULL) + { + std::cout << "mpd Fetcher thread is NULL. Need to think of how to handle this?" << std::endl; + } + } return true; } void DASHReceiver::Stop() @@ -260,8 +270,8 @@ void DASHReceiver::NotifyCheckedAdaptationLogic() //Is only called when this->adaptationLogic->IsBufferBased void DASHReceiver::OnSegmentBufferStateChanged(uint32_t fillstateInPercent, int maxC) { - this->adaptationLogic->bufferUpdate(this->observer->getBufferLevel(), maxC); this->bufferLevelAtUpdate = this->observer->getBufferLevel(); + this->adaptationLogic->bufferUpdate(this->bufferLevelAtUpdate, maxC); } void DASHReceiver::OnEOS(bool value) { @@ -274,14 +284,14 @@ bool DASHReceiver::PushBack(MediaObject *mediaObject) mediaObject->AddInitSegment(init); //TODO the read should be in a function - //Grab the infos for the analytics: bitrate, fps + //Grab the infos for the analytics: bitrate, bufferLevel uint32_t bitrate = 0; - int fps = 0; + int bufferLevel = 0; uint32_t quality = 0; bitrate = mediaObject->GetRepresentationBandwidth(); quality = mediaObject->GetRepresentationHeight(); - fps = this->bufferLevelAtUpdate; - this->observer->notifyStatistics((int)this->segmentNumber - 1, bitrate, fps, quality); + bufferLevel = this->bufferLevelAtUpdate; + this->observer->notifyStatistics((int)this->segmentNumber - 1, bitrate, bufferLevel, quality); return(this->buffer->pushBack(mediaObject)); } @@ -335,6 +345,25 @@ void* DASHReceiver::DoBuffering (void *recei return NULL; } +void* DASHReceiver::DoMPDFetching (void* receiver) +{ + DASHReceiver* dashReceiver = (DASHReceiver*) receiver; + uint32_t currTime = TimeResolver::getCurrentTimeInSec(); + uint32_t publishedTime = TimeResolver::getUTCDateTimeInSec(dashReceiver->mpdWrapper->getPublishTime()); + uint32_t period = TimeResolver::getDurationInSec(dashReceiver->mpdWrapper->getMinimumUpdatePeriod()); + while(dashReceiver->isBuffering) + { + while(dashReceiver->isBuffering && currTime < publishedTime + period) + { + usleep(((publishedTime + period) - currTime) * 1000000); + currTime = TimeResolver::getCurrentTimeInSec(); + } + dashReceiver->observer->fetchMPD(); + publishedTime = TimeResolver::getUTCDateTimeInSec(dashReceiver->mpdWrapper->getPublishTime()); + period = TimeResolver::getDurationInSec(dashReceiver->mpdWrapper->getMinimumUpdatePeriod()); + } +} + //can Push video to buffer in the renderer bool DASHReceiver::CanPush () { diff --git a/Input/DASHReceiver.h b/Input/DASHReceiver.h index a6db0382..e5b48adf 100644 --- a/Input/DASHReceiver.h +++ b/Input/DASHReceiver.h @@ -107,6 +107,7 @@ private: IICNConnection *conn; IICNConnection *initConn; THREAD_HANDLE bufferingThread; + THREAD_HANDLE mpdFetcherThread; bool isBuffering; bool icn; double icnAlpha; @@ -122,6 +123,7 @@ private: void DownloadInitSegmentWithoutLock(); bool InitSegmentExists(std::string rep); static void* DoBuffering(void *receiver); + static void* DoMPDFetching(void * data); }; } } diff --git a/Input/IDASHManagerObserver.h b/Input/IDASHManagerObserver.h index 0f2d95df..57f15726 100644 --- a/Input/IDASHManagerObserver.h +++ b/Input/IDASHManagerObserver.h @@ -33,6 +33,7 @@ public: virtual void notifyQualityDownloading (uint32_t quality) = 0; virtual bool canPush() = 0; virtual int getBufferLevel() = 0; + virtual void fetchMPD() = 0; }; } } diff --git a/Input/IDASHReceiverObserver.h b/Input/IDASHReceiverObserver.h index 0a334aa2..f6a2baa1 100644 --- a/Input/IDASHReceiverObserver.h +++ b/Input/IDASHReceiverObserver.h @@ -28,6 +28,7 @@ public: virtual void notifyQualityDownloading(uint32_t quality) = 0; virtual bool canPush() = 0; virtual int getBufferLevel() = 0; + virtual void fetchMPD() = 0; }; } } diff --git a/MPD/AbstractRepresentationStream.h b/MPD/AbstractRepresentationStream.h index da847c3c..113720ed 100644 --- a/MPD/AbstractRepresentationStream.h +++ b/MPD/AbstractRepresentationStream.h @@ -43,7 +43,7 @@ public: virtual dash::mpd::ISegment* getInitializationSegment() = 0; virtual dash::mpd::ISegment* getIndexSegment(size_t segmentNumber) = 0; - virtual dash::mpd::ISegment* getMediaSegment(size_t segmentNumber, uint64_t& segmentDuration) = 0; + virtual dash::mpd::ISegment* getMediaSegment(size_t segmentNumber) = 0; virtual dash::mpd::ISegment* getBitstreamSwitchingSegment() = 0; virtual RepresentationStreamType getStreamType() = 0; diff --git a/MPD/IRepresentationStream.h b/MPD/IRepresentationStream.h index 124216ba..bf8b08c4 100644 --- a/MPD/IRepresentationStream.h +++ b/MPD/IRepresentationStream.h @@ -35,7 +35,7 @@ public: virtual dash::mpd::ISegment* getInitializationSegment() = 0; virtual dash::mpd::ISegment* getIndexSegment(size_t segmentNumber) = 0; - virtual dash::mpd::ISegment* getMediaSegment(size_t segmentNumber, uint64_t& segmentDuration) = 0; + virtual dash::mpd::ISegment* getMediaSegment(size_t segmentNumber) = 0; virtual dash::mpd::ISegment* getBitstreamSwitchingSegment() = 0; virtual RepresentationStreamType getStreamType() = 0; virtual uint32_t getSize() = 0; diff --git a/MPD/MPDWrapper.cpp b/MPD/MPDWrapper.cpp index 0b1d9596..1dca34fb 100644 --- a/MPD/MPDWrapper.cpp +++ b/MPD/MPDWrapper.cpp @@ -28,8 +28,7 @@ MPDWrapper::MPDWrapper(IMPD *mpd): videoSegmentOffset (0), audioSegmentOffset (0), videoSegmentNumber (0), - audioSegmentNumber (0), - hasReachedEndOfList (false) + audioSegmentNumber (0) { InitializeConditionVariable (&this->mpdUpdate); @@ -52,7 +51,7 @@ void MPDWrapper::updateMPD (IMPD* mpd) //Assumptions here: // *only one period in the MPD // *only triggered if using SegmentTimeline dynamic MPD - EnterCriticalSection(&this->monitorMutex); + this->acquireLock(); this->period = mpd->GetPeriods().at(0); this->findVideoAdaptationSet(mpd); this->findAudioAdaptationSet(mpd); @@ -61,7 +60,7 @@ void MPDWrapper::updateMPD (IMPD* mpd) delete(this->mpd); this->mpd = mpd; WakeAllConditionVariable(&this->mpdUpdate); - LeaveCriticalSection(&this->monitorMutex); + this->releaseLock(); } void MPDWrapper::findVideoAdaptationSet (IMPD* mpd) @@ -186,16 +185,16 @@ void MPDWrapper::findAudioRepresentation (IMPD* mpd) std::string MPDWrapper::getType () { std::string type; - EnterCriticalSection(&this->monitorMutex); + this->acquireLock(); type = this->mpd->GetType(); - LeaveCriticalSection(&this->monitorMutex); + this->releaseLock(); return type; } void MPDWrapper::reInit (viper::managers::StreamType type) { - EnterCriticalSection(&this->monitorMutex); + this->acquireLock(); switch(type) { case viper::managers::StreamType::VIDEO: @@ -215,30 +214,30 @@ void MPDWrapper::reInit (viper::managers::StreamType type) default: break; } - LeaveCriticalSection(&this->monitorMutex); + this->releaseLock(); } bool MPDWrapper::hasVideoAdaptationSetAndVideoRepresentation () { - EnterCriticalSection(&this->monitorMutex); + this->acquireLock(); if(this->videoAdaptationSet && this->videoRepresentation) { - LeaveCriticalSection(&this->monitorMutex); + this->releaseLock(); return 1; } - LeaveCriticalSection(&this->monitorMutex); + this->releaseLock(); return 0; } bool MPDWrapper::hasAudioAdaptationSetAndAudioRepresentation () { - EnterCriticalSection(&this->monitorMutex); + this->acquireLock(); if(this->audioAdaptationSet && this->audioRepresentation) { - LeaveCriticalSection(&this->monitorMutex); + this->releaseLock(); return 1; } - LeaveCriticalSection(&this->monitorMutex); + this->releaseLock(); return 0; } @@ -281,7 +280,7 @@ void MPDWrapper::initializeAdaptationSetStream (viper::managers::StreamType type { IAdaptationSet *adaptationSet = NULL; std::map *representations = NULL; - EnterCriticalSection(&this->monitorMutex); + this->acquireLock(); switch(type) { @@ -311,7 +310,7 @@ void MPDWrapper::initializeAdaptationSetStream (viper::managers::StreamType type RepresentationStreamType typeR = determineRepresentationStreamType(representation, adaptationSet, this->period); (*representations)[representation] = RepresentationStreamFactory::create(type, typeR, this, period, adaptationSet, representation); } - LeaveCriticalSection(&this->monitorMutex); + this->releaseLock(); } void MPDWrapper::initializeAdaptationSetStreamWithoutLock (viper::managers::StreamType type) @@ -549,7 +548,7 @@ void MPDWrapper::releaseLock () void MPDWrapper::setSegmentOffset(viper::managers::StreamType type, uint32_t segmentOffset) { - EnterCriticalSection(&this->monitorMutex); + this->acquireLock(); switch(type) { case viper::managers::StreamType::AUDIO: @@ -563,31 +562,28 @@ void MPDWrapper::setSegmentOffset(viper::managers::StreamType type, uint32_t seg default: break; } - LeaveCriticalSection(&this->monitorMutex); + this->releaseLock(); } MediaObject* MPDWrapper::getNextSegment (viper::managers::StreamType type, bool isLooping, uint32_t &segmentNumber, bool withFeedBack) { IRepresentation* representation; std::map *representations; - dash::mpd::IAdaptationSet* adaptationSet; - - EnterCriticalSection(&this->monitorMutex); + + this->acquireLock(); switch(type) { case viper::managers::StreamType::AUDIO: representation = this->audioRepresentation; representations = this->audioRepresentations; - adaptationSet = this->audioAdaptationSet; break; case viper::managers::StreamType::VIDEO: representation = this->videoRepresentation; representations = this->videoRepresentations; - adaptationSet = this->videoAdaptationSet; break; default: - LeaveCriticalSection(&this->monitorMutex); - return NULL; + this->releaseLock(); + return NULL; } ISegment* seg = NULL; @@ -614,7 +610,7 @@ MediaObject* MPDWrapper::getNextSegment (viper::managers::StreamType type, bool default: break; } - LeaveCriticalSection(&this->monitorMutex); + this->releaseLock(); return NULL; } } @@ -624,105 +620,53 @@ MediaObject* MPDWrapper::getNextSegment (viper::managers::StreamType type, bool while((this->isStopping == false) && segmentNumber >= representationStream->getSize()) { SleepConditionVariableCS(&this->mpdUpdate, &this->monitorMutex, INFINITE); - this->hasReachedEndOfList = true; + + if(this->isStopping) + { + this->releaseLock(); + return NULL; + } + //Need to update representationStream here as it was updated with the mpd (Live only): switch(type) { case viper::managers::StreamType::AUDIO: representation = this->audioRepresentation; representations = this->audioRepresentations; - adaptationSet = this->audioAdaptationSet; - segmentNumber = this->audioSegmentNumber; break; case viper::managers::StreamType::VIDEO: representation = this->videoRepresentation; representations = this->videoRepresentations; - adaptationSet = this->videoAdaptationSet; - segmentNumber = this->videoSegmentNumber; break; default: break; } representationStream = representations->find(representation)->second; - if(this->hasReachedEndOfList) - segmentNumber += 1; - } - 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: - segmentNumber = this->audioSegmentNumber; - break; - case viper::managers::StreamType::VIDEO: - segmentNumber = this->videoSegmentNumber; - break; - default: - break; - } - if(this->hasReachedEndOfList) - { - segmentNumber += 1; - this->hasReachedEndOfList = false; } } - uint64_t segDuration = 0; - //Returns the segmentDuration in milliseconds - seg = representationStream->getMediaSegment(segmentNumber, segDuration); + seg = representationStream->getMediaSegment(segmentNumber); if(seg != NULL) { - MediaObject *media = new MediaObject(seg, representation, withFeedBack); - if(segDuration == 0) - { - uint32_t duration = 0; - uint32_t timescale = 0; - - if(representation->GetSegmentTemplate()) - { - duration = representation->GetSegmentTemplate()->GetDuration(); - timescale = representation->GetSegmentTemplate()->GetTimescale(); - } - else - { - if(adaptationSet->GetSegmentTemplate()) - { - duration = adaptationSet->GetSegmentTemplate()->GetDuration(); - timescale = adaptationSet->GetSegmentTemplate()->GetTimescale(); - } - else - { - if(this->period->GetSegmentTemplate()) - { - duration = this->period->GetSegmentTemplate()->GetDuration(); - timescale = this->period->GetSegmentTemplate()->GetTimescale(); - } - } - } - segDuration = 1.0*duration/(1.0*timescale) * 1000; - - } - media->SetSegmentDuration(segDuration); + MediaObject *media = new MediaObject(seg, representation, withFeedBack); segmentNumber++; - switch(type) { case viper::managers::StreamType::AUDIO: this->audioSegmentNumber = segmentNumber; + this->audioSegmentIsSet = false; + this->audioSegmentQuality = -1; break; case viper::managers::StreamType::VIDEO: this->videoSegmentNumber = segmentNumber; + this->videoSegmentIsSet = false; + this->videoSegmentQuality = -1; break; default: break; } - LeaveCriticalSection(&this->monitorMutex); + this->releaseLock(); return media; } - LeaveCriticalSection(&this->monitorMutex); + this->releaseLock(); return NULL; } @@ -730,7 +674,7 @@ MediaObject* MPDWrapper::getSegment (viper::managers::StreamType type, uint32_t { IRepresentation* representation; std::map *representations; - EnterCriticalSection(&this->monitorMutex); + this->acquireLock(); switch(type) { @@ -743,7 +687,7 @@ MediaObject* MPDWrapper::getSegment (viper::managers::StreamType type, uint32_t representations = this->videoRepresentations; break; default: - LeaveCriticalSection(&this->monitorMutex); + this->releaseLock(); return NULL; } @@ -751,19 +695,17 @@ MediaObject* MPDWrapper::getSegment (viper::managers::StreamType type, uint32_t IRepresentationStream* representationStream = representations->find(representation)->second; if(segNum >= representationStream->getSize()) { - LeaveCriticalSection(&this->monitorMutex); + this->releaseLock(); return NULL; } - uint64_t segDuration =0; - seg = representationStream->getMediaSegment(segNum, segDuration); + seg = representationStream->getMediaSegment(segNum); if(seg != NULL) { MediaObject *media = new MediaObject(seg, representation); - media->SetSegmentDuration(segDuration); - LeaveCriticalSection(&this->monitorMutex); + this->releaseLock(); return media; } - LeaveCriticalSection(&this->monitorMutex); + this->releaseLock(); return NULL; } @@ -771,7 +713,7 @@ MediaObject* MPDWrapper::getInitSegment (viper::managers::StreamType type) { IRepresentation* representation; std::map *representations; - EnterCriticalSection(&this->monitorMutex); + this->acquireLock(); switch(type) { @@ -784,7 +726,7 @@ MediaObject* MPDWrapper::getInitSegment (viper::managers::StreamType type) representations = this->videoRepresentations; break; default: - LeaveCriticalSection(&this->monitorMutex); + this->releaseLock(); return NULL; } @@ -795,10 +737,10 @@ MediaObject* MPDWrapper::getInitSegment (viper::managers::StreamType type) if(seg != NULL) { MediaObject *media = new MediaObject(seg, representation); - LeaveCriticalSection(&this->monitorMutex); + this->releaseLock(); return media; } - LeaveCriticalSection(&this->monitorMutex); + this->releaseLock(); return NULL; } @@ -822,7 +764,7 @@ void MPDWrapper::setAudioQuality (IPeriod *period, IAdaptationSet *adaptationSet bool periodChanged = false; if (this->audioRepresentation == representation) { - LeaveCriticalSection(&this->monitorMutex); + this->releaseLock(); return; } @@ -848,7 +790,7 @@ void MPDWrapper::setVideoQuality (IPeriod *period, IAdaptationSet *adaptationSet bool periodChanged = false; if (this->videoRepresentation == representation) { - LeaveCriticalSection(&this->monitorMutex); + this->releaseLock(); return; } @@ -873,7 +815,7 @@ uint32_t MPDWrapper::calculateSegmentOffset (viper::managers::StreamType type, u { IRepresentation* representation; std::map *representations; - EnterCriticalSection(&this->monitorMutex); + this->acquireLock(); switch(type) { @@ -886,13 +828,13 @@ uint32_t MPDWrapper::calculateSegmentOffset (viper::managers::StreamType type, u representations = this->videoRepresentations; break; default: - LeaveCriticalSection(&this->monitorMutex); + this->releaseLock(); return 0; } if(!(strcmp(this->mpd->GetType().c_str(), "static"))) { - LeaveCriticalSection(&this->monitorMutex); + this->releaseLock(); return 0; } IRepresentationStream* representationStream = representations->find(representation)->second; @@ -900,14 +842,14 @@ uint32_t MPDWrapper::calculateSegmentOffset (viper::managers::StreamType type, u uint32_t currSegNum = representationStream->getCurrentSegmentNumber(); uint32_t startSegNum = currSegNum - 2*bufferSize; - LeaveCriticalSection(&this->monitorMutex); + this->releaseLock(); return (startSegNum > firstSegNum) ? startSegNum : firstSegNum; } std::string MPDWrapper::getRepresentationID (viper::managers::StreamType type) { std::string id = ""; - EnterCriticalSection(&this->monitorMutex); + this->acquireLock(); switch(type) { @@ -920,23 +862,23 @@ std::string MPDWrapper::getRepresentationID (viper::managers::StreamType type) default: break; } - LeaveCriticalSection(&this->monitorMutex); + this->releaseLock(); return id; } std::string MPDWrapper::getPublishTime () { - EnterCriticalSection(&this->monitorMutex); + this->acquireLock(); std::string pubTime = this->mpd->GetPublishTime(); - LeaveCriticalSection(&this->monitorMutex); + this->releaseLock(); return pubTime; } std::string MPDWrapper::getMinimumUpdatePeriod () { - EnterCriticalSection(&this->monitorMutex); + this->acquireLock(); std::string res = this->mpd->GetMinimumUpdatePeriod(); - LeaveCriticalSection(&this->monitorMutex); + this->releaseLock(); return res; } @@ -1079,7 +1021,7 @@ uint32_t MPDWrapper::getFetchTime () void MPDWrapper::settingsChanged (int period, int videoAdaptationSet, int videoRepresentation, int audioAdaptationSet, int audioRepresentation) { - EnterCriticalSection(&this->monitorMutex); + this->acquireLock(); this->period = this->mpd->GetPeriods().at(period); std::vector videoAdaptationSets = AdaptationSetHelper::getVideoAdaptationSets(this->period); std::vector audioAdaptationSets = AdaptationSetHelper::getAudioAdaptationSets(this->period); @@ -1103,14 +1045,14 @@ void MPDWrapper::settingsChanged (int period, int videoAdaptationSet, int videoR this->audioAdaptationSet = NULL; this->audioRepresentation = NULL; } - LeaveCriticalSection(&this->monitorMutex); + this->releaseLock(); } //Returns the segmentDuration float MPDWrapper::onFirstDownloadMPD (viper::IViperGui *gui) { float segmentDuration = 0.0; - EnterCriticalSection(&this->monitorMutex); + this->acquireLock(); IRepresentation *representation = this->videoAdaptationSet->GetRepresentation().at(0); if(!strcmp(this->mpd->GetType().c_str(), "static")) // VOD MPD { @@ -1164,8 +1106,26 @@ float MPDWrapper::onFirstDownloadMPD (viper::IViperGui *gui) 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(); + uint32_t duration = 0; + uint32_t timescale = 0; + if(representation->GetSegmentTemplate()) + { + duration = representation->GetSegmentTemplate()->GetDuration(); + timescale = representation->GetSegmentTemplate()->GetTimescale(); + } + else + { + if(this->videoAdaptationSet->GetSegmentTemplate()) //SegmentTemplate at AdaptationSet level + { + duration = this->videoAdaptationSet->GetSegmentTemplate()->GetDuration(); + timescale = this->videoAdaptationSet->GetSegmentTemplate()->GetTimescale(); + } + else + { // SegmentTemplate at Period level + duration = this->period->GetSegmentTemplate()->GetDuration(); + timescale = this->period->GetSegmentTemplate()->GetTimescale(); + } + } segmentDuration = 1.0*duration/(1.0*timescale) * 1000; if(gui) { @@ -1173,7 +1133,7 @@ float MPDWrapper::onFirstDownloadMPD (viper::IViperGui *gui) gui->setListSegmentSize(0); } } - LeaveCriticalSection(&this->monitorMutex); + this->releaseLock(); return segmentDuration; } @@ -1182,3 +1142,59 @@ void MPDWrapper::setIsStopping (bool isStopping) this->isStopping = isStopping; WakeAllConditionVariable(&this->mpdUpdate); } + +void MPDWrapper::setSegmentIsSetFlag(viper::managers::StreamType type, bool flag) +{ + switch(type) + { + case viper::managers::StreamType::AUDIO: + this->audioSegmentIsSet = flag; + break; + case viper::managers::StreamType::VIDEO: + this->videoSegmentIsSet = flag; + break; + default: + break; + } +} + +bool MPDWrapper::getSegmentIsSetFlag(viper::managers::StreamType type) +{ + switch(type) + { + case viper::managers::StreamType::AUDIO: + return this->audioSegmentIsSet; + case viper::managers::StreamType::VIDEO: + return this->videoSegmentIsSet; + default: + return false; + } +} + +int MPDWrapper::getSegmentQuality(viper::managers::StreamType type) +{ + switch(type) + { + case viper::managers::StreamType::AUDIO: + return this->audioSegmentQuality; + case viper::managers::StreamType::VIDEO: + return this->videoSegmentQuality; + default: + return false; + } +} + +void MPDWrapper::setSegmentQuality(viper::managers::StreamType type, int segQuality) +{ + switch(type) + { + case viper::managers::StreamType::AUDIO: + this->audioSegmentIsSet = segQuality; + break; + case viper::managers::StreamType::VIDEO: + this->videoSegmentIsSet = segQuality; + break; + default: + break; + } +} diff --git a/MPD/MPDWrapper.h b/MPD/MPDWrapper.h index cf6275d8..75ade085 100644 --- a/MPD/MPDWrapper.h +++ b/MPD/MPDWrapper.h @@ -106,6 +106,10 @@ public: void settingsChanged(int period, int videoAdaptationSet, int videoRepresentation, int audioAdaptationSet, int audioRepresentation); float onFirstDownloadMPD(viper::IViperGui *gui); void setIsStopping(bool isStopping); + void setSegmentIsSetFlag(viper::managers::StreamType type, bool flag); + bool getSegmentIsSetFlag(viper::managers::StreamType type); + int getSegmentQuality(viper::managers::StreamType type); + void setSegmentQuality(viper::managers::StreamType type, int segQuality); private: RepresentationStreamType determineRepresentationStreamType(dash::mpd::IRepresentation *representation, dash::mpd::IAdaptationSet* adaptationSet, dash::mpd::IPeriod* period); @@ -124,8 +128,11 @@ private: uint32_t audioSegmentOffset; size_t videoSegmentNumber; size_t audioSegmentNumber; + bool videoSegmentIsSet; + bool audioSegmentIsSet; + int videoSegmentQuality; + int audioSegmentQuality; bool isStopping; - bool hasReachedEndOfList; }; } } diff --git a/MPD/SegmentListStream.cpp b/MPD/SegmentListStream.cpp index 86d36e68..0ab67570 100644 --- a/MPD/SegmentListStream.cpp +++ b/MPD/SegmentListStream.cpp @@ -53,15 +53,11 @@ ISegment* SegmentListStream::getIndexSegment(size_t segmentNumber) return NULL; } -ISegment* SegmentListStream::getMediaSegment(size_t segmentNumber, uint64_t& segmentDuration) +ISegment* SegmentListStream::getMediaSegment(size_t segmentNumber) { if (this->segmentList->GetSegmentURLs().size() > segmentNumber) - { - uint32_t duration = representation->GetSegmentList()->GetDuration(); - uint32_t timescale = representation->GetSegmentList()->GetTimescale(); - segmentDuration = (uint64_t)(((float)duration/(float)timescale) * 1000); return this->segmentList->GetSegmentURLs().at(segmentNumber)->ToMediaSegment(this->baseUrls); - } + return NULL; } diff --git a/MPD/SegmentListStream.h b/MPD/SegmentListStream.h index 589896ff..a9658748 100644 --- a/MPD/SegmentListStream.h +++ b/MPD/SegmentListStream.h @@ -33,7 +33,7 @@ public: virtual dash::mpd::ISegment* getInitializationSegment(); virtual dash::mpd::ISegment* getIndexSegment(size_t segmentNumber); - virtual dash::mpd::ISegment* getMediaSegment(size_t segmentNumber, uint64_t& segmentDuration); + virtual dash::mpd::ISegment* getMediaSegment(size_t segmentNumber); virtual dash::mpd::ISegment* getBitstreamSwitchingSegment(); virtual RepresentationStreamType getStreamType(); virtual uint32_t getSize(); diff --git a/MPD/SegmentTemplateStream.cpp b/MPD/SegmentTemplateStream.cpp index 5a6dd67c..b8f08530 100644 --- a/MPD/SegmentTemplateStream.cpp +++ b/MPD/SegmentTemplateStream.cpp @@ -64,14 +64,13 @@ ISegment* SegmentTemplateStream::getIndexSegment(size_t segmentNumber) this->segmentTemplate->GetStartNumber() + segmentNumber); } -ISegment* SegmentTemplateStream::getMediaSegment(size_t segmentNumber, uint64_t& segmentDuration) +ISegment* SegmentTemplateStream::getMediaSegment(size_t segmentNumber) { /* time-based template */ if (this->segmentTemplate->GetSegmentTimeline()) {//Get the one at segmentNumber if(this->segmentStartTimes.size() > segmentNumber) { - segmentDuration = (uint64_t)(((float)this->segmentDurationTimes.at(segmentNumber)/(float)this->getTimescale()) * 1000); return this->segmentTemplate->GetMediaSegmentFromTime(baseUrls, representation->GetId(), representation->GetBandwidth(), this->segmentStartTimes.at(segmentNumber)); } else @@ -228,7 +227,7 @@ uint64_t SegmentTemplateStream::getTime(size_t segmentNumber) if(segmentNumber < this->segmentStartTimes.size()) return this->segmentStartTimes.at(segmentNumber); else - return this->segmentStartTimes.at(this->segmentStartTimes.size()-1); + return (this->segmentStartTimes.size() == 0)? 0 : this->segmentStartTimes.at(this->segmentStartTimes.size()-1); } size_t SegmentTemplateStream::getSegmentNumber(uint64_t time) diff --git a/MPD/SegmentTemplateStream.h b/MPD/SegmentTemplateStream.h index 8485b56b..8325a387 100644 --- a/MPD/SegmentTemplateStream.h +++ b/MPD/SegmentTemplateStream.h @@ -34,7 +34,7 @@ public: virtual dash::mpd::ISegment* getInitializationSegment(); virtual dash::mpd::ISegment* getIndexSegment(size_t segmentNumber); - virtual dash::mpd::ISegment* getMediaSegment(size_t segmentNumber, uint64_t& segmentDuration); + virtual dash::mpd::ISegment* getMediaSegment(size_t segmentNumber); virtual dash::mpd::ISegment* getBitstreamSwitchingSegment(); virtual RepresentationStreamType getStreamType(); virtual uint32_t getSize(); diff --git a/MPD/SingleMediaSegmentStream.cpp b/MPD/SingleMediaSegmentStream.cpp index 3eccbefe..39301928 100644 --- a/MPD/SingleMediaSegmentStream.cpp +++ b/MPD/SingleMediaSegmentStream.cpp @@ -51,7 +51,7 @@ ISegment* SingleMediaSegmentStream::getIndexSegment(size_t segmentNumber) return NULL; } -ISegment* SingleMediaSegmentStream::getMediaSegment(size_t segmentNumber, uint64_t& segmentDuration) +ISegment* SingleMediaSegmentStream::getMediaSegment(size_t segmentNumber) { /* segmentNumber equals the desired BaseUrl */ if (this->representation->GetBaseURLs().size() > segmentNumber) diff --git a/MPD/SingleMediaSegmentStream.h b/MPD/SingleMediaSegmentStream.h index 44fead38..e619a7f8 100644 --- a/MPD/SingleMediaSegmentStream.h +++ b/MPD/SingleMediaSegmentStream.h @@ -31,7 +31,7 @@ public: virtual dash::mpd::ISegment* getInitializationSegment(); virtual dash::mpd::ISegment* getIndexSegment(size_t segmentNumber); - virtual dash::mpd::ISegment* getMediaSegment(size_t segmentNumber, uint64_t& segmentDuration); + virtual dash::mpd::ISegment* getMediaSegment(size_t segmentNumber); virtual dash::mpd::ISegment* getBitstreamSwitchingSegment(); virtual RepresentationStreamType getStreamType(); diff --git a/Managers/IStreamObserver.h b/Managers/IStreamObserver.h index 31baca68..1d628d51 100644 --- a/Managers/IStreamObserver.h +++ b/Managers/IStreamObserver.h @@ -38,6 +38,7 @@ public: virtual void notifyQualityDownloading(uint32_t quality) = 0; virtual bool canPush() = 0; virtual int getBufferLevel() = 0; + virtual void fetchMPD() = 0; }; } } diff --git a/Managers/MultimediaManager.cpp b/Managers/MultimediaManager.cpp index 1b759f4b..30f8427a 100644 --- a/Managers/MultimediaManager.cpp +++ b/Managers/MultimediaManager.cpp @@ -41,8 +41,7 @@ MultimediaManager::MultimediaManager(ViperGui *viperGui, int segBufSize, std::st eos (false), playing (false), noDecoding (nodecoding), - mpdWrapper (NULL), - mpdFetcherThread (NULL) + mpdWrapper (NULL) { InitializeCriticalSection (&this->monitorMutex); InitializeCriticalSection (&this->monitorBufferMutex); @@ -239,14 +238,6 @@ void MultimediaManager::start(bool icnEnabled, double icnAlpha, uint32_t nextOff this->started = true; this->playing = true; - if(!strcmp(this->mpdWrapper->getType().c_str(), "dynamic")) - { - this->mpdFetcherThread = createThreadPortable(DoMPDFetching, this); - if(this->mpdFetcherThread == NULL) - { - std::cout << "mpd Fetcher thread is NULL. Need to think of how to handle this?" << std::endl; - } - } LeaveCriticalSection(&this->monitorMutex); } @@ -265,11 +256,6 @@ void MultimediaManager::stop() Debug("VIDEO STOPPED\n"); this->mpdWrapper->reInit(viper::managers::StreamType::VIDEO); this->mpdWrapper->reInit(viper::managers::StreamType::AUDIO); - if(this->mpdFetcherThread != NULL) - { - JoinThread(this->mpdFetcherThread); - destroyThreadPortable(this->mpdFetcherThread); - } } void MultimediaManager::stopVideo() @@ -706,24 +692,3 @@ float MultimediaManager::getSegmentDuration() return this->segmentDuration; } -void* MultimediaManager::DoMPDFetching (void* data) -{ - MultimediaManager *manager = (MultimediaManager*) data; - uint32_t currTime = TimeResolver::getCurrentTimeInSec(); - uint32_t publishedTime = manager->mpdWrapper->getFetchTime(); -// To avoid clock synchronisation issues: using fetching time instead of publish time -// uint32_t publishedTime = TimeResolver::getUTCDateTimeInSec(dashReceiver->mpdWrapper->getPublishTime()); - uint32_t periodUpdate = TimeResolver::getDurationInSec(manager->mpdWrapper->getMinimumUpdatePeriod()); - while(manager->isStarted()) - { - while(manager->isStarted() && currTime < publishedTime + periodUpdate) - { - usleep(((publishedTime + periodUpdate) - currTime) * 1000000); - currTime = TimeResolver::getCurrentTimeInSec(); - } - manager->fetchMPD(); - publishedTime = manager->mpdWrapper->getFetchTime(); -// publishedTime = TimeResolver::getUTCDateTimeInSec(dashReceiver->mpdWrapper->getPublishTime()); - periodUpdate = TimeResolver::getDurationInSec(manager->mpdWrapper->getMinimumUpdatePeriod()); - } -} diff --git a/Managers/MultimediaManager.h b/Managers/MultimediaManager.h index c00ff866..ade2b767 100644 --- a/Managers/MultimediaManager.h +++ b/Managers/MultimediaManager.h @@ -106,7 +106,6 @@ private: double frameRate; THREAD_HANDLE videoRendererHandle; THREAD_HANDLE audioRendererHandle; - THREAD_HANDLE mpdFetcherThread; bool isVideoRendering; bool isAudioRendering; bool eos; @@ -137,7 +136,6 @@ private: void notifyAudioSegmentBufferObservers (uint32_t fillstateInPercent); void updateMPD (); void updateMPDICN (); - static void* DoMPDFetching (void* manager); }; } } diff --git a/Managers/MultimediaStream.cpp b/Managers/MultimediaStream.cpp index f70eabfb..86cde35d 100644 --- a/Managers/MultimediaStream.cpp +++ b/Managers/MultimediaStream.cpp @@ -198,3 +198,11 @@ void MultimediaStream::notifyBufferChange(uint32_t bufferfill, int maxC) { this->dashManager->onBufferStateChanged(libdash::framework::buffer::VIDEO, bufferfill, maxC); } + +void MultimediaStream::fetchMPD() +{ + for(size_t i=0; i < this->observers.size(); i++) + { + this->observers.at(i)->fetchMPD(); + } +} diff --git a/Managers/MultimediaStream.h b/Managers/MultimediaStream.h index 52a7ac9d..454cca23 100644 --- a/Managers/MultimediaStream.h +++ b/Managers/MultimediaStream.h @@ -75,6 +75,7 @@ public: bool isICN(); void shouldAbort(); void setTargetDownloadingTime(double); + void fetchMPD(); private: float beta; diff --git a/UI/ViperGui.cpp b/UI/ViperGui.cpp index 99d2e5a3..e23bd308 100644 --- a/UI/ViperGui.cpp +++ b/UI/ViperGui.cpp @@ -192,7 +192,7 @@ void ViperGui::writeData(libdash::framework::input::MediaObject* media) this->segment = this->segment + 1; if( this->segment > 0) { - this->bufferDuration += media->GetSegmentDuration(); + this->bufferDuration += this->segmentDuration; if(this->bufferDuration - this->position > 3000) { @@ -206,7 +206,7 @@ void ViperGui::writeData(libdash::framework::input::MediaObject* media) } else { - this->bufferDuration += (this->durationMilliseconds - (media->GetSegmentDuration() * (this->listSegmentSize - 1))); + this->bufferDuration += (this->durationMilliseconds - (this->segmentDuration * (this->listSegmentSize - 1))); if(this->bufferDuration - this->position >3000) { -- cgit 1.2.3-korg