diff --git a/src/Workflow/ClipWorkflow.cpp b/src/Workflow/ClipWorkflow.cpp index 889ac8a6da3fe464860c3cde4601b7676ce627f6..27db089f194f2013b7a840dd29e046d5653e9fa4 100644 --- a/src/Workflow/ClipWorkflow.cpp +++ b/src/Workflow/ClipWorkflow.cpp @@ -116,9 +116,10 @@ void ClipWorkflow::unlock( ClipWorkflow* cw ) cw->m_stateLock->unlock(); //Signal that render has been completed. cw->m_renderWaitCond->wake(); + qDebug() << "Render completed"; cw->emit renderComplete( cw ); -// qDebug() << "Entering condwait"; + qDebug() << "Entering condwait"; cw->m_waitCond->wait( cw->m_condMutex ); // qDebug() << "Leaved condwait"; cw->m_stateLock->lockForWrite(); diff --git a/src/Workflow/MainWorkflow.cpp b/src/Workflow/MainWorkflow.cpp index 73e81fa067cce6a0fdc0f25e44087090fca475fe..6213c4ee662655e64062e16bedeff3fe8b1e918b 100644 --- a/src/Workflow/MainWorkflow.cpp +++ b/src/Workflow/MainWorkflow.cpp @@ -46,15 +46,23 @@ MainWorkflow::MainWorkflow( int trackCount ) : 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( trackPaused() ), this, SLOT( trackPaused() ) ); + connect( m_tracks[i], SIGNAL( renderCompleted( unsigned int ) ), this, SLOT( tracksRenderCompleted( unsigned int ) ), Qt::DirectConnection ); } m_renderStartedLock = new QReadWriteLock; m_renderMutex = new QMutex; + m_highestTrackNumberMutex = new QMutex; + m_synchroneRenderWaitCondition = new QWaitCondition; + m_synchroneRenderWaitConditionMutex = new QMutex; } MainWorkflow::~MainWorkflow() { stop(); + delete m_synchroneRenderWaitConditionMutex; + delete m_synchroneRenderWaitCondition; + delete m_highestTrackNumberMutex; + delete m_renderMutex; delete m_renderStartedLock; for (unsigned int i = 0; i < m_trackCount; ++i) delete m_tracks[i]; @@ -102,6 +110,12 @@ unsigned char* MainWorkflow::getOutput() QReadLocker lock( m_renderStartedLock ); QMutexLocker lock2( m_renderMutex ); + { + QMutexLocker lockHighestTrackNumber( m_highestTrackNumberMutex ); + m_highestTrackNumber = 0; + } + m_nbTracksToRender = 0; + m_synchroneRenderingBuffer = NULL; if ( m_renderStarted == true ) { unsigned char* ret; @@ -110,12 +124,15 @@ unsigned char* MainWorkflow::getOutput() { if ( m_tracks[i].activated() == false ) continue ; + if ( ( ret = m_tracks[i]->getOutput( m_currentFrame ) ) != NULL ) + { + m_nbTracksToRender.fetchAndAddAcquire( 1 ); break ; + } } if ( ret == NULL ) ret = MainWorkflow::blackOutput; - nextFrame(); return ret; } @@ -261,3 +278,44 @@ void MainWorkflow::trackPaused() 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; +} diff --git a/src/Workflow/MainWorkflow.h b/src/Workflow/MainWorkflow.h index 36af7341ec5f285f57f2729087d36490c4f3ef8e..2f991187771b34e0aa984c946b0a2c8d70617f88 100644 --- a/src/Workflow/MainWorkflow.h +++ b/src/Workflow/MainWorkflow.h @@ -43,6 +43,7 @@ class MainWorkflow : public QObject, public Singleton void addClip( Clip* clip, unsigned int trackId, qint64 start ); void startRender(); unsigned char* getOutput(); + unsigned char* getSynchroneOutput(); /** * \brief Set the workflow position @@ -99,6 +100,12 @@ class MainWorkflow : public QObject, public Singleton QMutex* m_renderMutex; 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: void clipMoved( QUuid, int, int, qint64 ); @@ -106,6 +113,7 @@ class MainWorkflow : public QObject, public Singleton private slots: void trackEndReached( unsigned int trackId ); void trackPaused(); + void tracksRenderCompleted( unsigned int trackId ); signals: /** diff --git a/src/Workflow/TrackWorkflow.cpp b/src/Workflow/TrackWorkflow.cpp index 315528056e5560986b330f5e8ce15630fe5c29c7..ab8f40f8ee0048c810f8d6a48f9572f1cb75aac9 100644 --- a/src/Workflow/TrackWorkflow.cpp +++ b/src/Workflow/TrackWorkflow.cpp @@ -29,7 +29,8 @@ TrackWorkflow::TrackWorkflow( unsigned int trackId ) : m_trackId( trackId ), m_length( 0 ), m_forceRepositionning( false ), - m_paused( false ) + m_paused( false ), + m_synchroneRenderBuffer( NULL ) { m_forceRepositionningMutex = new QMutex; m_clipsLock = new QReadWriteLock; @@ -101,6 +102,7 @@ unsigned char* TrackWorkflow::renderClip( ClipWorkflow* cw, qint64 currentF } if ( cw->getState() == ClipWorkflow::Rendering ) { + qDebug() << "Rendering a 'Rendering' ClipWorkflow"; //The rendering state meens... whell it means that the frame is //beeing rendered, so we wait. cw->getStateLock()->unlock(); @@ -114,7 +116,9 @@ unsigned char* TrackWorkflow::renderClip( ClipWorkflow* cw, qint64 currentF //If frame has been rendered : if ( cw->getState() == ClipWorkflow::Sleeping || pauseAfterRender == true ) { + qDebug() << "renderign a sleeping clip worjkflow"; cw->getStateLock()->unlock(); + if ( needRepositioning == true ) { float pos = ( (float)( currentFrame - start ) / (float)(cw->getClip()->getLength()) ); @@ -127,6 +131,9 @@ unsigned char* TrackWorkflow::renderClip( ClipWorkflow* cw, qint64 currentF // qDebug() << "Querying state back to pause after render"; cw->queryStateChange( ClipWorkflow::Paused ); } + { + QMutexLocker lock( cw->getSleepMutex() ); + } cw->wake(); } else if ( cw->getState() == ClipWorkflow::Stopped ) @@ -260,6 +267,7 @@ void TrackWorkflow::stop() unsigned char* TrackWorkflow::getOutput( qint64 currentFrame ) { + qDebug() << "Getting track output"; QReadLocker lock( m_clipsLock ); unsigned char* ret = NULL; @@ -468,15 +476,16 @@ void TrackWorkflow::clipWorkflowPaused() void TrackWorkflow::clipWorkflowRenderCompleted( ClipWorkflow* cw ) { - m_lastFrame = cw->getOutput(); + m_synchroneRenderBuffer = cw->getOutput(); m_nbClipToRender.fetchAndAddAcquire( -1 ); if ( m_nbClipToRender == 0 ) { - qDebug() << "TrackWorkflow render is completed"; - emit renderCompleted(); - } - else - { - qDebug() << "Clip workflow render complete." << m_nbClipToRender << "clips remaining."; + qDebug() << "TrackWorkflow render is completed. Buffer =" << (void*)m_synchroneRenderBuffer; + emit renderCompleted( m_trackId ); } } + +unsigned char* TrackWorkflow::getSynchroneOutput() +{ + return m_synchroneRenderBuffer; +} diff --git a/src/Workflow/TrackWorkflow.h b/src/Workflow/TrackWorkflow.h index b47626e5bb2ddde7943a8402a3df46f48209cf4c..38271245713187b1b1dd9ac1f8ab0b4d07bd9e6a 100644 --- a/src/Workflow/TrackWorkflow.h +++ b/src/Workflow/TrackWorkflow.h @@ -58,6 +58,10 @@ class TrackWorkflow : public QObject void addClip( Clip*, qint64 start ); void addClip( ClipWorkflow*, qint64 start ); 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 static const unsigned int nbFrameBeforePreload = 60; @@ -97,7 +101,7 @@ class TrackWorkflow : public QObject QAtomicInt m_nbClipToPause; QAtomicInt m_nbClipToRender; - unsigned char* m_lastFrame; + unsigned char* m_synchroneRenderBuffer; private slots: void clipWorkflowPaused(); @@ -106,7 +110,7 @@ class TrackWorkflow : public QObject signals: void trackEndReached( unsigned int ); void trackPaused(); - void renderCompleted(); + void renderCompleted( unsigned int ); }; #endif // TRACKWORKFLOW_H diff --git a/src/renderer/WorkflowRenderer.cpp b/src/renderer/WorkflowRenderer.cpp index af9afe54f6dee4d70215632189ed8985dc558ece..db6b50ccc7120623ea97cb81e0302c017f4708f4 100644 --- a/src/renderer/WorkflowRenderer.cpp +++ b/src/renderer/WorkflowRenderer.cpp @@ -95,7 +95,7 @@ void* WorkflowRenderer::lock( void* datas ) } if ( self->m_oneFrameOnly < 2 ) { - void* ret = self->m_mainWorkflow->getOutput(); + void* ret = self->m_mainWorkflow->getSynchroneOutput(); self->m_lastFrame = static_cast( ret ); qDebug() << "Returning new frame"; return ret;