MetaDataWorker.cpp 9.56 KB
Newer Older
Christophe Courtaut's avatar
Christophe Courtaut committed
1
/*****************************************************************************
2
 * MetaDataWorker.cpp: Implement the thread that will get the media informations
Christophe Courtaut's avatar
Christophe Courtaut committed
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
 *****************************************************************************
 * Copyright (C) 2008-2009 the VLMC team
 *
 * Authors: Hugo Beauzee-Luyssen <hugo@vlmc.org>
 *
 * 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.
 *****************************************************************************/
22

Hugo Beauzee-Luyssen's avatar
Hugo Beauzee-Luyssen committed
23
#include <QtDebug>
24 25

#include "vlmc.h"
26
#include "MetaDataWorker.h"
Hugo Beauzee-Luyssen's avatar
Hugo Beauzee-Luyssen committed
27 28
#include "Library.h"

29 30
QThreadPool*    MetaDataWorker::m_metadataThreadPool = NULL;

31
MetaDataWorker::MetaDataWorker( Media* media ) :
32
        m_validity( true ),
33 34
        m_currentMedia( media ),
        m_mediaIsPlaying( false),
Hugo Beauzee-Luyssen's avatar
Hugo Beauzee-Luyssen committed
35
        m_lengthHasChanged( false )
36
{
37 38
    if ( m_metadataThreadPool == NULL )
        m_metadataThreadPool = new QThreadPool();
39
    m_mediaPlayer = new LibVLCpp::MediaPlayer();
40
    m_metadataThreadPool->setMaxThreadCount( 3 );
41 42
}

43
MetaDataWorker::~MetaDataWorker()
44
{
45 46
    if ( m_mediaPlayer->isPlaying() )
        m_mediaPlayer->stop();
47 48 49 50
    if (m_mediaPlayer)
        delete m_mediaPlayer;
}

51
void    MetaDataWorker::compute()
52
{
53 54
    if ( !m_validity )
        return ;
55
    if ( m_currentMedia->getFileType() == Media::Video )
56
    {
57
        computeVideoMetaData();
58
    }
59 60 61 62
    else if ( m_currentMedia->getFileType() == Media::Image )
    {
        computeImageMetaData();
    }
63
    m_currentMedia->addConstantParam( ":vout=dummy" );
64 65 66 67
    m_mediaPlayer->setMedia( m_currentMedia->getVLCMedia() );
    connect( m_mediaPlayer, SIGNAL( playing() ), this, SLOT( entrypointPlaying() ) );
    m_mediaPlayer->play();
    m_currentMedia->flushVolatileParameters();
68 69
}

70
void    MetaDataWorker::computeVideoMetaData()
71
{
72 73
    if ( !m_validity )
        return ;
74
    //Disabling audio for this specific use of the media
75
    m_currentMedia->addVolatileParam( ":no-audio", ":audio" );
76
    connect( m_mediaPlayer, SIGNAL( lengthChanged() ), this, SLOT( entrypointLengthChanged() ) );
77 78
}

79
void    MetaDataWorker::computeImageMetaData()
80
{
81 82
    if ( !m_validity )
        return ;
83 84
    m_currentMedia->addVolatileParam( ":access=fake", ":access=''" );
    m_currentMedia->addVolatileParam( ":fake-duration=10000", ":fake-duration=''" );
85 86
    //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;
87 88
}

