Commit 66610b1a authored by Hugo Beauzee-Luyssen's avatar Hugo Beauzee-Luyssen

Changing render mode to a buffer queue, to avoid losing frames

parent 60ce125d
......@@ -28,12 +28,12 @@
ClipWorkflow::ClipWorkflow( Clip::Clip* clip ) :
m_clip( clip ),
m_buffer( NULL ),
m_mediaPlayer(NULL),
m_state( ClipWorkflow::Stopped ),
m_requiredState( ClipWorkflow::None )
{
m_buffer = new unsigned char[VIDEOHEIGHT * VIDEOWIDTH * 4];
for ( unsigned int i = 0; i < 5; ++i )
m_availableBuffers.enqueue( new unsigned char[VIDEOHEIGHT * VIDEOWIDTH * 4] );
m_stateLock = new QReadWriteLock;
m_requiredStateLock = new QMutex;
m_waitCond = new QWaitCondition;
......@@ -42,10 +42,12 @@ ClipWorkflow::ClipWorkflow( Clip::Clip* clip ) :
m_renderWaitCond = new WaitCondition;
m_pausingStateWaitCond = new WaitCondition;
m_pausedThreadCondWait = new WaitCondition;
m_buffersLock = new QMutex;
}
ClipWorkflow::~ClipWorkflow()
{
delete m_buffersLock;
delete m_pausedThreadCondWait;
delete m_pausingStateWaitCond;
delete m_initWaitCond;
......@@ -53,12 +55,21 @@ ClipWorkflow::~ClipWorkflow()
delete m_waitCond;
delete m_requiredStateLock;
delete m_stateLock;
delete[] m_buffer;
while ( m_buffers.empty() == false )
delete[] m_availableBuffers.dequeue();
}
unsigned char* ClipWorkflow::getOutput()
{
return m_buffer;
QMutexLocker lock( m_buffersLock );
qDebug() << "Getting output";
if ( m_buffers.isEmpty() == true )
return NULL;
unsigned char* buff = m_buffers.dequeue();
m_availableBuffers.enqueue( buff );
return buff;
}
void ClipWorkflow::checkStateChange()
......@@ -75,11 +86,20 @@ void ClipWorkflow::checkStateChange()
void ClipWorkflow::lock( ClipWorkflow* cw, void** pp_ret )
{
*pp_ret = cw->m_buffer;
qDebug() << "Computing new frame";
cw->m_buffersLock->lock();
unsigned char* buff;
if ( cw->m_availableBuffers.size() > 0 )
buff = cw->m_availableBuffers.dequeue();
else
buff = new unsigned char[VIDEOHEIGHT * VIDEOWIDTH * 4];
cw->m_buffers.enqueue( buff );
*pp_ret = buff;
}
void ClipWorkflow::unlock( ClipWorkflow* cw )
{
cw->m_buffersLock->unlock();
cw->m_stateLock->lockForWrite();
if ( cw->m_state == Rendering )
......
......@@ -33,6 +33,7 @@
#include <QMutex>
#include "WaitCondition.hpp"
#include <QObject>
#include <QQueue>
#include "Clip.h"
#include "VLCMediaPlayer.h"
......@@ -160,8 +161,6 @@ class ClipWorkflow : public QObject
LibVLCpp::MediaPlayer* getMediaPlayer();
// void activateOneFrameOnly();
private:
static void lock( ClipWorkflow* clipWorkflow, void** pp_ret );
static void unlock( ClipWorkflow* clipWorkflow );
......@@ -181,18 +180,9 @@ class ClipWorkflow : public QObject
*/
LibVLCpp::Media* m_vlcMedia;
unsigned char* m_buffer;
//unsigned char* m_backBuffer;
/**
* This allow the render procedure to know in which buffer it should render.
* If true, then the render occurs in the back buffer, which means the
* returned buffer much be the "front" buffer.
* In other term :
* - When m_usingBackBuffer == false, lock() will return m_buffer, and getOutput() m_backBuffer
* - When m_usingBackBuffer == true, lock() will return m_backBuffer, and getOutput() m_buffer
*/
//bool m_usingBackBuffer;
//QReadWriteLock* m_backBufferLock;
QQueue<unsigned char*> m_availableBuffers;
QQueue<unsigned char*> m_buffers;
QMutex* m_buffersLock;
LibVLCpp::MediaPlayer* m_mediaPlayer;
......
......@@ -105,7 +105,7 @@ void MainWorkflow::startRender()
computeLength();
}
unsigned char* MainWorkflow::getOutput()
void MainWorkflow::getOutput()
{
QReadLocker lock( m_renderStartedLock );
QMutexLocker lock2( m_renderMutex );
......@@ -118,26 +118,19 @@ unsigned char* MainWorkflow::getOutput()
m_synchroneRenderingBuffer = NULL;
if ( m_renderStarted == true )
{
unsigned char* ret;
for ( unsigned int i = 0; i < m_trackCount; ++i )
{
if ( m_tracks[i].activated() == false )
continue ;
if ( ( ret = m_tracks[i]->getOutput( m_currentFrame ) ) != NULL )
if ( m_tracks[i]->getOutput( m_currentFrame ) != false )
{
m_nbTracksToRender.fetchAndAddAcquire( 1 );
break ;
}
}
if ( ret == NULL )
ret = MainWorkflow::blackOutput;
nextFrame();
return ret;
}
else
return MainWorkflow::blackOutput;
}
void MainWorkflow::pause()
......@@ -316,9 +309,7 @@ unsigned char* MainWorkflow::getSynchroneOutput()
{
m_synchroneRenderWaitConditionMutex->lock();
getOutput();
// qDebug() << "Waiting for synchrone output";
m_synchroneRenderWaitCondition->wait( m_synchroneRenderWaitConditionMutex );
// qDebug() << "Got it";
m_synchroneRenderWaitConditionMutex->unlock();
if ( m_synchroneRenderingBuffer == NULL )
return MainWorkflow::blackOutput;
......
......@@ -42,7 +42,7 @@ class MainWorkflow : public QObject, public Singleton<MainWorkflow>
void addClip( Clip* clip, unsigned int trackId, qint64 start );
void startRender();
unsigned char* getOutput();
void getOutput();
unsigned char* getSynchroneOutput();
/**
......
......@@ -82,12 +82,10 @@ qint64 TrackWorkflow::getLength() const
return m_length;
}
unsigned char* TrackWorkflow::renderClip( ClipWorkflow* cw, qint64 currentFrame,
void TrackWorkflow::renderClip( ClipWorkflow* cw, qint64 currentFrame,
qint64 start , bool needRepositioning,
bool pauseAfterRender )
{
unsigned char* ret = NULL;
cw->getStateLock()->lockForRead();
if ( cw->getState() == ClipWorkflow::ThreadPaused && pauseAfterRender == false )
......@@ -121,7 +119,6 @@ unsigned char* TrackWorkflow::renderClip( ClipWorkflow* cw, qint64 currentF
float pos = ( (float)( currentFrame - start ) / (float)(cw->getClip()->getLength()) );
cw->setPosition( pos );
}
ret = cw->getOutput();
if ( pauseAfterRender == false )
{
QMutexLocker lock( cw->getSleepMutex() );
......@@ -173,7 +170,6 @@ unsigned char* TrackWorkflow::renderClip( ClipWorkflow* cw, qint64 currentF
{
cw->getStateLock()->unlock();
}
return ret;
}
void TrackWorkflow::preloadClip( ClipWorkflow* cw )
......@@ -272,16 +268,16 @@ void TrackWorkflow::stop()
m_oneFrameOnly = 0;
}
unsigned char* TrackWorkflow::getOutput( qint64 currentFrame )
bool TrackWorkflow::getOutput( qint64 currentFrame )
{
QReadLocker lock( m_clipsLock );
unsigned char* ret = NULL;
QMap<qint64, ClipWorkflow*>::iterator it = m_clips.begin();
QMap<qint64, ClipWorkflow*>::iterator end = m_clips.end();
static qint64 lastFrame = 0;
bool needRepositioning;
bool oneFrameOnlyFlag = false;
bool hasRendered = false;
if ( m_oneFrameOnly == 1 )
oneFrameOnlyFlag = true;
......@@ -312,8 +308,9 @@ unsigned char* TrackWorkflow::getOutput( qint64 currentFrame )
if ( start <= currentFrame && currentFrame <= start + cw->getClip()->getLength() )
{
m_nbClipToRender.fetchAndAddAcquire( 1 );
ret = renderClip( cw, currentFrame, start, needRepositioning, oneFrameOnlyFlag );
renderClip( cw, currentFrame, start, needRepositioning, oneFrameOnlyFlag );
lastFrame = currentFrame;
hasRendered = true;
}
//Is it about to be rendered ?
else if ( start > currentFrame &&
......@@ -333,9 +330,7 @@ unsigned char* TrackWorkflow::getOutput( qint64 currentFrame )
{
m_oneFrameOnly = 0;
}
if ( ret == NULL )
clipWorkflowRenderCompleted( NULL );
return ret;
return hasRendered;
}
void TrackWorkflow::pauseClipWorkflow( ClipWorkflow* cw )
......@@ -485,6 +480,7 @@ void TrackWorkflow::clipWorkflowRenderCompleted( ClipWorkflow* cw )
{
if ( cw != NULL )
{
qDebug() << "Track is asking a ClipWorkflow output";
m_synchroneRenderBuffer = cw->getOutput();
}
else
......
......@@ -49,7 +49,7 @@ class TrackWorkflow : public QObject
TrackWorkflow( unsigned int trackId );
~TrackWorkflow();
unsigned char* getOutput( qint64 currentFrame );
bool getOutput( qint64 currentFrame );
qint64 getLength() const;
void stop();
/**
......@@ -72,7 +72,7 @@ class TrackWorkflow : public QObject
private:
void computeLength();
unsigned char* renderClip( ClipWorkflow* cw, qint64 currentFrame,
void renderClip( ClipWorkflow* cw, qint64 currentFrame,
qint64 start, bool needRepositioning,
bool pauseAfterRender );
void preloadClip( ClipWorkflow* cw );
......
......@@ -17,7 +17,7 @@ WorkflowFileRenderer::~WorkflowFileRenderer()
void* WorkflowFileRenderer::lock( void* datas )
{
WorkflowFileRenderer* self = reinterpret_cast<WorkflowFileRenderer*>( datas );
return self->m_mainWorkflow->getOutput();
return self->m_mainWorkflow->getSynchroneOutput();
}
void WorkflowFileRenderer::unlock( void* )
......
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