[vlmc-devel] commit: Workflow: Fixing potential deadlock. ( Hugo Beauzée-Luyssen )

git at videolan.org git at videolan.org
Fri May 14 18:51:23 CEST 2010


vlmc | branch: master | Hugo Beauzée-Luyssen <beauze.h at gmail.com> | Wed May 12 18:33:46 2010 +0200| [5d8a8deaace41527684f3ec8df75b30fffd399ae] | committer: Hugo Beauzée-Luyssen 

Workflow: Fixing potential deadlock.

Splitting the stopping process in three parts : first stopping the
ClipWorkflow media player, stopping the renderer, and put the workflow
in a stopped state.
This seems to improve the perfs with a MOV sample, though i don't really
see why it would...

> http://git.videolan.org/gitweb.cgi/vlmc.git/?a=commit;h=5d8a8deaace41527684f3ec8df75b30fffd399ae
---

 src/Renderer/WorkflowRenderer.cpp  |    1 +
 src/Workflow/ClipWorkflow.cpp      |   18 ++++++++++++++----
 src/Workflow/ClipWorkflow.h        |    7 +++++++
 src/Workflow/MainWorkflow.cpp      |    7 +++++++
 src/Workflow/MainWorkflow.h        |    8 ++++++++
 src/Workflow/TrackHandler.cpp      |   12 ++++++++++++
 src/Workflow/TrackHandler.h        |    2 ++
 src/Workflow/TrackWorkflow.cpp     |   24 ++++++++++++++++++++++++
 src/Workflow/TrackWorkflow.h       |    2 ++
 src/Workflow/VideoClipWorkflow.cpp |    3 +++
 10 files changed, 80 insertions(+), 4 deletions(-)

diff --git a/src/Renderer/WorkflowRenderer.cpp b/src/Renderer/WorkflowRenderer.cpp
index 97f5d08..5e8a4ab 100644
--- a/src/Renderer/WorkflowRenderer.cpp
+++ b/src/Renderer/WorkflowRenderer.cpp
@@ -299,6 +299,7 @@ WorkflowRenderer::killRenderer()
     m_isRendering = false;
     m_paused = false;
     m_stopping = true;
+    m_mainWorkflow->stopFrameComputing();
     m_mediaPlayer->stop();
     m_mainWorkflow->stop();
     delete[] m_silencedAudioBuffer;
diff --git a/src/Workflow/ClipWorkflow.cpp b/src/Workflow/ClipWorkflow.cpp
index 190a9cb..1f7eed9 100644
--- a/src/Workflow/ClipWorkflow.cpp
+++ b/src/Workflow/ClipWorkflow.cpp
@@ -114,18 +114,28 @@ void    ClipWorkflow::clipEndReached()
     setState( EndReached );
 }
 
-void            ClipWorkflow::stop()
+void
+ClipWorkflow::stop()
+{
+    flushComputedBuffers();
+    releasePrealocated();
+}
+
+void
+ClipWorkflow::stopRenderer()
 {
     if ( m_mediaPlayer )
     {
+        {
+            QMutexLocker    lock( m_renderLock );
+            m_renderWaitCond->wakeAll();
+        }
         m_mediaPlayer->stop();
         disconnect( m_mediaPlayer, SIGNAL( endReached() ), this, SLOT( clipEndReached() ) );
         MemoryPool<LibVLCpp::MediaPlayer>::getInstance()->release( m_mediaPlayer );
         m_mediaPlayer = NULL;
-        setState( Stopped );
         delete m_vlcMedia;
-        flushComputedBuffers();
-        releasePrealocated();
+        setState( Stopped );
     }
 }
 
diff --git a/src/Workflow/ClipWorkflow.h b/src/Workflow/ClipWorkflow.h
index a181550..f7f43d4 100644
--- a/src/Workflow/ClipWorkflow.h
+++ b/src/Workflow/ClipWorkflow.h
@@ -193,6 +193,13 @@ class   ClipWorkflow : public QObject
          */
         bool                    isResyncRequired();
 
+        /**
+         *  \brief              Stop the renderer part of the ClipWorkflow
+         *
+         *  IE. just stop the VLC thread, and do not flush anything.
+         */
+        void                    stopRenderer();
+
     private:
         void                    setState( State state );
         void                    adjustBegin();
diff --git a/src/Workflow/MainWorkflow.cpp b/src/Workflow/MainWorkflow.cpp
index 9e0f3cf..34a0dc3 100644
--- a/src/Workflow/MainWorkflow.cpp
+++ b/src/Workflow/MainWorkflow.cpp
@@ -196,6 +196,13 @@ MainWorkflow::stop()
 }
 
 void
