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

Hugo Beauzée-Luyssen hugo at beauzee.fr
Wed May 18 21:38:10 CEST 2016


On 05/04/2016 04:18 PM, Yikai Lu wrote:
> ---
>  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 );

It's weird to have the width & height for a "generic" clip workflow,
though I suppose this can be part of a future refactoring.

>  
>          /**
>           *  \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 );
> 

That looks good, but it would look even better if merged with the next
commit :)

-- 
Hugo Beauzée-Luyssen
www.beauzee.fr


More information about the Vlmc-devel mailing list