Commit 8a94f651 authored by Hugo Beauzee-Luyssen's avatar Hugo Beauzee-Luyssen

Fixed other bugs, but big refactoring incomming...

parent 4e6cbbc1
...@@ -32,26 +32,37 @@ ClipWorkflow::ClipWorkflow( Clip::Clip* clip, QMutex* condMutex, QWaitCondition* ...@@ -32,26 +32,37 @@ ClipWorkflow::ClipWorkflow( Clip::Clip* clip, QMutex* condMutex, QWaitCondition*
m_waitCond( waitCond ), m_waitCond( waitCond ),
m_mediaPlayer(NULL), m_mediaPlayer(NULL),
m_isReady( false ), m_isReady( false ),
m_endReached( false ) m_endReached( false ),
m_stopScheduled( false )
{ {
m_mutex = new QReadWriteLock(); m_renderCompleteMutex = new QReadWriteLock();
m_buffer = new unsigned char[VIDEOHEIGHT * VIDEOWIDTH * 4]; m_buffer = new unsigned char[VIDEOHEIGHT * VIDEOWIDTH * 4];
m_initMutex = new QReadWriteLock(); m_initMutex = new QReadWriteLock();
m_endReachedLock = new QReadWriteLock(); m_endReachedLock = new QReadWriteLock();
m_stopScheduledMutex = new QReadWriteLock();
} }
ClipWorkflow::~ClipWorkflow() ClipWorkflow::~ClipWorkflow()
{ {
delete[] m_buffer; delete[] m_buffer;
delete m_mutex; delete m_renderCompleteMutex;
delete m_initMutex; delete m_initMutex;
delete m_endReachedLock; delete m_endReachedLock;
delete m_stopScheduledMutex;
} }
bool ClipWorkflow::renderComplete() const bool ClipWorkflow::renderComplete() const
{ {
QReadLocker lock( m_mutex ); QReadLocker lock( m_renderCompleteMutex );
return m_renderComplete; QReadLocker lock2( m_endReachedLock );
return ( m_renderComplete || ( m_endReached == true) );
}
void ClipWorkflow::scheduleStop()
{
QWriteLocker lock( m_stopScheduledMutex );
m_stopScheduled = true;
} }
unsigned char* ClipWorkflow::getOutput() unsigned char* ClipWorkflow::getOutput()
...@@ -67,7 +78,7 @@ void ClipWorkflow::lock( ClipWorkflow* clipWorkflow, void** pp_ret ) ...@@ -67,7 +78,7 @@ void ClipWorkflow::lock( ClipWorkflow* clipWorkflow, void** pp_ret )
//In any case, we give vlc a buffer to render in... //In any case, we give vlc a buffer to render in...
//If we don't, segmentation fault will catch us and eat our brain !! ahem... //If we don't, segmentation fault will catch us and eat our brain !! ahem...
qDebug() << "Locking in ClipWorkflow::lock"; // qDebug() << "Locking in ClipWorkflow::lock";
*pp_ret = clipWorkflow->m_buffer; *pp_ret = clipWorkflow->m_buffer;
} }
...@@ -75,34 +86,30 @@ void ClipWorkflow::unlock( ClipWorkflow* clipWorkflow ) ...@@ -75,34 +86,30 @@ void ClipWorkflow::unlock( ClipWorkflow* clipWorkflow )
{ {
if ( clipWorkflow->m_isReady == true ) if ( clipWorkflow->m_isReady == true )
{ {
QMutexLocker lock5( clipWorkflow->m_condMutex );
{ {
QReadLocker lock( clipWorkflow->m_endReachedLock ); QWriteLocker lock( clipWorkflow->m_endReachedLock );
if ( clipWorkflow->m_endReached == true ) if ( clipWorkflow->m_endReached == true )
{ {
qDebug() << "UnLocking in ClipWorkflow::unlock"; qDebug() << "UnLocking in ClipWorkflow::unlock (endReached == true)";
return ; return ;
} }
} QReadLocker lock2( clipWorkflow->m_stopScheduledMutex );
{ if ( clipWorkflow->m_stopScheduled == true )
QWriteLocker lock2( clipWorkflow->m_mutex ); {
qDebug() << "UnLocking in ClipWorkflow::unlock (stopScheduled == true)";
return ;
}
QWriteLocker lock3( clipWorkflow->m_renderCompleteMutex );
clipWorkflow->m_renderComplete = true; clipWorkflow->m_renderComplete = true;
if ( clipWorkflow->m_mediaPlayer->getPosition() > clipWorkflow->m_clip->getEnd() )
clipWorkflow->m_endReached = true;
} }
if ( clipWorkflow->m_mediaPlayer->getPosition() > clipWorkflow->m_clip->getEnd() )
{
QWriteLocker lock2( clipWorkflow->m_endReachedLock );
clipWorkflow->m_endReached = true;
}
QMutexLocker lock( clipWorkflow->m_condMutex );
clipWorkflow->m_waitCond->wait( clipWorkflow->m_condMutex ); clipWorkflow->m_waitCond->wait( clipWorkflow->m_condMutex );
} }
qDebug() << "UnLocking in ClipWorkflow::unlock"; // qDebug() << "UnLocking in ClipWorkflow::unlock";
}
void ClipWorkflow::setRenderComplete()
{
} }
void ClipWorkflow::setVmem() void ClipWorkflow::setVmem()
...@@ -128,6 +135,7 @@ void ClipWorkflow::setVmem() ...@@ -128,6 +135,7 @@ void ClipWorkflow::setVmem()
void ClipWorkflow::initialize( LibVLCpp::MediaPlayer* mediaPlayer ) void ClipWorkflow::initialize( LibVLCpp::MediaPlayer* mediaPlayer )
{ {
reinitFlags();
setVmem(); setVmem();
m_mediaPlayer = mediaPlayer; m_mediaPlayer = mediaPlayer;
m_mediaPlayer->setMedia( m_clip->getParent()->getVLCMedia() ); m_mediaPlayer->setMedia( m_clip->getParent()->getVLCMedia() );
...@@ -207,20 +215,11 @@ const Clip* ClipWorkflow::getClip() const ...@@ -207,20 +215,11 @@ const Clip* ClipWorkflow::getClip() const
void ClipWorkflow::stop() void ClipWorkflow::stop()
{ {
Q_ASSERT( m_mediaPlayer != NULL ); qDebug() << "Calling mediaPlayer::stop()";
{
QWriteLocker lock2( m_mutex );
m_renderComplete = false;
}
{
QWriteLocker lock2( m_endReachedLock );
m_endReached = true;
}
{
QWriteLocker lock( m_initMutex);
m_isReady = false;
}
m_mediaPlayer->stop(); m_mediaPlayer->stop();
qDebug() << "Succesfully called mediaPlayer::stop()";
Q_ASSERT( m_mediaPlayer != NULL );
reinitFlags();
m_mediaPlayer = NULL; m_mediaPlayer = NULL;
qDebug() << "Stoped ClipWorkflow"; qDebug() << "Stoped ClipWorkflow";
} }
...@@ -234,3 +233,23 @@ bool ClipWorkflow::isStopped() const ...@@ -234,3 +233,23 @@ bool ClipWorkflow::isStopped() const
{ {
return ( m_mediaPlayer == NULL ); return ( m_mediaPlayer == NULL );
} }
void ClipWorkflow::reinitFlags()
{
{
QWriteLocker lock2( m_renderCompleteMutex );
m_renderComplete = false;
}
{
QWriteLocker lock2( m_endReachedLock );
m_endReached = false;
}
{
QWriteLocker lock( m_initMutex);
m_isReady = false;
}
{
QWriteLocker lock( m_stopScheduledMutex );
m_stopScheduled = false;
}
}
...@@ -45,6 +45,11 @@ class ClipWorkflow : public QObject ...@@ -45,6 +45,11 @@ class ClipWorkflow : public QObject
ClipWorkflow( Clip* clip, QMutex* condMutex, QWaitCondition* waitCond ); ClipWorkflow( Clip* clip, QMutex* condMutex, QWaitCondition* waitCond );
virtual ~ClipWorkflow(); virtual ~ClipWorkflow();
/**
* Will return true if the render is completed or the end of the clip has been
* reached.
* If the workflow is still rendering, this will return false.
*/
bool renderComplete() const; bool renderComplete() const;
unsigned char* getOutput(); unsigned char* getOutput();
void initialize( LibVLCpp::MediaPlayer* mediaPlayer ); void initialize( LibVLCpp::MediaPlayer* mediaPlayer );
...@@ -67,24 +72,31 @@ class ClipWorkflow : public QObject ...@@ -67,24 +72,31 @@ class ClipWorkflow : public QObject
*/ */
bool isStopped() const; bool isStopped() const;
void scheduleStop();
private: private:
static void lock( ClipWorkflow* clipWorkflow, void** pp_ret ); static void lock( ClipWorkflow* clipWorkflow, void** pp_ret );
static void unlock( ClipWorkflow* clipWorkflow ); static void unlock( ClipWorkflow* clipWorkflow );
void setVmem(); void setVmem();
void setRenderComplete(); void reinitFlags();
private: private:
Clip* m_clip; Clip* m_clip;
QReadWriteLock* m_mutex; QReadWriteLock* m_renderCompleteMutex;
bool m_renderComplete; bool m_renderComplete;
unsigned char* m_buffer; unsigned char* m_buffer;
QMutex* m_condMutex; QMutex* m_condMutex;
QWaitCondition* m_waitCond; QWaitCondition* m_waitCond;
LibVLCpp::MediaPlayer* m_mediaPlayer; LibVLCpp::MediaPlayer* m_mediaPlayer;
QReadWriteLock* m_initMutex; QReadWriteLock* m_initMutex;
bool m_isReady; bool m_isReady;
bool m_endReached;
QReadWriteLock* m_endReachedLock; QReadWriteLock* m_endReachedLock;
bool m_endReached;
QReadWriteLock* m_stopScheduledMutex;
bool m_stopScheduled;
public slots: public slots:
void pauseAfterPlaybackStarted(); void pauseAfterPlaybackStarted();
......
...@@ -137,13 +137,13 @@ unsigned char* TrackWorkflow::getOutput( qint64 currentFrame ) ...@@ -137,13 +137,13 @@ unsigned char* TrackWorkflow::getOutput( qint64 currentFrame )
QReadLocker lock( m_currentLock ); QReadLocker lock( m_currentLock );
// qDebug() << "Frame nb" << currentFrame; qDebug() << "Frame nb" << currentFrame;
clipsRemaining = checkNextClip( currentFrame ); clipsRemaining = checkNextClip( currentFrame );
if ( m_current == m_clips.end() ) if ( m_current == m_clips.end() )
{ {
if ( clipsRemaining == false ) if ( clipsRemaining == false )
{ {
// qDebug() << "End Reached"; qDebug() << "End Reached";
emit endReached(); emit endReached();
} }
// qDebug() << "Stil no clip at this time, going to the next frame"; // qDebug() << "Stil no clip at this time, going to the next frame";
...@@ -154,6 +154,8 @@ unsigned char* TrackWorkflow::getOutput( qint64 currentFrame ) ...@@ -154,6 +154,8 @@ unsigned char* TrackWorkflow::getOutput( qint64 currentFrame )
{ {
m_waitCondition->wakeAll(); m_waitCondition->wakeAll();
// We wait until the end of the render. If the clip reach end, this
// will also return true.
while ( m_current.value()->renderComplete() == false ) while ( m_current.value()->renderComplete() == false )
usleep( 20 ); usleep( 20 );
if ( m_current.value()->isEndReached() == false ) if ( m_current.value()->isEndReached() == false )
...@@ -172,9 +174,26 @@ unsigned char* TrackWorkflow::getOutput( qint64 currentFrame ) ...@@ -172,9 +174,26 @@ unsigned char* TrackWorkflow::getOutput( qint64 currentFrame )
void TrackWorkflow::stopCurrentClipWorkflow() void TrackWorkflow::stopCurrentClipWorkflow()
{ {
qDebug() << "About to stopCurrentClipWorkflow()";
//Awaking renderer thread to avoid dead lock //Awaking renderer thread to avoid dead lock
m_current.value()->scheduleStop();
m_waitCondition->wakeAll();
if ( m_current.value()->isStopped() == false ) if ( m_current.value()->isStopped() == false )
m_current.value()->stop(); m_current.value()->stop();
qDebug() << "Stopped stopCurrentClipWorkflow();";
}
void TrackWorkflow::initializeClipWorkflow( ClipWorkflow* cw )
{
//>Launching the initialization
qDebug()<< "Initializing clip workflow (initializeClipWorkflow())";
cw->initialize( m_mediaPlayer );
//And then wait for it to be ready
while ( cw->isReady() == false )
usleep( 20 );
//Once it is, we actually start the render
cw->startRender();
qDebug() << "End of clip workflow reinitialization";
} }
void TrackWorkflow::setPosition( float pos ) void TrackWorkflow::setPosition( float pos )
...@@ -202,7 +221,7 @@ void TrackWorkflow::setPosition( float pos ) ...@@ -202,7 +221,7 @@ void TrackWorkflow::setPosition( float pos )
if ( it.key() <= frame && if ( it.key() <= frame &&
( it.key() + it.value()->getClip()->getLength() ) > frame ) ( it.key() + it.value()->getClip()->getLength() ) > frame )
{ {
qDebug() << "Found new current clip workflow"; // qDebug() << "Found new current clip workflow";
break; break;
} }
else if ( next == m_clips.end() && it.key() > frame ) else if ( next == m_clips.end() && it.key() > frame )
...@@ -214,13 +233,13 @@ void TrackWorkflow::setPosition( float pos ) ...@@ -214,13 +233,13 @@ void TrackWorkflow::setPosition( float pos )
next = it; next = it;
if ( next != m_clips.begin() ) if ( next != m_clips.begin() )
{ {
qDebug() << "Next clip isn't the first one"; // qDebug() << "Next clip isn't the first one";
next = next - 1; //Since the iterator must point to the previous video next = next - 1; //Since the iterator must point to the previous video
} }
else else
{ {
next = end; next = end;
qDebug() << "Next clip is the first of the track"; // qDebug() << "Next clip is the first of the track";
} }
// in order to checkNextClip() to work. // in order to checkNextClip() to work.
it = end; it = end;
...@@ -229,36 +248,45 @@ void TrackWorkflow::setPosition( float pos ) ...@@ -229,36 +248,45 @@ void TrackWorkflow::setPosition( float pos )
++it; ++it;
} }
if ( it == m_clips.end() ) //No clip was found :
if ( it == end )
{ {
//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 ) if ( m_current != end )
{ {
stopCurrentClipWorkflow(); stopCurrentClipWorkflow();
} }
m_current = next; m_current = next;
} }
// If the clip found is the current, we just change the position of the
// media player
else if ( it == m_current ) else if ( it == m_current )
{ {
//The clip may have been stoped (if we reached end but came back at it)
if ( it.value()->isStopped() )
{
initializeClipWorkflow( it.value() );
}
qDebug() << "Changing the position of the current clip"; qDebug() << "Changing the position of the current clip";
//We're changing the position of the current clip
it.value()->setPosition( (float)( frame - it.key() ) / (float)(it.value()->getClip()->getLength()) ); it.value()->setPosition( (float)( frame - it.key() ) / (float)(it.value()->getClip()->getLength()) );
//Awaking renderers to avoid them to be stuck inside of the lock... //Awaking renderers to avoid them to be stuck inside of the lock...
// qDebug() << "Waking all renderer threads"; // qDebug() << "Waking all renderer threads";
m_waitCondition->wakeAll(); m_waitCondition->wakeAll();
} }
// Else, we found a clip that is not the current one.
else else
{ {
qDebug() << "Switching to other Clip"; // qDebug() << "Switching to other Clip";
//First, we stop the current workflow.
if ( m_current != end ) if ( m_current != end )
{ {
stopCurrentClipWorkflow(); stopCurrentClipWorkflow();
// m_waitCondition->wakeAll();
} }
//We initialize the new workflow
it.value()->initialize( m_mediaPlayer ); initializeClipWorkflow( it.value() );
while ( it.value()->isReady() == false ) //And this is now our current clip
usleep( 20 );
it.value()->startRender();
m_current = it; m_current = it;
// qDebug() << "Switched current clip workflow"; // qDebug() << "Switched current clip workflow";
} }
......
...@@ -69,6 +69,7 @@ class TrackWorkflow : public QObject ...@@ -69,6 +69,7 @@ class TrackWorkflow : public QObject
bool checkNextClip( qint64 currentFrame ); bool checkNextClip( qint64 currentFrame );
void computeLength(); void computeLength();
void stopCurrentClipWorkflow(); void stopCurrentClipWorkflow();
void initializeClipWorkflow( ClipWorkflow* cw );
private: private:
QMap<qint64, ClipWorkflow*> m_clips; QMap<qint64, ClipWorkflow*> m_clips;
......
...@@ -76,6 +76,7 @@ void RenderPreviewWidget::unlock( void* ) ...@@ -76,6 +76,7 @@ void RenderPreviewWidget::unlock( void* )
void RenderPreviewWidget::stopPreview() void RenderPreviewWidget::stopPreview()
{ {
//This might be called multiple times, but this is due to Qt message loop
m_mediaPlayer->stop(); m_mediaPlayer->stop();
m_isRendering = false; m_isRendering = false;
qDebug() << "Stopped"; qDebug() << "Stopped";
......
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