Commit 5fec77b4 authored by Hugo Beauzee-Luyssen's avatar Hugo Beauzee-Luyssen

Refactoring is almost finished :)

It works with the sound, a few hangs excepted. Should be fixed very soon
\o/
parent 470ff5d5
......@@ -67,7 +67,7 @@ void WorkflowRenderer::initializeRenderer()
strcat( inputSlave, audioParameters );
m_media = new LibVLCpp::Media( "imem://" + QString( videoString ) );
// m_media->addOption( inputSlave );
m_media->addOption( inputSlave );
sprintf( callbacks, "imem-get=%lld", (qint64)WorkflowRenderer::lock );
m_media->addOption( callbacks );
......@@ -155,8 +155,6 @@ int WorkflowRenderer::lockAudio( WorkflowRenderer* self, int64_t *pts, size
}
else
{
//We set the nbSample to 10ms, which is 1/100 of a sec, so we divide the samplerate
//by 100.
nbSample = self->m_rate / self->m_outputFps;
unsigned int buffSize = self->m_nbChannels * 2 * nbSample;
if ( WorkflowRenderer::silencedAudioBuffer == NULL )
......
......@@ -41,9 +41,7 @@ public:
Q_ASSERT( m_pool.empty() == true );
delete m_mutex;
}
//Yes, this is a const T, not a const T&
//This is usefull when manipulating copy on write :)
const T pop()
T pop()
{
QMutexLocker lock( m_mutex );
if ( m_pool.size() == 0 )
......
......@@ -4,5 +4,6 @@ HEADERS += MemoryPool.hpp \
Toggleable.hpp \
WaitCondition.hpp \
VlmcDebug.h \
Pool.hpp
Pool.hpp \
mdate.h
SOURCES += VlmcDebug.cpp
......@@ -23,23 +23,18 @@
#include <QtDebug>
#include "AudioClipWorkflow.h"
#include "StackedBuffer.hpp"
AudioClipWorkflow::AudioClipWorkflow( Clip* clip ) :
ClipWorkflow( clip )
{
m_availableBuffersLock = new QReadWriteLock;
m_computedBuffersLock = new QReadWriteLock;
}
AudioClipWorkflow::~AudioClipWorkflow()
{
while ( m_availableBuffers.isEmpty() == false )
delete m_availableBuffers.pop();
delete m_availableBuffers.dequeue();
while ( m_computedBuffers.isEmpty() == false )
delete m_computedBuffers.pop();
delete m_availableBuffersLock;
delete m_computedBuffersLock;
delete m_computedBuffers.dequeue();
}
void* AudioClipWorkflow::getLockCallback()
......@@ -55,14 +50,15 @@ void* AudioClipWorkflow::getUnlockCallback()
void* AudioClipWorkflow::getOutput( ClipWorkflow::GetMode mode )
{
QMutexLocker lock( m_renderLock );
QMutexLocker lock2( m_computedBuffersMutex );
preGetOutput();
qWarning() << "Audio. Available:" << m_availableBuffers.count() << "Computed:" << m_computedBuffers.count();
// qWarning() << "Audio. Available:" << m_availableBuffers.count() << "Computed:" << m_computedBuffers.count();
if ( isEndReached() == true )
return NULL;
if ( mode == ClipWorkflow::Get )
qCritical() << "A sound buffer should never be asked with 'Get' mode";
StackedBuffer<AudioSample*>* buff = new StackedBuffer<AudioSample*>( m_computedBuffers.pop(), &m_availableBuffers, true );
StackedBuffer<AudioSample*, AudioClipWorkflow>* buff = new StackedBuffer<AudioSample*, AudioClipWorkflow>( m_computedBuffers.dequeue(), this, true );
postGetOutput();
return buff;
}
......@@ -91,6 +87,8 @@ AudioClipWorkflow::AudioSample* AudioClipWorkflow::createBuffer( size_t size
void AudioClipWorkflow::lock( AudioClipWorkflow* cw, uint8_t** pcm_buffer , unsigned int size )
{
cw->m_renderLock->lock();
cw->m_computedBuffersMutex->lock();
QMutexLocker lock( cw->m_availableBuffersMutex );
//If there's no buffer at all, it must be the first render
if ( cw->m_availableBuffers.count() == 0 && cw->m_computedBuffers.count() == 0 )
{
......@@ -109,7 +107,7 @@ void AudioClipWorkflow::lock( AudioClipWorkflow* cw, uint8_t** pcm_buffer
as = cw->createBuffer( size );
}
else
as = cw->m_availableBuffers.pop();
as = cw->m_availableBuffers.dequeue();
cw->m_computedBuffers.push_back( as );
*pcm_buffer = as->buff;
}
......@@ -137,11 +135,7 @@ void AudioClipWorkflow::unlock( AudioClipWorkflow* cw, uint8_t* pcm_buffe
}
cw->commonUnlock();
cw->m_renderLock->unlock();
}
uint32_t AudioClipWorkflow::getAvailableBuffers() const
{
return m_availableBuffers.count();
cw->m_computedBuffersMutex->unlock();
}
uint32_t AudioClipWorkflow::getComputedBuffers() const
......@@ -153,3 +147,9 @@ uint32_t AudioClipWorkflow::getMaxComputedBuffers() const
{
return AudioClipWorkflow::nbBuffers;
}
void AudioClipWorkflow::releaseBuffer( AudioSample *sample )
{
QMutexLocker lock( m_availableBuffersMutex );
m_availableBuffers.enqueue( sample );
}
......@@ -25,6 +25,7 @@
#include "ClipWorkflow.h"
#include "Pool.hpp"
#include "StackedBuffer.hpp"
class AudioClipWorkflow : public ClipWorkflow
{
......@@ -45,15 +46,15 @@ class AudioClipWorkflow : public ClipWorkflow
virtual void* getOutput( ClipWorkflow::GetMode mode );
protected:
virtual uint32_t getAvailableBuffers() const;
virtual uint32_t getComputedBuffers() const;
virtual uint32_t getMaxComputedBuffers() const;
private:
QReadWriteLock* m_computedBuffersLock;
Pool<AudioSample*> m_computedBuffers;
QReadWriteLock* m_availableBuffersLock;
Pool<AudioSample*> m_availableBuffers;
void releaseBuffer( AudioSample* sample );
private:
QQueue<AudioSample*> m_computedBuffers;
QQueue<AudioSample*> m_availableBuffers;
void initVlcOutput();
AudioSample* createBuffer( size_t size );
static void lock( AudioClipWorkflow* clipWorkflow, uint8_t** pcm_buffer , unsigned int size );
......@@ -64,6 +65,8 @@ class AudioClipWorkflow : public ClipWorkflow
//FIXME: this is totally random powered ! Please adjust with a value that does make sense...
static const uint32_t nbBuffers = 1024;
friend class StackedBuffer<AudioSample*, AudioClipWorkflow>;
};
#endif // AUDIOCLIPWORKFLOW_H
......@@ -41,6 +41,8 @@ ClipWorkflow::ClipWorkflow( Clip::Clip* clip ) :
m_pausingStateWaitCond = new WaitCondition;
m_renderLock = new QMutex;
m_feedingCondWait = new WaitCondition;
m_availableBuffersMutex = new QMutex;
m_computedBuffersMutex = new QMutex;
}
ClipWorkflow::~ClipWorkflow()
......@@ -50,6 +52,8 @@ ClipWorkflow::~ClipWorkflow()
delete m_initWaitCond;
delete m_requiredStateLock;
delete m_stateLock;
delete m_availableBuffersMutex;
delete m_computedBuffersMutex;
}
void ClipWorkflow::checkStateChange()
......@@ -72,13 +76,13 @@ void ClipWorkflow::initialize()
m_vlcMedia = new LibVLCpp::Media( "file:///" + m_clip->getParent()->getFileInfo()->absoluteFilePath() );
m_currentPts = -1;
m_previousPts = -1;
m_pauseDuration = -1;
initVlcOutput();
m_mediaPlayer = MemoryPool<LibVLCpp::MediaPlayer>::getInstance()->get();
m_mediaPlayer->setMedia( m_vlcMedia );
connect( m_mediaPlayer, SIGNAL( playing() ), this, SLOT( loadingComplete() ), Qt::DirectConnection );
connect( m_mediaPlayer, SIGNAL( endReached() ), this, SLOT( clipEndReached() ), Qt::DirectConnection );
qDebug() << "Starting clipworkflow playback";
m_mediaPlayer->play();
}
......@@ -90,7 +94,6 @@ void ClipWorkflow::loadingComplete()
connect( m_mediaPlayer, SIGNAL( paused() ), this, SLOT( mediaPlayerPaused() ) );
QMutexLocker lock( m_initWaitCond->getMutex() );
setState( Rendering );
qDebug() << "Waking init wait cond";
m_initWaitCond->wake();
}
......@@ -134,7 +137,6 @@ void ClipWorkflow::stop()
m_mediaPlayer->stop();
disconnect( m_mediaPlayer, SIGNAL( endReached() ), this, SLOT( clipEndReached() ) );
MemoryPool<LibVLCpp::MediaPlayer>::getInstance()->release( m_mediaPlayer );
// qDebug() << "Setting media player to NULL";
m_mediaPlayer = NULL;
setState( Stopped );
QMutexLocker lock( m_requiredStateLock );
......@@ -142,7 +144,6 @@ void ClipWorkflow::stop()
delete m_vlcMedia;
m_initFlag = false;
m_rendering = false;
// qDebug() << "Clipworkflow stopped";
}
else
qDebug() << "ClipWorkflow has already been stopped";
......@@ -197,10 +198,12 @@ void ClipWorkflow::preGetOutput()
if ( getComputedBuffers() == 0 )
{
qWarning() << "Waiting for buffer to be fed";
// qWarning() << "Waiting for buffer to be fed";
m_renderLock->unlock();
qDebug() << "Unlocked render lock, entering cond wait";
m_computedBuffersMutex->unlock();
// qDebug() << "Unlocked render lock, entering cond wait";
m_feedingCondWait->waitLocked();
m_computedBuffersMutex->lock();
m_renderLock->lock();
}
}
......@@ -213,13 +216,13 @@ void ClipWorkflow::postGetOutput()
QWriteLocker lock( m_stateLock );
if ( m_state == ClipWorkflow::Paused )
{
qWarning() << "Unpausing media player";
// qWarning() << "Unpausing media player";
m_state = ClipWorkflow::UnpauseRequired;
//This will act like an "unpause";
m_mediaPlayer->pause();
}
else
qCritical() << "Running out of computed buffers !";
// else
// qCritical() << "Running out of computed buffers !";
}
}
......@@ -229,17 +232,17 @@ void ClipWorkflow::commonUnlock()
//no one is available : we would spawn a new buffer, thus modifying the number of available buffers
if ( getComputedBuffers() == getMaxComputedBuffers() )
{
qWarning() << "Pausing media player";
// qWarning() << "Pausing media player";
setState( ClipWorkflow::PauseRequired );
qDebug() << "State has been set...calling pause method.";
// qDebug() << "State has been set...calling pause method.";
m_mediaPlayer->pause();
qDebug() << "Pause method has been called";
// qDebug() << "Pause method has been called";
}
if ( getComputedBuffers() == 1 )
{
qDebug() << "Waking feeding cont wait... acquiring lock";
// qDebug() << "Waking feeding cont wait... acquiring lock";
QMutexLocker lock( m_feedingCondWait->getMutex() );
qDebug() << "feeding cont wait mutex acquired";
// qDebug() << "feeding cont wait mutex acquired";
m_feedingCondWait->wake();
}
checkStateChange();
......@@ -251,18 +254,27 @@ void ClipWorkflow::computePtsDiff( qint64 pts )
m_previousPts = pts;
if ( m_currentPts == -1 )
m_currentPts = pts;
m_previousPts = m_currentPts;
if ( m_pauseDuration != -1 )
{
m_previousPts = m_currentPts + m_pauseDuration;
m_pauseDuration = -1;
}
else
m_previousPts = m_currentPts;
m_currentPts = qMax( pts, m_previousPts );
}
void ClipWorkflow::mediaPlayerPaused()
{
qWarning() << "\n\n\n\nMedia player paused, waiting for buffers to be consumed\n\n\n\n";
// qWarning() << "\n\n\n\nMedia player paused, waiting for buffers to be consumed\n\n\n\n";
setState( ClipWorkflow::Paused );
m_beginPausePts = mdate();
// qDebug() << "got pause pts:" << m_beginPausePts;
}
void ClipWorkflow::mediaPlayerUnpaused()
{
qWarning() << "Media player unpaused. Go back to rendering";
// qWarning() << "Media player unpaused. Go back to rendering";
setState( ClipWorkflow::Rendering );
m_pauseDuration = mdate() - m_beginPausePts;
}
......@@ -32,6 +32,7 @@
#include "WaitCondition.hpp"
#include "VLCMediaPlayer.h"
#include "LightVideoFrame.h"
#include "mdate.h"
class ClipWorkflow : public QObject
{
......@@ -42,24 +43,24 @@ class ClipWorkflow : public QObject
{
None = -1,
/// \brief Used when the clipworkflow hasn't been started yet
Stopped, //0
Stopped, //0
/// \brief Used when the clipworkflow is launched and active
Rendering, //1
Rendering, //1
/// \brief Used when stopping
Stopping, //2
Stopping, //2
/// \brief Used when end is reached, IE no more frame has to be rendered, but the trackworkflow
/// may eventually ask for some.
EndReached, //3
EndReached, //3
// Here starts internal states :
/// \brief This state will be used when an unpause
/// has been required
UnpauseRequired,
UnpauseRequired, //4
/// \brief This state will be used when a pause
/// has been required
PauseRequired,
PauseRequired, //5
/// \brief This state will be used when the media player is paused,
/// because of a sufficient number of computed buffers
Paused,
Paused, //6
};
/**
......@@ -155,7 +156,8 @@ class ClipWorkflow : public QObject
protected:
void computePtsDiff( qint64 pts );
void commonUnlock();
virtual uint32_t getAvailableBuffers() const = 0;
/// \warning Must be called from a thread safe context.
/// This thread safe context has to be set from the underlying ClipWorkflow implementation.
virtual uint32_t getComputedBuffers() const = 0;
virtual uint32_t getMaxComputedBuffers() const = 0;
......@@ -197,6 +199,11 @@ class ClipWorkflow : public QObject
* while the renderer asks for one.
*/
WaitCondition* m_feedingCondWait;
QMutex* m_computedBuffersMutex;
QMutex* m_availableBuffersMutex;
qint64 m_beginPausePts;
qint64 m_pauseDuration;
protected:
/**
......
......@@ -23,15 +23,16 @@
#ifndef STACKEDBUFFER_HPP
#define STACKEDBUFFER_HPP
#include <QtDebug>
#include "Pool.hpp"
template <typename T>
template <typename T, typename U>
class StackedBuffer
{
public:
StackedBuffer( T buff, Pool<T>* pool, bool mustBeReleased = true ) :
StackedBuffer( T buff, U* poolHandler, bool mustBeReleased = true ) :
m_buff( buff ),
m_pool( pool ),
m_poolHandler( poolHandler ),
m_mustRelease( mustBeReleased )
{
}
......@@ -40,7 +41,7 @@ class StackedBuffer
void release()
{
if ( m_mustRelease == true )
m_pool->release( m_buff );
m_poolHandler->releaseBuffer( m_buff );
delete this;
}
const T& get() const
......@@ -62,7 +63,7 @@ class StackedBuffer
private:
T m_buff;
Pool<T>* m_pool;
U* m_poolHandler;
bool m_mustRelease;
};
......
......@@ -106,15 +106,15 @@ void TrackHandler::getOutput( qint64 currentFrame, qint64 subFrame )
m_effectEngine->setInputFrame( *TrackHandler::nullOutput, i );
else
{
StackedBuffer<LightVideoFrame*>* stackedBuffer =
reinterpret_cast<StackedBuffer<LightVideoFrame*>*>( m_tracks[i]->getOutput( currentFrame, subFrame ) );
StackedBuffer<LightVideoFrame*, VideoClipWorkflow>* stackedBuffer =
reinterpret_cast<StackedBuffer<LightVideoFrame*, VideoClipWorkflow>*>( m_tracks[i]->getOutput( currentFrame, subFrame ) );
m_effectEngine->setInputFrame( *(stackedBuffer->get()), i );
}
}
else
{
StackedBuffer<AudioClipWorkflow::AudioSample*>* stackedBuffer =
reinterpret_cast<StackedBuffer<AudioClipWorkflow::AudioSample*>*> ( m_tracks[i]->getOutput( currentFrame, subFrame ) );
StackedBuffer<AudioClipWorkflow::AudioSample*, AudioClipWorkflow>* stackedBuffer =
reinterpret_cast<StackedBuffer<AudioClipWorkflow::AudioSample*, AudioClipWorkflow>*> ( m_tracks[i]->getOutput( currentFrame, subFrame ) );
if ( stackedBuffer != NULL )
m_tmpAudioBuffer = stackedBuffer->get();
//else if will remain NULL
......
......@@ -135,7 +135,6 @@ void* TrackWorkflow::renderClip( ClipWorkflow* cw, qint64 currentFrame,
cw->getState() == ClipWorkflow::PauseRequired ||
cw->getState() == ClipWorkflow::UnpauseRequired )
{
qDebug() << "Asking for output";
cw->getStateLock()->unlock();
if ( needRepositioning == true )
adjustClipTime( currentFrame, start, cw );
......@@ -272,9 +271,9 @@ void* TrackWorkflow::getOutput( qint64 currentFrame, qint64 subFra
qCritical() << "There's more than one clip to render here. Undefined behaviour !";
ret = renderClip( cw, currentFrame, start, needRepositioning );
if ( m_trackType == MainWorkflow::VideoTrack )
m_videoStackedBuffer = reinterpret_cast<StackedBuffer<LightVideoFrame*>*>( ret );
m_videoStackedBuffer = reinterpret_cast<StackedBuffer<LightVideoFrame*, VideoClipWorkflow>*>( ret );
else
m_audioStackedBuffer = reinterpret_cast<StackedBuffer<AudioClipWorkflow::AudioSample*>*>( ret );
m_audioStackedBuffer = reinterpret_cast<StackedBuffer<AudioClipWorkflow::AudioSample*, AudioClipWorkflow>*>( ret );
}
//Is it about to be rendered ?
else if ( start > currentFrame &&
......
......@@ -45,6 +45,9 @@
#define MAX_TRACKS 64
#endif
class VideoClipWorkflow;
class AudioClipWorkflow;
class TrackWorkflow : public QObject
{
Q_OBJECT
......@@ -110,8 +113,8 @@ class TrackWorkflow : public QObject
MainWorkflow::TrackType m_trackType;
qint64 m_lastFrame;
//Damn i wish this could be a meta-if :D (ho wait... it could be ! once the code will be cleaned)
StackedBuffer<LightVideoFrame*>* m_videoStackedBuffer;
StackedBuffer<AudioClipWorkflow::AudioSample*> * m_audioStackedBuffer;
StackedBuffer<LightVideoFrame*, VideoClipWorkflow>* m_videoStackedBuffer;
StackedBuffer<AudioClipWorkflow::AudioSample*, AudioClipWorkflow>* m_audioStackedBuffer;
signals:
void trackEndReached( unsigned int );
......
......@@ -34,18 +34,14 @@ VideoClipWorkflow::VideoClipWorkflow( Clip* clip ) : ClipWorkflow( clip )
* MainWorkflow::getInstance()->getHeight()
* Pixel::NbComposantes ) );
}
// m_availableBuffersLock = new QReadWriteLock;
// m_computedBuffersLock = new QReadWriteLock;
}
VideoClipWorkflow::~VideoClipWorkflow()
{
while ( m_availableBuffers.isEmpty() == false )
delete m_availableBuffers.pop();
delete m_availableBuffers.dequeue();
while ( m_computedBuffers.isEmpty() == false )
delete m_computedBuffers.pop();
// delete m_availableBuffersLock;
// delete m_computedBuffersLock;
delete m_computedBuffers.dequeue();
}
void VideoClipWorkflow::initVlcOutput()
......@@ -88,40 +84,42 @@ void* VideoClipWorkflow::getUnlockCallback()
void* VideoClipWorkflow::getOutput( ClipWorkflow::GetMode mode )
{
QMutexLocker lock( m_renderLock );
QMutexLocker lock2( m_computedBuffersMutex );
preGetOutput();
qWarning() << "Video::getOutput(). Available:" << m_availableBuffers.count() << "Computed:" << m_computedBuffers.count();
// qWarning() << "Video::getOutput(). Available:" << m_availableBuffers.count() << "Computed:" << m_computedBuffers.count();
if ( isEndReached() == true )
{
qWarning() << "End is reached. returning NULL";
return NULL;
}
StackedBuffer<LightVideoFrame*>* buff;
StackedBuffer<LightVideoFrame*, VideoClipWorkflow>* buff;
if ( mode == ClipWorkflow::Pop )
buff = new StackedBuffer<LightVideoFrame*>( m_computedBuffers.pop(), &m_availableBuffers, true );
{
buff = new StackedBuffer<LightVideoFrame*, VideoClipWorkflow>( m_computedBuffers.dequeue(), this, true );
}
else if ( mode == ClipWorkflow::Get )
buff = new StackedBuffer<LightVideoFrame*>( m_computedBuffers.head(), NULL, false );
buff = new StackedBuffer<LightVideoFrame*, VideoClipWorkflow>( m_computedBuffers.head(), NULL, false );
postGetOutput();
qDebug() << "End of getoutput computation";
return buff;
}
void VideoClipWorkflow::lock( VideoClipWorkflow* cw, void** pp_ret, int size )
{
Q_UNUSED( size );
QMutexLocker lock( cw->m_availableBuffersMutex );
cw->m_renderLock->lock();
cw->m_computedBuffersMutex->lock();
LightVideoFrame* lvf = NULL;
if ( cw->m_availableBuffers.isEmpty() == true )
{
qCritical() << "Late buffer generation. Spawning new video buffer";
// qCritical() << "Late buffer generation. Spawning new video buffer";
lvf = new LightVideoFrame( MainWorkflow::getInstance()->getWidth()
* MainWorkflow::getInstance()->getHeight()
* Pixel::NbComposantes );
}
else
lvf = cw->m_availableBuffers.pop();
cw->m_computedBuffers.push_back( lvf );
qWarning() << ">>>VideoGeneration. Available:" << cw->m_availableBuffers.count() << "Computed:" << cw->m_computedBuffers.count();
lvf = cw->m_availableBuffers.dequeue();
cw->m_computedBuffers.enqueue( lvf );
// qWarning() << ">>>VideoGeneration. Available:" << cw->m_availableBuffers.count() << "Computed:" << cw->m_computedBuffers.count();
// qWarning() << "feeding video buffer";
*pp_ret = (*(lvf))->frame.octets;
}
......@@ -137,14 +135,16 @@ void VideoClipWorkflow::unlock( VideoClipWorkflow* cw, void* buffer, int widt
cw->computePtsDiff( pts );
LightVideoFrame* lvf = cw->m_computedBuffers.last();
(*(lvf))->ptsDiff = cw->m_currentPts - cw->m_previousPts;
// qWarning() << "Computed ptsDiff:" << (*(lvf))->ptsDiff;
// if ( (*(lvf))->ptsDiff > 100000 )
// {
// qWarning() << "Probably invalid pts diff. pts:" << pts << "m_currentPts:" << cw->m_currentPts << "m_previousPts:" << cw->m_previousPts
// << "state:" << cw->m_state;
// }
//If this is the first buffer that has been rendered, there may be a waiting TrackWorkflow.
cw->commonUnlock();
cw->m_renderLock->unlock();
}
uint32_t VideoClipWorkflow::getAvailableBuffers() const
{
return m_availableBuffers.count();
cw->m_computedBuffersMutex->unlock();
}
uint32_t VideoClipWorkflow::getComputedBuffers() const
......@@ -156,3 +156,9 @@ uint32_t VideoClipWorkflow::getMaxComputedBuffers() const
{
return VideoClipWorkflow::nbBuffers;
}
void VideoClipWorkflow::releaseBuffer( LightVideoFrame *lvf )
{
QMutexLocker lock( m_availableBuffersMutex );
m_availableBuffers.enqueue( lvf );
}
......@@ -41,17 +41,16 @@ class VideoClipWorkflow : public ClipWorkflow
protected:
virtual void initVlcOutput();
virtual uint32_t getAvailableBuffers() const;
virtual uint32_t getComputedBuffers() const;
virtual uint32_t getMaxComputedBuffers() const;
void releaseBuffer( LightVideoFrame* lvf );
private:
// Pool<LightVideoFrame*> m_pool;
// QReadWriteLock* m_computedBuffersLock;
Pool<LightVideoFrame*> m_computedBuffers;
// QReadWriteLock* m_availableBuffersLock;
Pool<LightVideoFrame*> m_availableBuffers;
QQueue<LightVideoFrame*> m_computedBuffers;
QQueue<LightVideoFrame*> m_availableBuffers;
static void lock( VideoClipWorkflow* clipWorkflow, void** pp_ret, int size );
static void unlock( VideoClipWorkflow* clipWorkflow, void* buffer, int width, int height, int bpp, int size, qint64 pts );
friend class StackedBuffer<LightVideoFrame*, VideoClipWorkflow>;
};
#endif // VIDEOCLIPWORKFLOW_H
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