Handling live MPDs with variable segments duration 69/7769/1
authorJacques Samain <[email protected]>
Tue, 25 Jul 2017 13:32:54 +0000 (15:32 +0200)
committerJacques Samain <[email protected]>
Tue, 25 Jul 2017 13:32:54 +0000 (15:32 +0200)
Change-Id: I074d8863a9afb47815e47bf663b87e7f663890b9
Signed-off-by: Jacques Samain <[email protected]>
17 files changed:
Adaptation/Bola.cpp
Input/DASHReceiver.cpp
Input/DASHReceiver.h
Input/MediaObject.cpp
Input/MediaObject.h
MPD/AbstractRepresentationStream.h
MPD/IRepresentationStream.h
MPD/MPDWrapper.cpp
MPD/SegmentListStream.cpp
MPD/SegmentListStream.h
MPD/SegmentTemplateStream.cpp
MPD/SegmentTemplateStream.h
MPD/SingleMediaSegmentStream.cpp
MPD/SingleMediaSegmentStream.h
Managers/MultimediaManager.cpp
UI/DASHPlayerNoGUI.cpp
UI/ViperGui.cpp

index f7acc72..470d22e 100644 (file)
@@ -50,7 +50,8 @@ using duration_in_seconds = std::chrono::duration<double, std::ratio<1, 1> >;
 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;
 
index 59514e5..74415bf 100644 (file)
@@ -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))
index ee2df38..a6db038 100644 (file)
@@ -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<int, MediaObject*>                         initSegments;
+    std::map<std::string, MediaObject*>                 initSegments;
     libdash::framework::buffer::Buffer<MediaObject>     *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);
 };
 }
index b2dde35..2f4e004 100644 (file)
@@ -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;
 }
index 1edd69a..24c2995 100644 (file)
@@ -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;
 };
 }
 }
index 113720e..da847c3 100644 (file)
@@ -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;
 
index bf8b08c..124216b 100644 (file)
@@ -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;
index 20d4aa5..c7bdee9 100644 (file)
@@ -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;
     }
index c353008..86d36e6 100644 (file)
@@ -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 */
index 264ac9c..589896f 100644 (file)
@@ -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();
index ee51cf0..5080189 100644 (file)
@@ -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;
        }
index 0bd0ad1..8485b56 100644 (file)
@@ -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<uint64_t>       segmentStartTimes;
+    std::vector<uint64_t>       segmentDurationTimes;
     uint32_t                    averageDuration;
     bool                        inSync;
     uint32_t                    currentSegment;
index 3930192..3eccbef 100644 (file)
@@ -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)
index e619a7f..44fead3 100644 (file)
@@ -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();
 
index 1806123..997fc6d 100644 (file)
@@ -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)
index d212b55..2195b88 100644 (file)
@@ -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);
         }
index e23bd30..99d2e5a 100644 (file)
@@ -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)
         {