vlc | branch: master | Francois Cartegnie <[email protected]> | 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; }; } _______________________________________________ vlc-commits mailing list [email protected] https://mailman.videolan.org/listinfo/vlc-commits
