defuze.me  Client
audiodecoder.cpp
00001 /**************************************************************************
00002 ** defuze.me Epitech Innovative Project
00003 **
00004 ** Copyright 2010-2011
00005 **   Athena Calmettes - Jocelyn De La Rosa - Francois Gaillard
00006 **   Adrien Jarthon - Alexandre Moore - Luc Peres - Arnaud Sellier
00007 **
00008 ** All rights reserved.
00009 **************************************************************************/
00010 
00011 #include <QDebug>
00012 #include <QMutexLocker>
00013 #include "audiodecoder.hpp"
00014 #include "exception.hpp"
00015 #include "ffmpeg.hpp"
00016 #include "audiocore.hpp"
00017 #include "audiomixer.hpp"
00018 #include "audioplayer.hpp"
00019 #include "status.hpp"
00020 
00021 using namespace Audio;
00022 
00023 AudioDecoder::AudioDecoder(QString, AudioCore *audioCore)
00024 {
00025     _audioCore = audioCore;
00026     _player = 0;
00027     initVars();
00028 }
00029 
00030 AudioDecoder::~AudioDecoder()
00031 {
00032     closeFile();
00033 }
00034 
00035 
00036 void    AudioDecoder::openFile(QString file)
00037 {
00038     closeFile();
00039     if (av_open_input_file(&aFormatCtx, file.toLocal8Bit().data(), NULL, 0, NULL) != 0)
00040         throw_exception(0x01, tr("Unable to open the audio file: %1").arg(file));
00041     if (av_find_stream_info(aFormatCtx) < 0)
00042         throw_exception(0x02, tr("Unable to find stream info in the file: %1").arg(file));
00043 
00044     for(unsigned int i = 0; i < aFormatCtx->nb_streams; i++)
00045         if(aFormatCtx->streams[i]->codec->codec_type == 1 && audioStream < 0)
00046             audioStream = i;
00047 
00048     if (audioStream == -1)
00049         throw_exception(0x03, tr("Unable to open the audio stream from: %1").arg(file));
00050 
00051     initCodec();
00052     setFormat();
00053 
00054     _state = init? Iddle : BadFormat;
00055 }
00056 
00057 void    AudioDecoder::closeFile()
00058 {
00059     if (state() == Decoding)
00060         stop();
00061     if(aCodecCtx)
00062         avcodec_close(aCodecCtx);
00063     if(aFormatCtx)
00064         av_close_input_file(aFormatCtx);
00065     if (decodedBuffer.isOpen())
00066         decodedBuffer.close();
00067     initVars();
00068 }
00069 
00070 void    AudioDecoder::initVars()
00071 {
00072     _state = NoFile;
00073     aFormatCtx = 0;
00074     aCodecCtx = 0;
00075     aCodec = 0;
00076     out_size = 0;
00077     packet.size = 0;
00078     audioStream = -1;
00079     playingPosition = 0;
00080     decodingPosition = 0;
00081     decodedBuffer.open(QBuffer::ReadWrite);
00082     init = false;
00083 }
00084 
00085 void    AudioDecoder::initCodec()
00086 {
00087     aCodecCtx=aFormatCtx->streams[audioStream]->codec;
00088     if (!aCodecCtx->sample_rate)
00089         aCodecCtx->sample_rate = 44100;
00090     if (!aCodecCtx->channels)
00091         aCodecCtx->channels = 2;
00092 
00093     aCodec = avcodec_find_decoder(aCodecCtx->codec_id);
00094     if(aCodec == 0)
00095         throw_exception(0x04, tr("Unsupported audio codec"));
00096     if(avcodec_open(aCodecCtx, aCodec) < 0)
00097         throw_exception(0x05, tr("Can't open codec"));
00098     init = true;
00099 }
00100 
00101 void    AudioDecoder::setFormat()
00102 {
00103     format.setFrequency(aCodecCtx->sample_rate);
00104     format.setChannels(aCodecCtx->channels);
00105     format.setSampleSize(16);
00106     format.setCodec("audio/pcm");
00107     format.setByteOrder(QAudioFormat::LittleEndian);
00108     format.setSampleType(QAudioFormat::SignedInt);
00109 }
00110 
00111 bool    AudioDecoder::isInit() const
00112 {
00113     return init;
00114 }
00115 
00116 int min(int a, int b)
00117 {
00118     return (a < b ? a : b);
00119 }
00120 
00121 void AudioDecoder::decodeFrame()
00122 {
00123     QMutexLocker    locker(&mutex);
00124     int len = 0;
00125     if (init && state() == Decoding)
00126     {
00127         if (out_size > 0)
00128         {
00129 //          qDebug() << "writing" << out_size;
00130             decodedBuffer.write((char*)audioBuf, out_size);
00131             decodingPosition += out_size;
00132             out_size = 0;
00133         }
00134         else if (packet.size > 0)
00135         {
00136             out_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
00137             len = avcodec_decode_audio3(aCodecCtx, audioBuf, &out_size, &packet);
00138 //          qDebug() << "decoding:" << len << " output:" << out_size;
00139             if (len < 0)
00140             {
00141                 packet.size = 0;
00142                 out_size = 0;
00143                 qDebug() << "Unable to decode audio packet";
00144                 return;
00145             }
00146             else
00147             {
00148                 packet.size -= len;
00149                 packet.data += len;
00150             }
00151         }
00152         else if (av_read_frame(aFormatCtx, &packet) >= 0)
00153         {
00154 //          qDebug() << "get new packet of size" << packet.size;
00155             if(!packet.stream_index == audioStream)
00156                 throw_exception(0x06, tr("Error while reading frame from file"));
00157         }
00158         else
00159         {
00160             qDebug() << "decoder stop decoding, buffer size: " << decodedBuffer.size();
00161             //Notification::Status::gMessage(tr("Decoding finished: %1 MB").arg(decodedBuffer.size()/1024/1024), Notification::OK);
00162             _state = Stopped;
00163             emit decodingFinished();
00164         }
00165     }
00166 }
00167 
00168 void    AudioDecoder::stop()
00169 {
00170     QMutexLocker    locker(&mutex);
00171     if (init)
00172         _state = Stopped;
00173 }
00174 
00175 void    AudioDecoder::start()
00176 {
00177     QMutexLocker    locker(&mutex);
00178     if (init && (state() == Stopped || state() == Iddle))
00179     {
00180         if (state() == Iddle)
00181             audioBuf = (short*) av_malloc((AVCODEC_MAX_AUDIO_FRAME_SIZE + FF_INPUT_BUFFER_PADDING_SIZE)* sizeof(*audioBuf));
00182         _state = Decoding;
00183         qDebug() << "decoder start decoding";
00184     }
00185 }
00186 
00187 AudioDecoder::DecoderState  AudioDecoder::state() const
00188 {
00189     return _state;
00190 }
00191 
00192 int     AudioDecoder::duration() const
00193 {
00194     if (!aFormatCtx && state() == NoFile)
00195         return 0;
00196     return aFormatCtx->duration / AV_TIME_BASE;
00197 }
00198 
00199 int     AudioDecoder::bytesToSeconds(int bytes) const
00200 {
00201     return (bytes/ aCodecCtx->sample_rate / 2 / aCodecCtx->channels);
00202 }
00203 
00204 FileFormat  AudioDecoder::getFileFormat(const QString& path)
00205 {
00206     AVFormatContext *afctx;
00207     FileFormat f;
00208     if (av_open_input_file(&afctx, path.toStdString().c_str(), NULL, 0, NULL) != 0)
00209         return FormatNoAudio;
00210     av_find_stream_info(afctx);
00211     if (QString(afctx->iformat->name) == "mp3")
00212         f = FormatMP3;
00213     else if (QString(afctx->iformat->name) == "asf")
00214         f = FormatWMA;
00215     else if (QString(afctx->iformat->name) == "ogg")
00216         f = FormatOGG;
00217     else if (QString(afctx->iformat->name) == "wav")
00218         f = FormatWAV;
00219     else if (QString(afctx->iformat->name) == "flac")
00220         f = FormatFLAC;
00221     else if (QString(afctx->iformat->name) == "mov,mp4,m4a,3gp,3g2,mj2")
00222         f = FormatAAC;
00223     else
00224         f = FormatUnknown;
00225     av_close_input_file(afctx);
00226     return f;
00227 }
00228 
00229 void    AudioDecoder::run()
00230 {
00231     if(state() != NoFile)
00232     {
00233         if (state() == Decoding)
00234             decodeFrame();
00235     }
00236 }
00237 
00238 qint64  AudioDecoder::readDecodedFrame(char *data, qint64 maxlen)
00239 {
00240     if (decodedBuffer.isOpen())
00241     {
00242         mutex.lock();
00243         decodedBuffer.seek(playingPosition);
00244         qint64 i = decodedBuffer.read(data, maxlen);
00245         playingPosition += i;
00246 //      qDebug() << "readData(" << maxlen << ") = " << i;
00247         decodedBuffer.seek(decodingPosition);
00248         mutex.unlock();
00249         return i;
00250     }
00251     else
00252         return 0;
00253 }
00254 
00255 qint64 AudioDecoder::bytesAvailable() const
00256 {
00257     if (decodedBuffer.isOpen())
00258         return decodedBuffer.size(); //+ QIODevice::bytesAvailable();
00259     return 0;
00260 }
00261 
00262 QAudioFormat& AudioDecoder::getFormat()
00263 {
00264     return format;
00265 }
00266 
00267 void    AudioDecoder::setPlayer(const Player::AudioPlayer *player)
00268 {
00269     _player = player;
00270 }
00271 
00272 bool    AudioDecoder::isPlayerPlaying() const
00273 {
00274     if (_player && _player->isPlaying())
00275         return true;
00276     return false;
00277 }
00278 
00279 void    AudioDecoder::setPlayingPosition(quint64 position)
00280 {
00281     playingPosition = position;
00282 }
00283 
00284 qint64  AudioDecoder::getPlayingPosition() const
00285 {
00286     if (state() != NoFile && state() != BadFormat)
00287         return bytesToSeconds(playingPosition);
00288     return 0;
00289 }
00290 
00291 /*
00292   **
00293   ** Old functions
00294   **
00295 
00296 int     AudioDecoder::currentPosition() const
00297 {
00298     int pos = 0;
00299     if (state() != NoFile)
00300     {
00301         if (_audioOutput->getType() == AudioMixerType)
00302             pos = bytesToSeconds(_currentFrame - static_cast<AudioMixer*>(_audioOutput)->inputBufferSize(_name));
00303         else
00304             pos = bytesToSeconds(_currentFrame);
00305     }
00306     return pos;
00307 }
00308 
00309 void    AudioDecoder::seek(int pos)
00310 {
00311     if (_state == Playing)
00312         pause();
00313     _currentPosition = pos;
00314     _currentFrame = pos  *  aCodecCtx->sample_rate * 2 * aCodecCtx->channels;
00315     int64_t timeToSeek = av_rescale(pos * 1000, aFormatCtx->streams[audioStream]->time_base.den ,aFormatCtx->streams[audioStream]->time_base.num);;
00316     timeToSeek /= 1000;
00317     avformat_seek_file(aFormatCtx, audioStream, 0, timeToSeek, timeToSeek, AVSEEK_FLAG_FRAME);
00318     avcodec_flush_buffers(aCodecCtx);
00319 }
00320 */