Commit 116529cc authored by Hugo Beauzee-Luyssen's avatar Hugo Beauzee-Luyssen

Added a synchrone mode for rendering

parent b909f520
...@@ -116,9 +116,10 @@ void ClipWorkflow::unlock( ClipWorkflow* cw ) ...@@ -116,9 +116,10 @@ void ClipWorkflow::unlock( ClipWorkflow* cw )
cw->m_stateLock->unlock(); cw->m_stateLock->unlock();
//Signal that render has been completed. //Signal that render has been completed.
cw->m_renderWaitCond->wake(); cw->m_renderWaitCond->wake();
qDebug() << "Render completed";
cw->emit renderComplete( cw ); cw->emit renderComplete( cw );
// qDebug() << "Entering condwait"; qDebug() << "Entering condwait";
cw->m_waitCond->wait( cw->m_condMutex ); cw->m_waitCond->wait( cw->m_condMutex );
// qDebug() << "Leaved condwait"; // qDebug() << "Leaved condwait";
cw->m_stateLock->lockForWrite(); cw->m_stateLock->lockForWrite();
......
...@@ -46,15 +46,23 @@ MainWorkflow::MainWorkflow( int trackCount ) : ...@@ -46,15 +46,23 @@ MainWorkflow::MainWorkflow( int trackCount ) :
m_tracks[i].setPtr( new TrackWorkflow( i ) ); m_tracks[i].setPtr( new TrackWorkflow( i ) );
connect( m_tracks[i], SIGNAL( trackEndReached( unsigned int ) ), this, SLOT( trackEndReached(unsigned int) ) ); connect( m_tracks[i], SIGNAL( trackEndReached( unsigned int ) ), this, SLOT( trackEndReached(unsigned int) ) );
connect( m_tracks[i], SIGNAL( trackPaused() ), this, SLOT( trackPaused() ) ); connect( m_tracks[i], SIGNAL( trackPaused() ), this, SLOT( trackPaused() ) );
connect( m_tracks[i], SIGNAL( renderCompleted( unsigned int ) ), this, SLOT( tracksRenderCompleted( unsigned int ) ), Qt::DirectConnection );
} }
m_renderStartedLock = new QReadWriteLock; m_renderStartedLock = new QReadWriteLock;
m_renderMutex = new QMutex; m_renderMutex = new QMutex;
m_highestTrackNumberMutex = new QMutex;
m_synchroneRenderWaitCondition = new QWaitCondition;
m_synchroneRenderWaitConditionMutex = new QMutex;
} }
MainWorkflow::~MainWorkflow() MainWorkflow::~MainWorkflow()
{ {
stop(); stop();
delete m_synchroneRenderWaitConditionMutex;
delete m_synchroneRenderWaitCondition;
delete m_highestTrackNumberMutex;
delete m_renderMutex;
delete m_renderStartedLock; delete m_renderStartedLock;
for (unsigned int i = 0; i < m_trackCount; ++i) for (unsigned int i = 0; i < m_trackCount; ++i)
delete m_tracks[i]; delete m_tracks[i];
...@@ -102,6 +110,12 @@ unsigned char* MainWorkflow::getOutput() ...@@ -102,6 +110,12 @@ unsigned char* MainWorkflow::getOutput()
QReadLocker lock( m_renderStartedLock ); QReadLocker lock( m_renderStartedLock );
QMutexLocker lock2( m_renderMutex ); QMutexLocker lock2( m_renderMutex );
{
QMutexLocker lockHighestTrackNumber( m_highestTrackNumberMutex );
m_highestTrackNumber = 0;
}
m_nbTracksToRender = 0;
m_synchroneRenderingBuffer = NULL;
if ( m_renderStarted == true ) if ( m_renderStarted == true )
{ {
unsigned char* ret; unsigned char* ret;
...@@ -110,12 +124,15 @@ unsigned char* MainWorkflow::getOutput() ...@@ -110,12 +124,15 @@ unsigned char* MainWorkflow::getOutput()
{ {
if ( m_tracks[i].activated() == false ) if ( m_tracks[i].activated() == false )
continue ; continue ;
if ( ( ret = m_tracks[i]->getOutput( m_currentFrame ) ) != NULL ) if ( ( ret = m_tracks[i]->getOutput( m_currentFrame ) ) != NULL )
{
m_nbTracksToRender.fetchAndAddAcquire( 1 );
break ; break ;
}
} }
if ( ret == NULL ) if ( ret == NULL )
ret = MainWorkflow::blackOutput; ret = MainWorkflow::blackOutput;
nextFrame(); nextFrame();
return ret; return ret;
} }
...@@ -261,3 +278,44 @@ void MainWorkflow::trackPaused() ...@@ -261,3 +278,44 @@ void MainWorkflow::trackPaused()
emit mainWorkflowPaused(); emit mainWorkflowPaused();
} }
} }
void MainWorkflow::tracksRenderCompleted( unsigned int trackId )
{
m_nbTracksToRender.fetchAndAddAcquire( -1 );
{
QMutexLocker lock( m_highestTrackNumberMutex );
if ( m_highestTrackNumber <= trackId )
{
m_highestTrackNumber = trackId;
m_synchroneRenderingBuffer = m_tracks[trackId]->getSynchroneOutput();
}
}
//We check for minus or equal, since we can have 0 frame to compute,
//therefore, m_nbTracksToRender will be equal to -1
if ( m_nbTracksToRender <= 0 )
{
qDebug() << "MainWorkflow render completed";
//Just a synchronisation barriere
{
QMutexLocker lock( m_synchroneRenderWaitConditionMutex );
}
m_synchroneRenderWaitCondition->wakeAll();
}
else
qDebug() << m_nbTracksToRender << "tracks left to render";
}
unsigned char* MainWorkflow::getSynchroneOutput()
{
m_synchroneRenderWaitConditionMutex->lock();
getOutput();
qDebug() << "Waiting for synchrone output";
m_synchroneRenderWaitCondition->wait( m_synchroneRenderWaitConditionMutex );
qDebug() << "Got it";
m_synchroneRenderWaitConditionMutex->unlock();
qDebug() << (void*)m_synchroneRenderingBuffer;
if ( m_synchroneRenderingBuffer == NULL )
return MainWorkflow::blackOutput;
return m_synchroneRenderingBuffer;
}
...@@ -43,6 +43,7 @@ class MainWorkflow : public QObject, public Singleton<MainWorkflow> ...@@ -43,6 +43,7 @@ class MainWorkflow : public QObject, public Singleton<MainWorkflow>
void addClip( Clip* clip, unsigned int trackId, qint64 start ); void addClip( Clip* clip, unsigned int trackId, qint64 start );
void startRender(); void startRender();
unsigned char* getOutput(); unsigned char* getOutput();
unsigned char* getSynchroneOutput();
/** /**
* \brief Set the workflow position * \brief Set the workflow position
...@@ -99,6 +100,12 @@ class MainWorkflow : public QObject, public Singleton<MainWorkflow> ...@@ -99,6 +100,12 @@ class MainWorkflow : public QObject, public Singleton<MainWorkflow>
QMutex* m_renderMutex; QMutex* m_renderMutex;
QAtomicInt m_nbTracksToPause; QAtomicInt m_nbTracksToPause;
QAtomicInt m_nbTracksToRender;
QMutex* m_highestTrackNumberMutex;
unsigned int m_highestTrackNumber;
unsigned char* m_synchroneRenderingBuffer;
QWaitCondition* m_synchroneRenderWaitCondition;
QMutex* m_synchroneRenderWaitConditionMutex;
public slots: public slots:
void clipMoved( QUuid, int, int, qint64 ); void clipMoved( QUuid, int, int, qint64 );
...@@ -106,6 +113,7 @@ class MainWorkflow : public QObject, public Singleton<MainWorkflow> ...@@ -106,6 +113,7 @@ class MainWorkflow : public QObject, public Singleton<MainWorkflow>
private slots: private slots:
void trackEndReached( unsigned int trackId ); void trackEndReached( unsigned int trackId );
void trackPaused(); void trackPaused();
void tracksRenderCompleted( unsigned int trackId );
signals: signals:
/** /**
......
...@@ -29,7 +29,8 @@ TrackWorkflow::TrackWorkflow( unsigned int trackId ) : ...@@ -29,7 +29,8 @@ TrackWorkflow::TrackWorkflow( unsigned int trackId ) :
m_trackId( trackId ), m_trackId( trackId ),
m_length( 0 ), m_length( 0 ),
m_forceRepositionning( false ), m_forceRepositionning( false ),
m_paused( false ) m_paused( false ),
m_synchroneRenderBuffer( NULL )
{ {
m_forceRepositionningMutex = new QMutex; m_forceRepositionningMutex = new QMutex;
m_clipsLock = new QReadWriteLock; m_clipsLock = new QReadWriteLock;
...@@ -101,6 +102,7 @@ unsigned char* TrackWorkflow::renderClip( ClipWorkflow* cw, qint64 currentF ...@@ -101,6 +102,7 @@ unsigned char* TrackWorkflow::renderClip( ClipWorkflow* cw, qint64 currentF
} }
if ( cw->getState() == ClipWorkflow::Rendering ) if ( cw->getState() == ClipWorkflow::Rendering )
{ {
qDebug() << "Rendering a 'Rendering' ClipWorkflow";
//The rendering state meens... whell it means that the frame is //The rendering state meens... whell it means that the frame is
//beeing rendered, so we wait. //beeing rendered, so we wait.
cw->getStateLock()->unlock(); cw->getStateLock()->unlock();
...@@ -114,7 +116,9 @@ unsigned char* TrackWorkflow::renderClip( ClipWorkflow* cw, qint64 currentF ...@@ -114,7 +116,9 @@ unsigned char* TrackWorkflow::renderClip( ClipWorkflow* cw, qint64 currentF
//If frame has been rendered : //If frame has been rendered :
if ( cw->getState() == ClipWorkflow::Sleeping || pauseAfterRender == true ) if ( cw->getState() == ClipWorkflow::Sleeping || pauseAfterRender == true )
{ {
qDebug() << "renderign a sleeping clip worjkflow";
cw->getStateLock()->unlock(); cw->getStateLock()->unlock();
if ( needRepositioning == true ) if ( needRepositioning == true )
{ {
float pos = ( (float)( currentFrame - start ) / (float)(cw->getClip()->getLength()) ); float pos = ( (float)( currentFrame - start ) / (float)(cw->getClip()->getLength()) );
...@@ -127,6 +131,9 @@ unsigned char* TrackWorkflow::renderClip( ClipWorkflow* cw, qint64 currentF ...@@ -127,6 +131,9 @@ unsigned char* TrackWorkflow::renderClip( ClipWorkflow* cw, qint64 currentF
// qDebug() << "Querying state back to pause after render"; // qDebug() << "Querying state back to pause after render";
cw->queryStateChange( ClipWorkflow::Paused ); cw->queryStateChange( ClipWorkflow::Paused );
} }
{
QMutexLocker lock( cw->getSleepMutex() );
}
cw->wake(); cw->wake();
} }
else if ( cw->getState() == ClipWorkflow::Stopped ) else if ( cw->getState() == ClipWorkflow::Stopped )
...@@ -260,6 +267,7 @@ void TrackWorkflow::stop() ...@@ -260,6 +267,7 @@ void TrackWorkflow::stop()
unsigned char* TrackWorkflow::getOutput( qint64 currentFrame ) unsigned char* TrackWorkflow::getOutput( qint64 currentFrame )
{ {
qDebug() << "Getting track output";
QReadLocker lock( m_clipsLock ); QReadLocker lock( m_clipsLock );
unsigned char* ret = NULL; unsigned char* ret = NULL;
...@@ -468,15 +476,16 @@ void TrackWorkflow::clipWorkflowPaused() ...@@ -468,15 +476,16 @@ void TrackWorkflow::clipWorkflowPaused()
void TrackWorkflow::clipWorkflowRenderCompleted( ClipWorkflow* cw ) void TrackWorkflow::clipWorkflowRenderCompleted( ClipWorkflow* cw )
{ {
m_lastFrame = cw->getOutput(); m_synchroneRenderBuffer = cw->getOutput();
m_nbClipToRender.fetchAndAddAcquire( -1 ); m_nbClipToRender.fetchAndAddAcquire( -1 );
if ( m_nbClipToRender == 0 ) if ( m_nbClipToRender == 0 )
{ {
qDebug() << "TrackWorkflow render is completed"; qDebug() << "TrackWorkflow render is completed. Buffer =" << (void*)m_synchroneRenderBuffer;
emit renderCompleted(); emit renderCompleted( m_trackId );
}
else
{
qDebug() << "Clip workflow render complete." << m_nbClipToRender << "clips remaining.";
} }
} }
unsigned char* TrackWorkflow::getSynchroneOutput()
{
return m_synchroneRenderBuffer;
}
...@@ -58,6 +58,10 @@ class TrackWorkflow : public QObject ...@@ -58,6 +58,10 @@ class TrackWorkflow : public QObject
void addClip( Clip*, qint64 start ); void addClip( Clip*, qint64 start );
void addClip( ClipWorkflow*, qint64 start ); void addClip( ClipWorkflow*, qint64 start );
void activateOneFrameOnly(); void activateOneFrameOnly();
/**
* Returns the output that has been computed in synchrone mode.
*/
unsigned char* getSynchroneOutput();
//FIXME: this won't be reliable as soon as we change the fps from the configuration //FIXME: this won't be reliable as soon as we change the fps from the configuration
static const unsigned int nbFrameBeforePreload = 60; static const unsigned int nbFrameBeforePreload = 60;
...@@ -97,7 +101,7 @@ class TrackWorkflow : public QObject ...@@ -97,7 +101,7 @@ class TrackWorkflow : public QObject
QAtomicInt m_nbClipToPause; QAtomicInt m_nbClipToPause;
QAtomicInt m_nbClipToRender; QAtomicInt m_nbClipToRender;
unsigned char* m_lastFrame; unsigned char* m_synchroneRenderBuffer;
private slots: private slots:
void clipWorkflowPaused(); void clipWorkflowPaused();
...@@ -106,7 +110,7 @@ class TrackWorkflow : public QObject ...@@ -106,7 +110,7 @@ class TrackWorkflow : public QObject
signals: signals:
void trackEndReached( unsigned int ); void trackEndReached( unsigned int );
void trackPaused(); void trackPaused();
void renderCompleted(); void renderCompleted( unsigned int );
}; };
#endif // TRACKWORKFLOW_H #endif // TRACKWORKFLOW_H
...@@ -95,7 +95,7 @@ void* WorkflowRenderer::lock( void* datas ) ...@@ -95,7 +95,7 @@ void* WorkflowRenderer::lock( void* datas )
} }
if ( self->m_oneFrameOnly < 2 ) if ( self->m_oneFrameOnly < 2 )
{ {
void* ret = self->m_mainWorkflow->getOutput(); void* ret = self->m_mainWorkflow->getSynchroneOutput();
self->m_lastFrame = static_cast<unsigned char*>( ret ); self->m_lastFrame = static_cast<unsigned char*>( ret );
qDebug() << "Returning new frame"; qDebug() << "Returning new frame";
return ret; return ret;
......
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