MetaDataWorker.cpp 9.66 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
const int   Clip::DefaultFPS = 30;

31 32 33 34
MetaDataWorker::MetaDataWorker( LibVLCpp::MediaPlayer* mediaPlayer, Media* media, MetaDataWorker::MetaDataType type ) :
        m_mediaPlayer( mediaPlayer ),
        m_type( type ),
        m_media( media ),
35
        m_mediaIsPlaying( false),
Hugo Beauzee-Luyssen's avatar
Hugo Beauzee-Luyssen committed
36
        m_lengthHasChanged( false )
37 38 39
{
}

40
MetaDataWorker::~MetaDataWorker()
41
{
42 43
    //if ( m_mediaPlayer->isPlaying() )
    //    m_mediaPlayer->stop();
44 45
}

46
void    MetaDataWorker::compute()
47
{
48
    if ( m_media->getFileType() == Media::Video )
49
    {
50
        computeVideoMetaData();
51
    }
52
    else if ( m_media->getFileType() == Media::Image )
53 54 55
    {
        computeImageMetaData();
    }
56 57
    m_media->addConstantParam( ":vout=dummy" );
    m_mediaPlayer->setMedia( m_media->getVLCMedia() );
58 59
    connect( m_mediaPlayer, SIGNAL( playing() ), this, SLOT( entrypointPlaying() ) );
    m_mediaPlayer->play();
60
    m_media->flushVolatileParameters();
61 62
}

63
void    MetaDataWorker::computeVideoMetaData()
64 65
{
    //Disabling audio for this specific use of the media
66
    m_media->addVolatileParam( ":no-audio", ":audio" );
67
    connect( m_mediaPlayer, SIGNAL( lengthChanged() ), this, SLOT( entrypointLengthChanged() ) );
68 69
}

70
void    MetaDataWorker::computeImageMetaData()
71
{
72 73
    m_media->addVolatileParam( ":access=fake", ":access=''" );
    m_media->addVolatileParam( ":fake-duration=10000", ":fake-duration=''" );
74 75
    //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;
76 77
}

78
void    MetaDataWorker::getMetaData()
79
{
80
    m_mediaIsPlaying = false;
Hugo Beauzee-Luyssen's avatar
Hugo Beauzee-Luyssen committed
81
    m_lengthHasChanged = false;
82

83
    //In order to wait for the VOUT to be ready:
84 85 86
    //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 );
87
    while ( m_mediaPlayer->hasVout() == false )
88
    {
89
        SleepMS( 1 ); //Ugly isn't it :)
90
    }
91 92
    LibVLCpp::Exception::setErrorCallback( NULL );

93
    if ( m_type == MetaData )
94
    {
95 96 97 98 99 100 101
        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();
102
            m_media->setFps( Clip::DefaultFPS );
103 104
        }
        m_media->setNbFrames( (m_media->getLengthMS() / 1000) * m_media->getFps() );
105
//        connect( m_mediaPlayer, SIGNAL( stopped () ), this, SLOT( mediaPlayerStopped() ), Qt::QueuedConnection );
106 107
        m_mediaPlayer->stop();
        emit mediaPlayerIdle( m_mediaPlayer );
108 109 110 111
        if ( m_type == Snapshot )
            m_media->emitSnapshotComputed();
        else
            m_media->emitMetaDataComputed( true );
112 113
        delete this;
        return;
114
    }
115
    else if ( m_type == Snapshot )
116
    {
117 118 119 120 121 122 123 124
        //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() ) );
125
    }
126
}
127

128
void    MetaDataWorker::renderSnapshot()
129
{
130
    if ( m_media->getFileType() == Media::Video )
131
        disconnect( m_mediaPlayer, SIGNAL( positionChanged() ), this, SLOT( renderSnapshot() ) );
132 133
    else
        disconnect( this, SIGNAL( snapshotRequested() ), this, SLOT( renderSnapshot() ) );
134 135 136
    QTemporaryFile tmp;
    tmp.setAutoRemove( false );
    tmp.open();
137
    m_tmpSnapshotFilename = tmp.fileName();
138

139
    connect( m_mediaPlayer, SIGNAL( snapshotTaken() ), this, SLOT( setSnapshot() ), Qt::QueuedConnection );
140 141

    //The slot should be triggered in this methode
142
    m_mediaPlayer->takeSnapshot( m_tmpSnapshotFilename.toStdString().c_str()
143
                                 , 0, 0 );
144 145 146
    //Snapshot slot should has been called (but maybe not in next version...)
}

