[vlc-commits] demux: adaptive: unify and fix potential lock inversion

Francois Cartegnie git at videolan.org
Thu May 9 16:15:27 CEST 2019


vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Wed May  8 18:31:25 2019 +0200| [d481d80280771be48a30dc201e5a36c556a0bcc2] | committer: Francois Cartegnie

demux: adaptive: unify and fix potential lock inversion

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

 modules/demux/adaptive/Streams.cpp                | 110 ++++++++++++----------
 modules/demux/adaptive/Streams.hpp                |   3 +-
 modules/demux/adaptive/plumbing/CommandsQueue.cpp |  28 ------
 modules/demux/adaptive/plumbing/CommandsQueue.hpp |   1 -
 modules/demux/adaptive/plumbing/FakeESOut.cpp     |  72 +++++++-------
 modules/demux/adaptive/plumbing/FakeESOut.hpp     |  14 +++
 modules/demux/hls/HLSStreams.cpp                  |   6 +-
 7 files changed, 117 insertions(+), 117 deletions(-)

diff --git a/modules/demux/adaptive/Streams.cpp b/modules/demux/adaptive/Streams.cpp
index 7f6f02a6af..acff1dd360 100644
--- a/modules/demux/adaptive/Streams.cpp
+++ b/modules/demux/adaptive/Streams.cpp
@@ -51,7 +51,6 @@ AbstractStream::AbstractStream(demux_t * demux_)
     inrestart = false;
     segmentTracker = NULL;
     demuxersource = NULL;
-    commandsqueue = NULL;
     demuxer = NULL;
     fakeesout = NULL;
     notfound_sequence = 0;
@@ -71,7 +70,7 @@ bool AbstractStream::init(const StreamFormat &format_, SegmentTracker *tracker,
         CommandsFactory *factory = new (std::nothrow) CommandsFactory();
         if(factory)
         {
-            commandsqueue = new (std::nothrow) CommandsQueue(factory);
+            CommandsQueue *commandsqueue = new (std::nothrow) CommandsQueue(factory);
             if(commandsqueue)
             {
                 fakeesout = new (std::nothrow) FakeESOut(p_realdemux->out, commandsqueue);
@@ -111,7 +110,6 @@ AbstractStream::~AbstractStream()
     delete demuxer;
     delete demuxersource;
     delete fakeesout;
-    delete commandsqueue;
 
     vlc_mutex_destroy(&lock);
 }
@@ -124,14 +122,14 @@ void AbstractStream::prepareRestart(bool b_discontinuity)
         demuxer->drain();
         setTimeOffset(true);
         /* Enqueue Del Commands for all current ES */
-        fakeesout->scheduleAllForDeletion();
+        fakeEsOut()->scheduleAllForDeletion();
         if(b_discontinuity)
-            fakeesout->schedulePCRReset();
-        commandsqueue->Commit();
+            fakeEsOut()->schedulePCRReset();
+        fakeEsOut()->commandsQueue()->Commit();
         /* ignoring demuxer's own Del commands */
-        commandsqueue->setDrop(true);
+        fakeEsOut()->commandsQueue()->setDrop(true);
         delete demuxer;
-        commandsqueue->setDrop(false);
+        fakeEsOut()->commandsQueue()->setDrop(false);
         demuxer = NULL;
     }
 }
@@ -149,7 +147,7 @@ void AbstractStream::setDescription(const std::string &desc)
 vlc_tick_t AbstractStream::getPCR() const
 {
     vlc_mutex_lock(const_cast<vlc_mutex_t *>(&lock));
-    vlc_tick_t pcr = isDisabled() ? VLC_TICK_INVALID : commandsqueue->getPCR();
+    vlc_tick_t pcr = isDisabled() ? VLC_TICK_INVALID : fakeEsOut()->commandsQueue()->getPCR();
     vlc_mutex_unlock(const_cast<vlc_mutex_t *>(&lock));
     return pcr;
 }
@@ -171,9 +169,9 @@ vlc_tick_t AbstractStream::getFirstDTS() const
     }
     else
     {
-        dts = commandsqueue->getFirstDTS();
+        dts = fakeEsOut()->commandsQueue()->getFirstDTS();
         if(dts == VLC_TICK_INVALID)
-            dts = commandsqueue->getPCR();
+            dts = fakeEsOut()->commandsQueue()->getPCR();
     }
     vlc_mutex_unlock(const_cast<vlc_mutex_t *>(&lock));
     return dts;
