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 --- Adaptation/AbstractAdaptationLogic.cpp | 29 +- Adaptation/AbstractAdaptationLogic.h | 38 +- Adaptation/AdaptationLogicFactory.cpp | 20 +- Adaptation/AdaptationLogicFactory.h | 4 +- Adaptation/AlwaysLowestLogic.cpp | 6 +- Adaptation/AlwaysLowestLogic.h | 3 +- Adaptation/Bola.cpp | 46 +- Adaptation/Bola.h | 73 +- Adaptation/BufferBasedAdaptation.cpp | 33 +- Adaptation/BufferBasedAdaptation.h | 17 +- Adaptation/BufferBasedAdaptationWithRateBased.cpp | 34 +- Adaptation/BufferBasedAdaptationWithRateBased.h | 25 +- Adaptation/BufferBasedThreeThresholdAdaptation.cpp | 151 +-- Adaptation/BufferBasedThreeThresholdAdaptation.h | 27 +- Adaptation/IAdaptationLogic.h | 7 +- Adaptation/Panda.cpp | 35 +- Adaptation/Panda.h | 53 +- Adaptation/RateBasedAdaptation.cpp | 22 +- Adaptation/RateBasedAdaptation.h | 11 +- Common/ViperBuffer.cpp | 5 +- Input/DASHManager.cpp | 21 +- Input/DASHManager.h | 25 +- Input/DASHReceiver.cpp | 291 +++--- Input/DASHReceiver.h | 44 +- Input/ICNConnectionConsumerApi.cpp | 8 +- Input/IDASHManagerObserver.h | 1 + Input/IDASHReceiverObserver.h | 1 + Input/MediaObject.cpp | 22 + Input/MediaObject.h | 6 + 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 +- Managers/IMultimediaManagerBase.h | 8 +- Managers/IMultimediaManagerObserver.h | 1 + Managers/IStreamObserver.h | 2 +- Managers/MultimediaManager.cpp | 176 +++- Managers/MultimediaManager.h | 129 +-- Managers/MultimediaStream.cpp | 33 +- Managers/MultimediaStream.h | 32 +- UI/DASHPlayer.cpp | 82 +- UI/DASHPlayer.h | 57 +- UI/DASHPlayerNoGUI.cpp | 101 +- UI/DASHPlayerNoGUI.h | 47 +- UI/IViperGui.h | 30 + UI/ViperGui.cpp | 43 +- UI/ViperGui.h | 3 +- libdash/include/IMPD.h | 9 +- libdash/source/mpd/MPD.cpp | 8 + libdash/source/mpd/MPD.h | 3 + libdash/source/xml/Node.cpp | 4 + viper.pro | 4 + 66 files changed, 2529 insertions(+), 925 deletions(-) create mode 100644 MPD/IMPDWrapper.h create mode 100644 MPD/MPDWrapper.cpp create mode 100644 MPD/MPDWrapper.h create mode 100644 UI/IViperGui.h diff --git a/Adaptation/AbstractAdaptationLogic.cpp b/Adaptation/AbstractAdaptationLogic.cpp index 4f578958..ada388b7 100644 --- a/Adaptation/AbstractAdaptationLogic.cpp +++ b/Adaptation/AbstractAdaptationLogic.cpp @@ -14,17 +14,16 @@ using namespace libdash::framework::adaptation; using namespace dash::mpd; -AbstractAdaptationLogic::AbstractAdaptationLogic(dash::mpd::IMPD *mpd, dash::mpd::IPeriod *period, dash::mpd::IAdaptationSet *adaptationSet, bool isVid) : - mpd (mpd), - period (period), - adaptationSet (adaptationSet), - representation (NULL), - isVideo (isVid) +AbstractAdaptationLogic::AbstractAdaptationLogic(viper::managers::StreamType type, libdash::framework::mpd::MPDWrapper *mpdWrapper) : + mpdWrapper (mpdWrapper), + type (type) { + InitializeCriticalSection (&this->monitorLock); } AbstractAdaptationLogic::~AbstractAdaptationLogic() { + DeleteCriticalSection (&this->monitorLock); } uint32_t AbstractAdaptationLogic::getPosition() @@ -39,15 +38,19 @@ void AbstractAdaptationLogic::setPosition(uint32_t segmentNumber) IRepresentation* AbstractAdaptationLogic::getRepresentation() { - return this->representation; +// return this->representation; } -void AbstractAdaptationLogic::setRepresentation(IPeriod *period, IAdaptationSet *adaptationSet, IRepresentation *representation) -{ - this->period = period; - this->adaptationSet = adaptationSet; - this->representation = representation; -} +//void AbstractAdaptationLogic::setRepresentation(IPeriod *period, IAdaptationSet *adaptationSet, IRepresentation *representation) +//{ +// this->period = period; +// this->adaptationSet = adaptationSet; +// this->representation = representation; +//} + +//void AbstractAdaptationLogic::updateMPD(IMPD* mpd) +//{ +//} void AbstractAdaptationLogic::dLTimeUpdate(double time) { diff --git a/Adaptation/AbstractAdaptationLogic.h b/Adaptation/AbstractAdaptationLogic.h index 24fab91d..c407f01b 100644 --- a/Adaptation/AbstractAdaptationLogic.h +++ b/Adaptation/AbstractAdaptationLogic.h @@ -24,33 +24,37 @@ namespace adaptation class AbstractAdaptationLogic : public IAdaptationLogic { public: - AbstractAdaptationLogic(dash::mpd::IMPD *mpd, dash::mpd::IPeriod* period, dash::mpd::IAdaptationSet *adaptationSet, bool isVideo); +// AbstractAdaptationLogic(dash::mpd::IMPD *mpd, dash::mpd::IPeriod* period, dash::mpd::IAdaptationSet *adaptationSet, bool isVideo); + AbstractAdaptationLogic(viper::managers::StreamType type, libdash::framework::mpd::MPDWrapper *mpdWrapper); virtual ~AbstractAdaptationLogic(); virtual uint32_t getPosition(); virtual void setPosition(uint32_t segmentNumber); virtual dash::mpd::IRepresentation* getRepresentation (); - virtual void setRepresentation(dash::mpd::IPeriod *period, - dash::mpd::IAdaptationSet *adaptationSet, - dash::mpd::IRepresentation *representation); +// virtual void setRepresentation(dash::mpd::IPeriod *period, +// dash::mpd::IAdaptationSet *adaptationSet, +// dash::mpd::IRepresentation *representation); +// virtual void updateMPD(dash::mpd::IMPD* mpd); - virtual LogicType getType() = 0; - virtual bool isUserDependent() = 0; - virtual bool isRateBased() = 0; - virtual bool isBufferBased() = 0; + virtual LogicType getType() = 0; + virtual bool isUserDependent() = 0; + virtual bool isRateBased() = 0; + virtual bool isBufferBased() = 0; virtual void bitrateUpdate(uint64_t, uint32_t) = 0; - virtual void bufferUpdate(uint32_t, int) = 0; - virtual void onEOS(bool value)= 0; - virtual void dLTimeUpdate(double) = 0; + virtual void bufferUpdate(uint32_t, int) = 0; + virtual void onEOS(bool value) = 0; + virtual void dLTimeUpdate(double) = 0; + virtual void checkedByDASHReceiver() = 0; - virtual void checkedByDASHReceiver() = 0; protected: - dash::mpd::IMPD *mpd; - dash::mpd::IPeriod *period; - dash::mpd::IAdaptationSet *adaptationSet; - dash::mpd::IRepresentation *representation; + libdash::framework::mpd::MPDWrapper *mpdWrapper; +// dash::mpd::IPeriod *period; +// dash::mpd::IAdaptationSet *adaptationSet; +// dash::mpd::IRepresentation *representation; uint32_t segmentNumber; - bool isVideo; +// bool isVideo; + viper::managers::StreamType type; + mutable CRITICAL_SECTION monitorLock; }; } } diff --git a/Adaptation/AdaptationLogicFactory.cpp b/Adaptation/AdaptationLogicFactory.cpp index 6901a597..b2cae9c1 100644 --- a/Adaptation/AdaptationLogicFactory.cpp +++ b/Adaptation/AdaptationLogicFactory.cpp @@ -13,36 +13,36 @@ #include using namespace libdash::framework::adaptation; +using namespace libdash::framework::mpd; using namespace dash::mpd; -IAdaptationLogic* AdaptationLogicFactory::create(LogicType logic, IMPD *mpd, IPeriod *period, IAdaptationSet *adaptationSet,bool isVid, struct AdaptationParameters* paramsForAdaptation) +IAdaptationLogic* AdaptationLogicFactory::create(LogicType logic, viper::managers::StreamType type, MPDWrapper *mpdWrapper, struct AdaptationParameters* paramsForAdaptation) { - Debug("Adaptation Logic for %s: ", isVid ? "video" : "audio"); switch(logic) { case AlwaysLowest: Debug("Always lowest\n"); - return new AlwaysLowestLogic(mpd, period, adaptationSet, isVid, paramsForAdaptation); + return new AlwaysLowestLogic(type, mpdWrapper, paramsForAdaptation); case RateBased: Debug("Rate based\n"); - return new RateBasedAdaptation(mpd,period,adaptationSet, isVid, paramsForAdaptation); + return new RateBasedAdaptation(type, mpdWrapper, paramsForAdaptation); case BufferBased: Debug("Buffer based\n"); - return new BufferBasedAdaptation(mpd,period,adaptationSet, isVid, paramsForAdaptation); + return new BufferBasedAdaptation(type, mpdWrapper, paramsForAdaptation); case BufferRateBased: Debug("Buffer Rate based\n"); - return new BufferBasedAdaptationWithRateBased(mpd,period,adaptationSet, isVid, paramsForAdaptation); + return new BufferBasedAdaptationWithRateBased(type, mpdWrapper, paramsForAdaptation); case BufferBasedThreeThreshold: Debug("Buffer based 3 threshold\n"); - return new BufferBasedThreeThresholdAdaptation(mpd,period,adaptationSet, isVid, paramsForAdaptation); + return new BufferBasedThreeThresholdAdaptation(type, mpdWrapper, paramsForAdaptation); case Panda: Debug("Panda\n"); - return new PandaAdaptation(mpd, period, adaptationSet, isVid, paramsForAdaptation); + return new PandaAdaptation(type, mpdWrapper, paramsForAdaptation); case Bola: Debug("Bola\n"); - return new BolaAdaptation(mpd, period, adaptationSet, isVid, paramsForAdaptation); + return new BolaAdaptation(type, mpdWrapper, paramsForAdaptation); default: Debug("default => return Always Lowest\n"); - return new AlwaysLowestLogic(mpd, period, adaptationSet, isVid, paramsForAdaptation); + return new AlwaysLowestLogic(type, mpdWrapper, paramsForAdaptation); } } diff --git a/Adaptation/AdaptationLogicFactory.h b/Adaptation/AdaptationLogicFactory.h index 0f1616a7..e78d2865 100644 --- a/Adaptation/AdaptationLogicFactory.h +++ b/Adaptation/AdaptationLogicFactory.h @@ -30,8 +30,8 @@ namespace adaptation class AdaptationLogicFactory { public: - static IAdaptationLogic* create(libdash::framework::adaptation::LogicType logic, - dash::mpd::IMPD *mpd, dash::mpd::IPeriod *period, dash::mpd::IAdaptationSet *adaptationSet, bool isVid, struct AdaptationParameters *params); + static IAdaptationLogic* create(libdash::framework::adaptation::LogicType logic, viper::managers::StreamType type, libdash::framework::mpd::MPDWrapper *mpdWrapper, struct AdaptationParameters *params); +// static IAdaptationLogic* create(libdash::framework::adaptation::LogicType logic, dash::mpd::IMPD *mpd, dash::mpd::IPeriod *period, dash::mpd::IAdaptationSet *adaptationSet, bool isVid, struct AdaptationParameters *params); }; } } diff --git a/Adaptation/AlwaysLowestLogic.cpp b/Adaptation/AlwaysLowestLogic.cpp index 54409bfd..1f318867 100644 --- a/Adaptation/AlwaysLowestLogic.cpp +++ b/Adaptation/AlwaysLowestLogic.cpp @@ -14,12 +14,12 @@ using namespace libdash::framework::adaptation; using namespace libdash::framework::input; +using namespace libdash::framework::mpd; using namespace dash::mpd; -AlwaysLowestLogic::AlwaysLowestLogic(IMPD *mpd, IPeriod *period, IAdaptationSet *adaptationSet, bool isVid, struct AdaptationParameters *params) : - AbstractAdaptationLogic(mpd, period, adaptationSet, isVid) +AlwaysLowestLogic::AlwaysLowestLogic(viper::managers::StreamType type, MPDWrapper *mpdWrapper, struct AdaptationParameters *params) : + AbstractAdaptationLogic(type, mpdWrapper) { - this->representation = this->adaptationSet->GetRepresentation().at(0); } AlwaysLowestLogic::~AlwaysLowestLogic() diff --git a/Adaptation/AlwaysLowestLogic.h b/Adaptation/AlwaysLowestLogic.h index 782a8b29..f8b50e37 100644 --- a/Adaptation/AlwaysLowestLogic.h +++ b/Adaptation/AlwaysLowestLogic.h @@ -24,7 +24,8 @@ namespace adaptation class AlwaysLowestLogic : public AbstractAdaptationLogic { public: - AlwaysLowestLogic(dash::mpd::IMPD *mpd, dash::mpd::IPeriod *period, dash::mpd::IAdaptationSet *adaptationSet, bool isVid, struct AdaptationParameters *params); +// AlwaysLowestLogic(dash::mpd::IMPD *mpd, dash::mpd::IPeriod *period, dash::mpd::IAdaptationSet *adaptationSet, bool isVid, struct AdaptationParameters *params); + AlwaysLowestLogic(viper::managers::StreamType type, libdash::framework::mpd::MPDWrapper *mpdWrapper, struct AdaptationParameters *params); virtual ~AlwaysLowestLogic(); virtual LogicType getType(); diff --git a/Adaptation/Bola.cpp b/Adaptation/Bola.cpp index 6477e0f5..f7acc72e 100644 --- a/Adaptation/Bola.cpp +++ b/Adaptation/Bola.cpp @@ -47,8 +47,8 @@ using std::placeholders::_2; using duration_in_seconds = std::chrono::duration >; -BolaAdaptation::BolaAdaptation(IMPD *mpd, IPeriod *period, IAdaptationSet *adaptationSet, bool isVid, struct AdaptationParameters *params) : - AbstractAdaptationLogic (mpd, period, adaptationSet, isVid) +BolaAdaptation::BolaAdaptation(viper::managers::StreamType type, MPDWrapper *mpdWrapper, struct AdaptationParameters *params) : + AbstractAdaptationLogic (type, mpdWrapper) { this->bufferMaxSizeSeconds =(double) params->segmentBufferSize * params->segmentDuration; this->alphaRate = params->Bola_Alpha; @@ -62,11 +62,12 @@ BolaAdaptation::BolaAdaptation(IMPD *mpd, IPeriod *period, IAdaptationSet *adapt this->currentDownloadTimeInstant = 0.0; //this->lastSegmentDownloadTime = 0.0; this->currentQuality = 0; - + this->representation = NULL; this->bufferTargetPerc = (uint32_t) ( round(this->bufferTargetSeconds / this->bufferMaxSizeSeconds)*100 ); + this->mpdWrapper->acquireLock(); /// Retrieve available bitrates - std::vector representations = this->adaptationSet->GetRepresentation(); + std::vector representations = this->mpdWrapper->getRepresentations(this->type); this->availableBitrates.clear(); Debug("BOLA Available Bitrates...\n"); @@ -85,8 +86,8 @@ BolaAdaptation::BolaAdaptation(IMPD *mpd, IPeriod *period, IAdaptationSet *adapt // return 0; // Check if exit with a message is necessary } - // Check if the following is correct - this->totalDuration = TimeResolver::getDurationInSec(this->mpd->GetMediaPresentationDuration()); + // Check if the following is correct XXX Maybe useless + this->totalDuration = TimeResolver::getDurationInSec(this->mpdWrapper->getMediaPresentationDuration()); // this->segmentDuration = (double) (representations.at(0)->GetSegmentTemplate()->GetDuration() / representations.at(0)->GetSegmentTemplate()->GetTimescale() ); this->segmentDuration = 2.0; Debug("Total Duration - BOLA:\t%f\nSegment Duration - BOLA:\t%f\n",this->totalDuration, this->segmentDuration); @@ -169,6 +170,7 @@ BolaAdaptation::BolaAdaptation(IMPD *mpd, IPeriod *period, IAdaptationSet *adapt this->representation = representations.at(0); this->currentBitrate = (uint64_t) this->representation->GetBandwidth(); + this->mpdWrapper->releaseLock(); Debug("BOLA Init Params - \tAlpha: %f \t BufferTarget: %f\n",this->alphaRate, this->bufferTargetSeconds); Debug("BOLA Init Current BitRate - %I64u\n",this->currentBitrate); Debug("Buffer Adaptation BOLA: STARTED\n"); @@ -204,16 +206,20 @@ void BolaAdaptation::setMultimediaManager(viper::managers::IMultimediaManagerBas void BolaAdaptation::notifyBitrateChange() { + this->mpdWrapper->setRepresentation(this->type, this->representation); if(this->multimediaManager) if(this->multimediaManager->isStarted() && !this->multimediaManager->isStopping()) - if(this->isVideo) - this->multimediaManager->setVideoQuality(this->period, this->adaptationSet, this->representation); + if(type==viper::managers::VIDEO) + this->multimediaManager->setVideoQuality(); +// this->multimediaManager->setVideoQuality(this->period, this->adaptationSet, this->representation); else - this->multimediaManager->setAudioQuality(this->period, this->adaptationSet, this->representation); + this->multimediaManager->setAudioQuality(); +// this->multimediaManager->setAudioQuality(this->period, this->adaptationSet, this->representation); //Should Abort is done here to avoid race condition with DASHReceiver::DoBuffering() if(this->shouldAbort) { - this->multimediaManager->shouldAbort(this->isVideo); + this->multimediaManager->shouldAbort(1); +// this->multimediaManager->shouldAbort((this->type == viper::managers::StreamType::VIDEO)); } this->shouldAbort = false; } @@ -263,10 +269,10 @@ void BolaAdaptation::setBitrate(uint32_t bufferFill) } //this->representation = this->availableBitrates[this->currentQuality]; //this->currentBitrate = (uint64_t) this->representation->GetBandwidth(); - this->representation = this->adaptationSet->GetRepresentation().at(this->currentQuality); + this->representation = this->mpdWrapper->getRepresentationAt(this->type, this->currentQuality); this->currentBitrate = (uint64_t) this->availableBitrates[this->currentQuality]; Debug("INIT - Current Bitrate:\t%I64u\n", this->currentBitrate); - Debug("ADAPTATION_LOGIC:\tFor %s:\tlast_buffer: %f\tbuffer_level: %f, instantaneousBw: %lu, AverageBW: %lu, choice: %d\n",isVideo ? "video" : "audio",(double)lastBufferFill/100 , (double)bufferFill/100, this->instantBw, this->averageBw , this->currentQuality); + Debug("ADAPTATION_LOGIC:\tFor %s:\tlast_buffer: %f\tbuffer_level: %f, instantaneousBw: %lu, AverageBW: %lu, choice: %d\n",(this->type == viper::managers::VIDEO) ? "video" : "audio",(double)lastBufferFill/100 , (double)bufferFill/100, this->instantBw, this->averageBw , this->currentQuality); this->lastBufferFill = bufferFill; return; } @@ -275,10 +281,10 @@ void BolaAdaptation::setBitrate(uint32_t bufferFill) this->currentQuality = 0; //this->representation = this->availableBitrates[this->currentQuality]; //this->currentBitrate = (uint64_t) this->representation->GetBandwidth(); - this->representation = this->adaptationSet->GetRepresentation().at(this->currentQuality); + this->representation = this->mpdWrapper->getRepresentationAt(this->type,this->currentQuality); this->currentBitrate = (uint64_t) this->availableBitrates[this->currentQuality]; Debug("ONE BITRATE - Current Bitrate:\t%I64u\n", this->currentBitrate); - Debug("ADAPTATION_LOGIC:\tFor %s:\tlast_buffer: %f\tbuffer_level: %f, instantaneousBw: %lu, AverageBW: %lu, choice: %d\n",isVideo ? "video" : "audio",(double)lastBufferFill/100 , (double)bufferFill/100, this->instantBw, this->averageBw , this->currentQuality); + Debug("ADAPTATION_LOGIC:\tFor %s:\tlast_buffer: %f\tbuffer_level: %f, instantaneousBw: %lu, AverageBW: %lu, choice: %d\n",(this->type == viper::managers::VIDEO) ? "video" : "audio",(double)lastBufferFill/100 , (double)bufferFill/100, this->instantBw, this->averageBw , this->currentQuality); this->lastBufferFill = bufferFill; return; } @@ -384,10 +390,10 @@ void BolaAdaptation::setBitrate(uint32_t bufferFill) this->currentQuality = quality; //this->representation = this->availableBitrates[this->currentQuality]; //this->currentBitrate = (uint64_t) this->representation->GetBandwidth(); - this->representation = this->adaptationSet->GetRepresentation().at(this->currentQuality); + this->representation = this->mpdWrapper->getRepresentationAt(this->type, this->currentQuality); this->currentBitrate = (uint64_t) this->availableBitrates[this->currentQuality]; Debug("STILL IN STARTUP - Current Bitrate:\t%I64u\n", this->currentBitrate); - Debug("ADAPTATION_LOGIC:\tFor %s:\tlast_buffer: %f\tbuffer_level: %f, instantaneousBw: %lu, AverageBW: %lu, choice: %d\n",isVideo ? "video" : "audio",(double)lastBufferFill/100 , (double)bufferFill/100, this->instantBw, this->averageBw , this->currentQuality); + Debug("ADAPTATION_LOGIC:\tFor %s:\tlast_buffer: %f\tbuffer_level: %f, instantaneousBw: %lu, AverageBW: %lu, choice: %d\n",(this->type == viper::managers::VIDEO) ? "video" : "audio",(double)lastBufferFill/100 , (double)bufferFill/100, this->instantBw, this->averageBw , this->currentQuality); this->lastBufferFill = bufferFill; return; } @@ -434,15 +440,15 @@ void BolaAdaptation::setBitrate(uint32_t bufferFill) // streamProcessor.getScheduleController().setTimeToLoadDelay(1000.0 * delaySeconds); // NEED TO CHECK THIS Debug("STEADY -- DELAY DOWNLOAD OF:\t%f\n", delaySeconds); - this->multimediaManager->setTargetDownloadingTime(this->isVideo, delaySeconds); + this->multimediaManager->setTargetDownloadingTime((this->type == viper::managers::StreamType::VIDEO), delaySeconds); } this->currentQuality = bolaQuality; //this->representation = this->availableBitrates[this->currentQuality]; - this->representation = this->adaptationSet->GetRepresentation().at(this->currentQuality); + this->representation = this->mpdWrapper->getRepresentationAt(this->type, this->currentQuality); this->currentBitrate = (uint64_t) this->availableBitrates[this->currentQuality]; Debug("STEADY - Current Bitrate:\t%I64u\n", this->currentBitrate); - Debug("ADAPTATION_LOGIC:\tFor %s:\tlast_buffer: %f\tbuffer_level: %f, instantaneousBw: %lu, AverageBW: %lu, choice: %d\n",isVideo ? "video" : "audio",(double)lastBufferFill/100 , (double)bufferFill/100, this->instantBw, this->averageBw , this->currentQuality); + Debug("ADAPTATION_LOGIC:\tFor %s:\tlast_buffer: %f\tbuffer_level: %f, instantaneousBw: %lu, AverageBW: %lu, choice: %d\n",(this->type == viper::managers::VIDEO) ? "video" : "audio",(double)lastBufferFill/100 , (double)bufferFill/100, this->instantBw, this->averageBw , this->currentQuality); this->lastBufferFill = bufferFill; } @@ -501,6 +507,8 @@ void BolaAdaptation::checkedByDASHReceiver() } void BolaAdaptation::bufferUpdate(uint32_t bufferFill, int maxC) { + this->mpdWrapper->acquireLock(); this->setBitrate(bufferFill); this->notifyBitrateChange(); + this->mpdWrapper->releaseLock(); } diff --git a/Adaptation/Bola.h b/Adaptation/Bola.h index 29011664..404e9968 100644 --- a/Adaptation/Bola.h +++ b/Adaptation/Bola.h @@ -29,7 +29,8 @@ namespace adaptation class BolaAdaptation : public AbstractAdaptationLogic { public: - BolaAdaptation (dash::mpd::IMPD *mpd, dash::mpd::IPeriod *period, dash::mpd::IAdaptationSet *adaptationSet, bool isVid, struct AdaptationParameters *params); +// BolaAdaptation (dash::mpd::IMPD *mpd, dash::mpd::IPeriod *period, dash::mpd::IAdaptationSet *adaptationSet, bool isVid, struct AdaptationParameters *params); + BolaAdaptation (viper::managers::StreamType type, libdash::framework::mpd::MPDWrapper *mpdWrapper, struct AdaptationParameters *params); virtual ~BolaAdaptation(); virtual LogicType getType(); @@ -58,58 +59,54 @@ private: STEADY // The buffer is primed (should be above bufferTarget) }; - bool initState; - double bufferMaxSizeSeconds; // Usually set to 30s - double bufferTargetSeconds; // It is passed as an init parameter. + bool initState; + double bufferMaxSizeSeconds; // Usually set to 30s + double bufferTargetSeconds; // It is passed as an init parameter. // It states the difference between STARTUP and STEADY // 12s following dash.js implementation - double bolaBufferTargetSeconds; // BOLA introduces a virtual buffer level in order to make quality decisions + double bolaBufferTargetSeconds; // BOLA introduces a virtual buffer level in order to make quality decisions // as it was filled (instead of the actual bufferTargetSeconds) - double bolaBufferMaxSeconds; // When using the virtual buffer, it must be capped. - - uint32_t bufferTargetPerc; // Computed considering a bufferSize = 30s - double totalDuration; // Total video duration in seconds (taken from MPD) - double segmentDuration; // Segment duration in seconds + double bolaBufferMaxSeconds; // When using the virtual buffer, it must be capped. + uint32_t bufferTargetPerc; // Computed considering a bufferSize = 30s + double totalDuration; // Total video duration in seconds (taken from MPD) + double segmentDuration; // Segment duration in seconds std::vector availableBitrates; std::vector utilityVector; - uint32_t bitrateCount; // Number of available bitrates - BolaState bolaState; // Keeps track of Bola state + uint32_t bitrateCount; // Number of available bitrates + BolaState bolaState; // Keeps track of Bola state // Bola Vp and gp (multiplied by the segment duration 'p') // They are dimensioned such that log utility would always prefer // - the lowest bitrate when bufferLevel = segmentDuration // - the highest bitrate when bufferLevel = bufferTarget - double Vp; - double gp; - - bool safetyGuarantee; - double maxRtt; - - double virtualBuffer; - - uint64_t currentBitrate; - int currentQuality; - uint64_t batchBw; - int batchBwCount; + double Vp; + double gp; + bool safetyGuarantee; + double maxRtt; + double virtualBuffer; + + uint64_t currentBitrate; + int currentQuality; + uint64_t batchBw; + int batchBwCount; std::vector batchBwSamples; - uint64_t instantBw; - uint64_t averageBw; - - double lastDownloadTimeInstant; - double currentDownloadTimeInstant; - double lastSegmentDownloadTime; - - uint32_t lastBufferFill; - bool bufferEOS; - bool shouldAbort; - double alphaRate; - bool isCheckedForReceiver; - + uint64_t instantBw; + uint64_t averageBw; + + double lastDownloadTimeInstant; + double currentDownloadTimeInstant; + double lastSegmentDownloadTime; + + uint32_t lastBufferFill; + bool bufferEOS; + bool shouldAbort; + double alphaRate; + bool isCheckedForReceiver; viper::managers::IMultimediaManagerBase *multimediaManager; - dash::mpd::IRepresentation *representation; + dash::mpd::IRepresentation *representation; }; } } diff --git a/Adaptation/BufferBasedAdaptation.cpp b/Adaptation/BufferBasedAdaptation.cpp index 18d4a592..eea7ef36 100644 --- a/Adaptation/BufferBasedAdaptation.cpp +++ b/Adaptation/BufferBasedAdaptation.cpp @@ -22,15 +22,13 @@ using namespace libdash::framework::adaptation; using namespace libdash::framework::input; using namespace libdash::framework::mpd; -BufferBasedAdaptation::BufferBasedAdaptation (IMPD *mpd, IPeriod *period, IAdaptationSet *adaptationSet, bool isVid, struct AdaptationParameters *params) : - AbstractAdaptationLogic (mpd, period, adaptationSet, isVid) +BufferBasedAdaptation::BufferBasedAdaptation (viper::managers::StreamType type, MPDWrapper *mpd, struct AdaptationParameters *params) : + AbstractAdaptationLogic (type, mpdWrapper) { this->reservoirThreshold = params->BufferBased_reservoirThreshold; this->maxThreshold = params->BufferBased_maxThreshold; - std::vector representations = this->adaptationSet->GetRepresentation(); - - this->representation = this->adaptationSet->GetRepresentation().at(0); +// this->representation = this->adaptationSet->GetRepresentation().at(0); this->multimediaManager = NULL; this->lastBufferFill = 0; this->bufferEOS = false; @@ -69,18 +67,19 @@ void BufferBasedAdaptation::setMultimediaManager (viper::managers::IMultimediaMa void BufferBasedAdaptation::notifyBitrateChange() { + this->mpdWrapper->setRepresentation(this->type, this->representation); if(this->multimediaManager) if(this->multimediaManager->isStarted() && !this->multimediaManager->isStopping()) - if(this->isVideo) - this->multimediaManager->setVideoQuality(this->period, this->adaptationSet, this->representation); + if(this->type == viper::managers::StreamType::VIDEO) + this->multimediaManager->setVideoQuality(); else - this->multimediaManager->setAudioQuality(this->period, this->adaptationSet, this->representation); + this->multimediaManager->setAudioQuality(); - if(this->shouldAbort) - { - this->multimediaManager->shouldAbort(this->isVideo); - } - this->shouldAbort = false; +// if(this->shouldAbort) +// { +// this->multimediaManager->shouldAbort((this->type == viper::managers::StreamType::VIDEO)); +// } +// this->shouldAbort = false; } uint64_t BufferBasedAdaptation::getBitrate() @@ -90,8 +89,8 @@ uint64_t BufferBasedAdaptation::getBitrate() void BufferBasedAdaptation::setBitrate(uint32_t bufferFill) { - std::vector representations; - representations = this->adaptationSet->GetRepresentation(); + std::vector representations = this->mpdWrapper->getRepresentations(this->type); + this->representation = representations.at(0); size_t i = 0; if(representations.size() == 1) @@ -112,7 +111,7 @@ void BufferBasedAdaptation::setBitrate(uint32_t bufferFill) { this->shouldAbort = true; } - Debug("ADAPTATION_LOGIC:\tFor %s:\tlast_buffer: %f\tbuffer_level: %f, choice: %lu, should_trigger_abort: %s\n",isVideo ? "video" : "audio",(double)lastBufferFill/100 , (double)bufferFill/100, i, this->shouldAbort ? "YES" : "NO"); + Debug("ADAPTATION_LOGIC:\tFor %s:\tlast_buffer: %f\tbuffer_level: %f, choice: %lu, should_trigger_abort: %s\n", (this->type == viper::managers::StreamType::VIDEO) ? "video" : "audio",(double)lastBufferFill/100 , (double)bufferFill/100, i, this->shouldAbort ? "YES" : "NO"); this->lastBufferFill = bufferFill; } @@ -136,6 +135,8 @@ void BufferBasedAdaptation::checkedByDASHReceiver() void BufferBasedAdaptation::bufferUpdate(uint32_t bufferFill, int maxC) { + this->mpdWrapper->acquireLock(); this->setBitrate(bufferFill); this->notifyBitrateChange(); + this->mpdWrapper->releaseLock(); } diff --git a/Adaptation/BufferBasedAdaptation.h b/Adaptation/BufferBasedAdaptation.h index 32ad8045..f610064f 100644 --- a/Adaptation/BufferBasedAdaptation.h +++ b/Adaptation/BufferBasedAdaptation.h @@ -29,7 +29,8 @@ namespace adaptation class BufferBasedAdaptation : public AbstractAdaptationLogic { public: - BufferBasedAdaptation(dash::mpd::IMPD *mpd, dash::mpd::IPeriod *period, dash::mpd::IAdaptationSet *adaptationSet, bool isVid, struct AdaptationParameters *params); +// BufferBasedAdaptation(dash::mpd::IMPD *mpd, dash::mpd::IPeriod *period, dash::mpd::IAdaptationSet *adaptationSet, bool isVid, struct AdaptationParameters *params); + BufferBasedAdaptation(viper::managers::StreamType type, libdash::framework::mpd::MPDWrapper *mpdWrapper, struct AdaptationParameters *params); virtual ~BufferBasedAdaptation(); virtual LogicType getType(); @@ -47,15 +48,15 @@ public: void checkedByDASHReceiver(); private: - uint64_t currentBitrate; + uint64_t currentBitrate; std::vector availableBitrates; viper::managers::IMultimediaManagerBase *multimediaManager; - dash::mpd::IRepresentation *representation; - uint32_t reservoirThreshold; - uint32_t maxThreshold; - uint32_t lastBufferFill; - bool bufferEOS; - bool shouldAbort; + dash::mpd::IRepresentation *representation; + uint32_t reservoirThreshold; + uint32_t maxThreshold; + uint32_t lastBufferFill; + bool bufferEOS; + bool shouldAbort; }; } } diff --git a/Adaptation/BufferBasedAdaptationWithRateBased.cpp b/Adaptation/BufferBasedAdaptationWithRateBased.cpp index 3a1895c0..3df1cf84 100644 --- a/Adaptation/BufferBasedAdaptationWithRateBased.cpp +++ b/Adaptation/BufferBasedAdaptationWithRateBased.cpp @@ -21,8 +21,8 @@ using namespace libdash::framework::adaptation; using namespace libdash::framework::input; using namespace libdash::framework::mpd; -BufferBasedAdaptationWithRateBased::BufferBasedAdaptationWithRateBased(IMPD *mpd, IPeriod *period, IAdaptationSet *adaptationSet, bool isVid, struct AdaptationParameters *params) : - AbstractAdaptationLogic(mpd, period, adaptationSet, isVid) +BufferBasedAdaptationWithRateBased::BufferBasedAdaptationWithRateBased(viper::managers::StreamType type, MPDWrapper *mpdWrapper, struct AdaptationParameters *params) : + AbstractAdaptationLogic(type, mpdWrapper) { this->alphaRate = params->Adaptech_Alpha; this->reservoirThreshold = params->Adaptech_FirstThreshold; @@ -30,18 +30,18 @@ BufferBasedAdaptationWithRateBased::BufferBasedAdaptationWithRateBased(IMPD *mpd this->switchUpThreshold = params->Adaptech_SwitchUpThreshold; this->slackParam = params->Adaptech_SlackParameter; - std::vector representations = this->adaptationSet->GetRepresentation(); - this->m_count = 0; this->instantBw = 0; this->averageBw = 0; - this->representation = this->adaptationSet->GetRepresentation().at(0); +// this->representation = this->adaptationSet->GetRepresentation().at(0); + this->multimediaManager = NULL; this->lastBufferFill = 0; this->bufferEOS = false; this->shouldAbort = false; this->isCheckedForReceiver = false; this->myQuality = 0; + this->currentBitrate = 0; Debug("BufferRateBasedParams:\talpha:%f\tfirst threshold: %f\tsecond threshold: %f\tswitch-up margin: %d\tSlack: %f\n",this->alphaRate, (double)reservoirThreshold/100, (double)maxThreshold/100, this->switchUpThreshold, this->slackParam); Debug("Buffer Adaptation: STARTED\n"); } @@ -75,18 +75,19 @@ void BufferBasedAdaptationWithRateBased::setMultimediaManager(viper::managers::I void BufferBasedAdaptationWithRateBased::notifyBitrateChange() { + this->mpdWrapper->setRepresentation(this->type, this->representation); if(this->multimediaManager) if(this->multimediaManager->isStarted() && !this->multimediaManager->isStopping()) - if(this->isVideo) - this->multimediaManager->setVideoQuality(this->period, this->adaptationSet, this->representation); + if(this->type==viper::managers::StreamType::VIDEO) + this->multimediaManager->setVideoQuality(); else - this->multimediaManager->setAudioQuality(this->period, this->adaptationSet, this->representation); + this->multimediaManager->setAudioQuality(); //Should Abort is done here to avoid race condition with DASHReceiver::DoBuffering() - if(this->shouldAbort) - { - this->multimediaManager->shouldAbort(this->isVideo); - } - this->shouldAbort = false; +// if(this->shouldAbort) +// { +// this->multimediaManager->shouldAbort((this->type == viper::managers::StreamType::VIDEO)); +// } +// this->shouldAbort = false; } uint64_t BufferBasedAdaptationWithRateBased::getBitrate() @@ -98,7 +99,7 @@ void BufferBasedAdaptationWithRateBased::setBitrate(uint32_t bufferFill) { uint32_t phi1, phi2; std::vector representations; - representations = this->adaptationSet->GetRepresentation(); + representations = this->mpdWrapper->getRepresentations(this->type); size_t i = 0; Debug("bufferlevel: %u, instant rate %lu, average rate %lu\n", bufferFill, this->instantBw, this->averageBw); @@ -167,7 +168,7 @@ void BufferBasedAdaptationWithRateBased::setBitrate(uint32_t bufferFill) } this->representation = representations.at(this->myQuality); this->currentBitrate = (uint64_t) this->representation->GetBandwidth(); - Debug("ADAPTATION_LOGIC:\tFor %s:\tlast_buffer: %f\tbuffer_level: %f, instantaneousBw: %lu, AverageBW: %lu, choice: %d\n",isVideo ? "video" : "audio",(double)lastBufferFill/100 , (double)bufferFill/100, this->instantBw, this->averageBw , this->myQuality); + Debug("ADAPTATION_LOGIC:\tFor %s:\tlast_buffer: %f\tbuffer_level: %f, instantaneousBw: %lu, AverageBW: %lu, choice: %d\n",(this->type == viper::managers::StreamType::VIDEO) ? "video" : "audio",(double)lastBufferFill/100 , (double)bufferFill/100, this->instantBw, this->averageBw , this->myQuality); } void BufferBasedAdaptationWithRateBased::bitrateUpdate(uint64_t bps, uint32_t segNum) @@ -196,11 +197,14 @@ void BufferBasedAdaptationWithRateBased::checkedByDASHReceiver() void BufferBasedAdaptationWithRateBased::bufferUpdate(uint32_t bufferFill, int maxC) { Debug("buffer update: %u\n", bufferFill); + EnterCriticalSection(&this->monitorLock); this->setBitrate(bufferFill); this->notifyBitrateChange(); + LeaveCriticalSection(&this->monitorLock); } void BufferBasedAdaptationWithRateBased::dLTimeUpdate(double time) { } + diff --git a/Adaptation/BufferBasedAdaptationWithRateBased.h b/Adaptation/BufferBasedAdaptationWithRateBased.h index 5c787d30..45147ed2 100644 --- a/Adaptation/BufferBasedAdaptationWithRateBased.h +++ b/Adaptation/BufferBasedAdaptationWithRateBased.h @@ -29,7 +29,8 @@ namespace adaptation class BufferBasedAdaptationWithRateBased : public AbstractAdaptationLogic { public: - BufferBasedAdaptationWithRateBased(dash::mpd::IMPD *mpd, dash::mpd::IPeriod *period, dash::mpd::IAdaptationSet *adaptationSet, bool isVid, struct AdaptationParameters *params); +// BufferBasedAdaptationWithRateBased(dash::mpd::IMPD *mpd, dash::mpd::IPeriod *period, dash::mpd::IAdaptationSet *adaptationSet, bool isVid, struct AdaptationParameters *params); + BufferBasedAdaptationWithRateBased(viper::managers::StreamType type, libdash::framework::mpd::MPDWrapper *mpdWrapper, struct AdaptationParameters *params); virtual ~BufferBasedAdaptationWithRateBased(); virtual LogicType getType(); @@ -48,22 +49,22 @@ public: private: uint64_t currentBitrate; - std::vector availableBitrates; - viper::managers::IMultimediaManagerBase *multimediaManager; - dash::mpd::IRepresentation *representation; + std::vector availableBitrates; + viper::managers::IMultimediaManagerBase *multimediaManager; + dash::mpd::IRepresentation *representation; uint32_t reservoirThreshold; uint32_t maxThreshold; uint32_t lastBufferFill; - int m_count; - int switchUpThreshold; - bool bufferEOS; - bool shouldAbort; - double alphaRate; + int m_count; + int switchUpThreshold; + bool bufferEOS; + bool shouldAbort; + double alphaRate; uint64_t averageBw; uint64_t instantBw; - int myQuality; - double slackParam; - bool isCheckedForReceiver; + int myQuality; + double slackParam; + bool isCheckedForReceiver; }; } } diff --git a/Adaptation/BufferBasedThreeThresholdAdaptation.cpp b/Adaptation/BufferBasedThreeThresholdAdaptation.cpp index 021e7b7c..7efab53a 100644 --- a/Adaptation/BufferBasedThreeThresholdAdaptation.cpp +++ b/Adaptation/BufferBasedThreeThresholdAdaptation.cpp @@ -20,23 +20,24 @@ using namespace dash::mpd; using namespace libdash::framework::adaptation; using namespace libdash::framework::input; using namespace libdash::framework::mpd; +using namespace viper::managers; -BufferBasedThreeThresholdAdaptation::BufferBasedThreeThresholdAdaptation(IMPD *mpd, IPeriod *period, IAdaptationSet *adaptationSet, bool isVid, struct AdaptationParameters *params) : - AbstractAdaptationLogic(mpd, period, adaptationSet, isVid) +BufferBasedThreeThresholdAdaptation::BufferBasedThreeThresholdAdaptation(viper::managers::StreamType type, MPDWrapper *mpdWrapper, struct AdaptationParameters *params) : + AbstractAdaptationLogic(type, mpdWrapper) { - this->firstThreshold = params->BufferThreeThreshold_FirstThreshold; - this->secondThreshold = params->BufferThreeThreshold_SecondThreshold; - this->thirdThreshold = params->BufferThreeThreshold_ThirdThreshold; - this->slackParam = params->BufferThreeThreshold_slackParameter; - std::vector representations = this->adaptationSet->GetRepresentation(); - this->representation = this->adaptationSet->GetRepresentation().at(0); - this->multimediaManager = NULL; - this->lastBufferFill = 0; - this->bufferEOS = false; - this->shouldAbort = false; - this->isCheckedForReceiver = false; - Debug("BufferRateBasedParams:\t%f\t%f\t%f\n",(double)this->firstThreshold/100, (double)secondThreshold/100, (double)thirdThreshold/100); - Debug("Buffer Adaptation: STARTED\n"); + this->firstThreshold = params->BufferThreeThreshold_FirstThreshold; + this->secondThreshold = params->BufferThreeThreshold_SecondThreshold; + this->thirdThreshold = params->BufferThreeThreshold_ThirdThreshold; + this->slackParam = params->BufferThreeThreshold_slackParameter; +// this->representation = this->adaptationSet->GetRepresentation().at(0); + this->multimediaManager = NULL; + this->lastBufferFill = 0; + this->bufferEOS = false; + this->shouldAbort = false; + this->isCheckedForReceiver = false; + this->currentBitrate = 0; + Debug("BufferRateBasedParams:\t%f\t%f\t%f\n",(double)this->firstThreshold/100, (double)secondThreshold/100, (double)thirdThreshold/100); + Debug("Buffer Adaptation: STARTED\n"); } BufferBasedThreeThresholdAdaptation::~BufferBasedThreeThresholdAdaptation() @@ -70,18 +71,19 @@ void BufferBasedThreeThresholdAdaptation::setMultimediaManager(viper::managers:: void BufferBasedThreeThresholdAdaptation::notifyBitrateChange() { - if(this->multimediaManager) - if(this->multimediaManager->isStarted() && !this->multimediaManager->isStopping()) - if(this->isVideo) - this->multimediaManager->setVideoQuality(this->period, this->adaptationSet, this->representation); - else - this->multimediaManager->setAudioQuality(this->period, this->adaptationSet, this->representation); - //Should Abort is done here to avoid race condition with DASHReceiver::DoBuffering() - if(this->shouldAbort) - { - this->multimediaManager->shouldAbort(this->isVideo); - } - this->shouldAbort = false; + this->mpdWrapper->setRepresentation(this->type, this->representation); + if(this->multimediaManager) + if(this->multimediaManager->isStarted() && !this->multimediaManager->isStopping()) + if(this->type == viper::managers::StreamType::VIDEO) + 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 BufferBasedThreeThresholdAdaptation::getBitrate() @@ -91,52 +93,53 @@ uint64_t BufferBasedThreeThresholdAdaptation::getBitrate() void BufferBasedThreeThresholdAdaptation::setBitrate(uint32_t bufferFill) { - uint32_t phi1, phi2; - std::vector representations; - representations = this->adaptationSet->GetRepresentation(); - size_t i = 0; - - if(this->isCheckedForReceiver) - { - return; - } - this->isCheckedForReceiver = true; - - - if(bufferFill < this->firstThreshold) - { - this->myQuality = 0; - } - else - { - if(bufferFill < this->secondThreshold) - { - if(this->currentBitrate >= this->instantBw) - { - if(this->myQuality > 0) - { - this->myQuality--; - } - } - } - else - { - if(bufferFill < this->thirdThreshold) - { - } - else - {// bufferLevel > thirdThreshold - if(this->currentBitrate <= this->instantBw) - { - if(this->myQuality < representations.size() - 1) - this->myQuality++; - } - } - } - } - this->representation = representations.at(this->myQuality); - this->currentBitrate = (uint64_t) this->representation->GetBandwidth(); - Debug("ADAPTATION_LOGIC:\tFor %s:\tlast_buffer: %f\tbuffer_level: %f, instantaneousBw: %lu, choice: %d\n",isVideo ? "video" : "audio",(double)lastBufferFill/100 , (double)bufferFill/100, this->instantBw, this->myQuality); + uint32_t phi1, phi2; + std::vector representations; + representations = this->mpdWrapper->getRepresentations(this->type); + this->representation = representations.at(0); + size_t i = 0; + + if(this->isCheckedForReceiver) + { + return; + } + this->isCheckedForReceiver = true; + + + if(bufferFill < this->firstThreshold) + { + this->myQuality = 0; + } + else + { + if(bufferFill < this->secondThreshold) + { + if(this->currentBitrate >= this->instantBw) + { + if(this->myQuality > 0) + { + this->myQuality--; + } + } + } + else + { + if(bufferFill < this->thirdThreshold) + { + } + else + {// bufferLevel > thirdThreshold + if(this->currentBitrate <= this->instantBw) + { + if(this->myQuality < representations.size() - 1) + this->myQuality++; + } + } + } + } + this->representation = representations.at(this->myQuality); + this->currentBitrate = (uint64_t) this->representation->GetBandwidth(); + Debug("ADAPTATION_LOGIC:\tFor %s:\tlast_buffer: %f\tbuffer_level: %f, instantaneousBw: %lu, choice: %d\n",(this->type == viper::managers::StreamType::VIDEO) ? "video" : "audio",(double)lastBufferFill/100 , (double)bufferFill/100, this->instantBw, this->myQuality); } void BufferBasedThreeThresholdAdaptation::bitrateUpdate(uint64_t bps, uint32_t segNum) @@ -155,8 +158,10 @@ void BufferBasedThreeThresholdAdaptation::checkedByDASHReceiver() } void BufferBasedThreeThresholdAdaptation::bufferUpdate(uint32_t bufferFill, int maxC) { + this->mpdWrapper->acquireLock(); this->setBitrate(bufferFill); this->notifyBitrateChange(); + this->mpdWrapper->releaseLock(); } void BufferBasedThreeThresholdAdaptation::dLTimeUpdate(double time) diff --git a/Adaptation/BufferBasedThreeThresholdAdaptation.h b/Adaptation/BufferBasedThreeThresholdAdaptation.h index 62160bc3..1448bae2 100644 --- a/Adaptation/BufferBasedThreeThresholdAdaptation.h +++ b/Adaptation/BufferBasedThreeThresholdAdaptation.h @@ -29,7 +29,8 @@ namespace adaptation class BufferBasedThreeThresholdAdaptation : public AbstractAdaptationLogic { public: - BufferBasedThreeThresholdAdaptation(dash::mpd::IMPD *mpd, dash::mpd::IPeriod *period, dash::mpd::IAdaptationSet *adaptationSet, bool isVid, struct AdaptationParameters *params); +// BufferBasedThreeThresholdAdaptation(dash::mpd::IMPD *mpd, dash::mpd::IPeriod *period, dash::mpd::IAdaptationSet *adaptationSet, bool isVid, struct AdaptationParameters *params); + BufferBasedThreeThresholdAdaptation(viper::managers::StreamType type, libdash::framework::mpd::MPDWrapper *mpdWrapper, struct AdaptationParameters *params); virtual ~BufferBasedThreeThresholdAdaptation(); virtual LogicType getType(); @@ -47,20 +48,20 @@ public: void checkedByDASHReceiver(); private: - uint64_t currentBitrate; + uint64_t currentBitrate; std::vector availableBitrates; viper::managers::IMultimediaManagerBase *multimediaManager; - dash::mpd::IRepresentation *representation; - uint32_t secondThreshold; - uint32_t thirdThreshold; - uint32_t lastBufferFill; - bool bufferEOS; - bool shouldAbort; - uint32_t firstThreshold; - uint64_t instantBw; - int myQuality; - double slackParam; - bool isCheckedForReceiver; + dash::mpd::IRepresentation *representation; + uint32_t secondThreshold; + uint32_t thirdThreshold; + uint32_t lastBufferFill; + bool bufferEOS; + bool shouldAbort; + uint32_t firstThreshold; + uint64_t instantBw; + int myQuality; + double slackParam; + bool isCheckedForReceiver; }; } } diff --git a/Adaptation/IAdaptationLogic.h b/Adaptation/IAdaptationLogic.h index bfe980c7..081366dd 100644 --- a/Adaptation/IAdaptationLogic.h +++ b/Adaptation/IAdaptationLogic.h @@ -58,9 +58,9 @@ public: virtual uint32_t getPosition() = 0; virtual void setPosition(uint32_t segmentNumber) = 0; virtual dash::mpd::IRepresentation* getRepresentation() = 0; - virtual void setRepresentation(dash::mpd::IPeriod *period, - dash::mpd::IAdaptationSet *adaptationSet, - dash::mpd::IRepresentation *representation)= 0; +// virtual void setRepresentation(dash::mpd::IPeriod *period, +// dash::mpd::IAdaptationSet *adaptationSet, +// dash::mpd::IRepresentation *representation)= 0; virtual LogicType getType() = 0; virtual bool isUserDependent()= 0; virtual void bitrateUpdate(uint64_t bps, uint32_t segNum) = 0; @@ -71,6 +71,7 @@ public: virtual void setMultimediaManager(viper::managers::IMultimediaManagerBase *mmManager)= 0; virtual void onEOS(bool value) = 0; virtual void checkedByDASHReceiver() = 0; +// virtual void updateMPD(dash::mpd::IMPD* mpd) = 0; }; struct AdaptationParameters diff --git a/Adaptation/Panda.cpp b/Adaptation/Panda.cpp index cb2ec660..e0c19b27 100644 --- a/Adaptation/Panda.cpp +++ b/Adaptation/Panda.cpp @@ -21,9 +21,10 @@ using namespace dash::mpd; using namespace libdash::framework::adaptation; using namespace libdash::framework::input; using namespace libdash::framework::mpd; +using namespace viper::managers; -PandaAdaptation::PandaAdaptation(IMPD *mpd, IPeriod *period, IAdaptationSet *adaptationSet, bool isVid, struct AdaptationParameters *params) : - AbstractAdaptationLogic (mpd, period, adaptationSet, isVid) +PandaAdaptation::PandaAdaptation(StreamType type, MPDWrapper *mpdWrapper, struct AdaptationParameters *params) : + AbstractAdaptationLogic (type, mpdWrapper) { this->param_Alpha = params->Panda_Alpha; this->param_Beta = params->Panda_Beta; @@ -52,17 +53,17 @@ PandaAdaptation::PandaAdaptation(IMPD *mpd, IPeriod *period, IAdaptationSet *ada this->downloadTime = 0.0; - this->isVideo = isVid; - this->mpd = mpd; - this->adaptationSet = adaptationSet; - this->period = period; +// this->mpd = mpd; +// this->adaptationSet = adaptationSet; +// this->period = period; this->multimediaManager = NULL; this->representation = NULL; this->currentBitrate = 0; this->current = 0; // Retrieve the available bitrates - std::vector representations = this->adaptationSet->GetRepresentation(); + this->mpdWrapper->acquireLock(); + std::vector representations = this->mpdWrapper->getRepresentations(this->type); this->availableBitrates.clear(); Debug("PANDA Available Bitrates...\n"); @@ -72,7 +73,7 @@ PandaAdaptation::PandaAdaptation(IMPD *mpd, IPeriod *period, IAdaptationSet *ada Debug("%d - %I64u bps\n", i+1, this->availableBitrates[i]); } - this->representation = this->adaptationSet->GetRepresentation().at(0); + 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); @@ -108,11 +109,12 @@ void PandaAdaptation::setMultimediaManager (viper::managers::IMultimediaManagerB void PandaAdaptation::notifyBitrateChange() { + this->mpdWrapper->setRepresentation(this->type, this->representation); if(this->multimediaManager->isStarted() && !this->multimediaManager->isStopping()) - if(this->isVideo) - this->multimediaManager->setVideoQuality(this->period, this->adaptationSet, this->representation); + if(this->type == viper::managers::StreamType::VIDEO) + this->multimediaManager->setVideoQuality(); else - this->multimediaManager->setAudioQuality(this->period, this->adaptationSet, this->representation); + this->multimediaManager->setAudioQuality(); } uint64_t PandaAdaptation::getBitrate() @@ -133,7 +135,7 @@ void PandaAdaptation::quantizer() Debug("** Smooth-BW UP:\t%d\t Smooth-BW DOWN:\t%d\n", smoothBw_UP, smoothBw_DOWN); std::vector representations; - representations = this->adaptationSet->GetRepresentation(); + representations = this->mpdWrapper->getRepresentations(this->type); uint32_t numQualLevels = representations.size(); // We have to find bitrateMin and bitrateMax @@ -188,7 +190,7 @@ void PandaAdaptation::quantizer() this->currentBitrate = bitrateDown; this->current = iDown; } - this->representation = this->adaptationSet->GetRepresentation().at(this->current); + this->representation = representations.at(this->current); } void PandaAdaptation::setBitrate(uint64_t bps) @@ -220,7 +222,7 @@ void PandaAdaptation::setBitrate(uint64_t bps) // 3. Quantization this->quantizer(); - Debug("ADAPTATION_LOGIC:\tFor %s:\tlast_buffer: %f\tbuffer_level: %f, instantaneousBw: %lu, AverageBW: %lu, choice: %d\n",isVideo ? "video" : "audio",(double)lastBufferLevel/100 , (double)bufferLevel/100, this->instantBw, this->averageBw , this->current); + Debug("ADAPTATION_LOGIC:\tFor %s:\tlast_buffer: %f\tbuffer_level: %f, instantaneousBw: %lu, AverageBW: %lu, choice: %d\n",(this->type == viper::managers::StreamType::VIDEO) ? "video" : "audio",(double)lastBufferLevel/100 , (double)bufferLevel/100, this->instantBw, this->averageBw , this->current); this->lastBufferLevel = this->bufferLevel; // 4. Computing the "actual inter time" @@ -233,7 +235,7 @@ void PandaAdaptation::setBitrate(uint64_t bps) this->interTime = this->interTime > 3 ? 3 : this->interTime; Debug("** ACTUAL INTER TIME:\t%f\n", this->interTime); - this->multimediaManager->setTargetDownloadingTime(this->isVideo, interTime); + this->multimediaManager->setTargetDownloadingTime((this->type == viper::managers::StreamType::VIDEO), interTime); } void PandaAdaptation::bitrateUpdate(uint64_t bps, uint32_t segNum) @@ -249,9 +251,10 @@ void PandaAdaptation::bitrateUpdate(uint64_t bps, uint32_t segNum) { this->averageBw = this->alpha_ewma*this->averageBw + (1 - this->alpha_ewma)*bps; } - + this->mpdWrapper->acquireLock(); this->setBitrate(bps); this->notifyBitrateChange(); + this->mpdWrapper->releaseLock(); } void PandaAdaptation::dLTimeUpdate(double time) diff --git a/Adaptation/Panda.h b/Adaptation/Panda.h index 000131a1..37b397fe 100644 --- a/Adaptation/Panda.h +++ b/Adaptation/Panda.h @@ -29,7 +29,8 @@ namespace adaptation class PandaAdaptation : public AbstractAdaptationLogic { public: - PandaAdaptation(dash::mpd::IMPD *mpd, dash::mpd::IPeriod *period, dash::mpd::IAdaptationSet *adaptationSet, bool isVid, struct AdaptationParameters *params); +// PandaAdaptation(dash::mpd::IMPD *mpd, dash::mpd::IPeriod *period, dash::mpd::IAdaptationSet *adaptationSet, bool isVid, struct AdaptationParameters *params); + PandaAdaptation(viper::managers::StreamType type, libdash::framework::mpd::MPDWrapper *mpdWrapper, struct AdaptationParameters *params); virtual ~PandaAdaptation(); virtual LogicType getType(); @@ -48,38 +49,36 @@ public: void quantizer(); private: - uint64_t currentBitrate; + uint64_t currentBitrate; std::vector availableBitrates; viper::managers::IMultimediaManagerBase *multimediaManager; - dash::mpd::IRepresentation *representation; + dash::mpd::IRepresentation *representation; - uint64_t averageBw; // Classic EWMA - uint64_t instantBw; - uint64_t smoothBw; // Panda paper smoothed y[n] - uint64_t targetBw; // Panda paper x[n] bw estimation + uint64_t averageBw; // Classic EWMA + uint64_t instantBw; + uint64_t smoothBw; // Panda paper smoothed y[n] + uint64_t targetBw; // Panda paper x[n] bw estimation + double param_Alpha; + double alpha_ewma; + double param_Epsilon; + double param_K; + double param_W; + double param_Beta; + double param_Bmin; + double interTime; // Actual inter time + double targetInterTime; // Target inter time + double downloadTime; - double param_Alpha; - double alpha_ewma; - double param_Epsilon; - double param_K; - double param_W; - double param_Beta; - double param_Bmin; + uint32_t bufferLevel; + uint32_t lastBufferLevel; + double bufferMaxSizeSeconds; // Usually set to 60s + double bufferLevelSeconds; // Current buffer level [s] - double interTime; // Actual inter time - double targetInterTime; // Target inter time - double downloadTime; - - uint32_t bufferLevel; - uint32_t lastBufferLevel; - double bufferMaxSizeSeconds; // Usually set to 60s - double bufferLevelSeconds; // Current buffer level [s] - - double segmentDuration; - double deltaUp; - double deltaDown; - size_t current; + double segmentDuration; + double deltaUp; + double deltaDown; + size_t current; }; } /* namespace adaptation */ diff --git a/Adaptation/RateBasedAdaptation.cpp b/Adaptation/RateBasedAdaptation.cpp index 73d4ee9b..14b3f3d6 100644 --- a/Adaptation/RateBasedAdaptation.cpp +++ b/Adaptation/RateBasedAdaptation.cpp @@ -19,11 +19,13 @@ using namespace dash::mpd; using namespace libdash::framework::adaptation; using namespace libdash::framework::input; using namespace libdash::framework::mpd; +using namespace viper::managers; -RateBasedAdaptation::RateBasedAdaptation(IMPD *mpd, IPeriod *period, IAdaptationSet *adaptationSet, bool isVid, struct AdaptationParameters *params) : - AbstractAdaptationLogic(mpd, period, adaptationSet, isVid) +RateBasedAdaptation::RateBasedAdaptation(StreamType type, MPDWrapper *mpdWrapper, struct AdaptationParameters *params) : + AbstractAdaptationLogic(type, mpdWrapper) { - std::vector representations = this->adaptationSet->GetRepresentation(); + this->mpdWrapper->acquireLock(); + std::vector representations = this->mpdWrapper->getRepresentations(type); this->availableBitrates.clear(); for(size_t i = 0; i < representations.size(); i++) @@ -32,6 +34,7 @@ RateBasedAdaptation::RateBasedAdaptation(IMPD *mpd, IPeriod *period, IAdaptation } this->currentBitrate = this->availableBitrates.at(0); this->representation = representations.at(0); + this->mpdWrapper->releaseLock(); this->multimediaManager = NULL; this->alpha = params->Rate_Alpha; Debug("RateBasedParams:\t%f\n",alpha); @@ -69,11 +72,12 @@ void RateBasedAdaptation::setMultimediaManager(viper::managers::IMultimediaManag void RateBasedAdaptation::notifyBitrateChange() { + this->mpdWrapper->setRepresentation(this->type, this->representation); if(this->multimediaManager->isStarted() && !this->multimediaManager->isStopping()) - if(this->isVideo) - this->multimediaManager->setVideoQuality(this->period, this->adaptationSet, this->representation); + if(this->type == viper::managers::StreamType::VIDEO) + this->multimediaManager->setVideoQuality(); else - this->multimediaManager->setAudioQuality(this->period, this->adaptationSet, this->representation); + this->multimediaManager->setAudioQuality(); } uint64_t RateBasedAdaptation::getBitrate() @@ -84,7 +88,7 @@ uint64_t RateBasedAdaptation::getBitrate() void RateBasedAdaptation::setBitrate(uint64_t bps) { std::vector representations; - representations = this->adaptationSet->GetRepresentation(); + representations = this->mpdWrapper->getRepresentations(this->type); size_t i = 0; this->ewma(bps); for(i = 0;i < representations.size();i++) @@ -99,7 +103,7 @@ void RateBasedAdaptation::setBitrate(uint64_t bps) if((size_t)i == (size_t)(representations.size())) i = i-1; - Debug("ADAPTATION_LOGIC:\tFor %s:\tBW_estimation(ewma): %lu, choice: %lu\n", (this->isVideo ? "video" : "audio"), this->averageBw, i); + Debug("ADAPTATION_LOGIC:\tFor %s:\tBW_estimation(ewma): %lu, choice: %lu\n", ((this->type == viper::managers::StreamType::VIDEO) ? "video" : "audio"), this->averageBw, i); this->representation = representations.at(i); this->currentBitrate = this->representation->GetBandwidth(); } @@ -107,8 +111,10 @@ void RateBasedAdaptation::setBitrate(uint64_t bps) void RateBasedAdaptation::bitrateUpdate(uint64_t bps, uint32_t segNum) { Debug("Rate Based adaptation: speed received: %lu\n", bps); + this->mpdWrapper->acquireLock(); this->setBitrate(bps); this->notifyBitrateChange(); + this->mpdWrapper->releaseLock(); } void RateBasedAdaptation::ewma(uint64_t bps) diff --git a/Adaptation/RateBasedAdaptation.h b/Adaptation/RateBasedAdaptation.h index cbf7471c..670bc031 100644 --- a/Adaptation/RateBasedAdaptation.h +++ b/Adaptation/RateBasedAdaptation.h @@ -29,7 +29,8 @@ namespace adaptation class RateBasedAdaptation : public AbstractAdaptationLogic { public: - RateBasedAdaptation(dash::mpd::IMPD *mpd, dash::mpd::IPeriod *period, dash::mpd::IAdaptationSet *adaptationSet, bool isVid, struct AdaptationParameters *params); +// RateBasedAdaptation(dash::mpd::IMPD *mpd, dash::mpd::IPeriod *period, dash::mpd::IAdaptationSet *adaptationSet, bool isVid, struct AdaptationParameters *params); + RateBasedAdaptation(viper::managers::StreamType type, libdash::framework::mpd::MPDWrapper *mpdWrapper, struct AdaptationParameters *params); virtual ~RateBasedAdaptation(); virtual LogicType getType(); @@ -47,12 +48,12 @@ public: void ewma(uint64_t bps); void checkedByDASHReceiver(); private: - uint64_t currentBitrate; + uint64_t currentBitrate; std::vector availableBitrates; viper::managers::IMultimediaManagerBase *multimediaManager; - dash::mpd::IRepresentation *representation; - double alpha; - uint64_t averageBw; + dash::mpd::IRepresentation *representation; + double alpha; + uint64_t averageBw; }; } } diff --git a/Common/ViperBuffer.cpp b/Common/ViperBuffer.cpp index 27ec8b5e..c59cec04 100644 --- a/Common/ViperBuffer.cpp +++ b/Common/ViperBuffer.cpp @@ -12,7 +12,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - +#include #include "ViperBuffer.h" ViperBuffer::ViperBuffer(QObject* parent) : QIODevice(parent) @@ -76,17 +76,18 @@ qint64 ViperBuffer::readData(char* data, qint64 maxSize) qint64 ViperBuffer::writeData(libdash::framework::input::MediaObject* media) { pthread_mutex_lock(&(this->monitorMutex)); + int ret = 0; int total = 0; ret = media->ReadInitSegment(readBuffer,readMax); total += ret; this->writeData((const char *)readBuffer, ret); - ret = media->Read(readBuffer,readMax); while(ret) { total += ret; this->writeData((const char *)readBuffer, ret); + ret = media->Read(readBuffer,readMax); } pthread_mutex_unlock(&(this->monitorMutex)); diff --git a/Input/DASHManager.cpp b/Input/DASHManager.cpp index a86263dc..4d52a638 100644 --- a/Input/DASHManager.cpp +++ b/Input/DASHManager.cpp @@ -17,8 +17,9 @@ using namespace libdash::framework::buffer; using namespace dash; using namespace dash::network; using namespace dash::mpd; +using namespace libdash::framework::mpd; -DASHManager::DASHManager(viper::managers::StreamType type, uint32_t maxCapacity, IDASHManagerObserver* stream, IMPD* mpd, bool icnEnabled, double icnAlpha, bool nodecoding, float beta, float drop) : +DASHManager::DASHManager(viper::managers::StreamType type, uint32_t maxCapacity, IDASHManagerObserver* stream, MPDWrapper* mpdWrapper, bool icnEnabled, double icnAlpha, bool nodecoding, float beta, float drop) : readSegmentCount (0), receiver (NULL), multimediaStream (stream), @@ -33,7 +34,7 @@ DASHManager::DASHManager(viper::managers::StreamType type, uint32_t maxCapacity, this->buffer = new Buffer(maxCapacity,libdash::framework::buffer::VIDEO); this->buffer->attachObserver(this); - this->receiver = new DASHReceiver(mpd, this, this->buffer, maxCapacity, this->isICN(), this->icnAlpha, this->beta, this->drop); + this->receiver = new DASHReceiver(type, mpdWrapper, this, this->buffer, maxCapacity, this->isICN(), this->icnAlpha, this->beta, this->drop); } DASHManager::~DASHManager() { @@ -107,14 +108,14 @@ void DASHManager::clear() this->buffer->clear(); } -void DASHManager::setRepresentation(IPeriod *period, IAdaptationSet *adaptationSet, IRepresentation *representation) +void DASHManager::setRepresentation() { - this->receiver->SetRepresentation(period, adaptationSet, representation); + this->receiver->SetRepresentation(); } void DASHManager::enqueueRepresentation(IPeriod *period, IAdaptationSet *adaptationSet, IRepresentation *representation) { - this->receiver->SetRepresentation(period, adaptationSet, representation); +// this->receiver->SetRepresentation(period, adaptationSet, representation); } void DASHManager::onSegmentDownloaded() @@ -159,3 +160,13 @@ void DASHManager::onBufferStateChanged(BufferType type, uint32_t fillstateInPerc if(this->adaptationLogic->isBufferBased()) this->receiver->OnSegmentBufferStateChanged(fillstateInPercent, maxC); } + +void DASHManager::updateMPD(IMPD* mpd) +{ +// this->receiver->updateMPD(mpd); +} + +void DASHManager::fetchMPD() +{ + this->multimediaStream->fetchMPD(); +} diff --git a/Input/DASHManager.h b/Input/DASHManager.h index 2b723426..6bd54da9 100644 --- a/Input/DASHManager.h +++ b/Input/DASHManager.h @@ -22,18 +22,21 @@ #include "../Managers/IStreamObserver.h" #include "../Buffer/IBufferObserver.h" - namespace libdash { namespace framework { +namespace mpd +{ +class MPDWrapper; +} namespace input { class DASHManager : public IDASHReceiverObserver, public IBufferObserver { public: - DASHManager (viper::managers::StreamType type, uint32_t maxCapacity, IDASHManagerObserver *multimediaStream, dash::mpd::IMPD *mpd, bool icnEnabled, double icnAlpha, bool nodecoding, float beta, float drop); + DASHManager (viper::managers::StreamType type, uint32_t maxCapacity, IDASHManagerObserver *multimediaStream, libdash::framework::mpd::MPDWrapper *mpdWrapper, bool icnEnabled, double icnAlpha, bool nodecoding, float beta, float drop); virtual ~DASHManager (); bool start(); @@ -43,7 +46,8 @@ public: void setLooping(bool looping); void setPositionInMsec(uint32_t millisec); void clear(); - void setRepresentation(dash::mpd::IPeriod *period, dash::mpd::IAdaptationSet *adaptationSet, dash::mpd::IRepresentation *representation); +// void setRepresentation(dash::mpd::IPeriod *period, dash::mpd::IAdaptationSet *adaptationSet, dash::mpd::IRepresentation *representation); + void setRepresentation(); void enqueueRepresentation(dash::mpd::IPeriod *period, dash::mpd::IAdaptationSet *adaptationSet, dash::mpd::IRepresentation *representation); void onSegmentDownloaded(); @@ -58,19 +62,20 @@ public: void setTargetDownloadingTime(double); MediaObject* getSegment(); void onBufferStateChanged(BufferType type, uint32_t fillstateInPercent, int maxC); + void updateMPD(dash::mpd::IMPD* mpd); + void fetchMPD(); private: - float beta; - float drop; - buffer::Buffer *buffer; - DASHReceiver *receiver; - uint32_t readSegmentCount; - IDASHManagerObserver *multimediaStream; + float beta; + float drop; + buffer::Buffer *buffer; + DASHReceiver *receiver; + uint32_t readSegmentCount; + IDASHManagerObserver *multimediaStream; bool isRunning; bool icn; double icnAlpha; bool noDecoding; - libdash::framework::adaptation::IAdaptationLogic *adaptationLogic; }; } diff --git a/Input/DASHReceiver.cpp b/Input/DASHReceiver.cpp index bbfe3e35..aaa75205 100644 --- a/Input/DASHReceiver.cpp +++ b/Input/DASHReceiver.cpp @@ -19,44 +19,47 @@ using namespace dash::mpd; using duration_in_seconds = std::chrono::duration >; -DASHReceiver::DASHReceiver (IMPD *mpd, IDASHReceiverObserver *obs, Buffer *buffer, uint32_t bufferSize, bool icnEnabled, double icnAlpha, float beta, float drop) : - mpd (mpd), - period (NULL), - adaptationSet (NULL), - representation (NULL), - adaptationSetStream (NULL), - representationStream (NULL), - segmentNumber (0), - observer (obs), - buffer (buffer), - bufferSize (bufferSize), - isBuffering (false), - withFeedBack (false), - icn (icnEnabled), - icnAlpha (icnAlpha), - previousQuality (0), - isPaused (false), - threadComplete (false), - isScheduledPaced (false), - targetDownload (0.0), - downloadingTime (0.0), - bufferLevelAtUpdate (0), - isBufferBased (false), - isLooping (false), - beta (beta), - drop (drop) +DASHReceiver::DASHReceiver (viper::managers::StreamType type, MPDWrapper *mpdWrapper, IDASHReceiverObserver *obs, Buffer *buffer, uint32_t bufferSize, bool icnEnabled, double icnAlpha, float beta, float drop) : + type (type), + mpdWrapper (mpdWrapper), +// period (NULL), +// adaptationSet (NULL), +// representation (NULL), + adaptationSetStream (NULL), +// representationStream (NULL), + segmentNumber (0), + observer (obs), + buffer (buffer), + bufferSize (bufferSize), + isBuffering (false), + withFeedBack (false), + icn (icnEnabled), + icnAlpha (icnAlpha), + previousQuality (0), + isPaused (false), + threadComplete (false), + isScheduledPaced (false), + targetDownload (0.0), + downloadingTime (0.0), + bufferLevelAtUpdate (0), + isBufferBased (false), + isLooping (false), + beta (beta), + drop (drop), + bufferingThread (NULL), + mpdFetcherThread (NULL) { readMax = 32768; readBuffer = (uint8_t*)malloc(sizeof(uint8_t)*readMax); - this->period = this->mpd->GetPeriods().at(0); - this->adaptationSet = this->period->GetAdaptationSets().at(0); - this->representation = this->adaptationSet->GetRepresentation().at(0); +// this->period = this->mpd->GetPeriods().at(0); +// this->adaptationSet = this->period->GetAdaptationSets().at(0); +// this->representation = this->adaptationSet->GetRepresentation().at(0); - this->adaptationSetStream = new AdaptationSetStream(mpd, period, adaptationSet); - this->representationStream = adaptationSetStream->getRepresentationStream(this->representation); + this->adaptationSetStream = new AdaptationSetStream(type, mpdWrapper); +// this->representationStream = adaptationSetStream->getRepresentationStream(this->representation); this->segmentOffset = CalculateSegmentOffset(); - this->representationStream->setSegmentOffset(this->segmentOffset); - +// this->representationStream->setSegmentOffset(this->segmentOffset); + this->mpdWrapper->setSegmentOffset(type, this->segmentOffset); this->conn = NULL; this->initConn = NULL; readMax = 32768; @@ -103,7 +106,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() @@ -119,83 +130,43 @@ void DASHReceiver::Stop() JoinThread(this->bufferingThread); destroyThreadPortable(this->bufferingThread); } - this->period = this->mpd->GetPeriods().at(0); - this->adaptationSet = this->period->GetAdaptationSets().at(0); - this->representation = this->adaptationSet->GetRepresentation().at(0); + if(this->mpdFetcherThread != NULL) + { + JoinThread(this->mpdFetcherThread); + destroyThreadPortable(this->mpdFetcherThread); + } } MediaObject* DASHReceiver::GetNextSegment () { - ISegment *seg = NULL; EnterCriticalSection(&this->monitorPausedMutex); while(this->isPaused) SleepConditionVariableCS(&this->paused, &this->monitorPausedMutex, INFINITE); - if(!strcmp(this->mpd->GetType().c_str(), "static")) - { - if(this->segmentNumber >= this->representationStream->getSize()) - { - qDebug("looping? : %s\n", this->isLooping ? "YES" : "NO"); - if(this->isLooping) - { - this->segmentNumber = 0; - } - else - { - LeaveCriticalSection(&this->monitorPausedMutex); - return NULL; - } - } - } - seg = this->representationStream->getMediaSegment(this->segmentNumber); - - if (seg != NULL) - { - std::vector rep = this->adaptationSet->GetRepresentation(); - - this->NotifyQualityDownloading(this->representation->GetBandwidth()); + MediaObject *media = this->mpdWrapper->getNextSegment(type, isLooping, this->segmentNumber, withFeedBack); - MediaObject *media = new MediaObject(seg, this->representation,this->withFeedBack); - this->segmentNumber++; - LeaveCriticalSection(&this->monitorPausedMutex); - return media; - } + if(media) + this->NotifyQualityDownloading(media->GetRepresentationBandwidth()); LeaveCriticalSection(&this->monitorPausedMutex); - return NULL; + return media; } MediaObject* DASHReceiver::GetSegment (uint32_t segNum) { - ISegment *seg = NULL; - - if(segNum >= this->representationStream->getSize()) - return NULL; - - seg = this->representationStream->getMediaSegment(segNum); - - if (seg != NULL) - { - MediaObject *media = new MediaObject(seg, this->representation); - return media; - } - - return NULL; + return this->mpdWrapper->getSegment(type, segNum); } + MediaObject* DASHReceiver::GetInitSegment () { - ISegment *seg = NULL; - - seg = this->representationStream->getInitializationSegment(); - - if (seg != NULL) - { - MediaObject *media = new MediaObject(seg, this->representation); - return media; - } + return this->mpdWrapper->getInitSegment(type); +} - return NULL; +MediaObject* DASHReceiver::GetInitSegmentWithoutLock () +{ + return this->mpdWrapper->getInitSegmentWithoutLock(type); } -MediaObject* DASHReceiver::FindInitSegment (dash::mpd::IRepresentation *representation) + +MediaObject* DASHReceiver::FindInitSegment (int representation) { if (!this->InitSegmentExists(representation)) return NULL; @@ -224,45 +195,9 @@ void DASHReceiver::NotifyQualityDownloading (uint32_t quality) this->observer->notifyQualityDownloading(quality); } -void DASHReceiver::SetRepresentation (IPeriod *period, IAdaptationSet *adaptationSet, IRepresentation *representation) +void DASHReceiver::SetRepresentation () { - EnterCriticalSection(&this->monitorMutex); - - bool periodChanged = false; - - if (this->representation == representation) - { - LeaveCriticalSection(&this->monitorMutex); - return; - } - - this->representation = representation; - - if (this->adaptationSet != adaptationSet) - { - this->adaptationSet = adaptationSet; - - if (this->period != period) - { - this->period = period; - periodChanged = true; - } - - delete this->adaptationSetStream; - this->adaptationSetStream = NULL; - - this->adaptationSetStream = new AdaptationSetStream(this->mpd, this->period, this->adaptationSet); - } - - this->representationStream = this->adaptationSetStream->getRepresentationStream(this->representation); - this->DownloadInitSegment(this->representation); - - if (periodChanged) - { - this->segmentNumber = 0; - this->CalculateSegmentOffset(); - } - LeaveCriticalSection(&this->monitorMutex); + this->DownloadInitSegmentWithoutLock(); } libdash::framework::adaptation::IAdaptationLogic* DASHReceiver::GetAdaptationLogic () @@ -271,19 +206,13 @@ libdash::framework::adaptation::IAdaptationLogic* DASHReceiver::GetAdaptationLog } dash::mpd::IRepresentation* DASHReceiver::GetRepresentation () { - return this->representation; + return NULL; } uint32_t DASHReceiver::CalculateSegmentOffset () { - if (mpd->GetType() == "static") - return 0; - - uint32_t firstSegNum = this->representationStream->getFirstSegmentNumber(); - uint32_t currSegNum = this->representationStream->getCurrentSegmentNumber(); - uint32_t startSegNum = currSegNum - 2*bufferSize; - - return (startSegNum > firstSegNum) ? startSegNum : firstSegNum; + return this->mpdWrapper->calculateSegmentOffset(type, bufferSize); } + void DASHReceiver::NotifySegmentDownloaded () { this->observer->onSegmentDownloaded(); @@ -291,14 +220,32 @@ void DASHReceiver::NotifySegmentDownloaded () void DASHReceiver::NotifyBitrateChange(dash::mpd::IRepresentation *representation) { - if(this->representation != representation) +// if(this->representation != representation) +// { +// this->representation = representation; +// this->SetRepresentation(this->period,this->adaptationSet,this->representation); +// } +} +void DASHReceiver::DownloadInitSegmentWithoutLock () +{ + int rep = std::stoi(this->mpdWrapper->getRepresentationIDWithoutLock(type).c_str()); + if (this->InitSegmentExists(rep)) + return; + + MediaObject *initSeg = NULL; + initSeg = this->GetInitSegmentWithoutLock(); + + if (initSeg) { - this->representation = representation; - this->SetRepresentation(this->period,this->adaptationSet,this->representation); + initSeg->StartDownload(this->initConn); + this->initSegments[rep] = initSeg; + initSeg->WaitFinished(); } } -void DASHReceiver::DownloadInitSegment (IRepresentation* rep) + +void DASHReceiver::DownloadInitSegment () { + int rep = std::stoi(this->mpdWrapper->getRepresentationID(type).c_str()); if (this->InitSegmentExists(rep)) return; @@ -312,7 +259,8 @@ void DASHReceiver::DownloadInitSegment (IRepresentatio initSeg->WaitFinished(); } } -bool DASHReceiver::InitSegmentExists (IRepresentation* rep) + +bool DASHReceiver::InitSegmentExists (int rep) { if (this->initSegments.find(rep) != this->initSegments.end()) return true; @@ -358,20 +306,18 @@ void DASHReceiver::OnEOS(bool value) bool DASHReceiver::PushBack(MediaObject *mediaObject) { - MediaObject *init = this->FindInitSegment(mediaObject->GetRepresentation()); + MediaObject *init = this->FindInitSegment(mediaObject->GetRepresentationID()); mediaObject->AddInitSegment(init); //TODO the read should be in a function //Grab the infos for the analytics: bitrate, fps - dash::mpd::IRepresentation* datRep = mediaObject->GetRepresentation(); uint32_t bitrate = 0; int fps = 0; uint32_t quality = 0; - bitrate = datRep->GetBandwidth(); - quality = datRep->GetHeight(); + bitrate = mediaObject->GetRepresentationBandwidth(); + quality = mediaObject->GetRepresentationHeight(); fps = this->bufferLevelAtUpdate; this->observer->notifyStatistics((int)this->segmentNumber - 1, bitrate, fps, quality); - return(this->buffer->pushBack(mediaObject)); } @@ -380,7 +326,7 @@ void* DASHReceiver::DoBuffering (void *recei { DASHReceiver *dashReceiver = (DASHReceiver *) receiver; - dashReceiver->DownloadInitSegment(dashReceiver->GetRepresentation()); + dashReceiver->DownloadInitSegment(); MediaObject *media = dashReceiver->GetNextSegment(); dashReceiver->NotifyCheckedAdaptationLogic(); @@ -426,6 +372,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 () { @@ -454,4 +419,30 @@ void DASHReceiver::SetDrop (float drop) this->drop = drop; } +void DASHReceiver::updateMPD(IMPD* mpd) +{ +// EnterCriticalSection(&this->monitorMutex); + //First we need to find the new segmentNumber -> what is the segment time now? +// uint32_t time = this->representationStream->getTime(this->segmentNumber); +// printf("old segmentNumber!: %d\n", this->segmentNumber); +// printf("time: %u\n", time); + //Second, replace the MPD with the new one +// delete(this->mpd); +// this->mpd = mpd; +// + //Third, Update all the structures associated to the mpd +// this->period = this->mpd->GetPeriods().at(0); +// this->adaptationSet = this->period->GetAdaptationSets().at(0); +// this->representation = this->adaptationSet->GetRepresentation().at(0); +// delete(this->adaptationSetStream); +// this->adaptationSetStream = new AdaptationSetStream(mpd, period, adaptationSet); +// this->representationStream = adaptationSetStream->getRepresentationStream(this->representation); +// this->segmentOffset = CalculateSegmentOffset(); +// this->representationStream->setSegmentOffset(this->segmentOffset); +// + //Fourth, Set the new segmentNumber by finding the index of the segment associated to 'uint32_t time' in the new mpd +// this->segmentNumber = this->representationStream->getSegmentNumber(time); +// printf("new segmentNumber!: %d\n", this->segmentNumber); +// LeaveCriticalSection(&this->monitorMutex); +} diff --git a/Input/DASHReceiver.h b/Input/DASHReceiver.h index a2893b4d..cf56166b 100644 --- a/Input/DASHReceiver.h +++ b/Input/DASHReceiver.h @@ -14,7 +14,7 @@ #include "libdash.h" #include "IMPD.h" - +#include "../MPD/MPDWrapper.h" #include "../Input/MediaObject.h" #include "IDASHReceiverObserver.h" #include "../MPD/AdaptationSetStream.h" @@ -28,6 +28,10 @@ namespace libdash { namespace framework { +namespace mpd +{ +class AdaptationSetStream; +} namespace adaptation { class IAdaptationLogic; @@ -44,7 +48,7 @@ class MediaObject; class DASHReceiver { public: - DASHReceiver(dash::mpd::IMPD *mpd, IDASHReceiverObserver *obs, buffer::Buffer *buffer, uint32_t bufferSize, bool icnEnabled, double icnAlpha, float beta, float drop); + DASHReceiver(viper::managers::StreamType type, libdash::framework::mpd::MPDWrapper *mpdWrapper, IDASHReceiverObserver *obs, buffer::Buffer *buffer, uint32_t bufferSize, bool icnEnabled, double icnAlpha, float beta, float drop); virtual ~DASHReceiver(); bool Start(); @@ -52,15 +56,18 @@ public: input::MediaObject* GetNextSegment(); input::MediaObject* GetSegment(uint32_t segmentNumber); input::MediaObject* GetInitSegment(); - input::MediaObject* FindInitSegment(dash::mpd::IRepresentation *representation); + input::MediaObject* GetInitSegmentWithoutLock(); +// input::MediaObject* FindInitSegment(dash::mpd::IRepresentation *representation); + input::MediaObject* FindInitSegment(int representation); uint32_t GetPosition(); void SetPosition(uint32_t segmentNumber); void SetLooping(bool isLoopinp); void SetPositionInMsecs(uint32_t milliSecs); dash::mpd::IRepresentation* GetRepresentation(); - void SetRepresentation(dash::mpd::IPeriod *period, - dash::mpd::IAdaptationSet *adaptationSet, - dash::mpd::IRepresentation *representation); +// void SetRepresentation(dash::mpd::IPeriod *period, +// dash::mpd::IAdaptationSet *adaptationSet, +// dash::mpd::IRepresentation *representation); + void SetRepresentation(); void SetAdaptationLogic(adaptation::IAdaptationLogic *_adaptationLogic); libdash::framework::adaptation::IAdaptationLogic* GetAdaptationLogic(); void NotifyQualityDownloading(uint32_t quality); @@ -78,21 +85,24 @@ public: bool CanPush(); void SetBeta(float beta); void SetDrop(float drop); + void updateMPD(dash::mpd::IMPD* mpd); private: float beta; float drop; bool withFeedBack; bool isBufferBased; - std::map initSegments; +// std::map initSegments; + std::map initSegments; libdash::framework::buffer::Buffer *buffer; IDASHReceiverObserver *observer; - dash::mpd::IMPD *mpd; - dash::mpd::IPeriod *period; - dash::mpd::IAdaptationSet *adaptationSet; - dash::mpd::IRepresentation *representation; + libdash::framework::mpd::MPDWrapper *mpdWrapper; +// dash::mpd::IMPD *mpd; +// dash::mpd::IPeriod *period; +// dash::mpd::IAdaptationSet *adaptationSet; +// dash::mpd::IRepresentation *representation; mpd::AdaptationSetStream *adaptationSetStream; - mpd::IRepresentationStream *representationStream; +// mpd::IRepresentationStream *representationStream; uint32_t segmentNumber; uint32_t positionInMsecs; uint32_t segmentOffset; @@ -109,6 +119,7 @@ private: IICNConnection *conn; IICNConnection *initConn; THREAD_HANDLE bufferingThread; + THREAD_HANDLE mpdFetcherThread; bool isBuffering; bool icn; double icnAlpha; @@ -116,11 +127,16 @@ private: int bufferLevelAtUpdate; int readMax; uint8_t *readBuffer; + viper::managers::StreamType type; uint32_t CalculateSegmentOffset(); void NotifySegmentDownloaded(); - void DownloadInitSegment(dash::mpd::IRepresentation* rep); - bool InitSegmentExists(dash::mpd::IRepresentation* rep); +// void DownloadInitSegment(dash::mpd::IRepresentation* rep); + void DownloadInitSegment(); + void DownloadInitSegmentWithoutLock(); +// bool InitSegmentExists(dash::mpd::IRepresentation* rep); + bool InitSegmentExists(int rep); static void* DoBuffering(void *receiver); + static void* DoMPDFetching(void * data); }; } } diff --git a/Input/ICNConnectionConsumerApi.cpp b/Input/ICNConnectionConsumerApi.cpp index 8f28e5ce..04b378df 100644 --- a/Input/ICNConnectionConsumerApi.cpp +++ b/Input/ICNConnectionConsumerApi.cpp @@ -68,7 +68,7 @@ ICNConnectionConsumerApi::ICNConnectionConsumerApi(double alpha, float beta, flo } if(!configFile) { - qDebug("beta %f, drop %f", this->beta, this->drop); +// qDebug("beta %f, drop %f", this->beta, this->drop); // this->myConsumer->setSocketOption(RaaqmTransportOptions::BETA_VALUE, this->beta); // this->myConsumer->setSocketOption(RaaqmTransportOptions::DROP_FACTOR, this->drop); } @@ -104,8 +104,8 @@ void ICNConnectionConsumerApi::Init(IChunk *chunk) { m_isFinished = false; res = false; - qDebug("ICN_Connection:\tINTIATED_to_name %s\n", m_name.c_str()); - qDebug("ICN_Connection:\tSTARTING DOWNLOAD %s\n", m_name.c_str()); + Debug("ICN_Connection:\tINTIATED_to_name %s\n", m_name.c_str()); + Debug("ICN_Connection:\tSTARTING DOWNLOAD %s\n", m_name.c_str()); } void ICNConnectionConsumerApi::InitForMPD(const std::string& url) @@ -118,7 +118,6 @@ void ICNConnectionConsumerApi::InitForMPD(const std::string& url) res = false; dataPos = 0; datSize = 0; - Debug("ICN_Connection:\tINTIATED_for_mpd %s\n", m_name.c_str()); } @@ -134,7 +133,6 @@ int ICNConnectionConsumerApi::Read(uint8_t *data, size_t len) std::string s(m_name.c_str()); hTTPClientConnection->get(s); response = hTTPClientConnection->response(); - std::cout << m_name.c_str()<< " SIZE:" << response.size() << std::endl; this->res = true; this->dataPos = 0; } diff --git a/Input/IDASHManagerObserver.h b/Input/IDASHManagerObserver.h index c5df8fe9..1003d8a1 100644 --- a/Input/IDASHManagerObserver.h +++ b/Input/IDASHManagerObserver.h @@ -34,6 +34,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/Input/MediaObject.cpp b/Input/MediaObject.cpp index ae6b9f6b..f479a886 100644 --- a/Input/MediaObject.cpp +++ b/Input/MediaObject.cpp @@ -26,6 +26,9 @@ MediaObject::MediaObject(ISegment *segment, IRepresentation *rep, bool withFeedB this->initSeg = NULL; InitializeConditionVariable (&this->stateChanged); InitializeCriticalSection (&this->stateLock); + this->representationBandwidth = rep->GetBandwidth(); + this->representationHeight = rep->GetHeight(); + this->representationId = std::stoi(rep->GetId()); } MediaObject::~MediaObject() @@ -44,6 +47,21 @@ MediaObject::~MediaObject() this->segment = NULL; } +uint32_t MediaObject::GetRepresentationBandwidth() +{ + return this->representationBandwidth; +} + +uint32_t MediaObject::GetRepresentationHeight() +{ + return this->representationHeight; +} + +int MediaObject::GetRepresentationID() +{ + return this->representationId; +} + void MediaObject::SetFeedBack(bool flag) { this->withFeedBack = flag; @@ -57,9 +75,13 @@ void MediaObject::AddInitSegment(MediaObject* initSeg) int MediaObject::ReadInitSegment(uint8_t* data, size_t len) { if(this->initSeg) + { return this->initSeg->Peek(data,len); + } else + { return 0; + } } bool MediaObject::StartDownload() diff --git a/Input/MediaObject.h b/Input/MediaObject.h index 9d5c7826..1edd69af 100644 --- a/Input/MediaObject.h +++ b/Input/MediaObject.h @@ -57,6 +57,9 @@ public: const std::vector& GetHTTPTransactionList() const; void SetAdaptationLogic(framework::adaptation::IAdaptationLogic *_adaptationLogic); void SetDASHReceiver(input::DASHReceiver *_dashReceiver); + uint32_t GetRepresentationBandwidth(); + uint32_t GetRepresentationHeight(); + int GetRepresentationID(); private: dash::mpd::ISegment *segment; @@ -70,6 +73,9 @@ private: adaptation::IAdaptationLogic *adaptationLogic; mutable CRITICAL_SECTION stateLock; mutable CONDITION_VARIABLE stateChanged; + uint32_t representationBandwidth; + uint32_t representationHeight; + int representationId; }; } } 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(); diff --git a/Managers/IMultimediaManagerBase.h b/Managers/IMultimediaManagerBase.h index f08803ba..1ef0b101 100644 --- a/Managers/IMultimediaManagerBase.h +++ b/Managers/IMultimediaManagerBase.h @@ -16,7 +16,7 @@ #ifndef VIPER_MANAGERS_IMULTIMEDIAMANAGERBASE_H_ #define VIPER_MANAGERS_IMULTIMEDIAMANAGERBASE_H_ -#include "IMPD.h" +#include "MPD/MPDWrapper.h" namespace viper { @@ -25,8 +25,10 @@ namespace managers class IMultimediaManagerBase { public: - virtual bool setVideoQuality(dash::mpd::IPeriod* period, dash::mpd::IAdaptationSet *adaptationSet, dash::mpd::IRepresentation *representation) = 0; - virtual bool setAudioQuality(dash::mpd::IPeriod* period, dash::mpd::IAdaptationSet *adaptationSet, dash::mpd::IRepresentation *representation) = 0; +// virtual bool setVideoQuality(dash::mpd::IPeriod* period, dash::mpd::IAdaptationSet *adaptationSet, dash::mpd::IRepresentation *representation) = 0; +// virtual bool setAudioQuality(dash::mpd::IPeriod* period, dash::mpd::IAdaptationSet *adaptationSet, dash::mpd::IRepresentation *representation) = 0; + virtual bool setVideoQuality() = 0; + virtual bool setAudioQuality() = 0; virtual bool isStarted() = 0; virtual bool isStopping() = 0; virtual void shouldAbort(bool isVideo) = 0; diff --git a/Managers/IMultimediaManagerObserver.h b/Managers/IMultimediaManagerObserver.h index eea0bfb1..24ce8d08 100644 --- a/Managers/IMultimediaManagerObserver.h +++ b/Managers/IMultimediaManagerObserver.h @@ -29,6 +29,7 @@ public: virtual void onEOS() = 0; virtual void notifyStatistics(int, uint32_t, int, uint32_t) = 0; virtual void notifyQualityDownloading(uint32_t) = 0; + virtual void setMPDWrapper(libdash::framework::mpd::MPDWrapper*) = 0; }; } } diff --git a/Managers/IStreamObserver.h b/Managers/IStreamObserver.h index d6e8a19c..1d628d51 100644 --- a/Managers/IStreamObserver.h +++ b/Managers/IStreamObserver.h @@ -38,7 +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 faab66cf..23118464 100644 --- a/Managers/MultimediaManager.cpp +++ b/Managers/MultimediaManager.cpp @@ -14,6 +14,7 @@ #include using namespace libdash::framework::adaptation; +using namespace libdash::framework::mpd; using namespace libdash::framework::buffer; using namespace viper::managers; using namespace dash::mpd; @@ -25,17 +26,11 @@ MultimediaManager::MultimediaManager(ViperGui *viperGui, int segBufSize, std::st segmentBufferSize (segBufSize), downloadPath (downloadPath), offset (offset), - mpd (NULL), - period (NULL), - videoAdaptationSet (NULL), - videoRepresentation (NULL), videoLogic (NULL), videoStream (NULL), - audioAdaptationSet (NULL), - audioRepresentation (NULL), audioLogic (NULL), - videoRendererHandle (NULL), - audioRendererHandle (NULL), + videoRendererHandle (NULL), + audioRendererHandle (NULL), audioStream (NULL), started (false), stopping (false), @@ -45,7 +40,8 @@ MultimediaManager::MultimediaManager(ViperGui *viperGui, int segBufSize, std::st isAudioRendering (false), eos (false), playing (false), - noDecoding (nodecoding) + noDecoding (nodecoding), + mpdWrapper (NULL) { InitializeCriticalSection (&this->monitorMutex); InitializeCriticalSection (&this->monitorBufferMutex); @@ -71,28 +67,39 @@ MultimediaManager::~MultimediaManager () IMPD* MultimediaManager::getMPD() { - return this->mpd; + return this->mpdWrapper->getMPD(); +} + +MPDWrapper* MultimediaManager::getMPDWrapper() +{ + return this->mpdWrapper; } bool MultimediaManager::init(const std::string& url) { + this->url = url; EnterCriticalSection(&this->monitorMutex); - this->mpd = this->manager->Open((char *)url.c_str()); + IMPD* mpd = this->manager->Open((char *)url.c_str()); Debug("url : %s\n", url.c_str()); - if(this->mpd == NULL) + if(mpd == NULL) { LeaveCriticalSection(&this->monitorMutex); return false; } Debug("Done DL the mpd\n"); + this->mpdWrapper->setIsStopping(false); + this->mpdWrapper->updateMPD(mpd); + for (size_t i = 0; i < this->managerObservers.size(); i++) + this->managerObservers.at(i)->setMPDWrapper(this->mpdWrapper); LeaveCriticalSection(&this->monitorMutex); return true; } bool MultimediaManager::initICN(const std::string& url) { + this->url = url; EnterCriticalSection(&this->monitorMutex); - libdash::framework::input::IICNConnection* icnConn = new libdash::framework::input::ICNConnectionConsumerApi(20.0, this->beta, this->drop); + this->icnConn = new libdash::framework::input::ICNConnectionConsumerApi(20.0, this->beta, this->drop); icnConn->InitForMPD(url); int ret = 0; char * data = (char *)malloc(4096); @@ -123,22 +130,69 @@ bool MultimediaManager::initICN(const std::string& url) ret = icnConn->Read((uint8_t*)data,4096); } fclose(fp); - this->mpd = this->manager->Open(const_cast(downloadFile.c_str()), url); - if(this->mpd == NULL) + IMPD* mpd = this->manager->Open(const_cast(downloadFile.c_str()), url); + remove(downloadFile.c_str()); + free(data); + if(mpd == NULL) { - remove(downloadFile.c_str()); - free(data); delete icnConn; LeaveCriticalSection(&this->monitorMutex); return false; } - remove(downloadFile.c_str()); - free(data); - delete icnConn; + this->mpdWrapper->setIsStopping(false); + this->mpdWrapper->updateMPD(mpd); + for (size_t i = 0; i < this->managerObservers.size(); i++) + this->managerObservers.at(i)->setMPDWrapper(this->mpdWrapper); + if( !strcmp(this->mpdWrapper->getType().c_str(), "static") ) + { + delete icnConn; + } + LeaveCriticalSection(&this->monitorMutex); return true; } +void MultimediaManager::updateMPD() +{ + this->mpdWrapper->updateMPD(this->manager->Open((char *)url.c_str())); +} + +void MultimediaManager::updateMPDICN() +{ + this->icnConn->InitForMPD(this->url); + int ret = 0; + char * data = (char *)malloc(4096); + int pos = this->url.find_last_of("/"); + if(pos == std::string::npos) + { + pos = strlen(this->url.c_str()); + } + else + { + pos = pos + 1; + } + + std::string downloadFile(this->downloadPath + this->url.substr(pos).c_str()); + FILE *fp; + fp = fopen(downloadFile.c_str(), "w"); + if(fp == NULL) + { + free(data); + return; + } + ret = icnConn->Read((uint8_t*)data, 4096); + while(ret) + { + fwrite(data, sizeof(char), ret, fp); + ret = icnConn->Read((uint8_t*)data,4096); + } + fclose(fp); + this->mpdWrapper->updateMPD(this->manager->Open(const_cast(downloadFile.c_str()), this->url)); + + remove(downloadFile.c_str()); + free(data); +} + bool MultimediaManager::isStarted() { return this->started; @@ -154,6 +208,11 @@ bool MultimediaManager::isICN() return this->icn; } +void MultimediaManager::setMPDWrapper(MPDWrapper* mpdWrapper) +{ + this->mpdWrapper = mpdWrapper; +} + void MultimediaManager::start(bool icnEnabled, double icnAlpha, uint32_t nextOffset) { this->icn = icnEnabled; @@ -168,7 +227,7 @@ void MultimediaManager::start(bool icnEnabled, double icnAlpha, uint32_t nextOff qDebug("normal rate estimation\n"); } EnterCriticalSection(&this->monitorMutex); - if (this->videoAdaptationSet && this->videoRepresentation) + if(this->mpdWrapper->hasVideoAdaptationSetAndVideoRepresentation()) { this->initVideoRendering(nextOffset); this->videoStream->setAdaptationLogic(this->videoLogic); @@ -185,6 +244,8 @@ void MultimediaManager::stop() { if (!this->started) return; + + this->mpdWrapper->setIsStopping(true); this->stopping = true; EnterCriticalSection(&this->monitorMutex); this->stopVideo(); @@ -192,10 +253,8 @@ void MultimediaManager::stop() this->started = false; LeaveCriticalSection(&this->monitorMutex); Debug("VIDEO STOPPED\n"); - this->period = this->mpd->GetPeriods().at(0); - this->videoAdaptationSet = this->period->GetAdaptationSets().at(0); - this->videoRepresentation = this->videoAdaptationSet->GetRepresentation().at(0); - + this->mpdWrapper->reInit(viper::managers::StreamType::VIDEO); + this->mpdWrapper->reInit(viper::managers::StreamType::AUDIO); } void MultimediaManager::stopVideo() @@ -219,30 +278,18 @@ void MultimediaManager::stopAudio() } } -bool MultimediaManager::setVideoQuality(IPeriod* period, IAdaptationSet *adaptationSet, IRepresentation *representation) +bool MultimediaManager::setVideoQuality() { - EnterCriticalSection(&this->monitorMutex); - this->period = period; - this->videoAdaptationSet = adaptationSet; - this->videoRepresentation = representation; if (this->videoStream) - this->videoStream->setRepresentation(this->period, this->videoAdaptationSet, this->videoRepresentation); - - LeaveCriticalSection(&this->monitorMutex); + this->videoStream->setRepresentation(); return true; } -bool MultimediaManager::setAudioQuality(IPeriod* period, IAdaptationSet *adaptationSet, IRepresentation *representation) +bool MultimediaManager::setAudioQuality() { - EnterCriticalSection(&this->monitorMutex); - - this->period = period; - this->audioAdaptationSet = adaptationSet; - this->audioRepresentation = representation; if (this->audioStream) - this->audioStream->setRepresentation(this->period, this->audioAdaptationSet, this->audioRepresentation); - LeaveCriticalSection(&this->monitorMutex); + this->audioStream->setRepresentation(); return true; } @@ -256,11 +303,11 @@ bool MultimediaManager::isUserDependent() bool MultimediaManager::setVideoAdaptationLogic(libdash::framework::adaptation::LogicType type, struct libdash::framework::adaptation::AdaptationParameters *params) { - if(this->videoAdaptationSet) + if(this->mpdWrapper->hasVideoAdaptationSetAndVideoRepresentation()) { if(this->videoLogic) delete(this->videoLogic); - this->videoLogic = AdaptationLogicFactory::create(type, this->mpd, this->period, this->videoAdaptationSet, 1, params); + this->videoLogic = AdaptationLogicFactory::create(type, viper::managers::StreamType::VIDEO, this->mpdWrapper, params); this->logicName = LogicType_string[type]; } else @@ -297,9 +344,11 @@ void MultimediaManager::setTargetDownloadingTime(bool isVideo, double target) bool MultimediaManager::setAudioAdaptationLogic(libdash::framework::adaptation::LogicType type, struct libdash::framework::adaptation::AdaptationParameters *params) { - if(this->audioAdaptationSet) + if(this->mpdWrapper->hasAudioAdaptationSetAndAudioRepresentation()) { - this->audioLogic = AdaptationLogicFactory::create(type, this->mpd, this->period, this->audioAdaptationSet, 0, params); + if(this->audioLogic) + delete(this->audioLogic); + this->audioLogic = AdaptationLogicFactory::create(type, viper::managers::StreamType::AUDIO, this->mpdWrapper, params); this->logicName = LogicType_string[type]; } else @@ -344,17 +393,15 @@ void MultimediaManager::notifyAudioBufferObservers(uint32_t fillstateInPercent) void MultimediaManager::initVideoRendering(uint32_t offset) { - this->videoStream = new MultimediaStream(viper::managers::VIDEO, this->mpd, this->segmentBufferSize, this->isICN(), this->icnAlpha, this->noDecoding, this->beta, this->drop); + this->videoStream = new MultimediaStream(viper::managers::VIDEO, this->mpdWrapper, this->segmentBufferSize, this->isICN(), this->icnAlpha, this->noDecoding, this->beta, this->drop); this->videoStream->attachStreamObserver(this); - this->videoStream->setRepresentation(this->period, this->videoAdaptationSet, this->videoRepresentation); this->videoStream->setPosition(offset); } void MultimediaManager::initAudioPlayback(uint32_t offset) { - this->audioStream = new MultimediaStream(viper::managers::AUDIO, this->mpd, this->segmentBufferSize, this->isICN(), this->icnAlpha, this->noDecoding, this->beta, this->drop); + this->audioStream = new MultimediaStream(viper::managers::AUDIO, this->mpdWrapper, this->segmentBufferSize, this->isICN(), this->icnAlpha, this->noDecoding, this->beta, this->drop); this->audioStream->attachStreamObserver(this); - this->audioStream->setRepresentation(this->period, this->audioAdaptationSet, this->audioRepresentation); this->audioStream->setPosition(offset); } @@ -506,14 +553,12 @@ void* MultimediaManager::pushVideoNoOut(void *data) { Debug("MANAGER:\tRebuffered %d ms\n", actualPosition *(-1)); manager->lastPointInTime = timeOfInsertion; - //TODO Replace the 2 by a variable with segmentDuration - manager->bufferingLimit = manager->lastPointInTime + std::chrono::seconds(2); + manager->bufferingLimit = manager->lastPointInTime + std::chrono::seconds(((int)manager->getSegmentDuration() / 1000)); } else { - //TODO Replace the 2 by a variable with segmentDuration Debug("MANAGER: INSERT TO BUFFER old_fillness: %f, new_fillness: %f\n", (double)((double)actualPosition/1000.0) / (double) this->segmentBufferSize, (double)((double)(actualPosition + 2000)/1000.0) / (double) manager->segmentBufferSize); - manager->bufferingLimit = manager->bufferingLimit + std::chrono::seconds(2); + manager->bufferingLimit = manager->bufferingLimit + std::chrono::seconds(((int)manager->getSegmentDuration() /1000)); manager->lastPointInTime = timeOfInsertion; } delete segment; @@ -566,7 +611,7 @@ int MultimediaManager::getBufferLevel() uint32_t MultimediaManager::getUBufferLevel() { int mBufferLevel = 0; - int segmentDurationInMs = 2000; + int segmentDurationInMs = (int) this->segmentDuration; if(noDecoding) { @@ -587,7 +632,7 @@ uint32_t MultimediaManager::getUBufferLevel() bool MultimediaManager::canPush() { - int segmentDurationInMs = 2000; + int segmentDurationInMs = (int)this->segmentDuration; while(this->getUBufferLevel() >= 100 && !this->stopping) { sleep(segmentDurationInMs / 1000); @@ -599,7 +644,7 @@ void* MultimediaManager::pushVideo(void *data) { MultimediaManager *manager = (MultimediaManager*) data; libdash::framework::input::MediaObject *segment = manager->videoStream->getSegment(); - long int segmentDurationInMs = 2000; + int segmentDurationInMs = (int)manager->getSegmentDuration(); while(manager->isVideoRendering) { if (segment) @@ -627,3 +672,22 @@ void MultimediaManager::setDrop(float drop) { this->drop = drop; } + +void MultimediaManager::fetchMPD() +{ + if(this->icn) + this->updateMPDICN(); + else + this->updateMPD(); +} + +//SegmentDuration is in ms +void MultimediaManager::setSegmentDuration(float segDuration) +{ + this->segmentDuration = segDuration; +} + +float MultimediaManager::getSegmentDuration() +{ + return this->segmentDuration; +} diff --git a/Managers/MultimediaManager.h b/Managers/MultimediaManager.h index b4187486..ade2b767 100644 --- a/Managers/MultimediaManager.h +++ b/Managers/MultimediaManager.h @@ -35,50 +35,52 @@ public: MultimediaManager(ViperGui *viperGui, int segmentBufferSize, std::string downloadPath, bool noDecoding = false); virtual ~MultimediaManager(); - bool init (const std::string& url); - bool initICN (const std::string& url); - void start (bool icnEnabled, double icnAlpha, uint32_t nextOffset); - void stop (); - dash::mpd::IMPD* getMPD (); - - bool setVideoQuality (dash::mpd::IPeriod* period, dash::mpd::IAdaptationSet *adaptationSet, dash::mpd::IRepresentation *representation); - bool setAudioQuality (dash::mpd::IPeriod* period, dash::mpd::IAdaptationSet *adaptationSet, dash::mpd::IRepresentation *representation); - - bool setVideoAdaptationLogic (libdash::framework::adaptation::LogicType type, struct libdash::framework::adaptation::AdaptationParameters *params); - bool setAudioAdaptationLogic (libdash::framework::adaptation::LogicType type, struct libdash::framework::adaptation::AdaptationParameters *params); - - void attachManagerObserver (IMultimediaManagerObserver *observer); - - void setFrameRate (double frameRate); + bool init (const std::string& url); + bool initICN (const std::string& url); + void start (bool icnEnabled, double icnAlpha, uint32_t nextOffset); + void stop (); + dash::mpd::IMPD* getMPD (); + bool setVideoQuality (); + bool setAudioQuality (); + bool setVideoAdaptationLogic (libdash::framework::adaptation::LogicType type, struct libdash::framework::adaptation::AdaptationParameters *params); + bool setAudioAdaptationLogic (libdash::framework::adaptation::LogicType type, struct libdash::framework::adaptation::AdaptationParameters *params); + void attachManagerObserver (IMultimediaManagerObserver *observer); + void setFrameRate (double frameRate); + void setSegmentDuration (float segDuration); + float getSegmentDuration (); /* IStreamObserver */ - void onSegmentDownloaded (); - void onSegmentBufferStateChanged (StreamType type, uint32_t fillstateInPercent, int maxC); - void onVideoBufferStateChanged (uint32_t fillstateInPercent); - void onAudioBufferStateChanged (uint32_t fillstateInPercent); - bool isUserDependent (); - bool isStarted (); - bool isStopping (); - bool isICN (); - void setEOS (bool value); - void shouldAbort (bool isVideo); - void setTargetDownloadingTime (bool isVid, double time); - bool isPlaying (); - void onPausePressed (); - void notifyStatistics (int segNum, uint32_t bitrate, int fps, uint32_t quality); - void notifyQualityDownloading (uint32_t quality); - uint32_t getUBufferLevel (); - int getBufferLevel (); - void setLooping (bool looping); - void setOffset(int offset); - void setBeta(float beta); - void setDrop(float drop); - bool canPush (); - CRITICAL_SECTION monitorBufferMutex; + void onSegmentDownloaded (); + void onSegmentBufferStateChanged (StreamType type, uint32_t fillstateInPercent, int maxC); + void onVideoBufferStateChanged (uint32_t fillstateInPercent); + void onAudioBufferStateChanged (uint32_t fillstateInPercent); + bool isUserDependent (); + bool isStarted (); + bool isStopping (); + bool isICN (); + void setEOS (bool value); + void shouldAbort (bool isVideo); + void setTargetDownloadingTime (bool isVid, double time); + bool isPlaying (); + void onPausePressed (); + void notifyStatistics (int segNum, uint32_t bitrate, int fps, uint32_t quality); + void notifyQualityDownloading (uint32_t quality); + uint32_t getUBufferLevel (); + int getBufferLevel (); + void setLooping (bool looping); + libdash::framework::mpd::MPDWrapper* getMPDWrapper (); + void setMPDWrapper (libdash::framework::mpd::MPDWrapper* mpdWrapper); + void setOffset (int offset); + void setBeta (float beta); + void setDrop (float drop); + bool canPush (); + void fetchMPD (); + - int offset; - std::chrono::time_point lastPointInTime; - std::chrono::time_point bufferingLimit; + CRITICAL_SECTION monitorBufferMutex; + int offset; + std::chrono::time_point lastPointInTime; + std::chrono::time_point bufferingLimit; private: float beta; @@ -87,14 +89,9 @@ private: int segmentBufferSize; ViperGui *viperGui; dash::IDASHManager *manager; - dash::mpd::IMPD *mpd; - dash::mpd::IPeriod *period; - dash::mpd::IAdaptationSet *videoAdaptationSet; - dash::mpd::IRepresentation *videoRepresentation; + libdash::framework::mpd::MPDWrapper *mpdWrapper; libdash::framework::adaptation::IAdaptationLogic *videoLogic; MultimediaStream *videoStream; - dash::mpd::IAdaptationSet *audioAdaptationSet; - dash::mpd::IRepresentation *audioRepresentation; libdash::framework::adaptation::IAdaptationLogic *audioLogic; MultimediaStream *audioStream; std::vector managerObservers; @@ -102,6 +99,7 @@ private: bool stopping; bool icn; double icnAlpha; + libdash::framework::input::IICNConnection *icnConn; uint64_t framesDisplayed; uint64_t segmentsDownloaded; CRITICAL_SECTION monitorMutex; @@ -117,22 +115,27 @@ private: mutable CRITICAL_SECTION monitor_playing_audio_mutex; mutable CONDITION_VARIABLE playingAudioStatusChanged; const char *logicName; - bool noDecoding; - void notifyBufferChange (); - bool startVideoRenderingThread (); - void stopVideoRenderingThread (); - static void* pushVideo (void *data); - static void* pushVideoNoOut (void *data); - bool startAudioRenderingThread (); - void stopAudioRenderingThread (); - void initVideoRendering (uint32_t offset); - void initAudioPlayback (uint32_t offset); - void stopVideo (); - void stopAudio (); - void notifyVideoBufferObservers (uint32_t fillstateInPercent); - void notifyVideoSegmentBufferObservers (uint32_t fillstateInPercent); - void notifyAudioBufferObservers (uint32_t fillstateInPercent); - void notifyAudioSegmentBufferObservers (uint32_t fillstateInPercent); + bool noDecoding; + std::string url; + float segmentDuration; + + void notifyBufferChange (); + bool startVideoRenderingThread (); + void stopVideoRenderingThread (); + static void* pushVideo (void *data); + static void* pushVideoNoOut (void *data); + bool startAudioRenderingThread (); + void stopAudioRenderingThread (); + void initVideoRendering (uint32_t offset); + void initAudioPlayback (uint32_t offset); + void stopVideo (); + void stopAudio (); + void notifyVideoBufferObservers (uint32_t fillstateInPercent); + void notifyVideoSegmentBufferObservers (uint32_t fillstateInPercent); + void notifyAudioBufferObservers (uint32_t fillstateInPercent); + void notifyAudioSegmentBufferObservers (uint32_t fillstateInPercent); + void updateMPD (); + void updateMPDICN (); }; } } diff --git a/Managers/MultimediaStream.cpp b/Managers/MultimediaStream.cpp index ed0d967c..4b5b66fe 100644 --- a/Managers/MultimediaStream.cpp +++ b/Managers/MultimediaStream.cpp @@ -15,23 +15,26 @@ using namespace viper::managers; using namespace libdash::framework::adaptation; using namespace libdash::framework::input; using namespace libdash::framework::buffer; +using namespace libdash::framework::mpd; using namespace dash::mpd; -MultimediaStream::MultimediaStream(StreamType type, IMPD *mpd, uint32_t bufferSize, bool icnEnabled, double icnAlpha, bool nodecoding, float beta, float drop) : +MultimediaStream::MultimediaStream(StreamType type, MPDWrapper *mpdWrapper, uint32_t bufferSize, bool icnEnabled, double icnAlpha, bool nodecoding, float beta, float drop) : type (type), segmentBufferSize (bufferSize), dashManager (NULL), - mpd (mpd), - icn (icnEnabled), + mpdWrapper (mpdWrapper), + icn (icnEnabled), icnAlpha (icnAlpha), noDecoding (nodecoding), - beta (beta), - drop (drop) + beta (beta), + drop (drop) { +// InitializeCriticalSection (&this->monitorMutex); this->init(); } MultimediaStream::~MultimediaStream () { +// DestroyCriticalSection (&this->monitorMutex); this->stop(); delete this->dashManager; } @@ -68,7 +71,7 @@ void MultimediaStream::setPositionInMsec(uint32_t milliSecs) void MultimediaStream::init() { - this->dashManager = new DASHManager(this->type, this->segmentBufferSize, this, this->mpd, this->isICN(), this->icnAlpha, this->noDecoding, this->beta, this->drop); + this->dashManager = new DASHManager(this->type, this->segmentBufferSize, this, this->mpdWrapper, this->isICN(), this->icnAlpha, this->noDecoding, this->beta, this->drop); } bool MultimediaStream::start() @@ -117,9 +120,9 @@ void MultimediaStream::attachStreamObserver(IStreamObserver *observer) this->observers.push_back(observer); } -void MultimediaStream::setRepresentation(IPeriod *period, IAdaptationSet *adaptationSet, IRepresentation *representation) +void MultimediaStream::setRepresentation() { - this->dashManager->setRepresentation(period, adaptationSet, representation); + this->dashManager->setRepresentation(); } void MultimediaStream::enqueueRepresentation(IPeriod *period, IAdaptationSet *adaptationSet, IRepresentation *representation) @@ -206,3 +209,17 @@ void MultimediaStream::notifyBufferChange(uint32_t bufferfill, int maxC) { this->dashManager->onBufferStateChanged(libdash::framework::buffer::VIDEO, bufferfill, maxC); } + +void MultimediaStream::updateMPD (IMPD* mpd) +{ +// this->mpd = mpd; +// this->dashManager->updateMPD(mpd); +} + +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 6918f639..d9db5f66 100644 --- a/Managers/MultimediaStream.h +++ b/Managers/MultimediaStream.h @@ -14,6 +14,7 @@ #include "IMPD.h" #include "IStreamObserver.h" +#include "../MPD/MPDWrapper.h" #include "../Input/DASHManager.h" #include "../Buffer/IBufferObserver.h" #include "../Adaptation/IAdaptationLogic.h" @@ -22,6 +23,20 @@ #include "../Buffer/Buffer.h" #include +namespace libdash +{ +namespace framework +{ +namespace mpd +{ +class MPDWrapper; +} +namespace input +{ +class DASHManager; +} +} +} namespace viper { namespace managers @@ -29,7 +44,7 @@ namespace managers class MultimediaStream : public libdash::framework::input::IDASHManagerObserver, public libdash::framework::buffer::IBufferObserver { public: - MultimediaStream(StreamType type, dash::mpd::IMPD *mpd, uint32_t segmentBufferSize, bool icnEnabled, double icnAlpha, bool nodecoding, float beta, float drop); + MultimediaStream(StreamType type, libdash::framework::mpd::MPDWrapper *mpdWrapper, uint32_t segmentBufferSize, bool icnEnabled, double icnAlpha, bool nodecoding, float beta, float drop); virtual ~MultimediaStream(); bool start(); @@ -50,7 +65,8 @@ public: void notifyBufferChange(uint32_t bufferfill, int maxC); - void setRepresentation(dash::mpd::IPeriod *period, dash::mpd::IAdaptationSet *adaptationSet, dash::mpd::IRepresentation *representation); +// void setRepresentation(dash::mpd::IPeriod *period, dash::mpd::IAdaptationSet *adaptationSet, dash::mpd::IRepresentation *representation); + void setRepresentation(); void enqueueRepresentation(dash::mpd::IPeriod *period, dash::mpd::IAdaptationSet *adaptationSet, dash::mpd::IRepresentation *representation); void setAdaptationLogic(libdash::framework::adaptation::IAdaptationLogic *logic); @@ -65,20 +81,22 @@ public: int getBufferLevel(); bool isICN(); void shouldAbort(); - void setTargetDownloadingTime(double); + void updateMPD(dash::mpd::IMPD* mpd); + void fetchMPD(); private: float beta; float drop; std::vector observers; - dash::mpd::IMPD *mpd; - libdash::framework::adaptation::IAdaptationLogic *logic; + libdash::framework::mpd::MPDWrapper *mpdWrapper; + libdash::framework::adaptation::IAdaptationLogic *logic; libdash::framework::input::DASHManager *dashManager; - uint32_t segmentBufferSize; - StreamType type; + uint32_t segmentBufferSize; + StreamType type; bool icn; double icnAlpha; + mutable CRITICAL_SECTION monitorMutex; bool noDecoding; void init (); diff --git a/UI/DASHPlayer.cpp b/UI/DASHPlayer.cpp index 0f1db8cc..cdad7d5a 100644 --- a/UI/DASHPlayer.cpp +++ b/UI/DASHPlayer.cpp @@ -30,7 +30,6 @@ DASHPlayer::DASHPlayer(ViperGui &gui, Config *config) : this->icn = false; this->adaptLogic = LogicType::RateBased; this->seek = false; - this->isLive = false; this->reloadParameters(); this->setSettings(0, 0, 0, 0, 0); this->multimediaManager = new MultimediaManager(this->gui, this->parametersAdaptation->segmentBufferSize, config->getConfigPath().toStdString() + QString::fromLatin1("/").toStdString()); @@ -40,15 +39,24 @@ DASHPlayer::DASHPlayer(ViperGui &gui, Config *config) : connect(this->gui->getVideoPlayer(), SIGNAL(stateChanged(QtAV::AVPlayer::State)), SLOT(manageGraph(QtAV::AVPlayer::State))); connect(this->gui->getVideoPlayer(), SIGNAL(error(QtAV::AVError)), this, SLOT(error(QtAV::AVError))); this->multimediaManager->attachManagerObserver(this); + this->mpdWrapper = new MPDWrapper(NULL); + this->multimediaManager->setMPDWrapper(this->mpdWrapper); } DASHPlayer::~DASHPlayer() { this->multimediaManager->stop(); delete(this->multimediaManager); + if(this->mpdWrapper) + delete(this->mpdWrapper); DeleteCriticalSection(&this->monitorMutex); } +void DASHPlayer::setMPDWrapper(MPDWrapper* mpdWrapper) +{ + this->mpdWrapper = mpdWrapper; +} + void DASHPlayer::onStartButtonPressed(int period, int videoAdaptationSet, int videoRepresentation, int audioAdaptationSet, int audioRepresentation, int adaptationLogic) { bool setOk = false; @@ -85,25 +93,27 @@ void DASHPlayer::onPauseButtonPressed() void DASHPlayer::onSettingsChanged(int period, int videoAdaptationSet, int videoRepresentation, int audioAdaptationSet, int audioRepresentation) { - if(this->multimediaManager->getMPD() == NULL) + if(this->mpdWrapper->getMPD() == NULL) return; if (!this->settingsChanged(period, videoAdaptationSet, videoRepresentation, audioAdaptationSet, audioRepresentation)) return; - IPeriod *currentPeriod = this->multimediaManager->getMPD()->GetPeriods().at(period); - std::vector videoAdaptationSets = AdaptationSetHelper::getVideoAdaptationSets(currentPeriod); - std::vector audioAdaptationSets = AdaptationSetHelper::getAudioAdaptationSets(currentPeriod); - if (videoAdaptationSet >= 0 && videoRepresentation >= 0) - { - this->multimediaManager->setVideoQuality(currentPeriod, - videoAdaptationSets.at(videoAdaptationSet), - videoAdaptationSets.at(videoAdaptationSet)->GetRepresentation().at(videoRepresentation)); - } - else - { - this->multimediaManager->setVideoQuality(currentPeriod, NULL, NULL); - } +// IPeriod *currentPeriod = this->multimediaManager->getMPD()->GetPeriods().at(period); +// std::vector videoAdaptationSets = AdaptationSetHelper::getVideoAdaptationSets(currentPeriod); +// std::vector audioAdaptationSets = AdaptationSetHelper::getAudioAdaptationSets(currentPeriod); +// if (videoAdaptationSet >= 0 && videoRepresentation >= 0) +// { +// this->multimediaManager->setVideoQuality(currentPeriod, +// videoAdaptationSets.at(videoAdaptationSet), +// videoAdaptationSets.at(videoAdaptationSet)->GetRepresentation().at(videoRepresentation)); +// } +// else +// { +// this->multimediaManager->setVideoQuality(currentPeriod, NULL, NULL); +// } + this->mpdWrapper->settingsChanged(period, videoAdaptationSet, videoRepresentation, audioAdaptationSet, audioRepresentation); + this->multimediaManager->setVideoQuality(); } void DASHPlayer::onVideoBufferStateChanged(uint32_t fillstateInPercent) @@ -149,7 +159,7 @@ bool DASHPlayer::onDownloadMPDPressed (const std::string &url) } } this->setSettings(-1, -1, -1, -1, -1); - this->gui->setGuiFields(this->multimediaManager->getMPD()); + this->gui->setGuiFields(this->mpdWrapper->getMPD()); return true; } @@ -205,42 +215,10 @@ bool DASHPlayer::downloadMPD(const QString &url, const QString &adaptationLogic, } if (!this->onDownloadMPDPressed(mUrl)) return false; - IPeriod *period = this->multimediaManager->getMPD()->GetPeriods().at(0); - IAdaptationSet *adaptation = period->GetAdaptationSets().at(0); - IRepresentation *representation = adaptation->GetRepresentation().at(0); - if(!strcmp(this->multimediaManager->getMPD()->GetType().c_str(), "static")) // VOD MPD - { - if(representation->GetSegmentList()) - { - uint32_t duration = representation->GetSegmentList()->GetDuration(); - uint32_t timescale = representation->GetSegmentList()->GetTimescale(); - this->gui->setListSegmentSize(representation->GetSegmentList()->GetSegmentURLs().size()); - this->segmentDuration = 1.0*duration/(1.0*timescale) * 1000; - this->gui->setSegmentDuration(this->segmentDuration); - this->parametersAdaptation->segmentDuration = this->segmentDuration; - } - else //SegmentTemplate - { - uint32_t duration = representation->GetSegmentTemplate()->GetDuration(); - uint32_t timescale = representation->GetSegmentTemplate()->GetTimescale(); - this->segmentDuration = 1.0*duration/(1.0*timescale) * 1000; - this->gui->setSegmentDuration(this->segmentDuration); - this->gui->setListSegmentSize(TimeResolver::getDurationInSec(period->GetDuration())*1000/this->segmentDuration + 1); - this->parametersAdaptation->segmentDuration = this->segmentDuration; - } - } - else //Live MPD - { - //SegmentTemplate->SegmentTimeline - this->isLive = true; - //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(); - this->segmentDuration = 1.0*duration/(1.0*timescale) * 1000; - this->gui->setSegmentDuration(this->segmentDuration); - this->gui->setListSegmentSize(1); - this->parametersAdaptation->segmentDuration = this->segmentDuration; - } + + this->segmentDuration = this->mpdWrapper->onFirstDownloadMPD(this->gui); + this->multimediaManager->setSegmentDuration(this->segmentDuration); + this->parametersAdaptation->segmentDuration = this->segmentDuration / 1000.0; //to have it in seconds this->onSettingsChanged(0,0,0,0,0); int j =0; std::string temp = adaptationLogic.toStdString(); diff --git a/UI/DASHPlayer.h b/UI/DASHPlayer.h index fad28710..6204f46a 100644 --- a/UI/DASHPlayer.h +++ b/UI/DASHPlayer.h @@ -60,6 +60,7 @@ public: virtual void notifyStatistics(int, uint32_t, int, uint32_t); virtual void notifyQualityDownloading(uint32_t); virtual bool onDownloadMPDPressed(const std::string &url); + void setMPDWrapper(libdash::framework::mpd::MPDWrapper* mpdWrapper); void setConfig(Config *config); Q_INVOKABLE bool downloadMPD(const QString &url, const QString &adaptationLogic, bool icn); Q_INVOKABLE void pause(); @@ -160,34 +161,36 @@ public: Q_INVOKABLE int getRateEstimator(); private: - float gamma; - float beta; - float drop; - bool seek; - bool isLive; - Config *config; - bool repeat; - float segmentDuration; - uint64_t offset; - uint64_t position; - int segment; - int adaptationLogic; - dash::mpd::IMPD *mpd; - ViperGui *gui = NULL; - viper::managers::MultimediaManager *multimediaManager; - settings_t currentSettings; - CRITICAL_SECTION monitorMutex; - const char *url; - bool icn; - std::string icnPrefix; - std::string httpPrefix; - std::string icnSuffix; - std::string httpSuffix; - double alpha; + float gamma; + float beta; + float drop; + bool seek; + bool isLive; + Config *config; + bool repeat; + float segmentDuration; + uint64_t offset; + uint64_t position; + int segment; + int adaptationLogic; + dash::mpd::IMPD *mpd; + libdash::framework::mpd::MPDWrapper *mpdWrapper; + ViperGui *gui = NULL; + viper::managers::MultimediaManager *multimediaManager; + settings_t currentSettings; + CRITICAL_SECTION monitorMutex; + const char *url; + bool icn; + std::string icnPrefix; + std::string httpPrefix; + std::string icnSuffix; + std::string httpSuffix; + double alpha; struct libdash::framework::adaptation::AdaptationParameters *parametersAdaptation; - libdash::framework::adaptation::LogicType adaptLogic; - std::map> mStats; - int qualityDownloading; + libdash::framework::adaptation::LogicType adaptLogic; + std::map> mStats; + int qualityDownloading; + bool settingsChanged(int period, int videoAdaptationSet, int videoRepresentation, int audioAdaptationSet, int audioRepresentation); void setSettings(int period, int videoAdaptationSet, int videoRepresentation, int audioAdaptationSet, int audioRepresentation); std::string msec2string(uint64_t milliseconds); diff --git a/UI/DASHPlayerNoGUI.cpp b/UI/DASHPlayerNoGUI.cpp index 729621ef..d212b556 100644 --- a/UI/DASHPlayerNoGUI.cpp +++ b/UI/DASHPlayerNoGUI.cpp @@ -30,11 +30,9 @@ DASHPlayerNoGUI::DASHPlayerNoGUI(int argc, char ** argv, pthread_cond_t *mainCon noDecoding (nodecoding) { InitializeCriticalSection(&this->monitorMutex); - - this->mpd = NULL; - this->url = NULL; - this->adaptLogic = LogicType::RateBased; - this->isICN = false; + this->url = NULL; + this->adaptLogic = LogicType::RateBased; + this->isICN = false; this->alpha = -1; this->graphData = NULL; this->parameterAdaptation = (struct libdash::framework::adaptation::AdaptationParameters *)malloc(sizeof(struct libdash::framework::adaptation::AdaptationParameters)); @@ -71,6 +69,8 @@ DASHPlayerNoGUI::DASHPlayerNoGUI(int argc, char ** argv, pthread_cond_t *mainCon this->parseArgs(argc, argv); this->multimediaManager = new MultimediaManager(NULL, this->parameterAdaptation->segmentBufferSize, "/tmp/", noDecoding); + this->mpdWrapper = new MPDWrapper(NULL); + this->multimediaManager->setMPDWrapper(this->mpdWrapper); this->multimediaManager->attachManagerObserver(this); if(this->url == NULL) @@ -87,6 +87,8 @@ DASHPlayerNoGUI::DASHPlayerNoGUI(int argc, char ** argv, pthread_cond_t *mainCon WebSocketService webSocketService; webSocketService.setGraphDataSource(this->graphData); webSocketService.start(); + this->parameterAdaptation->segmentDuration = this->mpdWrapper->onFirstDownloadMPD(NULL); + this->multimediaManager->setSegmentDuration(this->parameterAdaptation->segmentDuration); this->onStartButtonPressed(0,0,0,0,0); this->multimediaManager->setLooping(this->repeat); } @@ -102,40 +104,23 @@ DASHPlayerNoGUI::~DASHPlayerNoGUI() { this->multimediaManager->stop(); delete(this->multimediaManager); + if(this->mpdWrapper) + delete(this->mpdWrapper); if(this->graphData) delete(this->graphData); DeleteCriticalSection(&this->monitorMutex); } +void DASHPlayerNoGUI::setMPDWrapper(MPDWrapper *mpdWrapper) +{ + this->mpdWrapper = mpdWrapper; +} + void DASHPlayerNoGUI::onStartButtonPressed(int period, int videoAdaptationSet, int videoRepresentation, int audioAdaptationSet, int audioRepresentation) { this->onSettingsChanged(period,videoAdaptationSet,videoRepresentation, audioAdaptationSet, audioRepresentation); bool setOk = false; - - switch(adaptLogic) - { - case RateBased: - setOk = this->multimediaManager->setVideoAdaptationLogic((LogicType)adaptLogic, this->parameterAdaptation); - break; - case BufferBased: - setOk = this->multimediaManager->setVideoAdaptationLogic((LogicType)adaptLogic, this->parameterAdaptation); - break; - case BufferRateBased: - setOk = this->multimediaManager->setVideoAdaptationLogic((LogicType)adaptLogic, this->parameterAdaptation); - break; - case BufferBasedThreeThreshold: - setOk = this->multimediaManager->setVideoAdaptationLogic((LogicType)adaptLogic, this->parameterAdaptation); - break; - case Panda: - setOk = this->multimediaManager->setVideoAdaptationLogic((LogicType)adaptLogic, this->parameterAdaptation); - break; - case Bola: - setOk = this->multimediaManager->setVideoAdaptationLogic((LogicType)adaptLogic, this->parameterAdaptation); - break; - default: - setOk = this->multimediaManager->setVideoAdaptationLogic((LogicType)adaptLogic, this->parameterAdaptation); - break; - } + setOk = this->multimediaManager->setVideoAdaptationLogic((LogicType)adaptLogic, this->parameterAdaptation); if(!setOk) { @@ -302,37 +287,39 @@ void DASHPlayerNoGUI::helpMessage(char * name) void DASHPlayerNoGUI::onSettingsChanged(int period, int videoAdaptationSet, int videoRepresentation, int audioAdaptationSet, int audioRepresentation) { - if(this->multimediaManager->getMPD() == NULL) - return; // TODO dialog or symbol that indicates that error + if(this->mpdWrapper->getMPD() == NULL) + return; if (!this->settingsChanged(period, videoAdaptationSet, videoRepresentation, audioAdaptationSet, audioRepresentation)) return; - IPeriod *currentPeriod = this->multimediaManager->getMPD()->GetPeriods().at(period); - std::vector videoAdaptationSets = AdaptationSetHelper::getVideoAdaptationSets(currentPeriod); - std::vector audioAdaptationSets = AdaptationSetHelper::getAudioAdaptationSets(currentPeriod); - - if (videoAdaptationSet >= 0 && videoRepresentation >= 0 && !videoAdaptationSets.empty()) - { - this->multimediaManager->setVideoQuality(currentPeriod, - videoAdaptationSets.at(videoAdaptationSet), - videoAdaptationSets.at(videoAdaptationSet)->GetRepresentation().at(videoRepresentation)); - } - else - { - this->multimediaManager->setVideoQuality(currentPeriod, NULL, NULL); - } - - if (audioAdaptationSet >= 0 && audioRepresentation >= 0 && !audioAdaptationSets.empty()) - { - this->multimediaManager->setAudioQuality(currentPeriod, - audioAdaptationSets.at(audioAdaptationSet), - audioAdaptationSets.at(audioAdaptationSet)->GetRepresentation().at(audioRepresentation)); - } - else - { - this->multimediaManager->setAudioQuality(currentPeriod, NULL, NULL); - } +// IPeriod *currentPeriod = this->multimediaManager->getMPD()->GetPeriods().at(period); +// std::vector videoAdaptationSets = AdaptationSetHelper::getVideoAdaptationSets(currentPeriod); +// std::vector audioAdaptationSets = AdaptationSetHelper::getAudioAdaptationSets(currentPeriod); +// +// if (videoAdaptationSet >= 0 && videoRepresentation >= 0 && !videoAdaptationSets.empty()) +// { +// this->multimediaManager->setVideoQuality(currentPeriod, +// videoAdaptationSets.at(videoAdaptationSet), +// videoAdaptationSets.at(videoAdaptationSet)->GetRepresentation().at(videoRepresentation)); +// } +// else +// { +// this->multimediaManager->setVideoQuality(currentPeriod, NULL, NULL); +// } +// +// if (audioAdaptationSet >= 0 && audioRepresentation >= 0 && !audioAdaptationSets.empty()) +// { +// this->multimediaManager->setAudioQuality(currentPeriod, +// audioAdaptationSets.at(audioAdaptationSet), +// audioAdaptationSets.at(audioAdaptationSet)->GetRepresentation().at(audioRepresentation)); +// } +// else +// { +// this->multimediaManager->setAudioQuality(currentPeriod, NULL, NULL); +// } + this->mpdWrapper->settingsChanged(period, videoAdaptationSet, videoRepresentation, audioAdaptationSet, audioRepresentation); + this->multimediaManager->setVideoQuality(); } void DASHPlayerNoGUI::onEOS() diff --git a/UI/DASHPlayerNoGUI.h b/UI/DASHPlayerNoGUI.h index 58ba52c4..4b070de8 100644 --- a/UI/DASHPlayerNoGUI.h +++ b/UI/DASHPlayerNoGUI.h @@ -50,42 +50,25 @@ public: virtual void notifyStatistics(int, uint32_t, int, uint32_t); virtual void notifyQualityDownloading(uint32_t); virtual bool onDownloadMPDPressed(const std::string &url); + virtual void setMPDWrapper(libdash::framework::mpd::MPDWrapper* mpdWrapper); bool isRunning(); private: - dash::mpd::IMPD *mpd; - viper::managers::MultimediaManager *multimediaManager; - CRITICAL_SECTION monitorMutex; - char *url; - bool isICN; - libdash::framework::adaptation::LogicType adaptLogic; - pthread_cond_t *mainCond; - bool running; +// dash::mpd::IMPD *mpd; + libdash::framework::mpd::MPDWrapper *mpdWrapper; + viper::managers::MultimediaManager *multimediaManager; + CRITICAL_SECTION monitorMutex; + char *url; + bool isICN; + libdash::framework::adaptation::LogicType adaptLogic; + pthread_cond_t *mainCond; + bool running; struct libdash::framework::adaptation::AdaptationParameters *parameterAdaptation; - float segmentDuration; - int segmentBufferSize; - double alpha; - double rateAlpha; - double bolaAlpha; - double bolaBufferTargetSeconds; - int bufferBasedReservoirThreshold; - int bufferBasedMaxThreshold; - double adaptechAlpha; - int adaptechFirstThreshold; - int adaptechSecondThreshold; - int adaptechSwitchUpThreshold; - int bufferThreeThreshold_FirstThreshold; - int bufferThreeThreshold_SecondThreshold; - int bufferThreeThreshold_ThirdThreshold; - double pandaAlpha; - double pandaParam_Beta; - double pandaParam_Bmin; - double pandaParam_K; - double pandaParam_W; - double pandaParamEpsilon; - bool repeat; - GraphDataSource *graphData; - bool noDecoding; + double alpha; + bool repeat; + GraphDataSource *graphData; + bool noDecoding; + bool settingsChanged(int period, int videoAdaptationSet, int videoRepresentation, int audioAdaptationSet, int audioRepresentation); }; diff --git a/UI/IViperGui.h b/UI/IViperGui.h new file mode 100644 index 00000000..bf3cb5c3 --- /dev/null +++ b/UI/IViperGui.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2017 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACE_VIPER_H +#define INTERFACE_VIPER_H + +namespace viper +{ + +class IViperGui +{ +public: + virtual void setListSegmentSize(int listSegmentSize) = 0; + virtual void setSegmentDuration(long long int segmentDuration) = 0; +}; +} + +#endif // INTERFACE_VIPER_H diff --git a/UI/ViperGui.cpp b/UI/ViperGui.cpp index 11ba2e8e..24dcfad2 100644 --- a/UI/ViperGui.cpp +++ b/UI/ViperGui.cpp @@ -41,6 +41,7 @@ ViperGui::ViperGui(QObject *parent) : this->position = 0; this->videoPlayer = qvariant_cast(parent->property("mediaObject")); this->streamBuffer = new ViperBuffer(); + this->listSegmentSize = 0; pthread_mutex_init(&(this->monitorMutex), NULL); if (streamBuffer->open(QIODevice::ReadWrite)) { this->videoPlayer->setIODevice(streamBuffer); @@ -55,25 +56,28 @@ ViperGui::~ViperGui() void ViperGui::setGuiFields(dash::mpd::IMPD* mpd) { - this->setPeriodComboBox(mpd); - if (mpd->GetPeriods().size() > 0) +//USELESS CALLS +// this->setPeriodComboBox(mpd); +// if (mpd->GetPeriods().size() > 0) +// { +// IPeriod *period = mpd->GetPeriods().at(0); +// this->setVideoAdaptationSetComboBox(period); +// if (!AdaptationSetHelper::getVideoAdaptationSets(period).empty()) +// { +// IAdaptationSet *adaptationSet = AdaptationSetHelper::getVideoAdaptationSets(period).at(0); +// this->setRepresentationComoboBox(adaptationSet); +// } +// if (!AdaptationSetHelper::getAudioAdaptationSets(period).empty()) +// { +// IAdaptationSet *adaptationSet = AdaptationSetHelper::getAudioAdaptationSets(period).at(0); +// this->setRepresentationComoboBox(adaptationSet); +// } +// } + if(!strcmp(mpd->GetType().c_str(),"static")) { - IPeriod *period = mpd->GetPeriods().at(0); - this->setVideoAdaptationSetComboBox(period); - if (!AdaptationSetHelper::getVideoAdaptationSets(period).empty()) - { - IAdaptationSet *adaptationSet = AdaptationSetHelper::getVideoAdaptationSets(period).at(0); - this->setRepresentationComoboBox(adaptationSet); - } - if (!AdaptationSetHelper::getAudioAdaptationSets(period).empty()) - { - IAdaptationSet *adaptationSet = AdaptationSetHelper::getAudioAdaptationSets(period).at(0); - this->setRepresentationComoboBox(adaptationSet); - } + parse8601(mpd->GetMediaPresentationDuration()); + this->lifeLabel->setProperty("text", QVariant(this->durationString.c_str())); } - parse8601(mpd->GetMediaPresentationDuration()); - this->mpd = mpd; - this->lifeLabel->setProperty("text", QVariant(this->durationString.c_str())); } void ViperGui::parse8601(std::string durationISO8601) @@ -242,7 +246,10 @@ void ViperGui::writeData(libdash::framework::input::MediaObject* media) { this->streamBuffer->writeData(media); pthread_mutex_lock(&(this->monitorMutex)); - this->segment = (this->segment + 1) % this->listSegmentSize; + if(this->listSegmentSize) + this->segment = (this->segment + 1) % this->listSegmentSize; + else + this->segment = this->segment + 1; if( this->segment > 0) { this->bufferDuration += this->segmentDuration; diff --git a/UI/ViperGui.h b/UI/ViperGui.h index f4586753..1ce8e574 100644 --- a/UI/ViperGui.h +++ b/UI/ViperGui.h @@ -28,6 +28,7 @@ #include "../Common/QtQuick2ApplicationViewer.h" #include "../Managers/MultimediaStream.h" #include "GraphDataSource.h" +#include "IViperGui.h" #include @@ -35,7 +36,7 @@ namespace viper { class IDASHPlayerGuiObserver; -class ViperGui : public QObject +class ViperGui : public QObject,public IViperGui { Q_OBJECT diff --git a/libdash/include/IMPD.h b/libdash/include/IMPD.h index 7e69eecf..7ac82755 100644 --- a/libdash/include/IMPD.h +++ b/libdash/include/IMPD.h @@ -109,6 +109,13 @@ namespace dash */ virtual const std::string& GetType () const = 0; + /** + * Returns a reference to a string that specifies + * the publishTime + * @return a reference to a string + */ + virtual const std::string& GetPublishTime () const = 0; + /** * Returns a reference to a string that specifies *
    @@ -204,4 +211,4 @@ namespace dash } } -#endif /* IMPD_H_ */ \ No newline at end of file +#endif /* IMPD_H_ */ diff --git a/libdash/source/mpd/MPD.cpp b/libdash/source/mpd/MPD.cpp index 84e0e614..0c4f2f3a 100644 --- a/libdash/source/mpd/MPD.cpp +++ b/libdash/source/mpd/MPD.cpp @@ -104,6 +104,10 @@ void MPD::SetType { this->type = type; } +const std::string& MPD::GetPublishTime () const +{ + return this->publishTime; +} const std::string& MPD::GetAvailabilityStarttime () const { return this->availabilityStarttime; @@ -112,6 +116,10 @@ void MPD::SetAvailabilityStarttime { this->availabilityStarttime = availabilityStarttime; } +void MPD::SetPublishTime (const std::string& publishTime) +{ + this->publishTime = publishTime; +} const std::string& MPD::GetAvailabilityEndtime () const { return this->availabilityEndtime; diff --git a/libdash/source/mpd/MPD.h b/libdash/source/mpd/MPD.h index 9bcb38af..fec0266e 100644 --- a/libdash/source/mpd/MPD.h +++ b/libdash/source/mpd/MPD.h @@ -41,6 +41,7 @@ namespace dash const std::string& GetId () const; const std::vector& GetProfiles () const; const std::string& GetType () const; + const std::string& GetPublishTime () const; const std::string& GetAvailabilityStarttime () const; const std::string& GetAvailabilityEndtime () const; const std::string& GetMediaPresentationDuration () const; @@ -66,6 +67,7 @@ namespace dash void SetId (const std::string& id); void SetProfiles (const std::string& profiles); void SetType (const std::string& type); + void SetPublishTime (const std::string& publishTime); void SetAvailabilityStarttime (const std::string& availabilityStarttime); void SetAvailabilityEndtime (const std::string& availabilityEndtime); void SetMediaPresentationDuration (const std::string& mediaPresentationDuration); @@ -87,6 +89,7 @@ namespace dash std::string id; std::vector profiles; std::string type; + std::string publishTime; std::string availabilityStarttime; std::string availabilityEndtime; std::string mediaPresentationDuration; diff --git a/libdash/source/xml/Node.cpp b/libdash/source/xml/Node.cpp index d04558b6..53193207 100644 --- a/libdash/source/xml/Node.cpp +++ b/libdash/source/xml/Node.cpp @@ -715,6 +715,10 @@ dash::mpd::MPD* Node::ToMPD () cons { mpd->SetType(this->GetAttributeValue("type")); } + if (this->HasAttribute("publishTime")) + { + mpd->SetPublishTime(this->GetAttributeValue("publishTime")); + } if (this->HasAttribute("availabilityStartTime")) { mpd->SetAvailabilityStarttime(this->GetAttributeValue("availabilityStartTime")); diff --git a/viper.pro b/viper.pro index 9b12da0f..836eab92 100644 --- a/viper.pro +++ b/viper.pro @@ -55,6 +55,7 @@ SOURCES += \ MPD/SegmentTemplateStream.cpp \ MPD/SingleMediaSegmentStream.cpp \ MPD/TimeResolver.cpp \ + MPD/MPDWrapper.cpp \ Portable/MultiThreading.cpp \ Managers/MultimediaManager.cpp \ Managers/MultimediaStream.cpp \ @@ -142,6 +143,8 @@ HEADERS *= \ MPD/SegmentTemplateStream.h \ MPD/SingleMediaSegmentStream.h \ MPD/TimeResolver.h \ + MPD/IMPDWrapper.h \ + MPD/MPDWrapper.h \ Portable/MultiThreading.h \ Portable/Networking.h \ Managers/IMultimediaManagerBase.h \ @@ -257,6 +260,7 @@ HEADERS *= \ websocketpp/utf8_validator.hpp \ websocketpp/utilities.hpp \ websocketpp/version.hpp \ + UI/IViperGui.h \ UI/ViperGui.h \ Common/ViperBuffer.h \ Common/QtQuick2ApplicationViewer.h -- cgit 1.2.3-korg