[vlc-commits] demux: adaptive: fix commands comparison

Francois Cartegnie git at videolan.org
Tue Jan 19 16:50:34 UTC 2021


vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Thu Jan 14 20:38:04 2021 +0100| [e3ae28bcb236c51a3a1102354d93901b40e91e55] | committer: Francois Cartegnie

demux: adaptive: fix commands comparison

strictly weak ordering was not preserved with same pts pkts
(assumed a & b were compared in stored order)

Causing corruption with non standard split IFrames as < 2^16
PES size.

refs #25380

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

 modules/demux/adaptive/plumbing/CommandsQueue.cpp | 51 ++++++++++++++---------
 modules/demux/adaptive/plumbing/CommandsQueue.hpp |  7 +++-
 2 files changed, 36 insertions(+), 22 deletions(-)

diff --git a/modules/demux/adaptive/plumbing/CommandsQueue.cpp b/modules/demux/adaptive/plumbing/CommandsQueue.cpp
index 0cbcecda1b..34a54e0fc7 100644
--- a/modules/demux/adaptive/plumbing/CommandsQueue.cpp
+++ b/modules/demux/adaptive/plumbing/CommandsQueue.cpp
@@ -248,6 +248,7 @@ CommandsQueue::CommandsQueue( CommandsFactory *f )
     b_draining = false;
     b_eof = false;
     commandsFactory = f;
+    nextsequence = 0;
 }
 
 CommandsQueue::~CommandsQueue()
@@ -256,18 +257,27 @@ CommandsQueue::~CommandsQueue()
     delete commandsFactory;
 }
 
-static bool compareCommands( AbstractCommand *a, AbstractCommand *b )
+static bool compareCommands( const Queueentry &a, const Queueentry &b )
 {
-    if(a->getTime() == b->getTime())
+    if(a.second->getTime() == b.second->getTime())
     {
         /* Reorder the initial clock PCR setting PCR0 DTS0 PCR0 DTS1 PCR1
            so it appears after the block, avoiding it not being output */
-        if(a->getType() == ES_OUT_SET_GROUP_PCR &&
-           b->getType() == ES_OUT_PRIVATE_COMMAND_SEND)
+        if(a.second->getType() == ES_OUT_SET_GROUP_PCR &&
+           b.second->getType() == ES_OUT_PRIVATE_COMMAND_SEND &&
+           a.first < b.first)
             return false;
-        return true;
+
+        return a.first < b.first;
+    }
+    else if (a.second->getTime() == VLC_TICK_INVALID || b.second->getTime() == VLC_TICK_INVALID)
+    {
+        return a.first < b.first;
+    }
+    else
+    {
+        return a.second->getTime() < b.second->getTime();
     }
-    else return (a->getTime() < b->getTime() && a->getTime() != VLC_TICK_INVALID);
 }
 
 void CommandsQueue::Schedule( AbstractCommand *command )
@@ -280,11 +290,11 @@ void CommandsQueue::Schedule( AbstractCommand *command )
     {
         bufferinglevel = command->getTime();
         LockedCommit();
-        commands.push_back( command );
+        commands.push_back( Queueentry(nextsequence++, command) );
     }
     else
     {
-        incoming.push_back( command );
+        incoming.push_back( Queueentry(nextsequence++, command) );
     }
 }
 
@@ -306,15 +316,16 @@ vlc_tick_t CommandsQueue::Process( es_out_t *out, vlc_tick_t barrier )
        ex: for a target time of 2, you must dequeue <= 2 until >= PCR2
        A0,A1,A2,B0,PCR0,B1,B2,PCR2,B3,A3,PCR3
     */
-    std::list<AbstractCommand *> output;
-    std::list<AbstractCommand *> in;
+    std::list<Queueentry> output;
+    std::list<Queueentry> in;
 
 
     in.splice( in.end(), commands );
 
     while( !in.empty() )
     {
-        AbstractCommand *command = in.front();
+        Queueentry entry = in.front();
+        AbstractCommand *command = entry.second;
 
         if( command->getType() == ES_OUT_PRIVATE_COMMAND_DEL && b_datasent )
             break;
@@ -340,21 +351,21 @@ vlc_tick_t CommandsQueue::Process( es_out_t *out, vlc_tick_t barrier )
                 /* ensure no more non dated for that ES is sent
                  * since we're sure that data is above barrier */
                 disabled_esids.insert( id );
-                commands.push_back( command );
+                commands.push_back( entry );
             }
             else if( command->getTime() == VLC_TICK_INVALID )
             {
                 if( disabled_esids.find( id ) == disabled_esids.end() )
-                    output.push_back( command );
+                    output.push_back( entry );
                 else
-                    commands.push_back( command );
+                    commands.push_back( entry );
             }
             else /* Falls below barrier, send */
             {
-                output.push_back( command );
+                output.push_back( entry );
             }
         }
-        else output.push_back( command ); /* will discard below */
+        else output.push_back( entry ); /* will discard below */
     }
 
     /* push remaining ones if broke above */
@@ -366,7 +377,7 @@ vlc_tick_t CommandsQueue::Process( es_out_t *out, vlc_tick_t barrier )
     /* Now execute our selected commands */
     while( !output.empty() )
     {
-        AbstractCommand *command = output.front();
+        AbstractCommand *command = output.front().second;
         output.pop_front();
 
         if( command->getType() == ES_OUT_PRIVATE_COMMAND_SEND )
@@ -402,7 +413,7 @@ void CommandsQueue::Abort( bool b_reset )
     commands.splice( commands.end(), incoming );
     while( !commands.empty() )
     {
-        delete commands.front();
+        delete commands.front().second;
         commands.pop_front();
     }
 
@@ -471,11 +482,11 @@ vlc_tick_t CommandsQueue::getBufferingLevel() const
 
 vlc_tick_t CommandsQueue::getFirstDTS() const
 {
-    std::list<AbstractCommand *>::const_iterator it;
+    std::list<Queueentry>::const_iterator it;
     vlc_tick_t i_firstdts = pcr;
     for( it = commands.begin(); it != commands.end(); ++it )
     {
-        const vlc_tick_t i_dts = (*it)->getTime();
+        const vlc_tick_t i_dts = (*it).second->getTime();
         if( i_dts != VLC_TICK_INVALID )
         {
             if( i_dts < i_firstdts || i_firstdts == VLC_TICK_INVALID )
diff --git a/modules/demux/adaptive/plumbing/CommandsQueue.hpp b/modules/demux/adaptive/plumbing/CommandsQueue.hpp
index cc15fd4973..ab4b0d4a7b 100644
--- a/modules/demux/adaptive/plumbing/CommandsQueue.hpp
+++ b/modules/demux/adaptive/plumbing/CommandsQueue.hpp
@@ -147,6 +147,8 @@ namespace adaptive
             virtual EsOutMetaCommand * createEsOutMetaCommand( int, const vlc_meta_t * ) const;
     };
 
+    using Queueentry = std::pair<uint64_t, AbstractCommand *>;
+
     /* Queuing for doing all the stuff in order */
     class CommandsQueue
     {
@@ -173,13 +175,14 @@ namespace adaptive
             CommandsFactory *commandsFactory;
             void LockedCommit();
             void LockedSetDraining();
-            std::list<AbstractCommand *> incoming;
-            std::list<AbstractCommand *> commands;
+            std::list<Queueentry> incoming;
+            std::list<Queueentry> commands;
             vlc_tick_t bufferinglevel;
             vlc_tick_t pcr;
             bool b_draining;
             bool b_drop;
             bool b_eof;
+            uint64_t nextsequence;
     };
 }
 



More information about the vlc-commits mailing list