@@ -181,14 +179,14 @@ vlc_tick_t AbstractStream::getFirstDTS() const
 
 int AbstractStream::esCount() const
 {
-    return fakeesout->esCount();
+    return fakeEsOut()->esCount();
 }
 
 bool AbstractStream::seekAble() const
 {
-    bool restarting = fakeesout->restarting();
-    bool draining = commandsqueue->isDraining();
-    bool eof = commandsqueue->isEOF();
+    bool restarting = fakeEsOut()->restarting();
+    bool draining = fakeEsOut()->commandsQueue()->isDraining();
+    bool eof = fakeEsOut()->commandsQueue()->isEOF();
 
     msg_Dbg(p_realdemux, "demuxer %p, fakeesout restarting %d, "
             "discontinuity %d, commandsqueue draining %d, commandsqueue eof %d",
@@ -207,7 +205,7 @@ bool AbstractStream::seekAble() const
 
 bool AbstractStream::isSelected() const
 {
-    return fakeesout->hasSelectedEs();
+    return fakeEsOut()->hasSelectedEs();
 }
 
 bool AbstractStream::reactivate(vlc_tick_t basetime)
@@ -249,17 +247,17 @@ bool AbstractStream::restartDemux()
     {
         inrestart = true;
         /* Push all ES as recycling candidates */
-        fakeesout->recycleAll();
+        fakeEsOut()->recycleAll();
         /* Restart with ignoring es_Del pushes to queue when terminating demux */
-        commandsqueue->setDrop(true);
+        fakeEsOut()->commandsQueue()->setDrop(true);
         demuxer->destroy();
-        commandsqueue->setDrop(false);
+        fakeEsOut()->commandsQueue()->setDrop(false);
         b_ret = demuxer->create();
         inrestart = false;
     }
     else
     {
-        commandsqueue->Commit();
+        fakeEsOut()->commandsQueue()->Commit();
     }
     return b_ret;
 }
@@ -283,7 +281,7 @@ bool AbstractStream::canActivate() const
 
 bool AbstractStream::decodersDrained()
 {
-    return fakeesout->decodersDrained();
+    return fakeEsOut()->decodersDrained();
 }
 
 AbstractStream::buffering_status AbstractStream::getLastBufferStatus() const
@@ -293,7 +291,7 @@ AbstractStream::buffering_status AbstractStream::getLastBufferStatus() const
 
 vlc_tick_t AbstractStream::getDemuxedAmount() const
 {
-    return commandsqueue->getDemuxedAmount();
+    return fakeEsOut()->commandsQueue()->getDemuxedAmount();
 }
 
 AbstractStream::buffering_status AbstractStream::bufferize(vlc_tick_t nz_deadline,
@@ -316,18 +314,18 @@ AbstractStream::buffering_status AbstractStream::doBufferize(vlc_tick_t nz_deadl
     }
 
     /* Disable streams that are not selected (alternate streams) */
-    if(esCount() && !isSelected() && !fakeesout->restarting())
+    if(esCount() && !isSelected() && !fakeEsOut()->restarting())
     {
         setDisabled(true);
         segmentTracker->reset();
-        commandsqueue->Abort(false);
+        fakeEsOut()->commandsQueue()->Abort(false);
         msg_Dbg(p_realdemux, "deactivating %s stream %s",
                 format.str().c_str(), description.c_str());
         vlc_mutex_unlock(&lock);
         return AbstractStream::buffering_end;
     }
 
-    if(commandsqueue->isDraining())
+    if(fakeEsOut()->commandsQueue()->isDraining())
     {
         vlc_mutex_unlock(&lock);
         return AbstractStream::buffering_suspended;
@@ -344,12 +342,12 @@ AbstractStream::buffering_status AbstractStream::doBufferize(vlc_tick_t nz_deadl
                 msg_Dbg( p_realdemux, "Draining on format change" );
                 prepareRestart();
                 discontinuity = false;
-                commandsqueue->setDraining();
+                fakeEsOut()->commandsQueue()->setDraining();
                 vlc_mutex_unlock(&lock);
                 return AbstractStream::buffering_ongoing;
             }
             dead = true; /* Prevent further retries */
-            commandsqueue->setEOF(true);
+            fakeEsOut()->commandsQueue()->setEOF(true);
             vlc_mutex_unlock(&lock);
             return AbstractStream::buffering_end;
         }
@@ -357,7 +355,7 @@ AbstractStream::buffering_status AbstractStream::doBufferize(vlc_tick_t nz_deadl
 
     const vlc_tick_t i_total_buffering = i_min_buffering + i_extra_buffering;
 
-    vlc_tick_t i_demuxed = commandsqueue->getDemuxedAmount();
+    vlc_tick_t i_demuxed = fakeEsOut()->commandsQueue()->getDemuxedAmount();
     segmentTracker->notifyBufferingLevel(i_min_buffering, i_demuxed, i_total_buffering);
     if(i_demuxed < i_total_buffering) /* not already demuxed */
     {
@@ -367,8 +365,8 @@ AbstractStream::buffering_status AbstractStream::doBufferize(vlc_tick_t nz_deadl
             return AbstractStream::buffering_suspended;
         }
 
-        vlc_tick_t nz_extdeadline = commandsqueue->getBufferingLevel() +
-                                (i_total_buffering - commandsqueue->getDemuxedAmount()) / 4;
+        vlc_tick_t nz_extdeadline = fakeEsOut()->commandsQueue()->getBufferingLevel() +
+                                    (i_total_buffering - i_demuxed) / 4;
         nz_deadline = std::max(nz_deadline, nz_extdeadline);
 
         /* need to read, demuxer still buffering, ... */
@@ -384,18 +382,18 @@ AbstractStream::buffering_status AbstractStream::doBufferize(vlc_tick_t nz_deadl
                 if(discontinuity)
                 {
                     msg_Dbg(p_realdemux, "Draining on discontinuity");
-                    commandsqueue->setDraining();
+                    fakeEsOut()->commandsQueue()->setDraining();
                     discontinuity = false;
                 }
                 needrestart = false;
                 vlc_mutex_unlock(&lock);
                 return AbstractStream::buffering_ongoing;
             }
-            commandsqueue->setEOF(true);
+            fakeEsOut()->commandsQueue()->setEOF(true);
             vlc_mutex_unlock(&lock);
             return AbstractStream::buffering_end;
         }
-        i_demuxed = commandsqueue->getDemuxedAmount();
+        i_demuxed = fakeEsOut()->commandsQueue()->getDemuxedAmount();
         segmentTracker->notifyBufferingLevel(i_min_buffering, i_demuxed, i_total_buffering);
     }
     vlc_mutex_unlock(&lock);
@@ -415,36 +413,36 @@ AbstractStream::status AbstractStream::dequeue(vlc_tick_t nz_deadline, vlc_tick_
 
     *pi_pcr = nz_deadline;
 
-    if(commandsqueue->isDraining())
+    if(fakeEsOut()->commandsQueue()->isDraining())
     {
         AdvDebug(msg_Dbg(p_realdemux, "Stream %s pcr %" PRId64 " dts %" PRId64 " deadline %" PRId64 " [DRAINING]",
                          description.c_str(), commandsqueue->getPCR(), commandsqueue->getFirstDTS(),
                          nz_deadline));
 
-        *pi_pcr = commandsqueue->Process(p_realdemux->out, VLC_TICK_0 + nz_deadline);
-        if(!commandsqueue->isEmpty())
+        *pi_pcr = fakeEsOut()->commandsQueue()->Process(p_realdemux->out, VLC_TICK_0 + nz_deadline);
+        if(!fakeEsOut()->commandsQueue()->isEmpty())
             return AbstractStream::status_demuxed;
 
-        if(!commandsqueue->isEOF())
+        if(!fakeEsOut()->commandsQueue()->isEOF())
         {
-            commandsqueue->Abort(true); /* reset buffering level and flags */
+            fakeEsOut()->commandsQueue()->Abort(true); /* reset buffering level and flags */
             return AbstractStream::status_discontinuity;
         }
     }
 
-    if(isDisabled() || commandsqueue->isEOF())
+    if(isDisabled() || fakeEsOut()->commandsQueue()->isEOF())
     {
         *pi_pcr = nz_deadline;
         return AbstractStream::status_eof;
     }
 
     AdvDebug(msg_Dbg(p_realdemux, "Stream %s pcr %" PRId64 " dts %" PRId64 " deadline %" PRId64 " buflevel %" PRId64,
-                     description.c_str(), commandsqueue->getPCR(), commandsqueue->getFirstDTS(),
-                     nz_deadline, commandsqueue->getBufferingLevel()));
+                     description.c_str(), fakeEsOut()->commandsQueue()->getPCR(), fakeEsOut()->commandsQueue()->getFirstDTS(),
+                     nz_deadline, fakeEsOut()->commandsQueue()->getBufferingLevel()));
 
-    if(nz_deadline + VLC_TICK_0 <= commandsqueue->getBufferingLevel()) /* demuxed */
+    if(nz_deadline + VLC_TICK_0 <= fakeEsOut()->commandsQueue()->getBufferingLevel()) /* demuxed */
     {
-        *pi_pcr = commandsqueue->Process( p_realdemux->out, VLC_TICK_0 + nz_deadline );
+        *pi_pcr = fakeEsOut()->commandsQueue()->Process( p_realdemux->out, VLC_TICK_0 + nz_deadline );
         return AbstractStream::status_demuxed;
     }
 
@@ -454,7 +452,7 @@ AbstractStream::status AbstractStream::dequeue(vlc_tick_t nz_deadline, vlc_tick_
 std::string AbstractStream::getContentType()
 {
     if (currentChunk == NULL && !eof)
-        currentChunk = segmentTracker->getNextChunk(!fakeesout->restarting(), connManager);
+        currentChunk = segmentTracker->getNextChunk(!fakeEsOut()->restarting(), connManager);
     if(currentChunk)
         return currentChunk->getContentType();
     else
@@ -464,7 +462,7 @@ std::string AbstractStream::getContentType()
 block_t * AbstractStream::readNextBlock()
 {
     if (currentChunk == NULL && !eof)
-        currentChunk = segmentTracker->getNextChunk(!fakeesout->restarting(), connManager);
+        currentChunk = segmentTracker->getNextChunk(!fakeEsOut()->restarting(), connManager);
 
     if(discontinuity || needrestart)
     {
@@ -536,10 +534,10 @@ bool AbstractStream::setPosition(vlc_tick_t time, bool tryonly)
             }
             else
             {
-                commandsqueue->setEOF(false);
+                fakeEsOut()->commandsQueue()->setEOF(false);
             }
         }
-        else commandsqueue->Abort( true );
+        else fakeEsOut()->commandsQueue()->Abort( true );
 
         es_out_Control(p_realdemux->out, ES_OUT_SET_NEXT_DISPLAY_TIME,
                        VLC_TICK_0 + time);
@@ -572,24 +570,24 @@ void AbstractStream::setTimeOffset(vlc_tick_t i_offset)
      * will start from zero from seek point */
     if(i_offset < 0) /* reset */
     {
-        fakeesout->setExpectedTimestampOffset(0);
+        fakeEsOut()->setExpectedTimestampOffset(0);
     }
     else if(demuxer)
     {
-        fakeesout->setExpectedTimestampOffset(i_offset);
+        fakeEsOut()->setExpectedTimestampOffset(i_offset);
     }
 }
 
 AbstractDemuxer * AbstractStream::createDemux(const StreamFormat &format)
 {
     AbstractDemuxer *ret = newDemux( p_realdemux, format,
-                                     fakeesout->getEsOut(), demuxersource );
+                                     fakeEsOut()->getEsOut(), demuxersource );
     if(ret && !ret->create())
     {
         delete ret;
         ret = NULL;
     }
-    else commandsqueue->Commit();
+    else fakeEsOut()->commandsQueue()->Commit();
 
     return ret;
 }
@@ -655,3 +653,13 @@ void AbstractStream::trackerEvent(const SegmentTrackerEvent &event)
             break;
     }
 }
