Commit 3467724d authored by Hugo Beauzee-Luyssen's avatar Hugo Beauzee-Luyssen

Debug for track/clipworkflow

parent 76b6be97
......@@ -35,19 +35,15 @@ ClipWorkflow::ClipWorkflow( Clip::Clip* clip, QMutex* renderMutex,
m_state( ClipWorkflow::Stopped )
{
m_buffer = new unsigned char[VIDEOHEIGHT * VIDEOWIDTH * 4];
m_stateLock = new QReadWriteLock();
m_stateLock = new QReadWriteLock;
m_requiredStateLock = new QMutex;
}
ClipWorkflow::~ClipWorkflow()
{
delete[] m_buffer;
delete m_stateLock;
}
void ClipWorkflow::scheduleStop()
{
QWriteLocker lock( m_stateLock );
m_state = StopScheduled;
delete m_requiredStateLock;
}
unsigned char* ClipWorkflow::getOutput()
......@@ -56,6 +52,18 @@ unsigned char* ClipWorkflow::getOutput()
return m_buffer;
}
void ClipWorkflow::checkStateChange()
{
QMutexLocker lock( m_requiredStateLock );
QWriteLocker lock2 ( m_stateLock );
if ( m_requiredState != ClipWorkflow::None )
{
qDebug() << "Changing state";
m_state = m_requiredState;
m_requiredState = ClipWorkflow::None;
}
}
void ClipWorkflow::lock( ClipWorkflow* clipWorkflow, void** pp_ret )
{
//In any case, we give vlc a buffer to render in...
......@@ -70,13 +78,16 @@ void ClipWorkflow::unlock( ClipWorkflow* clipWorkflow )
{
clipWorkflow->m_renderMutex->unlock();
clipWorkflow->checkStateChange();
clipWorkflow->m_stateLock->lockForRead();
if ( clipWorkflow->m_state == Rendering )
{
QMutexLocker lock5( clipWorkflow->m_condMutex );
QMutexLocker lock( clipWorkflow->m_condMutex );
clipWorkflow->m_stateLock->unlock();
clipWorkflow->m_waitCond->wait( clipWorkflow->m_condMutex );
}
else
qDebug() << clipWorkflow->m_state;
clipWorkflow->m_stateLock->unlock();
// qDebug() << "UnLocking in ClipWorkflow::unlock";
}
......@@ -134,8 +145,7 @@ void ClipWorkflow::pauseAfterPlaybackStarted()
void ClipWorkflow::pausedMediaPlayer()
{
disconnect( m_mediaPlayer, SIGNAL( paused() ), this, SLOT( pausedMediaPlayer() ) );
QWriteLocker lock( m_stateLock );
m_state = ClipWorkflow::Ready;
setState( Ready );
}
bool ClipWorkflow::isReady() const
......@@ -183,13 +193,13 @@ const Clip* ClipWorkflow::getClip() const
void ClipWorkflow::stop()
{
QWriteLocker lock( m_stateLock );
qDebug() << "ClipWorkflow::stop()";
Q_ASSERT( m_mediaPlayer != NULL );
m_mediaPlayer->stop();
qDebug() << "Stopped media player";
m_mediaPlayer = NULL;
//Don't use setState here since m_stateLock is already locked;
m_state = Stopped;
setState( Stopped );
qDebug() << "Changed state";
}
void ClipWorkflow::setPosition( float pos )
......@@ -208,3 +218,10 @@ void ClipWorkflow::setState( State state )
QWriteLocker lock( m_stateLock );
m_state = state;
}
void ClipWorkflow::queryStateChange( State newState )
{
qDebug() << "Querying state change";
QMutexLocker lock( m_requiredStateLock );
m_requiredState = newState;
}
......@@ -44,12 +44,13 @@ class ClipWorkflow : public QObject
public:
enum State
{
None = -1,
Stopped,
Initializing,
Ready,
Rendering,
EndReached,
StopScheduled,
StopRequired,
};
ClipWorkflow( Clip* clip, QMutex* renderMutex, QMutex* condMutex, QWaitCondition* waitCond );
......@@ -110,13 +111,21 @@ class ClipWorkflow : public QObject
void stop();
void setPosition( float pos );
void scheduleStop();
/**
* This method must be used to change the state of the ClipWorkflow
* from outside its render loop, otherwise, it may lead to deadlocks.
* No additional operations will be executed (for example, if setting
* the new state to stop, the media player won't be stopped.)
* This is mainly to change the behaviour of the render loop.
*/
void queryStateChange( State newState );
private:
static void lock( ClipWorkflow* clipWorkflow, void** pp_ret );
static void unlock( ClipWorkflow* clipWorkflow );
void setVmem();
void setState( State state );
void checkStateChange();
private:
Clip* m_clip;
......@@ -130,6 +139,8 @@ class ClipWorkflow : public QObject
State m_state;
QReadWriteLock* m_stateLock;
State m_requiredState;
QMutex* m_requiredStateLock;
public slots:
......
......@@ -138,11 +138,13 @@ unsigned char* TrackWorkflow::getOutput( qint64 currentFrame )
setPosition( m_requiredPosition );
m_requiredPosition = -1.0f;
}
checkStop();
// qDebug() << "Frame nb" << currentFrame;
clipsRemaining = checkNextClip( currentFrame );
//This is true only before the first render.
if ( m_current == m_clips.end() )
{
// qDebug() << "m_current == m_clips.end()";
//If the track was empty, then its end is reached
if ( clipsRemaining == false )
emit endReached();
......@@ -153,20 +155,23 @@ unsigned char* TrackWorkflow::getOutput( qint64 currentFrame )
if ( m_current.value()->isRendering() == true )
{
m_waitCondition->wakeAll();
// qDebug() << "Is rendering == true";
ret = m_current.value()->getOutput();
return ret;
}
else if ( m_current.value()->getState() == ClipWorkflow::EndReached ||
m_current.value()->getState() == ClipWorkflow::StopScheduled )
m_current.value()->getState() == ClipWorkflow::StopRequired )
{
//First, we stop the current ClipWorkflow so that it won't
//enter the lock/unlock cycle anymore.
qDebug() << "Stopping";
m_current.value()->stop();
//Then, if there's no remaining clip, end of track is reached.
if ( clipsRemaining == false )
emit endReached();
}
// else
// qDebug() << "Uncoherent state : " << m_current.value()->getState();
return ret;
}
......@@ -177,8 +182,19 @@ void TrackWorkflow::initializeClipWorkflow( ClipWorkflow* cw )
cw->startRender();
}
void TrackWorkflow::stopClipWorkflow( ClipWorkflow* cw )
{
if ( cw->getState() != ClipWorkflow::Stopped && cw->getState() != ClipWorkflow::StopRequired )
{
cw->queryStateChange( ClipWorkflow::StopRequired );
//Since state change won't be immediate, we add the clip workflow to a lookup list
m_toStop.enqueue( cw );
}
}
void TrackWorkflow::setPosition( float pos )
{
qDebug() << "Setting pos";
qint64 frame = (float)m_length * pos;
QMap<qint64, ClipWorkflow*>::iterator it = m_clips.begin();
const QMap<qint64, ClipWorkflow*>::iterator end = m_clips.end();
......@@ -188,8 +204,9 @@ void TrackWorkflow::setPosition( float pos )
{
if ( m_current != end )
{
m_current.value()->scheduleStop();
stopClipWorkflow( m_current.value() );
m_current = end;
qDebug() << "After end of current track";
return ;
}
}
......@@ -224,22 +241,26 @@ void TrackWorkflow::setPosition( float pos )
++it;
}
//No clip was found :
//No clip was found, just adjusing the current clip. (Render will be black though)
if ( it == end )
{
qDebug() << "In black zone";
//We should use the next clip, however, we use the clip just before
//the next.
//We also stop the current clip if it was started.
if ( m_current != end )
{
m_current.value()->scheduleStop();
stopClipWorkflow( m_current.value() );
}
//TODO: it seems that m_current may be equal to next... check if that could be a problem...
m_current = next;
}
// If the clip found is the current, we just change the position of the
// media player
else if ( it == m_current )
{
qDebug() << "Using current clip with new position";
qDebug() << it.value()->getState();
//The clip may have been stoped (if we reached end but came back at it)
if ( it.value()->isStopped() )
{
......@@ -252,10 +273,11 @@ void TrackWorkflow::setPosition( float pos )
// Else, we found a clip that is not the current one.
else
{
qDebug() << "Using other clip";
//First, we stop the current workflow.
if ( m_current != end )
{
m_current.value()->scheduleStop();
stopClipWorkflow( m_current.value() );
}
//We initialize the new workflow
initializeClipWorkflow( it.value() );
......@@ -268,6 +290,25 @@ void TrackWorkflow::setPosition( float pos )
void TrackWorkflow::requirePositionChanged( float pos )
{
// QMutexLocker lock( m_requiredPositionLock );
// m_requiredPosition = pos;
QMutexLocker lock( m_requiredPositionLock );
m_requiredPosition = pos;
}
void TrackWorkflow::checkStop()
{
while ( m_toStop.isEmpty() == false )
{
ClipWorkflow* cw = m_toStop.head();
if ( cw->getState() == ClipWorkflow::StopRequired )
{
qDebug() << "Stopping from queue";
cw->stop();
m_toStop.dequeue();
}
else
{
qDebug() << cw->getState();
return ;
}
}
}
......@@ -27,6 +27,7 @@
#include <QMutex>
#include <QWaitCondition>
#include <QMap>
#include <QQueue>
#include <QReadWriteLock>
#include "ClipWorkflow.h"
......@@ -70,6 +71,8 @@ class TrackWorkflow : public QObject
bool checkNextClip( qint64 currentFrame );
void computeLength();
void initializeClipWorkflow( ClipWorkflow* cw );
void stopClipWorkflow( ClipWorkflow* cw );
void checkStop();
private:
QMap<qint64, ClipWorkflow*> m_clips;
......@@ -113,6 +116,8 @@ class TrackWorkflow : public QObject
float m_requiredPosition;
QMutex* m_requiredPositionLock;
QQueue<ClipWorkflow*> m_toStop;
public:
void addClip( Clip*, qint64 start );
......
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