Commit 285af18a authored by luyikei's avatar luyikei Committed by Hugo Beauzée-Luyssen

Use ClipSmemRenderer

Signed-off-by: 's avatarHugo Beauzée-Luyssen <hugo@beauzee.fr>
parent 1557e187
......@@ -74,6 +74,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
......@@ -86,15 +87,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)
......
......@@ -261,7 +261,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();
......@@ -305,7 +305,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();
......
......@@ -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"
......@@ -42,6 +43,7 @@ ClipWorkflow::ClipWorkflow( ClipHelper* ch )
, m_eventWatcher( nullptr )
, m_clipHelper( ch )
, m_state( ClipWorkflow::Stopped )
, m_fullSpeedRender( false )
, m_muted( false )
{
m_stateLock = new QReadWriteLock;
......@@ -61,30 +63,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, m_fullSpeedRender );
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 +117,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;
......@@ -131,15 +156,6 @@ ClipWorkflow::stop()
m_renderer->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 )
{
......@@ -165,34 +181,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 +232,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
......
......@@ -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
......@@ -142,11 +128,6 @@ class ClipWorkflow : public EffectUser
*/
void stop();
/**
* \brief Pause this workflow.
*/
void pause();
/**
* \brief Set the rendering position
* \param time The position in millisecond
......@@ -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,
......
......@@ -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;
......
......@@ -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 );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment