Commit 5b1ec1ac authored by Christophe Courtaut's avatar Christophe Courtaut

Stacked MetaData Computing

parent c4df6dd5
......@@ -122,8 +122,7 @@ void ImportModel::loadMedia( Media* media )
{
connect( media, SIGNAL( metaDataComputed( Media* ) ), this, SLOT( metaDataComputed( Media* ) ) );
connect( media, SIGNAL( snapshotComputed(Media*) ), this, SLOT( snapshotComputed(Media*) ) );
m_metaDataWorker = new MetaDataWorker( media );
m_metaDataWorker->compute();
MetaDataManager::getInstance()->computeMediaMetadata( media );
}
bool ImportModel::mediaAlreadyLoaded( const QFileInfo& fileInfo )
......
......@@ -32,7 +32,7 @@
#include "Media.h"
#include "Clip.h"
#include "MetaDataWorker.h"
#include "MetaDataManager.h"
class ImportModel : public QObject
{
......@@ -58,7 +58,6 @@ signals:
private:
QHash<QUuid, Media*>* m_medias;
MetaDataWorker* m_metaDataWorker;
QStringList m_filters;
QList<Media*> m_invalidMedias;
int m_loadingMedias;
......
......@@ -28,6 +28,7 @@
#include <QtDebug>
#include "Media.h"
#include "MetaDataManager.h"
QPixmap* Media::defaultSnapshot = NULL;
const QString Media::VideoExtensions = "*.mov *.avi *.mkv *.mpg *.mpeg *.wmv *.mp4";
......@@ -231,6 +232,7 @@ void Media::emitSnapshotComputed()
if ( m_metadataState == ParsedWithoutSnapshot )
m_metadataState = ParsedWithSnapshot;
emit snapshotComputed( this );
disconnect( this, SIGNAL( snapshotComputed( Media* ) ), MetaDataManager::getInstance(), SLOT( checkMediasToCompute() ) );
}
Media::InputType Media::getInputType() const
......
/*****************************************************************************
* MetaDataWorker.cpp: MetaDataManager
*****************************************************************************
* Copyright (C) 2008-2009 the VLMC team
*
* Authors: Christophe Courtaut <christophe.courtaut@gmail.com>
*
* 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 "MetaDataManager.h"
#include "MetaDataWorker.h"
#include <QMap>
MetaDataManager::MetaDataManager() : m_mediaPlayersMaxCount( DEFAULT_MAX_MEDIA_PLAYER ), m_mediaPlayersToRemove( 0 )
{
for ( int i = 0; i < m_mediaPlayersMaxCount; ++i )
addMediaPlayer();
}
void MetaDataManager::addMediaPlayer()
{
if ( m_mediaPlayers.count() <= m_mediaPlayersMaxCount )
m_mediaPlayers.insert( Idle, new LibVLCpp::MediaPlayer() );
}
void MetaDataManager::removeMediaPlayer()
{
if ( m_mediaPlayers.count() > 0 )
{
QMap<MediaPlayerState, LibVLCpp::MediaPlayer*>::iterator it = m_mediaPlayers.find( Idle );
if ( it != m_mediaPlayers.end() )
{
delete it.value();
m_mediaPlayers.erase( it );
}
else
++m_mediaPlayersToRemove;
}
}
void MetaDataManager::setMediaPlayersNumberMaxCount( int number )
{
if ( number <= 0 )
return;
if ( number <= m_mediaPlayers.count() )
{
for ( int i = m_mediaPlayers.count() - number; i > 0; --i )
removeMediaPlayer();
}
m_mediaPlayersMaxCount = number;
}
void MetaDataManager::populateEmptyMediaPlayerSlots()
{
if ( m_mediaPlayers.count() < m_mediaPlayersMaxCount )
{
for ( int i = m_mediaPlayersMaxCount - m_mediaPlayers.count(); i > 0; --i )
addMediaPlayer();
}
}
int MetaDataManager::mediaPlayersMaxCount() const
{
return m_mediaPlayers.count();
}
void MetaDataManager::computeMediaMetadata( Media *media )
{
m_mediasToComputeMetaData.enqueue( media );
checkMediasToCompute();
}
void MetaDataManager::checkMediasToCompute()
{
QMap<MediaPlayerState, LibVLCpp::MediaPlayer*>::iterator it;
if ( m_mediasToComputeMetaData.count() > 0 &&
( it = m_mediaPlayers.find( Idle ) ) != m_mediaPlayers.end() )
{
Media* media;
LibVLCpp::MediaPlayer* mediaPlayer = it.value();
m_mediaPlayers.erase( it );
m_mediaPlayers.insert( Running, mediaPlayer );
media = m_mediasToComputeMetaData.dequeue();
MetaDataWorker* worker = new MetaDataWorker( mediaPlayer, media, MetaDataWorker::MetaData );
connect( worker, SIGNAL( mediaPlayerIdle( LibVLCpp::MediaPlayer* ) ), this, SLOT( mediaPlayerIdle( LibVLCpp::MediaPlayer* ) ) );
//connect( media, SIGNAL( metaDataComputed( Media* ) ), this, SLOT( checkMediasToCompute() ) );
worker->compute();
m_mediasToComputeSnapshot.enqueue( media );
}
else if ( m_mediasToComputeSnapshot.count() > 0 &&
( it = m_mediaPlayers.find( Idle ) ) != m_mediaPlayers.end() )
{
Media* media;
LibVLCpp::MediaPlayer* mediaPlayer = it.value();
m_mediaPlayers.erase( it );
m_mediaPlayers.insert( Running, mediaPlayer );
media = m_mediasToComputeSnapshot.dequeue();
MetaDataWorker* worker = new MetaDataWorker( mediaPlayer, media, MetaDataWorker::Snapshot );
disconnect( media, SIGNAL( metaDataComputed( Media* ) ), this, SLOT( checkMediasToCompute() ) );
connect( worker, SIGNAL( mediaPlayerIdle( LibVLCpp::MediaPlayer* ) ), this, SLOT( mediaPlayerIdle( LibVLCpp::MediaPlayer* ) ) );
//connect( media, SIGNAL( snapshotComputed( Media* ) ), this, SLOT( checkMediasToCompute() ) );
worker->compute();
}
return;
}
void MetaDataManager::mediaPlayerIdle( LibVLCpp::MediaPlayer* mediaPlayer )
{
m_mediaPlayers.remove( Running, mediaPlayer );
m_mediaPlayers.insert( Idle, mediaPlayer );
checkMediasToCompute();
}
/*****************************************************************************
* MetaDataWorker.h: MetaDataManager
*****************************************************************************
* Copyright (C) 2008-2009 the VLMC team
*
* Authors: Christophe Courtaut <christophe.courtaut@gmail.com>
*
* 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 METADATAMANAGER_H
#define METADATAMANAGER_H
#include <QObject>
#include <QQueue>
#include <QMultiMap>
#include <QThreadPool>
#include "VLCMediaPlayer.h"
#include "Media.h"
#include "Singleton.hpp"
#define DEFAULT_MAX_MEDIA_PLAYER 1
class MetaDataManager : public QObject, public Singleton<MetaDataManager>
{
Q_OBJECT
Q_DISABLE_COPY( MetaDataManager )
enum MediaPlayerState
{
Idle,
Running
};
public:
void computeMediaMetadata( Media* media );
void setMediaPlayersNumberMaxCount( int number );
void addMediaPlayer();
void removeMediaPlayer();
void populateEmptyMediaPlayerSlots();
int mediaPlayersMaxCount() const;
void checkMediasToCompute();
private slots:
void mediaPlayerIdle( LibVLCpp::MediaPlayer* mediaPlayer );
private:
MetaDataManager();
private:
QQueue<Media*> m_mediasToComputeMetaData;
QQueue<Media*> m_mediasToComputeSnapshot;
QMultiMap<MediaPlayerState, LibVLCpp::MediaPlayer*> m_mediaPlayers;
int m_mediaPlayersMaxCount;
int m_mediaPlayersToRemove;
friend class Singleton<MetaDataManager>;
};
#endif //METADATAMANAGER_H
......@@ -26,62 +26,49 @@
#include "MetaDataWorker.h"
#include "Library.h"
QThreadPool* MetaDataWorker::m_metadataThreadPool = NULL;
MetaDataWorker::MetaDataWorker( Media* media ) :
m_validity( true ),
m_currentMedia( media ),
MetaDataWorker::MetaDataWorker( LibVLCpp::MediaPlayer* mediaPlayer, Media* media, MetaDataWorker::MetaDataType type ) :
m_mediaPlayer( mediaPlayer ),
m_type( type ),
m_media( media ),
m_mediaIsPlaying( false),
m_lengthHasChanged( false )
{
if ( m_metadataThreadPool == NULL )
m_metadataThreadPool = new QThreadPool();
m_mediaPlayer = new LibVLCpp::MediaPlayer();
m_metadataThreadPool->setMaxThreadCount( 3 );
}
MetaDataWorker::~MetaDataWorker()
{
if ( m_mediaPlayer->isPlaying() )
m_mediaPlayer->stop();
if (m_mediaPlayer)
delete m_mediaPlayer;
}
void MetaDataWorker::compute()
{
if ( !m_validity )
return ;
if ( m_currentMedia->getFileType() == Media::Video )
if ( m_media->getFileType() == Media::Video )
{
computeVideoMetaData();
}
else if ( m_currentMedia->getFileType() == Media::Image )
else if ( m_media->getFileType() == Media::Image )
{
computeImageMetaData();
}
m_currentMedia->addConstantParam( ":vout=dummy" );
m_mediaPlayer->setMedia( m_currentMedia->getVLCMedia() );
m_media->addConstantParam( ":vout=dummy" );
m_mediaPlayer->setMedia( m_media->getVLCMedia() );
connect( m_mediaPlayer, SIGNAL( playing() ), this, SLOT( entrypointPlaying() ) );
m_mediaPlayer->play();
m_currentMedia->flushVolatileParameters();
m_media->flushVolatileParameters();
}
void MetaDataWorker::computeVideoMetaData()
{
if ( !m_validity )
return ;
//Disabling audio for this specific use of the media
m_currentMedia->addVolatileParam( ":no-audio", ":audio" );
m_media->addVolatileParam( ":no-audio", ":audio" );
connect( m_mediaPlayer, SIGNAL( lengthChanged() ), this, SLOT( entrypointLengthChanged() ) );
}
void MetaDataWorker::computeImageMetaData()
{
if ( !m_validity )
return ;
m_currentMedia->addVolatileParam( ":access=fake", ":access=''" );
m_currentMedia->addVolatileParam( ":fake-duration=10000", ":fake-duration=''" );
m_media->addVolatileParam( ":access=fake", ":access=''" );
m_media->addVolatileParam( ":fake-duration=10000", ":fake-duration=''" );
//There can't be a length for an image file, so we don't have to wait for it to be updated.
m_lengthHasChanged = true;
}
......@@ -91,8 +78,6 @@ void MetaDataWorker::getMetaData()
m_mediaIsPlaying = false;
m_lengthHasChanged = false;
if ( !m_validity )
return ;
//In order to wait for the VOUT to be ready:
//Until we have a way of knowing when it is, both getWidth and getHeight method
//will trigger exception... so we shut it up.
......@@ -103,43 +88,43 @@ void MetaDataWorker::getMetaData()
}
LibVLCpp::Exception::setErrorCallback( NULL );
m_currentMedia->setLength( m_mediaPlayer->getLength() );
if ( m_currentMedia->getLengthMS() == 0 )
m_validity = false;
m_currentMedia->setWidth( m_mediaPlayer->getWidth() );
m_currentMedia->setHeight( m_mediaPlayer->getHeight() );
m_currentMedia->setFps( m_mediaPlayer->getFps() );
if ( m_currentMedia->getFps() == .0f )
if ( m_type == MetaData )
{
qWarning() << "Invalid FPS for media:" << m_currentMedia->getFileInfo()->absoluteFilePath();
m_currentMedia->setFps( FPS );
m_media->setLength( m_mediaPlayer->getLength() );
m_media->setWidth( m_mediaPlayer->getWidth() );
m_media->setHeight( m_mediaPlayer->getHeight() );
m_media->setFps( m_mediaPlayer->getFps() );
if ( m_media->getFps() == .0f )
{
qWarning() << "Invalid FPS for media:" << m_media->getFileInfo()->absoluteFilePath();
m_media->setFps( FPS );
}
m_media->setNbFrames( (m_media->getLengthMS() / 1000) * m_media->getFps() );
m_mediaPlayer->stop();
emit mediaPlayerIdle( m_mediaPlayer );
m_media->emitMetaDataComputed( true );
delete this;
return;
}
m_currentMedia->setNbFrames( (m_currentMedia->getLengthMS() / 1000) * m_currentMedia->getFps() );
m_currentMedia->emitMetaDataComputed( m_validity );
//Setting time for snapshot :
if ( m_currentMedia->getFileType() == Media::Video )
else if ( m_type == Snapshot )
{
connect( m_mediaPlayer, SIGNAL( positionChanged() ), this, SLOT( renderSnapshot() ) );
m_mediaPlayer->setTime( m_mediaPlayer->getLength() / 3 );
//Setting time for snapshot :
if ( m_media->getFileType() == Media::Video )
{
connect( m_mediaPlayer, SIGNAL( positionChanged() ), this, SLOT( renderSnapshot() ) );
m_mediaPlayer->setTime( m_mediaPlayer->getLength() / 3 );
}
else
connect( this, SIGNAL( snapshotRequested() ), this, SLOT( renderSnapshot() ) );
}
else
connect( this, SIGNAL( snapshotRequested() ), this, SLOT( renderSnapshot() ) );
}
void MetaDataWorker::renderSnapshot()
{
if ( m_currentMedia->getFileType() == Media::Video )
if ( m_media->getFileType() == Media::Video )
disconnect( m_mediaPlayer, SIGNAL( positionChanged() ), this, SLOT( renderSnapshot() ) );
else
disconnect( this, SIGNAL( snapshotRequested() ), this, SLOT( renderSnapshot() ) );
if ( !m_validity )
return ;
m_metadataThreadPool->start( new SnapshotHelper( this ) );
}
void MetaDataWorker::renderSnapshotAsync()
{
QTemporaryFile tmp;
tmp.setAutoRemove( false );
tmp.open();
......@@ -159,18 +144,18 @@ void MetaDataWorker::setSnapshot()
if ( pixmap->isNull() )
delete pixmap;
else
m_currentMedia->setSnapshot( pixmap );
m_media->setSnapshot( pixmap );
//TODO : we shouldn't have to do this... patch vlc to get a memory snapshot.
QFile tmp( m_tmpSnapshotFilename );
tmp.remove();
disconnect( m_mediaPlayer, SIGNAL( snapshotTaken() ), this, SLOT( setSnapshot() ) );
m_currentMedia->emitSnapshotComputed();
//CHECKME:
//This is synchrone, but it may become asynchrone in the future...
m_mediaPlayer->stop();
emit mediaPlayerIdle( m_mediaPlayer );
m_media->emitSnapshotComputed();
//startAudioDataParsing();
delete this;
}
......@@ -187,17 +172,17 @@ void MetaDataWorker::startAudioDataParsing()
sprintf( csb, ":amem-closesb=%lld", (long long int)(intptr_t) &MetaDataWorker::closeSoundBuffer);
sprintf( iph, ":amem-iph=%lld", (long long int)(intptr_t) &MetaDataWorker::instanceParameterHandler);
sprintf( data, ":amem-data=%lld", (long long int)(intptr_t) this);
m_currentMedia->addVolatileParam( ":no-video", ":video" );
m_currentMedia->addConstantParam( ":audio" );
m_currentMedia->addVolatileParam( ":aout=amem", ":aout=''" ); //I'm really not sure about this one...
m_currentMedia->addConstantParam( osb );
m_currentMedia->addConstantParam( psb );
m_currentMedia->addConstantParam( csb );
m_currentMedia->addConstantParam( iph );
m_currentMedia->addConstantParam( data );
m_mediaPlayer->setMedia( m_currentMedia->getVLCMedia() );
m_currentMedia->flushVolatileParameters();
m_media->addVolatileParam( ":no-video", ":video" );
m_media->addConstantParam( ":audio" );
m_media->addVolatileParam( ":aout=amem", ":aout=''" ); //I'm really not sure about this one...
m_media->addConstantParam( osb );
m_media->addConstantParam( psb );
m_media->addConstantParam( csb );
m_media->addConstantParam( iph );
m_media->addConstantParam( data );
m_mediaPlayer->setMedia( m_media->getVLCMedia() );
m_media->flushVolatileParameters();
connect( m_mediaPlayer, SIGNAL( endReached() ), this, SLOT( stopAudioDataParsing() ) );
qDebug() << "Starting playback again";
m_mediaPlayer->play();
......@@ -213,7 +198,7 @@ void MetaDataWorker::openSoundBuffer( void* datas, unsigned int* freq, unsign
{
//qDebug() << "Opening sound buffer with freq =" << *freq << "nbChannels =" << *nbChannels << "frameSize =" << *frameSize;
MetaDataWorker* self = reinterpret_cast<MetaDataWorker*>( datas );
self->m_currentMedia->initAudioData( datas, freq, nbChannels, fourCCFormat, frameSize );
self->m_media->initAudioData( datas, freq, nbChannels, fourCCFormat, frameSize );
}
void MetaDataWorker::playSoundBuffer( void* datas, unsigned char* buffer, size_t buffSize, unsigned int nbSample )
......@@ -222,7 +207,7 @@ void MetaDataWorker::playSoundBuffer( void* datas, unsigned char* buffer, siz
// qDebug() << "Buff[0] = " << (unsigned int)buffer[0];
//if (MetaDataWorker::getInstance()->getCurrentMedia()->getAudioData()->frameList.size() < 500 )
MetaDataWorker* self = reinterpret_cast<MetaDataWorker*>( datas );
self->m_currentMedia->addAudioFrame( datas, buffer, buffSize, nbSample );
self->m_media->addAudioFrame( datas, buffer, buffSize, nbSample );
//else
// MetaDataWorker::getInstance()->getMediaPlayer()->stop();
}
......@@ -254,13 +239,3 @@ void MetaDataWorker::entrypointPlaying()
if ( m_lengthHasChanged == true )
getMetaData();
}
void MetaDataWorker::setMediaValidity( bool validity )
{
m_validity = validity;
}
void SnapshotHelper::run()
{
m_worker->renderSnapshotAsync();
}
......@@ -38,10 +38,16 @@ class MetaDataWorker : public QObject
Q_DISABLE_COPY( MetaDataWorker )
public:
MetaDataWorker( Media* media );
enum MetaDataType
{
MetaData,
Snapshot
};
public:
MetaDataWorker( LibVLCpp::MediaPlayer* mediaPlayer, Media* media, MetaDataType type );
~MetaDataWorker();
void compute();
void setMediaValidity( bool validity );
private:
void computeVideoMetaData();
......@@ -58,22 +64,21 @@ class MetaDataWorker : public QObject
private:
void getMetaData();
void renderSnapshotAsync();
private:
LibVLCpp::MediaPlayer* m_mediaPlayer;
bool m_validity;
MetaDataType m_type;
Media* m_currentMedia;
Media* m_media;
QString m_tmpSnapshotFilename;
bool m_mediaIsPlaying;
bool m_lengthHasChanged;
static QThreadPool* m_metadataThreadPool;
friend class SnapshotHelper;
signals:
void snapshotRequested();
void mediaPlayerIdle( LibVLCpp::MediaPlayer* mediaPlayer );
private slots:
void renderSnapshot();
......@@ -84,13 +89,4 @@ class MetaDataWorker : public QObject
void entrypointLengthChanged();
};
class SnapshotHelper : public QRunnable
{
public:
SnapshotHelper( MetaDataWorker* worker ) : m_worker( worker ) { }
virtual void run();
private:
MetaDataWorker* m_worker;
};
#endif // METADATAWORKER_H
......@@ -34,6 +34,7 @@ SOURCES += src/main.cpp \
src/Media/Clip.cpp \
src/GUI/About.cpp \
src/Metadata/MetaDataWorker.cpp \
src/Metadata/MetaDataManager.cpp \
src/Library/Library.cpp \
src/GUI/GraphicsMovieItem.cpp \
src/GUI/GraphicsAudioItem.cpp \
......@@ -108,6 +109,7 @@ HEADERS += src/GUI/MainWindow.h \
src/GUI/MediaListWidget.h \
src/GUI/About.h \
src/Metadata/MetaDataWorker.h \
src/Metadata/MetaDataManager.h \
src/Tools/Singleton.hpp \
src/Library/Library.h \
src/GUI/AbstractGraphicsMediaItem.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