89
void    MetaDataWorker::getMetaData()
90
{
91
    m_mediaIsPlaying = false;
Hugo Beauzee-Luyssen's avatar
Hugo Beauzee-Luyssen committed
92
    m_lengthHasChanged = false;
93

94 95
    if ( !m_validity )
        return ;
96
    //In order to wait for the VOUT to be ready:
97 98 99
    //Until we have a way of knowing when it is, both getWidth and getHeight method
    //will trigger exception... so we shut it up.
    LibVLCpp::Exception::setErrorCallback( LibVLCpp::Exception::silentExceptionHandler );
100
    while ( m_mediaPlayer->hasVout() == false )
101
    {
102
        SleepMS( 1 ); //Ugly isn't it :)
103
    }
104 105
    LibVLCpp::Exception::setErrorCallback( NULL );

106
    m_currentMedia->setLength( m_mediaPlayer->getLength() );
107 108
    if ( m_currentMedia->getLengthMS() == 0 )
        m_validity = false;
109 110
    m_currentMedia->setWidth( m_mediaPlayer->getWidth() );
    m_currentMedia->setHeight( m_mediaPlayer->getHeight() );
111
    m_currentMedia->setFps( m_mediaPlayer->getFps() );
112 113 114 115 116
    if ( m_currentMedia->getFps() == .0f )
    {
        qWarning() << "Invalid FPS for media:" << m_currentMedia->getFileInfo()->absoluteFilePath();
        m_currentMedia->setFps( FPS );
    }
117
    m_currentMedia->setNbFrames( (m_currentMedia->getLengthMS() / 1000) * m_currentMedia->getFps() );
118

119
    m_currentMedia->emitMetaDataComputed( m_validity );
120
    //Setting time for snapshot :
121
    if ( m_currentMedia->getFileType() == Media::Video )
122 123 124 125 126
    {
        connect( m_mediaPlayer, SIGNAL( positionChanged() ), this, SLOT( renderSnapshot() ) );
        m_mediaPlayer->setTime( m_mediaPlayer->getLength() / 3 );
    }
    else
127
        connect( this, SIGNAL( snapshotRequested() ), this, SLOT( renderSnapshot() ) );
128
}
129

130
void    MetaDataWorker::renderSnapshot()
131
{
132
    if ( m_currentMedia->getFileType() == Media::Video )
133
        disconnect( m_mediaPlayer, SIGNAL( positionChanged() ), this, SLOT( renderSnapshot() ) );
134 135
    else
        disconnect( this, SIGNAL( snapshotRequested() ), this, SLOT( renderSnapshot() ) );
136 137
    if ( !m_validity )
        return ;
138 139 140 141 142
    m_metadataThreadPool->start( new SnapshotHelper( this ) );
}

void    MetaDataWorker::renderSnapshotAsync()
{
143 144 145
    QTemporaryFile tmp;
    tmp.setAutoRemove( false );
    tmp.open();
146
    m_tmpSnapshotFilename = tmp.fileName();
147

148
    connect( m_mediaPlayer, SIGNAL( snapshotTaken() ), this, SLOT( setSnapshot() ), Qt::QueuedConnection );
149 150

    //The slot should be triggered in this methode
151
    m_mediaPlayer->takeSnapshot( m_tmpSnapshotFilename.toStdString().c_str()
152
                                 , 0, 0 );
153 154 155
    //Snapshot slot should has been called (but maybe not in next version...)
}

156
void    MetaDataWorker::setSnapshot()
157
{
158 159 160 161
    QPixmap* pixmap = new QPixmap( m_tmpSnapshotFilename );
    if ( pixmap->isNull() )
        delete pixmap;
    else
162
        m_currentMedia->setSnapshot( pixmap );
163 164 165 166
    //TODO : we shouldn't have to do this... patch vlc to get a memory snapshot.
    QFile   tmp( m_tmpSnapshotFilename );
    tmp.remove();

167 168
    disconnect( m_mediaPlayer, SIGNAL( snapshotTaken() ), this, SLOT( setSnapshot() ) );

169
    m_currentMedia->emitSnapshotComputed();
170

171 172
    //CHECKME:
    //This is synchrone, but it may become asynchrone in the future...
173
    m_mediaPlayer->stop();
174
    //startAudioDataParsing();
175
    delete this;
176
}
177

