summaryrefslogtreecommitdiffstats
path: root/UI
diff options
context:
space:
mode:
authorLuca Muscariello <lumuscar+fdio@cisco.com>2017-02-25 23:42:31 +0100
committerLuca Muscariello <lumuscar+fdio@cisco.com>2017-02-25 23:42:31 +0100
commit05c1a838c881ea502888659848d8792843b28718 (patch)
treecf0b05b58bd725a1eb6c80325ba986c63dea42aa /UI
parent9b30fc10fb1cbebe651e5a107e8ca5b24de54675 (diff)
Initial commit: video player - viper
Change-Id: Id5aa33598ce34659bad4a7a9ae5006bfb84f9bd1 Signed-off-by: Luca Muscariello <lumuscar+fdio@cisco.com>
Diffstat (limited to 'UI')
-rw-r--r--UI/DASHPlayer.cpp923
-rw-r--r--UI/DASHPlayer.h207
-rw-r--r--UI/DASHPlayerNoGUI.cpp383
-rw-r--r--UI/DASHPlayerNoGUI.h93
-rw-r--r--UI/GraphDataSource.cpp146
-rw-r--r--UI/GraphDataSource.h62
-rw-r--r--UI/IDASHPlayerGuiObserver.h35
-rw-r--r--UI/IDASHPlayerNoGuiObserver.h29
-rw-r--r--UI/ViperGui.cpp414
-rw-r--r--UI/ViperGui.h128
10 files changed, 2420 insertions, 0 deletions
diff --git a/UI/DASHPlayer.cpp b/UI/DASHPlayer.cpp
new file mode 100644
index 00000000..b87dde74
--- /dev/null
+++ b/UI/DASHPlayer.cpp
@@ -0,0 +1,923 @@
+/*
+ * DASHPlayer.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 "DASHPlayer.h"
+#include <iostream>
+
+using namespace libdash::framework::adaptation;
+using namespace libdash::framework::mpd;
+using namespace libdash::framework::buffer;
+using namespace viper;
+using namespace viper::managers;
+using namespace dash::mpd;
+using namespace std;
+
+DASHPlayer::DASHPlayer(ViperGui &gui, Config *config) :
+ gui (&gui),
+ config (config)
+{
+ InitializeCriticalSection(&this->monitorMutex);
+ this->offset = 0;
+ this->url = NULL;
+ this->icn = false;
+ this->adaptLogic = LogicType::RateBased;
+ this->seek = false;
+ this->reloadParameters();
+ this->setSettings(0, 0, 0, 0, 0);
+ this->multimediaManager = new MultimediaManager(this->gui, this->parametersAdaptation->segmentBufferSize, config->getConfigPath().toStdString() + QString::fromLatin1("/").toStdString());
+ this->multimediaManager->setBeta(config->beta());
+ this->multimediaManager->setDrop(config->drop());
+ connect(this->gui->getVideoPlayer(), SIGNAL(positionChanged(qint64)), SLOT(updateSlider(qint64)));
+ connect(this->gui->getVideoPlayer(), SIGNAL(stateChanged(QtAV::AVPlayer::State)), SLOT(manageGraph(QtAV::AVPlayer::State)));
+ connect(this->gui->getVideoPlayer(), SIGNAL(error(QtAV::AVError)), this, SLOT(error(QtAV::AVError)));
+ this->multimediaManager->attachManagerObserver(this);
+}
+
+DASHPlayer::~DASHPlayer()
+{
+ this->multimediaManager->stop();
+ delete(this->multimediaManager);
+ DeleteCriticalSection(&this->monitorMutex);
+}
+
+void DASHPlayer::onStartButtonPressed(int period, int videoAdaptationSet, int videoRepresentation, int audioAdaptationSet, int audioRepresentation, int adaptationLogic)
+{
+ bool setOk = false;
+ setOk = this->multimediaManager->setVideoAdaptationLogic((LogicType)adaptationLogic, parametersAdaptation);
+
+ if(!setOk)
+ {
+ return;
+ }
+ Debug("DASH PLAYER: STARTING VIDEO\n");
+ this->multimediaManager->start(this->icn, 20, 0);
+}
+void DASHPlayer::stopButtonPressed()
+{
+ this->multimediaManager->stop();
+}
+
+void DASHPlayer::onStopButtonPressed()
+{
+ QMetaObject::invokeMethod(this->gui->getRootObject(), "unSetBuffering");
+ this->gui->setPlay(false);
+ this->gui->setStop(true);
+ this->gui->setPause(false);
+ this->gui->getVideoPlayer()->stop();
+ this->stopButtonPressed();
+ this->multimediaManager->setOffset(0);
+ this->gui->resetGraphValues();
+}
+
+void DASHPlayer::onPauseButtonPressed()
+{
+ this->multimediaManager->onPausePressed();
+}
+
+void DASHPlayer::onSettingsChanged(int period, int videoAdaptationSet, int videoRepresentation, int audioAdaptationSet, int audioRepresentation)
+{
+ if(this->multimediaManager->getMPD() == NULL)
+ return;
+
+ if (!this->settingsChanged(period, videoAdaptationSet, videoRepresentation, audioAdaptationSet, audioRepresentation))
+ return;
+
+ IPeriod *currentPeriod = this->multimediaManager->getMPD()->GetPeriods().at(period);
+ std::vector<IAdaptationSet *> videoAdaptationSets = AdaptationSetHelper::getVideoAdaptationSets(currentPeriod);
+ std::vector<IAdaptationSet *> audioAdaptationSets = AdaptationSetHelper::getAudioAdaptationSets(currentPeriod);
+ if (videoAdaptationSet >= 0 && videoRepresentation >= 0)
+ {
+ this->multimediaManager->setVideoQuality(currentPeriod,
+ videoAdaptationSets.at(videoAdaptationSet),
+ videoAdaptationSets.at(videoAdaptationSet)->GetRepresentation().at(videoRepresentation));
+ }
+ else
+ {
+ this->multimediaManager->setVideoQuality(currentPeriod, NULL, NULL);
+ }
+}
+
+void DASHPlayer::onVideoBufferStateChanged(uint32_t fillstateInPercent)
+{
+ emit videoBufferFillStateChanged(fillstateInPercent);
+}
+
+void DASHPlayer::onVideoSegmentBufferStateChanged(uint32_t fillstateInPercent)
+{
+ emit videoSegmentBufferFillStateChanged(fillstateInPercent);
+}
+
+void DASHPlayer::onAudioBufferStateChanged(uint32_t fillstateInPercent)
+{
+ emit audioBufferFillStateChanged(fillstateInPercent);
+}
+
+void DASHPlayer::onAudioSegmentBufferStateChanged(uint32_t fillstateInPercent)
+{
+ emit audioSegmentBufferFillStateChanged(fillstateInPercent);
+}
+
+void DASHPlayer::onEOS()
+{
+ this->onStopButtonPressed();
+}
+
+bool DASHPlayer::onDownloadMPDPressed (const std::string &url)
+{
+ this->multimediaManager->setOffset(0);
+ if(this->icn)
+ {
+ if(!this->multimediaManager->initICN(url))
+ {
+ return false;
+ }
+ }
+ else
+ {
+ if(!this->multimediaManager->init(url))
+ {
+ return false;
+ }
+ }
+ this->setSettings(-1, -1, -1, -1, -1);
+ this->gui->setGuiFields(this->multimediaManager->getMPD());
+ return true;
+}
+
+bool DASHPlayer::settingsChanged (int period, int videoAdaptationSet, int videoRepresentation, int audioAdaptationSet, int audioRepresentation)
+{
+ EnterCriticalSection(&this->monitorMutex);
+ bool settingsChanged = false;
+ if (this->currentSettings.videoRepresentation != videoRepresentation ||
+ this->currentSettings.audioRepresentation != audioRepresentation ||
+ this->currentSettings.videoAdaptationSet != videoAdaptationSet ||
+ this->currentSettings.audioAdaptationSet != audioAdaptationSet ||
+ this->currentSettings.period != period)
+ settingsChanged = true;
+ if (settingsChanged)
+ this->setSettings(period, videoAdaptationSet, videoRepresentation, audioAdaptationSet, audioRepresentation);
+ LeaveCriticalSection(&this->monitorMutex);
+ return settingsChanged;
+}
+
+void DASHPlayer::setSettings(int period, int videoAdaptationSet, int videoRepresentation, int audioAdaptationSet, int audioRepresentation)
+{
+ this->currentSettings.period = period;
+ this->currentSettings.videoAdaptationSet = videoAdaptationSet;
+ this->currentSettings.videoRepresentation = videoRepresentation;
+ this->currentSettings.audioAdaptationSet = audioAdaptationSet;
+ this->currentSettings.audioRepresentation = audioRepresentation;
+}
+
+bool DASHPlayer::downloadMPD(const QString &url, const QString &adaptationLogic, bool icn)
+{
+
+ if (this->gui->getStop())
+ {
+ QMetaObject::invokeMethod(this->gui->getRootObject(), "stopGraph");
+ this->gui->setStop(false);
+ this->gui->setPause(false);
+ this->gui->setPlay(true);
+ this->offset = 0;
+ this->multimediaManager->setOffset(0);
+ this->gui->setOffset(0);
+ this->gui->setPlay(true);
+ this->gui->initVideoPlayer();
+ this->icn = icn;
+ this->segment = 0;
+ std::string mUrl;
+ if(this->icn)
+ {
+ mUrl = this->icnPrefix + url.toStdString() + this->icnSuffix;
+ }
+ else
+ {
+ mUrl = this->httpPrefix + url.toStdString() + this->httpSuffix;
+ }
+ if (!this->onDownloadMPDPressed(mUrl))
+ return false;
+ IPeriod *period = this->multimediaManager->getMPD()->GetPeriods().at(0);
+ IAdaptationSet *adaptation = period->GetAdaptationSets().at(0);
+ IRepresentation *representation = adaptation->GetRepresentation().at(0);
+ uint32_t duration = representation->GetSegmentList()->GetDuration();
+ uint32_t timescale = representation->GetSegmentList()->GetTimescale();
+ this->gui->setListSegmentSize(representation->GetSegmentList()->GetSegmentURLs().size());
+ this->segmentDuration = 1.0*duration/(1.0*timescale) * 1000;
+ this->gui->setSegmentDuration(this->segmentDuration);
+ this->parametersAdaptation->segmentDuration = this->segmentDuration;
+ this->parametersAdaptation->segmentDuration = 1.0*duration/(1.0*timescale) * 1000;
+ this->onSettingsChanged(0,0,0,0,0);
+ int j =0;
+ std::string temp = adaptationLogic.toStdString();
+ temp.erase(std::remove(temp.begin(), temp.end(), ' '), temp.end());
+ int adaptationLogicID = (LogicType)1; //Always Lowest by default
+ for(j = 0; j < LogicType::Count; j++)
+ {
+ if(!strcmp(LogicType_string[j],temp.c_str()))
+ {
+ adaptationLogicID = (LogicType)j;
+ break;
+ }
+ }
+ if(j == LogicType::Count)
+ {
+ std::cout << "Could not find the ID of the adaptation logic asked, using " << LogicType_string[adaptationLogicID] << " instead.\n" << std::endl;
+ }
+ this->onStartButtonPressed(0,0,0,0,0, adaptationLogicID );
+ this->multimediaManager->setLooping(this->repeat);
+ this->adaptationLogic = adaptationLogicID;
+ } else {
+ if (this->gui->getPause())
+ {
+ this->gui->setPlay(true);
+ this->gui->setPause(false);
+ this->gui->getVideoPlayer()->play();
+ this->gui->getVideoPlayer()->pause(false);
+ }
+ }
+ return true;
+}
+
+void DASHPlayer::play()
+{
+ this->offset = 0;
+ this->gui->initVideoPlayer();
+ this->multimediaManager->setOffset(0);
+ this->onSettingsChanged(0,0,0,0,0);
+ this->onStartButtonPressed(0,0,0,0,0, this->adaptationLogic);
+}
+
+void DASHPlayer::repeatVideo(bool repeat)
+{
+ this->repeat = repeat;
+ this->multimediaManager->setLooping(repeat);
+ this->gui->setRepeat(repeat);
+}
+
+void DASHPlayer::seekVideo(float value) {
+ this->multimediaManager->stop();
+ this->seek = true;
+ this->gui->initVideoPlayer();
+ this->segment = value*this->gui->getDurationMilliseconds()/this->segmentDuration;
+ this->offset = this->segment * this->segmentDuration;
+ this->gui->seekSegment(this->segment);
+ this->multimediaManager->setOffset(this->offset);
+ if (!(this->multimediaManager->setVideoAdaptationLogic((LogicType)this->adaptationLogic, this->parametersAdaptation)))
+ {
+ return;
+ }
+ this->multimediaManager->start(this->icn, 20, this->segment);
+ this->multimediaManager->setLooping(this->repeat);
+
+}
+
+void DASHPlayer::notifyQualityDownloading(uint32_t quality)
+{
+ this->qualityDownloading = quality/1000000;
+}
+
+//WARNING FPS IS USED AS BUFFERLVL
+void DASHPlayer::notifyStatistics(int segNum, uint32_t bitrate, int fps, uint32_t quality)
+{
+ if(quality == 240)
+ this->mStats[segNum] = std::make_tuple(bitrate, fps, 1);
+ else if(quality == 360)
+ this->mStats[segNum] = std::make_tuple(bitrate, fps, 3);
+ else if(quality == 720)
+ this->mStats[segNum] = std::make_tuple(bitrate, fps, 5);
+ else if(quality == 1080)
+ this->mStats[segNum] = std::make_tuple(bitrate, fps, 7);
+ else if(quality == 1440)
+ this->mStats[segNum] = std::make_tuple(bitrate, fps, 9);
+ else
+ this->mStats[segNum] = std::make_tuple(bitrate, fps, 11);
+}
+
+void DASHPlayer::updateSlider(qint64 value)
+{
+ this->position = this->offset + (uint64_t)value;
+ if (this->position <= this->gui->getDurationMilliseconds()){
+ this->segment = (this->offset + value)/this->segmentDuration;
+ this->gui->setAnaliticsValues(std::get<0>(this->mStats[segment])/1000000,
+ std::get<2>(this->mStats[segment]),
+ (uint32_t)this->qualityDownloading,
+ (double)this->multimediaManager->getBufferLevel());
+ this->gui->getProgressBar()->setProperty("value", 1.0*(this->position)/(1.0*this->gui->getDurationMilliseconds()));
+ this->gui->getNowLabel()->setProperty("text", QVariant(msec2string(this->position).c_str()));
+ this->gui->pauseIfBuffering(this->offset + value);
+ }
+}
+
+void DASHPlayer::initSlider()
+{
+ this->offset = 0;
+ this->gui->getProgressBar()->setProperty("value", 0.0);
+ this->gui->getNowLabel()->setProperty("text", QVariant("00:00:00"));
+ this->gui->getLifeLabel()->setProperty("text", QVariant("00:00:00"));
+
+}
+
+std::string DASHPlayer::msec2string(uint64_t milliseconds)
+{
+ uint64_t seconds = milliseconds/1000;
+ int32_t sec = seconds%60;
+ seconds = (seconds - sec)/60;
+ int32_t min = seconds%60;
+ int32_t hours = (seconds - min)/60;
+ char timeStamp[10];
+ sprintf(timeStamp, "%02d:%02d:%02d", hours, min, sec);
+ return std::string(timeStamp);
+}
+
+void DASHPlayer::onStopped()
+{
+ int posPlayer = this->position;
+ if (this->seek)
+ {
+ this->seek = false;
+ }
+ else
+ {
+ if(!this->gui->getStop())
+ {
+ if (posPlayer <= 1000 || posPlayer > this->gui->getDurationMilliseconds() || (this->gui->getDurationMilliseconds()- posPlayer) <= 2000 )
+ {
+ if (this->repeat)
+ {
+ this->gui->getStreamBuffer()->readFromNextBuffer();
+ this->gui->startIfRepeat();
+ this->offset = 0;
+ this->multimediaManager->setOffset(0);
+ }
+ else
+ {
+ this->gui->initVideoPlayer();
+ this->gui->seekSegment(0);
+ this->gui->setStop(true);
+ this->gui->setPlay(false);
+ this->gui->setPause(false);
+ this->multimediaManager->stop();
+ QMetaObject::invokeMethod(this->gui->getRootObject(), "pauseGraph");
+ this->initSlider();
+ QMetaObject::invokeMethod(this->gui->getRootObject(), "setStop");
+ }
+
+ } else {
+ qDebug("wrong position");
+ }
+ }
+ else
+ {
+ this->gui->setStop(true);
+ this->gui->setPlay(false);
+ this->gui->setPause(false);
+ this->gui->initVideoPlayer();
+ this->gui->seekSegment(0);
+ this->multimediaManager->stop();
+ QMetaObject::invokeMethod(this->gui->getRootObject(), "pauseGraph");
+ this->initSlider();
+ }
+ }
+}
+
+void DASHPlayer::pause()
+{
+ this->gui->setPlay(false);
+ this->gui->setPause(true);
+ this->gui->getVideoPlayer()->pause(true);
+}
+
+void DASHPlayer::setConfig (Config *config)
+{
+ this->config = config;
+}
+
+void DASHPlayer::manageGraph(QtAV::AVPlayer::State value)
+{
+ switch (value)
+ {
+ case QtAV::AVPlayer::State::PlayingState:
+ if (config->graph())
+ {
+ QMetaObject::invokeMethod(this->gui->getRootObject(), "startGraph");
+ }
+ break;
+ case QtAV::AVPlayer::State::StoppedState:
+ if (config->graph())
+ {
+ QMetaObject::invokeMethod(this->gui->getRootObject(), "pauseGraph");
+ }
+ break;
+ case QtAV::AVPlayer::State::PausedState:
+ if (config->graph()) {
+ QMetaObject::invokeMethod(this->gui->getRootObject(), "pauseGraph");
+ }
+ break;
+ }
+}
+
+void DASHPlayer::reloadParameters()
+{
+ this->beta = config->beta();
+ this->drop = config->drop();
+ this->icnPrefix = config->icnPrefix().toStdString();
+ this->httpPrefix = config->httpPrefix().toStdString();
+ this->icnSuffix = config->icnSuffix().toStdString();
+ this->httpSuffix = config->httpSuffix().toStdString();
+ this->alpha = config->alpha();
+ this->repeat = config->repeat();
+ this->parametersAdaptation = (struct AdaptationParameters *)malloc(sizeof(struct AdaptationParameters));
+ this->parametersAdaptation->segmentBufferSize = config->segmentBufferSize();
+ this->parametersAdaptation->segmentDuration = 2;
+ this->parametersAdaptation->Rate_Alpha = config->rateAlpha();
+ this->parametersAdaptation->Bola_Alpha = config->bolaAlpha();
+ this->parametersAdaptation->Bola_bufferTargetSeconds = config->bolaBufferTarget();
+ this->parametersAdaptation->BufferBased_reservoirThreshold = config->bufferReservoirThreshold();
+ this->parametersAdaptation->BufferBased_maxThreshold = config->bufferMaxThreshold();
+ this->parametersAdaptation->Adaptech_Alpha = config->adaptechAlpha();
+ this->parametersAdaptation->Adaptech_FirstThreshold = config->adaptechFirstThreshold();
+ this->parametersAdaptation->Adaptech_SecondThreshold = config->adaptechSecondThreshold();
+ this->parametersAdaptation->Adaptech_SwitchUpThreshold = config->adaptechSwitchUpMargin();
+ this->parametersAdaptation->Adaptech_SlackParameter = config->adaptechSlackParameter();
+ this->parametersAdaptation->BufferThreeThreshold_FirstThreshold = config->bufferThreeThresholdFirst();
+ this->parametersAdaptation->BufferThreeThreshold_SecondThreshold = config->bufferThreeThresholdSecond();
+ this->parametersAdaptation->BufferThreeThreshold_ThirdThreshold = config->bufferThreeThresholdThird();
+ this->parametersAdaptation->Panda_Alpha = config->pandaParamAlpha();
+ this->parametersAdaptation->Panda_Beta = config->pandaParamBeta();
+ this->parametersAdaptation->Panda_Bmin = config->pandaParamBMin();
+ this->parametersAdaptation->Panda_K = config->pandaParamK();
+ this->parametersAdaptation->Panda_W = config->pandaParamW();
+ this->parametersAdaptation->Panda_Epsilon = config->pandaParamEpsilon();
+}
+
+QString DASHPlayer::getLastPlayed()
+{
+ return config->lastPlayed();
+}
+
+void DASHPlayer::setLastPlayed(QString lastPlayed)
+{
+ config->setLastPlayed(lastPlayed);
+}
+
+QString DASHPlayer::getAdaptationLogic()
+{
+ return config->adaptationLogic();
+}
+
+void DASHPlayer::setAdaptationLogic(QString adaptationLogic)
+{
+ config->setAdaptationLogic(adaptationLogic);
+}
+
+bool DASHPlayer::getIcn()
+{
+ return config->icn();
+}
+
+void DASHPlayer::setIcn(bool icn)
+{
+ config->setIcn(icn);
+}
+
+QString DASHPlayer::getIcnPrefix()
+{
+ return config->icnPrefix();
+}
+
+void DASHPlayer::setIcnPrefix(QString icnPrefix)
+{
+ config->setIcnPrefix(icnPrefix);
+}
+
+QString DASHPlayer::getHttpPrefix()
+{
+ return config->httpPrefix();
+}
+
+void DASHPlayer::setHttpPrefix(QString httpPrefix)
+{
+ config->setHttpPrefix(httpPrefix);
+}
+
+QString DASHPlayer::getIcnSuffix()
+{
+ return config->icnSuffix();
+}
+
+void DASHPlayer::setIcnSuffix(QString icnSuffix)
+{
+ config->setIcnSuffix(icnSuffix);
+}
+
+QString DASHPlayer::getHttpSuffix()
+{
+ return config->httpSuffix();
+}
+
+void DASHPlayer::setHttpSuffix(QString httpSuffix)
+{
+ config->setHttpSuffix(httpSuffix);
+}
+
+qreal DASHPlayer::getAlpha()
+{
+ return config->alpha();
+}
+
+void DASHPlayer::setAlpha(qreal alpha)
+{
+ config->setAlpha(alpha);
+}
+
+qreal DASHPlayer::getSegmentBufferSize()
+{
+ return config->segmentBufferSize();
+}
+
+void DASHPlayer::setSegmentBufferSize(qreal segmentBufferSize)
+{
+ config->setSegmentBufferSize(segmentBufferSize);
+}
+
+qreal DASHPlayer::getRateAlpha()
+{
+ return config->rateAlpha();
+}
+
+void DASHPlayer::setRateAlpha(qreal rateAlpha)
+{
+ config->setRateAlpha(rateAlpha);
+}
+
+qreal DASHPlayer::getBufferReservoirThreshold()
+{
+ return config->bufferReservoirThreshold();
+}
+
+void DASHPlayer::setBufferReservoirThreshold(qreal bufferReservoirThreshold)
+{
+ config->setBufferReservoirThreshold(bufferReservoirThreshold);
+}
+
+qreal DASHPlayer::getBufferMaxThreshold()
+{
+ return config->bufferMaxThreshold();
+}
+
+void DASHPlayer::setBufferMaxThreshold(qreal bufferMaxThreshold)
+{
+ config->setBufferMaxThreshold(bufferMaxThreshold);
+}
+
+qreal DASHPlayer::getAdaptechFirstThreshold()
+{
+ return config->adaptechFirstThreshold();
+}
+
+void DASHPlayer::setAdaptechFirstThreshold(qreal adaptechFirstThreshold)
+{
+ config->setAdaptechFirstThreshold(adaptechFirstThreshold);
+}
+
+qreal DASHPlayer::getAdaptechSecondThreshold()
+{
+ return config->adaptechSecondThreshold();
+}
+
+void DASHPlayer::setAdaptechSecondThreshold(qreal adaptechSecondThreshold)
+{
+ config->setAdaptechSecondThreshold(adaptechSecondThreshold);
+}
+
+qreal DASHPlayer::getAdaptechSwitchUpMargin()
+{
+ return config->adaptechSwitchUpMargin();
+}
+
+void DASHPlayer::setAdaptechSwitchUpMargin(qreal adaptechSwitchUpMargin)
+{
+ config->setAdaptechSwitchUpMargin(adaptechSwitchUpMargin);
+}
+
+qreal DASHPlayer::getAdaptechSlackParameter()
+{
+ return config->adaptechSlackParameter();
+}
+
+void DASHPlayer::setAdaptechSlackParameter(qreal adaptechSlackParameter)
+{
+ config->setAdaptechSlackParameter(adaptechSlackParameter);
+}
+
+qreal DASHPlayer::getAdaptechAlpha()
+{
+ return config->adaptechAlpha();
+}
+
+void DASHPlayer::setAdaptechAlpha(qreal adaptechAlpha)
+{
+ config->setAdaptechAlpha(adaptechAlpha);
+}
+
+qreal DASHPlayer::getBufferThreeThresholdFirst()
+{
+ return config->bufferThreeThresholdFirst();
+}
+
+void DASHPlayer::setBufferThreeThresholdFirst(qreal bufferThreeThresholdFirst)
+{
+ config->setBufferThreeThresholdFirst(bufferThreeThresholdFirst);
+}
+
+qreal DASHPlayer::getBufferThreeThresholdSecond()
+{
+ return config->bufferThreeThresholdSecond();
+}
+
+void DASHPlayer::setBufferThreeThresholdSecond(qreal bufferThreeThresholdSecond)
+{
+ config->setBufferThreeThresholdSecond(bufferThreeThresholdSecond);
+}
+
+qreal DASHPlayer::getBufferThreeThresholdThird()
+{
+ return config->bufferThreeThresholdThird();
+}
+
+void DASHPlayer::setBufferThreeThresholdThird(qreal bufferThreeThresholdThird)
+{
+ config->setBufferThreeThresholdThird(bufferThreeThresholdThird);
+}
+
+qreal DASHPlayer::getPandaParamAlpha()
+{
+ return config->pandaParamAlpha();
+}
+
+void DASHPlayer::setPandaParamAlpha(qreal pandaParamAlpha)
+{
+ config->setPandaParamAlpha(pandaParamAlpha);
+}
+
+qreal DASHPlayer::getPandaParamBeta()
+{
+ return config->pandaParamBeta();
+}
+
+void DASHPlayer::setPandaParamBeta(qreal pandaParamBeta)
+{
+ config->setPandaParamBeta(pandaParamBeta);
+}
+
+qreal DASHPlayer::getPandaParamBMin()
+{
+ return config->pandaParamBMin();
+}
+
+void DASHPlayer::setPandaParamBMin(qreal pandaParamBMin)
+{
+ config->setPandaParamBMin(pandaParamBMin);
+}
+
+qreal DASHPlayer::getPandaParamK()
+{
+ return config->pandaParamK();
+}
+
+void DASHPlayer::setPandaParamK(qreal pandaParamK)
+{
+ config->setPandaParamK(pandaParamK);
+}
+
+qreal DASHPlayer::getPandaParamW()
+{
+ return config->pandaParamW();
+}
+
+void DASHPlayer::setPandaParamW(qreal pandaParamW)
+{
+ config->setPandaParamW(pandaParamW);
+}
+
+qreal DASHPlayer::getPandaParamEpsilon()
+{
+ return config->pandaParamEpsilon();
+}
+
+void DASHPlayer::setPandaParamEpsilon(qreal pandaParamEpsilon)
+{
+ config->setPandaParamEpsilon(pandaParamEpsilon);
+}
+
+qreal DASHPlayer::getBolaBufferTarget()
+{
+ return config->bolaBufferTarget();
+}
+
+void DASHPlayer::setBolaBufferTarget(qreal bolaBufferTarget)
+{
+ config->setBolaBufferTarget(bolaBufferTarget);
+}
+
+qreal DASHPlayer::getBolaAlpha()
+{
+ return config->bolaAlpha();
+}
+
+void DASHPlayer::setBolaAlpha(qreal bolaAlpha)
+{
+ config->setBolaAlpha(bolaAlpha);
+}
+
+bool DASHPlayer::getRepeat()
+{
+ return config->repeat();
+}
+
+void DASHPlayer::setRepeat(bool repeat)
+{
+ this->repeatVideo(repeat);
+ config->setRepeat(repeat);
+}
+
+bool DASHPlayer::getGraph()
+{
+ return config->graph();
+}
+
+void DASHPlayer::setGraph (bool graph)
+{
+ config->setGraph(graph);
+ if (graph) {
+ if (this->gui->getPlay() && this->gui->getVideoPlayer()->isPlaying()) {
+ QMetaObject::invokeMethod(this->gui->getRootObject(), "startGraph");
+ }
+ } else {
+ QMetaObject::invokeMethod(this->gui->getRootObject(), "stopGraph");
+ }
+}
+
+bool DASHPlayer::getFullScreen()
+{
+ return config->fullScreen();
+}
+
+void DASHPlayer::setFullScreen(bool fullScreen)
+{
+ config->setFullScreen(fullScreen);
+}
+
+bool DASHPlayer::getStop()
+{
+ return this->gui->getStop();
+}
+
+bool DASHPlayer::getAutotune()
+{
+ return config->autotune();
+}
+
+void DASHPlayer::setAutotune(bool autotune)
+{
+ config->setAutotune(autotune);
+}
+
+int DASHPlayer::getLifetime()
+{
+ return config->lifetime();
+}
+
+void DASHPlayer::setLifetime(int lifetime)
+{
+ config->setLifetime(lifetime);
+}
+
+int DASHPlayer::getRetransmissions()
+{
+ return config->retransmissions();
+}
+
+void DASHPlayer::setRetransmissions(int retransmissions)
+{
+ config->setRetransmissions(retransmissions);
+}
+
+qreal DASHPlayer::getBeta()
+{
+ return config->beta();
+}
+
+void DASHPlayer::setBeta(qreal beta)
+{
+ config->setBeta(beta);
+ this->multimediaManager->setBeta(beta);
+}
+
+qreal DASHPlayer::getDrop()
+{
+ return config->drop();
+}
+
+void DASHPlayer::setDrop(qreal drop)
+{
+ config->setDrop(drop);
+ this->multimediaManager->setDrop(drop);
+}
+
+qreal DASHPlayer::getBetaWifi()
+{
+ return config->betaWifi();
+}
+
+void DASHPlayer::setBetaWifi(qreal betaWifi)
+{
+ config->setBetaWifi(betaWifi);
+}
+
+qreal DASHPlayer::getDropWifi()
+{
+ return config->dropWifi();
+}
+
+void DASHPlayer::setDropWifi(qreal dropWifi)
+{
+ config->setDropWifi(dropWifi);
+}
+
+int DASHPlayer::getDelayWifi()
+{
+ return config->delayWifi();
+}
+
+void DASHPlayer::setDelayWifi(int delayWifi)
+{
+ config->setDelayWifi(delayWifi);
+}
+
+qreal DASHPlayer::getBetaLte()
+{
+ return config->betaLte();
+}
+
+void DASHPlayer::setBetaLte(qreal betaLte)
+{
+ config->setBetaLte(betaLte);
+}
+
+qreal DASHPlayer::getDropLte()
+{
+ return config->dropLte();
+}
+
+void DASHPlayer::setDropLte(qreal dropLte)
+{
+ config->setDropLte(dropLte);
+}
+
+int DASHPlayer::getDelayLte()
+{
+ return config->delayLte();
+}
+
+void DASHPlayer::setDelayLte(int delayLte)
+{
+ config->setDelayLte(delayLte);
+}
+
+int DASHPlayer::getBatchingParameter()
+{
+ return config->batchingParameter();
+}
+
+void DASHPlayer::setBatchingParameter(int batchingParameter)
+{
+ config->setBatchingParameter(batchingParameter);
+}
+
+int DASHPlayer::getRateEstimator ()
+{
+ return config->rateEstimator();
+}
+
+void DASHPlayer::setRateEstimator(int rateEstimator)
+{
+ config->setRateEstimator(rateEstimator);
+}
+
+void DASHPlayer::error(const QtAV::AVError &e)
+{
+ qDebug("error in the player!");
+ seekVideo(0);
+}
+
+
+
diff --git a/UI/DASHPlayer.h b/UI/DASHPlayer.h
new file mode 100644
index 00000000..8913a843
--- /dev/null
+++ b/UI/DASHPlayer.h
@@ -0,0 +1,207 @@
+/*
+ * DASHPlayer.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 DASHPLAYER_H_
+#define DASHPLAYER_H_
+
+#include <iostream>
+#include <sstream>
+#include <qobject.h>
+#include "libdash.h"
+#include "IDASHPlayerGuiObserver.h"
+#include "../Managers/IMultimediaManagerObserver.h"
+#include "../Managers/MultimediaManager.h"
+#include "../Adaptation/IAdaptationLogic.h"
+#include "../Buffer/IBufferObserver.h"
+#include "../MPD/AdaptationSetHelper.h"
+#include "../Common/Config.h"
+#include <QMessageLogger>
+#include <qimage.h>
+#include<map>
+#include<tuple>
+
+namespace viper
+{
+struct settings_t
+{
+ int period;
+ int videoAdaptationSet;
+ int audioAdaptationSet;
+ int videoRepresentation;
+ int audioRepresentation;
+};
+
+class DASHPlayer : public IDASHPlayerGuiObserver, public managers::IMultimediaManagerObserver
+
+{
+ Q_OBJECT
+
+public:
+ DASHPlayer(ViperGui& gui, Config *config);
+ virtual ~DASHPlayer();
+
+ virtual void onSettingsChanged(int period, int videoAdaptationSet, int videoRepresentation, int audioAdaptationSet, int audioRepresentation);
+ virtual void onStartButtonPressed(int period, int videoAdaptationSet, int videoRepresentation, int audioAdaptationSet, int audioRepresentation, int adaptationLogic);
+ virtual void stopButtonPressed();
+ virtual void onPauseButtonPressed();
+ virtual void onVideoBufferStateChanged(uint32_t fillstateInPercent);
+ virtual void onVideoSegmentBufferStateChanged(uint32_t fillstateInPercent);
+ virtual void onAudioBufferStateChanged(uint32_t fillstateInPercent);
+ virtual void onAudioSegmentBufferStateChanged(uint32_t fillstateInPercent);
+ virtual void onEOS();
+ virtual void notifyStatistics(int, uint32_t, int, uint32_t);
+ virtual void notifyQualityDownloading(uint32_t);
+ virtual bool onDownloadMPDPressed(const std::string &url);
+ void setConfig(Config *config);
+ Q_INVOKABLE bool downloadMPD(const QString &url, const QString &adaptationLogic, bool icn);
+ Q_INVOKABLE void pause();
+ Q_INVOKABLE void seekVideo(float value);
+ Q_INVOKABLE void repeatVideo(bool repeat);
+ Q_INVOKABLE void onStopButtonPressed();
+ Q_INVOKABLE void play();
+ Q_INVOKABLE void onStopped();
+ Q_INVOKABLE QString getLastPlayed();
+ Q_INVOKABLE void setLastPlayed(QString lastPlayed);
+ Q_INVOKABLE QString getAdaptationLogic();
+ Q_INVOKABLE void setAdaptationLogic(QString adaptationLogic);
+ Q_INVOKABLE bool getIcn();
+ Q_INVOKABLE void setIcn(bool icn);
+ Q_INVOKABLE QString getIcnPrefix();
+ Q_INVOKABLE void setIcnPrefix(QString icnPrefix);
+ Q_INVOKABLE QString getHttpPrefix();
+ Q_INVOKABLE void setHttpPrefix(QString httpPrefix);
+ Q_INVOKABLE QString getIcnSuffix();
+ Q_INVOKABLE void setIcnSuffix(QString icnSuffix);
+ Q_INVOKABLE QString getHttpSuffix();
+ Q_INVOKABLE void setHttpSuffix(QString httpSuffix);
+ Q_INVOKABLE qreal getAlpha();
+ Q_INVOKABLE void setAlpha(qreal alpha);
+ Q_INVOKABLE qreal getSegmentBufferSize();
+ Q_INVOKABLE void setSegmentBufferSize(qreal segmentBufferSize);
+ Q_INVOKABLE qreal getRateAlpha();
+ Q_INVOKABLE void setRateAlpha(qreal rateAlpha);
+ Q_INVOKABLE qreal getBufferReservoirThreshold();
+ Q_INVOKABLE void setBufferReservoirThreshold(qreal bufferReservoirThreshold);
+ Q_INVOKABLE qreal getBufferMaxThreshold();
+ Q_INVOKABLE void setBufferMaxThreshold(qreal bufferMaxThreshold);
+ Q_INVOKABLE qreal getAdaptechFirstThreshold();
+ Q_INVOKABLE void setAdaptechFirstThreshold(qreal adaptechFirstThreshold);
+ Q_INVOKABLE qreal getAdaptechSecondThreshold();
+ Q_INVOKABLE void setAdaptechSecondThreshold(qreal adaptechSecondThreshold);
+ Q_INVOKABLE qreal getAdaptechSwitchUpMargin();
+ Q_INVOKABLE void setAdaptechSwitchUpMargin(qreal adaptechSwitchUpMargin);
+ Q_INVOKABLE qreal getAdaptechSlackParameter();
+ Q_INVOKABLE void setAdaptechSlackParameter(qreal adaptechSlackParameter);
+ Q_INVOKABLE qreal getAdaptechAlpha();
+ Q_INVOKABLE void setAdaptechAlpha(qreal adaptechAlpha);
+ Q_INVOKABLE qreal getBufferThreeThresholdFirst();
+ Q_INVOKABLE void setBufferThreeThresholdFirst(qreal bufferThreeThresholdFirst);
+ Q_INVOKABLE qreal getBufferThreeThresholdSecond();
+ Q_INVOKABLE void setBufferThreeThresholdSecond(qreal bufferThreeThresholdSecond);
+ Q_INVOKABLE qreal getBufferThreeThresholdThird();
+ Q_INVOKABLE void setBufferThreeThresholdThird(qreal bufferThreeThresholdThird);
+ Q_INVOKABLE qreal getPandaParamAlpha();
+ Q_INVOKABLE void setPandaParamAlpha(qreal pandaParamAlpha);
+ Q_INVOKABLE qreal getPandaParamBeta();
+ Q_INVOKABLE void setPandaParamBeta(qreal pandaParamBeta);
+ Q_INVOKABLE qreal getPandaParamBMin();
+ Q_INVOKABLE void setPandaParamBMin(qreal pandaParamBMin);
+ Q_INVOKABLE qreal getPandaParamK();
+ Q_INVOKABLE void setPandaParamK(qreal pandaParamK);
+ Q_INVOKABLE qreal getPandaParamW();
+ Q_INVOKABLE void setPandaParamW(qreal pandaParamW);
+ Q_INVOKABLE qreal getPandaParamEpsilon();
+ Q_INVOKABLE void setPandaParamEpsilon(qreal pandaParamEpsilon);
+ Q_INVOKABLE qreal getBolaBufferTarget();
+ Q_INVOKABLE void setBolaBufferTarget(qreal bolaBufferTarget);
+ Q_INVOKABLE qreal getBolaAlpha();
+ Q_INVOKABLE void setBolaAlpha(qreal bolaAlpha);
+ Q_INVOKABLE bool getRepeat();
+ Q_INVOKABLE void setRepeat(bool repeat);
+ Q_INVOKABLE bool getGraph();
+ Q_INVOKABLE void setGraph(bool graph);
+ Q_INVOKABLE bool getFullScreen();
+ Q_INVOKABLE void setFullScreen(bool fullScreen);
+ Q_INVOKABLE void reloadParameters();
+ Q_INVOKABLE bool getStop();
+ Q_INVOKABLE void setAutotune(bool autoTune);
+ Q_INVOKABLE bool getAutotune();
+ Q_INVOKABLE void setLifetime(int lifeTime);
+ Q_INVOKABLE int getLifetime();
+ Q_INVOKABLE void setRetransmissions(int retranmsissions);
+ Q_INVOKABLE int getRetransmissions();
+ Q_INVOKABLE void setBeta(qreal beta);
+ Q_INVOKABLE qreal getBeta();
+ Q_INVOKABLE void setDrop(qreal drop);
+ Q_INVOKABLE qreal getDrop();
+ Q_INVOKABLE void setBetaWifi(qreal betaWifi);
+ Q_INVOKABLE qreal getBetaWifi();
+ Q_INVOKABLE void setDropWifi(qreal dropWifi);
+ Q_INVOKABLE qreal getDropWifi();
+ Q_INVOKABLE void setDelayWifi(int delayWifi);
+ Q_INVOKABLE int getDelayWifi();
+ Q_INVOKABLE void setBetaLte(qreal betaLte);
+ Q_INVOKABLE qreal getBetaLte();
+ Q_INVOKABLE void setDropLte(qreal dropLte);
+ Q_INVOKABLE qreal getDropLte();
+ Q_INVOKABLE void setDelayLte(int delayLte);
+ Q_INVOKABLE int getDelayLte();
+ Q_INVOKABLE void setBatchingParameter(int batchingParameter);
+ Q_INVOKABLE int getBatchingParameter();
+ Q_INVOKABLE void setRateEstimator(int rateEstimator);
+ Q_INVOKABLE int getRateEstimator();
+
+private:
+ float gamma;
+ float beta;
+ float drop;
+ bool seek;
+ Config *config;
+ bool repeat;
+ float segmentDuration;
+ uint64_t offset;
+ uint64_t position;
+ int segment;
+ int adaptationLogic;
+ dash::mpd::IMPD *mpd;
+ ViperGui *gui = NULL;
+ viper::managers::MultimediaManager *multimediaManager;
+ settings_t currentSettings;
+ CRITICAL_SECTION monitorMutex;
+ const char *url;
+ bool icn;
+ std::string icnPrefix;
+ std::string httpPrefix;
+ std::string icnSuffix;
+ std::string httpSuffix;
+ double alpha;
+ struct libdash::framework::adaptation::AdaptationParameters *parametersAdaptation;
+ libdash::framework::adaptation::LogicType adaptLogic;
+ std::map<int,std::tuple<uint32_t, int, uint32_t>> mStats;
+ int qualityDownloading;
+ bool settingsChanged(int period, int videoAdaptationSet, int videoRepresentation, int audioAdaptationSet, int audioRepresentation);
+ void setSettings(int period, int videoAdaptationSet, int videoRepresentation, int audioAdaptationSet, int audioRepresentation);
+ std::string msec2string(uint64_t milliseconds);
+ void initSlider();
+
+signals:
+ void videoSegmentBufferFillStateChanged(int fillStateInPercent);
+ void videoBufferFillStateChanged(int fillStateInPercent);
+ void audioSegmentBufferFillStateChanged(int fillStateInPercent);
+ void audioBufferFillStateChanged(int fillStateInPercent);
+
+private Q_SLOTS:
+ void updateSlider(qint64 value);
+ void manageGraph(QtAV::AVPlayer::State state);
+ void error(const QtAV::AVError &e);
+};
+}
+#endif /* DASHPLAYER_H_ */
diff --git a/UI/DASHPlayerNoGUI.cpp b/UI/DASHPlayerNoGUI.cpp
new file mode 100644
index 00000000..729621ef
--- /dev/null
+++ b/UI/DASHPlayerNoGUI.cpp
@@ -0,0 +1,383 @@
+/*
+ * 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 "DASHPlayerNoGUI.h"
+#include <iostream>
+
+using namespace libdash::framework::adaptation;
+using namespace libdash::framework::mpd;
+using namespace libdash::framework::buffer;
+using namespace viper;
+using namespace viper::managers;
+using namespace dash::mpd;
+using namespace std;
+
+DASHPlayerNoGUI::DASHPlayerNoGUI(int argc, char ** argv, pthread_cond_t *mainCond, bool nodecoding) :
+ mainCond (mainCond),
+ running (true),
+ noDecoding (nodecoding)
+{
+ InitializeCriticalSection(&this->monitorMutex);
+
+ this->mpd = NULL;
+ this->url = NULL;
+ this->adaptLogic = LogicType::RateBased;
+ this->isICN = false;
+ this->alpha = -1;
+ this->graphData = NULL;
+ this->parameterAdaptation = (struct libdash::framework::adaptation::AdaptationParameters *)malloc(sizeof(struct libdash::framework::adaptation::AdaptationParameters));
+
+ this->parameterAdaptation->segmentDuration = 2.0;
+ this->parameterAdaptation->segmentBufferSize = 10;
+
+ this->parameterAdaptation->Rate_Alpha = 0.8;
+
+ this->parameterAdaptation->Bola_Alpha = 0.8;
+ this->parameterAdaptation->Bola_bufferTargetSeconds = 8.0;
+
+ this->parameterAdaptation->BufferBased_reservoirThreshold = 25;
+ this->parameterAdaptation->BufferBased_maxThreshold = 75;
+
+ this->parameterAdaptation->Adaptech_Alpha = 0.8;
+ this->parameterAdaptation->Adaptech_FirstThreshold = 25;
+ this->parameterAdaptation->Adaptech_SecondThreshold = 45;
+ this->parameterAdaptation->Adaptech_SwitchUpThreshold = 5;
+ this->parameterAdaptation->Adaptech_SlackParameter = 0.8;
+
+ this->parameterAdaptation->BufferThreeThreshold_FirstThreshold = 25;
+ this->parameterAdaptation->BufferThreeThreshold_SecondThreshold = 50;
+ this->parameterAdaptation->BufferThreeThreshold_ThirdThreshold = 75;
+
+ this->parameterAdaptation->Panda_Alpha = 0.2;
+ this->parameterAdaptation->Panda_Beta = 0.2;
+ this->parameterAdaptation->Panda_Bmin = 44;
+ this->parameterAdaptation->Panda_K = 0.14;
+ this->parameterAdaptation->Panda_W = 300000;
+ this->parameterAdaptation->Panda_Epsilon = 0.15;
+
+ this->repeat = false;
+ this->parseArgs(argc, argv);
+
+ this->multimediaManager = new MultimediaManager(NULL, this->parameterAdaptation->segmentBufferSize, "/tmp/", noDecoding);
+ this->multimediaManager->attachManagerObserver(this);
+
+ if(this->url == NULL)
+ {
+ this->running = false;
+ pthread_cond_broadcast(mainCond);
+ return;
+ }
+ else
+ {
+ if(this->onDownloadMPDPressed(string(this->url).c_str()))
+ {
+ this->graphData = new GraphDataSource(NULL);
+ WebSocketService webSocketService;
+ webSocketService.setGraphDataSource(this->graphData);
+ webSocketService.start();
+ this->onStartButtonPressed(0,0,0,0,0);
+ this->multimediaManager->setLooping(this->repeat);
+ }
+ else
+ {
+ this->running = false;
+ pthread_cond_broadcast(mainCond);
+ }
+ }
+}
+
+DASHPlayerNoGUI::~DASHPlayerNoGUI()
+{
+ this->multimediaManager->stop();
+ delete(this->multimediaManager);
+ if(this->graphData)
+ delete(this->graphData);
+ DeleteCriticalSection(&this->monitorMutex);
+}
+
+void DASHPlayerNoGUI::onStartButtonPressed(int period, int videoAdaptationSet, int videoRepresentation, int audioAdaptationSet, int audioRepresentation)
+{
+ this->onSettingsChanged(period,videoAdaptationSet,videoRepresentation, audioAdaptationSet, audioRepresentation);
+ bool setOk = false;
+
+ switch(adaptLogic)
+ {
+ case RateBased:
+ setOk = this->multimediaManager->setVideoAdaptationLogic((LogicType)adaptLogic, this->parameterAdaptation);
+ break;
+ case BufferBased:
+ setOk = this->multimediaManager->setVideoAdaptationLogic((LogicType)adaptLogic, this->parameterAdaptation);
+ break;
+ case BufferRateBased:
+ setOk = this->multimediaManager->setVideoAdaptationLogic((LogicType)adaptLogic, this->parameterAdaptation);
+ break;
+ case BufferBasedThreeThreshold:
+ setOk = this->multimediaManager->setVideoAdaptationLogic((LogicType)adaptLogic, this->parameterAdaptation);
+ break;
+ case Panda:
+ setOk = this->multimediaManager->setVideoAdaptationLogic((LogicType)adaptLogic, this->parameterAdaptation);
+ break;
+ case Bola:
+ setOk = this->multimediaManager->setVideoAdaptationLogic((LogicType)adaptLogic, this->parameterAdaptation);
+ break;
+ default:
+ setOk = this->multimediaManager->setVideoAdaptationLogic((LogicType)adaptLogic, this->parameterAdaptation);
+ break;
+ }
+
+ if(!setOk)
+ {
+ return;
+ }
+
+ Debug("DASH PLAYER: STARTING VIDEO\n");
+ this->multimediaManager->start(this->isICN, this->alpha, 0);
+}
+
+void DASHPlayerNoGUI::onStopButtonPressed ()
+{
+ this->running = false;
+ pthread_cond_broadcast(mainCond);
+}
+
+bool DASHPlayerNoGUI::isRunning ()
+{
+ return this->running;
+}
+
+void DASHPlayerNoGUI::notifyStatistics(int segNum, uint32_t bitrate, int fps, uint32_t quality)
+{
+}
+
+void DASHPlayerNoGUI::notifyQualityDownloading(uint32_t quality)
+{
+ this->graphData->setAnaliticsValues(quality/1000000, 0, quality/1000000, 0);
+}
+
+void DASHPlayerNoGUI::parseArgs(int argc, char ** argv)
+{
+ if(argc == 1)
+ {
+ helpMessage(argv[0]);
+ return;
+ }
+ else
+ {
+ int i = 0;
+ while(i < argc)
+ {
+ if(!strcmp(argv[i],"-u"))
+ {
+ this->url = argv[i+1];
+ i++;
+ i++;
+ continue;
+ }
+ if(!strcmp(argv[i],"-n"))
+ {
+ this->isICN = true;
+ this->alpha = -1;
+ i++;
+ continue;
+ }
+ if(!strcmp(argv[i],"-loop"))
+ {
+ this->repeat = true;
+ i++;
+ continue;
+ }
+ if(!strcmp(argv[i],"-nr"))
+ {
+ this->isICN = true;
+ this->alpha = atof(argv[i+1]);
+ i++;
+ i++;
+ continue;
+ }
+ if(!strcmp(argv[i], "-b"))
+ {
+ this->adaptLogic = LogicType::BufferBased;
+ this->parameterAdaptation->BufferBased_reservoirThreshold = atoi(argv[i+1]);
+ this->parameterAdaptation->BufferBased_maxThreshold = atoi(argv[i+2]);
+ i = i + 3;
+ continue;
+ }
+ if(!strcmp(argv[i], "-br"))
+ {
+ this->adaptLogic = LogicType::BufferRateBased;
+ this->parameterAdaptation->Adaptech_Alpha = atof(argv[i+1]);
+ this->parameterAdaptation->Adaptech_FirstThreshold = atoi(argv[i+2]);
+ this->parameterAdaptation->Adaptech_SecondThreshold = atoi(argv[i+3]);
+ this->parameterAdaptation->Adaptech_SwitchUpThreshold = atoi(argv[i+4]);
+ i = i + 4;
+ continue;
+ }
+ if(!strcmp(argv[i], "-bola"))
+ {
+ this->adaptLogic = LogicType::Bola;
+ this->parameterAdaptation->Bola_Alpha = atof(argv[i+1]);
+ this->parameterAdaptation->Bola_bufferTargetSeconds = atoi(argv[i+2]);
+ i = i + 2;
+ continue;
+ }
+ if(!strcmp(argv[i], "-bt"))
+ {
+ this->adaptLogic = LogicType::BufferBasedThreeThreshold;
+ this->parameterAdaptation->BufferThreeThreshold_FirstThreshold = atoi(argv[i+1]);
+ this->parameterAdaptation->BufferThreeThreshold_SecondThreshold = atoi(argv[i+2]);
+ this->parameterAdaptation->BufferThreeThreshold_ThirdThreshold = atoi(argv[i+3]);
+ i = i + 3;
+ continue;
+ }
+ if(!strcmp(argv[i], "-r"))
+ {
+ this->adaptLogic = LogicType::RateBased;
+ this->parameterAdaptation->Rate_Alpha = atof(argv[i+1]);
+ i = i + 2;
+ continue;
+ }
+ if(!strcmp(argv[i], "-p"))
+ {
+ this->adaptLogic = LogicType::Panda;
+ this->parameterAdaptation->Panda_Alpha = atof(argv[i+1]);
+ i = i + 2;
+ continue;
+ }
+
+ if(!strcmp(argv[i],"-a"))
+ {
+ int j =0;
+ for(j = 0; j < LogicType::Count; j++)
+ {
+ if(!strcmp(LogicType_string[j],argv[i+1]))
+ {
+ this->adaptLogic = (LogicType)j;
+ break;
+ }
+ }
+ if(j == LogicType::Count)
+ {
+ std::cout << "the different adaptation logics implemented are:" << std::endl;
+ for(j = 0;j < LogicType::Count; j++)
+ {
+ std::cout << LogicType_string[j] << std::endl;
+ }
+ std::cout << "By default, the " << LogicType_string[this->adaptLogic] << " logic is selected." << std::endl;
+ }
+ i++;
+ i++;
+ continue;
+ }
+ i++;
+ }
+ }
+}
+
+void DASHPlayerNoGUI::helpMessage(char * name)
+{
+ std::cout << "Usage: " << name << " -u url -a adaptationLogic -n" << std::endl << \
+ "-u:\tThe MPD's url" << std::endl << \
+ "-a:\tThe adaptationLogic:" << std::endl << \
+ "\t*AlwaysLowest" << std::endl << \
+ "\t*RateBased(default)" << std::endl << \
+ "\t*BufferBased" << std::endl << \
+ "-n:\tFlag to use ICN instead of TCP" << std::endl << \
+ "-nr alpha:\tFlag to use ICN instead of TCP and estimation at packet lvl" << std::endl << \
+ "-b reservoirThreshold maxThreshold (both in %)" << std::endl << \
+ "-br alpha reservoirThreshold maxThreshold" << std::endl << \
+ "-r alpha" << std::endl;
+}
+
+void DASHPlayerNoGUI::onSettingsChanged(int period, int videoAdaptationSet, int videoRepresentation, int audioAdaptationSet, int audioRepresentation)
+{
+ if(this->multimediaManager->getMPD() == NULL)
+ return; // TODO dialog or symbol that indicates that error
+
+ if (!this->settingsChanged(period, videoAdaptationSet, videoRepresentation, audioAdaptationSet, audioRepresentation))
+ return;
+
+ IPeriod *currentPeriod = this->multimediaManager->getMPD()->GetPeriods().at(period);
+ std::vector<IAdaptationSet *> videoAdaptationSets = AdaptationSetHelper::getVideoAdaptationSets(currentPeriod);
+ std::vector<IAdaptationSet *> audioAdaptationSets = AdaptationSetHelper::getAudioAdaptationSets(currentPeriod);
+
+ if (videoAdaptationSet >= 0 && videoRepresentation >= 0 && !videoAdaptationSets.empty())
+ {
+ this->multimediaManager->setVideoQuality(currentPeriod,
+ videoAdaptationSets.at(videoAdaptationSet),
+ videoAdaptationSets.at(videoAdaptationSet)->GetRepresentation().at(videoRepresentation));
+ }
+ else
+ {
+ this->multimediaManager->setVideoQuality(currentPeriod, NULL, NULL);
+ }
+
+ if (audioAdaptationSet >= 0 && audioRepresentation >= 0 && !audioAdaptationSets.empty())
+ {
+ this->multimediaManager->setAudioQuality(currentPeriod,
+ audioAdaptationSets.at(audioAdaptationSet),
+ audioAdaptationSets.at(audioAdaptationSet)->GetRepresentation().at(audioRepresentation));
+ }
+ else
+ {
+ this->multimediaManager->setAudioQuality(currentPeriod, NULL, NULL);
+ }
+}
+
+void DASHPlayerNoGUI::onEOS()
+{
+ this->onStopButtonPressed();
+}
+
+bool DASHPlayerNoGUI::onDownloadMPDPressed(const std::string &url)
+{
+ if(this->isICN)
+ {
+ if(!this->multimediaManager->initICN(url))
+ {
+ std::cout << "Problem parsing the mpd. ICN is enabled." << std::endl;
+ return false;
+ }
+ }
+ else
+ {
+ if(!this->multimediaManager->init(url))
+ {
+ std::cout << "Problem parsing the mpd. ICN is disabled." << std::endl;
+ return false;
+ }
+ }
+ return true;
+}
+
+bool DASHPlayerNoGUI::settingsChanged(int period, int videoAdaptationSet, int videoRepresentation, int audioAdaptationSet, int audioRepresentation)
+{
+ return true;
+}
+
+void DASHPlayerNoGUI::onVideoBufferStateChanged(uint32_t fillstateInPercent)
+{
+}
+
+void DASHPlayerNoGUI::onVideoSegmentBufferStateChanged(uint32_t fillstateInPercent)
+{
+}
+
+void DASHPlayerNoGUI::onAudioBufferStateChanged(uint32_t fillstateInPercent)
+{
+}
+
+void DASHPlayerNoGUI::onAudioSegmentBufferStateChanged(uint32_t fillstateInPercent)
+{
+}
diff --git a/UI/DASHPlayerNoGUI.h b/UI/DASHPlayerNoGUI.h
new file mode 100644
index 00000000..58ba52c4
--- /dev/null
+++ b/UI/DASHPlayerNoGUI.h
@@ -0,0 +1,93 @@
+/*
+ * 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 DASHPLAYERNOGUI_H_
+#define DASHPLAYERNOGUI_H_
+
+#include <iostream>
+#include <sstream>
+#include "libdash.h"
+#include "DASHPlayer.h"
+#include "IDASHPlayerNoGuiObserver.h"
+#include "../Managers/IMultimediaManagerObserver.h"
+#include "../Managers/MultimediaManager.h"
+#include "../Adaptation/IAdaptationLogic.h"
+#include "../Buffer/IBufferObserver.h"
+#include "../MPD/AdaptationSetHelper.h"
+#include "UI/GraphDataSource.h"
+#include "Websocket/WebSocketService.h"
+
+namespace viper
+{
+class DASHPlayerNoGUI : public IDASHPlayerNoGuiObserver, public managers::IMultimediaManagerObserver
+{
+public:
+ DASHPlayerNoGUI (int argc, char** argv, pthread_cond_t *mainCond, bool nodecoding);
+ virtual ~DASHPlayerNoGUI ();
+ void parseArgs(int argc, char ** argv);
+ void helpMessage(char *name);
+ virtual void onStartButtonPressed(int period, int videoAdaptationSet, int videoRepresentation, int audioAdaptationSet, int audioRepresentation);
+ virtual void onStopButtonPressed();
+ virtual void onSettingsChanged(int period, int videoAdaptationSet, int videoRepresentation, int audioAdaptationSet, int audioRepresentation);
+ /* IMultimediaManagerObserver */
+ virtual void onVideoBufferStateChanged(uint32_t fillstateInPercent);
+ virtual void onVideoSegmentBufferStateChanged(uint32_t fillstateInPercent);
+ virtual void onAudioBufferStateChanged(uint32_t fillstateInPercent);
+ virtual void onAudioSegmentBufferStateChanged(uint32_t fillstateInPercent);
+ virtual void onEOS();
+ virtual void notifyStatistics(int, uint32_t, int, uint32_t);
+ virtual void notifyQualityDownloading(uint32_t);
+ virtual bool onDownloadMPDPressed(const std::string &url);
+ bool isRunning();
+
+private:
+ dash::mpd::IMPD *mpd;
+ viper::managers::MultimediaManager *multimediaManager;
+ CRITICAL_SECTION monitorMutex;
+ char *url;
+ bool isICN;
+ libdash::framework::adaptation::LogicType adaptLogic;
+ pthread_cond_t *mainCond;
+ bool running;
+ struct libdash::framework::adaptation::AdaptationParameters *parameterAdaptation;
+ float segmentDuration;
+ int segmentBufferSize;
+ double alpha;
+ double rateAlpha;
+ double bolaAlpha;
+ double bolaBufferTargetSeconds;
+ int bufferBasedReservoirThreshold;
+ int bufferBasedMaxThreshold;
+ double adaptechAlpha;
+ int adaptechFirstThreshold;
+ int adaptechSecondThreshold;
+ int adaptechSwitchUpThreshold;
+ int bufferThreeThreshold_FirstThreshold;
+ int bufferThreeThreshold_SecondThreshold;
+ int bufferThreeThreshold_ThirdThreshold;
+ double pandaAlpha;
+ double pandaParam_Beta;
+ double pandaParam_Bmin;
+ double pandaParam_K;
+ double pandaParam_W;
+ double pandaParamEpsilon;
+ bool repeat;
+ GraphDataSource *graphData;
+ bool noDecoding;
+ bool settingsChanged(int period, int videoAdaptationSet, int videoRepresentation, int audioAdaptationSet, int audioRepresentation);
+
+};
+}
+#endif /* DASHPLAYER_H_ */
diff --git a/UI/GraphDataSource.cpp b/UI/GraphDataSource.cpp
new file mode 100644
index 00000000..b35b1869
--- /dev/null
+++ b/UI/GraphDataSource.cpp
@@ -0,0 +1,146 @@
+/*
+ * 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 "GraphDataSource.h"
+#include <QtCharts/QXYSeries>
+#include <QtCharts/QAreaSeries>
+#include <QtQuick/QQuickView>
+#include <QtQuick/QQuickItem>
+#include <QtCore/QDebug>
+#include <QtCore/QtMath>
+#include <QtCore/QDateTime>
+
+QT_CHARTS_USE_NAMESPACE
+
+Q_DECLARE_METATYPE(QAbstractSeries *)
+Q_DECLARE_METATYPE(QAbstractAxis *)
+
+GraphDataSource::GraphDataSource(QQuickView *appViewer, QObject *parent) :
+ QObject(parent),
+ m_appViewer(appViewer)
+{
+ qRegisterMetaType<QAbstractSeries*>();
+ qRegisterMetaType<QAbstractAxis*>();
+ index = 0;
+ this->bitRate = -1;
+ this->fps = -1;
+ this->quality = -1;
+ this->bufferLevel = -1;
+}
+
+void GraphDataSource::update(QAbstractSeries *bitRateSeries, QAbstractSeries *qualitySeries)
+{
+ QXYSeries *xyBitRateSeries = static_cast<QXYSeries *>(bitRateSeries);
+ QXYSeries *xyQualitySeries = static_cast<QXYSeries *>(qualitySeries);
+ if (bitRatePoints.size() == 1000)
+ bitRatePoints.remove(0);
+ if (qualityPoints.size() == 1000)
+ qualityPoints.remove(0);
+
+ if(bitRate != -1)
+ {
+ bitRatePoints.append(QPointF(this->index, bitRate));
+ xyBitRateSeries->replace(bitRatePoints);
+ }
+
+ if(quality != -1)
+ {
+ qualityPoints.append(QPointF(this->index, quality));
+ xyQualitySeries->replace(qualityPoints);
+ }
+ this->index++;
+}
+
+void GraphDataSource::update(QAbstractSeries *bitRateSeries, QAbstractSeries *qualitySeries, QAbstractSeries *bufferLevelSeries)
+{
+ QXYSeries *xyBitRateSeries = static_cast<QXYSeries *>(bitRateSeries);
+ QXYSeries *xyBufferLevelSeries = static_cast<QXYSeries *>(bufferLevelSeries);
+ QXYSeries *xyQualitySeries = static_cast<QXYSeries *>(qualitySeries);
+ if (bitRatePoints.size() == 1000)
+ bitRatePoints.remove(0);
+ if (bufferLevelPoints.size() == 1000)
+ bufferLevelPoints.remove(0);
+ if (qualityPoints.size() == 1000)
+ qualityPoints.remove(0);
+ if(bitRate != -1)
+ {
+ bitRatePoints.append(QPointF(this->index, bitRate));
+ xyBitRateSeries->replace(bitRatePoints);
+ }
+ if(bufferLevel != -1)
+ {
+ bufferLevelPoints.append(QPointF(this->index, bufferLevel));
+ xyBufferLevelSeries->replace(bufferLevelPoints);
+ }
+ if(quality != -1)
+ {
+ qualityPoints.append(QPointF(this->index, quality));
+ xyQualitySeries->replace(qualityPoints);
+ }
+
+ this->index++;
+
+}
+
+void GraphDataSource::clearData()
+{
+ bitRatePoints.clear();
+ fpsPoints.clear();
+ qualityPoints.clear();
+ bufferLevelPoints.clear();
+
+ this->index = 0;
+ this->bitRate = -1;
+ this->fps = -1;
+ this->quality = -1;
+ this->bufferLevel = -1;
+}
+
+void GraphDataSource::setAnaliticsValues(uint32_t bitrate, int fps, uint32_t quality, double bufferLevel)
+{
+ this->bitRate = quality;
+ this->fps = bufferLevel;
+ this->quality = bitrate;
+ this->bufferLevel = bufferLevel;
+}
+
+uint32_t GraphDataSource::getBitRate()
+{
+ return this->bitRate;
+}
+
+int GraphDataSource::getFps()
+{
+ return this->fps;
+}
+
+uint32_t GraphDataSource::getQuality()
+{
+ return this->bitRate;
+}
+
+double GraphDataSource::getBufferLevel()
+{
+ return this->bufferLevel;
+}
+
+void GraphDataSource::resetGraphValues()
+{
+ this->bitRate = -1;
+ this->fps = -1;
+ this->quality = -1;
+ this->bufferLevel = -1;
+}
+
diff --git a/UI/GraphDataSource.h b/UI/GraphDataSource.h
new file mode 100644
index 00000000..d46a5730
--- /dev/null
+++ b/UI/GraphDataSource.h
@@ -0,0 +1,62 @@
+/*
+ * 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 GRAPHDATASOURCE_H
+#define GRAPHDATASOURCE_H
+
+#include <QtCore/QObject>
+#include <QtCharts/QAbstractSeries>
+
+QT_BEGIN_NAMESPACE
+class QQuickView;
+QT_END_NAMESPACE
+
+QT_CHARTS_USE_NAMESPACE
+
+class GraphDataSource : public QObject
+{
+ Q_OBJECT
+public:
+ explicit GraphDataSource(QQuickView *appViewer, QObject *parent = 0);
+ void setAnaliticsValues(uint32_t bitRate, int fps, uint32_t quality, double bufferLevel);
+ uint32_t getBitRate();
+ int getFps();
+ double getBufferLevel();
+ uint32_t getQuality();
+
+
+Q_SIGNALS:
+
+public slots:
+ void clearData();
+ void update(QAbstractSeries *bitRateSeries,QAbstractSeries *qualitySeries, QAbstractSeries *bufferLevelSeries);
+ void update(QAbstractSeries *bitRateSeries, QAbstractSeries *qualitySeries);
+ void resetGraphValues();
+
+private:
+ QQuickView *m_appViewer;
+ QVector<QPointF> bitRatePoints;
+ QVector<QPointF> fpsPoints;
+ QVector<QPointF> qualityPoints;
+ QVector<QPointF> bufferLevelPoints;
+ long int index;
+ long int bitRate;
+ int fps;
+ int quality;
+ double bufferLevel;
+
+};
+
+#endif // GRAPHDATASOURCE_H
diff --git a/UI/IDASHPlayerGuiObserver.h b/UI/IDASHPlayerGuiObserver.h
new file mode 100644
index 00000000..30d5022a
--- /dev/null
+++ b/UI/IDASHPlayerGuiObserver.h
@@ -0,0 +1,35 @@
+/*
+ * IDASHPlayerGuiObserver.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 IDASHPLAYERGUIOBSERVER_H_
+#define IDASHPLAYERGUIOBSERVER_H_
+
+#include <string>
+#include <qobject.h>
+#include "ViperGui.h"
+
+namespace viper
+{
+class IDASHPlayerGuiObserver : public QObject
+{
+ Q_OBJECT
+
+public:
+ virtual ~IDASHPlayerGuiObserver() {}
+ virtual void onSettingsChanged(int period, int videoAdaptationSet, int videoRepresentation, int audioAdaptationSet, int audioRepresentation) = 0;
+ virtual void onStartButtonPressed(int period, int videoAdaptationSet, int videoRepresentation, int audioAdaptationSet, int audioRepresentation, int adaptationLogic) = 0;
+ virtual void onStopButtonPressed() = 0;
+ virtual bool onDownloadMPDPressed(const std::string &url) = 0;
+ virtual void onPauseButtonPressed() = 0;
+
+};
+}
+#endif /* IDASHPLAYERGUIOBSERVER_H_ */
diff --git a/UI/IDASHPlayerNoGuiObserver.h b/UI/IDASHPlayerNoGuiObserver.h
new file mode 100644
index 00000000..6d3a870d
--- /dev/null
+++ b/UI/IDASHPlayerNoGuiObserver.h
@@ -0,0 +1,29 @@
+/*
+ * IDASHPlayerNoGuiObserver.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 IDASHPLAYERNOGUIOBSERVER_H_
+#define IDASHPLAYERNOGUIOBSERVER_H_
+
+#include <string>
+
+namespace viper
+{
+class IDASHPlayerNoGuiObserver
+{
+public:
+ virtual ~IDASHPlayerNoGuiObserver() {}
+ virtual void onSettingsChanged(int period, int videoAdaptationSet, int videoRepresentation, int audioAdaptationSet, int audioRepresentation) = 0;
+ virtual void onStartButtonPressed(int period, int videoAdaptationSet, int videoRepresentation, int audioAdaptationSet, int audioRepresentation) = 0;
+ virtual void onStopButtonPressed() = 0;
+ virtual bool onDownloadMPDPressed(const std::string &url) = 0;
+};
+}
+#endif /* IDASHPLAYERNOGUIOBSERVER_H_ */
diff --git a/UI/ViperGui.cpp b/UI/ViperGui.cpp
new file mode 100644
index 00000000..11ba2e8e
--- /dev/null
+++ b/UI/ViperGui.cpp
@@ -0,0 +1,414 @@
+/*
+ * 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 <QtWidgets>
+#include <vector>
+#include <sstream>
+#include "ViperGui.h"
+#include "IDASHPlayerGuiObserver.h"
+#include "libdash.h"
+#include <iostream>
+#include <sstream>
+#include <QQmlEngine>
+#include <QQmlComponent>
+
+using namespace viper;
+using namespace dash::mpd;
+using namespace libdash::framework::mpd;
+
+ViperGui::ViperGui(QObject *parent) :
+ QObject (parent),
+ mpd (NULL)
+{
+ this->segment = 0;
+ this->bufferDuration = 0;
+ this->play = false;
+ this->pause = false;
+ this->stop = true;
+ this->offset = 0;
+ this->position = 0;
+ this->videoPlayer = qvariant_cast<QtAV::AVPlayer *>(parent->property("mediaObject"));
+ this->streamBuffer = new ViperBuffer();
+ pthread_mutex_init(&(this->monitorMutex), NULL);
+ if (streamBuffer->open(QIODevice::ReadWrite)) {
+ this->videoPlayer->setIODevice(streamBuffer);
+ }
+}
+
+ViperGui::~ViperGui()
+{
+ this->videoPlayer->stop();
+ pthread_mutex_destroy(&(this->monitorMutex));
+}
+
+void ViperGui::setGuiFields(dash::mpd::IMPD* mpd)
+{
+ this->setPeriodComboBox(mpd);
+ if (mpd->GetPeriods().size() > 0)
+ {
+ IPeriod *period = mpd->GetPeriods().at(0);
+ this->setVideoAdaptationSetComboBox(period);
+ if (!AdaptationSetHelper::getVideoAdaptationSets(period).empty())
+ {
+ IAdaptationSet *adaptationSet = AdaptationSetHelper::getVideoAdaptationSets(period).at(0);
+ this->setRepresentationComoboBox(adaptationSet);
+ }
+ if (!AdaptationSetHelper::getAudioAdaptationSets(period).empty())
+ {
+ IAdaptationSet *adaptationSet = AdaptationSetHelper::getAudioAdaptationSets(period).at(0);
+ this->setRepresentationComoboBox(adaptationSet);
+ }
+ }
+ parse8601(mpd->GetMediaPresentationDuration());
+ this->mpd = mpd;
+ this->lifeLabel->setProperty("text", QVariant(this->durationString.c_str()));
+}
+
+void ViperGui::parse8601(std::string durationISO8601)
+{
+ int hours, min, sec, millisec;
+ sscanf(durationISO8601.c_str(), "PT%dH%dM%d.%dS", &hours, &min, &sec, &millisec);
+ this->durationMilliseconds = millisec + 1000*( + sec + 60 *(min + hours * 60));
+ char timeStamp[10];
+ sprintf(timeStamp, "%02d:%02d:%02d", hours, min, sec);
+ this->durationString.assign(timeStamp);
+}
+
+void ViperGui::setRepresentationComoboBox(dash::mpd::IAdaptationSet *adaptationSet)
+{
+ std::vector<IRepresentation *> represenations = adaptationSet->GetRepresentation();
+ for(size_t i = 0; i < represenations.size(); i++)
+ {
+ IRepresentation *representation = represenations.at(i);
+ }
+}
+void ViperGui::setAdaptationSetComboBox(dash::mpd::IPeriod *period)
+{
+ std::vector<IAdaptationSet *> adaptationSets = period->GetAdaptationSets();
+ for(size_t i = 0; i < adaptationSets.size(); i++)
+ {
+ IAdaptationSet *adaptationSet = adaptationSets.at(i);
+ }
+}
+
+void ViperGui::setAudioAdaptationSetComboBox(dash::mpd::IPeriod *period)
+{
+ std::vector<IAdaptationSet *> adaptationSets = AdaptationSetHelper::getAudioAdaptationSets(period);
+ for(size_t i = 0; i < adaptationSets.size(); i++)
+ {
+ IAdaptationSet *adaptationSet = adaptationSets.at(i);
+ }
+}
+
+void ViperGui::setVideoAdaptationSetComboBox(dash::mpd::IPeriod *period)
+{
+ std::vector<IAdaptationSet *> adaptationSets = AdaptationSetHelper::getVideoAdaptationSets(period);
+ for(size_t i = 0; i < adaptationSets.size(); i++)
+ {
+ IAdaptationSet *adaptationSet = adaptationSets.at(i);
+ }
+}
+void ViperGui::setPeriodComboBox(dash::mpd::IMPD *mpd)
+{
+ std::vector<IPeriod *> periods = mpd->GetPeriods();
+ for(size_t i = 0; i < periods.size(); i++)
+ {
+ IPeriod *period = periods.at(i);
+ }
+}
+
+ViperBuffer* ViperGui::getStreamBuffer()
+{
+ return this->streamBuffer;
+}
+
+
+QtAV::AVPlayer* ViperGui::getVideoPlayer()
+{
+ return this->videoPlayer;
+}
+
+void ViperGui::setOffset(int offset)
+{
+ this->offset = offset;
+}
+
+void ViperGui::setPosition(qint64 position)
+{
+ pthread_mutex_lock(&(this->monitorMutex));
+ this->position = position;
+ pthread_mutex_unlock(&(this->monitorMutex));
+
+}
+
+void ViperGui::setLifeLabel(QObject *lifeLabel)
+{
+ this->lifeLabel = lifeLabel;
+}
+
+
+QObject* ViperGui::getLifeLabel()
+{
+ return this->lifeLabel;
+}
+
+void ViperGui::setNowLabel(QObject *nowLabel)
+{
+ this->nowLabel = nowLabel;
+}
+
+QObject* ViperGui::getNowLabel(){
+ return this->nowLabel;
+}
+
+void ViperGui::setPlayButton(QObject *playButton)
+{
+ this->playButton = playButton;
+}
+
+void ViperGui::setProgressBar(QObject *progressBar)
+{
+ this->progressBar = progressBar;
+}
+
+QObject* ViperGui::getProgressBar()
+{
+ return this->progressBar;
+}
+
+void ViperGui::initSlider()
+{
+ this->offset = 0;
+ this->progressBar->setProperty("value", 0.0);
+ this->nowLabel->setProperty("text", QVariant("00:00:00"));
+ this->lifeLabel->setProperty("text", this->lifeLabel->property("text"));
+
+}
+
+
+void ViperGui::seekSegment(int segment)
+{
+ pthread_mutex_lock(&(this->monitorMutex));
+ this->segment = segment;
+ this->offset = this->segment * this->segmentDuration;
+ this->position = this->offset;
+ this->bufferDuration = this->segment * this->segmentDuration;
+ pthread_mutex_unlock(&(this->monitorMutex));
+}
+
+uint64_t ViperGui::getDurationMilliseconds()
+{
+ return this->durationMilliseconds;
+}
+
+void ViperGui::initVideoPlayer()
+{
+ this->videoPlayer->stop();
+ this->streamBuffer->clear();
+}
+
+void ViperGui::setVideoStream(managers::MultimediaStream *videoStream)
+{
+ this->videoStream = videoStream;
+}
+
+void ViperGui::clearGraph()
+{
+ this->graphDataSource->clearData();
+}
+
+void ViperGui::setAnaliticsValues(uint32_t bitRate, int fps, uint32_t quality, double bufferSize)
+{
+ this->graphDataSource->setAnaliticsValues(bitRate, fps, quality, bufferSize);
+}
+
+void ViperGui::setGraphDataSource(GraphDataSource *graphDataSource){
+ this->graphDataSource = graphDataSource;
+}
+
+void ViperGui::writeData(libdash::framework::input::MediaObject* media)
+{
+ this->streamBuffer->writeData(media);
+ pthread_mutex_lock(&(this->monitorMutex));
+ this->segment = (this->segment + 1) % this->listSegmentSize;
+ if( this->segment > 0)
+ {
+ this->bufferDuration += this->segmentDuration;
+
+ if(this->bufferDuration - this->position > 3000)
+ {
+ if (this->play == true)
+ {
+ this->videoPlayer->pause(false);
+ this->videoPlayer->play();
+ QMetaObject::invokeMethod(this->rootObject, "unSetBuffering");
+ }
+ }
+ }
+ else
+ {
+ this->bufferDuration += (this->durationMilliseconds - (this->segmentDuration * (this->listSegmentSize - 1)));
+
+ if(this->bufferDuration - this->position >3000)
+ {
+ this->videoPlayer->pause(false);
+ this->videoPlayer->play();
+ QMetaObject::invokeMethod(this->rootObject, "unSetBuffering");
+ }
+ else
+ {
+ if (this->play == true)
+ {
+ this->videoPlayer->pause(false);
+ this->videoPlayer->play();
+ QMetaObject::invokeMethod(this->rootObject, "unSetBuffering");
+ }
+ }
+ this->streamBuffer->writeToNextBuffer();
+ }
+ pthread_mutex_unlock(&(this->monitorMutex));
+
+}
+
+void ViperGui::setListSegmentSize(int listSegmentSize)
+{
+ this->listSegmentSize = listSegmentSize;
+}
+
+void ViperGui::setPlay(bool play)
+{
+ this->play = play;
+}
+
+bool ViperGui::getPlay()
+{
+ return this->play;
+}
+
+void ViperGui::setStop(bool stop)
+{
+ this->stop = stop;
+ this->segment = 0;
+ this->bufferDuration = 0;
+}
+
+bool ViperGui::getStop()
+{
+ return this->stop;
+}
+
+void ViperGui::setPause(bool pause)
+{
+ this->pause = pause;
+}
+
+bool ViperGui::getPause()
+{
+ return this->pause;
+}
+
+void ViperGui::setRepeat(bool repeat)
+{
+ this->repeat = repeat;
+}
+
+void ViperGui::setSegmentDuration(qint64 segmentDuration)
+{
+ this->segmentDuration = segmentDuration;
+}
+
+int64_t ViperGui::getSegmentDuration()
+{
+ return this->segmentDuration;
+}
+
+int64_t ViperGui::getLastSegmentDuration()
+{
+ return this->lastSegmentDuration;
+}
+
+
+int64_t ViperGui::getBufferDuration()
+{
+ int64_t bufferDuration;
+ pthread_mutex_lock(&(this->monitorMutex));
+ bufferDuration = this->bufferDuration - this->position;
+ pthread_mutex_unlock(&(this->monitorMutex));
+ return bufferDuration;
+}
+
+void ViperGui::pauseIfBuffering(qint64 position)
+{
+ pthread_mutex_lock(&(this->monitorMutex));
+ this->position = position;
+ if (this->videoPlayer->isPlaying()) {
+ if (this->segment == 0) {
+ if (this->repeat == true && this->bufferDuration - this->position <= 3000) {
+ this->videoPlayer->pause(true);
+ QMetaObject::invokeMethod(this->rootObject, "setBuffering");
+ }
+ } else
+ {
+ if ((this->bufferDuration - this->position) <= 3000)
+ {
+ this->videoPlayer->pause(true);
+ QMetaObject::invokeMethod(this->rootObject, "setBuffering");
+ }
+ }
+ }
+ pthread_mutex_unlock(&(this->monitorMutex));
+}
+
+void ViperGui::startIfRepeat()
+{
+ if(this->play) {
+ pthread_mutex_lock(&(this->monitorMutex));
+ this->videoPlayer->setStartPosition(0);
+ this->bufferDuration -= this->durationMilliseconds;
+ this->position = 0;
+ this->offset = 0;
+ this->videoPlayer->play();
+ pthread_mutex_unlock(&(this->monitorMutex));
+ }
+}
+
+void ViperGui::setRootObject(QObject *rootObject)
+{
+ this->rootObject = rootObject;
+}
+
+QObject* ViperGui::getRootObject()
+{
+ return this->rootObject;
+}
+
+qint64 ViperGui::getPosition()
+{
+
+ qint64 position;
+ pthread_mutex_lock(&(this->monitorMutex));
+ position = this->position;
+ pthread_mutex_unlock(&(this->monitorMutex));
+ return position;
+}
+
+void ViperGui::resetGraphValues() {
+ this->graphDataSource->resetGraphValues();
+}
+
+
+
+
+
diff --git a/UI/ViperGui.h b/UI/ViperGui.h
new file mode 100644
index 00000000..f4586753
--- /dev/null
+++ b/UI/ViperGui.h
@@ -0,0 +1,128 @@
+/*
+ * 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 VIPER_H
+#define VIPER_H
+
+#include <QtMultimedia/qmediaplayer.h>
+#include <QtMultimediaWidgets/qvideowidget.h>
+#include <QtGui/QMovie>
+#include <QtAV/QtAV.h>
+#include <QByteArray>
+#include "Common/ViperBuffer.h"
+#include <QBuffer>
+#include "libdash.h"
+#include "../MPD/AdaptationSetHelper.h"
+#include "../Common/QtQuick2ApplicationViewer.h"
+#include "../Managers/MultimediaStream.h"
+#include "GraphDataSource.h"
+
+#include <QLabel>
+
+namespace viper
+{
+class IDASHPlayerGuiObserver;
+
+class ViperGui : public QObject
+{
+ Q_OBJECT
+
+public:
+ ViperGui(QObject *parent = 0);
+ virtual ~ViperGui ();
+ void seekSegment(int segment);
+ void writeData(libdash::framework::input::MediaObject* media);
+ void setListSegmentSize(int listSegmentSize);
+ ViperBuffer* getStreamBuffer();
+ QtAV::AVPlayer* getVideoPlayer();
+ void setGuiFields(dash::mpd::IMPD* mpd);
+ void setLifeLabel(QObject *lifeLabel);
+ void setNowLabel(QObject *nowLabel);
+ void setPlayButton(QObject *playButton);
+ void setProgressBar(QObject *progressBar);
+ void seekVideo(float value);
+ uint64_t getDurationMilliseconds();
+ void initVideoPlayer();
+ void setOffset(int offset);
+ void setPosition(qint64 position);
+ qint64 getPosition();
+ void initSlider();
+ void setVideoStream(managers::MultimediaStream *videoStream);
+ QObject* getLifeLabel();
+
+ QObject* getNowLabel();
+ QObject* getProgressBar();
+ void clearGraph();
+ void setAnaliticsValues(uint32_t bitRate, int fps, uint32_t quality, double bufferSize);
+ void setGraphDataSource(GraphDataSource *graphDataSource);
+ void setPlay(bool play);
+ bool getPlay();
+ void setStop(bool stop);
+ bool getStop();
+ void setPause(bool pause);
+ bool getPause();
+ void setRepeat(bool repeat);
+ void setSegmentDuration(qint64 segmentDuration);
+ void initPlayer(int segmentOffset);
+ void pauseIfBuffering(qint64 position);
+ void startIfRepeat();
+ int64_t getLastSegmentDuration();
+ int64_t getBufferDuration();
+ int64_t getSegmentDuration();
+ void setRootObject(QObject *rootObject);
+ QObject *getRootObject();
+ void resetGraphValues();
+
+private:
+ pthread_mutex_t monitorMutex;
+ GraphDataSource *graphDataSource;
+ managers::MultimediaStream *videoStream;
+ int64_t offset;
+ int64_t durationMilliseconds;
+ qint64 position;
+ std::string durationString;
+ QtAV::AVPlayer *videoPlayer;
+ ViperBuffer *streamBuffer;
+ std::map<std::string, std::string> keyValues;
+ std::map<std::string, int> keyIndices;
+ std::map<std::string, std::vector<std::string>> video;
+ std::map<std::string, std::vector<std::string>> audio;
+ QObject *lifeLabel;
+ QObject *nowLabel;
+ QObject *progressBar;
+ QObject *playButton;
+ std::vector<IDASHPlayerGuiObserver *> observers;
+ dash::mpd::IMPD *mpd;
+ void setPeriodComboBox(dash::mpd::IMPD *mpd);
+ void setAdaptationSetComboBox(dash::mpd::IPeriod *period);
+ void setVideoAdaptationSetComboBox(dash::mpd::IPeriod *period);
+ void setAudioAdaptationSetComboBox(dash::mpd::IPeriod *period);
+ void setRepresentationComoboBox(dash::mpd::IAdaptationSet *adaptationSet);
+ void parse8601(std::string durationISO8601);
+ int listSegmentSize;
+ int segment;
+ int64_t bufferDuration;
+ int64_t segmentDuration;
+ int64_t lastSegmentDuration;
+ bool play;
+ bool stop;
+ bool pause;
+ bool repeat;
+ QObject *rootObject;
+
+};
+}
+
+#endif // VIPER_H