[vlc-commits] demux: adaptive: use new buffering logic

Francois Cartegnie git at videolan.org
Tue Mar 24 23:35:19 CET 2020


vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Mon Mar 23 19:37:17 2020 +0100| [f8f3f11fae3f4c95e595a3f0cc3ad5ce8ab8994a] | committer: Francois Cartegnie

demux: adaptive: use new buffering logic

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=f8f3f11fae3f4c95e595a3f0cc3ad5ce8ab8994a
---

 modules/demux/adaptive/PlaylistManager.cpp         |  18 ++-
 modules/demux/adaptive/PlaylistManager.h           |   2 +
 modules/demux/adaptive/SegmentTracker.cpp          |  25 +++-
 modules/demux/adaptive/SegmentTracker.hpp          |   7 +-
 modules/demux/adaptive/Streams.cpp                 |   7 ++
 .../demux/adaptive/playlist/SegmentInformation.cpp | 127 +--------------------
 .../demux/adaptive/playlist/SegmentInformation.hpp |   2 -
 .../demux/adaptive/playlist/SegmentTemplate.cpp    |  18 ++-
 modules/demux/adaptive/playlist/SegmentTemplate.h  |   2 +-
 modules/demux/hls/playlist/Parser.cpp              |   4 +-
 10 files changed, 69 insertions(+), 143 deletions(-)

diff --git a/modules/demux/adaptive/PlaylistManager.cpp b/modules/demux/adaptive/PlaylistManager.cpp
index ce6da8e5dd..fea803ef27 100644
--- a/modules/demux/adaptive/PlaylistManager.cpp
+++ b/modules/demux/adaptive/PlaylistManager.cpp
@@ -36,6 +36,7 @@
 #include "logic/AlwaysLowestAdaptationLogic.hpp"
 #include "logic/PredictiveAdaptationLogic.hpp"
 #include "logic/NearOptimalAdaptationLogic.hpp"
+#include "logic/BufferingLogic.hpp"
 #include "tools/Debug.hpp"
 #include <vlc_stream.h>
 #include <vlc_demux.h>
