MetaDataWorker.cpp 9.62 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 31 32
MetaDataWorker::MetaDataWorker( LibVLCpp::MediaPlayer* mediaPlayer, Media* media, MetaDataWorker::MetaDataType type ) :
        m_mediaPlayer( mediaPlayer ),
        m_type( type ),
        m_media( media ),
33
        m_mediaIsPlaying( false),
Hugo Beauzee-Luyssen's avatar
Hugo Beauzee-Luyssen committed
34
        m_lengthHasChanged( false )
35 36 37
{
}

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

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

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

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

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

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

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

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

137
    connect( m_mediaPlayer, SIGNAL( snapshotTaken() ), this, SLOT( setSnapshot() ), Qt::QueuedConnection );
138 139

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

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

156 157 158 159
    disconnect( m_mediaPlayer, SIGNAL( snapshotTaken() ), this, SLOT( setSnapshot() ) );

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

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 );
179
    delete this;
180
}
181

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

187
//    disconnect( m_mediaPlayer, SIGNAL( stopped() ), this, SLOT( startAudioDataParsing() ) );
188

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

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

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

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

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

    self->m_mediaPlayer->stop();
240 241
}

242
void    MetaDataWorker::instanceParameterHandler( void*, char*, char* )
243 244
{
}
245

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

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