Commit 2045a7d0 authored by Hugo Beauzee-Luyssen's avatar Hugo Beauzee-Luyssen
Browse files

Merge branch 'chouquette_pausing_render_preview'

parents 27c46196 a893c052
......@@ -34,6 +34,7 @@ Instance::Instance()
{
// "-vvvvv",
"--no-skip-frames",
// "--intf", "dummy",
//"--no-audio",
//"--plugin-path", VLC_TREE "/modules",
"--disable-screensaver",
......
......@@ -74,9 +74,11 @@ void MediaPlayer::callbacks( const libvlc_event_t* ev
switch ( event->type )
{
case libvlc_MediaPlayerPlaying:
// qDebug() << "Media player playing";
self->emit playing();
break;
case libvlc_MediaPlayerPaused:
// qDebug() << "Media player paused";
self->emit paused();
break;
case libvlc_MediaPlayerStopped:
......
......@@ -70,6 +70,7 @@ void ClipWorkflow::checkStateChange()
QWriteLocker lock2( m_stateLock );
if ( m_requiredState != ClipWorkflow::None )
{
// qDebug() << "Changed state from" << m_state << "to state" << m_requiredState;
m_state = m_requiredState;
m_requiredState = ClipWorkflow::None;
}
......@@ -86,6 +87,7 @@ void ClipWorkflow::lock( ClipWorkflow* cw, void** pp_ret )
// else
// {
*pp_ret = cw->m_buffer;
qDebug() << "Clip workflow locking <<<<<<<<<<<<<<<<<<<<<<<<<<";
// }
}
......@@ -93,21 +95,42 @@ void ClipWorkflow::unlock( ClipWorkflow* cw )
{
cw->m_stateLock->lockForWrite();
// if ( cw->m_oneFrameOnly )
// {
// qDebug() << "One frame only mode is ON :)";
// //Forcing pause after rendering a frame
// cw->m_oneFrameOnly = 0;
// cw->m_state = Paused;
// }
// else
// qDebug() << "One frame only mode is OFF :(";
if ( cw->m_state == Rendering )
{
cw->m_state = Sleeping;
cw->m_stateLock->unlock();
QMutexLocker lock( cw->m_condMutex );
// qDebug() << "Entering condwait";
cw->m_waitCond->wait( cw->m_condMutex );
// qDebug() << "Leaved condwait";
cw->m_stateLock->lockForWrite();
cw->m_state = Rendering;
// {
// QWriteLocker lock2( cw->m_backBufferLock );
// cw->m_usingBackBuffer = !cw->m_usingBackBuffer;
// }
cw->m_stateLock->unlock();
}
cw->m_stateLock->unlock();
else if ( cw->m_state == Paused )
{
qDebug() << "Forcing pause by pausing thread";
cw->m_stateLock->unlock();
QMutexLocker lock( cw->m_condMutex );
cw->m_waitCond->wait( cw->m_condMutex );
}
else
cw->m_stateLock->unlock();
cw->checkStateChange();
}
......@@ -264,3 +287,28 @@ void ClipWorkflow::reinitialize()
m_state = Stopped;
queryStateChange( None );
}
void ClipWorkflow::pause()
{
setState( Paused );
m_mediaPlayer->pause();
QMutexLocker lock( m_requiredStateLock );
m_requiredState = ClipWorkflow::None;
}
void ClipWorkflow::unpause( bool wakeRenderThread /*= true*/ )
{
//Since VLC will detect that the media player is paused and unpause it, we can do this safely
setState( ClipWorkflow::Rendering );
m_mediaPlayer->pause();
// QMutexLocker lock( m_requiredStateLock );
// m_requiredState = ClipWorkflow::None;
if ( wakeRenderThread == true )
wake();
}
//void ClipWorkflow::activateOneFrameOnly()
//{
// qDebug() << "Activating one frame only";
// m_oneFrameOnly = 1;
//}
......@@ -50,6 +50,8 @@ class ClipWorkflow : public QObject
Ready,
Rendering,
Sleeping,
Pausing,
Paused,
Stopping,
EndReached,
};
......@@ -84,7 +86,7 @@ class ClipWorkflow : public QObject
bool isStopped() const;
/**
* Return true ONLY if the state is equal to Stopped.
* Return true ONLY if the state is equal to Rendering.
* In any other cases, this will return false.
*/
bool isRendering() const;
......@@ -114,6 +116,7 @@ class ClipWorkflow : public QObject
\brief Stop this workflow.
*/
void stop();
void pause();
void setPosition( float pos );
/**
......@@ -142,6 +145,10 @@ class ClipWorkflow : public QObject
*/
void reinitialize();
void unpause( bool wakeRenderThread = true );
// void activateOneFrameOnly();
private:
static void lock( ClipWorkflow* clipWorkflow, void** pp_ret );
static void unlock( ClipWorkflow* clipWorkflow );
......@@ -183,6 +190,8 @@ class ClipWorkflow : public QObject
State m_requiredState;
QMutex* m_requiredStateLock;
QAtomicInt m_oneFrameOnly;
private slots:
void pauseAfterPlaybackStarted();
......
......@@ -113,6 +113,15 @@ unsigned char* MainWorkflow::getOutput()
return MainWorkflow::blackOutput;
}
void MainWorkflow::pause()
{
for ( unsigned int i = 0; i < m_trackCount; ++i )
{
if ( m_tracks[i].activated() == true )
m_tracks[i]->pause();
}
}
void MainWorkflow::nextFrame()
{
++m_currentFrame;
......@@ -209,3 +218,13 @@ void MainWorkflow::clipMoved( QUuid clipUuid, int oldTrack, int newTra
m_tracks[newTrack].activate();
}
}
void MainWorkflow::activateOneFrameOnly()
{
for (unsigned int i = 0; i < m_trackCount; ++i)
{
//FIXME: After debugging period, this should'nt be necessary --
if ( m_tracks[i].activated() == true )
m_tracks[i]->activateOneFrameOnly();
}
}
......@@ -65,9 +65,16 @@ class MainWorkflow : public QObject, public Singleton<MainWorkflow>
*/
void stop();
/**
* Pause the main workflow and all its sub-workflows
*/
void pause();
static unsigned char* blackOutput;
void nextFrame();
void previousFrame();
void activateOneFrameOnly();
static MainWorkflow* getInstance();
......
......@@ -28,7 +28,8 @@
TrackWorkflow::TrackWorkflow( unsigned int trackId ) :
m_trackId( trackId ),
m_length( 0 ),
m_forceRepositionning( false )
m_forceRepositionning( false ),
m_paused( false )
{
m_forceRepositionningMutex = new QMutex;
m_clipsLock = new QReadWriteLock;
......@@ -79,16 +80,29 @@ qint64 TrackWorkflow::getLength() const
}
unsigned char* TrackWorkflow::renderClip( ClipWorkflow* cw, qint64 currentFrame,
qint64 start , bool needRepositioning )
qint64 start , bool needRepositioning,
bool pauseAfterRender )
{
unsigned char* ret = NULL;
cw->getStateLock()->lockForRead();
qDebug() << "Rendering clip";
if ( cw->getState() == ClipWorkflow::Paused && pauseAfterRender == false )
{
cw->getStateLock()->unlock();
qDebug() << "Unpausing clip workflow";
//If we must pause after render, we must NOT wake the renderer thread, or it could render more than one frame
// (since this is for the next/previous frame)
//However, if this is just for a classic unpause, with just don't give a shit :)
cw->unpause( false );
cw->getStateLock()->lockForRead();
}
if ( cw->getState() == ClipWorkflow::Rendering )
{
//The rendering state meens... whell it means that the frame is
//beeing rendered, so we wait.
qDebug() << "State == rendering";
cw->getStateLock()->unlock();
while ( cw->isRendering() == true )
{
......@@ -101,7 +115,7 @@ unsigned char* TrackWorkflow::renderClip( ClipWorkflow* cw, qint64 currentF
}
//If frame has been rendered :
if ( cw->getState() == ClipWorkflow::Sleeping )
if ( cw->getState() == ClipWorkflow::Sleeping || pauseAfterRender == true )
{
cw->getStateLock()->unlock();
if ( needRepositioning == true )
......@@ -110,6 +124,12 @@ unsigned char* TrackWorkflow::renderClip( ClipWorkflow* cw, qint64 currentF
cw->setPosition( pos );
}
ret = cw->getOutput();
if ( pauseAfterRender == true )
{
cw->unpause( false );
qDebug() << "Querying state back to pause after render";
cw->queryStateChange( ClipWorkflow::Paused );
}
cw->wake();
//FIXME: sometimes, the renderer isn't awake soon enough, and we can
//pass though this function many times before the frame is actually rendered.
......@@ -193,9 +213,16 @@ void TrackWorkflow::stopClipWorkflow( ClipWorkflow* cw )
SleepMS( 1 );
cw->stop();
}
else if ( cw->getState() == ClipWorkflow::Paused )
{
cw->getStateLock()->unlock();
cw->queryStateChange( ClipWorkflow::Stopping );
cw->unpause();
cw->stop();
}
else
{
// qDebug() << "Unexpected ClipWorkflow::State when stopping :" << cw->getState();
qDebug() << "Unexpected ClipWorkflow::State when stopping :" << cw->getState();
cw->getStateLock()->unlock();
}
}
......@@ -231,7 +258,16 @@ unsigned char* TrackWorkflow::getOutput( qint64 currentFrame )
QMap<qint64, ClipWorkflow*>::iterator end = m_clips.end();
static qint64 lastFrame = 0;
bool needRepositioning;
bool oneFrameOnlyFlag = false;
qDebug() << "Checking flag...";
if ( m_oneFrameOnly == 1 )
{
qDebug() << "...Flag is activated";
oneFrameOnlyFlag = true;
}
else
qDebug() << "...Flag is OFF";
if ( checkEnd( currentFrame ) == true )
{
emit trackEndReached( m_trackId );
......@@ -255,7 +291,14 @@ unsigned char* TrackWorkflow::getOutput( qint64 currentFrame )
//Is the clip supposed to render now ?
if ( start <= currentFrame && currentFrame <= start + cw->getClip()->getLength() )
{
ret = renderClip( cw, currentFrame, start, needRepositioning );
// if ( oneFrameOnlyFlag == true )
// cw->activateOneFrameOnly();
ret = renderClip( cw, currentFrame, start, needRepositioning, oneFrameOnlyFlag );
if ( oneFrameOnlyFlag == true )
{
cw->pause();
qDebug() << "Pausing back clip workflow";
}
lastFrame = currentFrame;
}
//Is it about to be rendered ?
......@@ -272,9 +315,95 @@ unsigned char* TrackWorkflow::getOutput( qint64 currentFrame )
++it;
}
if ( oneFrameOnlyFlag == true )
{
qDebug() << "Switching off m_oneFrameOnly";
m_oneFrameOnly = 0;
}
return ret;
}
void TrackWorkflow::pauseClipWorkflow( ClipWorkflow* cw )
{
cw->getStateLock()->lockForRead();
if ( cw->getState() == ClipWorkflow::Sleeping ||
cw->getState() == ClipWorkflow::Ready ||
cw->getState() == ClipWorkflow::EndReached )
{
cw->getStateLock()->unlock();
cw->queryStateChange( ClipWorkflow::Pausing );
cw->wake();
}
else if ( cw->getState() == ClipWorkflow::Rendering )
{
cw->getStateLock()->unlock();
while ( cw->isRendering() == true )
SleepMS( 1 );
cw->queryStateChange( ClipWorkflow::Pausing );
cw->wake();
}
else if ( cw->getState() == ClipWorkflow::Initializing )
{
cw->getStateLock()->unlock();
while ( cw->isReady() == false )
SleepMS( 1 );
}
else
{
qDebug() << "Unexpected ClipWorkflow::State when pausing:" << cw->getState();
cw->getStateLock()->unlock();
}
bool pausing = false;
while ( pausing == false )
{
cw->getStateLock()->lockForRead();
pausing = ( cw->getState() == ClipWorkflow::Pausing );
SleepMS( 1 );
cw->getStateLock()->unlock();
}
cw->pause();
}
void TrackWorkflow::pause()
{
QReadLocker lock( m_clipsLock );
QMap<qint64, ClipWorkflow*>::iterator it = m_clips.begin();
QMap<qint64, ClipWorkflow*>::iterator end = m_clips.end();
//FIXME: it's probably bad to iterate over every clip workflows.
while ( it != end )
{
qDebug() << "Iterating...";
ClipWorkflow* cw = it.value();
cw->getStateLock()->lockForRead();
if ( cw->getState() != ClipWorkflow::Paused )
{
qDebug() << "Pausing clip workflow";
cw->getStateLock()->unlock();
pauseClipWorkflow( cw );
}
else
{
//This should never be used.
Q_ASSERT( false );
if ( cw->getState() == ClipWorkflow::Paused )
{
cw->getStateLock()->unlock();
cw->unpause();
}
else
{
cw->getStateLock()->unlock();
}
}
++it;
}
m_paused = !m_paused;
}
void TrackWorkflow::moveClip( const QUuid& id, qint64 startingFrame )
{
QWriteLocker lock( m_clipsLock );
......@@ -321,3 +450,10 @@ Clip* TrackWorkflow::removeClip( const QUuid& id )
}
return NULL;
}
void TrackWorkflow::activateOneFrameOnly()
{
qDebug() << "Activating flag";
m_oneFrameOnly = 1;
qDebug() << "Flag activated";
}
......@@ -52,10 +52,12 @@ class TrackWorkflow : public QObject
unsigned char* getOutput( qint64 currentFrame );
qint64 getLength() const;
void stop();
void pause();
void moveClip( const QUuid& id, qint64 startingFrame );
Clip* removeClip( const QUuid& id );
void addClip( Clip*, qint64 start );
void addClip( ClipWorkflow*, qint64 start );
void activateOneFrameOnly();
//FIXME: this won't be reliable as soon as we change the fps from the configuration
static const unsigned int nbFrameBeforePreload = 60;
......@@ -63,9 +65,11 @@ class TrackWorkflow : public QObject
private:
void computeLength();
unsigned char* renderClip( ClipWorkflow* cw, qint64 currentFrame,
qint64 start, bool needRepositioning );
qint64 start, bool needRepositioning,
bool pauseAfterRender );
void preloadClip( ClipWorkflow* cw );
void stopClipWorkflow( ClipWorkflow* cw );
void pauseClipWorkflow( ClipWorkflow* cw );
bool checkEnd( qint64 currentFrame ) const;
private:
......@@ -86,6 +90,10 @@ class TrackWorkflow : public QObject
QMutex* m_forceRepositionningMutex;
QReadWriteLock* m_clipsLock;
bool m_paused;
QAtomicInt m_oneFrameOnly;
signals:
void trackEndReached( unsigned int );
};
......
......@@ -29,10 +29,8 @@
RenderPreviewWidget::RenderPreviewWidget( MainWorkflow* mainWorkflow, QWidget* renderWidget ) :
GenericPreviewWidget( renderWidget ),
m_mainWorkflow( mainWorkflow ),
m_framePlayed( false )
m_mainWorkflow( mainWorkflow )
{
m_framePlayedLock = new QReadWriteLock;
m_media = new LibVLCpp::Media( "fake://" );
// --invmem-width <integer> Width
// --invmem-height <integer> Height
......@@ -52,6 +50,11 @@ RenderPreviewWidget::RenderPreviewWidget( MainWorkflow* mainWorkflow, QWidget* r
m_media->addOption( buffer );
sprintf( buffer, ":invmem-data=%lld", (qint64)this );
m_media->addOption( buffer );
sprintf( buffer, ":width=%i", VIDEOWIDTH );
m_media->addOption( buffer );
sprintf( buffer, ":height=%i", VIDEOHEIGHT );
m_media->addOption( buffer );
m_mediaPlayer->setMedia( m_media );
connect( m_mediaPlayer, SIGNAL( playing() ), this, SLOT( __videoPlaying() ) );
......@@ -78,16 +81,27 @@ RenderPreviewWidget::~RenderPreviewWidget()
void* RenderPreviewWidget::lock( void* datas )
{
RenderPreviewWidget* self = reinterpret_cast<RenderPreviewWidget*>( datas );
void* ret = self->m_mainWorkflow->getOutput();
return ret;
if ( self->m_oneFrameOnly < 2 )
{
qDebug() << "\nQuerying new picture";
void* ret = self->m_mainWorkflow->getOutput();
self->m_lastFrame = static_cast<unsigned char*>( ret );
return ret;
}
else
return self->m_lastFrame;
}
void RenderPreviewWidget::unlock( void* datas )
{
RenderPreviewWidget* self = reinterpret_cast<RenderPreviewWidget*>( datas );
QWriteLocker lock( self->m_framePlayedLock );
self->m_framePlayed = true;
if ( self->m_oneFrameOnly == 1 )
{
self->m_mediaPlayer->pause();
self->m_oneFrameOnly = 2;
qDebug() << "Pausing RenderPreviewWidget";
}
}
void RenderPreviewWidget::stopPreview()
......@@ -118,20 +132,17 @@ void RenderPreviewWidget::setPosition( float newPos )
void RenderPreviewWidget::nextFrame()
{
{
QWriteLocker lock( m_framePlayedLock );
m_framePlayed = false;
}
qDebug() << "Next frame :";
m_oneFrameOnly = 1;
m_mainWorkflow->nextFrame();
m_mediaPlayer->play();
bool framePlayed = false;
while ( framePlayed == false )
{
SleepMS( 50 );
QReadLocker lock( m_framePlayedLock );
framePlayed = m_framePlayed;
}
qDebug() << "Activatign one frame only";
m_mainWorkflow->activateOneFrameOnly();
//Both media players should be stopped now... restauring playback
// m_framePlayed = 0;
m_mediaPlayer->pause();
// while ( m_framePlayed == 0 )
// SleepMS( 1 );
// m_mediaPlayer->pause();
}
void RenderPreviewWidget::previousFrame()
......@@ -148,7 +159,10 @@ void RenderPreviewWidget::togglePlayPause( bool forcePause )
{
if ( m_paused == true && forcePause == false )
{
qDebug() << "Unpausing";
m_mediaPlayer->play();
//This will automaticly unpause... no worries
// m_mainWorkflow->pause();
m_paused = false;
}
else
......@@ -157,7 +171,9 @@ void RenderPreviewWidget::togglePlayPause( bool forcePause )
//So be careful about pausing two times :
if ( m_paused == false )
{
qDebug() << "Pausing";
m_mediaPlayer->pause();
m_mainWorkflow->pause();
m_paused = true;
}
}
......@@ -194,6 +210,10 @@ void RenderPreviewWidget::__positionChanged( float pos )
void RenderPreviewWidget::__videoPaused()
{
if ( m_oneFrameOnly != 0 )
{
m_oneFrameOnly = 0;
}
emit paused();
}
......
......@@ -60,8 +60,8 @@ class RenderPreviewWidget : public GenericPreviewWidget
private:
MainWorkflow* m_mainWorkflow;
LibVLCpp::Media* m_media;
QReadWriteLock* m_framePlayedLock;
bool m_framePlayed;
QAtomicInt m_oneFrameOnly;
unsigned char* m_lastFrame;
public slots:
void __positionChanged();
......
......@@ -41,7 +41,7 @@ TracksView::TracksView( QGraphicsScene* scene, MainWorkflow* mainWorkflow, QWidg
m_tracksHeight = 25;
m_tracksCount = mainWorkflow->getTrackCount();
m_fps = 30;
m_fps = FPS;
m_numAudioTrack = 0;
m_numVideoTrack = 0;
......
......@@ -107,6 +107,11 @@ INCLUDEPATH += src/LibVLCpp \
src/gui \
src/tools \
src
# QMAKE_CFLAGS+=-pg
# QMAKE_CXXFLAGS+=-pg
# QMAKE_LFLAGS+=-pg
LIBS = -L/usr/local/lib \
-lvlc
SUBDIRS += modules
......
Supports Markdown
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