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

37
MetaDataWorker::~MetaDataWorker()
38 39 40 41 42
{
    if (m_mediaPlayer)
        delete m_mediaPlayer;
}

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

59
void    MetaDataWorker::computeVideoMetaData()
60 61
{
    //Disabling audio for this specific use of the media
62
    m_currentMedia->addVolatileParam( ":no-audio", ":audio" );
63
    m_currentMedia->addConstantParam( ":vout=dummy" );
64

65
    connect( m_mediaPlayer, SIGNAL( lengthChanged() ), this, SLOT( entrypointLengthChanged() ) );
66 67
}

68
void    MetaDataWorker::computeImageMetaData()
69
{
70 71
    m_currentMedia->addVolatileParam( ":access=fake", ":access=''" );
    m_currentMedia->addVolatileParam( ":fake-duration=10000", ":fake-duration=''" );
72 73
}

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

79
    //In order to wait for the VOUT to be ready:
80 81 82
    //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 );
83 84
    while ( m_mediaPlayer->getWidth() == 0 )
        SleepMS( 1 ); //Ugly isn't it :)
85 86
    LibVLCpp::Exception::setErrorCallback( NULL );

87
    m_currentMedia->setLength( m_mediaPlayer->getLength() );
88

89 90
    m_currentMedia->setWidth( m_mediaPlayer->getWidth() );
    m_currentMedia->setHeight( m_mediaPlayer->getHeight() );
91
    m_currentMedia->setFps( m_mediaPlayer->getFps() );
92 93 94 95 96
    if ( m_currentMedia->getFps() == .0f )
    {
        qWarning() << "Invalid FPS for media:" << m_currentMedia->getFileInfo()->absoluteFilePath();
        m_currentMedia->setFps( FPS );
    }
97
    m_currentMedia->setNbFrames( m_currentMedia->getLengthMS() / 1000 * m_currentMedia->getFps() );
98

99
    //Setting time for snapshot :
100
    if ( m_currentMedia->getFileType() == Media::Video )
101 102 103 104 105 106
    {
        connect( m_mediaPlayer, SIGNAL( positionChanged() ), this, SLOT( renderSnapshot() ) );
        m_mediaPlayer->setTime( m_mediaPlayer->getLength() / 3 );
    }
    else
        renderSnapshot();
107
}
108

109
void    MetaDataWorker::renderSnapshot()
110
{
111
    if ( m_currentMedia->getFileType() == Media::Video )
112
        disconnect( m_mediaPlayer, SIGNAL( positionChanged() ), this, SLOT( renderSnapshot() ) );
113 114 115
    QTemporaryFile tmp;
    tmp.setAutoRemove( false );
    tmp.open();
116
    m_tmpSnapshotFilename = tmp.fileName();
117

118
    connect( m_mediaPlayer, SIGNAL( snapshotTaken() ), this, SLOT( setSnapshot() ), Qt::QueuedConnection );
119 120

    //The slot should be triggered in this methode
121
    m_mediaPlayer->takeSnapshot( m_tmpSnapshotFilename.toStdString().c_str()
122
                                 , 0, 0 );
123 124 125
    //Snapshot slot should has been called (but maybe not in next version...)
}

126
void    MetaDataWorker::setSnapshot()
127
{
128 129 130 131
    QPixmap* pixmap = new QPixmap( m_tmpSnapshotFilename );
    if ( pixmap->isNull() )
        delete pixmap;
    else
132
        m_currentMedia->setSnapshot( pixmap );
133 134 135 136
    //TODO : we shouldn't have to do this... patch vlc to get a memory snapshot.
    QFile   tmp( m_tmpSnapshotFilename );
    tmp.remove();

137 138
    disconnect( m_mediaPlayer, SIGNAL( snapshotTaken() ), this, SLOT( setSnapshot() ) );

139 140
    m_currentMedia->emitMetaDataComputed();

141 142
    //CHECKME:
    //This is synchrone, but it may become asynchrone in the future...
143
    m_mediaPlayer->stop();
144
    //startAudioDataParsing();
145
    delete this;
146
}
147

148
void    MetaDataWorker::startAudioDataParsing()
149
{
150 151 152
    qDebug() << "Starting audio parsing";
    char    osb[64], psb[64], csb[64], iph[64], data[64];

153
//    disconnect( m_mediaPlayer, SIGNAL( stopped() ), this, SLOT( startAudioDataParsing() ) );
154

155 156 157 158
    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);
159
    sprintf( data, ":amem-data=%lld", (long long int)(intptr_t) this);
160 161 162 163 164 165 166 167 168 169 170
    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();
171
    connect( m_mediaPlayer, SIGNAL( endReached() ), this, SLOT( stopAudioDataParsing() ) );
172
    qDebug() << "Starting playback again";
173
    m_mediaPlayer->play();
174 175
}

176
void    MetaDataWorker::stopAudioDataParsing()
177
{
178 179
    qDebug() << "Stopping AudioDataParsing";
    m_mediaPlayer->stop();
180 181
}

182
void    MetaDataWorker::openSoundBuffer( void* datas, unsigned int* freq, unsigned int* nbChannels, unsigned int* fourCCFormat, unsigned int* frameSize )
183 184
{
    //qDebug() << "Opening sound buffer with freq =" << *freq << "nbChannels =" << *nbChannels << "frameSize =" << *frameSize;
185 186
    MetaDataWorker* self = reinterpret_cast<MetaDataWorker*>( datas );
    self->m_currentMedia->initAudioData( datas, freq, nbChannels, fourCCFormat, frameSize );
187 188
 }

189
void    MetaDataWorker::playSoundBuffer( void* datas, unsigned char* buffer, size_t buffSize, unsigned int nbSample )
190
{
191
    //qDebug() << "Playing sound buffer with nbSample =" << nbSample << "buffSize =" << buffSize;
192
//    qDebug() << "Buff[0] = " << (unsigned int)buffer[0];
193 194 195
    //if (MetaDataWorker::getInstance()->getCurrentMedia()->getAudioData()->frameList.size() < 500 )
    MetaDataWorker* self = reinterpret_cast<MetaDataWorker*>( datas );
    self->m_currentMedia->addAudioFrame( datas, buffer, buffSize, nbSample );
196
    //else
197
//        MetaDataWorker::getInstance()->getMediaPlayer()->stop();
198 199
}

200
void    MetaDataWorker::closeSoundBuffer( void* datas )
201 202
{
    qDebug() << "Closing sound buffer";
203 204 205
    MetaDataWorker* self = reinterpret_cast<MetaDataWorker*>( datas );

    self->m_mediaPlayer->stop();
206 207
}

208
void    MetaDataWorker::instanceParameterHandler( void*, char*, char* )
209 210
{
}
211

212
void    MetaDataWorker::entrypointLengthChanged()
213 214 215 216 217 218 219
{
    disconnect( m_mediaPlayer, SIGNAL( lengthChanged() ), this, SLOT( entrypointLengthChanged() ) );
    m_lengthHasChanged = true;
    if ( m_mediaIsPlaying == true )
        getMetaData();
}

220
void    MetaDataWorker::entrypointPlaying()
221 222 223 224 225 226
{
    disconnect( m_mediaPlayer, SIGNAL( playing() ), this, SLOT( entrypointPlaying() ) );
    m_mediaIsPlaying = true;
    if ( m_lengthHasChanged == true )
        getMetaData();
}