+MainWorkflow::stopFrameComputing()
+{
+    for ( qint32 type = 0; type < NbTrackType; ++type )
+        m_tracks[type]->stopFrameComputing();
+}
+
+void
 MainWorkflow::moveClip( const QUuid &clipUuid, unsigned int oldTrack,
                         unsigned int newTrack, qint64 startingFrame,
                         MainWorkflow::TrackType trackType,
diff --git a/src/Workflow/MainWorkflow.h b/src/Workflow/MainWorkflow.h
index 2aff016..2d4f096 100644
--- a/src/Workflow/MainWorkflow.h
+++ b/src/Workflow/MainWorkflow.h
@@ -339,6 +339,14 @@ class   MainWorkflow : public QObject, public Singleton<MainWorkflow>
          */
         bool                    contains( const QUuid& uuid ) const;
 
+        /**
+         *  \brief      Stop the frame computing process.
+         *
+         *  This will stop all the currently running ClipWorkflow.
+         *  This is meant to be called just before the stop() method.
+         */
+        void                    stopFrameComputing();
+
     private:
         MainWorkflow( int trackCount = 64 );
         ~MainWorkflow();
diff --git a/src/Workflow/TrackHandler.cpp b/src/Workflow/TrackHandler.cpp
index 0f2cdec..b1b9b72 100644
--- a/src/Workflow/TrackHandler.cpp
+++ b/src/Workflow/TrackHandler.cpp
@@ -325,3 +325,15 @@ TrackHandler::contains( const QUuid &uuid ) const
             return true;
     return false;
 }
+
+void
+TrackHandler::stopFrameComputing()
+{
+    for ( unsigned int i = 0; i < m_trackCount; ++i )
+    {
+        //First stop the frame computing
+        m_tracks[i]->stopFrameComputing();
+        //then deactivate the track to avoid the generation to be resumed.
+        m_tracks[i].deactivate();
+    }
+}
diff --git a/src/Workflow/TrackHandler.h b/src/Workflow/TrackHandler.h
index 39b95d3..e059683 100644
--- a/src/Workflow/TrackHandler.h
+++ b/src/Workflow/TrackHandler.h
@@ -101,6 +101,8 @@ class   TrackHandler : public QObject
 
         bool                    contains( const QUuid& uuid ) const;
 
+        void                    stopFrameComputing();
+
     private:
         void                    computeLength();
         void                    activateTrack( unsigned int tracKId );
diff --git a/src/Workflow/TrackWorkflow.cpp b/src/Workflow/TrackWorkflow.cpp
index 0370aae..4f55e88 100644
--- a/src/Workflow/TrackWorkflow.cpp
+++ b/src/Workflow/TrackWorkflow.cpp
@@ -526,3 +526,27 @@ TrackWorkflow::contains( const QUuid &uuid ) const
     }
     return false;
 }
+
+void
+TrackWorkflow::stopFrameComputing()
+{
+    QMap<qint64, ClipWorkflow*>::const_iterator       it = m_clips.begin();
+    QMap<qint64, ClipWorkflow*>::const_iterator       end = m_clips.end();
+
+    while ( it != end )
+    {
+        ClipWorkflow*   cw = it.value();
+
+        cw->getStateLock()->lockForRead();
+
+        if ( cw->getState() == ClipWorkflow::Stopped ||
+             cw->getState() == ClipWorkflow::Muted )
+        {
+            cw->getStateLock()->unlock();
+            return ;
+        }
+        cw->getStateLock()->unlock();
+        cw->stopRenderer();
+        ++it;
+    }
+}
diff --git a/src/Workflow/TrackWorkflow.h b/src/Workflow/TrackWorkflow.h
index b503cb7..3f3dab6 100644
--- a/src/Workflow/TrackWorkflow.h
+++ b/src/Workflow/TrackWorkflow.h
@@ -87,6 +87,8 @@ class   TrackWorkflow : public QObject
 
         bool                                    contains( const QUuid& uuid ) const;
 
+        void                                    stopFrameComputing();
+
     private:
         void                                    computeLength();
         void*                                   renderClip( ClipWorkflow* cw, qint64 currentFrame,
diff --git a/src/Workflow/VideoClipWorkflow.cpp b/src/Workflow/VideoClipWorkflow.cpp
index 1d53317..0aba2d3 100644
--- a/src/Workflow/VideoClipWorkflow.cpp
+++ b/src/Workflow/VideoClipWorkflow.cpp
@@ -116,6 +116,9 @@ VideoClipWorkflow::getOutput( ClipWorkflow::GetMode mode )
         return NULL;
     if ( getNbComputedBuffers() == 0 )
         m_renderWaitCond->wait( m_renderLock );
+    //Recheck again, as the WaitCondition may have been awaken when stopping.
+    if ( getNbComputedBuffers() == 0 )
+        return NULL;
     ::StackedBuffer<LightVideoFrame*>* buff;
     if ( mode == ClipWorkflow::Pop )
         buff = new StackedBuffer( m_computedBuffers.dequeue(), this, true );



More information about the Vlmc-devel mailing list