summaryrefslogtreecommitdiffstats
path: root/Adaptation
diff options
context:
space:
mode:
Diffstat (limited to 'Adaptation')
-rw-r--r--Adaptation/AbstractAdaptationLogic.cpp54
-rw-r--r--Adaptation/AbstractAdaptationLogic.h58
-rw-r--r--Adaptation/AdaptationLogicFactory.cpp48
-rw-r--r--Adaptation/AdaptationLogicFactory.h40
-rw-r--r--Adaptation/AlwaysLowestLogic.cpp71
-rw-r--r--Adaptation/AlwaysLowestLogic.h48
-rw-r--r--Adaptation/Bola.cpp506
-rw-r--r--Adaptation/Bola.h118
-rw-r--r--Adaptation/BufferBasedAdaptation.cpp141
-rw-r--r--Adaptation/BufferBasedAdaptation.h64
-rw-r--r--Adaptation/BufferBasedAdaptationWithRateBased.cpp206
-rw-r--r--Adaptation/BufferBasedAdaptationWithRateBased.h72
-rw-r--r--Adaptation/BufferBasedThreeThresholdAdaptation.cpp166
-rw-r--r--Adaptation/BufferBasedThreeThresholdAdaptation.h69
-rw-r--r--Adaptation/IAdaptationLogic.h115
-rw-r--r--Adaptation/Panda.cpp274
-rw-r--r--Adaptation/Panda.h89
-rw-r--r--Adaptation/RateBasedAdaptation.cpp140
-rw-r--r--Adaptation/RateBasedAdaptation.h61
19 files changed, 2340 insertions, 0 deletions
diff --git a/Adaptation/AbstractAdaptationLogic.cpp b/Adaptation/AbstractAdaptationLogic.cpp
new file mode 100644
index 00000000..4f578958
--- /dev/null
+++ b/Adaptation/AbstractAdaptationLogic.cpp
@@ -0,0 +1,54 @@
+/*
+ * AbstractAdaptationLogic.cpp
+ *****************************************************************************
+ * Copyright (C) 2012, bitmovin Softwareentwicklung OG, All Rights Reserved
+ *
+ * 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 "AbstractAdaptationLogic.h"
+
+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()
+{
+}
+
+uint32_t AbstractAdaptationLogic::getPosition()
+{
+ return 0;
+}
+
+void AbstractAdaptationLogic::setPosition(uint32_t segmentNumber)
+{
+ this->segmentNumber = segmentNumber;
+}
+
+IRepresentation* AbstractAdaptationLogic::getRepresentation()
+{
+ return this->representation;
+}
+
+void AbstractAdaptationLogic::setRepresentation(IPeriod *period, IAdaptationSet *adaptationSet, IRepresentation *representation)
+{
+ this->period = period;
+ this->adaptationSet = adaptationSet;
+ this->representation = representation;
+}
+
+void AbstractAdaptationLogic::dLTimeUpdate(double time)
+{
+}
diff --git a/Adaptation/AbstractAdaptationLogic.h b/Adaptation/AbstractAdaptationLogic.h
new file mode 100644
index 00000000..24fab91d
--- /dev/null
+++ b/Adaptation/AbstractAdaptationLogic.h
@@ -0,0 +1,58 @@
+/*
+ * AbstractAdaptationLogic.h
+ *****************************************************************************
+ * Copyright (C) 2012, bitmovin Softwareentwicklung OG, All Rights Reserved
+ *
+ * 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.
+ *****************************************************************************/
+
+#ifndef LIBDASH_FRAMEWORK_ADAPTATION_ABSTRACTADAPTATIONLOGIC_H_
+#define LIBDASH_FRAMEWORK_ADAPTATION_ABSTRACTADAPTATIONLOGIC_H_
+
+#include "IAdaptationLogic.h"
+#include "IMPD.h"
+
+namespace libdash
+{
+namespace framework
+{
+namespace adaptation
+{
+class AbstractAdaptationLogic : public IAdaptationLogic
+{
+public:
+ AbstractAdaptationLogic(dash::mpd::IMPD *mpd, dash::mpd::IPeriod* period, dash::mpd::IAdaptationSet *adaptationSet, bool isVideo);
+ 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 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 checkedByDASHReceiver() = 0;
+protected:
+ dash::mpd::IMPD *mpd;
+ dash::mpd::IPeriod *period;
+ dash::mpd::IAdaptationSet *adaptationSet;
+ dash::mpd::IRepresentation *representation;
+ uint32_t segmentNumber;
+ bool isVideo;
+};
+}
+}
+}
+#endif /* LIBDASH_FRAMEWORK_ADAPTATION_ABSTRACTADAPTATIONLOGIC_H_ */
diff --git a/Adaptation/AdaptationLogicFactory.cpp b/Adaptation/AdaptationLogicFactory.cpp
new file mode 100644
index 00000000..6901a597
--- /dev/null
+++ b/Adaptation/AdaptationLogicFactory.cpp
@@ -0,0 +1,48 @@
+/*
+ * AdaptationLogicFactory.cpp
+ *****************************************************************************
+ * Copyright (C) 2012, bitmovin Softwareentwicklung OG, All Rights Reserved
+ *
+ * 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 "AdaptationLogicFactory.h"
+#include<stdio.h>
+
+using namespace libdash::framework::adaptation;
+using namespace dash::mpd;
+
+IAdaptationLogic* AdaptationLogicFactory::create(LogicType logic, IMPD *mpd, IPeriod *period, IAdaptationSet *adaptationSet,bool isVid, 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);
+ case RateBased:
+ Debug("Rate based\n");
+ return new RateBasedAdaptation(mpd,period,adaptationSet, isVid, paramsForAdaptation);
+ case BufferBased:
+ Debug("Buffer based\n");
+ return new BufferBasedAdaptation(mpd,period,adaptationSet, isVid, paramsForAdaptation);
+ case BufferRateBased:
+ Debug("Buffer Rate based\n");
+ return new BufferBasedAdaptationWithRateBased(mpd,period,adaptationSet, isVid, paramsForAdaptation);
+ case BufferBasedThreeThreshold:
+ Debug("Buffer based 3 threshold\n");
+ return new BufferBasedThreeThresholdAdaptation(mpd,period,adaptationSet, isVid, paramsForAdaptation);
+ case Panda:
+ Debug("Panda\n");
+ return new PandaAdaptation(mpd, period, adaptationSet, isVid, paramsForAdaptation);
+ case Bola:
+ Debug("Bola\n");
+ return new BolaAdaptation(mpd, period, adaptationSet, isVid, paramsForAdaptation);
+ default:
+ Debug("default => return Always Lowest\n");
+ return new AlwaysLowestLogic(mpd, period, adaptationSet, isVid, paramsForAdaptation);
+ }
+}
diff --git a/Adaptation/AdaptationLogicFactory.h b/Adaptation/AdaptationLogicFactory.h
new file mode 100644
index 00000000..0f1616a7
--- /dev/null
+++ b/Adaptation/AdaptationLogicFactory.h
@@ -0,0 +1,40 @@
+/*
+ * AdaptationLogicFactory.h
+ *****************************************************************************
+ * Copyright (C) 2012, bitmovin Softwareentwicklung OG, All Rights Reserved
+ *
+ * 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.
+ *****************************************************************************/
+
+#ifndef LIBDASH_FRAMEWORK_ADAPTATION_ADAPTATIONLOGICFACTORY_H_
+#define LIBDASH_FRAMEWORK_ADAPTATION_ADAPTATIONLOGICFACTORY_H_
+
+#include "IAdaptationLogic.h"
+#include "AlwaysLowestLogic.h"
+#include "RateBasedAdaptation.h"
+#include "BufferBasedAdaptation.h"
+#include "BufferBasedAdaptationWithRateBased.h"
+#include "BufferBasedThreeThresholdAdaptation.h"
+#include "Panda.h"
+#include "Bola.h"
+
+namespace libdash
+{
+namespace framework
+{
+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);
+};
+}
+}
+}
+
+#endif /* LIBDASH_FRAMEWORK_ADAPTATION_ADAPTATIONLOGICFACTORY_H_ */
diff --git a/Adaptation/AlwaysLowestLogic.cpp b/Adaptation/AlwaysLowestLogic.cpp
new file mode 100644
index 00000000..54409bfd
--- /dev/null
+++ b/Adaptation/AlwaysLowestLogic.cpp
@@ -0,0 +1,71 @@
+/*
+ * AlwaysLowestLogic.cpp
+ *****************************************************************************
+ * Copyright (C) 2012, bitmovin Softwareentwicklung OG, All Rights Reserved
+ *
+ * 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 "AlwaysLowestLogic.h"
+#include<stdio.h>
+
+using namespace libdash::framework::adaptation;
+using namespace libdash::framework::input;
+using namespace dash::mpd;
+
+AlwaysLowestLogic::AlwaysLowestLogic(IMPD *mpd, IPeriod *period, IAdaptationSet *adaptationSet, bool isVid, struct AdaptationParameters *params) :
+ AbstractAdaptationLogic(mpd, period, adaptationSet, isVid)
+{
+ this->representation = this->adaptationSet->GetRepresentation().at(0);
+}
+
+AlwaysLowestLogic::~AlwaysLowestLogic()
+{
+}
+
+LogicType AlwaysLowestLogic::getType()
+{
+ return adaptation::AlwaysLowest;
+}
+
+bool AlwaysLowestLogic::isUserDependent()
+{
+ return false;
+}
+
+bool AlwaysLowestLogic::isRateBased()
+{
+ return false;
+}
+
+bool AlwaysLowestLogic::isBufferBased()
+{
+ return false;
+}
+
+void AlwaysLowestLogic::bitrateUpdate(uint64_t bps, uint32_t segNum)
+{
+}
+
+void AlwaysLowestLogic::bufferUpdate(uint32_t bufferfill, int maxC)
+{
+}
+
+void AlwaysLowestLogic::setMultimediaManager(viper::managers::IMultimediaManagerBase *mmM)
+{
+}
+
+void AlwaysLowestLogic::onEOS(bool value)
+{
+}
+
+void AlwaysLowestLogic::dLTimeUpdate(double time)
+{
+}
+
+void AlwaysLowestLogic::checkedByDASHReceiver()
+{
+}
diff --git a/Adaptation/AlwaysLowestLogic.h b/Adaptation/AlwaysLowestLogic.h
new file mode 100644
index 00000000..782a8b29
--- /dev/null
+++ b/Adaptation/AlwaysLowestLogic.h
@@ -0,0 +1,48 @@
+/*
+ * AlwaysLowestLogic.h
+ *****************************************************************************
+ * Copyright (C) 2012, bitmovin Softwareentwicklung OG, All Rights Reserved
+ *
+ * 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.
+ *****************************************************************************/
+
+#ifndef LIBDASH_FRAMEWORK_ADAPTATION_ALWAYSLOWESTLOGIC_H_
+#define LIBDASH_FRAMEWORK_ADAPTATION_ALWAYSLOWESTLOGIC_H_
+
+#include "IMPD.h"
+#include "AbstractAdaptationLogic.h"
+
+namespace libdash
+{
+namespace framework
+{
+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);
+ virtual ~AlwaysLowestLogic();
+
+ virtual LogicType getType();
+ virtual bool isUserDependent();
+ virtual bool isRateBased();
+ virtual bool isBufferBased();
+ virtual void bitrateUpdate(uint64_t, uint32_t);
+ virtual void dLTimeUpdate(double time);
+ virtual void bufferUpdate(uint32_t, int);
+ virtual void setMultimediaManager(viper::managers::IMultimediaManagerBase *mmM);
+ virtual void onEOS(bool value);
+ virtual void checkedByDASHReceiver();
+private:
+
+
+};
+}
+}
+}
+
+#endif /* LIBDASH_FRAMEWORK_ADAPTATION_ALWAYSLOWESTLOGIC_H_ */
diff --git a/Adaptation/Bola.cpp b/Adaptation/Bola.cpp
new file mode 100644
index 00000000..6477e0f5
--- /dev/null
+++ b/Adaptation/Bola.cpp
@@ -0,0 +1,506 @@
+/*
+ * 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.
+ */
+
+#include "Bola.h"
+#include <stdio.h>
+#include <math.h>
+#include <chrono>
+#include <string>
+#include <stdint.h>
+#include <iostream>
+#include <sstream>
+#include <chrono>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <algorithm>
+#include <inttypes.h>
+#include <time.h>
+#include <limits.h>
+#include <errno.h>
+
+const double MINIMUM_BUFFER_LEVEL_SPACING = 5.0; // The minimum space required between buffer levels (in seconds).
+const uint32_t THROUGHPUT_SAMPLES = 3; // Number of samples considered for throughput estimate.
+const double SAFETY_FACTOR = 0.9; // Safety factor used with bandwidth estimate.
+
+using namespace dash::mpd;
+using namespace libdash::framework::adaptation;
+using namespace libdash::framework::input;
+using namespace libdash::framework::mpd;
+
+using std::bind;
+using std::placeholders::_1;
+using std::placeholders::_2;
+
+
+using duration_in_seconds = std::chrono::duration<double, std::ratio<1, 1> >;
+
+BolaAdaptation::BolaAdaptation(IMPD *mpd, IPeriod *period, IAdaptationSet *adaptationSet, bool isVid, struct AdaptationParameters *params) :
+ AbstractAdaptationLogic (mpd, period, adaptationSet, isVid)
+{
+ this->bufferMaxSizeSeconds =(double) params->segmentBufferSize * params->segmentDuration;
+ this->alphaRate = params->Bola_Alpha;
+ this->bufferTargetSeconds = params->Bola_bufferTargetSeconds;
+
+ // Set Bola init STATE
+ this->initState = true;
+ this->bolaState = STARTUP;
+
+ this->lastDownloadTimeInstant = 0.0;
+ this->currentDownloadTimeInstant = 0.0;
+ //this->lastSegmentDownloadTime = 0.0;
+ this->currentQuality = 0;
+
+ this->bufferTargetPerc = (uint32_t) ( round(this->bufferTargetSeconds / this->bufferMaxSizeSeconds)*100 );
+
+ /// Retrieve available bitrates
+ std::vector<IRepresentation* > representations = this->adaptationSet->GetRepresentation();
+
+ this->availableBitrates.clear();
+ Debug("BOLA Available Bitrates...\n");
+ for(size_t i = 0; i < representations.size(); i++)
+ {
+ this->availableBitrates.push_back((uint64_t)(representations.at(i)->GetBandwidth()));
+ Debug("%d - %I64u bps\n", i+1, this->availableBitrates[i]);
+ }
+ // Check if they are in increasing order (i.e., bitrate[0] <= bitrate[1], etc.)
+
+ this->bitrateCount = this->availableBitrates.size();
+
+ // We check if we have only one birate value or if the bitrate list is irregular (i.e., it is not strictly increasing)
+ if (this->bitrateCount < 2 || this->availableBitrates[0] >= this->availableBitrates[1] || this->availableBitrates[this->bitrateCount - 2] >= this->availableBitrates[this->bitrateCount - 1]) {
+ this->bolaState = ONE_BITRATE;
+ // return 0; // Check if exit with a message is necessary
+ }
+
+ // Check if the following is correct
+ this->totalDuration = TimeResolver::getDurationInSec(this->mpd->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);
+ // if not correct --> segmentDuration = 2.0;
+
+ // Compute the BOLA Buffer Target
+ this->bolaBufferTargetSeconds = this->bufferTargetSeconds;
+ if (this->bolaBufferTargetSeconds < this->segmentDuration + MINIMUM_BUFFER_LEVEL_SPACING)
+ {
+ this->bolaBufferTargetSeconds = this->segmentDuration + MINIMUM_BUFFER_LEVEL_SPACING;
+ }
+ Debug("BOLA Buffer Target Seconds:\t%f\n",this->bolaBufferTargetSeconds);
+
+ // Compute UTILTY vector, Vp, and gp
+ Debug("BOLA Utility Values...\n");
+ for (uint32_t i = 0; i < this->bitrateCount; ++i) {
+ this->utilityVector.push_back( log(((double)this->availableBitrates[i] * (1./(double)this->availableBitrates[0]))));
+ Debug("%d - %f\n", i+1, this->utilityVector[i]);
+ }
+
+ this->Vp = (this->bolaBufferTargetSeconds - this->segmentDuration) / this->utilityVector[this->bitrateCount - 1];
+ this->gp = 1.0 + this->utilityVector[this->bitrateCount - 1] / (this->bolaBufferTargetSeconds / this->segmentDuration - 1.0);
+
+ Debug("BOLA Parameters:\tVp: %f\tgp: %f\n",this->Vp, this->gp);
+ /* If bufferTargetSeconds (not bolaBufferTargetSecond) is large enough, we might guarantee that Bola will never rebuffer
+ * unless the network bandwidth drops below the lowest encoded bitrate level. For this to work, Bola needs to use the real buffer
+ * level without the additional virtualBuffer. Also, for this to work efficiently, we need to make sure that if the buffer level
+ * drops to one fragment during a download, the current download does not have more bits remaining than the size of one fragment
+ * at the lowest quality*/
+
+ this->maxRtt = 0.2; // Is this reasonable?
+ if(this->bolaBufferTargetSeconds == this->bufferTargetSeconds) {
+ this->safetyGuarantee = true;
+ }
+ if (this->safetyGuarantee) {
+ Debug("BOLA SafetyGuarantee...\n");
+ // we might need to adjust Vp and gp
+ double VpNew = this->Vp;
+ double gpNew = this->gp;
+ for (uint32_t i = 1; i < this->bitrateCount; ++i) {
+ double threshold = VpNew * (gpNew - this->availableBitrates[0] * this->utilityVector[i] / (this->availableBitrates[i] - this->availableBitrates[0]));
+ double minThreshold = this->segmentDuration * (2.0 - this->availableBitrates[0] / this->availableBitrates[i]) + maxRtt;
+ if (minThreshold >= this->bufferTargetSeconds) {
+ safetyGuarantee = false;
+ break;
+ }
+ if (threshold < minThreshold) {
+ VpNew = VpNew * (this->bufferTargetSeconds - minThreshold) / (this->bufferTargetSeconds - threshold);
+ gpNew = minThreshold / VpNew + this->utilityVector[i] * this->availableBitrates[0] / (this->availableBitrates[i] - this->availableBitrates[0]);
+ }
+ }
+ if (safetyGuarantee && (this->bufferTargetSeconds - this->segmentDuration) * VpNew / this->Vp < MINIMUM_BUFFER_LEVEL_SPACING) {
+ safetyGuarantee = false;
+ }
+ if (safetyGuarantee) {
+ this->Vp = VpNew;
+ this->gp = gpNew;
+ }
+ }
+
+ Debug("BOLA New Parameters:\tVp: %f\tgp: %f\n",this->Vp, this->gp);
+
+ // Capping of the virtual buffer (when using it)
+ this->bolaBufferMaxSeconds = this->Vp * (this->utilityVector[this->bitrateCount - 1] + this->gp);
+ Debug("BOLA Max Buffer Seconds:\t%f\n",this->bolaBufferMaxSeconds);
+
+ this->virtualBuffer = 0.0; // Check if we should use either the virtualBuffer or the safetyGuarantee
+
+ this->instantBw = 0;
+ this->averageBw = 0;
+ this->batchBw = 0; // Computed every THROUGHPUT_SAMPLES samples (average)
+ this->batchBwCount = 0;
+
+ this->multimediaManager = NULL;
+ this->lastBufferFill = 0; // (?)
+ this->bufferEOS = false;
+ this->shouldAbort = false;
+ this->isCheckedForReceiver = false;
+
+ this->representation = representations.at(0);
+ this->currentBitrate = (uint64_t) this->representation->GetBandwidth();
+
+ 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");
+}
+
+BolaAdaptation::~BolaAdaptation()
+{
+}
+
+LogicType BolaAdaptation::getType()
+{
+ return adaptation::BufferBased;
+}
+
+bool BolaAdaptation::isUserDependent()
+{
+ return false;
+}
+
+bool BolaAdaptation::isRateBased()
+{
+ return true;
+}
+bool BolaAdaptation::isBufferBased()
+{
+ return true;
+}
+
+void BolaAdaptation::setMultimediaManager(viper::managers::IMultimediaManagerBase *_mmManager)
+{
+ this->multimediaManager = _mmManager;
+}
+
+void BolaAdaptation::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;
+}
+
+uint64_t BolaAdaptation::getBitrate()
+{
+ return this->currentBitrate;
+}
+
+int BolaAdaptation::getQualityFromThroughput(uint64_t bps) {
+ int q = 0;
+ for (int i = 0; i < this->availableBitrates.size(); ++i) {
+ if (this->availableBitrates[i] > bps) {
+ break;
+ }
+ q = i;
+ }
+ return q;
+}
+
+int BolaAdaptation::getQualityFromBufferLevel(double bufferLevelSec) {
+ int quality = this->bitrateCount - 1;
+ double score = 0.0;
+ for (int i = 0; i < this->bitrateCount; ++i) {
+ double s = (this->utilityVector[i] + this->gp - bufferLevelSec / this->Vp) / this->availableBitrates[i];
+ if (s > score) {
+ score = s;
+ quality = i;
+ }
+ }
+ return quality;
+}
+
+void BolaAdaptation::setBitrate(uint32_t bufferFill)
+{
+ // *** NB *** Insert Log messages
+
+ if(this->initState)
+ {
+ this->initState = false;
+
+ if(this->bolaState != ONE_BITRATE)
+ {
+ if(this->batchBw != 0) // Check the current estimated throughput (batch mean)
+ this->currentQuality = getQualityFromThroughput(this->batchBw*SAFETY_FACTOR);
+ //else --> quality unchanged
+ }
+ //this->representation = this->availableBitrates[this->currentQuality];
+ //this->currentBitrate = (uint64_t) this->representation->GetBandwidth();
+ this->representation = this->adaptationSet->GetRepresentation().at(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);
+ this->lastBufferFill = bufferFill;
+ return;
+ }
+
+ if(this->bolaState == ONE_BITRATE) {
+ 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->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);
+ this->lastBufferFill = bufferFill;
+ return;
+ }
+
+ // Obtain bufferFill in seconds;
+ double bufferLevelSeconds = (double)( (bufferFill * this->bufferMaxSizeSeconds) *1./100);
+ int bolaQuality = getQualityFromBufferLevel(bufferLevelSeconds);
+
+ Debug("REGULAR - Buffer Level Seconds:\t%f; Bola Quality:\t%d\n", bufferLevelSeconds, bolaQuality);
+
+
+ if (bufferLevelSeconds <= 0.1) {
+ // rebuffering occurred, reset virtual buffer
+ this->virtualBuffer = 0.0;
+ }
+
+ // We check if the safetyGuarantee should be used. if not, we use the virtual buffer
+ // STILL NOT COMPLETE; Find a way to retrieved time since the last download
+ if (!this->safetyGuarantee) // we can use virtualBuffer
+ {
+ // find out if there was delay because of lack of availability or because bolaBufferTarget > bufferTarget
+ // TODO
+ //double timeSinceLastDownload = getDelayFromLastFragmentInSeconds(); // Define function
+ double timeSinceLastDownload = this->currentDownloadTimeInstant - this->lastDownloadTimeInstant;
+
+ Debug("VirtualBuffer - Time Since Last Download:\t%f\n", timeSinceLastDownload);
+
+ if (timeSinceLastDownload > 0.0) {
+ this->virtualBuffer += timeSinceLastDownload;
+ }
+ if ( (bufferLevelSeconds + this->virtualBuffer) > this->bolaBufferMaxSeconds) {
+ this->virtualBuffer = this->bolaBufferMaxSeconds - bufferLevelSeconds;
+ }
+ if (this->virtualBuffer < 0.0) {
+ this->virtualBuffer = 0.0;
+ }
+
+ Debug("VirtualBuffer - Virtual Buffer Value:\t%f\n", this->virtualBuffer);
+
+ // Update currentDownloadTimeInstant
+ this->lastDownloadTimeInstant = this->currentDownloadTimeInstant;
+
+ // Update bolaQuality using virtualBuffer: bufferLevel might be artificially low because of lack of availability
+
+ int bolaQualityVirtual = getQualityFromBufferLevel(bufferLevelSeconds + this->virtualBuffer);
+ Debug("VirtualBuffer - Bola Quality Virtual:\t%d\n", bolaQualityVirtual);
+ if (bolaQualityVirtual > bolaQuality) {
+ // May use quality higher than that indicated by real buffer level.
+ // In this case, make sure there is enough throughput to download a fragment before real buffer runs out.
+ int maxQuality = bolaQuality;
+ while (maxQuality < bolaQualityVirtual && (this->availableBitrates[maxQuality + 1] * this->segmentDuration) / (this->currentBitrate * SAFETY_FACTOR) < bufferLevelSeconds)
+ {
+ ++maxQuality;
+ }
+ // TODO: maybe we can use a more conservative level here, but this should be OK
+ Debug("VirtualBuffer - Bola Quality Virtual HIGHER than Bola Quality - Max Quality:\t%d\n", maxQuality);
+ if (maxQuality > bolaQuality)
+ {
+ // We can (and will) download at a quality higher than that indicated by real buffer level.
+ if (bolaQualityVirtual <= maxQuality) {
+ // we can download fragment indicated by real+virtual buffer without rebuffering
+ bolaQuality = bolaQualityVirtual;
+ } else {
+ // downloading fragment indicated by real+virtual rebuffers, use lower quality
+ bolaQuality = maxQuality;
+ // deflate virtual buffer to match quality
+ double targetBufferLevel = this->Vp * (this->gp + this->utilityVector[bolaQuality]);
+ if (bufferLevelSeconds + this->virtualBuffer > targetBufferLevel) {
+ this->virtualBuffer = targetBufferLevel - bufferLevelSeconds;
+ if (this->virtualBuffer < 0.0) { // should be false
+ this->virtualBuffer = 0.0;
+ }
+ }
+ }
+ }
+ }
+ }
+
+
+ if (this->bolaState == STARTUP || this->bolaState == STARTUP_NO_INC) {
+ // in startup phase, use some throughput estimation
+
+ int quality = getQualityFromThroughput(this->batchBw*SAFETY_FACTOR);
+
+ if (this->batchBw <= 0.0) {
+ // something went wrong - go to steady state
+ this->bolaState = STEADY;
+ }
+ if (this->bolaState == STARTUP && quality < this->currentQuality) {
+ // Since the quality is decreasing during startup, it will not be allowed to increase again.
+ this->bolaState = STARTUP_NO_INC;
+ }
+ if (this->bolaState == STARTUP_NO_INC && quality > this->currentQuality) {
+ // In this state the quality is not allowed to increase until steady state.
+ quality = this->currentQuality;
+ }
+ if (quality <= bolaQuality) {
+ // Since the buffer is full enough for steady state operation to match startup operation, switch over to steady state.
+ this->bolaState = STEADY;
+ }
+ if (this->bolaState != STEADY) {
+ // still in startup mode
+ 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->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);
+ this->lastBufferFill = bufferFill;
+ return;
+ }
+ }
+
+ // Steady State
+
+ // In order to avoid oscillation, the "BOLA-O" variant is implemented.
+ // When network bandwidth lies between two encoded bitrate levels, stick to the lowest one.
+ double delaySeconds = 0.0;
+ if (bolaQuality > this->currentQuality) {
+ Debug("STEADY -- BOLA QUALITY:\t%d - HIGHER than - CURRENT QUALITY:\t%I64u\n", bolaQuality, this->currentBitrate);
+ // do not multiply throughput by bandwidthSafetyFactor here;
+ // we are not using throughput estimation but capping bitrate to avoid oscillations
+ int quality = getQualityFromThroughput(this->batchBw);
+ if (bolaQuality > quality) {
+ // only intervene if we are trying to *increase* quality to an *unsustainable* level
+ if (quality < this->currentQuality) {
+ // The aim is only to avoid oscillations - do not drop below current quality
+ quality = this->currentQuality;
+ } else {
+ // We are dropping to an encoded bitrate which is a little less than the network bandwidth
+ // since bitrate levels are discrete. Quality 'quality' might lead to buffer inflation,
+ // so we deflate the buffer to the level that 'quality' gives positive utility.
+ double targetBufferLevel = this->Vp * (this->utilityVector[quality] + this->gp);
+ delaySeconds = bufferLevelSeconds - targetBufferLevel;
+ }
+ bolaQuality = quality;
+ }
+ }
+
+ if (delaySeconds > 0.0) {
+ // first reduce virtual buffer
+ if (delaySeconds > this->virtualBuffer) {
+ delaySeconds -= this->virtualBuffer;
+ this->virtualBuffer = 0.0;
+ } else {
+ this->virtualBuffer -= delaySeconds;
+ delaySeconds = 0.0;
+ }
+ }
+ if (delaySeconds > 0.0) {
+ // TODO Check the scope of this function. Is it a delayed request?
+ // 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->currentQuality = bolaQuality;
+ //this->representation = this->availableBitrates[this->currentQuality];
+ this->representation = this->adaptationSet->GetRepresentation().at(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);
+ this->lastBufferFill = bufferFill;
+}
+
+void BolaAdaptation::bitrateUpdate(uint64_t bps, uint32_t segNum)
+{
+ this->instantBw = bps;
+
+ // Avg bandwidth estimate with EWMA
+ if(this->averageBw == 0)
+ {
+ this->averageBw = bps;
+ }
+ else
+ {
+ this->averageBw = this->alphaRate*this->averageBw + (1 - this->alphaRate)*bps;
+ }
+
+ // Avg bandwidth estimate with batch mean of THROUGHPUT_SAMPLES sample
+ this->batchBwCount++;
+ this->batchBwSamples.push_back(bps);
+
+ if(this->batchBwCount++ == THROUGHPUT_SAMPLES)
+ {
+ for(int i=0; i<THROUGHPUT_SAMPLES; i++)
+ this->batchBw += this->batchBwSamples[i];
+
+ this->batchBw /= THROUGHPUT_SAMPLES;
+
+ Debug("BATCH BW:\t%I64u\n", this->batchBw);
+
+ this->batchBwCount=0;
+ this->batchBwSamples.clear();
+ }
+}
+
+void BolaAdaptation::dLTimeUpdate(double time)
+{
+ auto m_now = std::chrono::system_clock::now();
+ auto m_now_sec = std::chrono::time_point_cast<std::chrono::seconds>(m_now);
+
+ auto now_value = m_now_sec.time_since_epoch();
+ double dl_instant = now_value.count();
+ //this->lastSegmentDownloadTime = time;
+ //this->currentDownloadTimeInstant = std::chrono::duration_cast<duration_in_seconds>(system_clock::now()).count();
+ this->currentDownloadTimeInstant = dl_instant;
+}
+
+void BolaAdaptation::onEOS(bool value)
+{
+ this->bufferEOS = value;
+}
+
+void BolaAdaptation::checkedByDASHReceiver()
+{
+ this->isCheckedForReceiver = false;
+}
+void BolaAdaptation::bufferUpdate(uint32_t bufferFill, int maxC)
+{
+ this->setBitrate(bufferFill);
+ this->notifyBitrateChange();
+}
diff --git a/Adaptation/Bola.h b/Adaptation/Bola.h
new file mode 100644
index 00000000..29011664
--- /dev/null
+++ b/Adaptation/Bola.h
@@ -0,0 +1,118 @@
+/*
+ * 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 LIBDASH_FRAMEWORK_ADAPTATION_BOLA_H_
+#define LIBDASH_FRAMEWORK_ADAPTATION_BOLA_H_
+
+#include "AbstractAdaptationLogic.h"
+#include "../MPD/AdaptationSetStream.h"
+#include "../Input/IDASHReceiverObserver.h"
+
+namespace libdash
+{
+namespace framework
+{
+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);
+ virtual ~BolaAdaptation();
+
+ virtual LogicType getType();
+ virtual bool isUserDependent();
+ virtual bool isRateBased();
+ virtual bool isBufferBased();
+ virtual void bitrateUpdate(uint64_t bps, uint32_t segNum);
+ virtual void dLTimeUpdate(double time);
+ virtual void bufferUpdate(uint32_t bufferFill, int maxC);
+ void setBitrate(uint32_t bufferFill);
+ uint64_t getBitrate();
+ virtual void setMultimediaManager(viper::managers::IMultimediaManagerBase *_mmManager);
+ void notifyBitrateChange();
+ void onEOS(bool value);
+ void checkedByDASHReceiver();
+
+ int getQualityFromThroughput(uint64_t bps);
+ int getQualityFromBufferLevel(double bufferLevelSec);
+
+private:
+ enum BolaState
+ {
+ ONE_BITRATE, // If one bitrate (or init failed), always NO_CHANGE
+ STARTUP, // Download fragments at most recently measured throughput
+ STARTUP_NO_INC, // If quality increased then decreased during startup, then quality cannot be increased.
+ 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.
+ // 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
+ // 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
+
+ std::vector<uint64_t> availableBitrates;
+ std::vector<double> utilityVector;
+ 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;
+ std::vector<uint64_t> batchBwSamples;
+ 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;
+};
+}
+}
+}
+
+#endif /* LIBDASH_FRAMEWORK_ADAPTATION_BOLA_H_ */
diff --git a/Adaptation/BufferBasedAdaptation.cpp b/Adaptation/BufferBasedAdaptation.cpp
new file mode 100644
index 00000000..18d4a592
--- /dev/null
+++ b/Adaptation/BufferBasedAdaptation.cpp
@@ -0,0 +1,141 @@
+/*
+ * 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.
+ */
+
+#include "BufferBasedAdaptation.h"
+#include<stdio.h>
+
+
+using namespace dash::mpd;
+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)
+{
+ this->reservoirThreshold = params->BufferBased_reservoirThreshold;
+ this->maxThreshold = params->BufferBased_maxThreshold;
+
+ std::vector<IRepresentation* > representations = this->adaptationSet->GetRepresentation();
+
+ this->representation = this->adaptationSet->GetRepresentation().at(0);
+ this->multimediaManager = NULL;
+ this->lastBufferFill = 0;
+ this->bufferEOS = false;
+ this->shouldAbort = false;
+ Debug("BufferBasedParams:\t%f\t%f\n", (double)reservoirThreshold/100, (double)maxThreshold/100);
+ Debug("Buffer Adaptation: STARTED\n");
+}
+
+BufferBasedAdaptation::~BufferBasedAdaptation ()
+{
+}
+
+LogicType BufferBasedAdaptation::getType()
+{
+ return adaptation::BufferBased;
+}
+
+bool BufferBasedAdaptation::isUserDependent()
+{
+ return false;
+}
+
+bool BufferBasedAdaptation::isRateBased()
+{
+ return false;
+}
+bool BufferBasedAdaptation::isBufferBased()
+{
+ return true;
+}
+
+void BufferBasedAdaptation::setMultimediaManager (viper::managers::IMultimediaManagerBase *_mmManager)
+{
+ this->multimediaManager = _mmManager;
+}
+
+void BufferBasedAdaptation::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);
+
+ if(this->shouldAbort)
+ {
+ this->multimediaManager->shouldAbort(this->isVideo);
+ }
+ this->shouldAbort = false;
+}
+
+uint64_t BufferBasedAdaptation::getBitrate()
+{
+ return this->currentBitrate;
+}
+
+void BufferBasedAdaptation::setBitrate(uint32_t bufferFill)
+{
+ std::vector<IRepresentation *> representations;
+ representations = this->adaptationSet->GetRepresentation();
+ size_t i = 0;
+
+ if(representations.size() == 1)
+ {
+ i = 0;
+ }
+ else
+ {
+ while(bufferFill > this->reservoirThreshold + i * (this->maxThreshold - this->reservoirThreshold)/(representations.size()-1))
+ {
+ i++;
+ }
+ }
+ if((size_t)i >= (size_t)(representations.size()))
+ i = representations.size() - 1;
+ this->representation = representations.at(i);
+ if( 0 && !this->bufferEOS && this->lastBufferFill > this->reservoirThreshold && bufferFill <= this->reservoirThreshold)
+ {
+ 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");
+ this->lastBufferFill = bufferFill;
+
+}
+
+void BufferBasedAdaptation::bitrateUpdate(uint64_t bps, uint32_t segNum)
+{
+}
+
+void BufferBasedAdaptation::dLTimeUpdate(double time)
+{
+}
+
+void BufferBasedAdaptation::onEOS(bool value)
+{
+ this->bufferEOS = value;
+}
+
+void BufferBasedAdaptation::checkedByDASHReceiver()
+{
+}
+
+void BufferBasedAdaptation::bufferUpdate(uint32_t bufferFill, int maxC)
+{
+ this->setBitrate(bufferFill);
+ this->notifyBitrateChange();
+}
diff --git a/Adaptation/BufferBasedAdaptation.h b/Adaptation/BufferBasedAdaptation.h
new file mode 100644
index 00000000..32ad8045
--- /dev/null
+++ b/Adaptation/BufferBasedAdaptation.h
@@ -0,0 +1,64 @@
+/*
+ * 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 LIBDASH_FRAMEWORK_ADAPTATION_BUFFERBASEDADAPTATION_H_
+#define LIBDASH_FRAMEWORK_ADAPTATION_BUFFERBASEDADAPTATION_H_
+
+#include "AbstractAdaptationLogic.h"
+#include "../MPD/AdaptationSetStream.h"
+#include "../Input/IDASHReceiverObserver.h"
+
+namespace libdash
+{
+namespace framework
+{
+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);
+ virtual ~BufferBasedAdaptation();
+
+ virtual LogicType getType();
+ virtual bool isUserDependent();
+ virtual bool isRateBased();
+ virtual bool isBufferBased();
+ virtual void bitrateUpdate(uint64_t bps, uint32_t segNum);
+ virtual void bufferUpdate(uint32_t bufferFill, int maxC);
+ virtual void dLTimeUpdate(double time);
+ void setBitrate(uint32_t bufferFill);
+ uint64_t getBitrate();
+ virtual void setMultimediaManager(viper::managers::IMultimediaManagerBase *_mmManager);
+ void notifyBitrateChange();
+ void onEOS(bool value);
+ void checkedByDASHReceiver();
+
+private:
+ uint64_t currentBitrate;
+ std::vector<uint64_t> availableBitrates;
+ viper::managers::IMultimediaManagerBase *multimediaManager;
+ dash::mpd::IRepresentation *representation;
+ uint32_t reservoirThreshold;
+ uint32_t maxThreshold;
+ uint32_t lastBufferFill;
+ bool bufferEOS;
+ bool shouldAbort;
+};
+}
+}
+}
+
+#endif /* LIBDASH_FRAMEWORK_ADAPTATION_BUFFERBASEDADAPTATION_H_ */
diff --git a/Adaptation/BufferBasedAdaptationWithRateBased.cpp b/Adaptation/BufferBasedAdaptationWithRateBased.cpp
new file mode 100644
index 00000000..3a1895c0
--- /dev/null
+++ b/Adaptation/BufferBasedAdaptationWithRateBased.cpp
@@ -0,0 +1,206 @@
+/*
+ * 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.
+ */
+
+#include "BufferBasedAdaptationWithRateBased.h"
+#include<stdio.h>
+
+using namespace dash::mpd;
+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)
+{
+ this->alphaRate = params->Adaptech_Alpha;
+ this->reservoirThreshold = params->Adaptech_FirstThreshold;
+ this->maxThreshold = params->Adaptech_SecondThreshold;
+ this->switchUpThreshold = params->Adaptech_SwitchUpThreshold;
+ this->slackParam = params->Adaptech_SlackParameter;
+
+ std::vector<IRepresentation* > representations = this->adaptationSet->GetRepresentation();
+
+ this->m_count = 0;
+ this->instantBw = 0;
+ this->averageBw = 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;
+ 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");
+}
+BufferBasedAdaptationWithRateBased::~BufferBasedAdaptationWithRateBased ()
+{
+}
+
+LogicType BufferBasedAdaptationWithRateBased::getType()
+{
+ return adaptation::BufferBased;
+}
+
+bool BufferBasedAdaptationWithRateBased::isUserDependent()
+{
+ return false;
+}
+
+bool BufferBasedAdaptationWithRateBased::isRateBased()
+{
+ return true;
+}
+bool BufferBasedAdaptationWithRateBased::isBufferBased()
+{
+ return true;
+}
+
+void BufferBasedAdaptationWithRateBased::setMultimediaManager(viper::managers::IMultimediaManagerBase *_mmManager)
+{
+ this->multimediaManager = _mmManager;
+}
+
+void BufferBasedAdaptationWithRateBased::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;
+}
+
+uint64_t BufferBasedAdaptationWithRateBased::getBitrate()
+{
+ return this->currentBitrate;
+}
+
+void BufferBasedAdaptationWithRateBased::setBitrate(uint32_t bufferFill)
+{
+ uint32_t phi1, phi2;
+ std::vector<IRepresentation *> representations;
+ representations = this->adaptationSet->GetRepresentation();
+ size_t i = 0;
+
+ Debug("bufferlevel: %u, instant rate %lu, average rate %lu\n", bufferFill, this->instantBw, this->averageBw);
+ phi1 = 0;
+ phi2 = 0;
+ while(i < representations.size())
+ {
+ if(phi1 == 0 && representations.at(i)->GetBandwidth() > slackParam * this->instantBw)
+ {
+ phi1 = representations.at((i == 0) ? i : i -1)->GetBandwidth();
+ }
+ if(phi2 == 0 && representations.at(i)->GetBandwidth() > slackParam * this->averageBw)
+ {
+ phi2 = representations.at((i == 0) ? i : i -1)->GetBandwidth();
+ }
+ i++;
+ }
+
+ if(!phi1)
+ phi1 = representations.at(representations.size() - 1)->GetBandwidth();
+
+ if(!phi2)
+ phi2 = representations.at(representations.size() - 1)->GetBandwidth();
+
+ if(bufferFill < this->reservoirThreshold)
+ {
+ this->m_count = 0;
+ this->myQuality = 0;
+ }
+ else
+ {
+ if(bufferFill < this->maxThreshold)
+ {
+ this->m_count = 0;
+ if(this->currentBitrate > phi1)
+ {
+ if(this->myQuality > 0)
+ {
+ this->myQuality--;
+ }
+ }
+ else
+ {
+ if(this->currentBitrate < phi1)
+ {
+ if(this->myQuality < representations.size() - 1)
+ {
+ this->myQuality++;
+ }
+ }
+ }
+ }
+ else
+ { // bufferFill > this->maxThreshold
+ if(this->currentBitrate < phi2)
+ {
+ m_count++;
+
+ if(m_count >= switchUpThreshold && this->myQuality < representations.size() - 1)
+ {
+ this->m_count = 0;
+ 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, AverageBW: %lu, choice: %d\n",isVideo ? "video" : "audio",(double)lastBufferFill/100 , (double)bufferFill/100, this->instantBw, this->averageBw , this->myQuality);
+}
+
+void BufferBasedAdaptationWithRateBased::bitrateUpdate(uint64_t bps, uint32_t segNum)
+{
+ Debug("rate estimation: %lu\n", bps);
+ this->instantBw = bps;
+ if(this->averageBw == 0)
+ {
+ this->averageBw = bps;
+ }
+ else
+ {
+ this->averageBw = this->alphaRate*this->averageBw + (1 - this->alphaRate)*bps;
+ }
+}
+
+void BufferBasedAdaptationWithRateBased::onEOS(bool value)
+{
+ this->bufferEOS = value;
+}
+
+void BufferBasedAdaptationWithRateBased::checkedByDASHReceiver()
+{
+ this->isCheckedForReceiver = false;
+}
+void BufferBasedAdaptationWithRateBased::bufferUpdate(uint32_t bufferFill, int maxC)
+{
+ Debug("buffer update: %u\n", bufferFill);
+ this->setBitrate(bufferFill);
+ this->notifyBitrateChange();
+}
+
+void BufferBasedAdaptationWithRateBased::dLTimeUpdate(double time)
+{
+}
+
diff --git a/Adaptation/BufferBasedAdaptationWithRateBased.h b/Adaptation/BufferBasedAdaptationWithRateBased.h
new file mode 100644
index 00000000..5c787d30
--- /dev/null
+++ b/Adaptation/BufferBasedAdaptationWithRateBased.h
@@ -0,0 +1,72 @@
+/*
+ * 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 LIBDASH_FRAMEWORK_ADAPTATION_BUFFERBASEDADAPTATIONRATE_H_
+#define LIBDASH_FRAMEWORK_ADAPTATION_BUFFERBASEDADAPTATIONRATE_H_
+
+#include "AbstractAdaptationLogic.h"
+#include "../MPD/AdaptationSetStream.h"
+#include "../Input/IDASHReceiverObserver.h"
+
+namespace libdash
+{
+namespace framework
+{
+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);
+ virtual ~BufferBasedAdaptationWithRateBased();
+
+ virtual LogicType getType();
+ virtual bool isUserDependent();
+ virtual bool isRateBased();
+ virtual bool isBufferBased();
+ virtual void bitrateUpdate(uint64_t bps, uint32_t segNum);
+ virtual void bufferUpdate(uint32_t bufferFill, int maxC);
+ virtual void dLTimeUpdate(double time);
+ void setBitrate(uint32_t bufferFill);
+ uint64_t getBitrate();
+ virtual void setMultimediaManager(viper::managers::IMultimediaManagerBase *_mmManager);
+ void notifyBitrateChange();
+ void onEOS(bool value);
+ void checkedByDASHReceiver();
+
+private:
+ uint64_t currentBitrate;
+ std::vector<uint64_t> 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;
+ uint64_t averageBw;
+ uint64_t instantBw;
+ int myQuality;
+ double slackParam;
+ bool isCheckedForReceiver;
+};
+}
+}
+}
+
+#endif /* LIBDASH_FRAMEWORK_ADAPTATION_BUFFERBASEDADAPTATIONRATE_H_ */
diff --git a/Adaptation/BufferBasedThreeThresholdAdaptation.cpp b/Adaptation/BufferBasedThreeThresholdAdaptation.cpp
new file mode 100644
index 00000000..021e7b7c
--- /dev/null
+++ b/Adaptation/BufferBasedThreeThresholdAdaptation.cpp
@@ -0,0 +1,166 @@
+/*
+ * 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.
+ */
+
+#include "BufferBasedThreeThresholdAdaptation.h"
+#include<stdio.h>
+
+using namespace dash::mpd;
+using namespace libdash::framework::adaptation;
+using namespace libdash::framework::input;
+using namespace libdash::framework::mpd;
+
+BufferBasedThreeThresholdAdaptation::BufferBasedThreeThresholdAdaptation(IMPD *mpd, IPeriod *period, IAdaptationSet *adaptationSet, bool isVid, struct AdaptationParameters *params) :
+ AbstractAdaptationLogic(mpd, period, adaptationSet, isVid)
+{
+ this->firstThreshold = params->BufferThreeThreshold_FirstThreshold;
+ this->secondThreshold = params->BufferThreeThreshold_SecondThreshold;
+ this->thirdThreshold = params->BufferThreeThreshold_ThirdThreshold;
+ this->slackParam = params->BufferThreeThreshold_slackParameter;
+ std::vector<IRepresentation* > 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");
+}
+
+BufferBasedThreeThresholdAdaptation::~BufferBasedThreeThresholdAdaptation()
+{
+}
+
+LogicType BufferBasedThreeThresholdAdaptation::getType()
+{
+ return adaptation::BufferBasedThreeThreshold;
+}
+
+bool BufferBasedThreeThresholdAdaptation::isUserDependent()
+{
+ return false;
+}
+
+bool BufferBasedThreeThresholdAdaptation::isRateBased()
+{
+ return true;
+}
+
+bool BufferBasedThreeThresholdAdaptation::isBufferBased()
+{
+ return true;
+}
+
+void BufferBasedThreeThresholdAdaptation::setMultimediaManager(viper::managers::IMultimediaManagerBase *_mmManager)
+{
+ this->multimediaManager = _mmManager;
+}
+
+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;
+}
+
+uint64_t BufferBasedThreeThresholdAdaptation::getBitrate()
+{
+ return this->currentBitrate;
+}
+
+void BufferBasedThreeThresholdAdaptation::setBitrate(uint32_t bufferFill)
+{
+ uint32_t phi1, phi2;
+ std::vector<IRepresentation *> 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);
+}
+
+void BufferBasedThreeThresholdAdaptation::bitrateUpdate(uint64_t bps, uint32_t segNum)
+{
+ this->instantBw = bps;
+}
+
+void BufferBasedThreeThresholdAdaptation::onEOS(bool value)
+{
+ this->bufferEOS = value;
+}
+
+void BufferBasedThreeThresholdAdaptation::checkedByDASHReceiver()
+{
+ this->isCheckedForReceiver = false;
+}
+void BufferBasedThreeThresholdAdaptation::bufferUpdate(uint32_t bufferFill, int maxC)
+{
+ this->setBitrate(bufferFill);
+ this->notifyBitrateChange();
+}
+
+void BufferBasedThreeThresholdAdaptation::dLTimeUpdate(double time)
+{
+}
+
+
diff --git a/Adaptation/BufferBasedThreeThresholdAdaptation.h b/Adaptation/BufferBasedThreeThresholdAdaptation.h
new file mode 100644
index 00000000..62160bc3
--- /dev/null
+++ b/Adaptation/BufferBasedThreeThresholdAdaptation.h
@@ -0,0 +1,69 @@
+/*
+ * 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 LIBDASH_FRAMEWORK_ADAPTATION_BUFFERBASEDADAPTATIONTHREE_H_
+#define LIBDASH_FRAMEWORK_ADAPTATION_BUFFERBASEDADAPTATIONTHREE_H_
+
+#include "AbstractAdaptationLogic.h"
+#include "../MPD/AdaptationSetStream.h"
+#include "../Input/IDASHReceiverObserver.h"
+
+namespace libdash
+{
+namespace framework
+{
+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);
+ virtual ~BufferBasedThreeThresholdAdaptation();
+
+ virtual LogicType getType();
+ virtual bool isUserDependent();
+ virtual bool isRateBased();
+ virtual bool isBufferBased();
+ virtual void bitrateUpdate(uint64_t bps, uint32_t segNum);
+ virtual void bufferUpdate(uint32_t bufferFill, int maxC);
+ virtual void dLTimeUpdate(double time);
+ void setBitrate(uint32_t bufferFill);
+ uint64_t getBitrate();
+ virtual void setMultimediaManager(viper::managers::IMultimediaManagerBase *_mmManager);
+ void notifyBitrateChange();
+ void onEOS(bool value);
+ void checkedByDASHReceiver();
+
+private:
+ uint64_t currentBitrate;
+ std::vector<uint64_t> 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;
+};
+}
+}
+}
+
+#endif /* LIBDASH_FRAMEWORK_ADAPTATION_BUFFERBASEDADAPTATIONTHREE_H_ */
diff --git a/Adaptation/IAdaptationLogic.h b/Adaptation/IAdaptationLogic.h
new file mode 100644
index 00000000..bfe980c7
--- /dev/null
+++ b/Adaptation/IAdaptationLogic.h
@@ -0,0 +1,115 @@
+/*
+ * IAdaptationLogic.h
+ *****************************************************************************
+ * Copyright (C) 2012, bitmovin Softwareentwicklung OG, All Rights Reserved
+ *
+ * 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.
+ *****************************************************************************/
+
+#ifndef LIBDASH_FRAMEWORK_ADAPTATION_IADAPTATIONLOGIC_H_
+#define LIBDASH_FRAMEWORK_ADAPTATION_IADAPTATIONLOGIC_H_
+#include "../Input/MediaObject.h"
+#include "../Input/DASHReceiver.h"
+#include "IRepresentation.h"
+#include "../Managers/IMultimediaManagerBase.h"
+
+namespace libdash
+{
+namespace framework
+{
+namespace input
+{
+class DASHReceiver;
+}
+namespace adaptation
+{
+//#define START __LINE__
+//ADAPTATIONLOGIC Count is an hack to have the number of adaptation logic that we can use
+#define FOREACH_ADAPTATIONLOGIC(ADAPTATIONLOGIC) \
+ ADAPTATIONLOGIC(AlwaysLowest) \
+ ADAPTATIONLOGIC(RateBased) \
+ ADAPTATIONLOGIC(BufferBased) \
+ ADAPTATIONLOGIC(BufferRateBased) \
+ ADAPTATIONLOGIC(BufferBasedThreeThreshold) \
+ ADAPTATIONLOGIC(Panda) \
+ ADAPTATIONLOGIC(Bola) \
+ ADAPTATIONLOGIC(Count) \
+
+
+#define GENERATE_ENUM(ENUM) ENUM,
+#define GENERATE_STRING(STRING) #STRING,
+
+enum LogicType {
+ FOREACH_ADAPTATIONLOGIC(GENERATE_ENUM)
+};
+
+static const char *LogicType_string[] = {
+ FOREACH_ADAPTATIONLOGIC(GENERATE_STRING)
+};
+
+class IAdaptationLogic
+{
+public:
+ virtual ~IAdaptationLogic() {}
+
+ 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 LogicType getType() = 0;
+ virtual bool isUserDependent()= 0;
+ virtual void bitrateUpdate(uint64_t bps, uint32_t segNum) = 0;
+ virtual void dLTimeUpdate(double time) = 0;
+ virtual void bufferUpdate(uint32_t bufferfillstate, int maxC) = 0;
+ virtual bool isRateBased() = 0;
+ virtual bool isBufferBased() = 0;
+ virtual void setMultimediaManager(viper::managers::IMultimediaManagerBase *mmManager)= 0;
+ virtual void onEOS(bool value) = 0;
+ virtual void checkedByDASHReceiver() = 0;
+};
+
+struct AdaptationParameters
+{
+ int segmentBufferSize;
+ double segmentDuration;
+
+ //RATE BASED
+ double Rate_Alpha;
+
+ //BUFFER BASED
+ int BufferBased_reservoirThreshold;
+ int BufferBased_maxThreshold;
+
+ //BOLA
+ double Bola_Alpha;
+ double Bola_bufferTargetSeconds;
+
+ //ADAPTECH
+ double Adaptech_Alpha;
+ int Adaptech_FirstThreshold;
+ int Adaptech_SecondThreshold;
+ int Adaptech_SwitchUpThreshold;
+ double Adaptech_SlackParameter;
+
+ //BUFFER THREE THRESHOLDS
+ int BufferThreeThreshold_FirstThreshold;
+ int BufferThreeThreshold_SecondThreshold;
+ int BufferThreeThreshold_ThirdThreshold;
+ double BufferThreeThreshold_slackParameter;
+ //PANDA
+ double Panda_Alpha;
+ double Panda_Beta;
+ double Panda_Bmin;
+ double Panda_K;
+ double Panda_W;
+ double Panda_Epsilon;
+};
+}
+}
+}
+#endif /* LIBDASH_FRAMEWORK_ADAPTATION_IADAPTATIONLOGIC_H_ */
diff --git a/Adaptation/Panda.cpp b/Adaptation/Panda.cpp
new file mode 100644
index 00000000..cb2ec660
--- /dev/null
+++ b/Adaptation/Panda.cpp
@@ -0,0 +1,274 @@
+/*
+ * 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.
+ */
+
+#include "Panda.h"
+#include<stdio.h>
+
+
+using namespace dash::mpd;
+using namespace libdash::framework::adaptation;
+using namespace libdash::framework::input;
+using namespace libdash::framework::mpd;
+
+PandaAdaptation::PandaAdaptation(IMPD *mpd, IPeriod *period, IAdaptationSet *adaptationSet, bool isVid, struct AdaptationParameters *params) :
+ AbstractAdaptationLogic (mpd, period, adaptationSet, isVid)
+{
+ this->param_Alpha = params->Panda_Alpha;
+ this->param_Beta = params->Panda_Beta;
+ this->param_Bmin = params->Panda_Bmin;
+ this->param_K = params->Panda_K;
+ this->param_W = params->Panda_W;
+ this->param_Epsilon = params->Panda_Epsilon;
+
+ this->segmentDuration = params->segmentDuration;
+ this->bufferMaxSizeSeconds = params->segmentBufferSize * this->segmentDuration;
+ this->targetBw = 0;
+ this->targetInterTime = 0.0;
+
+ this->averageBw = 0;
+ this->smoothBw = 0;
+ this->instantBw = 0;
+ this->targetBw = 0;
+
+ this->targetInterTime = 0.0;
+ this->interTime = 0.0;
+
+ this->alpha_ewma = 0.8;
+
+ this->bufferLevel = 0;
+ this->bufferLevelSeconds = 0.0;
+
+ this->downloadTime = 0.0;
+
+ this->isVideo = isVid;
+ 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<IRepresentation* > representations = this->adaptationSet->GetRepresentation();
+
+ this->availableBitrates.clear();
+ Debug("PANDA Available Bitrates...\n");
+ for(size_t i = 0; i < representations.size(); i++)
+ {
+ this->availableBitrates.push_back((uint64_t)(representations.at(i)->GetBandwidth()));
+ Debug("%d - %I64u bps\n", i+1, this->availableBitrates[i]);
+ }
+
+ this->representation = this->adaptationSet->GetRepresentation().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);
+}
+
+PandaAdaptation::~PandaAdaptation() {
+}
+
+LogicType PandaAdaptation::getType()
+{
+ return adaptation::Panda;
+}
+
+bool PandaAdaptation::isUserDependent()
+{
+ return false;
+}
+
+bool PandaAdaptation::isRateBased()
+{
+ return true;
+}
+
+bool PandaAdaptation::isBufferBased()
+{
+ return true;
+}
+
+void PandaAdaptation::setMultimediaManager (viper::managers::IMultimediaManagerBase *_mmManager)
+{
+ this->multimediaManager = _mmManager;
+}
+
+void PandaAdaptation::notifyBitrateChange()
+{
+ 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);
+}
+
+uint64_t PandaAdaptation::getBitrate()
+{
+ return this->currentBitrate;
+}
+
+void PandaAdaptation::quantizer()
+{
+ this->deltaUp = this->param_Epsilon * (double)this->smoothBw;
+ this->deltaDown = 0.0;
+
+ Debug("** DELTA UP:\t%f\n", this->deltaUp);
+
+ uint64_t smoothBw_UP = this->smoothBw - this->deltaUp;
+ uint64_t smoothBw_DOWN = this->smoothBw - this->deltaDown;
+
+ Debug("** Smooth-BW UP:\t%d\t Smooth-BW DOWN:\t%d\n", smoothBw_UP, smoothBw_DOWN);
+
+ std::vector<IRepresentation *> representations;
+ representations = this->adaptationSet->GetRepresentation();
+ uint32_t numQualLevels = representations.size();
+
+ // We have to find bitrateMin and bitrateMax
+ uint64_t bitrateDown, bitrateUp;
+
+ // DOWN
+ uint32_t iDown = 0;
+ uint32_t i_d,i_u;
+ for (i_d = 0; i_d < this->availableBitrates.size(); ++i_d) {
+ if (this->availableBitrates[i_d] > smoothBw_DOWN) {
+ break;
+ }
+ }
+ if(i_d > 0)
+ iDown = i_d-1;
+ else
+ iDown = 0;
+
+ bitrateDown = (uint64_t) representations.at(iDown)->GetBandwidth();
+ Debug("** Bitrate DOWN:\t%d\t at Quality:\t%d\n", bitrateDown, iDown);
+
+ // UP
+ uint32_t iUp = 0;
+ for (i_u = 0; i_u < this->availableBitrates.size(); ++i_u) {
+ if (this->availableBitrates[i_u] > smoothBw_UP) {
+ break;
+ }
+ }
+ if(i_u > 0)
+ iUp = i_u-1;
+ else
+ iUp = 0;
+
+ bitrateUp = (uint64_t) representations.at(iUp)->GetBandwidth();
+ Debug("** Bitrate UP:\t%d\t at Quality:\t%d\n", bitrateUp, iUp);
+
+ Debug("** Current RATE:\t%d\n Current QUALITY:\t%d\n", this->currentBitrate, this->current);
+
+
+ // Next bitrate computation
+ if(this->currentBitrate < bitrateUp)
+ {
+ this->currentBitrate = bitrateUp;
+ this->current = iUp;
+ }
+ else if(this->currentBitrate <= bitrateDown && this->currentBitrate >= bitrateUp)
+ {
+ Debug("** CURRENT UNCHANGED **\n");
+ }
+ else
+ {
+ this->currentBitrate = bitrateDown;
+ this->current = iDown;
+ }
+ this->representation = this->adaptationSet->GetRepresentation().at(this->current);
+}
+
+void PandaAdaptation::setBitrate(uint64_t bps)
+{
+
+ // 1. Calculating the targetBW
+ if(this->targetBw)
+ {
+ //this->targetBw = this->targetBw + param_K * this->interTime * (param_W - ((this->targetBw - bps + this->param_W) > 0 ? this->targetBw - bps + this->param_W: 0));
+ if ((double)this->targetBw - (double)bps + this->param_W > 0)
+ this->targetBw = this->targetBw + (uint64_t)(param_K * this->interTime * (param_W - ((double)this->targetBw - (double)bps + this->param_W)));
+ else
+ this->targetBw = this->targetBw + (uint64_t)(param_K * this->interTime * param_W);
+ }
+ else
+ this->targetBw = bps;
+
+ Debug("** INSTANTANEOUS BW:\t%d\n", bps);
+ Debug("** CLASSIC EWMA BW:\t%d\n", this->averageBw);
+ Debug("** PANDA TARGET BW:\t%d\n", this->targetBw);
+
+ // 2. Calculating the smoothBW
+ if(this->interTime)
+ this->smoothBw = (uint64_t)((double)this->smoothBw - this->param_Alpha * this->interTime * ((double)this->smoothBw - (double)this->targetBw));
+ else
+ this->smoothBw = this->targetBw;
+
+ Debug("** PANDA SMOOTH BW:\t%d\n", this->smoothBw);
+
+ // 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);
+ this->lastBufferLevel = this->bufferLevel;
+
+ // 4. Computing the "actual inter time"
+ this->bufferLevelSeconds = (double)((this->bufferLevel * this->bufferMaxSizeSeconds) *1./100);
+ this->targetInterTime = ((double)this->currentBitrate * segmentDuration) * 1./this->smoothBw + param_Beta * (this->bufferLevelSeconds - param_Bmin);
+ Debug("** TARGET INTER TIME:\t%f\n", this->targetInterTime);
+ Debug("** DOWNLOAD TIME:\t%f\n", this->downloadTime);
+ this->targetInterTime = (this->targetInterTime > 0) ? this->targetInterTime : 0.0;
+ this->interTime = this->targetInterTime > this->downloadTime ? this->targetInterTime : this->downloadTime;
+ this->interTime = this->interTime > 3 ? 3 : this->interTime;
+
+ Debug("** ACTUAL INTER TIME:\t%f\n", this->interTime);
+ this->multimediaManager->setTargetDownloadingTime(this->isVideo, interTime);
+}
+
+void PandaAdaptation::bitrateUpdate(uint64_t bps, uint32_t segNum)
+{
+ this->instantBw = bps;
+
+ // Avg bandwidth estimate with EWMA
+ if(this->averageBw == 0)
+ {
+ this->averageBw = bps;
+ }
+ else
+ {
+ this->averageBw = this->alpha_ewma*this->averageBw + (1 - this->alpha_ewma)*bps;
+ }
+
+ this->setBitrate(bps);
+ this->notifyBitrateChange();
+}
+
+void PandaAdaptation::dLTimeUpdate(double time)
+{
+ this->downloadTime = time;
+}
+
+void PandaAdaptation::bufferUpdate(uint32_t bufferfill, int maxC)
+{
+ Debug("bufferlvl: %d\n", bufferfill);
+ this->bufferLevel = bufferfill;
+}
+
+void PandaAdaptation::onEOS(bool value)
+{
+}
+
+void PandaAdaptation::checkedByDASHReceiver()
+{
+}
diff --git a/Adaptation/Panda.h b/Adaptation/Panda.h
new file mode 100644
index 00000000..000131a1
--- /dev/null
+++ b/Adaptation/Panda.h
@@ -0,0 +1,89 @@
+/*
+ * 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 LIBDASH_FRAMEWORK_ADAPTATION_PANDA_H_
+#define LIBDASH_FRAMEWORK_ADAPTATION_PANDA_H_
+
+#include "AbstractAdaptationLogic.h"
+#include "../MPD/AdaptationSetStream.h"
+#include "../Input/IDASHReceiverObserver.h"
+
+namespace libdash
+{
+namespace framework
+{
+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);
+ virtual ~PandaAdaptation();
+
+ virtual LogicType getType();
+ virtual bool isUserDependent();
+ virtual bool isRateBased();
+ virtual bool isBufferBased();
+ virtual void bitrateUpdate(uint64_t bps, uint32_t segNum);
+ virtual void dLTimeUpdate(double time);
+ virtual void bufferUpdate(uint32_t bufferFill, int maxC);
+ void setBitrate(uint64_t bufferFill);
+ uint64_t getBitrate();
+ virtual void setMultimediaManager(viper::managers::IMultimediaManagerBase *_mmManager);
+ void notifyBitrateChange();
+ void onEOS(bool value);
+ void checkedByDASHReceiver();
+
+ void quantizer();
+private:
+ uint64_t currentBitrate;
+
+ std::vector<uint64_t> availableBitrates;
+ viper::managers::IMultimediaManagerBase *multimediaManager;
+ 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
+
+ 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;
+
+ 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;
+};
+
+} /* namespace adaptation */
+} /* namespace framework */
+} /* namespace libdash */
+
+#endif /* LIBDASH_FRAMEWORK_ADAPTATION_PANDA_H_ */
diff --git a/Adaptation/RateBasedAdaptation.cpp b/Adaptation/RateBasedAdaptation.cpp
new file mode 100644
index 00000000..73d4ee9b
--- /dev/null
+++ b/Adaptation/RateBasedAdaptation.cpp
@@ -0,0 +1,140 @@
+/*
+ * 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.
+ */
+
+#include "RateBasedAdaptation.h"
+#include<stdio.h>
+using namespace dash::mpd;
+using namespace libdash::framework::adaptation;
+using namespace libdash::framework::input;
+using namespace libdash::framework::mpd;
+
+RateBasedAdaptation::RateBasedAdaptation(IMPD *mpd, IPeriod *period, IAdaptationSet *adaptationSet, bool isVid, struct AdaptationParameters *params) :
+ AbstractAdaptationLogic(mpd, period, adaptationSet, isVid)
+{
+ std::vector<IRepresentation* > representations = this->adaptationSet->GetRepresentation();
+
+ this->availableBitrates.clear();
+ for(size_t i = 0; i < representations.size(); i++)
+ {
+ this->availableBitrates.push_back((uint64_t)(representations.at(i)->GetBandwidth()));
+ }
+ this->currentBitrate = this->availableBitrates.at(0);
+ this->representation = representations.at(0);
+ this->multimediaManager = NULL;
+ this->alpha = params->Rate_Alpha;
+ Debug("RateBasedParams:\t%f\n",alpha);
+ this->averageBw = 0;
+}
+
+RateBasedAdaptation::~RateBasedAdaptation()
+{
+}
+
+LogicType RateBasedAdaptation::getType()
+{
+ return adaptation::RateBased;
+}
+
+bool RateBasedAdaptation::isUserDependent()
+{
+ return false;
+}
+
+bool RateBasedAdaptation::isRateBased()
+{
+ return true;
+}
+
+bool RateBasedAdaptation::isBufferBased()
+{
+ return false;
+}
+
+void RateBasedAdaptation::setMultimediaManager(viper::managers::IMultimediaManagerBase *_mmManager)
+{
+ this->multimediaManager = _mmManager;
+}
+
+void RateBasedAdaptation::notifyBitrateChange()
+{
+ 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);
+}
+
+uint64_t RateBasedAdaptation::getBitrate()
+{
+ return this->currentBitrate;
+}
+
+void RateBasedAdaptation::setBitrate(uint64_t bps)
+{
+ std::vector<IRepresentation *> representations;
+ representations = this->adaptationSet->GetRepresentation();
+ size_t i = 0;
+ this->ewma(bps);
+ for(i = 0;i < representations.size();i++)
+ {
+ if(representations.at(i)->GetBandwidth() > this->averageBw)
+ {
+ if(i > 0)
+ i--;
+ break;
+ }
+ }
+ 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);
+ this->representation = representations.at(i);
+ this->currentBitrate = this->representation->GetBandwidth();
+}
+
+void RateBasedAdaptation::bitrateUpdate(uint64_t bps, uint32_t segNum)
+{
+ Debug("Rate Based adaptation: speed received: %lu\n", bps);
+ this->setBitrate(bps);
+ this->notifyBitrateChange();
+}
+
+void RateBasedAdaptation::ewma(uint64_t bps)
+{
+ if(averageBw)
+ {
+ averageBw = alpha*averageBw + (1-alpha)*bps;
+ }
+ else
+ {
+ averageBw = bps;
+ }
+}
+
+void RateBasedAdaptation::onEOS(bool value)
+{
+}
+
+void RateBasedAdaptation::checkedByDASHReceiver()
+{
+}
+
+void RateBasedAdaptation::bufferUpdate(uint32_t bufferfill, int maxC)
+{
+}
+
+void RateBasedAdaptation::dLTimeUpdate(double time)
+{
+}
diff --git a/Adaptation/RateBasedAdaptation.h b/Adaptation/RateBasedAdaptation.h
new file mode 100644
index 00000000..cbf7471c
--- /dev/null
+++ b/Adaptation/RateBasedAdaptation.h
@@ -0,0 +1,61 @@
+/*
+ * 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 LIBDASH_FRAMEWORK_ADAPTATION_RATEBASEDADAPTATION_H_
+#define LIBDASH_FRAMEWORK_ADAPTATION_RATEBASEDADAPTATION_H_
+
+#include "AbstractAdaptationLogic.h"
+#include "../MPD/AdaptationSetStream.h"
+#include "../Input/IDASHReceiverObserver.h"
+
+namespace libdash
+{
+namespace framework
+{
+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);
+ virtual ~RateBasedAdaptation();
+
+ virtual LogicType getType();
+ virtual bool isUserDependent();
+ virtual bool isRateBased();
+ virtual bool isBufferBased();
+ virtual void bitrateUpdate(uint64_t bps, uint32_t segNum);
+ virtual void bufferUpdate(uint32_t bufferfill, int maxC);
+ virtual void dLTimeUpdate(double time);
+ void setBitrate(uint64_t bps);
+ uint64_t getBitrate();
+ virtual void setMultimediaManager(viper::managers::IMultimediaManagerBase *_mmManager);
+ void notifyBitrateChange();
+ void onEOS(bool value);
+ void ewma(uint64_t bps);
+ void checkedByDASHReceiver();
+private:
+ uint64_t currentBitrate;
+ std::vector<uint64_t> availableBitrates;
+ viper::managers::IMultimediaManagerBase *multimediaManager;
+ dash::mpd::IRepresentation *representation;
+ double alpha;
+ uint64_t averageBw;
+};
+}
+}
+}
+
+#endif /* LIBDASH_FRAMEWORK_ADAPTATION_RATEBASEDADAPTATION_H_ */