+
+FakeESOut::LockedFakeEsOut AbstractStream::fakeEsOut()
+{
+    return fakeesout->WithLock();
+}
+
+FakeESOut::LockedFakeEsOut AbstractStream::fakeEsOut() const
+{
+    return fakeesout->WithLock();
+}
diff --git a/modules/demux/adaptive/Streams.hpp b/modules/demux/adaptive/Streams.hpp
index 4e7bedbcd5..c0c83255b5 100644
--- a/modules/demux/adaptive/Streams.hpp
+++ b/modules/demux/adaptive/Streams.hpp
@@ -127,9 +127,10 @@ namespace adaptive
         std::string language;
         std::string description;
 
-        CommandsQueue *commandsqueue;
         AbstractDemuxer *demuxer;
         AbstractSourceStream *demuxersource;
+        FakeESOut::LockedFakeEsOut fakeEsOut();
+        FakeESOut::LockedFakeEsOut fakeEsOut() const;
         FakeESOut *fakeesout; /* to intercept/proxy what is sent from demuxstream */
         vlc_mutex_t lock; /* lock for everything accessed by dequeuing */
 
diff --git a/modules/demux/adaptive/plumbing/CommandsQueue.cpp b/modules/demux/adaptive/plumbing/CommandsQueue.cpp
index 566f696b2b..a45ae13c5b 100644
--- a/modules/demux/adaptive/plumbing/CommandsQueue.cpp
+++ b/modules/demux/adaptive/plumbing/CommandsQueue.cpp
@@ -248,14 +248,12 @@ CommandsQueue::CommandsQueue( CommandsFactory *f )
     b_draining = false;
     b_eof = false;
     commandsFactory = f;