@@ -61,6 +62,7 @@ PlaylistManager::PlaylistManager( demux_t *p_demux_,
 {
     currentPeriod = playlist->getFirstPeriod();
     resources = res;
+    bufferingLogic = NULL;
     failedupdates = 0;
     b_thread = false;
     b_buffering = false;
@@ -89,6 +91,7 @@ PlaylistManager::~PlaylistManager   ()
     delete playlist;
     delete logic;
     delete resources;
+    delete bufferingLogic;
 }
 
 void PlaylistManager::unsetPeriod()
@@ -107,6 +110,9 @@ bool PlaylistManager::setupPeriod()
     if(!logic && !(logic = createLogic(logicType, resources->getConnManager())))
         return false;
 
+    if(!bufferingLogic && !(bufferingLogic = createBufferingLogic()))
+        return false;
+
     std::vector<BaseAdaptationSet*> sets = currentPeriod->getAdaptationSets();
     std::vector<BaseAdaptationSet*>::iterator it;
     for(it=sets.begin();it!=sets.end();++it)
@@ -114,7 +120,8 @@ bool PlaylistManager::setupPeriod()
         BaseAdaptationSet *set = *it;
         if(set && streamFactory)
         {
-            SegmentTracker *tracker = new SegmentTracker(resources, logic, set);
+            SegmentTracker *tracker = new SegmentTracker(resources, logic,
+                                                         bufferingLogic, set);
             if(!tracker)
                 continue;
 
@@ -610,8 +617,8 @@ void PlaylistManager::setBufferingRunState(bool b)
 void PlaylistManager::Run()
 {
     vlc_mutex_lock(&lock);
-    const vlc_tick_t i_min_buffering = playlist->getMinBuffering();
-    const vlc_tick_t i_extra_buffering = playlist->getMaxBuffering() - i_min_buffering;
+    const vlc_tick_t i_min_buffering = bufferingLogic->getMinBuffering(playlist);
+    const vlc_tick_t i_extra_buffering = bufferingLogic->getMaxBuffering(playlist) - i_min_buffering;
     while(1)
     {
         while(!b_buffering && !b_canceled)
@@ -823,3 +830,8 @@ AbstractAdaptationLogic *PlaylistManager::createLogic(AbstractAdaptationLogic::L
 
     return logic;
 }
+
+AbstractBufferingLogic *PlaylistManager::createBufferingLogic() const
+{
+    return new DefaultBufferingLogic();
+}
diff --git a/modules/demux/adaptive/PlaylistManager.h b/modules/demux/adaptive/PlaylistManager.h
index 55ceacde7c..6d0f6e15c5 100644
--- a/modules/demux/adaptive/PlaylistManager.h
+++ b/modules/demux/adaptive/PlaylistManager.h
@@ -90,10 +90,12 @@ namespace adaptive
             /* local factories */
             virtual AbstractAdaptationLogic *createLogic(AbstractAdaptationLogic::LogicType,
                                                          AbstractConnectionManager *);
+            virtual AbstractBufferingLogic *createBufferingLogic() const;
 
             SharedResources                     *resources;
             AbstractAdaptationLogic::LogicType  logicType;
             AbstractAdaptationLogic             *logic;
+            AbstractBufferingLogic              *bufferingLogic;
             AbstractPlaylist                    *playlist;
             AbstractStreamFactory               *streamFactory;
             demux_t                             *p_demux;
diff --git a/modules/demux/adaptive/SegmentTracker.cpp b/modules/demux/adaptive/SegmentTracker.cpp
index ff853558d7..7655d1621c 100644
--- a/modules/demux/adaptive/SegmentTracker.cpp
+++ b/modules/demux/adaptive/SegmentTracker.cpp
@@ -29,6 +29,7 @@
 #include "playlist/Segment.h"
 #include "playlist/SegmentChunk.hpp"
 #include "logic/AbstractAdaptationLogic.h"
+#include "logic/BufferingLogic.hpp"
 
 #include <cassert>
 #include <limits>
@@ -80,7 +81,9 @@ SegmentTrackerEvent::SegmentTrackerEvent(const ID &id, vlc_tick_t duration)
 }
 
 SegmentTracker::SegmentTracker(SharedResources *res,
-        AbstractAdaptationLogic *logic_, BaseAdaptationSet *adaptSet)
+        AbstractAdaptationLogic *logic_,
+        const AbstractBufferingLogic *bl,
+        BaseAdaptationSet *adaptSet)
 {
     resources = res;
     first = true;
@@ -89,6 +92,7 @@ SegmentTracker::SegmentTracker(SharedResources *res,
     index_sent = false;
     init_sent = false;
     curRepresentation = NULL;
+    bufferingLogic = bl;
     setAdaptationLogic(logic_);
     adaptationSet = adaptSet;
     format = StreamFormat::UNKNOWN;
@@ -213,7 +217,7 @@ SegmentChunk * SegmentTracker::getNextChunk(bool switch_allowed,
 
     if(curNumber == std::numeric_limits<uint64_t>::max())
     {
-        next = rep->getLiveStartSegmentNumber(next);
+        next = bufferingLogic->getStartSegmentNumber(rep);
         if(next == std::numeric_limits<uint64_t>::max())
             return NULL;
     }
@@ -381,7 +385,15 @@ vlc_tick_t SegmentTracker::getMinAheadTime() const
     if(!rep)
         rep = logic->getNextRepresentation(adaptationSet, NULL);
     if(rep)
-        return rep->getMinAheadTime(curNumber);
+    {
+        /* Ensure ephemere content is updated/loaded */
+        if(rep->needsUpdate())
+            (void) rep->runLocalUpdates(resources);
+
+        uint64_t startnumber = bufferingLogic->getStartSegmentNumber(rep);
+        assert(startnumber != std::numeric_limits<uint64_t>::max());
+        return rep->getMinAheadTime(startnumber);
+    }
     return 0;
 }
 
@@ -400,6 +412,13 @@ void SegmentTracker::registerListener(SegmentTrackerListenerInterface *listener)
     listeners.push_back(listener);
 }
 
+bool SegmentTracker::bufferingAvailable() const
+{
+    if(adaptationSet->getPlaylist()->isLive())
+        return bufferingLogic->getMinBuffering(adaptationSet->getPlaylist()) <= getMinAheadTime();
+    return true;
+}
+
 void SegmentTracker::updateSelected()
 {
     if(curRepresentation && curRepresentation->needsUpdate())
diff --git a/modules/demux/adaptive/SegmentTracker.hpp b/modules/demux/adaptive/SegmentTracker.hpp
index 4f6e132caf..91dd84c792 100644
--- a/modules/demux/adaptive/SegmentTracker.hpp
+++ b/modules/demux/adaptive/SegmentTracker.hpp
@@ -39,6 +39,7 @@ namespace adaptive
     namespace logic
     {
         class AbstractAdaptationLogic;
+        class AbstractBufferingLogic;
     }
 
     namespace playlist
@@ -116,7 +117,9 @@ namespace adaptive
     {
         public:
             SegmentTracker(SharedResources *,
-                           AbstractAdaptationLogic *, BaseAdaptationSet *);
+                           AbstractAdaptationLogic *,
+                           const AbstractBufferingLogic *,
+                           BaseAdaptationSet *);
             ~SegmentTracker();
 
             StreamFormat getCurrentFormat() const;
@@ -136,6 +139,7 @@ namespace adaptive
             void notifyBufferingLevel(vlc_tick_t, vlc_tick_t, vlc_tick_t) const;
             void registerListener(SegmentTrackerListenerInterface *);
             void updateSelected();
+            bool bufferingAvailable() const;
 
         private:
             void setAdaptationLogic(AbstractAdaptationLogic *);
@@ -149,6 +153,7 @@ namespace adaptive
             StreamFormat format;
             SharedResources *resources;
             AbstractAdaptationLogic *logic;
+            const AbstractBufferingLogic *bufferingLogic;
             BaseAdaptationSet *adaptationSet;
             BaseRepresentation *curRepresentation;
             std::list<SegmentTrackerListenerInterface *> listeners;
diff --git a/modules/demux/adaptive/Streams.cpp b/modules/demux/adaptive/Streams.cpp
index f78aaf1a70..668aaec412 100644
--- a/modules/demux/adaptive/Streams.cpp
+++ b/modules/demux/adaptive/Streams.cpp
@@ -338,6 +338,13 @@ AbstractStream::buffering_status AbstractStream::doBufferize(vlc_tick_t nz_deadl
         return AbstractStream::buffering_suspended;
     }
 
+    /* Reached end of live playlist */
+    if(!segmentTracker->bufferingAvailable())
+    {
+        vlc_mutex_unlock(&lock);
+        return AbstractStream::buffering_suspended;
+    }
+
     if(!demuxer)
     {
         format = segmentTracker->getCurrentFormat();
diff --git a/modules/demux/adaptive/playlist/SegmentInformation.cpp b/modules/demux/adaptive/playlist/SegmentInformation.cpp
index 3e3a24baf8..adbead58f1 100644
--- a/modules/demux/adaptive/playlist/SegmentInformation.cpp
+++ b/modules/demux/adaptive/playlist/SegmentInformation.cpp
@@ -162,131 +162,6 @@ std::size_t SegmentInformation::getAllSegments(std::vector<ISegment *> &retSegme
     return retSegments.size();
 }
 
-uint64_t SegmentInformation::getLiveSegmentNumberByTime(uint64_t def, vlc_tick_t t) const
-{
-    if( mediaSegmentTemplate )
-    {
-        if( mediaSegmentTemplate->duration.Get() )
-        {
-            return mediaSegmentTemplate->getLiveTemplateNumber(t);
-        }
-    }
-
-    if(parent)
-        return parent->getLiveStartSegmentNumber(def);
-    else
-        return def;
-}
-
-uint64_t SegmentInformation::getLiveStartSegmentNumber(uint64_t def) const
-{
-    const vlc_tick_t i_max_buffering = getPlaylist()->getMaxBuffering() +
-                                    /* FIXME: add dynamic pts-delay */ VLC_TICK_FROM_SEC(1);
-
-    /* Try to never buffer up to really end */
-    const uint64_t OFFSET_FROM_END = 3;
-
-    if( mediaSegmentTemplate )
-    {
-        uint64_t start = 0;
-        uint64_t end = 0;
-        const Timescale timescale = mediaSegmentTemplate->inheritTimescale();
-
-        const SegmentTimeline *timeline = mediaSegmentTemplate->inheritSegmentTimeline();
-        if( timeline )
-        {
-            start = timeline->minElementNumber();
-            end = timeline->maxElementNumber();
-            /* Try to never buffer up to really end */
-            end = end - std::min(end - start, OFFSET_FROM_END);
-            stime_t endtime, duration;
-
-            bool b_ret = timeline->getScaledPlaybackTimeDurationBySegmentNumber( end, &endtime, &duration );
-            if(unlikely(!b_ret)) /* should never happen */
-            {
-                assert(b_ret);
-                return 0;
-            }
-
-            vlc_tick_t fromend = std::max( i_max_buffering, getPlaylist()->suggestedPresentationDelay.Get() );
-            if( endtime + duration <= timescale.ToScaled( fromend ) )
-                return start;
-
-            uint64_t number = timeline->getElementNumberByScaledPlaybackTime(endtime - timescale.ToScaled( fromend ));
-            if( number < start )
-                number = start;
-            return number;
-        }
-        /* Else compute, current time and timeshiftdepth based */
-        else if( mediaSegmentTemplate->duration.Get() )
-        {
-            vlc_tick_t i_delay = getPlaylist()->suggestedPresentationDelay.Get();
-
-            if( i_delay == 0 || i_delay > getPlaylist()->timeShiftBufferDepth.Get() )
-                 i_delay = getPlaylist()->timeShiftBufferDepth.Get();
-
-            if( i_delay < getPlaylist()->getMinBuffering() )
-                i_delay = getPlaylist()->getMinBuffering();
-
-            const uint64_t startnumber = mediaSegmentTemplate->inheritStartNumber();
-            end = mediaSegmentTemplate->getLiveTemplateNumber(vlc_tick_from_sec(time(NULL)));
-
-            const uint64_t count = timescale.ToScaled( i_delay ) / mediaSegmentTemplate->duration.Get();
-            if( startnumber + count >= end )
-                start = startnumber;
-            else
-                start = end - count;
-
-            uint64_t bufcount = ( OFFSET_FROM_END + timescale.ToScaled(i_max_buffering) /
-                                  mediaSegmentTemplate->duration.Get() );
-            /* Ensure we always pick > start # of availability window as this segment might no longer be avail */
-            if( end - start <= bufcount )
-                bufcount = end - start - 1;
-
-            return ( end - start > bufcount ) ? end - bufcount : start;
-        }
-    }
-    else if ( segmentList && !segmentList->getSegments().empty() )
-    {
-        const Timescale timescale = segmentList->inheritTimescale();
-        const std::vector<ISegment *> list = segmentList->getSegments();
-
-        const ISegment *back = list.back();
-        vlc_tick_t fromend = std::max( i_max_buffering, getPlaylist()->suggestedPresentationDelay.Get() );
-        stime_t bufferingstart = back->startTime.Get() + back->duration.Get() - timescale.ToScaled( fromend );
-
-        uint64_t number;
-        if( !segmentList->getSegmentNumberByScaledTime( bufferingstart, &number ) )
-            return list.front()->getSequenceNumber();
-        if( number > list.front()->getSequenceNumber() + OFFSET_FROM_END )
-            number -= OFFSET_FROM_END;
-        else
-            number = list.front()->getSequenceNumber();
-        return number;
-    }
-    else if( segmentBase )
-    {
-        const std::vector<ISegment *> list = segmentBase->subSegments();
-        if(!list.empty())
-            return segmentBase->getSequenceNumber();
-
-        const Timescale timescale = inheritTimescale();
-        const ISegment *back = list.back();
-        vlc_tick_t fromend = std::max( i_max_buffering, getPlaylist()->suggestedPresentationDelay.Get() );
-        const stime_t bufferingstart = back->startTime.Get() -
-                (OFFSET_FROM_END * back->duration.Get())- timescale.ToScaled( fromend );
-        uint64_t number;
-        if( !SegmentInfoCommon::getSegmentNumberByScaledTime( list, bufferingstart, &number ) )
-            return list.front()->getSequenceNumber();
-        return number;
-    }
-
-    if(parent)
-        return parent->getLiveStartSegmentNumber(def);
-    else
-        return def;
-}
-
 bool SegmentInformation::getMediaPlaybackRange(vlc_tick_t *rangeBegin,
                                                vlc_tick_t *rangeEnd,
                                                vlc_tick_t *rangeLength) const
@@ -454,7 +329,7 @@ bool SegmentInformation::getSegmentNumberByTime(vlc_tick_t time, uint64_t *ret)
         {
             if( getPlaylist()->isLive() )
             {
-                *ret = getLiveSegmentNumberByTime( mediaSegmentTemplate->inheritStartNumber(), time );
+                *ret = mediaSegmentTemplate->getLiveTemplateNumber(time, false);
             }
             else
             {
diff --git a/modules/demux/adaptive/playlist/SegmentInformation.hpp b/modules/demux/adaptive/playlist/SegmentInformation.hpp
index ffbdf9dcb6..48d6e9c227 100644
--- a/modules/demux/adaptive/playlist/SegmentInformation.hpp
+++ b/modules/demux/adaptive/playlist/SegmentInformation.hpp
@@ -75,8 +75,6 @@ namespace adaptive
                 ISegment * getNextSegment(SegmentInfoType, uint64_t, uint64_t *, bool *) const;
                 bool getSegmentNumberByTime(vlc_tick_t, uint64_t *) const;
                 bool getPlaybackTimeDurationBySegmentNumber(uint64_t, vlc_tick_t *, vlc_tick_t *) const;
-                uint64_t getLiveSegmentNumberByTime(uint64_t, vlc_tick_t) const;
-                uint64_t getLiveStartSegmentNumber(uint64_t) const;
                 bool     getMediaPlaybackRange(vlc_tick_t *, vlc_tick_t *, vlc_tick_t *) const;
                 virtual void updateWith(SegmentInformation *);
                 virtual void mergeWithTimeline(SegmentTimeline *); /* ! don't use with global merge */
diff --git a/modules/demux/adaptive/playlist/SegmentTemplate.cpp b/modules/demux/adaptive/playlist/SegmentTemplate.cpp
index 458c9668de..b024936763 100644
--- a/modules/demux/adaptive/playlist/SegmentTemplate.cpp
+++ b/modules/demux/adaptive/playlist/SegmentTemplate.cpp
@@ -148,7 +148,7 @@ SegmentTimeline * MediaSegmentTemplate::inheritSegmentTimeline() const
     return NULL;
 }
 
-uint64_t MediaSegmentTemplate::getLiveTemplateNumber(vlc_tick_t playbacktime) const
+uint64_t MediaSegmentTemplate::getLiveTemplateNumber(vlc_tick_t playbacktime, bool abs) const
 {
     uint64_t number = inheritStartNumber();
     /* live streams / templated */
@@ -156,12 +156,18 @@ uint64_t MediaSegmentTemplate::getLiveTemplateNumber(vlc_tick_t playbacktime) co
     if(dur)
     {
         /* compute, based on current time */
+        /* N = (T - AST - PS - D)/D + sSN */
         const Timescale timescale = inheritTimescale();
-        vlc_tick_t streamstart =
-                vlc_tick_from_sec(parentSegmentInformation->getPlaylist()->availabilityStartTime.Get());
-        streamstart += parentSegmentInformation->getPeriodStart();
-        stime_t elapsed = timescale.ToScaled(playbacktime - streamstart);
-        number += elapsed / dur;
+        if(abs)
+        {
+            vlc_tick_t streamstart =
+                    vlc_tick_from_sec(parentSegmentInformation->getPlaylist()->availabilityStartTime.Get());
+            streamstart += parentSegmentInformation->getPeriodStart();
+            playbacktime -= streamstart;
+        }
+        stime_t elapsed = timescale.ToScaled(playbacktime) - dur;
+        if(elapsed > 0)
+            number += elapsed / dur;
     }
 
     return number;
diff --git a/modules/demux/adaptive/playlist/SegmentTemplate.h b/modules/demux/adaptive/playlist/SegmentTemplate.h
index 9d100439f1..12d3e1f7c7 100644
--- a/modules/demux/adaptive/playlist/SegmentTemplate.h
+++ b/modules/demux/adaptive/playlist/SegmentTemplate.h
@@ -55,7 +55,7 @@ namespace adaptive
                 void setSegmentTimeline( SegmentTimeline * );
                 void updateWith( MediaSegmentTemplate * );
                 virtual uint64_t getSequenceNumber() const; /* reimpl */
-                uint64_t getLiveTemplateNumber(vlc_tick_t) const;
+                uint64_t getLiveTemplateNumber(vlc_tick_t, bool = true) const;
                 stime_t getMinAheadScaledTime(uint64_t) const;
                 void pruneByPlaybackTime(vlc_tick_t);
                 size_t pruneBySequenceNumber(uint64_t);
diff --git a/modules/demux/hls/playlist/Parser.cpp b/modules/demux/hls/playlist/Parser.cpp
index 2c4d645007..5dcb370c7f 100644
--- a/modules/demux/hls/playlist/Parser.cpp
+++ b/modules/demux/hls/playlist/Parser.cpp
@@ -32,6 +32,7 @@
 #include "../../adaptive/tools/Retrieve.hpp"
 #include "../../adaptive/tools/Helper.h"
 #include "../../adaptive/tools/Conversions.hpp"
+#include "../../adaptive/logic/BufferingLogic.hpp"
 #include "M3U8.hpp"
 #include "Tags.hpp"
 
@@ -148,7 +149,8 @@ void M3U8Parser::createAndFillRepresentation(vlc_object_t *p_obj, BaseAdaptation
         if(rep->isLive())
         {
             /* avoid update playlist immediately */
-            uint64_t startseq = rep->getLiveStartSegmentNumber(0);
+            logic::DefaultBufferingLogic buflogic;
+            uint64_t startseq = buflogic.getStartSegmentNumber(rep);
             rep->scheduleNextUpdate(startseq);
         }
         adaptSet->addRepresentation(rep);



More information about the vlc-commits mailing list