[vlc-commits] demux: adaptive: detect format change by from segmentchunk

Francois Cartegnie git at videolan.org
Mon Mar 15 20:56:29 UTC 2021


vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Sun Mar 14 20:14:07 2021 +0100| [126cb62893a177916d4c863da89252edf4e7c75a] | committer: Francois Cartegnie

demux: adaptive: detect format change by from segmentchunk

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

 modules/demux/adaptive/SegmentTracker.cpp        | 65 +++++++++++-------------
 modules/demux/adaptive/SegmentTracker.hpp        |  3 +-
 modules/demux/adaptive/Streams.cpp               | 23 +++++----
 modules/demux/adaptive/Streams.hpp               |  1 +
 modules/demux/adaptive/playlist/SegmentChunk.cpp | 10 ++--
 modules/demux/adaptive/playlist/SegmentChunk.hpp |  2 +
 6 files changed, 54 insertions(+), 50 deletions(-)

diff --git a/modules/demux/adaptive/SegmentTracker.cpp b/modules/demux/adaptive/SegmentTracker.cpp
index d3331d55d7..4f76aaf928 100644
--- a/modules/demux/adaptive/SegmentTracker.cpp
+++ b/modules/demux/adaptive/SegmentTracker.cpp
@@ -323,7 +323,7 @@ void SegmentTracker::resetChunksSequence()
     }
 }
 