-    vlc_mutex_init(&lock);
 }
 
 CommandsQueue::~CommandsQueue()
 {
     Abort( false );
     delete commandsFactory;
-    vlc_mutex_destroy(&lock);
 }
 
 static bool compareCommands( AbstractCommand *a, AbstractCommand *b )
@@ -274,7 +272,6 @@ static bool compareCommands( AbstractCommand *a, AbstractCommand *b )
 
 void CommandsQueue::Schedule( AbstractCommand *command )
 {
-    vlc_mutex_lock(&lock);
     if( b_drop )
     {
         delete command;
@@ -289,7 +286,6 @@ void CommandsQueue::Schedule( AbstractCommand *command )
     {
         incoming.push_back( command );
     }
-    vlc_mutex_unlock(&lock);
 }
 
 const CommandsFactory * CommandsQueue::factory() const
@@ -313,7 +309,6 @@ vlc_tick_t CommandsQueue::Process( es_out_t *out, vlc_tick_t barrier )
     std::list<AbstractCommand *> output;
     std::list<AbstractCommand *> in;
 
-    vlc_mutex_lock(&lock);
 
     in.splice( in.end(), commands );
 
@@ -386,7 +381,6 @@ vlc_tick_t CommandsQueue::Process( es_out_t *out, vlc_tick_t barrier )
     }
     pcr = lastdts; /* Warn! no PCR update/lock release until execution */
 
