diff --git a/src/Workflow/ClipWorkflow.cpp b/src/Workflow/ClipWorkflow.cpp index 56aeeb934937781a484eeaf434bcf784d01fc50a..d8ab77408633a72d6f91f1ca12321e5a37aa3bde 100644 --- a/src/Workflow/ClipWorkflow.cpp +++ b/src/Workflow/ClipWorkflow.cpp @@ -75,7 +75,7 @@ void ClipWorkflow::checkStateChange() QWriteLocker lock2( m_stateLock ); if ( m_requiredState != ClipWorkflow::None ) { -// qDebug() << "Changed state from" << m_state << "to state" << m_requiredState; + qDebug() << "Changed state from" << m_state << "to state" << m_requiredState; m_state = m_requiredState; m_requiredState = ClipWorkflow::None; checkSynchronisation( m_state ); @@ -122,9 +122,9 @@ void ClipWorkflow::unlock( ClipWorkflow* cw ) // qDebug() << "Clip render completed"; cw->emit renderComplete( cw ); -// qDebug() << "Entering condwait"; + qDebug() << "\t\tEntering condwait"; cw->m_waitCond->wait( cw->m_condMutex ); -// qDebug() << "Leaved condwait"; + qDebug() << "\t\tLeaved condwait"; cw->m_stateLock->lockForWrite(); cw->m_state = Rendering; // { @@ -138,11 +138,11 @@ void ClipWorkflow::unlock( ClipWorkflow* cw ) QMutexLocker lock( cw->m_condMutex ); cw->m_stateLock->unlock(); -// qDebug() << "Entering forced pause condwait"; + qDebug() << "Entering forced pause condwait"; cw->setState( ClipWorkflow::ThreadPaused ); cw->m_pausedThreadCondWait->wake(); cw->m_waitCond->wait( cw->m_condMutex ); -// qDebug() << "Leaving forced pause condwait"; + qDebug() << "Leaving forced pause condwait"; cw->setState( ClipWorkflow::Paused ); } else @@ -309,6 +309,7 @@ void ClipWorkflow::setState( State state ) { { QWriteLocker lock( m_stateLock ); + qDebug() << "Changing from state" << m_state << "to state" << state; m_state = state; } checkSynchronisation( state ); diff --git a/src/Workflow/MainWorkflow.cpp b/src/Workflow/MainWorkflow.cpp index 3ec7427d5df840b75a71f286302fc3fbd821c104..6ff5b47ce29e477257e9538f65d3cbdf9bd6c0e8 100644 --- a/src/Workflow/MainWorkflow.cpp +++ b/src/Workflow/MainWorkflow.cpp @@ -153,6 +153,7 @@ void MainWorkflow::pause() m_tracks[i]->pause(); } } + qDebug() << "All tracks are paused"; } void MainWorkflow::nextFrame() @@ -275,10 +276,11 @@ void MainWorkflow::activateOneFrameOnly() void MainWorkflow::trackPaused() { + qDebug() << "Track pausing finished..."; m_nbTracksToPause.fetchAndAddAcquire( -1 ); if ( m_nbTracksToPause <= 0 ) { -// qDebug() << "MainWorkflow is paused"; + qDebug() << "\t\t...MainWorkflow is paused"; emit mainWorkflowPaused(); } } diff --git a/src/Workflow/TrackWorkflow.cpp b/src/Workflow/TrackWorkflow.cpp index 004e1d6251170f8145db07120bbda33f1a0e127c..2e158acb874d14f089273d04880642b1ae8d81d0 100644 --- a/src/Workflow/TrackWorkflow.cpp +++ b/src/Workflow/TrackWorkflow.cpp @@ -314,6 +314,8 @@ unsigned char* TrackWorkflow::getOutput( qint64 currentFrame ) needRepositioning = ( abs( currentFrame - lastFrame ) > 1 ) ? true : false; } m_nbClipToRender = 0; + //If we ask for an output, then the track should'nt be paused anymore. + m_paused = false; while ( it != end ) { qint64 start = it.key(); @@ -324,10 +326,10 @@ unsigned char* TrackWorkflow::getOutput( qint64 currentFrame ) { m_nbClipToRender.fetchAndAddAcquire( 1 ); ret = renderClip( cw, currentFrame, start, needRepositioning, oneFrameOnlyFlag ); - if ( oneFrameOnlyFlag == true ) - { - cw->pause(); - } +// if ( oneFrameOnlyFlag == true ) +// { +// cw->pause(); +// } lastFrame = currentFrame; } //Is it about to be rendered ? @@ -353,7 +355,7 @@ unsigned char* TrackWorkflow::getOutput( qint64 currentFrame ) return ret; } -void TrackWorkflow::pauseClipWorkflow( ClipWorkflow* cw ) +void TrackWorkflow::pauseClipWorkflow( ClipWorkflow* cw ) { cw->getStateLock()->lockForRead(); @@ -362,40 +364,49 @@ void TrackWorkflow::pauseClipWorkflow( ClipWorkflow* cw ) cw->getStateLock()->unlock(); return ; } - if ( cw->getState() == ClipWorkflow::Sleeping || - cw->getState() == ClipWorkflow::Ready || - cw->getState() == ClipWorkflow::EndReached ) + if ( cw->getState() != ClipWorkflow::Paused ) { - cw->getStateLock()->unlock(); + if ( cw->getState() == ClipWorkflow::Sleeping || + cw->getState() == ClipWorkflow::Ready || + cw->getState() == ClipWorkflow::EndReached ) + { + cw->getStateLock()->unlock(); - QMutexLocker lock( cw->getSleepMutex() ); - cw->queryStateChange( ClipWorkflow::Pausing ); - cw->wake(); - } - else if ( cw->getState() == ClipWorkflow::Rendering ) - { - cw->getStateLock()->unlock(); - cw->waitForCompleteRender(); - QMutexLocker lock( cw->getSleepMutex() ); - cw->queryStateChange( ClipWorkflow::Pausing ); - cw->wake(); - } - else if ( cw->getState() == ClipWorkflow::Initializing ) - { - cw->getStateLock()->unlock(); - //TODO: since a Initializing clipworkflow will pause itself at the end, shouldn't we do nothing ? - cw->waitForCompleteInit(); + //Locking this mutex ensure that the thread is really asleep, and hasn't + //just changed the state, and then get pulled back by the scheduler... + QMutexLocker lock( cw->getSleepMutex() ); + cw->queryStateChange( ClipWorkflow::Pausing ); + cw->wake(); + } + else if ( cw->getState() == ClipWorkflow::Rendering ) + { + cw->getStateLock()->unlock(); + qDebug() << "Waiting for complete render"; + cw->waitForCompleteRender(); + qDebug() << "Render has been completed... continue pausing"; + QMutexLocker lock( cw->getSleepMutex() ); + cw->queryStateChange( ClipWorkflow::Pausing ); + cw->wake(); + } + else if ( cw->getState() == ClipWorkflow::Initializing ) + { + cw->getStateLock()->unlock(); + //TODO: since a Initializing clipworkflow will pause itself at the end, shouldn't we do nothing ? + cw->waitForCompleteInit(); + } + else + { + // qDebug() << "Unexpected ClipWorkflow::State when pausing:" << cw->getState(); + cw->getStateLock()->unlock(); + } + cw->waitForPausingState(); + cw->pause(); } else - { -// qDebug() << "Unexpected ClipWorkflow::State when pausing:" << cw->getState(); cw->getStateLock()->unlock(); - } - cw->waitForPausingState(); - cw->pause(); -// qDebug() << "Wait for pausedthread state"; + qDebug() << "Wait for pausedthread state"; cw->waitForPausedThread(); -// qDebug() << "Ok thread is paused"; + qDebug() << "Ok thread is paused"; } void TrackWorkflow::pause() @@ -412,27 +423,30 @@ void TrackWorkflow::pause() ClipWorkflow* cw = it.value(); cw->getStateLock()->lockForRead(); + qDebug() << "Pausing a clip in state" << cw->getState(); if ( cw->getState() == ClipWorkflow::Stopped ) { cw->getStateLock()->unlock(); continue ; } - if ( cw->getState() != ClipWorkflow::Paused ) + else if ( cw->getState() != ClipWorkflow::ThreadPaused ) { cw->getStateLock()->unlock(); m_nbClipToPause.fetchAndAddAcquire( 1 ); - connect( cw->getMediaPlayer(), SIGNAL( paused() ), this, SLOT( clipWorkflowPaused() ) ); +// connect( cw->getMediaPlayer(), SIGNAL( paused() ), this, SLOT( clipWorkflowPaused() ) ); pauseClipWorkflow( cw ); } else { //This should never be used. - //TODO: remove this in a few revision (wrote on July 16 2009 ) -// qDebug() << "Asking to pause in an already paused state"; + qDebug() << "Asking to pause in an already paused state"; cw->getStateLock()->unlock(); } } m_paused = !m_paused; + qDebug() << "m_paused ==" << m_paused; + if ( m_paused == true ) + emit trackPaused(); } void TrackWorkflow::moveClip( const QUuid& id, qint64 startingFrame ) @@ -489,14 +503,14 @@ void TrackWorkflow::activateOneFrameOnly() m_oneFrameOnly = 1; } -void TrackWorkflow::clipWorkflowPaused() -{ - m_nbClipToPause.fetchAndAddAcquire( -1 ); - if ( m_nbClipToPause == 0 ) - { - emit trackPaused(); - } -} +//void TrackWorkflow::clipWorkflowPaused() +//{ +// m_nbClipToPause.fetchAndAddAcquire( -1 ); +// if ( m_nbClipToPause == 0 ) +// { +// emit trackPaused(); +// } +//} void TrackWorkflow::clipWorkflowRenderCompleted( ClipWorkflow* cw ) { diff --git a/src/Workflow/TrackWorkflow.h b/src/Workflow/TrackWorkflow.h index 38271245713187b1b1dd9ac1f8ab0b4d07bd9e6a..6a39272fbd2229188ee812fb6044e058742ba18d 100644 --- a/src/Workflow/TrackWorkflow.h +++ b/src/Workflow/TrackWorkflow.h @@ -52,6 +52,10 @@ class TrackWorkflow : public QObject unsigned char* getOutput( qint64 currentFrame ); qint64 getLength() const; void stop(); + /** + * Will pause all the track's ClipWorkflow. + * This method *is synchrone*, and will not return until all of the ClipWorkflow's thread are asleep + */ void pause(); void moveClip( const QUuid& id, qint64 startingFrame ); Clip* removeClip( const QUuid& id ); @@ -104,7 +108,7 @@ class TrackWorkflow : public QObject unsigned char* m_synchroneRenderBuffer; private slots: - void clipWorkflowPaused(); +// void clipWorkflowPaused(); void clipWorkflowRenderCompleted( ClipWorkflow* ); signals: diff --git a/src/renderer/WorkflowRenderer.cpp b/src/renderer/WorkflowRenderer.cpp index 1292755c3c78daa04ada2e6de8b30dd97732734a..cc83dbb47bb32983efefbc3dcaae520acf1c0ccc 100644 --- a/src/renderer/WorkflowRenderer.cpp +++ b/src/renderer/WorkflowRenderer.cpp @@ -133,9 +133,9 @@ void WorkflowRenderer::unlock( void* datas ) // qDebug() << "Workflowrenderer::unlock. m_oneFrameOnly ==" << self->m_oneFrameOnly; if ( self->m_oneFrameOnly == 1 ) { -// qDebug() << "Pausing back"; + qDebug() << "Pausing back"; self->togglePlayPause( true ); -// qDebug() << "Switching m_oneFrameOnly flag to 2"; + qDebug() << "Switching m_oneFrameOnly flag to 2"; self->m_oneFrameOnly = 2; } self->m_framePlayed = true; @@ -214,6 +214,8 @@ void WorkflowRenderer::frameByFramePausingProxy() if ( nbPaused == 2 ) { nbPaused = 0; + disconnect( m_mediaPlayer, SIGNAL( paused() ), this, SLOT( frameByFramePausingProxy() ) ); + disconnect( m_mainWorkflow, SIGNAL( mainWorkflowPaused() ), this, SLOT( frameByFramePausingProxy() ) ); frameByFrameAfterPaused(); } } @@ -313,6 +315,7 @@ void WorkflowRenderer::__videoPaused() { m_oneFrameOnly = 0; } + qDebug() << "Pausing main workflow"; pauseMainWorkflow(); }