[vlmc-devel] [PATCH 06/10] Use ClipSmemRenderer

Yikai Lu luyikei.qmltu at gmail.com
Wed May 4 16:18:37 CEST 2016


---
 src/CMakeLists.txt                |   4 +-
 src/Renderer/ClipSmemRenderer.cpp |   4 +-
 src/Workflow/ClipWorkflow.cpp     | 100 ++++++++++++++++++++------------------
 src/Workflow/ClipWorkflow.h       |  47 ++++--------------
 src/Workflow/TrackWorkflow.cpp    |  47 ++++++------------
 src/Workflow/TrackWorkflow.h      |   2 +-
 6 files changed, 83 insertions(+), 121 deletions(-)

diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 75d6679..9b1a88d 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -66,6 +66,7 @@ SET(VLMC_SRCS
     Project/WorkspaceWorker.cpp
     Project/RecentProjects.cpp
     Renderer/AbstractRenderer.cpp
+    Renderer/ClipSmemRenderer.cpp
     Renderer/WorkflowRenderer.cpp
     Services/AbstractSharingService.h
     Services/UploaderIODevice.cpp
@@ -78,15 +79,12 @@ SET(VLMC_SRCS
     Tools/Toggleable.hpp
     Tools/VlmcDebug.h
     Tools/VlmcLogger.cpp
-    Workflow/AudioClipWorkflow.cpp
     Workflow/ClipWorkflow.cpp
     Workflow/ClipHelper.cpp
     Workflow/Helper.cpp
-    Workflow/ImageClipWorkflow.cpp
     Workflow/MainWorkflow.cpp
     Workflow/TrackWorkflow.cpp
     Workflow/Types.cpp
-    Workflow/VideoClipWorkflow.cpp
   )
 
 IF (WIN32)
diff --git a/src/Renderer/ClipSmemRenderer.cpp b/src/Renderer/ClipSmemRenderer.cpp
index 5565d5b..b44c7cf 100644
--- a/src/Renderer/ClipSmemRenderer.cpp
+++ b/src/Renderer/ClipSmemRenderer.cpp
@@ -264,7 +264,7 @@ ClipSmemRenderer::audioUnlock( void *data, uint8_t *pcm_buffer, unsigned int cha
     ClipSmemRenderer* renderer = reinterpret_cast<ClipSmemRenderer*>( data );
 
     Workflow::Frame     *frame = renderer->m_computedBuffers[Workflow::AudioTrack].last();
-    frame->pts = pts;
+    frame->setPts( pts );
     renderer->m_renderWaitCond[Workflow::AudioTrack]->wakeAll();
     if ( maxNumBuffers( Workflow::AudioTrack ) <= renderer->m_computedBuffers[Workflow::AudioTrack].count() )
         emit renderer->bufferReachedMax();
@@ -308,7 +308,7 @@ ClipSmemRenderer::videoUnlock( void *data, uint8_t *buffer, int width, int heigh
     ClipSmemRenderer* renderer = reinterpret_cast<ClipSmemRenderer*>( data );
 
     Workflow::Frame     *frame = renderer->m_computedBuffers[Workflow::VideoTrack].last();
-    frame->pts = pts;
+    frame->setPts( pts );
     renderer->m_renderWaitCond[Workflow::VideoTrack]->wakeAll();
     if ( maxNumBuffers( Workflow::VideoTrack ) <= renderer->m_computedBuffers[Workflow::VideoTrack].count() )
         emit renderer->bufferReachedMax();
diff --git a/src/Workflow/ClipWorkflow.cpp b/src/Workflow/ClipWorkflow.cpp
index f7fa55c..c272c48 100644
--- a/src/Workflow/ClipWorkflow.cpp
+++ b/src/Workflow/ClipWorkflow.cpp
@@ -31,6 +31,7 @@
 #include "ClipWorkflow.h"
 #include "Backend/ISource.h"
 #include "Backend/ISourceRenderer.h"
+#include "Renderer/ClipSmemRenderer.h"
 #include "Media/Media.h"
 #include "Tools/RendererEventWatcher.h"
 #include "Workflow/Types.h"
@@ -61,30 +62,53 @@ ClipWorkflow::~ClipWorkflow()
     delete m_stateLock;
 }
 
+Workflow::Frame*
+ClipWorkflow::getOutput( Workflow::TrackType trackType, ClipSmemRenderer::GetMode mode, qint64 currentFrame )
+{
+    if ( m_clipHelper->clip()->media()->fileType() == Media::Image )
+        mode = ClipSmemRenderer::Get;
+
+    auto ret = m_renderer->getOutput( trackType, mode, currentFrame );
+    if ( ret )
+    {
+        computePtsDiff( ret->pts(), trackType );
+        ret->ptsDiff = m_currentPts[trackType] - m_previousPts[trackType];
+    }
+    if ( trackType == Workflow::VideoTrack )
+    {
+        auto newFrame = applyFilters( ret, currentFrame );
+        if ( newFrame != nullptr )
+            ret->setBuffer( newFrame );
+    }
+
+    return ret;
+}
+
 void
-ClipWorkflow::initialize()
+ClipWorkflow::initialize( quint32 width, quint32 height )
 {
     QWriteLocker lock( m_stateLock );
     m_state = ClipWorkflow::Initializing;
 
     delete m_renderer;
-    m_renderer = m_clipHelper->clip()->media()->source()->createRenderer( m_eventWatcher );
-
-    preallocate();
-    initializeInternals();
+    m_renderer = new ClipSmemRenderer( m_clipHelper, width, height );
+    if ( m_clipHelper->formats() & ClipHelper::Video )
+        initFilters();
 
-    m_currentPts = -1;
-    m_previousPts = -1;
+    for ( int i = 0; i < Workflow::NbTrackType; ++i )
+    {
+        m_currentPts[i] = -1;
+        m_previousPts[i] = -1;
+    }
     m_pauseDuration = -1;
 
     //Use QueuedConnection to avoid getting called from intf-event callback, as
     //we will trigger intf-event callback as well when setting time for this clip,
     //thus resulting in a deadlock.
-    connect( m_eventWatcher, SIGNAL( playing() ), this, SLOT( loadingComplete() ), Qt::QueuedConnection );
-    connect( m_eventWatcher, SIGNAL( endReached() ), this, SLOT( clipEndReached() ), Qt::DirectConnection );
-    connect( m_eventWatcher, SIGNAL( errorEncountered() ), this, SLOT( errorEncountered() ) );
-    connect( m_eventWatcher, &RendererEventWatcher::stopped, this, &ClipWorkflow::mediaPlayerStopped );
-    connect( this, &ClipWorkflow::bufferReachedMax, this, &ClipWorkflow::pause, Qt::QueuedConnection );
+    connect( m_renderer->eventWatcher(), SIGNAL( playing() ), this, SLOT( loadingComplete() ), Qt::QueuedConnection );
+    connect( m_renderer->eventWatcher(), SIGNAL( endReached() ), this, SLOT( clipEndReached() ), Qt::DirectConnection );
+    connect( m_renderer->eventWatcher(), SIGNAL( errorEncountered() ), this, SLOT( errorEncountered() ) );
+    connect( m_renderer->eventWatcher(), &RendererEventWatcher::stopped, this, &ClipWorkflow::mediaPlayerStopped );
     m_renderer->start();
 }
 
@@ -92,9 +116,9 @@ void
 ClipWorkflow::loadingComplete()
 {
     adjustBegin();
-    disconnect( m_eventWatcher, SIGNAL( playing() ), this, SLOT( loadingComplete() ) );
-    connect( m_eventWatcher, SIGNAL( playing() ), this, SLOT( mediaPlayerUnpaused() ), Qt::DirectConnection );
-    connect( m_eventWatcher, SIGNAL( paused() ), this, SLOT( mediaPlayerPaused() ), Qt::DirectConnection );
+    disconnect( m_renderer->eventWatcher(), SIGNAL( playing() ), this, SLOT( loadingComplete() ) );
+    connect( m_renderer->eventWatcher(), SIGNAL( playing() ), this, SLOT( mediaPlayerUnpaused() ), Qt::DirectConnection );
+    connect( m_renderer->eventWatcher(), SIGNAL( paused() ), this, SLOT( mediaPlayerPaused() ), Qt::DirectConnection );
     QWriteLocker lock( m_stateLock );
     m_isRendering = true;
     m_state = Rendering;
@@ -132,15 +156,6 @@ ClipWorkflow::stop()
 }
 
 void
-ClipWorkflow::pause()
-{
-    if ( m_renderer != nullptr ) {
-        m_renderer->setPause( true );
-        vlmcWarning() << "ClipWorkflow:" << m_clipHelper->uuid() << " was paused unexpectedly";
-    }
-}
-
-void
 ClipWorkflow::setTime( qint64 time )
 {
     vlmcDebug() << "Setting ClipWorkflow" << m_clipHelper->uuid() << "time:" << time;
@@ -165,34 +180,24 @@ ClipWorkflow::waitForCompleteInit()
 }
 
 void
-ClipWorkflow::postGetOutput()
-{
-    //If we're running out of computed buffers, refill our stack.
-    if ( getNbComputedBuffers() < getMaxComputedBuffers() / 3 )
-        m_renderer->setPause( false );
-    //Don't test using availableBuffer, as it may evolve if a buffer is required while
-    //no one is available : we would spawn a new buffer, thus modifying the number of available buffers
-    else if ( getNbComputedBuffers() >= getMaxComputedBuffers() )
-    {
-        // It's OK to check from here: if getOutput is not called, it means the clipworkflow is
-        // stopped or preloading, in which case, we don't care about the buffer queue growing uncontrolled
-        m_renderer->setPause( true );
-    }
-}
-
-void
-ClipWorkflow::computePtsDiff( qint64 pts )
+ClipWorkflow::computePtsDiff( qint64 pts, Workflow::TrackType trackType )
 {
     if ( m_pauseDuration != -1 )
     {
         //No need to check for m_currentPtr before, as we can't start in paused mode.
         //so m_currentPts will not be -1
-        m_previousPts = m_currentPts + m_pauseDuration;
+        m_previousPts[trackType] = m_currentPts[trackType] + m_pauseDuration;
         m_pauseDuration = -1;
     }
     else
-        m_previousPts = m_currentPts;
-    m_currentPts = qMax( pts, m_previousPts );
+        m_previousPts[trackType] = m_currentPts[trackType];
+    m_currentPts[trackType] = qMax( pts, m_previousPts[trackType] );
+}
+
+void
+ClipWorkflow::flushComputedBuffers()
+{
+    m_renderer->flushComputedBuffers();
 }
 
 void
@@ -226,8 +231,11 @@ void
 ClipWorkflow::resyncClipWorkflow()
 {
     flushComputedBuffers();
-    m_previousPts = -1;
-    m_currentPts = -1;
+    for ( int i = 0; i < Workflow::NbTrackType; ++i )
+    {
+        m_currentPts[i] = -1;
+        m_previousPts[i] = -1;
+    }
 }
 
 void
diff --git a/src/Workflow/ClipWorkflow.h b/src/Workflow/ClipWorkflow.h
index 5419a23..0b812e7 100644
--- a/src/Workflow/ClipWorkflow.h
+++ b/src/Workflow/ClipWorkflow.h
@@ -28,6 +28,7 @@
 #include "EffectsEngine/EffectUser.h"
 #include "ClipHelper.h"
 #include "Workflow/Types.h"
+#include "Renderer/ClipSmemRenderer.h"
 
 #include <QObject>
 #include <QUuid>
@@ -78,17 +79,6 @@ class   ClipWorkflow : public EffectUser
             Error               //5
         };
 
-        /**
-         *  \brief  Used to know which way you want to get a computed output.
-         *          Pop: the buffer is popped and returned
-         *          Get: the buffer is just returned (for paused mode for instance)
-         */
-        enum        GetMode
-        {
-            Pop,
-            Get,
-        };
-
         ClipWorkflow( ClipHelper* clip );
         virtual ~ClipWorkflow();
 
@@ -97,18 +87,14 @@ class   ClipWorkflow : public EffectUser
          *  therefore, you can call this method blindly, without taking care
          *  of the rendering process advancement.
          */
-        virtual Workflow::OutputBuffer      *getOutput( ClipWorkflow::GetMode mode, qint64 currentFrame ) = 0;
-        virtual Workflow::TrackType         type() const = 0;
-        void                    postGetOutput();
+        Workflow::Frame*        getOutput( Workflow::TrackType trackType, ClipSmemRenderer::GetMode mode, qint64 currentFrame );
         /**
          * @brief Initialize base variables for the SourceRenderer.
          *
          * This may also perform some addditional initializations, and
          * therefore should be called before createSoutChain()
          */
-        virtual void            initializeInternals() = 0;
-        virtual void            preallocate() = 0;
-        void                    initialize();
+        void                    initialize( quint32 width, quint32 height );
 
         /**
          *  \return             true if the ClipWorkflow is able to, and should render
@@ -143,11 +129,6 @@ class   ClipWorkflow : public EffectUser
         void                    stop();
 
         /**
-         *  \brief  Pause this workflow.
-         */
-        void                    pause();
-
-        /**
          *  \brief  Set the rendering position
          *  \param  time    The position in millisecond
          *  \param  frame   The new current frame.
@@ -181,25 +162,15 @@ class   ClipWorkflow : public EffectUser
         void                    adjustBegin();
 
     protected:
-        void                    computePtsDiff( qint64 pts );
-        /**
-         *  \warning    Must be called from a thread safe context.
-         *              This thread safe context has to be set
-         *              from the underlying ClipWorkflow implementation.
-         */
-        virtual quint32         getNbComputedBuffers() const = 0;
-        virtual quint32         getMaxComputedBuffers() const = 0;
+        void                    computePtsDiff( qint64 pts , Workflow::TrackType trackType );
+
         /**
          *  \brief  Will empty the computed buffers stack.
          *          This has to be implemented in the underlying
          *          clipworkflow implementation.
          */
-        virtual void            flushComputedBuffers() = 0;
+        void                    flushComputedBuffers();
 
-        /**
-         *  \brief  Release the preallocated buffers
-         */
-        virtual void            releasePrealocated() = 0;
 
     private:
         /**
@@ -217,14 +188,14 @@ class   ClipWorkflow : public EffectUser
         bool                    m_resyncRequired;
 
     protected:
-        Backend::ISourceRenderer*   m_renderer;
+        ClipSmemRenderer*           m_renderer;
         RendererEventWatcher*       m_eventWatcher;
         ClipHelper*                 m_clipHelper;
         QMutex*                     m_renderLock;
         QReadWriteLock*             m_stateLock;
         State                       m_state;
-        qint64                      m_previousPts;
-        qint64                      m_currentPts;
+        qint64                      m_previousPts[Workflow::NbTrackType];
+        qint64                      m_currentPts[Workflow::NbTrackType];
         /**
          *  \brief  This is used for basic synchronisation when
          *          the clipworkflow hasn't generate a frame yet,
diff --git a/src/Workflow/TrackWorkflow.cpp b/src/Workflow/TrackWorkflow.cpp
index f40ed4c..9d34269 100644
--- a/src/Workflow/TrackWorkflow.cpp
+++ b/src/Workflow/TrackWorkflow.cpp
@@ -26,17 +26,15 @@
 #include "Project/Project.h"
 #include "Media/Clip.h"
 #include "ClipHelper.h"
-#include "AudioClipWorkflow.h"
+#include "ClipWorkflow.h"
 #include "EffectsEngine/EffectInstance.h"
 #include "EffectsEngine/EffectHelper.h"
-#include "ImageClipWorkflow.h"
 #include "Backend/ISource.h"
 #include "Main/Core.h"
 #include "Library/Library.h"
 #include "MainWorkflow.h"
 #include "Media/Media.h"
 #include "Types.h"
-#include "VideoClipWorkflow.h"
 #include "vlmc.h"
 #include "Tools/VlmcDebug.h"
 
@@ -80,22 +78,7 @@ TrackWorkflow::~TrackWorkflow()
 void
 TrackWorkflow::addClip( ClipHelper* ch, qint64 start )
 {
-    ClipWorkflow* cw;
-    if ( ch->clip()->media()->fileType() == Media::FileType::Video )
-        // FIXME: This whole if statement will be gone as soon as I implement a united ClipWorkflow,
-        //        which can generate both audio and video buffers.
-        if ( ch->formats() & ClipHelper::Video )
-            cw = new VideoClipWorkflow( ch );
-        else if ( ch->formats() & ClipHelper::Audio )
-            cw = new AudioClipWorkflow( ch );
-        else
-            vlmcFatal( "Nothing to render from this clip!" );
-    else if ( ch->clip()->media()->fileType() == Media::FileType::Audio )
-        cw = new AudioClipWorkflow( ch );
-    else if ( ch->clip()->media()->fileType() == Media::FileType::Image )
-        cw = new ImageClipWorkflow( ch );
-    else
-        vlmcFatal( "Unknown file type!" );
+    ClipWorkflow* cw = new ClipWorkflow( ch );
     ch->setClipWorkflow( cw );
     addClip( cw, start );
 }
@@ -180,15 +163,15 @@ TrackWorkflow::getClipHelper( const QUuid& uuid )
 }
 
 Workflow::OutputBuffer*
-TrackWorkflow::renderClip( ClipWorkflow* cw, qint64 currentFrame,
+TrackWorkflow::renderClip( Workflow::TrackType trackType, ClipWorkflow* cw, qint64 currentFrame,
                                         qint64 start , bool needRepositioning,
                                         bool renderOneFrame, bool paused )
 {
     if ( cw->isMuted() == true )
         return nullptr;
 
-    ClipWorkflow::GetMode       mode = ( paused == false || renderOneFrame == true ?
-                                         ClipWorkflow::Pop : ClipWorkflow::Get );
+    ClipSmemRenderer::GetMode       mode = ( paused == false || renderOneFrame == true ?
+                                                 ClipSmemRenderer::Pop : ClipSmemRenderer::Get );
 
     ClipWorkflow::State state = cw->getState();
     if ( state == ClipWorkflow::Rendering ||
@@ -196,12 +179,12 @@ TrackWorkflow::renderClip( ClipWorkflow* cw, qint64 currentFrame,
     {
         if ( cw->isResyncRequired() == true || needRepositioning == true )
             adjustClipTime( currentFrame, start, cw );
-        return cw->getOutput( mode, currentFrame - start );
+        return cw->getOutput( trackType, mode, currentFrame - start );
     }
     else if ( state == ClipWorkflow::Stopped || state == ClipWorkflow::Initializing )
     {
         if ( state == ClipWorkflow::Stopped )
-            cw->initialize();
+            cw->initialize( m_width, m_height );
         //If the init failed, don't even try to call getOutput.
         if ( cw->waitForCompleteInit() == false )
             return nullptr;
@@ -211,7 +194,7 @@ TrackWorkflow::renderClip( ClipWorkflow* cw, qint64 currentFrame,
             //Clip was not started at its real begining: adjust the position
             adjustClipTime( currentFrame, start, cw );
         }
-        return cw->getOutput( mode, currentFrame - start );
+        return cw->getOutput( trackType, mode, currentFrame - start );
     }
     else if ( state == ClipWorkflow::EndReached ||
               state == ClipWorkflow::Error )
@@ -230,7 +213,7 @@ void
 TrackWorkflow::preloadClip( ClipWorkflow* cw )
 {
     if ( cw->getState() == ClipWorkflow::Stopped )
-        cw->initialize();
+        cw->initialize( m_width, m_height );
 }
 
 void
@@ -310,17 +293,19 @@ TrackWorkflow::getOutput( Workflow::TrackType trackType, qint64 currentFrame, qi
         qint64          start = it.key();
         ClipWorkflow*   cw = it.value();
 
-        if ( trackType != cw->type() )
+        if ( ( trackType == Workflow::VideoTrack && cw->getClipHelper()->formats().testFlag( ClipHelper::Video ) == false ) ||
+             ( trackType == Workflow::AudioTrack && cw->getClipHelper()->formats().testFlag( ClipHelper::Audio ) == false ) ||
+             cw->getClipHelper()->formats().testFlag( ClipHelper::None )
+             )
         {
             ++it;
             continue ;
         }
-
         //Is the clip supposed to render now?
         if ( start <= currentFrame && currentFrame <= start + cw->getClipHelper()->length() )
         {
-            ret = renderClip( cw, currentFrame, start, needRepositioning,
-                              renderOneFrame, paused );
+            ret = renderClip( trackType, cw, currentFrame, start, needRepositioning,
+                                     renderOneFrame, paused );
             if ( trackType == Workflow::VideoTrack )
             {
                 frames[frameId] = static_cast<Workflow::Frame*>( ret );
@@ -613,7 +598,7 @@ TrackWorkflow::initRender( quint32 width, quint32 height )
 {
     QReadLocker     lock( m_clipsLock );
 
-    m_mixerBuffer->resize( width, height );
+    m_mixerBuffer->resize( width * height * Workflow::Depth );
     m_width = width;
     m_height = height;
     m_isRendering = true;
diff --git a/src/Workflow/TrackWorkflow.h b/src/Workflow/TrackWorkflow.h
index d9369d2..dff05b0 100644
--- a/src/Workflow/TrackWorkflow.h
+++ b/src/Workflow/TrackWorkflow.h
@@ -102,7 +102,7 @@ class   TrackWorkflow : public EffectUser
 
     private:
         void                                    computeLength();
-        Workflow::OutputBuffer                  *renderClip( ClipWorkflow* cw, qint64 currentFrame,
+        Workflow::OutputBuffer                  *renderClip( Workflow::TrackType trackType, ClipWorkflow* cw, qint64 currentFrame,
                                                             qint64 start, bool needRepositioning,
                                                             bool renderOneFrame, bool paused );
         void                                    preloadClip( ClipWorkflow* cw );
-- 
1.9.1



More information about the Vlmc-devel mailing list