-    vlc_mutex_unlock(&lock);
 
     return lastdts;
 }
@@ -400,14 +394,11 @@ void CommandsQueue::LockedCommit()
 
 void CommandsQueue::Commit()
 {
-    vlc_mutex_lock(&lock);
     LockedCommit();
-    vlc_mutex_unlock(&lock);
 }
 
 void CommandsQueue::Abort( bool b_reset )
 {
-    vlc_mutex_lock(&lock);
     commands.splice( commands.end(), incoming );
     while( !commands.empty() )
     {
@@ -422,55 +413,42 @@ void CommandsQueue::Abort( bool b_reset )
         b_draining = false;
         b_eof = false;
     }
-    vlc_mutex_unlock(&lock);
 }
 
 bool CommandsQueue::isEmpty() const
 {
-    vlc_mutex_lock(const_cast<vlc_mutex_t *>(&lock));
     bool b_empty = commands.empty() && incoming.empty();
-    vlc_mutex_unlock(const_cast<vlc_mutex_t *>(&lock));
     return b_empty;
 }
 
 void CommandsQueue::setDrop( bool b )
 {
-    vlc_mutex_lock(&lock);
     b_drop = b;
-    vlc_mutex_unlock(&lock);
 }
 
 void CommandsQueue::setDraining()
 {
-    vlc_mutex_lock(&lock);
     LockedSetDraining();
-    vlc_mutex_unlock(&lock);
 }
 
 bool CommandsQueue::isDraining() const
 {
-    vlc_mutex_lock(const_cast<vlc_mutex_t *>(&lock));
     bool b = b_draining;
-    vlc_mutex_unlock(const_cast<vlc_mutex_t *>(&lock));
     return b;
 }
 
 void CommandsQueue::setEOF( bool b )
 {
-    vlc_mutex_lock(&lock);
     b_eof = b;
     if( b_eof )
         LockedSetDraining();
     else
         b_draining = false;
-    vlc_mutex_unlock(&lock);
 }
 
 bool CommandsQueue::isEOF() const
 {
-    vlc_mutex_lock(const_cast<vlc_mutex_t *>(&lock));
     bool b = b_eof;
-    vlc_mutex_unlock(const_cast<vlc_mutex_t *>(&lock));
     return b;
 }
 
@@ -482,16 +460,13 @@ vlc_tick_t CommandsQueue::getDemuxedAmount() const
 vlc_tick_t CommandsQueue::getBufferingLevel() const
 {
     vlc_tick_t i_buffer;
-    vlc_mutex_lock(const_cast<vlc_mutex_t *>(&lock));
     i_buffer = bufferinglevel;
-    vlc_mutex_unlock(const_cast<vlc_mutex_t *>(&lock));
     return i_buffer;
 }
 
 vlc_tick_t CommandsQueue::getFirstDTS() const
 {
     std::list<AbstractCommand *>::const_iterator it;
-    vlc_mutex_lock(const_cast<vlc_mutex_t *>(&lock));
     vlc_tick_t i_firstdts = pcr;
     for( it = commands.begin(); it != commands.end(); ++it )
     {
@@ -503,7 +478,6 @@ vlc_tick_t CommandsQueue::getFirstDTS() const
             break;
         }
     }
-    vlc_mutex_unlock(const_cast<vlc_mutex_t *>(&lock));
     return i_firstdts;
 }
 