178
void    MetaDataWorker::startAudioDataParsing()
179
{
180 181 182
    qDebug() << "Starting audio parsing";
    char    osb[64], psb[64], csb[64], iph[64], data[64];

183
//    disconnect( m_mediaPlayer, SIGNAL( stopped() ), this, SLOT( startAudioDataParsing() ) );
184

185 186 187 188
    sprintf( osb, ":amem-opensb=%lld", (long long int)(intptr_t) &MetaDataWorker::openSoundBuffer);
    sprintf( psb, ":amem-playsb=%lld", (long long int)(intptr_t) &MetaDataWorker::playSoundBuffer);
    sprintf( csb, ":amem-closesb=%lld", (long long int)(intptr_t) &MetaDataWorker::closeSoundBuffer);
    sprintf( iph, ":amem-iph=%lld", (long long int)(intptr_t) &MetaDataWorker::instanceParameterHandler);
189
    sprintf( data, ":amem-data=%lld", (long long int)(intptr_t) this);
190 191 192 193 194 195 196 197 198 199 200
    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();
201
    connect( m_mediaPlayer, SIGNAL( endReached() ), this, SLOT( stopAudioDataParsing() ) );
202
    qDebug() << "Starting playback again";
203
    m_mediaPlayer->play();
204 205
}

206
void    MetaDataWorker::stopAudioDataParsing()
207
{
208 209
    qDebug() << "Stopping AudioDataParsing";
    m_mediaPlayer->stop();
210 211
}

212
void    MetaDataWorker::openSoundBuffer( void* datas, unsigned int* freq, unsigned int* nbChannels, unsigned int* fourCCFormat, unsigned int* frameSize )
213 214
{
    //qDebug() << "Opening sound buffer with freq =" << *freq << "nbChannels =" << *nbChannels << "frameSize =" << *frameSize;
215 216
    MetaDataWorker* self = reinterpret_cast<MetaDataWorker*>( datas );
    self->m_currentMedia->initAudioData( datas, freq, nbChannels, fourCCFormat, frameSize );
217 218
 }

219
void    MetaDataWorker::playSoundBuffer( void* datas, unsigned char* buffer, size_t buffSize, unsigned int nbSample )
220
{
221
    //qDebug() << "Playing sound buffer with nbSample =" << nbSample << "buffSize =" << buffSize;
222
//    qDebug() << "Buff[0] = " << (unsigned int)buffer[0];
223 224 225
    //if (MetaDataWorker::getInstance()->getCurrentMedia()->getAudioData()->frameList.size() < 500 )
    MetaDataWorker* self = reinterpret_cast<MetaDataWorker*>( datas );
    self->m_currentMedia->addAudioFrame( datas, buffer, buffSize, nbSample );
226
    //else
227
//        MetaDataWorker::getInstance()->getMediaPlayer()->stop();
228 229
}

230
void    MetaDataWorker::closeSoundBuffer( void* datas )
231 232
{
    qDebug() << "Closing sound buffer";
233 234 235
    MetaDataWorker* self = reinterpret_cast<MetaDataWorker*>( datas );

    self->m_mediaPlayer->stop();
236 237
}

238
void    MetaDataWorker::instanceParameterHandler( void*, char*, char* )
239 240
{
}
241

242
void    MetaDataWorker::entrypointLengthChanged()
243 244 245 246 247 248 249
{
    disconnect( m_mediaPlayer, SIGNAL( lengthChanged() ), this, SLOT( entrypointLengthChanged() ) );
    m_lengthHasChanged = true;
    if ( m_mediaIsPlaying == true )
        getMetaData();
}

250
void    MetaDataWorker::entrypointPlaying()
251 252 253 254 255 256
{
    disconnect( m_mediaPlayer, SIGNAL( playing() ), this, SLOT( entrypointPlaying() ) );
    m_mediaIsPlaying = true;
    if ( m_lengthHasChanged == true )
        getMetaData();
}
257 258 259 260 261

void    MetaDataWorker::setMediaValidity( bool validity )
{
    m_validity = validity;
}
262 263 264 265 266

void    SnapshotHelper::run()
{
    m_worker->renderSnapshotAsync();
}