MetaDataWorker.cpp 8.96 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
MetaDataWorker::MetaDataWorker( Media* media ) :
30
        m_validity( true ),
31 32
        m_currentMedia( media ),
        m_mediaIsPlaying( false),
Hugo Beauzee-Luyssen's avatar
Hugo Beauzee-Luyssen committed
33
        m_lengthHasChanged( false )
34 35 36 37
{
    m_mediaPlayer = new LibVLCpp::MediaPlayer();
}

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

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

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

74
void    MetaDataWorker::computeImageMetaData()
75
{
76 77
    if ( !m_validity )
        return ;
78 79
    m_currentMedia->addVolatileParam( ":access=fake", ":access=''" );
    m_currentMedia->addVolatileParam( ":fake-duration=10000", ":fake-duration=''" );
80 81
    //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;
82 83
}

84
void    MetaDataWorker::getMetaData()
85
{
86
    m_mediaIsPlaying = false;
Hugo Beauzee-Luyssen's avatar
Hugo Beauzee-Luyssen committed
87
    m_lengthHasChanged = false;
88

89 90
    if ( !m_validity )
        return ;
91
    //In order to wait for the VOUT to be ready:
92 93 94
    //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 );
95
    while ( m_mediaPlayer->hasVout() == false )
96
    {
97
        SleepMS( 1 ); //Ugly isn't it :)
98
    }
99 100
    LibVLCpp::Exception::setErrorCallback( NULL );

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

114
    //Setting time for snapshot :
115
    if ( m_currentMedia->getFileType() == Media::Video )
116 117 118 119 120 121
    {
        connect( m_mediaPlayer, SIGNAL( positionChanged() ), this, SLOT( renderSnapshot() ) );
        m_mediaPlayer->setTime( m_mediaPlayer->getLength() / 3 );
    }
    else
        renderSnapshot();
122
}
123

124
void    MetaDataWorker::renderSnapshot()
125
{
126
    if ( m_currentMedia->getFileType() == Media::Video )
127
        disconnect( m_mediaPlayer, SIGNAL( positionChanged() ), this, SLOT( renderSnapshot() ) );
128 129
    if ( !m_validity )
        return ;
130 131 132
    QTemporaryFile tmp;
    tmp.setAutoRemove( false );
    tmp.open();
133
    m_tmpSnapshotFilename = tmp.fileName();
134

135
    connect( m_mediaPlayer, SIGNAL( snapshotTaken() ), this, SLOT( setSnapshot() ), Qt::QueuedConnection );
136 137

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

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

154 155
    disconnect( m_mediaPlayer, SIGNAL( snapshotTaken() ), this, SLOT( setSnapshot() ) );

156 157
    m_currentMedia->emitMetaDataComputed();

158 159
    //CHECKME:
    //This is synchrone, but it may become asynchrone in the future...
160
    m_mediaPlayer->stop();
161
    //startAudioDataParsing();
162
    delete this;
163
}
164

165
void    MetaDataWorker::startAudioDataParsing()
166
{
167 168 169
    qDebug() << "Starting audio parsing";
    char    osb[64], psb[64], csb[64], iph[64], data[64];

170
//    disconnect( m_mediaPlayer, SIGNAL( stopped() ), this, SLOT( startAudioDataParsing() ) );
171

172 173 174 175
    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);
176
    sprintf( data, ":amem-data=%lld", (long long int)(intptr_t) this);
177 178 179 180 181 182 183 184 185 186 187
    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();
188
    connect( m_mediaPlayer, SIGNAL( endReached() ), this, SLOT( stopAudioDataParsing() ) );
189
    qDebug() << "Starting playback again";
190
    m_mediaPlayer->play();
191 192
}

193
void    MetaDataWorker::stopAudioDataParsing()
194
{
195 196
    qDebug() << "Stopping AudioDataParsing";
    m_mediaPlayer->stop();
197 198
}

199
void    MetaDataWorker::openSoundBuffer( void* datas, unsigned int* freq, unsigned int* nbChannels, unsigned int* fourCCFormat, unsigned int* frameSize )
200 201
{
    //qDebug() << "Opening sound buffer with freq =" << *freq << "nbChannels =" << *nbChannels << "frameSize =" << *frameSize;
202 203
    MetaDataWorker* self = reinterpret_cast<MetaDataWorker*>( datas );
    self->m_currentMedia->initAudioData( datas, freq, nbChannels, fourCCFormat, frameSize );
204 205
 }

206
void    MetaDataWorker::playSoundBuffer( void* datas, unsigned char* buffer, size_t buffSize, unsigned int nbSample )
207
{
208
    //qDebug() << "Playing sound buffer with nbSample =" << nbSample << "buffSize =" << buffSize;
209
//    qDebug() << "Buff[0] = " << (unsigned int)buffer[0];
210 211 212
    //if (MetaDataWorker::getInstance()->getCurrentMedia()->getAudioData()->frameList.size() < 500 )
    MetaDataWorker* self = reinterpret_cast<MetaDataWorker*>( datas );
    self->m_currentMedia->addAudioFrame( datas, buffer, buffSize, nbSample );
213
    //else
214
//        MetaDataWorker::getInstance()->getMediaPlayer()->stop();
215 216
}

217
void    MetaDataWorker::closeSoundBuffer( void* datas )
218 219
{
    qDebug() << "Closing sound buffer";
220 221 222
    MetaDataWorker* self = reinterpret_cast<MetaDataWorker*>( datas );

    self->m_mediaPlayer->stop();
223 224
}

225
void    MetaDataWorker::instanceParameterHandler( void*, char*, char* )
226 227
{
}
228

229
void    MetaDataWorker::entrypointLengthChanged()
230 231 232 233 234 235 236
{
    disconnect( m_mediaPlayer, SIGNAL( lengthChanged() ), this, SLOT( entrypointLengthChanged() ) );
    m_lengthHasChanged = true;
    if ( m_mediaIsPlaying == true )
        getMetaData();
}

237
void    MetaDataWorker::entrypointPlaying()
238 239 240 241 242 243
{
    disconnect( m_mediaPlayer, SIGNAL( playing() ), this, SLOT( entrypointPlaying() ) );
    m_mediaIsPlaying = true;
    if ( m_lengthHasChanged == true )
        getMetaData();
}
244 245 246 247 248

void    MetaDataWorker::setMediaValidity( bool validity )
{
    m_validity = validity;
}