-SegmentChunk * SegmentTracker::getNextChunk(bool switch_allowed,
+ChunkInterface * SegmentTracker::getNextChunk(bool switch_allowed,
                                             AbstractConnectionManager *connManager)
 {
     if(!adaptationSet || !next.isValid())
@@ -345,7 +345,8 @@ SegmentChunk * SegmentTracker::getNextChunk(bool switch_allowed,
 
     /* here next == wanted chunk pos */
     bool b_gap = (next.number != chunk.pos.number);
-    bool b_switched = (next.rep != chunk.pos.rep);
+    const bool b_switched = (next.rep != chunk.pos.rep);
+    const bool b_discontinuity = chunk.chunk->discontinuity;
 
     if(b_switched)
     {
@@ -356,33 +357,36 @@ SegmentChunk * SegmentTracker::getNextChunk(bool switch_allowed,
     /* advance or don't trigger duplicate events */
     next = current = chunk.pos;
 
-    if(chunk.pos.rep->getStreamFormat() != format)
-    {
-        /* Initial format ? */
-        if(format == StreamFormat(StreamFormat::UNKNOWN))
-        {
-            format = chunk.pos.rep->getStreamFormat();
-        }
-        else
-        {
-            format = chunk.pos.rep->getStreamFormat();
-            notify(FormatChangedEvent(&format)); /* Notify new demux format */
-            return nullptr; /* Force current demux to end */
-        }
-    }
-    else if(format == StreamFormat(StreamFormat::UNKNOWN) && b_switched)
+    /* From this point chunk must be returned */
+    ChunkInterface *returnedChunk;
+    StreamFormat chunkformat = chunk.chunk->getStreamFormat();
+
+    /* Wrap and probe format */
+    if(chunkformat == StreamFormat(StreamFormat::UNKNOWN))
     {
-        /* Handle the corner case when only the demuxer can know the format and
-         * demuxer starts after the format change (Probe != buffering) */
-        notify(FormatChangedEvent(&format)); /* Notify new demux format */
-        return nullptr; /* Force current demux to end */
+        ProbeableChunk *wrappedck = new ProbeableChunk(chunk.chunk);
+        const uint8_t *p_peek;
+        size_t i_peek = wrappedck->peek(&p_peek);
+        chunkformat = StreamFormat(p_peek, i_peek);
+        /* fallback on Mime type */
+        if(chunkformat == StreamFormat(StreamFormat::UNKNOWN))
+            format = StreamFormat(chunk.chunk->getContentType());
+        chunk.chunk->setStreamFormat(chunkformat);
+        returnedChunk = wrappedck;
     }
+    else returnedChunk = chunk.chunk;
 
-    if(format == StreamFormat(StreamFormat::UNSUPPORTED))
+    if(chunkformat != format &&
+       chunkformat != StreamFormat(StreamFormat::UNKNOWN))
     {
-        return nullptr; /* Can't return chunk because no demux will be created */
+        format = chunkformat;
+        notify(FormatChangedEvent(&format));
     }
 
+    /* pop position and return our chunk */
+    chunkssequence.pop_front();
+    chunk.chunk = nullptr;
+
     if(initializing)
     {
         b_gap = false;
@@ -394,25 +398,14 @@ SegmentChunk * SegmentTracker::getNextChunk(bool switch_allowed,
     if(chunk.pos.init_sent && chunk.pos.index_sent)
         notify(SegmentChangedEvent(adaptationSet->getID(), chunk.duration));
 
-    /* We need to check segment/chunk format changes, as we can't rely on representation's (HLS)*/
-    if(format != chunk.pos.rep->getStreamFormat())
-    {
-        format = chunk.pos.rep->getStreamFormat();
-        notify(FormatChangedEvent(&format));
-    }
-
     /* Handle both implicit and explicit discontinuities */
-    if(b_gap || chunk.chunk->discontinuity)
+    if(b_gap || b_discontinuity)
         notify(DiscontinuityEvent());
 
     if(!b_gap)
         ++next;
 
-    /* pop position and return our chunk */
-    chunkssequence.pop_front();
-    SegmentChunk *segmentChunk = chunk.chunk;
-    chunk.chunk = nullptr;
-    return segmentChunk;
+    return returnedChunk;
 }
 
 bool SegmentTracker::setPositionByTime(vlc_tick_t time, bool restarted, bool tryonly)
diff --git a/modules/demux/adaptive/SegmentTracker.hpp b/modules/demux/adaptive/SegmentTracker.hpp
index 05b05d4a05..c131d333bc 100644
--- a/modules/demux/adaptive/SegmentTracker.hpp
+++ b/modules/demux/adaptive/SegmentTracker.hpp
@@ -35,6 +35,7 @@ namespace adaptive
     namespace http
     {
         class AbstractConnectionManager;
+        class ChunkInterface;
     }
 
     namespace logic
@@ -184,7 +185,7 @@ namespace adaptive
             void getCodecsDesc(CodecDescriptionList *) const;
             const Role & getStreamRole() const;
             void reset();
-            SegmentChunk* getNextChunk(bool, AbstractConnectionManager *);
+            ChunkInterface* getNextChunk(bool, AbstractConnectionManager *);
             bool setPositionByTime(vlc_tick_t, bool, bool);
             void setPosition(const Position &, bool);
             bool setStartPosition();
diff --git a/modules/demux/adaptive/Streams.cpp b/modules/demux/adaptive/Streams.cpp
index fbaca03307..b94f8a5686 100644
--- a/modules/demux/adaptive/Streams.cpp
+++ b/modules/demux/adaptive/Streams.cpp
@@ -260,6 +260,12 @@ bool AbstractStream::startDemux()
     if(demuxer)
         return false;
 
+    if(!currentChunk)
+    {
+        currentChunk = getNextChunk();
+        needrestart = false;
+    }
+
     demuxersource->Reset();
     demuxer = createDemux(format);
     if(!demuxer && format != StreamFormat())
@@ -396,7 +402,6 @@ AbstractStream::BufferingStatus AbstractStream::doBufferize(vlc_tick_t nz_deadli
 
     if(!demuxer)
     {
-        format = segmentTracker->getCurrentFormat();
         if(!startDemux())
         {
             /* If demux fails because of probing failure / wrong format*/
@@ -513,13 +518,16 @@ AbstractStream::Status AbstractStream::dequeue(vlc_tick_t nz_deadline, vlc_tick_
     return Status::Buffering;
 }
 
+ChunkInterface * AbstractStream::getNextChunk() const
+{
+    const bool b_restarting = fakeEsOut()->restarting();
+    return segmentTracker->getNextChunk(!b_restarting, connManager);
+}
+
 std::string AbstractStream::getContentType()
 {
     if (currentChunk == nullptr && !eof)
-    {
-        const bool b_restarting = fakeEsOut()->restarting();
-        currentChunk = segmentTracker->getNextChunk(!b_restarting, connManager);
-    }
+        currentChunk = getNextChunk();
     if(currentChunk)
         return currentChunk->getContentType();
     else
@@ -529,10 +537,7 @@ std::string AbstractStream::getContentType()
 block_t * AbstractStream::readNextBlock()
 {
     if (currentChunk == nullptr && !eof)
-    {
-        const bool b_restarting = fakeEsOut()->restarting();
-        currentChunk = segmentTracker->getNextChunk(!b_restarting, connManager);
-    }
+        currentChunk = getNextChunk();
 
     if(discontinuity && demuxfirstchunk)
     {
diff --git a/modules/demux/adaptive/Streams.hpp b/modules/demux/adaptive/Streams.hpp
index f80cd266fa..dc78e2fdc5 100644
--- a/modules/demux/adaptive/Streams.hpp
+++ b/modules/demux/adaptive/Streams.hpp
@@ -127,6 +127,7 @@ namespace adaptive
         AbstractConnectionManager *connManager; /* not owned */
         SegmentTracker *segmentTracker;
 
+        ChunkInterface * getNextChunk() const;
         ChunkInterface *currentChunk;
         bool eof;
         std::string language;
diff --git a/modules/demux/adaptive/playlist/SegmentChunk.cpp b/modules/demux/adaptive/playlist/SegmentChunk.cpp
index 3756325d6c..d659f4ef95 100644
--- a/modules/demux/adaptive/playlist/SegmentChunk.cpp
+++ b/modules/demux/adaptive/playlist/SegmentChunk.cpp
@@ -69,10 +69,12 @@ void SegmentChunk::onDownload(block_t **pp_block)
 
 StreamFormat SegmentChunk::getStreamFormat() const
 {
-    if(rep)
-        return rep->getStreamFormat();
-    else
-        return StreamFormat();
+    return (format == StreamFormat() && rep) ? rep->getStreamFormat() : format;
+}
+
+void SegmentChunk::setStreamFormat(const StreamFormat &f)
+{
+    format = f;
 }
 
 void SegmentChunk::setEncryptionSession(CommonEncryptionSession *s)
diff --git a/modules/demux/adaptive/playlist/SegmentChunk.hpp b/modules/demux/adaptive/playlist/SegmentChunk.hpp
index db1798aab8..d4b2ca32b3 100644
--- a/modules/demux/adaptive/playlist/SegmentChunk.hpp
+++ b/modules/demux/adaptive/playlist/SegmentChunk.hpp
@@ -45,6 +45,7 @@ namespace adaptive
             virtual ~SegmentChunk();
             void         setEncryptionSession(CommonEncryptionSession *);
             StreamFormat getStreamFormat() const;
+            void setStreamFormat(const StreamFormat &);
             bool discontinuity;
             uint64_t sequence;
 
@@ -52,6 +53,7 @@ namespace adaptive
             bool         decrypt(block_t **);
             virtual void onDownload(block_t **) override;
             BaseRepresentation *rep;
+            StreamFormat format;
             CommonEncryptionSession *encryptionSession;
         };
 



More information about the vlc-commits mailing list