@@ -515,8 +489,6 @@ void CommandsQueue::LockedSetDraining()
 
 vlc_tick_t CommandsQueue::getPCR() const
 {
-    vlc_mutex_lock(const_cast<vlc_mutex_t *>(&lock));
     vlc_tick_t i_pcr = pcr;
-    vlc_mutex_unlock(const_cast<vlc_mutex_t *>(&lock));
     return i_pcr;
 }
diff --git a/modules/demux/adaptive/plumbing/CommandsQueue.hpp b/modules/demux/adaptive/plumbing/CommandsQueue.hpp
index 50ff75bbd4..14c06738d0 100644
--- a/modules/demux/adaptive/plumbing/CommandsQueue.hpp
+++ b/modules/demux/adaptive/plumbing/CommandsQueue.hpp
@@ -171,7 +171,6 @@ namespace adaptive
 
         private:
             CommandsFactory *commandsFactory;
-            vlc_mutex_t lock;
             void LockedCommit();
             void LockedSetDraining();
             std::list<AbstractCommand *> incoming;
diff --git a/modules/demux/adaptive/plumbing/FakeESOut.cpp b/modules/demux/adaptive/plumbing/FakeESOut.cpp
index e377759aa3..8c922c8461 100644
--- a/modules/demux/adaptive/plumbing/FakeESOut.cpp
+++ b/modules/demux/adaptive/plumbing/FakeESOut.cpp
@@ -46,6 +46,27 @@ struct adaptive::es_out_fake
     es_out_t es_out;
 };
 
+FakeESOut::LockedFakeEsOut::LockedFakeEsOut(FakeESOut &q)
+{
+    p = &q;
+    vlc_mutex_lock(&p->lock);
+}
+
+FakeESOut::LockedFakeEsOut::~LockedFakeEsOut()
+{
+    vlc_mutex_unlock(&p->lock);
+}
+
+FakeESOut & FakeESOut::LockedFakeEsOut::operator *()
+{
+    return *p;
+}
+
+FakeESOut * FakeESOut::LockedFakeEsOut::operator ->()
+{
+    return p;
+}
+
 FakeESOut::FakeESOut( es_out_t *es, CommandsQueue *queue )
     : real_es_out( es )
     , extrainfo( NULL )
@@ -61,6 +82,16 @@ FakeESOut::FakeESOut( es_out_t *es, CommandsQueue *queue )
     vlc_mutex_init(&lock);
 }
 
+FakeESOut::LockedFakeEsOut FakeESOut::WithLock()
+{
+    return LockedFakeEsOut(*this);
+}
+
+CommandsQueue * FakeESOut::commandsQueue()
+{
+    return commandsqueue;
+}
+
 es_out_t * FakeESOut::getEsOut()
 {
     return &fakeesout->es_out;
@@ -72,31 +103,26 @@ FakeESOut::~FakeESOut()
     gc();
 
     delete fakeesout;
+    delete commandsqueue;
     vlc_mutex_destroy(&lock);
 }
 
 void FakeESOut::setExpectedTimestampOffset(vlc_tick_t offset)
 {
-    vlc_mutex_lock(&lock);
     timestamps_offset = 0;
     timestamps_expected = offset;
     timestamps_check_done = false;
-    vlc_mutex_unlock(&lock);
 }
 
 void FakeESOut::setTimestampOffset(vlc_tick_t offset)
 {
-    vlc_mutex_lock(&lock);
     timestamps_offset = offset;
     timestamps_check_done = true;
-    vlc_mutex_unlock(&lock);
 }
 
 void FakeESOut::setExtraInfoProvider( ExtraFMTInfoInterface *extra )
 {
-    vlc_mutex_lock(&lock);
     extrainfo = extra;
-    vlc_mutex_unlock(&lock);
 }
 
 FakeESOutID * FakeESOut::createNewID( const es_format_t *p_fmt )
@@ -107,8 +133,6 @@ FakeESOutID * FakeESOut::createNewID( const es_format_t *p_fmt )
     fmtcopy.i_group = 0; /* Always ignore group for adaptive */
     fmtcopy.i_id = -1;
 
-    vlc_mutex_lock(&lock);
-
     if( extrainfo )
         extrainfo->fillExtraFMTInfo( &fmtcopy );
 
@@ -116,8 +140,6 @@ FakeESOutID * FakeESOut::createNewID( const es_format_t *p_fmt )
     if(likely(es_id))
         fakeesidlist.push_back( es_id );
 
-    vlc_mutex_unlock(&lock);
-
     es_format_Clean( &fmtcopy );
 
     return es_id;
@@ -128,8 +150,6 @@ void FakeESOut::createOrRecycleRealEsID( FakeESOutID *es_id )
     std::list<FakeESOutID *>::iterator it;
     es_out_id_t *realid = NULL;
 
