defuze.me
Client
|
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 */