[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