[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