diff options
Diffstat (limited to 'Adaptation/Panda.cpp')
-rw-r--r-- | Adaptation/Panda.cpp | 274 |
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() +{ +} |