diff options
author | Luca Muscariello <lumuscar+fdio@cisco.com> | 2017-02-25 23:42:31 +0100 |
---|---|---|
committer | Luca Muscariello <lumuscar+fdio@cisco.com> | 2017-02-25 23:42:31 +0100 |
commit | 05c1a838c881ea502888659848d8792843b28718 (patch) | |
tree | cf0b05b58bd725a1eb6c80325ba986c63dea42aa /Input | |
parent | 9b30fc10fb1cbebe651e5a107e8ca5b24de54675 (diff) |
Initial commit: video player - viper
Change-Id: Id5aa33598ce34659bad4a7a9ae5006bfb84f9bd1
Signed-off-by: Luca Muscariello <lumuscar+fdio@cisco.com>
Diffstat (limited to 'Input')
-rw-r--r-- | Input/DASHManager.cpp | 161 | ||||
-rw-r--r-- | Input/DASHManager.h | 80 | ||||
-rw-r--r-- | Input/DASHReceiver.cpp | 453 | ||||
-rw-r--r-- | Input/DASHReceiver.h | 129 | ||||
-rw-r--r-- | Input/ICNConnectionConsumerApi.cpp | 283 | ||||
-rw-r--r-- | Input/ICNConnectionConsumerApi.h | 138 | ||||
-rw-r--r-- | Input/IDASHManagerObserver.h | 41 | ||||
-rw-r--r-- | Input/IDASHReceiverObserver.h | 35 | ||||
-rw-r--r-- | Input/IDataReceiver.h | 34 | ||||
-rw-r--r-- | Input/IICNConnection.h | 44 | ||||
-rw-r--r-- | Input/MediaObject.cpp | 175 | ||||
-rw-r--r-- | Input/MediaObject.h | 78 |
12 files changed, 1651 insertions, 0 deletions
diff --git a/Input/DASHManager.cpp b/Input/DASHManager.cpp new file mode 100644 index 00000000..a86263dc --- /dev/null +++ b/Input/DASHManager.cpp @@ -0,0 +1,161 @@ +/* + * DASHManager.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 "DASHManager.h" + +using namespace libdash::framework::input; +using namespace libdash::framework::buffer; + +using namespace dash; +using namespace dash::network; +using namespace dash::mpd; + +DASHManager::DASHManager(viper::managers::StreamType type, uint32_t maxCapacity, IDASHManagerObserver* stream, IMPD* mpd, bool icnEnabled, double icnAlpha, bool nodecoding, float beta, float drop) : + readSegmentCount (0), + receiver (NULL), + multimediaStream (stream), + isRunning (false), + icn (icnEnabled), + icnAlpha (icnAlpha), + noDecoding (nodecoding), + beta (beta), + drop (drop) +{ + + this->buffer = new Buffer<MediaObject>(maxCapacity,libdash::framework::buffer::VIDEO); + this->buffer->attachObserver(this); + + this->receiver = new DASHReceiver(mpd, this, this->buffer, maxCapacity, this->isICN(), this->icnAlpha, this->beta, this->drop); +} +DASHManager::~DASHManager() +{ + this->stop(); + delete this->receiver; + delete this->buffer; + + this->receiver = NULL; + this->buffer = NULL; +} + +bool DASHManager::isICN() +{ + return this->icn; +} + +void DASHManager::shouldAbort() +{ + Debug("DASH MANAGER: ABORT REQUEST\n"); + this->receiver->ShouldAbort(); +} + +bool DASHManager::start() +{ + this->receiver->SetAdaptationLogic(this->adaptationLogic); + if (!this->receiver->Start()) + return false; + + this->isRunning = true; + return true; +} + +void DASHManager::stop() +{ + if (!this->isRunning) + return; + + this->isRunning = false; + + this->receiver->Stop(); + this->buffer->clear(); +} + +uint32_t DASHManager::getPosition() +{ + return this->receiver->GetPosition(); +} + +void DASHManager::setLooping(bool looping) +{ + this->receiver->SetLooping(looping); +} + +void DASHManager::setPosition(uint32_t segmentNumber) +{ + this->receiver->SetPosition(segmentNumber); +} + +void DASHManager::setPositionInMsec(uint32_t milliSecs) +{ + this->receiver->SetPositionInMsecs(milliSecs); +} + +void DASHManager::setAdaptationLogic(libdash::framework::adaptation::IAdaptationLogic *_adaptationLogic) +{ + this->adaptationLogic = _adaptationLogic; +} + +void DASHManager::clear() +{ + this->buffer->clear(); +} + +void DASHManager::setRepresentation(IPeriod *period, IAdaptationSet *adaptationSet, IRepresentation *representation) +{ + this->receiver->SetRepresentation(period, adaptationSet, representation); +} + +void DASHManager::enqueueRepresentation(IPeriod *period, IAdaptationSet *adaptationSet, IRepresentation *representation) +{ + this->receiver->SetRepresentation(period, adaptationSet, representation); +} + +void DASHManager::onSegmentDownloaded() +{ + this->readSegmentCount++; +} + +void DASHManager::notifyStatistics(int segNum, uint32_t bitrate, int fps, uint32_t quality) +{ + this->multimediaStream->notifyStatistics(segNum, bitrate, fps, quality); +} + +void DASHManager::notifyQualityDownloading(uint32_t quality) +{ + this->multimediaStream->notifyQualityDownloading(quality); +} + +int DASHManager::getBufferLevel() +{ + int res = this->multimediaStream->getBufferLevel(); + return this->multimediaStream->getBufferLevel(); +} + +bool DASHManager::canPush() +{ + this->multimediaStream->canPush(); +} + +MediaObject* DASHManager::getSegment() +{ + return this->buffer->getFront(); +} + +void DASHManager::setTargetDownloadingTime(double target) +{ + this->receiver->SetTargetDownloadingTime(target); +} + +void DASHManager::onBufferStateChanged(BufferType type, uint32_t fillstateInPercent, int maxC) +{ + this->multimediaStream->onSegmentBufferStateChanged(fillstateInPercent, maxC); + if(this->adaptationLogic->isBufferBased()) + this->receiver->OnSegmentBufferStateChanged(fillstateInPercent, maxC); +} diff --git a/Input/DASHManager.h b/Input/DASHManager.h new file mode 100644 index 00000000..2b723426 --- /dev/null +++ b/Input/DASHManager.h @@ -0,0 +1,80 @@ +/* + * DASHManager.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 LIBDASH_FRAMEWORK_INPUT_DASHMANAGER_H_ +#define LIBDASH_FRAMEWORK_INPUT_DASHMANAGER_H_ + +#include "DASHReceiver.h" +#include "IDASHReceiverObserver.h" +#include "libdash.h" +#include "IMPD.h" +#include <QtMultimedia/qaudioformat.h> +#include "IDASHManagerObserver.h" +//#include "../Buffer/Segment.h" +#include "../Managers/IStreamObserver.h" +#include "../Buffer/IBufferObserver.h" + + +namespace libdash +{ +namespace framework +{ +namespace input +{ + +class DASHManager : public IDASHReceiverObserver, public IBufferObserver +{ +public: + DASHManager (viper::managers::StreamType type, uint32_t maxCapacity, IDASHManagerObserver *multimediaStream, dash::mpd::IMPD *mpd, bool icnEnabled, double icnAlpha, bool nodecoding, float beta, float drop); + virtual ~DASHManager (); + + bool start(); + void stop(); + uint32_t getPosition(); + void setPosition(uint32_t segmentNumber); // to implement + void setLooping(bool looping); + void setPositionInMsec(uint32_t millisec); + void clear(); + 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 onSegmentDownloaded(); + void notifyStatistics(int, uint32_t, int, uint32_t); + void notifyQualityDownloading (uint32_t); + bool canPush(); + int getBufferLevel(); + void setAdaptationLogic(libdash::framework::adaptation::IAdaptationLogic *_adaptationLogic); + bool isICN(); + void shouldAbort(); + + void setTargetDownloadingTime(double); + MediaObject* getSegment(); + void onBufferStateChanged(BufferType type, uint32_t fillstateInPercent, int maxC); + +private: + float beta; + float drop; + buffer::Buffer<MediaObject> *buffer; + DASHReceiver *receiver; + uint32_t readSegmentCount; + IDASHManagerObserver *multimediaStream; + bool isRunning; + bool icn; + double icnAlpha; + bool noDecoding; + + libdash::framework::adaptation::IAdaptationLogic *adaptationLogic; +}; +} +} +} + +#endif /* LIBDASH_FRAMEWORK_INPUT_DASHMANAGER_H_ */ diff --git a/Input/DASHReceiver.cpp b/Input/DASHReceiver.cpp new file mode 100644 index 00000000..df9d019b --- /dev/null +++ b/Input/DASHReceiver.cpp @@ -0,0 +1,453 @@ +/* + * DASHReceiver.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 "DASHReceiver.h" +#include<stdio.h> + +using namespace libdash::framework::input; +using namespace libdash::framework::buffer; +using namespace libdash::framework::mpd; +using namespace dash::mpd; + +using duration_in_seconds = std::chrono::duration<double, std::ratio<1, 1> >; + +DASHReceiver::DASHReceiver (IMPD *mpd, IDASHReceiverObserver *obs, Buffer<MediaObject> *buffer, uint32_t bufferSize, bool icnEnabled, double icnAlpha, float beta, float drop) : + mpd (mpd), + period (NULL), + adaptationSet (NULL), + representation (NULL), + adaptationSetStream (NULL), + representationStream (NULL), + segmentNumber (0), + observer (obs), + buffer (buffer), + bufferSize (bufferSize), + isBuffering (false), + withFeedBack (false), + icn (icnEnabled), + icnAlpha (icnAlpha), + previousQuality (0), + isPaused (false), + threadComplete (false), + isScheduledPaced (false), + targetDownload (0.0), + downloadingTime (0.0), + bufferLevelAtUpdate (0), + isBufferBased (false), + isLooping (false), + beta (beta), + drop (drop) +{ + readMax = 32768; + readBuffer = (uint8_t*)malloc(sizeof(uint8_t)*readMax); + this->period = this->mpd->GetPeriods().at(0); + this->adaptationSet = this->period->GetAdaptationSets().at(0); + this->representation = this->adaptationSet->GetRepresentation().at(0); + + this->adaptationSetStream = new AdaptationSetStream(mpd, period, adaptationSet); + this->representationStream = adaptationSetStream->getRepresentationStream(this->representation); + this->segmentOffset = CalculateSegmentOffset(); + + this->conn = NULL; + this->initConn = NULL; + readMax = 32768; + readBuffer = (uint8_t *)malloc(sizeof(uint8_t) * readMax); + + if(icn) + { + this->conn = new ICNConnectionConsumerApi(this->icnAlpha, this->beta, this->drop); + this->initConn = new ICNConnectionConsumerApi(this->icnAlpha, this->beta, this->drop); + } + InitializeCriticalSection(&this->monitorMutex); + InitializeCriticalSection(&this->monitorPausedMutex); + InitializeConditionVariable(&this->paused); +} +DASHReceiver::~DASHReceiver () +{ + free(readBuffer); + if(this->initConn) + delete(this->initConn); + if(this->conn) + delete(this->conn); + delete(this->adaptationSetStream); + DeleteCriticalSection(&this->monitorMutex); + DeleteCriticalSection(&this->monitorPausedMutex); + DeleteConditionVariable(&this->paused); +} + +void DASHReceiver::SetAdaptationLogic(adaptation::IAdaptationLogic *_adaptationLogic) +{ + this->adaptationLogic = _adaptationLogic; + this->isBufferBased = this->adaptationLogic->isBufferBased(); + this->withFeedBack = this->adaptationLogic->isRateBased(); +} +bool DASHReceiver::Start () +{ + if(this->isBuffering) + return false; + + this->isBuffering = true; + this->bufferingThread = createThreadPortable(DoBuffering, this); + + if(this->bufferingThread == NULL) + { + this->isBuffering = false; + return false; + } + + return true; +} +void DASHReceiver::Stop() +{ + if(!this->isBuffering) + return; + + this->isBuffering = false; + this->buffer->setEOS(true); + + if(this->bufferingThread != NULL) + { + JoinThread(this->bufferingThread); + destroyThreadPortable(this->bufferingThread); + } + this->period = this->mpd->GetPeriods().at(0); + this->adaptationSet = this->period->GetAdaptationSets().at(0); + this->representation = this->adaptationSet->GetRepresentation().at(0); +} + +MediaObject* DASHReceiver::GetNextSegment () +{ + ISegment *seg = NULL; + + EnterCriticalSection(&this->monitorPausedMutex); + while(this->isPaused) + SleepConditionVariableCS(&this->paused, &this->monitorPausedMutex, INFINITE); + + if(this->segmentNumber >= this->representationStream->getSize()) + { + qDebug("looping? : %s\n", this->isLooping ? "YES" : "NO"); + if(this->isLooping) + { + this->segmentNumber = 0; + } + else + { + LeaveCriticalSection(&this->monitorPausedMutex); + return NULL; + } + } + seg = this->representationStream->getMediaSegment(this->segmentNumber + this->segmentOffset); + + if (seg != NULL) + { + std::vector<IRepresentation *> rep = this->adaptationSet->GetRepresentation(); + + this->NotifyQualityDownloading(this->representation->GetBandwidth()); + + MediaObject *media = new MediaObject(seg, this->representation,this->withFeedBack); + this->segmentNumber++; + LeaveCriticalSection(&this->monitorPausedMutex); + return media; + } + LeaveCriticalSection(&this->monitorPausedMutex); + return NULL; +} +MediaObject* DASHReceiver::GetSegment (uint32_t segNum) +{ + ISegment *seg = NULL; + + if(segNum >= this->representationStream->getSize()) + return NULL; + + seg = this->representationStream->getMediaSegment(segNum + segmentOffset); + + if (seg != NULL) + { + MediaObject *media = new MediaObject(seg, this->representation); + return media; + } + + return NULL; +} +MediaObject* DASHReceiver::GetInitSegment () +{ + ISegment *seg = NULL; + + seg = this->representationStream->getInitializationSegment(); + + if (seg != NULL) + { + MediaObject *media = new MediaObject(seg, this->representation); + return media; + } + + return NULL; +} +MediaObject* DASHReceiver::FindInitSegment (dash::mpd::IRepresentation *representation) +{ + if (!this->InitSegmentExists(representation)) + return NULL; + + return this->initSegments[representation]; +} +uint32_t DASHReceiver::GetPosition () +{ + return this->segmentNumber; +} +void DASHReceiver::SetLooping (bool looping) +{ + this->isLooping = looping; +} +void DASHReceiver::SetPosition (uint32_t segmentNumber) +{ + this->segmentNumber = segmentNumber; +} +void DASHReceiver::SetPositionInMsecs (uint32_t milliSecs) +{ + this->positionInMsecs = milliSecs; +} + +void DASHReceiver::NotifyQualityDownloading (uint32_t quality) +{ + this->observer->notifyQualityDownloading(quality); +} + +void DASHReceiver::SetRepresentation (IPeriod *period, IAdaptationSet *adaptationSet, IRepresentation *representation) +{ + EnterCriticalSection(&this->monitorMutex); + + bool periodChanged = false; + + if (this->representation == representation) + { + LeaveCriticalSection(&this->monitorMutex); + return; + } + + this->representation = representation; + + if (this->adaptationSet != adaptationSet) + { + this->adaptationSet = adaptationSet; + + if (this->period != period) + { + this->period = period; + periodChanged = true; + } + + delete this->adaptationSetStream; + this->adaptationSetStream = NULL; + + this->adaptationSetStream = new AdaptationSetStream(this->mpd, this->period, this->adaptationSet); + } + + this->representationStream = this->adaptationSetStream->getRepresentationStream(this->representation); + this->DownloadInitSegment(this->representation); + + if (periodChanged) + { + this->segmentNumber = 0; + this->CalculateSegmentOffset(); + } + LeaveCriticalSection(&this->monitorMutex); +} + +libdash::framework::adaptation::IAdaptationLogic* DASHReceiver::GetAdaptationLogic () +{ + return this->adaptationLogic; +} +dash::mpd::IRepresentation* DASHReceiver::GetRepresentation () +{ + return this->representation; +} +uint32_t DASHReceiver::CalculateSegmentOffset () +{ + if (mpd->GetType() == "static") + return 0; + + uint32_t firstSegNum = this->representationStream->getFirstSegmentNumber(); + uint32_t currSegNum = this->representationStream->getCurrentSegmentNumber(); + uint32_t startSegNum = currSegNum - 2*bufferSize; + + return (startSegNum > firstSegNum) ? startSegNum : firstSegNum; +} +void DASHReceiver::NotifySegmentDownloaded () +{ + this->observer->onSegmentDownloaded(); +} + +void DASHReceiver::NotifyBitrateChange(dash::mpd::IRepresentation *representation) +{ + if(this->representation != representation) + { + this->representation = representation; + this->SetRepresentation(this->period,this->adaptationSet,this->representation); + } +} +void DASHReceiver::DownloadInitSegment (IRepresentation* rep) +{ + if (this->InitSegmentExists(rep)) + return; + + MediaObject *initSeg = NULL; + initSeg = this->GetInitSegment(); + + if (initSeg) + { + initSeg->StartDownload(this->initConn); + this->initSegments[rep] = initSeg; + initSeg->WaitFinished(); + } +} +bool DASHReceiver::InitSegmentExists (IRepresentation* rep) +{ + if (this->initSegments.find(rep) != this->initSegments.end()) + return true; + + return false; +} + +void DASHReceiver::Notifybps (uint64_t bps) +{ + if(this->adaptationLogic) + { + if(this->withFeedBack) + { + this->adaptationLogic->bitrateUpdate(bps, this->segmentNumber); + } + } +} +void DASHReceiver::NotifyDLTime (double time) +{ + if(this->adaptationLogic) + { + if(this->withFeedBack) + { + this->adaptationLogic->dLTimeUpdate(time); + } + } +} + +void DASHReceiver::NotifyCheckedAdaptationLogic() +{ + this->adaptationLogic->checkedByDASHReceiver(); +} +//Is only called when this->adaptationLogic->IsBufferBased +void DASHReceiver::OnSegmentBufferStateChanged(uint32_t fillstateInPercent, int maxC) +{ + this->adaptationLogic->bufferUpdate(this->observer->getBufferLevel(), maxC); + this->bufferLevelAtUpdate = this->observer->getBufferLevel(); +} +void DASHReceiver::OnEOS(bool value) +{ + this->adaptationLogic->onEOS(value); +} + +bool DASHReceiver::PushBack(MediaObject *mediaObject) +{ + MediaObject *init = this->FindInitSegment(mediaObject->GetRepresentation()); + mediaObject->AddInitSegment(init); + //TODO the read should be in a function + + //Grab the infos for the analytics: bitrate, fps + dash::mpd::IRepresentation* datRep = mediaObject->GetRepresentation(); + uint32_t bitrate = 0; + int fps = 0; + uint32_t quality = 0; + bitrate = datRep->GetBandwidth(); + quality = datRep->GetHeight(); + fps = this->bufferLevelAtUpdate; + this->observer->notifyStatistics((int)this->segmentNumber - 1, bitrate, fps, quality); + + return(this->buffer->pushBack(mediaObject)); +} + +/* Thread that does the buffering of segments */ +void* DASHReceiver::DoBuffering (void *receiver) +{ + DASHReceiver *dashReceiver = (DASHReceiver *) receiver; + + dashReceiver->DownloadInitSegment(dashReceiver->GetRepresentation()); + + MediaObject *media = dashReceiver->GetNextSegment(); + dashReceiver->NotifyCheckedAdaptationLogic(); + media->SetDASHReceiver(dashReceiver); + std::chrono::time_point<std::chrono::system_clock> m_start_time = std::chrono::system_clock::now(); + while(media != NULL && dashReceiver->isBuffering) + { + //this is the case in PANDA + if(dashReceiver->isScheduledPaced) + { + double delay = std::chrono::duration_cast<duration_in_seconds>(std::chrono::system_clock::now() - m_start_time).count(); + Debug("delay: %f, target: %f\n", delay, dashReceiver->targetDownload); + if(delay < dashReceiver->targetDownload) + { + sleep(dashReceiver->targetDownload - delay); + } + } + m_start_time = std::chrono::system_clock::now(); + media->StartDownload(dashReceiver->conn); + + media->WaitFinished(); + bool canPush = dashReceiver->CanPush(); + if (canPush && !dashReceiver->PushBack(media)) + { + if(media) + { + delete(media); + } + media = NULL; + dashReceiver->threadComplete = true; + return NULL; + } + + dashReceiver->NotifySegmentDownloaded(); + media = dashReceiver->GetNextSegment(); + dashReceiver->NotifyCheckedAdaptationLogic(); + if(media) + media->SetDASHReceiver(dashReceiver); + } + + dashReceiver->buffer->setEOS(true); + dashReceiver->threadComplete = true; + return NULL; +} + +//can Push video to buffer in the renderer +bool DASHReceiver::CanPush () +{ + return this->observer->canPush(); +} +void DASHReceiver::ShouldAbort () +{ + Debug("DASH RECEIVER SEGMENT --\n"); + this->segmentNumber--; + Debug("DASH RECEIVER ABORT REQUEST\n"); +} + +void DASHReceiver::SetTargetDownloadingTime (double target) +{ + this->isScheduledPaced = true; + this->targetDownload = target; +} + +void DASHReceiver::SetBeta (float beta) +{ + this->beta = beta; +} + +void DASHReceiver::SetDrop (float drop) +{ + this->drop = drop; +} + + diff --git a/Input/DASHReceiver.h b/Input/DASHReceiver.h new file mode 100644 index 00000000..a2893b4d --- /dev/null +++ b/Input/DASHReceiver.h @@ -0,0 +1,129 @@ +/* + * DASHReceiver.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 LIBDASH_FRAMEWORK_INPUT_DASHRECEIVER_H_ +#define LIBDASH_FRAMEWORK_INPUT_DASHRECEIVER_H_ + +#include "libdash.h" +#include "IMPD.h" + +#include "../Input/MediaObject.h" +#include "IDASHReceiverObserver.h" +#include "../MPD/AdaptationSetStream.h" +#include "../MPD/IRepresentationStream.h" +#include "../Portable/MultiThreading.h" +#include "../Buffer/Buffer.h" +#include <chrono> +#include "ICNConnectionConsumerApi.h" + +namespace libdash +{ +namespace framework +{ +namespace adaptation +{ +class IAdaptationLogic; +} +namespace buffer +{ +class MediaObjectBuffer; +template <class T> +class Buffer; +} +namespace input +{ +class MediaObject; +class DASHReceiver +{ +public: + DASHReceiver(dash::mpd::IMPD *mpd, IDASHReceiverObserver *obs, buffer::Buffer<MediaObject> *buffer, uint32_t bufferSize, bool icnEnabled, double icnAlpha, float beta, float drop); + virtual ~DASHReceiver(); + + bool Start(); + void Stop(); + input::MediaObject* GetNextSegment(); + input::MediaObject* GetSegment(uint32_t segmentNumber); + input::MediaObject* GetInitSegment(); + input::MediaObject* FindInitSegment(dash::mpd::IRepresentation *representation); + uint32_t GetPosition(); + void SetPosition(uint32_t segmentNumber); + void SetLooping(bool isLoopinp); + void SetPositionInMsecs(uint32_t milliSecs); + dash::mpd::IRepresentation* GetRepresentation(); + void SetRepresentation(dash::mpd::IPeriod *period, + dash::mpd::IAdaptationSet *adaptationSet, + dash::mpd::IRepresentation *representation); + void SetAdaptationLogic(adaptation::IAdaptationLogic *_adaptationLogic); + libdash::framework::adaptation::IAdaptationLogic* GetAdaptationLogic(); + void NotifyQualityDownloading(uint32_t quality); + void Notifybps(uint64_t bps); + void NotifyDLTime(double time); + void NotifyBitrateChange(dash::mpd::IRepresentation *representation); + void OnSegmentBufferStateChanged(uint32_t fillstateInPercent, int maxC); + bool IsICN(); + void ShouldAbort(); + void OnEOS(bool value); + void SetTargetDownloadingTime(double); + void NotifyCheckedAdaptationLogic(); + bool threadComplete; + bool PushBack(MediaObject* media); + bool CanPush(); + void SetBeta(float beta); + void SetDrop(float drop); + +private: + float beta; + float drop; + bool withFeedBack; + bool isBufferBased; + std::map<dash::mpd::IRepresentation*, MediaObject*> initSegments; + libdash::framework::buffer::Buffer<MediaObject> *buffer; + IDASHReceiverObserver *observer; + dash::mpd::IMPD *mpd; + dash::mpd::IPeriod *period; + dash::mpd::IAdaptationSet *adaptationSet; + dash::mpd::IRepresentation *representation; + mpd::AdaptationSetStream *adaptationSetStream; + mpd::IRepresentationStream *representationStream; + uint32_t segmentNumber; + uint32_t positionInMsecs; + uint32_t segmentOffset; + uint32_t bufferSize; + mutable CRITICAL_SECTION monitorMutex; + mutable CRITICAL_SECTION monitorPausedMutex; + mutable CONDITION_VARIABLE paused; + bool isPaused; + bool isScheduledPaced; + bool isLooping; + double targetDownload; + double downloadingTime; + adaptation::IAdaptationLogic *adaptationLogic; + IICNConnection *conn; + IICNConnection *initConn; + THREAD_HANDLE bufferingThread; + bool isBuffering; + bool icn; + double icnAlpha; + int previousQuality; + int bufferLevelAtUpdate; + int readMax; + uint8_t *readBuffer; + uint32_t CalculateSegmentOffset(); + void NotifySegmentDownloaded(); + void DownloadInitSegment(dash::mpd::IRepresentation* rep); + bool InitSegmentExists(dash::mpd::IRepresentation* rep); + static void* DoBuffering(void *receiver); +}; +} +} +} + +#endif /* LIBDASH_FRAMEWORK_INPUT_DASHRECEIVER_H_ */ diff --git a/Input/ICNConnectionConsumerApi.cpp b/Input/ICNConnectionConsumerApi.cpp new file mode 100644 index 00000000..9de82908 --- /dev/null +++ b/Input/ICNConnectionConsumerApi.cpp @@ -0,0 +1,283 @@ +/* + * 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 ICNICPDOWNLOAD + +#include "ICNConnectionConsumerApi.h" + +#define DEFAULT_LIFETIME 250 +#define RETRY_TIMEOUTS 5 + +using namespace dash; +using namespace dash::network; +using namespace dash::metrics; +using namespace icnet; + +using std::bind; +using std::placeholders::_1; +using std::placeholders::_2; +using std::placeholders::_3; + +using duration_in_seconds = std::chrono::duration<double, std::ratio<1, 1> >; + + +namespace libdash { +namespace framework { +namespace input { +ICNConnectionConsumerApi::ICNConnectionConsumerApi(double alpha, float beta, float drop) : + m_recv_name(ccnx::Name()), + m_first(1), + m_isFinished(false), + sizeDownloaded (0), + cumulativeBytesReceived(0), + icnAlpha(alpha), + beta(beta), + drop(drop) +{ + gamma = 1; + this->speed = 0.0; + this->dnltime = 0.0; + this->deezData = NULL; + this->deezDataSize = 0; + this->datSize = 0; + this->dataPos = 0; + InitializeConditionVariable (&this->contentRetrieved); + InitializeCriticalSection (&this->monitorMutex); + + this->myConsumer = new ConsumerSocket(ccnx::Name(), TransportProtocolAlgorithms::RAAQM); + this->myConsumer->setSocketOption(RaaqmTransportOptions::GAMMA_VALUE, (int)gamma); + + bool configFile = false; + //CHECK if we are not going to override the configuration file. (if !autotune) + if(FILE *fp = fopen("/usr/etc/consumer.conf", "r")) + { + fclose(fp); + configFile = true; + } + if(!configFile) + { + qDebug("beta %f, drop %f", this->beta, this->drop); + this->myConsumer->setSocketOption(RaaqmTransportOptions::BETA_VALUE, this->beta); + this->myConsumer->setSocketOption(RaaqmTransportOptions::DROP_FACTOR, this->drop); + } + this->myConsumer->setSocketOption(RateEstimationOptions::RATE_ESTIMATION_OBSERVER, this); + this->myConsumer->setSocketOption(ConsumerCallbacksOptions::CONTENT_RETRIEVED, (ConsumerContentCallback) bind(&ICNConnectionConsumerApi::processPayload, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); + this->myConsumer->setSocketOption(ConsumerCallbacksOptions::CONTENT_OBJECT_TO_VERIFY, (ConsumerContentObjectVerificationCallback)bind(&ICNConnectionConsumerApi::onPacket, this, std::placeholders::_1, std::placeholders::_2)); +#ifdef NO_GUI + if(this->icnAlpha != 20) + this->icnRateBased = true; +#else + this->icnRateBased = true; +#endif + Debug("ICN class created\n"); + +} + +ICNConnectionConsumerApi::~ICNConnectionConsumerApi() { + delete this->myConsumer; + if(this->deezData) + { + free(this->deezData); + this->deezData = NULL; + } + DeleteConditionVariable (&this->contentRetrieved); + DeleteCriticalSection (&this->monitorMutex); +} + +void ICNConnectionConsumerApi::Init(IChunk *chunk) { + Debug("ICN Connection: STARTING\n"); + m_first = 1; + sizeDownloaded = 0; + m_name = "ccnx:/" + chunk->Host() + chunk->Path(); + m_isFinished = false; + + res = false; + dataPos = 0; + datSize = 0; + if(this->deezData) + { + memset(this->deezData, 0, this->deezDataSize); + } + + qDebug("ICN_Connection:\tINTIATED_to_name %s\n", m_name.c_str()); + qDebug("ICN_Connection:\tSTARTING DOWNLOAD %s\n", m_name.c_str()); +} + +void ICNConnectionConsumerApi::InitForMPD(const std::string& url) +{ + m_first = 1; + sizeDownloaded = 0; + + if(url.find("//") != std::string::npos) + { + int pos = url.find("//"); + char* myName = (char*)malloc(strlen(url.c_str()) - 1); + strncpy(myName, url.c_str(), pos + 1); + strncpy(myName + pos + 1, url.c_str() + pos + 2, strlen(url.c_str()) - pos - 2); + m_name = std::string(myName); + free(myName); + } + else + { + m_name = url; + } + m_isFinished = false; + + res = false; + dataPos = 0; + datSize = 0; + Debug("ICN_Connection:\tINTIATED_for_mpd %s\n", m_name.c_str()); +} + +int ICNConnectionConsumerApi::Read(uint8_t* data, size_t len, IChunk *chunk) +{ + return this->Read(data, len); +} + +int ICNConnectionConsumerApi::Read(uint8_t *data, size_t len) +{ + if(!res) + m_start_time = std::chrono::system_clock::now(); + + if(res) + { + if(this->dataPos == this->datSize) + { + this->dnltime = std::chrono::duration_cast<duration_in_seconds>(std::chrono::system_clock::now() - m_start_time).count(); + if(speed == 0 || !this->icnRateBased) + speed = (double) (sizeDownloaded * 8 / this->dnltime); + cumulativeBytesReceived += sizeDownloaded; + Debug("ICN_Connection:\tFINISHED DOWNLOADING %s Average_DL: %f size: %lu cumulative: %lu Throughput: %f\n", m_name.c_str(), speed, sizeDownloaded, cumulativeBytesReceived, (double) (sizeDownloaded * 8 / this->dnltime)); + return 0; + } + if((this->datSize - this->dataPos) > (int)len) + { + memcpy(data, this->deezData + this->dataPos, len); + this->dataPos += len; + sizeDownloaded += len; + return len; + } + else + { + assert(this->datSize - this->dataPos > 0); + memcpy(data, this->deezData + this->dataPos, this->datSize - this->dataPos); + int temp = this->datSize - this->dataPos; + this->dataPos += this->datSize - this->dataPos; + sizeDownloaded += temp; + return temp; + } + } + + Debug("will consume: %s\n", m_name.c_str()); + this->myConsumer->consume(m_name); + EnterCriticalSection(&this->monitorMutex); + + while(this->m_isFinished == false) + SleepConditionVariableCS(&this->contentRetrieved, &this->monitorMutex, INFINITE); + + assert(this->datSize != 0); + this->res = true; + LeaveCriticalSection(&this->monitorMutex); + if(this->datSize > (int)len) + { + memcpy(data, this->deezData, len); + this->dataPos += len; + sizeDownloaded += len; + return len; + } + else + { + memcpy(data, this->deezData, this->datSize); + this->dataPos += this->datSize; + sizeDownloaded += this->datSize; + return this->datSize; + } +} + +int ICNConnectionConsumerApi::Peek(uint8_t *data, size_t len, IChunk *chunk) { + return -1; +} + +bool ICNConnectionConsumerApi::onPacket(ConsumerSocket& c, const ContentObject& data) +{ + return true; +} + +void ICNConnectionConsumerApi::processPayload(ConsumerSocket& c, const uint8_t* buffer, size_t bufferSize) +{ + EnterCriticalSection(&this->monitorMutex); + if(this->deezData == NULL) + { + this->deezData = (char *)malloc(bufferSize*sizeof(uint8_t)); + this->deezDataSize = bufferSize; + } + else + { + if(bufferSize > this->deezDataSize) + { + this->deezData = (char *)realloc(this->deezData, bufferSize * (sizeof(uint8_t))); + this->deezDataSize = bufferSize; + } + } + memcpy(this->deezData, buffer, bufferSize*sizeof(uint8_t)); + this->m_isFinished = true; + this->datSize = (int) bufferSize; + WakeAllConditionVariable(&this->contentRetrieved); + LeaveCriticalSection(&this->monitorMutex); +} + +double ICNConnectionConsumerApi::GetAverageDownloadingSpeed() +{ + Debug("ICNConnection: DL speed is %f\n", this->speed); + return this->speed; +} + +double ICNConnectionConsumerApi::GetDownloadingTime() +{ + Debug("ICNConnection: DL time is %f\n", this->dnltime); + return this->dnltime; +} + +const std::vector<ITCPConnection *> &ICNConnectionConsumerApi::GetTCPConnectionList() const { + return tcpConnections; +} + +const std::vector<IHTTPTransaction *> &ICNConnectionConsumerApi::GetHTTPTransactionList() const { + return httpTransactions; +} + +void ICNConnectionConsumerApi::notifyStats(double winSize) +{ + this->speed = (winSize); // * 1000000 * 1400 * 8; + Debug("ICNConnection:\tNotificationICPDL\t%f\t%f\n", winSize, speed); +} + +void ICNConnectionConsumerApi::SetBeta(float beta) +{ + this->beta = beta; +} + + +void ICNConnectionConsumerApi::SetDrop(float drop) +{ + this->drop = drop; +} + +} /* namespace input */ +} /* namespace framework */ +} /* namespace libdash */ + + +#endif //NDEF ICNICPDOWNLOAD diff --git a/Input/ICNConnectionConsumerApi.h b/Input/ICNConnectionConsumerApi.h new file mode 100644 index 00000000..a0343443 --- /dev/null +++ b/Input/ICNConnectionConsumerApi.h @@ -0,0 +1,138 @@ +/* + * 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 QTPLAYER_INPUT_ICNCONNECTIONCONSUMERAPI_H_ +#define QTPLAYER_INPUT_ICNCONNECTIONCONSUMERAPI_H_ + +#include <QMessageLogger> +#include "../Portable/Networking.h" +#include "IICNConnection.h" +#include "../debug.h" + +#include <sys/types.h> +#include <string> +#include <stdint.h> +#include <iostream> +#include <sstream> +#include <chrono> +#include <inttypes.h> +#include <stdlib.h> +#include <stdarg.h> +#include <algorithm> +#include <icnet/icnet_socket_consumer.h> +#include <icnet/icnet_download_observer.h> +#include <future> +#include <inttypes.h> +#include <time.h> +#include <limits.h> +#include <errno.h> + +#include "../Portable/MultiThreading.h" +#include <boost/exception/diagnostic_information.hpp> + +//logging purpose +#include <chrono> +#include <stdarg.h> + + +namespace libdash { +namespace framework { +namespace input { + +class ICNConnectionConsumerApi : public IICNConnection, public icnet::IcnObserver { +public: + ICNConnectionConsumerApi(double alpha, float beta, float drop); + virtual ~ICNConnectionConsumerApi(); + + virtual void Init(dash::network::IChunk *chunk); + + void InitForMPD(const std::string& url); + + virtual int Read(uint8_t *data, size_t len, dash::network::IChunk *chunk); + + int Read(uint8_t *data, size_t len); + + virtual int Peek(uint8_t *data, size_t len, dash::network::IChunk *chunk); + + virtual double GetAverageDownloadingSpeed(); + + virtual double GetDownloadingTime(); + + void processPayload(icnet::ConsumerSocket& , const uint8_t*, size_t); + + bool onPacket(icnet::ConsumerSocket& , const icnet::ContentObject&); + + const std::vector<dash::metrics::ITCPConnection *> &GetTCPConnectionList() const; + + const std::vector<dash::metrics::IHTTPTransaction *> &GetHTTPTransactionList() const; + virtual void SetBeta(float beta); + virtual void SetDrop(float drop); + virtual void notifyStats(double throughput); + +private: + float beta; + float drop; + uint64_t i_chunksize; + int i_lifetime; + int i_missed_co; + /**< number of content objects we missed in ICNBlock */ + + std::string m_name; + icnet::ccnx::Name m_recv_name; + icnet::ccnx::Portal m_portal; + int m_first; + bool m_isFinished; + uint64_t m_nextSeg; + + double icnAlpha; + bool icnRateBased; + + bool allow_stale; + int sysTimeout; + unsigned InitialMaxwindow; + unsigned int timer; + double drop_factor; + double p_min; + unsigned int gamma; + unsigned int samples; + unsigned int nchunks; // XXX chunks=-1 means: download the whole file! + bool output; + bool report_path; + icnet::ConsumerSocket* myConsumer; + bool res; + std::vector<char> mdata; + char* deezData; + int deezDataSize; + int datSize; + int dataPos; + int firstChunk; + double speed; // in bps + double dnltime; //in seconds + uint64_t sizeDownloaded; + std::chrono::time_point<std::chrono::system_clock> m_start_time; + + std::vector<dash::metrics::ITCPConnection *> tcpConnections; + std::vector<dash::metrics::IHTTPTransaction *> httpTransactions; + uint64_t cumulativeBytesReceived; + + mutable CRITICAL_SECTION monitorMutex; + mutable CONDITION_VARIABLE contentRetrieved; +}; + +} /* namespace input */ +} /* namespace framework */ +} /* namespace libdash */ + +#endif /* QTPLAYER_INPUT_ICNCONNECTIONCONSUMERAPI_H_ */ diff --git a/Input/IDASHManagerObserver.h b/Input/IDASHManagerObserver.h new file mode 100644 index 00000000..c5df8fe9 --- /dev/null +++ b/Input/IDASHManagerObserver.h @@ -0,0 +1,41 @@ +/* + * IDASHManagerObserver.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 LIBDASH_FRAMEWORK_INPUT_IDASHMANAGEROBSERVER_H_ +#define LIBDASH_FRAMEWORK_INPUT_IDASHMANAGEROBSERVER_H_ + +#include <QImage> +#include "../Buffer/Buffer.h" + +namespace libdash +{ +namespace framework +{ +namespace input +{ +class IDASHManagerObserver +{ +public: + virtual ~IDASHManagerObserver() {} + + virtual void addFrame(QImage *frame) = 0; + virtual void setEOS(bool value)= 0; + + virtual void onSegmentBufferStateChanged(uint32_t fillstateInPercent, int maxC) = 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 /* LIBDASH_FRAMEWORK_INPUT_IDASHMANAGEROBSERVER_H_ */ diff --git a/Input/IDASHReceiverObserver.h b/Input/IDASHReceiverObserver.h new file mode 100644 index 00000000..0a334aa2 --- /dev/null +++ b/Input/IDASHReceiverObserver.h @@ -0,0 +1,35 @@ +/* + * IDASHReceiverObserver.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 LIBDASH_FRAMEWORK_INPUT_IDASHRECEIVEROBSERVER_H_ +#define LIBDASH_FRAMEWORK_INPUT_IDASHRECEIVEROBSERVER_H_ + +namespace libdash +{ +namespace framework +{ +namespace input +{ +class IDASHReceiverObserver +{ +public: + virtual ~IDASHReceiverObserver() {} + + virtual void onSegmentDownloaded() = 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 /* LIBDASH_FRAMEWORK_INPUT_IDASHRECEIVEROBSERVER_H_ */ diff --git a/Input/IDataReceiver.h b/Input/IDataReceiver.h new file mode 100644 index 00000000..15d7e0f6 --- /dev/null +++ b/Input/IDataReceiver.h @@ -0,0 +1,34 @@ +/* + * IDataReceiver.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 LIBDASH_FRAMEWORK_INPUT_IDATARECEIVER_H_ +#define LIBDASH_FRAMEWORK_INPUT_IDATARECEIVER_H_ + +#include <stdint.h> + +namespace libdash +{ +namespace framework +{ +namespace input +{ +class IDataReceiver +{ +public: + virtual ~IDataReceiver() {} + + virtual int read(uint8_t *buf, int buf_size ) = 0; + virtual bool isAudio() = 0; +}; +} +} +} +#endif /* LIBDASH_FRAMEWORK_INPUT_IDATARECEIVER_H_ */ diff --git a/Input/IICNConnection.h b/Input/IICNConnection.h new file mode 100644 index 00000000..260f0450 --- /dev/null +++ b/Input/IICNConnection.h @@ -0,0 +1,44 @@ +/* + * 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 QTPLAYER_INPUT_IICNCONNECTION_H_ +#define QTPLAYER_INPUT_IICNCONNECTION_H_ + +#include "IConnection.h" +#include "IChunk.h" + + +namespace libdash { +namespace framework { + +namespace input { + +class IICNConnection : public dash::network::IConnection { + +public: + virtual ~IICNConnection(){}; + + virtual int Read(uint8_t* data, size_t len) = 0; + virtual void Init(dash::network::IChunk *chunk) = 0; + virtual void InitForMPD(const std::string&) = 0; + virtual void SetBeta(float beta) = 0; + virtual void SetDrop(float drop) = 0; +}; +} +} +} + + +#endif // QTPLAYER_INPUT_IICNCONNECTION_H_ diff --git a/Input/MediaObject.cpp b/Input/MediaObject.cpp new file mode 100644 index 00000000..ae6b9f6b --- /dev/null +++ b/Input/MediaObject.cpp @@ -0,0 +1,175 @@ +/* + * MediaObject.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 "MediaObject.h" +#include <inttypes.h> +#include<stdio.h> + +using namespace libdash::framework::input; +using namespace dash::mpd; +using namespace dash::network; +using namespace dash::metrics; + +MediaObject::MediaObject(ISegment *segment, IRepresentation *rep, bool withFeedBack) : + segment (segment), + rep (rep), + withFeedBack (withFeedBack) +{ + this->initSeg = NULL; + InitializeConditionVariable (&this->stateChanged); + InitializeCriticalSection (&this->stateLock); +} + +MediaObject::~MediaObject() +{ + if(this->state == IN_PROGRESS) + { + this->segment->AbortDownload(); + this->OnDownloadStateChanged(ABORTED); + } + this->segment->DetachDownloadObserver(this); + this->WaitFinished(); + + DeleteConditionVariable (&this->stateChanged); + DeleteCriticalSection (&this->stateLock); + delete this->segment; + this->segment = NULL; +} + +void MediaObject::SetFeedBack(bool flag) +{ + this->withFeedBack = flag; +} + +void MediaObject::AddInitSegment(MediaObject* initSeg) +{ + this->initSeg = initSeg; +} + +int MediaObject::ReadInitSegment(uint8_t* data, size_t len) +{ + if(this->initSeg) + return this->initSeg->Peek(data,len); + else + return 0; +} + +bool MediaObject::StartDownload() +{ + this->segment->AttachDownloadObserver(this); + return this->segment->StartDownload(); +} + +bool MediaObject::StartDownload(IICNConnection* conn) +{ + if(conn == NULL) + return this->StartDownload(); + + conn->Init(this->segment); + + this->segment->AttachDownloadObserver(this); + return this->segment->StartDownload(conn); +} + +const char* MediaObject::GetPath() +{ + return ((IChunk*)this->segment)->Path().c_str(); +} + +void MediaObject::AbortDownload() +{ + this->segment->AbortDownload(); + this->OnDownloadStateChanged(ABORTED); +} + +void MediaObject::WaitFinished() +{ + EnterCriticalSection(&this->stateLock); + + while(this->state != COMPLETED && this->state != ABORTED){ + SleepConditionVariableCS(&this->stateChanged, &this->stateLock, INFINITE); + } + + LeaveCriticalSection(&this->stateLock); + if(this->state != ABORTED) + { + if(this->withFeedBack && this->dashReceiver) + { + this->dashReceiver->Notifybps(this->bps); + this->dashReceiver->NotifyDLTime(this->dnltime); + } + } +} + +int MediaObject::Read(uint8_t *data, size_t len) +{ + return this->segment->Read(data, len); +} + +int MediaObject::Peek(uint8_t *data, size_t len) +{ + return this->segment->Peek(data, len); +} + +int MediaObject::Peek(uint8_t *data, size_t len, size_t offset) +{ + return this->segment->Peek(data, len, offset); +} + +IRepresentation* MediaObject::GetRepresentation() +{ + return this->rep; +} + +ISegment* MediaObject::GetSegment() +{ + return this->segment; +} + +void MediaObject::OnDownloadTimeChanged(double dnltime) +{ + this->dnltime = dnltime; +} + +void MediaObject::OnDownloadStateChanged(DownloadState state) +{ + EnterCriticalSection(&this->stateLock); + + this->state = state; + + WakeAllConditionVariable(&this->stateChanged); + LeaveCriticalSection(&this->stateLock); +} + +void MediaObject::OnDownloadRateChanged(uint64_t bitsPerSecond) +{ + this->bps = bitsPerSecond; +} + +void MediaObject::SetDASHReceiver(input::DASHReceiver *_dashReceiver) +{ + this->dashReceiver = _dashReceiver; +} + +void MediaObject::SetAdaptationLogic(adaptation::IAdaptationLogic *_adaptationLogic) +{ + this->adaptationLogic = _adaptationLogic; +} + +const std::vector<ITCPConnection *>& MediaObject::GetTCPConnectionList() const +{ + return this->segment->GetTCPConnectionList(); +} + +const std::vector<IHTTPTransaction *>& MediaObject::GetHTTPTransactionList () const +{ + return this->segment->GetHTTPTransactionList(); +} diff --git a/Input/MediaObject.h b/Input/MediaObject.h new file mode 100644 index 00000000..9d5c7826 --- /dev/null +++ b/Input/MediaObject.h @@ -0,0 +1,78 @@ +/* + * MediaObject.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 LIBDASH_FRAMEWORK_INPUT_MEDIAOBJECT_H_ +#define LIBDASH_FRAMEWORK_INPUT_MEDIAOBJECT_H_ + +#include "../Adaptation/IAdaptationLogic.h" +#include "IMPD.h" +#include "IDownloadObserver.h" +#include "IDASHMetrics.h" +#include "../Portable/MultiThreading.h" +#include "ICNConnectionConsumerApi.h" + +namespace libdash +{ +namespace framework +{ +namespace adaptation +{ +class IAdaptationLogic; +} +namespace input +{ +class DASHReceiver; +class MediaObject : public dash::network::IDownloadObserver, public dash::metrics::IDASHMetrics +{ +public: + MediaObject(dash::mpd::ISegment *segment, dash::mpd::IRepresentation *rep, bool withFeedBack = false); + virtual ~MediaObject(); + + bool StartDownload(); + bool StartDownload(IICNConnection* conn); + void AbortDownload(); + void WaitFinished(); + int Read(uint8_t *data, size_t len); + int Peek(uint8_t *data, size_t len); + int Peek(uint8_t *data, size_t len, size_t offset); + dash::mpd::IRepresentation* GetRepresentation(); + dash::mpd::ISegment* GetSegment(); + const char* GetPath(); + void SetFeedBack(bool flag); + virtual void OnDownloadStateChanged(dash::network::DownloadState state); + virtual void OnDownloadRateChanged(uint64_t bytesDownloaded); //Here the bytesDownloaded is in fact the bitrate bps + virtual void OnDownloadTimeChanged(double dnltime); + + void AddInitSegment(MediaObject* initSeg); + int ReadInitSegment(uint8_t* data, size_t len); + const std::vector<dash::metrics::ITCPConnection *>& GetTCPConnectionList() const; + const std::vector<dash::metrics::IHTTPTransaction *>& GetHTTPTransactionList() const; + void SetAdaptationLogic(framework::adaptation::IAdaptationLogic *_adaptationLogic); + void SetDASHReceiver(input::DASHReceiver *_dashReceiver); + +private: + dash::mpd::ISegment *segment; + MediaObject *initSeg; + dash::mpd::IRepresentation *rep; + dash::network::DownloadState state; + uint64_t bps; + bool withFeedBack; + double dnltime; + input::DASHReceiver *dashReceiver; + adaptation::IAdaptationLogic *adaptationLogic; + mutable CRITICAL_SECTION stateLock; + mutable CONDITION_VARIABLE stateChanged; +}; +} +} +} + +#endif /* LIBDASH_FRAMEWORK_INPUT_MEDIAOBJECT_H_ */ |