147
void    MetaDataWorker::setSnapshot()
148
{
149 150 151 152
    QPixmap* pixmap = new QPixmap( m_tmpSnapshotFilename );
    if ( pixmap->isNull() )
        delete pixmap;
    else
153
        m_media->setSnapshot( pixmap );
154 155 156 157
    //TODO : we shouldn't have to do this... patch vlc to get a memory snapshot.
    QFile   tmp( m_tmpSnapshotFilename );
    tmp.remove();

158 159 160 161
    disconnect( m_mediaPlayer, SIGNAL( snapshotTaken() ), this, SLOT( setSnapshot() ) );

    //CHECKME:
    //This is synchrone, but it may become asynchrone in the future...
162
//    connect( m_mediaPlayer, SIGNAL( stopped () ), this, SLOT( mediaPlayerStopped() ), Qt::QueuedConnection );
163
    m_mediaPlayer->stop();
164
    emit mediaPlayerIdle( m_mediaPlayer );
165 166 167 168 169
    if ( m_type == Snapshot )
        m_media->emitSnapshotComputed();
    else
        m_media->emitMetaDataComputed( true );
    delete this;
170
    //startAudioDataParsing();
171 172 173 174 175 176 177 178 179 180
}

void    MetaDataWorker::mediaPlayerStopped()
{
    disconnect( m_mediaPlayer, SIGNAL( stopped() ), this, SLOT( mediaPlayerStopped() ) );
    emit mediaPlayerIdle( m_mediaPlayer );
    if ( m_type == Snapshot )
        m_media->emitSnapshotComputed();
    else
        m_media->emitMetaDataComputed( true );
181
    delete this;
182
}
183

184
void    MetaDataWorker::startAudioDataParsing()
185
{
186 187 188
    qDebug() << "Starting audio parsing";
    char    osb[64], psb[64], csb[64], iph[64], data[64];

189
//    disconnect( m_mediaPlayer, SIGNAL( stopped() ), this, SLOT( startAudioDataParsing() ) );
190

191 192 193 194
    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);
195
    sprintf( data, ":amem-data=%lld", (long long int)(intptr_t) this);
196 197 198 199 200 201 202 203 204 205 206
    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();
207
    connect( m_mediaPlayer, SIGNAL( endReached() ), this, SLOT( stopAudioDataParsing() ) );
208
    qDebug() << "Starting playback again";
209
    m_mediaPlayer->play();
210 211
}

212
void    MetaDataWorker::stopAudioDataParsing()
213
{
214 215
    qDebug() << "Stopping AudioDataParsing";
    m_mediaPlayer->stop();
216 217
}

218
void    MetaDataWorker::openSoundBuffer( void* datas, unsigned int* freq, unsigned int* nbChannels, unsigned int* fourCCFormat, unsigned int* frameSize )
219 220
{
    //qDebug() << "Opening sound buffer with freq =" << *freq << "nbChannels =" << *nbChannels << "frameSize =" << *frameSize;
221
    MetaDataWorker* self = reinterpret_cast<MetaDataWorker*>( datas );
222
    self->m_media->initAudioData( datas, freq, nbChannels, fourCCFormat, frameSize );
223 224
 }

225
void    MetaDataWorker::playSoundBuffer( void* datas, unsigned char* buffer, size_t buffSize, unsigned int nbSample )
226
{
227
    //qDebug() << "Playing sound buffer with nbSample =" << nbSample << "buffSize =" << buffSize;
228
//    qDebug() << "Buff[0] = " << (unsigned int)buffer[0];
229 230
    //if (MetaDataWorker::getInstance()->getCurrentMedia()->getAudioData()->frameList.size() < 500 )
    MetaDataWorker* self = reinterpret_cast<MetaDataWorker*>( datas );
231
    self->m_media->addAudioFrame( datas, buffer, buffSize, nbSample );
232
    //else
233
//        MetaDataWorker::getInstance()->getMediaPlayer()->stop();
234 235
}

236
void    MetaDataWorker::closeSoundBuffer( void* datas )
237 238
{
    qDebug() << "Closing sound buffer";
239 240 241
    MetaDataWorker* self = reinterpret_cast<MetaDataWorker*>( datas );

    self->m_mediaPlayer->stop();
242 243
}

244
void    MetaDataWorker::instanceParameterHandler( void*, char*, char* )
245 246
{
}
247

248
void    MetaDataWorker::entrypointLengthChanged()
249 250 251 252 253 254 255
{
    disconnect( m_mediaPlayer, SIGNAL( lengthChanged() ), this, SLOT( entrypointLengthChanged() ) );
    m_lengthHasChanged = true;
    if ( m_mediaIsPlaying == true )
        getMetaData();
}

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