aboutsummaryrefslogtreecommitdiffstats
path: root/Managers
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 /Managers
parent9b30fc10fb1cbebe651e5a107e8ca5b24de54675 (diff)
Initial commit: video player - viper
Change-Id: Id5aa33598ce34659bad4a7a9ae5006bfb84f9bd1 Signed-off-by: Luca Muscariello <lumuscar+fdio@cisco.com>
Diffstat (limited to 'Managers')
-rw-r--r--Managers/IMultimediaManagerBase.h39
-rw-r--r--Managers/IMultimediaManagerObserver.h35
-rw-r--r--Managers/IStreamObserver.h46
-rw-r--r--Managers/MultimediaManager.cpp629
-rw-r--r--Managers/MultimediaManager.h140
-rw-r--r--Managers/MultimediaStream.cpp208
-rw-r--r--Managers/MultimediaStream.h89
7 files changed, 1186 insertions, 0 deletions
diff --git a/Managers/IMultimediaManagerBase.h b/Managers/IMultimediaManagerBase.h
new file mode 100644
index 00000000..f08803ba
--- /dev/null
+++ b/Managers/IMultimediaManagerBase.h
@@ -0,0 +1,39 @@
+/*
+ * 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_MANAGERS_IMULTIMEDIAMANAGERBASE_H_
+#define VIPER_MANAGERS_IMULTIMEDIAMANAGERBASE_H_
+
+#include "IMPD.h"
+
+namespace viper
+{
+namespace managers
+{
+class IMultimediaManagerBase
+{
+public:
+ virtual bool setVideoQuality(dash::mpd::IPeriod* period, dash::mpd::IAdaptationSet *adaptationSet, dash::mpd::IRepresentation *representation) = 0;
+ virtual bool setAudioQuality(dash::mpd::IPeriod* period, dash::mpd::IAdaptationSet *adaptationSet, dash::mpd::IRepresentation *representation) = 0;
+ virtual bool isStarted() = 0;
+ virtual bool isStopping() = 0;
+ virtual void shouldAbort(bool isVideo) = 0;
+ virtual void setTargetDownloadingTime(bool,double) = 0;
+
+};
+}
+}
+
+#endif //VIPER_MANAGERS_IMULTIMEDIAMANAGERBASE_H_
diff --git a/Managers/IMultimediaManagerObserver.h b/Managers/IMultimediaManagerObserver.h
new file mode 100644
index 00000000..eea0bfb1
--- /dev/null
+++ b/Managers/IMultimediaManagerObserver.h
@@ -0,0 +1,35 @@
+/*
+ * IMultimediaManagerObserver.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 VIPER_MANAGERS_IMULTIMEDIAMANAGEROBSERVER_H_
+#define VIPER_MANAGERS_IMULTIMEDIAMANAGEROBSERVER_H_
+
+#include <stdint.h>
+
+namespace viper
+{
+namespace managers
+{
+class IMultimediaManagerObserver
+{
+public:
+ virtual ~IMultimediaManagerObserver () {}
+ virtual void onVideoBufferStateChanged(uint32_t fillstateInPercent) = 0;
+ virtual void onVideoSegmentBufferStateChanged(uint32_t fillstateInPercent) = 0;
+ virtual void onAudioBufferStateChanged(uint32_t fillstateInPercent) = 0;
+ virtual void onAudioSegmentBufferStateChanged(uint32_t fillstateInPercent) = 0;
+ virtual void onEOS() = 0;
+ virtual void notifyStatistics(int, uint32_t, int, uint32_t) = 0;
+ virtual void notifyQualityDownloading(uint32_t) = 0;
+};
+}
+}
+#endif /* VIPER_MANAGERS_IMULTIMEDIAMANAGEROBSERVER_H_ */
diff --git a/Managers/IStreamObserver.h b/Managers/IStreamObserver.h
new file mode 100644
index 00000000..d6e8a19c
--- /dev/null
+++ b/Managers/IStreamObserver.h
@@ -0,0 +1,46 @@
+/*
+ * IStreamObserver.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 VIPER_MANAGERS_STREAMOBSERVER_H_
+#define VIPER_MANAGERS_STREAMOBSERVER_H_
+
+#include <stdint.h>
+
+namespace viper
+{
+namespace managers
+{
+enum StreamType
+{
+ AUDIO = (1u << 0),
+ VIDEO = (1u << 1),
+ SUBTITLE = (1u << 2),
+};
+
+class IStreamObserver
+{
+public:
+ virtual ~IStreamObserver () {}
+ virtual void onSegmentDownloaded() = 0;
+ virtual void onSegmentBufferStateChanged(StreamType type, uint32_t fillstateInPercent, int maxC) = 0;
+ virtual void onVideoBufferStateChanged(uint32_t fillstateInPercent) = 0;
+ virtual void onAudioBufferStateChanged(uint32_t fillstateInPercent) = 0;
+ virtual void setEOS(bool value) = 0;
+ virtual void notifyStatistics(int segNum, uint32_t bitrate, int fps, uint32_t quality) = 0;
+ virtual void notifyQualityDownloading(uint32_t quality) = 0;
+ virtual bool canPush() = 0;
+ virtual int getBufferLevel() = 0;
+
+};
+}
+}
+
+#endif /* VIPER_MANAGERS_STREAMOBSERVER_H_ */
diff --git a/Managers/MultimediaManager.cpp b/Managers/MultimediaManager.cpp
new file mode 100644
index 00000000..faab66cf
--- /dev/null
+++ b/Managers/MultimediaManager.cpp
@@ -0,0 +1,629 @@
+/*
+ * MultimediaManager.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 "MultimediaManager.h"
+
+#include <fstream>
+
+using namespace libdash::framework::adaptation;
+using namespace libdash::framework::buffer;
+using namespace viper::managers;
+using namespace dash::mpd;
+
+#include <queue>
+
+MultimediaManager::MultimediaManager(ViperGui *viperGui, int segBufSize, std::string downloadPath, bool nodecoding) :
+ viperGui (viperGui),
+ segmentBufferSize (segBufSize),
+ downloadPath (downloadPath),
+ offset (offset),
+ mpd (NULL),
+ period (NULL),
+ videoAdaptationSet (NULL),
+ videoRepresentation (NULL),
+ videoLogic (NULL),
+ videoStream (NULL),
+ audioAdaptationSet (NULL),
+ audioRepresentation (NULL),
+ audioLogic (NULL),
+ videoRendererHandle (NULL),
+ audioRendererHandle (NULL),
+ audioStream (NULL),
+ started (false),
+ stopping (false),
+ framesDisplayed (0),
+ segmentsDownloaded (0),
+ isVideoRendering (false),
+ isAudioRendering (false),
+ eos (false),
+ playing (false),
+ noDecoding (nodecoding)
+{
+ InitializeCriticalSection (&this->monitorMutex);
+ InitializeCriticalSection (&this->monitorBufferMutex);
+ InitializeCriticalSection (&this->monitor_playing_video_mutex);
+ InitializeConditionVariable (&this->playingVideoStatusChanged);
+ InitializeCriticalSection (&this->monitor_playing_audio_mutex);
+ InitializeConditionVariable (&this->playingAudioStatusChanged);
+
+ this->manager = CreateDashManager();
+}
+
+MultimediaManager::~MultimediaManager ()
+{
+ this->stop();
+ this->manager->Delete();
+ DeleteCriticalSection (&this->monitorMutex);
+ DeleteCriticalSection (&this->monitorBufferMutex);
+ DeleteCriticalSection (&this->monitor_playing_video_mutex);
+ DeleteConditionVariable (&this->playingVideoStatusChanged);
+ DeleteCriticalSection (&this->monitor_playing_audio_mutex);
+ DeleteConditionVariable (&this->playingAudioStatusChanged);
+}
+
+IMPD* MultimediaManager::getMPD()
+{
+ return this->mpd;
+}
+
+bool MultimediaManager::init(const std::string& url)
+{
+ EnterCriticalSection(&this->monitorMutex);
+ this->mpd = this->manager->Open((char *)url.c_str());
+ Debug("url : %s\n", url.c_str());
+ if(this->mpd == NULL)
+ {
+ LeaveCriticalSection(&this->monitorMutex);
+ return false;
+ }
+ Debug("Done DL the mpd\n");
+ LeaveCriticalSection(&this->monitorMutex);
+ return true;
+}
+
+bool MultimediaManager::initICN(const std::string& url)
+{
+ EnterCriticalSection(&this->monitorMutex);
+ libdash::framework::input::IICNConnection* icnConn = new libdash::framework::input::ICNConnectionConsumerApi(20.0, this->beta, this->drop);
+ icnConn->InitForMPD(url);
+ int ret = 0;
+ char * data = (char *)malloc(4096);
+ int pos = url.find_last_of("/");
+ if(pos == std::string::npos)
+ {
+ pos = strlen(url.c_str());
+ }
+ else
+ {
+ pos = pos + 1;
+ }
+
+ std::string downloadFile(this->downloadPath + url.substr(pos).c_str());
+ FILE *fp;
+ fp = fopen(downloadFile.c_str(), "w");
+ if(fp == NULL)
+ {
+ free(data);
+ delete icnConn;
+ LeaveCriticalSection(&this->monitorMutex);
+ return false;
+ }
+ ret = icnConn->Read((uint8_t*)data, 4096);
+ while(ret)
+ {
+ fwrite(data, sizeof(char), ret, fp);
+ ret = icnConn->Read((uint8_t*)data,4096);
+ }
+ fclose(fp);
+ this->mpd = this->manager->Open(const_cast<char*>(downloadFile.c_str()), url);
+ if(this->mpd == NULL)
+ {
+ remove(downloadFile.c_str());
+ free(data);
+ delete icnConn;
+ LeaveCriticalSection(&this->monitorMutex);
+ return false;
+ }
+ remove(downloadFile.c_str());
+ free(data);
+ delete icnConn;
+ LeaveCriticalSection(&this->monitorMutex);
+ return true;
+}
+
+bool MultimediaManager::isStarted()
+{
+ return this->started;
+}
+
+bool MultimediaManager::isStopping()
+{
+ return this->stopping;
+}
+
+bool MultimediaManager::isICN()
+{
+ return this->icn;
+}
+
+void MultimediaManager::start(bool icnEnabled, double icnAlpha, uint32_t nextOffset)
+{
+ this->icn = icnEnabled;
+ this->icnAlpha = icnAlpha;
+ if (this->started)
+ this->stop();
+ if(icnAlpha <= 1 && icnAlpha >=0)
+ {
+ qDebug("ICN-enhanced rate estimation: alpha = %f\n",icnAlpha);
+
+ } else {
+ qDebug("normal rate estimation\n");
+ }
+ EnterCriticalSection(&this->monitorMutex);
+ if (this->videoAdaptationSet && this->videoRepresentation)
+ {
+ this->initVideoRendering(nextOffset);
+ this->videoStream->setAdaptationLogic(this->videoLogic);
+ this->videoLogic->setMultimediaManager(this);
+ this->videoStream->start();
+ this->startVideoRenderingThread();
+ }
+ this->started = true;
+ this->playing = true;
+ LeaveCriticalSection(&this->monitorMutex);
+}
+
+void MultimediaManager::stop()
+{
+ if (!this->started)
+ return;
+ this->stopping = true;
+ EnterCriticalSection(&this->monitorMutex);
+ this->stopVideo();
+ this->stopping = false;
+ this->started = false;
+ LeaveCriticalSection(&this->monitorMutex);
+ Debug("VIDEO STOPPED\n");
+ this->period = this->mpd->GetPeriods().at(0);
+ this->videoAdaptationSet = this->period->GetAdaptationSets().at(0);
+ this->videoRepresentation = this->videoAdaptationSet->GetRepresentation().at(0);
+
+}
+
+void MultimediaManager::stopVideo()
+{
+ if(this->started && this->videoStream)
+ {
+ this->videoStream->stop();
+ this->stopVideoRenderingThread();
+ delete this->videoStream;
+ delete this->videoLogic;
+ this->videoStream = NULL;
+ this->videoLogic = NULL;
+ }
+}
+
+void MultimediaManager::stopAudio()
+{
+ if (this->started && this->audioStream)
+ {
+ //TODO add audio support
+ }
+}
+
+bool MultimediaManager::setVideoQuality(IPeriod* period, IAdaptationSet *adaptationSet, IRepresentation *representation)
+{
+ EnterCriticalSection(&this->monitorMutex);
+
+ this->period = period;
+ this->videoAdaptationSet = adaptationSet;
+ this->videoRepresentation = representation;
+ if (this->videoStream)
+ this->videoStream->setRepresentation(this->period, this->videoAdaptationSet, this->videoRepresentation);
+
+ LeaveCriticalSection(&this->monitorMutex);
+ return true;
+}
+
+bool MultimediaManager::setAudioQuality(IPeriod* period, IAdaptationSet *adaptationSet, IRepresentation *representation)
+{
+ EnterCriticalSection(&this->monitorMutex);
+
+ this->period = period;
+ this->audioAdaptationSet = adaptationSet;
+ this->audioRepresentation = representation;
+ if (this->audioStream)
+ this->audioStream->setRepresentation(this->period, this->audioAdaptationSet, this->audioRepresentation);
+ LeaveCriticalSection(&this->monitorMutex);
+ return true;
+}
+
+bool MultimediaManager::isUserDependent()
+{
+ if(this->videoLogic)
+ return this->videoLogic->isUserDependent();
+ else
+ return true;
+}
+
+bool MultimediaManager::setVideoAdaptationLogic(libdash::framework::adaptation::LogicType type, struct libdash::framework::adaptation::AdaptationParameters *params)
+{
+ if(this->videoAdaptationSet)
+ {
+ if(this->videoLogic)
+ delete(this->videoLogic);
+ this->videoLogic = AdaptationLogicFactory::create(type, this->mpd, this->period, this->videoAdaptationSet, 1, params);
+ this->logicName = LogicType_string[type];
+ }
+ else
+ {
+ this->videoLogic = NULL;
+ return true;
+ }
+ if(this->videoLogic)
+ return true;
+ else
+ return false;
+}
+
+void MultimediaManager::shouldAbort(bool isVideo)
+{
+ if(isVideo)
+ {
+ this->videoStream->shouldAbort();
+ return;
+ }
+ else
+ {
+ this->audioStream->shouldAbort();
+ }
+}
+
+void MultimediaManager::setTargetDownloadingTime(bool isVideo, double target)
+{
+ if(isVideo)
+ this->videoStream->setTargetDownloadingTime(target);
+ else
+ this->audioStream->setTargetDownloadingTime(target);
+}
+
+bool MultimediaManager::setAudioAdaptationLogic(libdash::framework::adaptation::LogicType type, struct libdash::framework::adaptation::AdaptationParameters *params)
+{
+ if(this->audioAdaptationSet)
+ {
+ this->audioLogic = AdaptationLogicFactory::create(type, this->mpd, this->period, this->audioAdaptationSet, 0, params);
+ this->logicName = LogicType_string[type];
+ }
+ else
+ {
+ this->audioLogic = NULL;
+ return true;
+ }
+ if(this->audioLogic)
+ return true;
+ else
+ return false;
+}
+
+void MultimediaManager::attachManagerObserver(IMultimediaManagerObserver *observer)
+{
+ this->managerObservers.push_back(observer);
+}
+
+void MultimediaManager::notifyVideoBufferObservers(uint32_t fillstateInPercent)
+{
+ for (size_t i = 0; i < this->managerObservers.size(); i++)
+ this->managerObservers.at(i)->onVideoBufferStateChanged(fillstateInPercent);
+}
+
+void MultimediaManager::notifyVideoSegmentBufferObservers(uint32_t fillstateInPercent)
+{
+ for (size_t i = 0; i < this->managerObservers.size(); i++)
+ this->managerObservers.at(i)->onVideoSegmentBufferStateChanged(fillstateInPercent);
+}
+
+void MultimediaManager::notifyAudioSegmentBufferObservers(uint32_t fillstateInPercent)
+{
+ for (size_t i = 0; i < this->managerObservers.size(); i++)
+ this->managerObservers.at(i)->onAudioSegmentBufferStateChanged(fillstateInPercent);
+}
+
+void MultimediaManager::notifyAudioBufferObservers(uint32_t fillstateInPercent)
+{
+ for (size_t i = 0; i < this->managerObservers.size(); i++)
+ this->managerObservers.at(i)->onAudioBufferStateChanged(fillstateInPercent);
+}
+
+void MultimediaManager::initVideoRendering(uint32_t offset)
+{
+ this->videoStream = new MultimediaStream(viper::managers::VIDEO, this->mpd, this->segmentBufferSize, this->isICN(), this->icnAlpha, this->noDecoding, this->beta, this->drop);
+ this->videoStream->attachStreamObserver(this);
+ this->videoStream->setRepresentation(this->period, this->videoAdaptationSet, this->videoRepresentation);
+ this->videoStream->setPosition(offset);
+}
+
+void MultimediaManager::initAudioPlayback(uint32_t offset)
+{
+ this->audioStream = new MultimediaStream(viper::managers::AUDIO, this->mpd, this->segmentBufferSize, this->isICN(), this->icnAlpha, this->noDecoding, this->beta, this->drop);
+ this->audioStream->attachStreamObserver(this);
+ this->audioStream->setRepresentation(this->period, this->audioAdaptationSet, this->audioRepresentation);
+ this->audioStream->setPosition(offset);
+}
+
+void MultimediaManager::setLooping(bool looping)
+{
+ if(this->videoStream)
+ {
+ this->videoStream->setLooping(looping);
+ }
+ if(this->audioStream)
+ {
+ this->audioStream->setLooping(looping);
+ }
+}
+
+void MultimediaManager::onSegmentDownloaded ()
+{
+ this->segmentsDownloaded++;
+}
+
+void MultimediaManager::onSegmentBufferStateChanged(StreamType type, uint32_t fillstateInPercent, int maxC)
+{
+ switch (type)
+ {
+ case AUDIO:
+ this->notifyAudioSegmentBufferObservers(fillstateInPercent);
+ break;
+ case VIDEO:
+ this->notifyVideoSegmentBufferObservers(fillstateInPercent);
+ break;
+ default:
+ break;
+ }
+}
+
+void MultimediaManager::onVideoBufferStateChanged(uint32_t fillstateInPercent)
+{
+ this->notifyVideoBufferObservers(fillstateInPercent);
+}
+
+void MultimediaManager::onAudioBufferStateChanged(uint32_t fillstateInPercent)
+{
+ this->notifyAudioBufferObservers(fillstateInPercent);
+}
+
+void MultimediaManager::setFrameRate(double framerate)
+{
+ this->frameRate = framerate;
+}
+
+void MultimediaManager::setEOS(bool value)
+{
+ this->eos = value;
+ if(value) //ie: End of Stream so the rendering thread(s) will finish
+ {
+ this->stopping = true;
+ if(this->videoRendererHandle != NULL)
+ {
+ this->stopVideoRenderingThread();
+ this->videoRendererHandle = NULL;
+ }
+ if(this->audioRendererHandle != NULL)
+ {
+ this->stopAudioRenderingThread();
+ this->audioRendererHandle = NULL;
+ }
+ this->stopping = false;
+ for(size_t i = 0; i < this->managerObservers.size(); i++)
+ this->managerObservers.at(i)->onEOS();
+ }
+}
+
+bool MultimediaManager::startVideoRenderingThread()
+{
+ this->isVideoRendering = true;
+ if(!noDecoding)
+ this->videoRendererHandle = createThreadPortable (pushVideo, this);
+ else
+ this->videoRendererHandle = createThreadPortable (pushVideoNoOut, this);
+
+ if(this->videoRendererHandle == NULL)
+ return false;
+
+ return true;
+}
+
+void MultimediaManager::stopVideoRenderingThread()
+{
+ this->isVideoRendering = false;
+ if (this->videoRendererHandle != NULL)
+ {
+ JoinThread(this->videoRendererHandle);
+ destroyThreadPortable(this->videoRendererHandle);
+ }
+}
+
+bool MultimediaManager::startAudioRenderingThread()
+{
+ this->isAudioRendering = true;
+ if(this->audioRendererHandle == NULL)
+ return false;
+ return true;
+}
+
+void MultimediaManager::stopAudioRenderingThread()
+{
+ this->isAudioRendering = false;
+ if (this->audioRendererHandle != NULL)
+ {
+ JoinThread(this->audioRendererHandle);
+ destroyThreadPortable(this->audioRendererHandle);
+ }
+}
+
+bool MultimediaManager::isPlaying()
+{
+ return this->playing;
+}
+
+void MultimediaManager::onPausePressed()
+{
+ EnterCriticalSection(&this->monitor_playing_video_mutex);
+ EnterCriticalSection(&this->monitor_playing_audio_mutex);
+ this->playing = !this->playing;
+ WakeAllConditionVariable(&this->playingVideoStatusChanged);
+ WakeAllConditionVariable(&this->playingAudioStatusChanged);
+ LeaveCriticalSection(&this->monitor_playing_video_mutex);
+ LeaveCriticalSection(&this->monitor_playing_audio_mutex);
+}
+
+void* MultimediaManager::pushVideoNoOut(void *data)
+{
+ MultimediaManager *manager = (MultimediaManager*) data;
+ manager->lastPointInTime = std::chrono::system_clock::now();
+ manager->bufferingLimit = manager->lastPointInTime;
+ libdash::framework::input::MediaObject *segment = manager->videoStream->getSegment();
+ using duration_in_milliSeconds = std::chrono::duration<long int, std::ratio<1,1000>>;
+ std::chrono::time_point<std::chrono::system_clock> timeOfInsertion;
+ std::chrono::time_point<std::chrono::system_clock> startTime;
+ long int actualPosition;
+
+ while(manager->isVideoRendering)
+ {
+ if (segment)
+ {
+ timeOfInsertion = std::chrono::system_clock::now();
+ actualPosition = std::chrono::duration_cast<duration_in_milliSeconds>(manager->bufferingLimit - timeOfInsertion).count();
+ if(actualPosition < 0)
+ {
+ Debug("MANAGER:\tRebuffered %d ms\n", actualPosition *(-1));
+ manager->lastPointInTime = timeOfInsertion;
+ //TODO Replace the 2 by a variable with segmentDuration
+ manager->bufferingLimit = manager->lastPointInTime + std::chrono::seconds(2);
+ }
+ else
+ {
+ //TODO Replace the 2 by a variable with segmentDuration
+ Debug("MANAGER: INSERT TO BUFFER old_fillness: %f, new_fillness: %f\n", (double)((double)actualPosition/1000.0) / (double) this->segmentBufferSize, (double)((double)(actualPosition + 2000)/1000.0) / (double) manager->segmentBufferSize);
+ manager->bufferingLimit = manager->bufferingLimit + std::chrono::seconds(2);
+ manager->lastPointInTime = timeOfInsertion;
+ }
+ delete segment;
+ }
+ else
+ {
+ //noDecoding here means noGUI
+ if(manager->noDecoding)
+ manager->setEOS(true);
+ }
+ segment = manager->videoStream->getSegment();
+ }
+ return NULL;
+
+}
+
+void MultimediaManager::notifyStatistics(int segNum, uint32_t bitrate, int fps, uint32_t quality)
+{
+ for(size_t i = 0; i < this->managerObservers.size(); i++)
+ {
+ this->managerObservers.at(i)->notifyStatistics(segNum, bitrate, fps, quality);
+ }
+}
+
+void MultimediaManager::notifyQualityDownloading(uint32_t quality)
+{
+ for(size_t i = 0; i < this->managerObservers.size(); i++)
+ {
+ this->managerObservers.at(i)->notifyQualityDownloading(quality);
+ }
+}
+
+void MultimediaManager::notifyBufferChange()
+{
+ if(this->videoStream)
+ {
+ this->videoStream->notifyBufferChange(this->getUBufferLevel(), this->segmentBufferSize);
+ }
+ if(this->audioStream)
+ {
+ this->audioStream->notifyBufferChange(this->getUBufferLevel(), this->segmentBufferSize);
+ }
+}
+
+int MultimediaManager::getBufferLevel()
+{
+ return (int)this->getUBufferLevel();
+}
+
+uint32_t MultimediaManager::getUBufferLevel()
+{
+ int mBufferLevel = 0;
+ int segmentDurationInMs = 2000;
+
+ if(noDecoding)
+ {
+ std::chrono::time_point<std::chrono::system_clock> timeNow = std::chrono::system_clock::now();
+ using duration_in_milliSeconds = std::chrono::duration<long int, std::ratio<1,1000>>;
+ long int actualPos = std::chrono::duration_cast<duration_in_milliSeconds>(this->bufferingLimit - timeNow).count();
+ int res = ((double)actualPos) / (double (this->segmentBufferSize * segmentDurationInMs)) * 100;
+ return res >= 0 ? res > 100 ? 100 : (uint32_t) res : 0;
+ }
+ else
+ {
+ mBufferLevel = this->viperGui->getBufferDuration();
+ int res = ((int)mBufferLevel)/((double) (this->segmentBufferSize * this->viperGui->getSegmentDuration())) * 100;
+ return res >= 0 ? res > 100 ? 100 : (uint32_t) res : 0;
+
+ }
+}
+
+bool MultimediaManager::canPush()
+{
+ int segmentDurationInMs = 2000;
+ while(this->getUBufferLevel() >= 100 && !this->stopping)
+ {
+ sleep(segmentDurationInMs / 1000);
+ }
+ return true;
+}
+
+void* MultimediaManager::pushVideo(void *data)
+{
+ MultimediaManager *manager = (MultimediaManager*) data;
+ libdash::framework::input::MediaObject *segment = manager->videoStream->getSegment();
+ long int segmentDurationInMs = 2000;
+ while(manager->isVideoRendering)
+ {
+ if (segment)
+ {
+ manager->notifyBufferChange();
+ manager->viperGui->writeData(segment);
+ delete segment;
+ }
+ segment = manager->videoStream->getSegment();
+ }
+ return NULL;
+}
+
+void MultimediaManager::setOffset(int offset)
+{
+ this->offset = offset;
+}
+
+void MultimediaManager::setBeta(float beta)
+{
+ this->beta = beta;
+}
+
+void MultimediaManager::setDrop(float drop)
+{
+ this->drop = drop;
+}
diff --git a/Managers/MultimediaManager.h b/Managers/MultimediaManager.h
new file mode 100644
index 00000000..b4187486
--- /dev/null
+++ b/Managers/MultimediaManager.h
@@ -0,0 +1,140 @@
+/*
+ * MultimediaManager.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 VIPER_MANAGERS_MULTIMEDIAMANAGER_H_
+#define VIPER_MANAGERS_MULTIMEDIAMANAGER_H_
+
+#include "IMPD.h"
+#include "MultimediaStream.h"
+#include "IMultimediaManagerBase.h"
+#include "IMultimediaManagerObserver.h"
+#include "../Adaptation/IAdaptationLogic.h"
+#include "../Adaptation/AdaptationLogicFactory.h"
+#include "../Portable/MultiThreading.h"
+#include <QtMultimedia/qaudiooutput.h>
+#include <cstring>
+#include <QtAV/QtAV.h>
+#include "Common/ViperBuffer.h"
+#include "UI/ViperGui.h"
+
+namespace viper
+{
+namespace managers
+{
+class MultimediaManager : public IStreamObserver, public IMultimediaManagerBase
+{
+public:
+ MultimediaManager(ViperGui *viperGui, int segmentBufferSize, std::string downloadPath, bool noDecoding = false);
+ virtual ~MultimediaManager();
+
+ bool init (const std::string& url);
+ bool initICN (const std::string& url);
+ void start (bool icnEnabled, double icnAlpha, uint32_t nextOffset);
+ void stop ();
+ dash::mpd::IMPD* getMPD ();
+
+ bool setVideoQuality (dash::mpd::IPeriod* period, dash::mpd::IAdaptationSet *adaptationSet, dash::mpd::IRepresentation *representation);
+ bool setAudioQuality (dash::mpd::IPeriod* period, dash::mpd::IAdaptationSet *adaptationSet, dash::mpd::IRepresentation *representation);
+
+ bool setVideoAdaptationLogic (libdash::framework::adaptation::LogicType type, struct libdash::framework::adaptation::AdaptationParameters *params);
+ bool setAudioAdaptationLogic (libdash::framework::adaptation::LogicType type, struct libdash::framework::adaptation::AdaptationParameters *params);
+
+ void attachManagerObserver (IMultimediaManagerObserver *observer);
+
+ void setFrameRate (double frameRate);
+
+ /* IStreamObserver */
+ void onSegmentDownloaded ();
+ void onSegmentBufferStateChanged (StreamType type, uint32_t fillstateInPercent, int maxC);
+ void onVideoBufferStateChanged (uint32_t fillstateInPercent);
+ void onAudioBufferStateChanged (uint32_t fillstateInPercent);
+ bool isUserDependent ();
+ bool isStarted ();
+ bool isStopping ();
+ bool isICN ();
+ void setEOS (bool value);
+ void shouldAbort (bool isVideo);
+ void setTargetDownloadingTime (bool isVid, double time);
+ bool isPlaying ();
+ void onPausePressed ();
+ void notifyStatistics (int segNum, uint32_t bitrate, int fps, uint32_t quality);
+ void notifyQualityDownloading (uint32_t quality);
+ uint32_t getUBufferLevel ();
+ int getBufferLevel ();
+ void setLooping (bool looping);
+ void setOffset(int offset);
+ void setBeta(float beta);
+ void setDrop(float drop);
+ bool canPush ();
+ CRITICAL_SECTION monitorBufferMutex;
+
+ int offset;
+ std::chrono::time_point<std::chrono::system_clock> lastPointInTime;
+ std::chrono::time_point<std::chrono::system_clock> bufferingLimit;
+
+private:
+ float beta;
+ float drop;
+ std::string downloadPath;
+ int segmentBufferSize;
+ ViperGui *viperGui;
+ dash::IDASHManager *manager;
+ dash::mpd::IMPD *mpd;
+ dash::mpd::IPeriod *period;
+ dash::mpd::IAdaptationSet *videoAdaptationSet;
+ dash::mpd::IRepresentation *videoRepresentation;
+ libdash::framework::adaptation::IAdaptationLogic *videoLogic;
+ MultimediaStream *videoStream;
+ dash::mpd::IAdaptationSet *audioAdaptationSet;
+ dash::mpd::IRepresentation *audioRepresentation;
+ libdash::framework::adaptation::IAdaptationLogic *audioLogic;
+ MultimediaStream *audioStream;
+ std::vector<IMultimediaManagerObserver *> managerObservers;
+ bool started;
+ bool stopping;
+ bool icn;
+ double icnAlpha;
+ uint64_t framesDisplayed;
+ uint64_t segmentsDownloaded;
+ CRITICAL_SECTION monitorMutex;
+ double frameRate;
+ THREAD_HANDLE videoRendererHandle;
+ THREAD_HANDLE audioRendererHandle;
+ bool isVideoRendering;
+ bool isAudioRendering;
+ bool eos;
+ bool playing;
+ mutable CRITICAL_SECTION monitor_playing_video_mutex;
+ mutable CONDITION_VARIABLE playingVideoStatusChanged;
+ mutable CRITICAL_SECTION monitor_playing_audio_mutex;
+ mutable CONDITION_VARIABLE playingAudioStatusChanged;
+ const char *logicName;
+ bool noDecoding;
+ void notifyBufferChange ();
+ bool startVideoRenderingThread ();
+ void stopVideoRenderingThread ();
+ static void* pushVideo (void *data);
+ static void* pushVideoNoOut (void *data);
+ bool startAudioRenderingThread ();
+ void stopAudioRenderingThread ();
+ void initVideoRendering (uint32_t offset);
+ void initAudioPlayback (uint32_t offset);
+ void stopVideo ();
+ void stopAudio ();
+ void notifyVideoBufferObservers (uint32_t fillstateInPercent);
+ void notifyVideoSegmentBufferObservers (uint32_t fillstateInPercent);
+ void notifyAudioBufferObservers (uint32_t fillstateInPercent);
+ void notifyAudioSegmentBufferObservers (uint32_t fillstateInPercent);
+};
+}
+}
+
+#endif /* VIPER_MANAGERS_MULTIMEDIAMANAGER_H_ */
diff --git a/Managers/MultimediaStream.cpp b/Managers/MultimediaStream.cpp
new file mode 100644
index 00000000..ed0d967c
--- /dev/null
+++ b/Managers/MultimediaStream.cpp
@@ -0,0 +1,208 @@
+/*
+ * MultimediaStream.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 "MultimediaStream.h"
+
+using namespace viper::managers;
+using namespace libdash::framework::adaptation;
+using namespace libdash::framework::input;
+using namespace libdash::framework::buffer;
+using namespace dash::mpd;
+
+MultimediaStream::MultimediaStream(StreamType type, IMPD *mpd, uint32_t bufferSize, bool icnEnabled, double icnAlpha, bool nodecoding, float beta, float drop) :
+ type (type),
+ segmentBufferSize (bufferSize),
+ dashManager (NULL),
+ mpd (mpd),
+ icn (icnEnabled),
+ icnAlpha (icnAlpha),
+ noDecoding (nodecoding),
+ beta (beta),
+ drop (drop)
+{
+ this->init();
+}
+MultimediaStream::~MultimediaStream ()
+{
+ this->stop();
+ delete this->dashManager;
+}
+
+bool MultimediaStream::isICN()
+{
+ return this->icn;
+}
+
+void MultimediaStream::shouldAbort()
+{
+ this->dashManager->shouldAbort();
+}
+
+uint32_t MultimediaStream::getPosition()
+{
+ return this->dashManager->getPosition();
+}
+
+void MultimediaStream::setLooping(bool looping)
+{
+ this->dashManager->setLooping(looping);
+}
+
+void MultimediaStream::setPosition(uint32_t segmentNumber)
+{
+ this->dashManager->setPosition(segmentNumber);
+}
+
+void MultimediaStream::setPositionInMsec(uint32_t milliSecs)
+{
+ this->dashManager->setPositionInMsec(milliSecs);
+}
+
+void MultimediaStream::init()
+{
+ this->dashManager = new DASHManager(this->type, this->segmentBufferSize, this, this->mpd, this->isICN(), this->icnAlpha, this->noDecoding, this->beta, this->drop);
+}
+
+bool MultimediaStream::start()
+{
+ if(!this->startDownload())
+ return false;
+
+ return true;
+}
+
+bool MultimediaStream::startDownload()
+{
+ dashManager->setAdaptationLogic(this->logic);
+ if(!dashManager->start())
+ return false;
+
+ return true;
+}
+
+void MultimediaStream::stop()
+{
+ this->stopDownload();
+}
+
+void MultimediaStream::stopDownload()
+{
+ this->dashManager->stop();
+}
+
+void MultimediaStream::clear()
+{
+ this->dashManager->clear();
+}
+
+void MultimediaStream::addFrame(QImage *frame)
+{
+}
+
+QImage* MultimediaStream::getFrame()
+{
+ return NULL;
+}
+
+void MultimediaStream::attachStreamObserver(IStreamObserver *observer)
+{
+ this->observers.push_back(observer);
+}
+
+void MultimediaStream::setRepresentation(IPeriod *period, IAdaptationSet *adaptationSet, IRepresentation *representation)
+{
+ this->dashManager->setRepresentation(period, adaptationSet, representation);
+}
+
+void MultimediaStream::enqueueRepresentation(IPeriod *period, IAdaptationSet *adaptationSet, IRepresentation *representation)
+{
+ this->dashManager->enqueueRepresentation(period, adaptationSet, representation);
+}
+
+void MultimediaStream::setAdaptationLogic(libdash::framework::adaptation::IAdaptationLogic *logic)
+{
+ this->logic = logic;
+}
+
+void MultimediaStream::onSegmentBufferStateChanged(uint32_t fillstateInPercent, int maxC)
+{
+ for (size_t i = 0; i < observers.size(); i++)
+ this->observers.at(i)->onSegmentBufferStateChanged(this->type, fillstateInPercent, maxC);
+}
+
+void MultimediaStream::onBufferStateChanged(BufferType type, uint32_t fillstateInPercent, int maxC)
+{
+ switch(type)
+ {
+ case libdash::framework::buffer::AUDIO:
+ for (size_t i = 0; i < observers.size(); i++)
+ this->observers.at(i)->onAudioBufferStateChanged(fillstateInPercent);
+ break;
+ case libdash::framework::buffer::VIDEO:
+ for (size_t i = 0; i < observers.size(); i++)
+ this->observers.at(i)->onVideoBufferStateChanged(fillstateInPercent);
+ default:
+ break;
+ }
+}
+
+void MultimediaStream::setEOS(bool value)
+{
+ for(size_t i = 0; i < observers.size(); i++)
+ this->observers.at(i)->setEOS(value);
+}
+
+void MultimediaStream::setTargetDownloadingTime(double target)
+{
+ this->dashManager->setTargetDownloadingTime(target);
+}
+
+void MultimediaStream::notifyStatistics(int segNum, uint32_t bitrate, int fps, uint32_t quality)
+{
+ for(size_t i = 0; i < observers.size(); i++)
+ this->observers.at(i)->notifyStatistics(segNum, bitrate, fps, quality);
+}
+
+void MultimediaStream::notifyQualityDownloading(uint32_t quality)
+{
+ for(size_t i = 0; i < observers.size(); i++)
+ this->observers.at(i)->notifyQualityDownloading(quality);
+}
+
+int MultimediaStream::getBufferLevel()
+{
+ int bufferFill = 0;
+ for(size_t i=0; i < observers.size(); i++)
+ {
+ bufferFill = this->observers.at(i)->getBufferLevel();
+ }
+ return bufferFill;
+}
+bool MultimediaStream::canPush()
+{
+ bool flag = false;
+ for(size_t i=0; i < observers.size(); i++)
+ {
+ flag = flag || this->observers.at(i)->canPush();
+ }
+ return flag;
+}
+
+
+libdash::framework::input::MediaObject* MultimediaStream::getSegment()
+{
+ return this->dashManager->getSegment();
+}
+
+void MultimediaStream::notifyBufferChange(uint32_t bufferfill, int maxC)
+{
+ this->dashManager->onBufferStateChanged(libdash::framework::buffer::VIDEO, bufferfill, maxC);
+}
diff --git a/Managers/MultimediaStream.h b/Managers/MultimediaStream.h
new file mode 100644
index 00000000..6918f639
--- /dev/null
+++ b/Managers/MultimediaStream.h
@@ -0,0 +1,89 @@
+/*
+ * MultimediaStream.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 VIPER_MANAGERS_MULTIMEDIASTREAM_H_
+#define VIPER_MANAGERS_MULTIMEDIASTREAM_H_
+
+#include "IMPD.h"
+#include "IStreamObserver.h"
+#include "../Input/DASHManager.h"
+#include "../Buffer/IBufferObserver.h"
+#include "../Adaptation/IAdaptationLogic.h"
+#include <QtMultimedia/qaudioformat.h>
+#include "../Input/IDASHManagerObserver.h"
+#include "../Buffer/Buffer.h"
+#include <QImage>
+
+namespace viper
+{
+namespace managers
+{
+class MultimediaStream : public libdash::framework::input::IDASHManagerObserver, public libdash::framework::buffer::IBufferObserver
+{
+public:
+ MultimediaStream(StreamType type, dash::mpd::IMPD *mpd, uint32_t segmentBufferSize, bool icnEnabled, double icnAlpha, bool nodecoding, float beta, float drop);
+ virtual ~MultimediaStream();
+
+ bool start();
+ void stop();
+ void stopDownload();
+ bool startDownload();
+ void clear();
+ uint32_t getPosition();
+ void setPosition(uint32_t segmentNumber);
+ void setLooping(bool looping);
+ void setPositionInMsec(uint32_t milliSecs);
+
+ void addFrame(QImage *frame);
+ QImage* getFrame();
+ libdash::framework::input::MediaObject* getSegment();
+
+ void setEOS(bool value);
+
+ void notifyBufferChange(uint32_t bufferfill, int maxC);
+
+ void setRepresentation(dash::mpd::IPeriod *period, dash::mpd::IAdaptationSet *adaptationSet, dash::mpd::IRepresentation *representation);
+ void enqueueRepresentation(dash::mpd::IPeriod *period, dash::mpd::IAdaptationSet *adaptationSet, dash::mpd::IRepresentation *representation);
+ void setAdaptationLogic(libdash::framework::adaptation::IAdaptationLogic *logic);
+
+ void attachStreamObserver(IStreamObserver *observer);
+
+ void onSegmentBufferStateChanged(uint32_t fillstateInPercent, int maxC);
+ void onBufferStateChanged(libdash::framework::buffer::BufferType type, uint32_t fillstateInPercent, int maxC);
+
+ void notifyStatistics(int segNum, uint32_t bitrate, int fps, uint32_t quality);
+ void notifyQualityDownloading (uint32_t quality);
+ bool canPush();
+ int getBufferLevel();
+ bool isICN();
+ void shouldAbort();
+
+ void setTargetDownloadingTime(double);
+
+private:
+ float beta;
+ float drop;
+ std::vector<IStreamObserver *> observers;
+ dash::mpd::IMPD *mpd;
+ libdash::framework::adaptation::IAdaptationLogic *logic;
+ libdash::framework::input::DASHManager *dashManager;
+ uint32_t segmentBufferSize;
+ StreamType type;
+ bool icn;
+ double icnAlpha;
+
+ bool noDecoding;
+ void init ();
+};
+}
+}
+
+#endif /* VIPER_MANAGERS_MULTIMEDIASTREAM_H_ */