aboutsummaryrefslogtreecommitdiffstats
path: root/Adaptation/Panda.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Adaptation/Panda.cpp')
-rw-r--r--Adaptation/Panda.cpp274
1 files changed, 274 insertions, 0 deletions
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()
+{
+}