[vlc-commits] demux: adaptive: track position as compound

Francois Cartegnie git at videolan.org
Mon Jul 20 21:03:19 CEST 2020


vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Fri Jul 17 17:05:00 2020 +0200| [1b347a3bfc38f60529763af00409e6ad8f04e46f] | committer: Francois Cartegnie

demux: adaptive: track position as compound

regroups states an associated refs in the same struct

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

 modules/demux/adaptive/SegmentTracker.cpp | 259 +++++++++++++++++++-----------
 modules/demux/adaptive/SegmentTracker.hpp |  24 ++-
 2 files changed, 179 insertions(+), 104 deletions(-)

diff --git a/modules/demux/adaptive/SegmentTracker.cpp b/modules/demux/adaptive/SegmentTracker.cpp
index 862984cd7c..ceca27629c 100644
--- a/modules/demux/adaptive/SegmentTracker.cpp
+++ b/modules/demux/adaptive/SegmentTracker.cpp
@@ -87,11 +87,7 @@ SegmentTracker::SegmentTracker(SharedResources *res,
 {
     resources = res;
     first = true;
-    curNumber = next = std::numeric_limits<uint64_t>::max();
     initializing = true;
-    index_sent = false;
-    init_sent = false;
-    curRepresentation = NULL;
     bufferingLogic = bl;
     setAdaptationLogic(logic_);
     adaptationSet = adaptSet;
@@ -103,6 +99,57 @@ SegmentTracker::~SegmentTracker()
     reset();
 }
 
+SegmentTracker::Position::Position()
+{
+    number = std::numeric_limits<uint64_t>::max();
+    rep = NULL;
+    init_sent = false;
+    index_sent = false;
+}
+
+SegmentTracker::Position::Position(BaseRepresentation *rep, uint64_t number)
+{
+    this->rep = rep;
+    this->number = number;
+    init_sent = false;
+    index_sent = false;
+}
+
+bool SegmentTracker::Position::isValid() const
+{
+    return number != std::numeric_limits<uint64_t>::max() &&
+           rep != NULL;
+}
+
+std::string SegmentTracker::Position::toString() const
+{
+    std::stringstream ss;
+    ss.imbue(std::locale("C"));
+    if(isValid())
+        ss << "seg# " << number
+           << " " << init_sent
+           << ":" << index_sent
+           << " " << rep->getID().str();
+    else
+        ss << "invalid";
+    return ss.str();
+}
+
+SegmentTracker::Position & SegmentTracker::Position::operator ++()
+{
+    if(isValid())
+    {
+        if(index_sent)
+            ++number;
+        else if(init_sent)
+            index_sent = true;
+        else
+            init_sent = true;
+        return *this;
+    }
+    return *this;
+}
+
 void SegmentTracker::setAdaptationLogic(AbstractAdaptationLogic *logic_)
 {
     logic = logic_;
@@ -111,13 +158,13 @@ void SegmentTracker::setAdaptationLogic(AbstractAdaptationLogic *logic_)
 
 StreamFormat SegmentTracker::getCurrentFormat() const
 {
-    BaseRepresentation *rep = curRepresentation;
+    BaseRepresentation *rep = current.rep;
     if(!rep)
         rep = logic->getNextRepresentation(adaptationSet, NULL);
     if(rep)
     {
         /* Ensure ephemere content is updated/loaded */
-        if(rep->needsUpdate(next))
+        if(rep->needsUpdate(next.number))
             (void) rep->runLocalUpdates(resources);
         return rep->getStreamFormat();
     }
@@ -126,7 +173,7 @@ StreamFormat SegmentTracker::getCurrentFormat() const
 
 std::list<std::string> SegmentTracker::getCurrentCodecs() const
 {
-    BaseRepresentation *rep = curRepresentation;
+    BaseRepresentation *rep = current.rep;
     if(!rep)
         rep = logic->getNextRepresentation(adaptationSet, NULL);
     if(rep)
@@ -151,10 +198,9 @@ const Role & SegmentTracker::getStreamRole() const
 
 void SegmentTracker::reset()
 {
-    notify(SegmentTrackerEvent(curRepresentation, NULL));
-    curRepresentation = NULL;
-    init_sent = false;
-    index_sent = false;
+    notify(SegmentTrackerEvent(current.rep, NULL));
+    current = Position();
+    next = Position();
     initializing = true;
     format = StreamFormat::UNKNOWN;
 }
@@ -162,75 +208,79 @@ void SegmentTracker::reset()
 SegmentChunk * SegmentTracker::getNextChunk(bool switch_allowed,
                                             AbstractConnectionManager *connManager)
 {
-    BaseRepresentation *rep = NULL, *prevRep = NULL;
     ISegment *segment;
 
     if(!adaptationSet)
         return NULL;
 
-    /* Ensure we don't keep chaining init/index without data */
-    if( initializing )
+    bool b_updated = false;
+    bool b_switched = false;
+
+    /* starting */
+    if(!next.isValid())
     {
-        if( curRepresentation )
-            switch_allowed = false;
-        else
-            switch_allowed = true;
+        next = getStartPosition();
+        b_switched = true;
     }
-
-    if( !switch_allowed ||
-       (curRepresentation && !curRepresentation->getAdaptationSet()->isSegmentAligned()) )
-        rep = curRepresentation;
-    else
-        rep = logic->getNextRepresentation(adaptationSet, curRepresentation);
-
-    if ( rep == NULL )
-            return NULL;
-
-
-    if(rep != curRepresentation)
+    else /* continuing, or seek */
     {
-        notify(SegmentTrackerEvent(curRepresentation, rep));
-        prevRep = curRepresentation;
-        curRepresentation = rep;
-        init_sent = false;
-        index_sent = false;
-        initializing = true;
+        if(!current.isValid() || !adaptationSet->isSegmentAligned() || initializing)
+            switch_allowed = false;
+
+        if(switch_allowed)
+        {
+            Position temp;
+            temp.rep = logic->getNextRepresentation(adaptationSet, next.rep);
+            if(temp.rep && temp.rep != next.rep)
+            {
+                /* Ensure ephemere content is updated/loaded */
+                if(temp.rep->needsUpdate(next.number))
+                    b_updated = temp.rep->runLocalUpdates(resources);
+                /* if we need to translate pos */
+                if(!temp.rep->consistentSegmentNumber())
+                {
+                    /* Convert our segment number */
+                    temp.number = temp.rep->translateSegmentNumber(next.number, next.rep);
+                }
+                else temp.number = next.number;
+            }
+            if(temp.isValid())
+            {
+                next = temp;
+                b_switched = current.isValid();
+            }
+        }
     }
 
-    bool b_updated = false;
-    /* Ensure ephemere content is updated/loaded */
-    if(rep->needsUpdate(next))
-        b_updated = rep->runLocalUpdates(resources);
+    if(!next.isValid())
+        return NULL;
 
-    if(curNumber == std::numeric_limits<uint64_t>::max())
+    if(b_switched)
     {
-        next = bufferingLogic->getStartSegmentNumber(rep);
-        if(next == std::numeric_limits<uint64_t>::max())
-            return NULL;
-    }
-    else if(prevRep && !rep->consistentSegmentNumber())
-    {
-        /* Convert our segment number */
-        next = rep->translateSegmentNumber(next, prevRep);
+        notify(SegmentTrackerEvent(current.rep, next.rep));
+        initializing = true;
+        assert(!next.index_sent);
+        assert(!next.init_sent);
     }
 
-    curRepresentation->scheduleNextUpdate(next, b_updated);
+    next.rep->scheduleNextUpdate(next.number, b_updated);
+    current = next;
 
-    if(rep->getStreamFormat() != format)
+    if(current.rep->getStreamFormat() != format)
     {
         /* Initial format ? */
         if(format == StreamFormat(StreamFormat::UNKNOWN))
         {
-            format = rep->getStreamFormat();
+            format = current.rep->getStreamFormat();
         }
         else
         {
-            format = rep->getStreamFormat();
+            format = current.rep->getStreamFormat();
             notify(SegmentTrackerEvent(&format)); /* Notify new demux format */
             return NULL; /* Force current demux to end */
         }
     }
-    else if(format == StreamFormat(StreamFormat::UNKNOWN) && prevRep && prevRep != rep)
+    else if(format == StreamFormat(StreamFormat::UNKNOWN) && b_switched)
     {
         /* Handle the corner case when only the demuxer can know the format and
          * demuxer starts after the format change (Probe != buffering) */
@@ -243,28 +293,31 @@ SegmentChunk * SegmentTracker::getNextChunk(bool switch_allowed,
         return NULL; /* Can't return chunk because no demux will be created */
     }
 
-    if(!init_sent)
+    if(!current.init_sent)
     {
-        init_sent = true;
-        segment = rep->getSegment(BaseRepresentation::INFOTYPE_INIT);
+        ++next;
+        segment = current.rep->getSegment(BaseRepresentation::INFOTYPE_INIT);
         if(segment)
-            return segment->toChunk(resources, connManager, next, rep);
+            return segment->toChunk(resources, connManager, current.number, current.rep);
+        current = next;
     }
 
-    if(!index_sent)
+    if(!current.index_sent)
     {
-        index_sent = true;
-        segment = rep->getSegment(BaseRepresentation::INFOTYPE_INDEX);
+        ++next;
+        segment = current.rep->getSegment(BaseRepresentation::INFOTYPE_INDEX);
         if(segment)
-            return segment->toChunk(resources, connManager, next, rep);
+            return segment->toChunk(resources, connManager, current.number, current.rep);
+        current = next;
     }
 
     bool b_gap = false;
-    segment = rep->getNextSegment(BaseRepresentation::INFOTYPE_MEDIA, next, &next, &b_gap);
+    segment = current.rep->getNextSegment(BaseRepresentation::INFOTYPE_MEDIA,
+                                          current.number, &current.number, &b_gap);
     if(!segment)
-    {
         return NULL;
-    }
+    if(b_gap)
+        next = current;
 
     if(initializing)
     {
@@ -273,13 +326,13 @@ SegmentChunk * SegmentTracker::getNextChunk(bool switch_allowed,
         initializing = false;
     }
 
-    SegmentChunk *chunk = segment->toChunk(resources, connManager, next, rep);
+    SegmentChunk *chunk = segment->toChunk(resources, connManager, next.number, next.rep);
 
     /* Notify new segment length for stats / logic */
     if(chunk)
     {
-        const Timescale timescale = rep->inheritTimescale();
-        notify(SegmentTrackerEvent(rep->getAdaptationSet()->getID(),
+        const Timescale timescale = next.rep->inheritTimescale();
+        notify(SegmentTrackerEvent(next.rep->getAdaptationSet()->getID(),
                                    timescale.ToTime(segment->duration.Get())));
     }
 
@@ -291,66 +344,76 @@ SegmentChunk * SegmentTracker::getNextChunk(bool switch_allowed,
     }
 
     /* Handle both implicit and explicit discontinuities */
-    if( (b_gap && next) || (chunk && chunk->discontinuity) )
+    if( (b_gap && next.number) || (chunk && chunk->discontinuity) )
     {
         notify(SegmentTrackerEvent(chunk));
     }
 
     if(chunk)
-    {
-        curNumber = next;
-        next++;
-    }
+        ++next;
 
     return chunk;
 }
 
 bool SegmentTracker::setPositionByTime(vlc_tick_t time, bool restarted, bool tryonly)
 {
-    uint64_t segnumber;
-    BaseRepresentation *rep = curRepresentation;
-    if(!rep)
-        rep = logic->getNextRepresentation(adaptationSet, NULL);
+    Position pos = Position(current.rep, current.number);
+    if(!pos.isValid())
+        pos.rep = logic->getNextRepresentation(adaptationSet, NULL);
+
+    if(!pos.rep)
+        return false;
 
     /* Stream might not have been loaded at all (HLS) or expired */
-    if(rep && rep->needsUpdate(next) && !rep->runLocalUpdates(resources))
+    if(pos.rep->needsUpdate(pos.number) && !pos.rep->runLocalUpdates(resources))
     {
-        msg_Err(rep->getAdaptationSet()->getPlaylist()->getVLCObject(),
-                "Failed to update Representation %s", rep->getID().str().c_str());
+        msg_Err(adaptationSet->getPlaylist()->getVLCObject(),
+                "Failed to update Representation %s",
+                pos.rep->getID().str().c_str());
         return false;
     }
 
-    if(rep &&
-       rep->getSegmentNumberByTime(time, &segnumber))
+    if(pos.rep->getSegmentNumberByTime(time, &pos.number))
     {
         if(!tryonly)
-            setPositionByNumber(segnumber, restarted);
+            setPosition(pos, restarted);
         return true;
     }
     return false;
 }
 
-void SegmentTracker::setPositionByNumber(uint64_t segnumber, bool restarted)
+void SegmentTracker::setPosition(const Position &pos, bool restarted)
 {
     if(restarted)
-    {
         initializing = true;
-        index_sent = false;
-        init_sent = false;
+    current = Position();
+    next = pos;
+}
+
+SegmentTracker::Position SegmentTracker::getStartPosition()
+{
+    Position pos;
+    pos.rep = logic->getNextRepresentation(adaptationSet, NULL);
+    if(pos.rep)
+    {
+        /* Ensure ephemere content is updated/loaded */
+        if(pos.rep->needsUpdate(pos.number))
+            pos.rep->runLocalUpdates(resources);
+        pos.number = bufferingLogic->getStartSegmentNumber(pos.rep);
     }
-    curNumber = next = segnumber;
+    return pos;
 }
 
 vlc_tick_t SegmentTracker::getPlaybackTime(bool b_next) const
 {
     vlc_tick_t time, duration;
 
-    BaseRepresentation *rep = curRepresentation;
+    BaseRepresentation *rep = current.rep;
     if(!rep)
         rep = logic->getNextRepresentation(adaptationSet, NULL);
 
     if(rep &&
-       rep->getPlaybackTimeDurationBySegmentNumber(b_next ? next : curNumber, &time, &duration))
+       rep->getPlaybackTimeDurationBySegmentNumber(b_next ? next.number : current.number, &time, &duration))
     {
         return time;
     }
@@ -360,23 +423,23 @@ vlc_tick_t SegmentTracker::getPlaybackTime(bool b_next) const
 bool SegmentTracker::getMediaPlaybackRange(vlc_tick_t *start, vlc_tick_t *end,
                                            vlc_tick_t *length) const
 {
-    if(!curRepresentation)
+    if(!current.rep)
         return false;
-    return curRepresentation->getMediaPlaybackRange(start, end, length);
+    return current.rep->getMediaPlaybackRange(start, end, length);
 }
 
 vlc_tick_t SegmentTracker::getMinAheadTime() const
 {
-    BaseRepresentation *rep = curRepresentation;
+    BaseRepresentation *rep = current.rep;
     if(!rep)
         rep = logic->getNextRepresentation(adaptationSet, NULL);
     if(rep)
     {
         /* Ensure ephemere content is updated/loaded */
-        if(rep->needsUpdate(next))
+        if(rep->needsUpdate(next.number))
             (void) rep->runLocalUpdates(resources);
 
-        uint64_t startnumber = curNumber;
+        uint64_t startnumber = current.number;
         if(startnumber == std::numeric_limits<uint64_t>::max())
             startnumber = bufferingLogic->getStartSegmentNumber(rep);
         if(startnumber != std::numeric_limits<uint64_t>::max())
@@ -409,10 +472,10 @@ bool SegmentTracker::bufferingAvailable() const
 
 void SegmentTracker::updateSelected()
 {
-    if(curRepresentation && curRepresentation->needsUpdate(next))
+    if(current.rep && current.rep->needsUpdate(next.number))
     {
-        bool b_updated = curRepresentation->runLocalUpdates(resources);
-        curRepresentation->scheduleNextUpdate(curNumber, b_updated);
+        bool b_updated = current.rep->runLocalUpdates(resources);
+        current.rep->scheduleNextUpdate(current.number, b_updated);
     }
 }
 
diff --git a/modules/demux/adaptive/SegmentTracker.hpp b/modules/demux/adaptive/SegmentTracker.hpp
index ba2955a1e7..8ad8e44845 100644
--- a/modules/demux/adaptive/SegmentTracker.hpp
+++ b/modules/demux/adaptive/SegmentTracker.hpp
@@ -122,6 +122,20 @@ namespace adaptive
                            BaseAdaptationSet *);
             ~SegmentTracker();
 
+            class Position
+            {
+                public:
+                    Position();
+                    Position(BaseRepresentation *, uint64_t);
+                    Position & operator++();
+                    bool isValid() const;
+                    std::string toString() const;
+                    uint64_t number;
+                    BaseRepresentation *rep;
+                    bool init_sent;
+                    bool index_sent;
+            };
+
             StreamFormat getCurrentFormat() const;
             std::list<std::string> getCurrentCodecs() const;
             const std::string & getStreamDescription() const;
@@ -130,7 +144,8 @@ namespace adaptive
             void reset();
             SegmentChunk* getNextChunk(bool, AbstractConnectionManager *);
             bool setPositionByTime(vlc_tick_t, bool, bool);
-            void setPositionByNumber(uint64_t, bool);
+            void setPosition(const Position &, bool);
+            Position getStartPosition();
             vlc_tick_t getPlaybackTime(bool = false) const; /* Current segment start time if selected */
             bool getMediaPlaybackRange(vlc_tick_t *, vlc_tick_t *, vlc_tick_t *) const;
             vlc_tick_t getMinAheadTime() const;
@@ -145,16 +160,13 @@ namespace adaptive
             void notify(const SegmentTrackerEvent &) const;
             bool first;
             bool initializing;
-            bool index_sent;
-            bool init_sent;
-            uint64_t next;
-            uint64_t curNumber;
+            Position current;
+            Position next;
             StreamFormat format;
             SharedResources *resources;
             AbstractAdaptationLogic *logic;
             const AbstractBufferingLogic *bufferingLogic;
             BaseAdaptationSet *adaptationSet;
-            BaseRepresentation *curRepresentation;
             std::list<SegmentTrackerListenerInterface *> listeners;
     };
 }



More information about the vlc-commits mailing list