Commit b7f8dbae authored by luyikei's avatar luyikei Committed by Hugo Beauzée-Luyssen

Remove Image/Auido/VideoClipWorkflow

Signed-off-by: 's avatarHugo Beauzée-Luyssen <hugo@beauzee.fr>
parent 285af18a
/*****************************************************************************
* AudioClipWorkflow.cpp : Clip workflow. Will extract audio samples using ISourceRenderer
*****************************************************************************
* Copyright (C) 2008-2016 VideoLAN
*
* Authors: Hugo Beauzée-Luyssen <hugo@beauzee.fr>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#include "AudioClipWorkflow.h"
#include "Tools/VlmcDebug.h"
#include "Backend/ISourceRenderer.h"
#include "Workflow/Types.h"
#include <QMutexLocker>
#include <QStringBuilder>
AudioClipWorkflow::AudioClipWorkflow( ClipHelper *ch ) :
ClipWorkflow( ch ),
m_lastReturnedBuffer( nullptr )
{
m_ptsOffset = 0;
}
void
AudioClipWorkflow::preallocate()
{
for ( quint32 i = 0; i < AudioClipWorkflow::nbBuffers; ++i )
{
Workflow::AudioSample *as = new Workflow::AudioSample;
m_availableBuffers.push_back( as );
}
}
void
AudioClipWorkflow::releasePrealocated()
{
while ( m_availableBuffers.isEmpty() == false )
{
Workflow::AudioSample *as = m_availableBuffers.takeFirst();
delete[] as->buff;
delete as;
}
while ( m_computedBuffers.isEmpty() == false )
{
Workflow::AudioSample *as = m_computedBuffers.takeFirst();
delete[] as->buff;
delete as;
}
}
Workflow::OutputBuffer*
AudioClipWorkflow::getOutput( ClipWorkflow::GetMode mode, qint64 )
{
QMutexLocker lock( m_renderLock );
if ( m_lastReturnedBuffer != nullptr )
{
m_availableBuffers.enqueue( m_lastReturnedBuffer );
m_lastReturnedBuffer = nullptr;
}
if ( getNbComputedBuffers() == 0 )
return nullptr;
if ( shouldRender() == false )
return nullptr;
if ( mode == ClipWorkflow::Get )
vlmcCritical() << "A sound buffer should never be asked with 'Get' mode";
Workflow::AudioSample *buff = m_computedBuffers.dequeue();
if ( m_previousPts == -1 )
{
buff->ptsDiff = 0;
m_previousPts = buff->pts;
}
else
{
buff->ptsDiff = buff->pts - m_previousPts;
m_previousPts = buff->pts;
}
postGetOutput();
m_lastReturnedBuffer = buff;
return buff;
}
Workflow::TrackType
AudioClipWorkflow::type() const
{
return Workflow::AudioTrack;
}
void AudioClipWorkflow::initializeInternals()
{
m_renderer->setName( qPrintable( QString("AudioClipWorkflow " % m_clipHelper->uuid().toString() ) ) );
m_renderer->setOutputAudioCodec( "f32l" );
m_renderer->setOutputAudioNumberChannels( 2 );
m_renderer->setOutputAudioSampleRate( 48000 );
m_renderer->enableAudioOutputToMemory( this, &lock, &unlock, m_fullSpeedRender );
}
Workflow::AudioSample*
AudioClipWorkflow::createBuffer( size_t size )
{
Workflow::AudioSample *as = new Workflow::AudioSample;
as->buff = new uchar[size];
as->size = size;
return as;
}
void
AudioClipWorkflow::lock( void *data, quint8 **pcm_buffer, size_t size )
{
AudioClipWorkflow* cw = reinterpret_cast<AudioClipWorkflow*>( data );
cw->m_renderLock->lock();
Workflow::AudioSample *as = nullptr;
if ( cw->m_availableBuffers.isEmpty() == true )
as = cw->createBuffer( size );
else
{
as = cw->m_availableBuffers.dequeue();
if ( as->size < size )
{
delete[] as->buff;
as->buff = nullptr;
}
if ( as->buff == nullptr )
{
as->buff = new uchar[size];
as->size = size;
}
}
cw->m_computedBuffers.enqueue( as );
*pcm_buffer = as->buff;
}
void
AudioClipWorkflow::unlock( void* data, uint8_t *pcm_buffer, unsigned int channels,
unsigned int rate, unsigned int nb_samples, unsigned int bits_per_sample,
size_t size, int64_t pts )
{
Q_UNUSED( pcm_buffer );
Q_UNUSED( rate );
Q_UNUSED( bits_per_sample );
Q_UNUSED( size );
AudioClipWorkflow* cw = reinterpret_cast<AudioClipWorkflow*>( data );
pts -= cw->m_ptsOffset;
Workflow::AudioSample* as = cw->m_computedBuffers.last();
if ( as->buff != nullptr )
{
as->nbSample = nb_samples;
as->nbChannels = channels;
as->ptsDiff = 0;
as->pts = pts;
if ( cw->m_pauseDuration != -1 )
{
cw->m_ptsOffset += cw->m_pauseDuration;
cw->m_pauseDuration = -1;
}
if ( cw->m_currentPts > pts )
{
cw->m_computedBuffers.removeLast();
cw->insertPastBlock( as );
}
else
cw->m_currentPts = pts;
}
if ( cw->getMaxComputedBuffers() <= cw->getNbComputedBuffers() )
emit cw->bufferReachedMax();
cw->m_renderLock->unlock();
}
void
AudioClipWorkflow::insertPastBlock( Workflow::AudioSample *as )
{
QQueue<Workflow::AudioSample*>::iterator it = m_computedBuffers.begin();
QQueue<Workflow::AudioSample*>::iterator end = m_computedBuffers.end();
while ( it != end )
{
if ( (*it)->pts > as->pts )
{
m_computedBuffers.insert( it, as );
return ;
}
++it;
}
//Fail safe: reinsert the block at the end.
m_computedBuffers.push_back( as );
}
quint32
AudioClipWorkflow::getNbComputedBuffers() const
{
return m_computedBuffers.count();
}
quint32
AudioClipWorkflow::getMaxComputedBuffers() const
{
return AudioClipWorkflow::nbBuffers;
}
void
AudioClipWorkflow::flushComputedBuffers()
{
QMutexLocker lock( m_renderLock );
while ( m_computedBuffers.isEmpty() == false )
{
m_availableBuffers.enqueue( m_computedBuffers.dequeue() );
}
}
/*****************************************************************************
* AudioClipWorkflow.h : Clip workflow. Will extract a single frame from a VLCMedia
*****************************************************************************
* Copyright (C) 2008-2016 VideoLAN
*
* Authors: Hugo Beauzée-Luyssen <hugo@beauzee.fr>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#ifndef AUDIOCLIPWORKFLOW_H
#define AUDIOCLIPWORKFLOW_H
#include "ClipWorkflow.h"
#include <QPointer>
#include <QQueue>
namespace Workflow
{
class AudioSample;
}
class AudioClipWorkflow : public ClipWorkflow
{
Q_OBJECT
public:
AudioClipWorkflow( ClipHelper* ch );
virtual Workflow::OutputBuffer *getOutput( ClipWorkflow::GetMode mode, qint64 currentFrame );
virtual Workflow::TrackType type() const;
protected:
virtual quint32 getNbComputedBuffers() const;
virtual quint32 getMaxComputedBuffers() const;
virtual void flushComputedBuffers();
virtual void preallocate();
virtual void releasePrealocated();
private:
virtual void initializeInternals();
Workflow::AudioSample* createBuffer( size_t size );
void insertPastBlock( Workflow::AudioSample* as );
static void lock(void *data,
quint8** pcm_buffer , size_t size );
static void unlock(void *data,
uint8_t * pcm_buffer, unsigned int channels,
unsigned int rate, unsigned int nb_samples,
unsigned int bits_per_sample,
size_t size, int64_t pts );
private:
QQueue<Workflow::AudioSample*> m_computedBuffers;
QQueue<Workflow::AudioSample*> m_availableBuffers;
qint64 m_ptsOffset;
Workflow::AudioSample *m_lastReturnedBuffer;
static const quint32 nbBuffers = 256;
};
#endif // AUDIOCLIPWORKFLOW_H
/*****************************************************************************
* ImageClipWorkflow.cpp : Will extract a frame from an image
*****************************************************************************
* Copyright (C) 2008-2016 VideoLAN
*
* Authors: Hugo Beauzée-Luyssen <hugo@beauzee.fr>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#include <QMutex>
#include <QReadWriteLock>
#include <QStringBuilder>
#include "Project/Project.h"
#include "ImageClipWorkflow.h"
#include "Media/Clip.h"
#include "ClipHelper.h"
#include "Backend/ISource.h"
#include "Backend/ISourceRenderer.h"
#include "MainWorkflow.h"
#include "Media/Media.h"
#include "Settings/Settings.h"
#include "Workflow/Types.h"
ImageClipWorkflow::ImageClipWorkflow( ClipHelper *ch ) :
ClipWorkflow( ch ),
m_buffer( nullptr )
{
//This is used to queue the media player stopping, as it can't be asked for
//from vlc's input thread (well it can but it will deadlock)
connect( this, SIGNAL( computedFinished() ),
this, SLOT( stopComputation() ), Qt::QueuedConnection );
m_effectFrame = new Workflow::Frame;
}
ImageClipWorkflow::~ImageClipWorkflow()
{
stop();
delete m_effectFrame;
}
void ImageClipWorkflow::initializeInternals()
{
m_renderer->setName( qPrintable( QString("ImageClipWorkflow " % m_clipHelper->uuid().toString() ) ) );
m_renderer->enableVideoOutputToMemory( this, &lock, &unlock, m_fullSpeedRender );
m_renderer->setOutputWidth( m_width );
m_renderer->setOutputHeight( m_height );
m_renderer->setOutputFps( Core::instance()->project()->fps() );
m_renderer->setOutputVideoCodec( "RV32" );
m_effectFrame->resize( Core::instance()->workflow()->getWidth(),
Core::instance()->workflow()->getHeight() );
m_isRendering = true;
}
void
ImageClipWorkflow::preallocate()
{
}
Workflow::OutputBuffer*
ImageClipWorkflow::getOutput( ClipWorkflow::GetMode, qint64 currentFrame )
{
QMutexLocker lock( m_renderLock );
quint32 *buff = applyFilters( m_buffer, currentFrame );
if ( buff != nullptr )
{
m_effectFrame->setBuffer( buff );
return m_effectFrame;
}
return m_buffer;
}
Workflow::TrackType
ImageClipWorkflow::type() const
{
return Workflow::VideoTrack;
}
void
ImageClipWorkflow::lock(void *data, uint8_t **pp_ret, size_t )
{
ImageClipWorkflow* cw = reinterpret_cast<ImageClipWorkflow*>( data );
cw->m_renderLock->lock();
if ( cw->m_buffer == nullptr )
{
cw->m_buffer = new Workflow::Frame( Core::instance()->workflow()->getWidth(),
Core::instance()->workflow()->getHeight() );
}
*pp_ret = (uint8_t*)cw->m_buffer->buffer();
}
void
ImageClipWorkflow::unlock( void* data, uint8_t*, int, int, int, size_t, int64_t )
{
ImageClipWorkflow* cw = reinterpret_cast<ImageClipWorkflow*>( data );
cw->m_renderLock->unlock();
cw->emit computedFinished();
}
quint32
ImageClipWorkflow::getNbComputedBuffers() const
{
QMutexLocker lock( m_renderLock );
if ( m_buffer != nullptr )
return 1;
return 0;
}
quint32
ImageClipWorkflow::getMaxComputedBuffers() const
{
return 1;
}
void
ImageClipWorkflow::stopComputation()
{
m_renderer->stop();
}
void
ImageClipWorkflow::flushComputedBuffers()
{
}
/*****************************************************************************
* ImageClipWorkflow.h : Will extract a frame from an image
*****************************************************************************
* Copyright (C) 2008-2016 VideoLAN
*
* Authors: Hugo Beauzée-Luyssen <hugo@beauzee.fr>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#ifndef IMAGECLIPWORKFLOW_H
#define IMAGECLIPWORKFLOW_H
#include "ClipWorkflow.h"
class ImageClipWorkflow : public ClipWorkflow
{
Q_OBJECT
public:
ImageClipWorkflow( ClipHelper* ch );
~ImageClipWorkflow();
virtual Workflow::OutputBuffer *getOutput( ClipWorkflow::GetMode mode, qint64 currentFrame );
virtual Workflow::TrackType type() const;
/**
* \brief Deactivate time seeking in an ImageClipWorkflow
*/
virtual void setTime( qint64 ){}
protected:
virtual void initializeInternals();
virtual void preallocate();
virtual quint32 getNbComputedBuffers() const;
virtual quint32 getMaxComputedBuffers() const;
virtual void flushComputedBuffers();
virtual void releasePrealocated(){}
private:
static void lock(void *data, uint8_t **pp_ret,
size_t size );
static void unlock(void *data, uint8_t *buffer,
int width, int height, int bpp, size_t size,
int64_t pts );
private:
Workflow::Frame *m_buffer;
EffectsEngine::EffectList m_filters;
Workflow::Frame *m_effectFrame;
private slots:
void stopComputation();
signals:
void computedFinished();
};
#endif // IMAGECLIPWORKFLOW_H
/*****************************************************************************
* VideoClipWorkflow.cpp : Clip workflow. Will extract a single frame from a VLCMedia
*****************************************************************************
* Copyright (C) 2008-2016 VideoLAN
*
* Authors: Hugo Beauzée-Luyssen <hugo@beauzee.fr>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#include "Media/Clip.h"
#include "EffectsEngine/EffectInstance.h"
#include "Project/Project.h"
#include "MainWorkflow.h"
#include "Media/Media.h"
#include "Backend/ISource.h"
#include "Backend/ISourceRenderer.h"
#include "Settings/Settings.h"
#include "VideoClipWorkflow.h"
#include "Tools/VlmcDebug.h"
#include "Workflow/Types.h"
#include <QMutexLocker>
#include <QReadWriteLock>
#include <QStringBuilder>
#include <QWaitCondition>
VideoClipWorkflow::VideoClipWorkflow( ClipHelper *ch ) :
ClipWorkflow( ch ),
m_lastReturnedBuffer( nullptr )
{
}
void
VideoClipWorkflow::releasePrealocated()
{
while ( m_availableBuffers.isEmpty() == false )
delete m_availableBuffers.dequeue();
while ( m_computedBuffers.isEmpty() == false )
delete m_computedBuffers.dequeue();
}
void
VideoClipWorkflow::preallocate()
{
quint32 newWidth = Core::instance()->workflow()->getWidth();
quint32 newHeight = Core::instance()->workflow()->getHeight();
if ( newWidth != m_width || newHeight != m_height )
{
m_width = newWidth;
m_height = newHeight;
while ( m_availableBuffers.isEmpty() == false )
delete m_availableBuffers.dequeue();
for ( unsigned int i = 0; i < VideoClipWorkflow::nbBuffers; ++i )
{
m_availableBuffers.enqueue( new Workflow::Frame( newWidth, newHeight ) );
}
}
}
void
VideoClipWorkflow::initializeInternals()
{
initFilters();
m_renderer->setName( qPrintable( QString("VideoClipWorkflow " % m_clipHelper->uuid().toString() ) ) );
m_renderer->enableVideoOutputToMemory( this, &lock, &unlock, m_fullSpeedRender );
m_renderer->setOutputWidth( m_width );
m_renderer->setOutputHeight( m_height );
m_renderer->setOutputFps( Core::instance()->project()->fps() );
m_renderer->setOutputVideoCodec( "RV32" );
}
Workflow::OutputBuffer*
VideoClipWorkflow::getOutput( ClipWorkflow::GetMode mode, qint64 currentFrame )
{
QMutexLocker lock( m_renderLock );
if ( m_lastReturnedBuffer != nullptr )
{
m_availableBuffers.enqueue( m_lastReturnedBuffer );
m_lastReturnedBuffer = nullptr;
}
if ( shouldRender() == false )
return nullptr;
if ( getNbComputedBuffers() == 0 )
{
if ( m_renderWaitCond->wait( m_renderLock, 100 ) == false )
{
vlmcWarning() << "Clip workflow" << m_clipHelper->uuid() << "Timed out while waiting for a frame";
return nullptr;
}
if ( shouldRender() == false )
return nullptr;
}
Workflow::Frame *buff = nullptr;
if ( mode == ClipWorkflow::Pop )
{
buff = m_computedBuffers.dequeue();
m_lastReturnedBuffer = buff;
}
else
buff = m_computedBuffers.head();
quint32 *newFrame = applyFilters( buff, currentFrame );
if ( newFrame != nullptr )
buff->setBuffer( newFrame );
postGetOutput();
return buff;
}
Workflow::TrackType
VideoClipWorkflow::type() const
{
return Workflow::VideoTrack;
}
void
VideoClipWorkflow::lock( void *data, uint8_t** p_buffer, size_t size )
{
VideoClipWorkflow* cw = reinterpret_cast<VideoClipWorkflow*>( data );
//Mind the fact that frame size in bytes might not be width * height * bpp
Workflow::Frame* frame = nullptr;
cw->m_renderLock->lock();
if ( cw->m_availableBuffers.isEmpty() == true )
{
if ( Workflow::Frame::Size( cw->m_width, cw->m_height ) == size )
frame = new Workflow::Frame( cw->m_width, cw->m_height );
else
frame = new Workflow::Frame( cw->m_width, cw->m_height, size );
}
else
{
frame = cw->m_availableBuffers.dequeue();
if ( frame->size() != size )
frame->resize( size );
}
cw->m_computedBuffers.enqueue( frame );
*p_buffer = (uint8_t*)frame->buffer();
}
void
VideoClipWorkflow::unlock( void *data, uint8_t *buffer, int width,
int height, int bpp, size_t size, int64_t pts )
{
Q_UNUSED( buffer );
Q_UNUSED( width );
Q_UNUSED( height );
Q_UNUSED( bpp );
Q_UNUSED( size );
VideoClipWorkflow* cw = reinterpret_cast<VideoClipWorkflow*>( data );
cw->computePtsDiff( pts );
Workflow::Frame *frame = cw->m_computedBuffers.last();
frame->ptsDiff = cw->m_currentPts - cw->m_previousPts;
cw->m_renderWaitCond->wakeAll();
if ( cw->getMaxComputedBuffers() <= cw->getNbComputedBuffers() )
emit cw->bufferReachedMax();
cw->m_renderLock->unlock();
}
quint32
VideoClipWorkflow::getNbComputedBuffers() const
{
return m_computedBuffers.count();
}
quint32
VideoClipWorkflow::getMaxComputedBuffers() const
{
return VideoClipWorkflow::nbBuffers;
}
void
VideoClipWorkflow::flushComputedBuffers()
{
QMutexLocker lock( m_renderLock );
while ( m_computedBuffers.isEmpty() == false )
m_availableBuffers.enqueue( m_computedBuffers.dequeue() );
}
/*****************************************************************************
* VideoClipWorkflow.h : Clip workflow. Will extract a single frame from a VLCMedia
*****************************************************************************
* Copyright (C) 2008-2016 VideoLAN
*
* Authors: Hugo Beauzée-Luyssen <hugo@beauzee.fr>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#ifndef VIDEOCLIPWORKFLOW_H
#define VIDEOCLIPWORKFLOW_H
#include "ClipWorkflow.h"
#include "EffectsEngine/EffectsEngine.h"
#include <QQueue>
<