-    vlc_mutex_lock(&lock);
-
     bool b_preexisting = false;
     bool b_select = false;
     for( it=recycle_candidates.begin(); it!=recycle_candidates.end(); ++it )
@@ -169,15 +189,11 @@ void FakeESOut::createOrRecycleRealEsID( FakeESOutID *es_id )
     }
 
     es_id->setRealESID( realid );
-
-    vlc_mutex_unlock(&lock);
 }
 
 vlc_tick_t FakeESOut::getTimestampOffset() const
 {
-    vlc_mutex_lock(const_cast<vlc_mutex_t *>(&lock));
     vlc_tick_t time = timestamps_offset;
-    vlc_mutex_unlock(const_cast<vlc_mutex_t *>(&lock));
     return time;
 }
 
@@ -185,11 +201,9 @@ size_t FakeESOut::esCount() const
 {
     size_t i_count = 0;
     std::list<FakeESOutID *>::const_iterator it;
-    vlc_mutex_lock(const_cast<vlc_mutex_t *>(&lock));
     for( it=fakeesidlist.begin(); it!=fakeesidlist.end(); ++it )
         if( (*it)->realESID() )
             i_count++;
-    vlc_mutex_unlock(const_cast<vlc_mutex_t *>(&lock));
     return i_count;
 }
 
@@ -203,7 +217,6 @@ void FakeESOut::schedulePCRReset()
 void FakeESOut::scheduleAllForDeletion()
 {
     std::list<FakeESOutID *>::const_iterator it;
-    vlc_mutex_lock(&lock);
     for( it=fakeesidlist.begin(); it!=fakeesidlist.end(); ++it )
     {
         FakeESOutID *es_id = *it;
@@ -217,7 +230,6 @@ void FakeESOut::scheduleAllForDeletion()
             }
         }
     }
-    vlc_mutex_unlock(&lock);
 }
 
 void FakeESOut::recycleAll()
@@ -225,17 +237,13 @@ void FakeESOut::recycleAll()
     /* Only used when demux is killed and commands queue is cancelled */
     commandsqueue->Abort( true );
     assert(commandsqueue->isEmpty());
-    vlc_mutex_lock(&lock);
     recycle_candidates.splice( recycle_candidates.end(), fakeesidlist );
-    vlc_mutex_unlock(&lock);
 }
 
 void FakeESOut::gc()
 {
-    vlc_mutex_lock(&lock);
     if( recycle_candidates.empty() )
     {
-        vlc_mutex_unlock(&lock);
         return;
     }
 
@@ -250,21 +258,18 @@ void FakeESOut::gc()
         delete *it;
     }
     recycle_candidates.clear();
-    vlc_mutex_unlock(&lock);
 }
 
 bool FakeESOut::hasSelectedEs() const
 {
     bool b_selected = false;
     std::list<FakeESOutID *>::const_iterator it;
-    vlc_mutex_lock(const_cast<vlc_mutex_t *>(&lock));
     for( it=fakeesidlist.begin(); it!=fakeesidlist.end() && !b_selected; ++it )
     {
         FakeESOutID *esID = *it;
         if( esID->realESID() )
             es_out_Control( real_es_out, ES_OUT_GET_ES_STATE, esID->realESID(), &b_selected );
     }
-    vlc_mutex_unlock(const_cast<vlc_mutex_t *>(&lock));
     return b_selected;
 }
 
@@ -277,18 +282,14 @@ bool FakeESOut::decodersDrained()
 
 bool FakeESOut::restarting() const
 {
-    vlc_mutex_lock(const_cast<vlc_mutex_t *>(&lock));
     bool b = !recycle_candidates.empty();
-    vlc_mutex_unlock(const_cast<vlc_mutex_t *>(&lock));
     return b;
 }
 
 void FakeESOut::recycle( FakeESOutID *id )
 {
-    vlc_mutex_lock(&lock);
     fakeesidlist.remove( id );
     recycle_candidates.push_back( id );
-    vlc_mutex_unlock(&lock);
 }
 
 /* Static callbacks */
@@ -325,19 +326,19 @@ void FakeESOut::checkTimestampsStart(vlc_tick_t i_start)
     if( i_start == VLC_TICK_INVALID )
         return;
 
-    vlc_mutex_lock(&lock);
     if( !timestamps_check_done )
     {
         if( i_start < VLC_TICK_FROM_SEC(1) ) /* Starts 0 */
             timestamps_offset = timestamps_expected;
         timestamps_check_done = true;
     }
