From 0e275345e28c34f2c6b91a75f44ac93034ae477c Mon Sep 17 00:00:00 2001 From: Jacques Samain Date: Tue, 25 Jul 2017 15:32:54 +0200 Subject: Handling live MPDs with variable segments duration Change-Id: I074d8863a9afb47815e47bf663b87e7f663890b9 Signed-off-by: Jacques Samain --- Adaptation/Bola.cpp | 8 ++++---- Input/DASHReceiver.cpp | 9 ++++----- Input/DASHReceiver.h | 6 +++--- Input/MediaObject.cpp | 16 +++++++++++++--- Input/MediaObject.h | 15 +++++++++------ MPD/AbstractRepresentationStream.h | 2 +- MPD/IRepresentationStream.h | 2 +- MPD/MPDWrapper.cpp | 9 +++++++-- MPD/SegmentListStream.cpp | 13 +++++++++++-- MPD/SegmentListStream.h | 3 ++- MPD/SegmentTemplateStream.cpp | 22 +++++++++++++++------- MPD/SegmentTemplateStream.h | 3 ++- MPD/SingleMediaSegmentStream.cpp | 2 +- MPD/SingleMediaSegmentStream.h | 2 +- Managers/MultimediaManager.cpp | 1 - UI/DASHPlayerNoGUI.cpp | 2 ++ UI/ViperGui.cpp | 4 ++-- 17 files changed, 78 insertions(+), 41 deletions(-) diff --git a/Adaptation/Bola.cpp b/Adaptation/Bola.cpp index f7acc72e..470d22e8 100644 --- a/Adaptation/Bola.cpp +++ b/Adaptation/Bola.cpp @@ -50,7 +50,8 @@ using duration_in_seconds = std::chrono::duration >; BolaAdaptation::BolaAdaptation(viper::managers::StreamType type, MPDWrapper *mpdWrapper, struct AdaptationParameters *params) : AbstractAdaptationLogic (type, mpdWrapper) { - this->bufferMaxSizeSeconds =(double) params->segmentBufferSize * params->segmentDuration; + this->segmentDuration = params->segmentDuration; + this->bufferMaxSizeSeconds =(double) params->segmentBufferSize * this->segmentDuration; this->alphaRate = params->Bola_Alpha; this->bufferTargetSeconds = params->Bola_bufferTargetSeconds; @@ -86,10 +87,9 @@ BolaAdaptation::BolaAdaptation(viper::managers::StreamType type, MPDWrapper *mpd // return 0; // Check if exit with a message is necessary } - // Check if the following is correct XXX Maybe useless this->totalDuration = TimeResolver::getDurationInSec(this->mpdWrapper->getMediaPresentationDuration()); -// this->segmentDuration = (double) (representations.at(0)->GetSegmentTemplate()->GetDuration() / representations.at(0)->GetSegmentTemplate()->GetTimescale() ); - this->segmentDuration = 2.0; + if(!(this->segmentDuration)) + this->segmentDuration = 2.0; Debug("Total Duration - BOLA:\t%f\nSegment Duration - BOLA:\t%f\n",this->totalDuration, this->segmentDuration); // if not correct --> segmentDuration = 2.0; diff --git a/Input/DASHReceiver.cpp b/Input/DASHReceiver.cpp index 59514e57..74415bfa 100644 --- a/Input/DASHReceiver.cpp +++ b/Input/DASHReceiver.cpp @@ -141,7 +141,7 @@ MediaObject* DASHReceiver::GetInitSegmentWithoutLock () return this->mpdWrapper->getInitSegmentWithoutLock(type); } -MediaObject* DASHReceiver::FindInitSegment (int representation) +MediaObject* DASHReceiver::FindInitSegment (std::string representation) { if (!this->InitSegmentExists(representation)) return NULL; @@ -192,7 +192,7 @@ void DASHReceiver::NotifySegmentDownloaded () void DASHReceiver::DownloadInitSegmentWithoutLock () { - int rep = atoi(this->mpdWrapper->getRepresentationIDWithoutLock(type).c_str()); + std::string rep = this->mpdWrapper->getRepresentationIDWithoutLock(type); if (this->InitSegmentExists(rep)) return; @@ -209,7 +209,7 @@ void DASHReceiver::DownloadInitSegmentWithoutLock () void DASHReceiver::DownloadInitSegment () { - int rep = atoi(this->mpdWrapper->getRepresentationID(type).c_str()); + std::string rep = this->mpdWrapper->getRepresentationID(type); if (this->InitSegmentExists(rep)) return; @@ -224,7 +224,7 @@ void DASHReceiver::DownloadInitSegment () } } -bool DASHReceiver::InitSegmentExists (int rep) +bool DASHReceiver::InitSegmentExists (std::string rep) { if (this->initSegments.find(rep) != this->initSegments.end()) return true; @@ -310,7 +310,6 @@ void* DASHReceiver::DoBuffering (void *recei } m_start_time = std::chrono::system_clock::now(); media->StartDownload(dashReceiver->conn); - media->WaitFinished(); bool canPush = dashReceiver->CanPush(); if (canPush && !dashReceiver->PushBack(media)) diff --git a/Input/DASHReceiver.h b/Input/DASHReceiver.h index ee2df388..a6db0382 100644 --- a/Input/DASHReceiver.h +++ b/Input/DASHReceiver.h @@ -57,7 +57,7 @@ public: input::MediaObject* GetSegment(uint32_t segmentNumber); input::MediaObject* GetInitSegment(); input::MediaObject* GetInitSegmentWithoutLock(); - input::MediaObject* FindInitSegment(int representation); + input::MediaObject* FindInitSegment(std::string representation); uint32_t GetPosition(); void SetPosition(uint32_t segmentNumber); void SetLooping(bool isLoopinp); @@ -86,7 +86,7 @@ private: float drop; bool withFeedBack; bool isBufferBased; - std::map initSegments; + std::map initSegments; libdash::framework::buffer::Buffer *buffer; IDASHReceiverObserver *observer; libdash::framework::mpd::MPDWrapper *mpdWrapper; @@ -120,7 +120,7 @@ private: void NotifySegmentDownloaded(); void DownloadInitSegment(); void DownloadInitSegmentWithoutLock(); - bool InitSegmentExists(int rep); + bool InitSegmentExists(std::string rep); static void* DoBuffering(void *receiver); }; } diff --git a/Input/MediaObject.cpp b/Input/MediaObject.cpp index b2dde357..2f4e0044 100644 --- a/Input/MediaObject.cpp +++ b/Input/MediaObject.cpp @@ -28,7 +28,7 @@ MediaObject::MediaObject(ISegment *segment, IRepresentation *rep, bool withFeedB InitializeCriticalSection (&this->stateLock); this->representationBandwidth = rep->GetBandwidth(); this->representationHeight = rep->GetHeight(); - this->representationId = atoi(rep->GetId().c_str()); + this->representationId = rep->GetId(); } MediaObject::~MediaObject() @@ -57,12 +57,22 @@ uint32_t MediaObject::GetRepresentationHeight() return this->representationHeight; } -int MediaObject::GetRepresentationID() +std::string MediaObject::GetRepresentationID() { return this->representationId; } -void MediaObject::SetFeedBack(bool flag) +uint64_t MediaObject::GetSegmentDuration() +{ + return this->segmentDuration; +} + +void MediaObject::SetSegmentDuration(uint64_t segDuration) +{ + this->segmentDuration = segDuration; +} + +void MediaObject::SetFeedBack(bool flag) { this->withFeedBack = flag; } diff --git a/Input/MediaObject.h b/Input/MediaObject.h index 1edd69af..24c2995b 100644 --- a/Input/MediaObject.h +++ b/Input/MediaObject.h @@ -59,23 +59,26 @@ public: void SetDASHReceiver(input::DASHReceiver *_dashReceiver); uint32_t GetRepresentationBandwidth(); uint32_t GetRepresentationHeight(); - int GetRepresentationID(); + std::string GetRepresentationID(); + uint64_t GetSegmentDuration(); + void SetSegmentDuration(uint64_t segmentDuration); private: dash::mpd::ISegment *segment; MediaObject *initSeg; dash::mpd::IRepresentation *rep; dash::network::DownloadState state; - uint64_t bps; - bool withFeedBack; + uint64_t bps; + bool withFeedBack; double dnltime; input::DASHReceiver *dashReceiver; adaptation::IAdaptationLogic *adaptationLogic; mutable CRITICAL_SECTION stateLock; mutable CONDITION_VARIABLE stateChanged; - uint32_t representationBandwidth; - uint32_t representationHeight; - int representationId; + uint32_t representationBandwidth; + uint32_t representationHeight; + std::string representationId; + uint64_t segmentDuration; }; } } diff --git a/MPD/AbstractRepresentationStream.h b/MPD/AbstractRepresentationStream.h index 113720ed..da847c3c 100644 --- a/MPD/AbstractRepresentationStream.h +++ b/MPD/AbstractRepresentationStream.h @@ -43,7 +43,7 @@ public: virtual dash::mpd::ISegment* getInitializationSegment() = 0; virtual dash::mpd::ISegment* getIndexSegment(size_t segmentNumber) = 0; - virtual dash::mpd::ISegment* getMediaSegment(size_t segmentNumber) = 0; + virtual dash::mpd::ISegment* getMediaSegment(size_t segmentNumber, uint64_t& segmentDuration) = 0; virtual dash::mpd::ISegment* getBitstreamSwitchingSegment() = 0; virtual RepresentationStreamType getStreamType() = 0; diff --git a/MPD/IRepresentationStream.h b/MPD/IRepresentationStream.h index bf8b08c4..124216ba 100644 --- a/MPD/IRepresentationStream.h +++ b/MPD/IRepresentationStream.h @@ -35,7 +35,7 @@ public: virtual dash::mpd::ISegment* getInitializationSegment() = 0; virtual dash::mpd::ISegment* getIndexSegment(size_t segmentNumber) = 0; - virtual dash::mpd::ISegment* getMediaSegment(size_t segmentNumber) = 0; + virtual dash::mpd::ISegment* getMediaSegment(size_t segmentNumber, uint64_t& segmentDuration) = 0; virtual dash::mpd::ISegment* getBitstreamSwitchingSegment() = 0; virtual RepresentationStreamType getStreamType() = 0; virtual uint32_t getSize() = 0; diff --git a/MPD/MPDWrapper.cpp b/MPD/MPDWrapper.cpp index 20d4aa5e..c7bdee9f 100644 --- a/MPD/MPDWrapper.cpp +++ b/MPD/MPDWrapper.cpp @@ -645,10 +645,13 @@ MediaObject* MPDWrapper::getNextSegment (viper::managers::StreamType type, bool representationStream = representations->find(representation)->second; } } - seg = representationStream->getMediaSegment(segmentNumber); + uint64_t segDuration = 0; + //Returns the segmentDuration in milliseconds + seg = representationStream->getMediaSegment(segmentNumber, segDuration); if(seg != NULL) { MediaObject *media = new MediaObject(seg, representation, withFeedBack); + media->SetSegmentDuration(segDuration); segmentNumber++; switch(type) { @@ -696,10 +699,12 @@ MediaObject* MPDWrapper::getSegment (viper::managers::StreamType type, uint32_t LeaveCriticalSection(&this->monitorMutex); return NULL; } - seg = representationStream->getMediaSegment(segNum); + uint64_t segDuration =0; + seg = representationStream->getMediaSegment(segNum, segDuration); if(seg != NULL) { MediaObject *media = new MediaObject(seg, representation); + media->SetSegmentDuration(segDuration); LeaveCriticalSection(&this->monitorMutex); return media; } diff --git a/MPD/SegmentListStream.cpp b/MPD/SegmentListStream.cpp index c3530086..86d36e68 100644 --- a/MPD/SegmentListStream.cpp +++ b/MPD/SegmentListStream.cpp @@ -53,11 +53,15 @@ ISegment* SegmentListStream::getIndexSegment(size_t segmentNumber) return NULL; } -ISegment* SegmentListStream::getMediaSegment(size_t segmentNumber) +ISegment* SegmentListStream::getMediaSegment(size_t segmentNumber, uint64_t& segmentDuration) { if (this->segmentList->GetSegmentURLs().size() > segmentNumber) + { + uint32_t duration = representation->GetSegmentList()->GetDuration(); + uint32_t timescale = representation->GetSegmentList()->GetTimescale(); + segmentDuration = (uint64_t)(((float)duration/(float)timescale) * 1000); return this->segmentList->GetSegmentURLs().at(segmentNumber)->ToMediaSegment(this->baseUrls); - + } return NULL; } @@ -93,6 +97,11 @@ ISegmentList* SegmentListStream::findSegmentList() return NULL; } +uint32_t SegmentListStream::getTimescale () +{ + return this->segmentList->GetTimescale(); +} + uint32_t SegmentListStream::getAverageSegmentDuration() { /* TODO calculate average segment durations for SegmentTimeline */ diff --git a/MPD/SegmentListStream.h b/MPD/SegmentListStream.h index 264ac9cc..589896ff 100644 --- a/MPD/SegmentListStream.h +++ b/MPD/SegmentListStream.h @@ -33,11 +33,12 @@ public: virtual dash::mpd::ISegment* getInitializationSegment(); virtual dash::mpd::ISegment* getIndexSegment(size_t segmentNumber); - virtual dash::mpd::ISegment* getMediaSegment(size_t segmentNumber); + virtual dash::mpd::ISegment* getMediaSegment(size_t segmentNumber, uint64_t& segmentDuration); virtual dash::mpd::ISegment* getBitstreamSwitchingSegment(); virtual RepresentationStreamType getStreamType(); virtual uint32_t getSize(); virtual uint32_t getAverageSegmentDuration(); + virtual uint32_t getTimescale(); private: dash::mpd::ISegmentList *findSegmentList(); diff --git a/MPD/SegmentTemplateStream.cpp b/MPD/SegmentTemplateStream.cpp index ee51cf07..50801896 100644 --- a/MPD/SegmentTemplateStream.cpp +++ b/MPD/SegmentTemplateStream.cpp @@ -64,16 +64,19 @@ ISegment* SegmentTemplateStream::getIndexSegment(size_t segmentNumber) this->segmentTemplate->GetStartNumber() + segmentNumber); } -ISegment* SegmentTemplateStream::getMediaSegment(size_t segmentNumber) +ISegment* SegmentTemplateStream::getMediaSegment(size_t segmentNumber, uint64_t& segmentDuration) { /* time-based template */ if (this->segmentTemplate->GetSegmentTimeline()) {//Get the one at segmentNumber - if(this->segmentStartTimes.size() > segmentNumber) - return this->segmentTemplate->GetMediaSegmentFromTime(baseUrls, representation->GetId(), representation->GetBandwidth(), this->segmentStartTimes.at(segmentNumber)); - else - return NULL; - + if(this->segmentStartTimes.size() > segmentNumber) + { + segmentDuration = (uint64_t)(((float)this->segmentDurationTimes.at(segmentNumber)/(float)this->getTimescale()) * 1000); + return this->segmentTemplate->GetMediaSegmentFromTime(baseUrls, representation->GetId(), representation->GetBandwidth(), this->segmentStartTimes.at(segmentNumber)); + } + else + return NULL; + //The following is to be used if you wish to start directly from the right time /* { if(this->inSync) @@ -110,6 +113,9 @@ ISegment* SegmentTemplateStream::getMediaSegment(size_t segmentNumber) } /* number-based template */ + uint32_t duration = representation->GetSegmentTemplate()->GetDuration(); + uint32_t timescale = representation->GetSegmentTemplate()->GetTimescale(); + segmentDuration = (uint64_t)(((float)duration/(float)timescale) * 1000); return this->segmentTemplate->GetMediaSegmentFromNumber(baseUrls, representation->GetId(), representation->GetBandwidth(), this->segmentTemplate->GetStartNumber() + segmentNumber); @@ -199,6 +205,7 @@ void SegmentTemplateStream::calculateSegmentStartTimes() if (segStartTime > 0) { this->segmentStartTimes.push_back(segStartTime + segDuration * j); + this->segmentDurationTimes.push_back(segDuration); } else { @@ -209,6 +216,7 @@ void SegmentTemplateStream::calculateSegmentStartTimes() else { this->segmentStartTimes.push_back(segStartTime); + this->segmentDurationTimes.push_back(segDuration); } } this->averageDuration = totalDuration / numOfTimelines; @@ -227,7 +235,7 @@ size_t SegmentTemplateStream::getSegmentNumber(uint64_t time) size_t i; for(i = 0; i < this->segmentStartTimes.size(); i ++) { - if(time <= this->segmentStartTimes.at(i)) + if(time < this->segmentStartTimes.at(i)) { break; } diff --git a/MPD/SegmentTemplateStream.h b/MPD/SegmentTemplateStream.h index 0bd0ad13..8485b56b 100644 --- a/MPD/SegmentTemplateStream.h +++ b/MPD/SegmentTemplateStream.h @@ -34,7 +34,7 @@ public: virtual dash::mpd::ISegment* getInitializationSegment(); virtual dash::mpd::ISegment* getIndexSegment(size_t segmentNumber); - virtual dash::mpd::ISegment* getMediaSegment(size_t segmentNumber); + virtual dash::mpd::ISegment* getMediaSegment(size_t segmentNumber, uint64_t& segmentDuration); virtual dash::mpd::ISegment* getBitstreamSwitchingSegment(); virtual RepresentationStreamType getStreamType(); virtual uint32_t getSize(); @@ -49,6 +49,7 @@ private: dash::mpd::ISegmentTemplate *segmentTemplate; std::vector segmentStartTimes; + std::vector segmentDurationTimes; uint32_t averageDuration; bool inSync; uint32_t currentSegment; diff --git a/MPD/SingleMediaSegmentStream.cpp b/MPD/SingleMediaSegmentStream.cpp index 39301928..3eccbefe 100644 --- a/MPD/SingleMediaSegmentStream.cpp +++ b/MPD/SingleMediaSegmentStream.cpp @@ -51,7 +51,7 @@ ISegment* SingleMediaSegmentStream::getIndexSegment(size_t segmentNumber) return NULL; } -ISegment* SingleMediaSegmentStream::getMediaSegment(size_t segmentNumber) +ISegment* SingleMediaSegmentStream::getMediaSegment(size_t segmentNumber, uint64_t& segmentDuration) { /* segmentNumber equals the desired BaseUrl */ if (this->representation->GetBaseURLs().size() > segmentNumber) diff --git a/MPD/SingleMediaSegmentStream.h b/MPD/SingleMediaSegmentStream.h index e619a7f8..44fead38 100644 --- a/MPD/SingleMediaSegmentStream.h +++ b/MPD/SingleMediaSegmentStream.h @@ -31,7 +31,7 @@ public: virtual dash::mpd::ISegment* getInitializationSegment(); virtual dash::mpd::ISegment* getIndexSegment(size_t segmentNumber); - virtual dash::mpd::ISegment* getMediaSegment(size_t segmentNumber); + virtual dash::mpd::ISegment* getMediaSegment(size_t segmentNumber, uint64_t& segmentDuration); virtual dash::mpd::ISegment* getBitstreamSwitchingSegment(); virtual RepresentationStreamType getStreamType(); diff --git a/Managers/MultimediaManager.cpp b/Managers/MultimediaManager.cpp index 18061238..997fc6de 100644 --- a/Managers/MultimediaManager.cpp +++ b/Managers/MultimediaManager.cpp @@ -659,7 +659,6 @@ void* MultimediaManager::pushVideo(void *data) { MultimediaManager *manager = (MultimediaManager*) data; libdash::framework::input::MediaObject *segment = manager->videoStream->getSegment(); - int segmentDurationInMs = (int)manager->getSegmentDuration(); while(manager->isVideoRendering) { if (segment) diff --git a/UI/DASHPlayerNoGUI.cpp b/UI/DASHPlayerNoGUI.cpp index d212b556..2195b88a 100644 --- a/UI/DASHPlayerNoGUI.cpp +++ b/UI/DASHPlayerNoGUI.cpp @@ -89,6 +89,8 @@ DASHPlayerNoGUI::DASHPlayerNoGUI(int argc, char ** argv, pthread_cond_t *mainCon webSocketService.start(); this->parameterAdaptation->segmentDuration = this->mpdWrapper->onFirstDownloadMPD(NULL); this->multimediaManager->setSegmentDuration(this->parameterAdaptation->segmentDuration); + //should be in seconds + this->parameterAdaptation->segmentDuration = this->parameterAdaptation->segmentDuration / 1000.0; this->onStartButtonPressed(0,0,0,0,0); this->multimediaManager->setLooping(this->repeat); } diff --git a/UI/ViperGui.cpp b/UI/ViperGui.cpp index e23bd308..99d2e5a3 100644 --- a/UI/ViperGui.cpp +++ b/UI/ViperGui.cpp @@ -192,7 +192,7 @@ void ViperGui::writeData(libdash::framework::input::MediaObject* media) this->segment = this->segment + 1; if( this->segment > 0) { - this->bufferDuration += this->segmentDuration; + this->bufferDuration += media->GetSegmentDuration(); if(this->bufferDuration - this->position > 3000) { @@ -206,7 +206,7 @@ void ViperGui::writeData(libdash::framework::input::MediaObject* media) } else { - this->bufferDuration += (this->durationMilliseconds - (this->segmentDuration * (this->listSegmentSize - 1))); + this->bufferDuration += (this->durationMilliseconds - (media->GetSegmentDuration() * (this->listSegmentSize - 1))); if(this->bufferDuration - this->position >3000) { -- cgit 1.2.3-korg