diff options
Diffstat (limited to 'UI')
-rw-r--r-- | UI/DASHPlayer.cpp | 923 | ||||
-rw-r--r-- | UI/DASHPlayer.h | 207 | ||||
-rw-r--r-- | UI/DASHPlayerNoGUI.cpp | 383 | ||||
-rw-r--r-- | UI/DASHPlayerNoGUI.h | 93 | ||||
-rw-r--r-- | UI/GraphDataSource.cpp | 146 | ||||
-rw-r--r-- | UI/GraphDataSource.h | 62 | ||||
-rw-r--r-- | UI/IDASHPlayerGuiObserver.h | 35 | ||||
-rw-r--r-- | UI/IDASHPlayerNoGuiObserver.h | 29 | ||||
-rw-r--r-- | UI/ViperGui.cpp | 414 | ||||
-rw-r--r-- | UI/ViperGui.h | 128 |
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 |