-    vlc_mutex_unlock(&lock);
 }
 
 int FakeESOut::esOutSend_Callback(es_out_t *fakees, es_out_id_t *p_es, block_t *p_block)
 {
     FakeESOut *me = container_of(fakees, es_out_fake, es_out)->fake;
+    vlc_mutex_locker locker(&me->lock);
+
     FakeESOutID *es_id = reinterpret_cast<FakeESOutID *>( p_es );
     assert(!es_id->scheduledForDeletion());
 
@@ -362,6 +363,8 @@ int FakeESOut::esOutSend_Callback(es_out_t *fakees, es_out_id_t *p_es, block_t *
 void FakeESOut::esOutDel_Callback(es_out_t *fakees, es_out_id_t *p_es)
 {
     FakeESOut *me = container_of(fakees, es_out_fake, es_out)->fake;
+    vlc_mutex_locker locker(&me->lock);
+
     FakeESOutID *es_id = reinterpret_cast<FakeESOutID *>( p_es );
     AbstractCommand *command = me->commandsqueue->factory()->createEsOutDelCommand( es_id );
     if( likely(command) )
@@ -374,6 +377,7 @@ void FakeESOut::esOutDel_Callback(es_out_t *fakees, es_out_id_t *p_es)
 int FakeESOut::esOutControl_Callback(es_out_t *fakees, int i_query, va_list args)
 {
     FakeESOut *me = container_of(fakees, es_out_fake, es_out)->fake;
+    vlc_mutex_locker locker(&me->lock);
 
     switch( i_query )
     {
@@ -431,6 +435,8 @@ int FakeESOut::esOutControl_Callback(es_out_t *fakees, int i_query, va_list args
 void FakeESOut::esOutDestroy_Callback(es_out_t *fakees)
 {
     FakeESOut *me = container_of(fakees, es_out_fake, es_out)->fake;
+    vlc_mutex_locker locker(&me->lock);
+
     AbstractCommand *command = me->commandsqueue->factory()->createEsOutDestroyCommand();
     if( likely(command) )
         me->commandsqueue->Schedule( command );
diff --git a/modules/demux/adaptive/plumbing/FakeESOut.hpp b/modules/demux/adaptive/plumbing/FakeESOut.hpp
index 3c434a7333..aefe3f2976 100644
--- a/modules/demux/adaptive/plumbing/FakeESOut.hpp
+++ b/modules/demux/adaptive/plumbing/FakeESOut.hpp
@@ -38,9 +38,22 @@ namespace adaptive
     class FakeESOut
     {
         public:
+            class LockedFakeEsOut
+            {
+                friend class FakeESOut;
+                public:
+                    ~LockedFakeEsOut();
+                    FakeESOut & operator*();
+                    FakeESOut * operator->();
+                private:
+                    FakeESOut *p;
+                    LockedFakeEsOut(FakeESOut &q);
+            };
             FakeESOut( es_out_t *, CommandsQueue * );
             ~FakeESOut();
             es_out_t * getEsOut();
+            LockedFakeEsOut WithLock();
+            CommandsQueue * commandsQueue();
             void setTimestampOffset( vlc_tick_t );
             void setExpectedTimestampOffset(vlc_tick_t);
             size_t esCount() const;
@@ -68,6 +81,7 @@ namespace adaptive
             static void esOutDestroy_Callback( es_out_t * );
 
         private:
+            friend class LockedFakeESOut;
             vlc_mutex_t lock;
             es_out_t *real_es_out;
             FakeESOutID * createNewID( const es_format_t * );
diff --git a/modules/demux/hls/HLSStreams.cpp b/modules/demux/hls/HLSStreams.cpp
index af68129040..bbeaab0235 100644
--- a/modules/demux/hls/HLSStreams.cpp
+++ b/modules/demux/hls/HLSStreams.cpp
@@ -57,7 +57,7 @@ void HLSStream::setTimeOffset(vlc_tick_t i_offset)
         {
             if(!b_id3_timestamps_offset_set)
             {
-                fakeesout->setTimestampOffset(i_offset);
+                fakeEsOut()->setTimestampOffset(i_offset);
             }
             return;
         }
@@ -116,9 +116,9 @@ block_t * HLSStream::checkBlock(block_t *p_block, bool b_first)
     if( b_meta_updated )
     {
         b_meta_updated = false;
-        AbstractCommand *command = commandsqueue->factory()->createEsOutMetaCommand( -1, p_meta );
+        AbstractCommand *command = fakeEsOut()->commandsQueue()->factory()->createEsOutMetaCommand( -1, p_meta );
         if( command )
-            commandsqueue->Schedule( command );
+            fakeEsOut()->commandsQueue()->Schedule( command );
     }
 
     return p_block;



More information about the vlc-commits mailing list