File indexing completed on 2024-05-05 04:48:35
0001 /**************************************************************************************** 0002 * Copyright (c) 2010 Sergey Ivanov <123kash@gmail.com> * 0003 * * 0004 * This program is free software; you can redistribute it and/or modify it under * 0005 * the terms of the GNU General Public License as published by the Free Software * 0006 * Foundation; either version 2 of the License, or (at your option) any later * 0007 * version. * 0008 * * 0009 * This program is distributed in the hope that it will be useful, but WITHOUT ANY * 0010 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A * 0011 * PARTICULAR PURPOSE. See the GNU General Public License for more details. * 0012 * * 0013 * You should have received a copy of the GNU General Public License along with * 0014 * this program. If not, see <http://www.gnu.org/licenses/>. * 0015 ****************************************************************************************/ 0016 0017 #define DEBUG_PREFIX "MusicDNSAudioDecoder" 0018 0019 #include "MusicDNSAudioDecoder.h" 0020 0021 #include <config.h> 0022 #include "core/support/Debug.h" 0023 #include "core/meta/Meta.h" 0024 0025 extern "C" { 0026 typedef quint64 UINT64_C; 0027 #include <libavcodec/avcodec.h> 0028 #include <libavformat/avformat.h> 0029 #include <libavutil/mathematics.h> 0030 } 0031 0032 #include <ofa1/ofa.h> 0033 0034 DecodedAudioData::DecodedAudioData() 0035 : m_sRate( 0 ) 0036 , m_channels( 0 ) 0037 , m_duration( 0 ) 0038 , m_data( new QByteArray ) 0039 { 0040 } 0041 0042 DecodedAudioData::~DecodedAudioData() 0043 { 0044 if( m_data ) 0045 delete m_data; 0046 } 0047 0048 int 0049 DecodedAudioData::sRate() 0050 { 0051 return m_sRate; 0052 } 0053 0054 void 0055 DecodedAudioData::setSampleRate( const int sampleRate ) 0056 { 0057 m_sRate = sampleRate; 0058 } 0059 0060 quint8 0061 DecodedAudioData::channels() 0062 { 0063 return m_channels; 0064 } 0065 0066 void 0067 DecodedAudioData::setChannels( const quint8 channels ) 0068 { 0069 m_channels = channels; 0070 } 0071 0072 const char * 0073 DecodedAudioData::data() 0074 { 0075 return m_data->data(); 0076 } 0077 0078 qint64 0079 DecodedAudioData::duration() 0080 { 0081 return m_duration; 0082 } 0083 0084 void 0085 DecodedAudioData::addTime( const qint64 ms ) 0086 { 0087 m_duration += ms; 0088 } 0089 0090 int 0091 DecodedAudioData::length() 0092 { 0093 return m_data->length(); 0094 } 0095 0096 void 0097 DecodedAudioData::appendData( const quint8 *data, int length ) 0098 { 0099 m_data->append( (const char *)data, length ); 0100 } 0101 0102 DecodedAudioData &DecodedAudioData::operator<< ( const quint8 &byte ) 0103 { 0104 m_data->append( byte ); 0105 return *this; 0106 } 0107 0108 void DecodedAudioData::flush() 0109 { 0110 m_sRate = 0; 0111 m_channels = 0; 0112 m_duration = 0; 0113 m_data->clear(); 0114 } 0115 0116 MusicDNSAudioDecoder::MusicDNSAudioDecoder( const Meta::TrackList &tracks, const int sampleLength ) 0117 : QObject() 0118 , ThreadWeaver::Job() 0119 , m_tracks( tracks ) 0120 , m_sampleLength( sampleLength ) 0121 { 0122 } 0123 0124 MusicDNSAudioDecoder::~MusicDNSAudioDecoder() 0125 { 0126 0127 } 0128 0129 void 0130 MusicDNSAudioDecoder::run(ThreadWeaver::JobPointer self, ThreadWeaver::Thread *thread) 0131 { 0132 Q_UNUSED(self); 0133 Q_UNUSED(thread); 0134 DecodedAudioData data; 0135 0136 #if LIBAVCODEC_VERSION_MAJOR < 59 0137 avcodec_register_all(); 0138 av_register_all(); 0139 #endif 0140 0141 foreach( Meta::TrackPtr track, m_tracks ) 0142 { 0143 decode( track->playableUrl().toLocalFile(), &data, m_sampleLength ); 0144 if( data.duration() > MIN_SAMPLE_LENGTH ) 0145 { 0146 QString fingerprint( ofa_create_print( ( unsigned char * ) data.data(), 0147 OFA_LITTLE_ENDIAN, ( data.length() >> 1 ), 0148 data.sRate(), data.channels() ) ); 0149 emit trackDecoded( track, fingerprint ); 0150 } 0151 else 0152 warning() << QLatin1String( "Some error occurred during fingerprint generation, probably track is too short: " ) + 0153 track->playableUrl().toLocalFile(); 0154 data.flush(); 0155 } 0156 } 0157 0158 void 0159 MusicDNSAudioDecoder::defaultBegin(const ThreadWeaver::JobPointer& self, ThreadWeaver::Thread *thread) 0160 { 0161 Q_EMIT started(self); 0162 ThreadWeaver::Job::defaultBegin(self, thread); 0163 } 0164 0165 void 0166 MusicDNSAudioDecoder::defaultEnd(const ThreadWeaver::JobPointer& self, ThreadWeaver::Thread *thread) 0167 { 0168 ThreadWeaver::Job::defaultEnd(self, thread); 0169 if (!self->success()) { 0170 Q_EMIT failed(self); 0171 } 0172 Q_EMIT done(self); 0173 } 0174 0175 // Function below has separate implementation for each ffmpeg API version 0176 int 0177 MusicDNSAudioDecoder::decode( const QString &fileName, DecodedAudioData *data, const int length ) 0178 #if LIBAVCODEC_VERSION_MAJOR >= 59 // ffmpeg 5.0 0179 { 0180 AVFormatContext *pFormatCtx = nullptr; 0181 AVCodecContext *pCodecCtx = nullptr; 0182 const AVCodec *pCodec = nullptr; 0183 AVFrame *decodedFrame = nullptr; 0184 AVPacket *packet = nullptr, *avpkt = nullptr; 0185 AVCodecParameters *codecpar = nullptr; 0186 AVRational streamTimeBase = { 1, 1000000 }; 0187 AVRational localTimeBase = { 1, 1000 }; 0188 0189 int audioStream = 0; 0190 int decoderRet = 0; 0191 int planeSize = 0; 0192 0193 bool isOk = true; 0194 av_log_set_level(AV_LOG_VERBOSE); 0195 0196 if( avformat_open_input( &pFormatCtx, fileName.toLocal8Bit(), nullptr, nullptr ) < 0 ) 0197 { 0198 warning() << QLatin1String( "Unable to open input file: " ) + fileName; 0199 return 0; 0200 } 0201 0202 if( avformat_find_stream_info( pFormatCtx, nullptr ) < 0 ) 0203 { 0204 warning() << QLatin1String( "Unable to find stream info: " ) + fileName; 0205 avformat_close_input( &pFormatCtx ); 0206 return 0; 0207 } 0208 0209 audioStream = av_find_best_stream(pFormatCtx, AVMEDIA_TYPE_AUDIO, -1, -1, &pCodec, 0); 0210 if( audioStream < 0 ) 0211 { 0212 warning() << QLatin1String( "Unable to find stream: " ) + fileName; 0213 avformat_close_input( &pFormatCtx ); 0214 return 0; 0215 } 0216 0217 if( !pCodec ) 0218 { 0219 warning() << QLatin1String( "Unable to find decoder: " ) + fileName; 0220 avformat_close_input( &pFormatCtx ); 0221 return 0; 0222 } 0223 0224 pCodecCtx = avcodec_alloc_context3(pCodec); 0225 0226 if( avcodec_open2( pCodecCtx, pCodec, nullptr ) < 0 ) 0227 { 0228 warning() << QLatin1String( "Unable to open codec " ) + fileName; 0229 avformat_close_input( &pFormatCtx ); 0230 return 0; 0231 } 0232 0233 streamTimeBase = pFormatCtx->streams[audioStream]->time_base; 0234 codecpar = pFormatCtx->streams[audioStream]->codecpar; 0235 0236 data->setSampleRate( codecpar->sample_rate ); 0237 data->setChannels( ( codecpar->channels > 1 )? 1 : 0 ); 0238 0239 avpkt = av_packet_alloc(); 0240 packet = av_packet_alloc(); 0241 while( !av_read_frame( pFormatCtx, packet ) && isOk ) 0242 { 0243 if( packet->stream_index == audioStream ) 0244 { 0245 avpkt->size = packet->size; 0246 avpkt->data = packet->data; 0247 if( !decodedFrame ) 0248 { 0249 decodedFrame = av_frame_alloc(); 0250 if( !decodedFrame ) 0251 { 0252 warning() << "Unable to allocate enough memory to decode file."; 0253 isOk = false; 0254 break; 0255 } 0256 else 0257 av_frame_unref( decodedFrame ); 0258 } 0259 0260 decoderRet = avcodec_send_packet( pCodecCtx, avpkt ); 0261 if( decoderRet < 0 ) 0262 { 0263 warning() << "Error while sending avcodec packet."; 0264 isOk = false; 0265 break; 0266 } 0267 do { 0268 decoderRet = avcodec_receive_frame( pCodecCtx, decodedFrame ); 0269 if( decoderRet == AVERROR(AVERROR_EOF) || decoderRet == AVERROR(EAGAIN) ) 0270 { 0271 break; 0272 } 0273 else if( decoderRet < 0 ) 0274 { 0275 warning() << "Error while decoding."; 0276 isOk = false; 0277 break; 0278 } 0279 av_samples_get_buffer_size( &planeSize, pCodecCtx->channels, decodedFrame->nb_samples, pCodecCtx->sample_fmt, 1); 0280 for( int i = 0; i < qMin( pCodecCtx->channels, 2 ); i++ ) 0281 data->appendData( const_cast<const quint8 *>( decodedFrame->extended_data[i] ), planeSize ); 0282 } while( decoderRet == 0 ); 0283 0284 data->addTime( av_rescale_q( packet->duration, streamTimeBase, localTimeBase ) ); 0285 } 0286 0287 av_packet_unref( packet ); 0288 0289 if( data->duration() >= length ) 0290 break; 0291 } 0292 0293 av_packet_unref( avpkt ); 0294 0295 avcodec_close( pCodecCtx ); 0296 avformat_close_input( &pFormatCtx ); 0297 av_free( decodedFrame ); 0298 0299 return data->duration(); 0300 } 0301 #elif LIBAVCODEC_VERSION_MAJOR >= 54 // ffmpeg 0.11 0302 { 0303 AVFormatContext *pFormatCtx = nullptr; 0304 AVCodecContext *pCodecCtx = nullptr; 0305 AVCodec *pCodec = nullptr; 0306 AVFrame *decodedFrame = nullptr; 0307 AVPacket packet, avpkt; 0308 AVRational streamTimeBase = { 1, 1000000 }; 0309 AVRational localTimeBase = { 1, 1000 }; 0310 0311 int audioStream = 0; 0312 int gotFrame = 0; 0313 int decoderRet = 0; 0314 int planeSize = 0; 0315 0316 bool isOk = true; 0317 0318 if( avformat_open_input( &pFormatCtx, fileName.toLocal8Bit(), nullptr, nullptr ) < 0 ) 0319 { 0320 warning() << QLatin1String( "Unable to open input file: " ) + fileName; 0321 return 0; 0322 } 0323 0324 if( avformat_find_stream_info( pFormatCtx, nullptr ) < 0 ) 0325 { 0326 warning() << QLatin1String( "Unable to find stream info: " ) + fileName; 0327 avformat_close_input( &pFormatCtx ); 0328 return 0; 0329 } 0330 0331 audioStream = av_find_best_stream(pFormatCtx, AVMEDIA_TYPE_AUDIO, -1, -1, &pCodec, 0); 0332 if( audioStream < 0 ) 0333 { 0334 warning() << QLatin1String( "Unable to find stream: " ) + fileName; 0335 avformat_close_input( &pFormatCtx ); 0336 return 0; 0337 } 0338 0339 if( !pCodec ) 0340 { 0341 warning() << QLatin1String( "Unable to find decoder: " ) + fileName; 0342 avformat_close_input( &pFormatCtx ); 0343 return 0; 0344 } 0345 0346 pCodecCtx = pFormatCtx->streams[audioStream]->codec; 0347 0348 if( avcodec_open2( pCodecCtx, pCodec, nullptr ) < 0 ) 0349 { 0350 warning() << QLatin1String( "Unable to open codec " ) + fileName; 0351 avformat_close_input( &pFormatCtx ); 0352 return 0; 0353 } 0354 0355 streamTimeBase = pFormatCtx->streams[audioStream]->time_base; 0356 0357 data->setSampleRate( pCodecCtx->sample_rate ); 0358 data->setChannels( ( pCodecCtx->channels > 1 )? 1 : 0 ); 0359 0360 av_init_packet( &avpkt ); 0361 while( !av_read_frame( pFormatCtx, &packet ) && isOk ) 0362 { 0363 if( packet.stream_index == audioStream ) 0364 { 0365 avpkt.size = packet.size; 0366 avpkt.data = packet.data; 0367 while( avpkt.size > 0 ) 0368 { 0369 if( !decodedFrame ) 0370 { 0371 decodedFrame = av_frame_alloc(); 0372 if( !decodedFrame ) 0373 { 0374 warning() << "Unable to allocate enough memory to decode file."; 0375 isOk = false; 0376 break; 0377 } 0378 else 0379 av_frame_unref( decodedFrame ); 0380 } 0381 0382 decoderRet = avcodec_decode_audio4( pCodecCtx, decodedFrame, &gotFrame, &avpkt ); 0383 if( decoderRet < 0 ) 0384 { 0385 warning() << "Error while decoding."; 0386 isOk = false; 0387 break; 0388 } 0389 0390 if( gotFrame ) 0391 { 0392 0393 av_samples_get_buffer_size( &planeSize, pCodecCtx->channels, decodedFrame->nb_samples, pCodecCtx->sample_fmt, 1); 0394 for( int i = 0; i < qMin( pCodecCtx->channels, 2 ); i++ ) 0395 data->appendData( const_cast<const quint8 *>( decodedFrame->extended_data[i] ), planeSize ); 0396 } 0397 0398 avpkt.size -= decoderRet; 0399 avpkt.data += decoderRet; 0400 } 0401 0402 data->addTime( av_rescale_q( packet.duration, streamTimeBase, localTimeBase ) ); 0403 } 0404 0405 av_free_packet( &packet ); 0406 0407 if( data->duration() >= length ) 0408 break; 0409 } 0410 0411 av_free_packet( &avpkt ); 0412 0413 avcodec_close( pCodecCtx ); 0414 avformat_close_input( &pFormatCtx ); 0415 av_free( decodedFrame ); 0416 0417 return data->duration(); 0418 } 0419 #elif LIBAVCODEC_VERSION_MAJOR == 53 && LIBAVCODEC_VERSION_MINOR >= 60 // ffmpeg 0.10 0420 { 0421 AVFormatContext *pFormatCtx = NULL; 0422 AVCodecContext *pCodecCtx = NULL; 0423 AVCodec *pCodec = NULL; 0424 AVFrame *decodedFrame = NULL; 0425 AVPacket packet, avpkt; 0426 AVRational streamTimeBase = { 1, 1000000 }; 0427 AVRational localTimeBase = { 1, 1000 }; 0428 0429 int audioStream = 0; 0430 int gotFrame = 0; 0431 int decoderRet = 0; 0432 int planeSize = 0; 0433 0434 bool isOk = true; 0435 0436 if( avformat_open_input( &pFormatCtx, fileName.toLocal8Bit(), NULL, NULL ) < 0 ) 0437 { 0438 warning() << QLatin1String( "Unable to open input file: " ) + fileName; 0439 return 0; 0440 } 0441 0442 if( avformat_find_stream_info( pFormatCtx, NULL ) < 0 ) 0443 { 0444 warning() << QLatin1String( "Unable to find stream info: " ) + fileName; 0445 avformat_close_input( &pFormatCtx ); 0446 return 0; 0447 } 0448 0449 audioStream = av_find_best_stream(pFormatCtx, AVMEDIA_TYPE_AUDIO, -1, -1, &pCodec, 0); 0450 if( audioStream < 0 ) 0451 { 0452 warning() << QLatin1String( "Unable to find stream: " ) + fileName; 0453 avformat_close_input( &pFormatCtx ); 0454 return 0; 0455 } 0456 0457 if( !pCodec ) 0458 { 0459 warning() << QLatin1String( "Unable to find decoder: " ) + fileName; 0460 avformat_close_input( &pFormatCtx ); 0461 return 0; 0462 } 0463 0464 pCodecCtx = pFormatCtx->streams[audioStream]->codec; 0465 0466 if( avcodec_open2( pCodecCtx, pCodec, NULL ) < 0 ) 0467 { 0468 warning() << QLatin1String( "Unable to open codec " ) + fileName; 0469 avformat_close_input( &pFormatCtx ); 0470 return 0; 0471 } 0472 0473 streamTimeBase = pFormatCtx->streams[audioStream]->time_base; 0474 0475 data->setSampleRate( pCodecCtx->sample_rate ); 0476 data->setChannels( ( pCodecCtx->channels > 1 )? 1 : 0 ); 0477 0478 av_init_packet( &avpkt ); 0479 while( !av_read_frame( pFormatCtx, &packet ) && isOk ) 0480 { 0481 if( packet.stream_index == audioStream ) 0482 { 0483 avpkt.size = packet.size; 0484 avpkt.data = packet.data; 0485 while( avpkt.size > 0 ) 0486 { 0487 if( !decodedFrame ) 0488 { 0489 decodedFrame = av_frame_alloc(); 0490 if( !decodedFrame ) 0491 { 0492 warning() << "Unable to allocate enough memory to decode file."; 0493 isOk = false; 0494 break; 0495 } 0496 else 0497 av_frame_unref( decodedFrame ); 0498 } 0499 0500 decoderRet = avcodec_decode_audio4( pCodecCtx, decodedFrame, &gotFrame, &avpkt ); 0501 if( decoderRet < 0 ) 0502 { 0503 warning() << "Error while decoding."; 0504 isOk = false; 0505 break; 0506 } 0507 0508 if( gotFrame ) 0509 { 0510 0511 av_samples_get_buffer_size( &planeSize, pCodecCtx->channels, decodedFrame->nb_samples, pCodecCtx->sample_fmt, 1); 0512 for( int i = 0; i < qMin( pCodecCtx->channels, 2 ); i++ ) 0513 data->appendData( const_cast<const quint8 *>( decodedFrame->extended_data[i] ), planeSize ); 0514 } 0515 0516 avpkt.size -= decoderRet; 0517 avpkt.data += decoderRet; 0518 } 0519 0520 data->addTime( av_rescale_q( packet.duration, streamTimeBase, localTimeBase ) ); 0521 } 0522 0523 av_free_packet( &packet ); 0524 0525 if( data->duration() >= length ) 0526 break; 0527 } 0528 0529 av_free_packet( &avpkt ); 0530 0531 avcodec_close( pCodecCtx ); 0532 avformat_close_input( &pFormatCtx ); 0533 av_free( decodedFrame ); 0534 0535 return data->duration(); 0536 } 0537 #elif LIBAVCODEC_VERSION_MAJOR == 53 && LIBAVCODEC_VERSION_MINOR >= 42 // ffmpeg 0.9 0538 { 0539 AVFormatContext *pFormatCtx = NULL; 0540 AVCodecContext *pCodecCtx = NULL; 0541 AVCodec *pCodec = NULL; 0542 AVFrame *decodedFrame = NULL; 0543 AVPacket packet, avpkt; 0544 AVRational streamTimeBase = { 1, 1000000 }; 0545 AVRational localTimeBase = { 1, 1000 }; 0546 0547 int audioStream = 0; 0548 int gotFrame = 0; 0549 int decoderRet = 0; 0550 int planeSize = 0; 0551 0552 bool isOk = true; 0553 0554 if( avformat_open_input( &pFormatCtx, fileName.toLocal8Bit(), NULL, NULL ) < 0 ) 0555 { 0556 warning() << QLatin1String( "Unable to open input file: " ) + fileName; 0557 return 0; 0558 } 0559 0560 if( avformat_find_stream_info( pFormatCtx, NULL ) < 0 ) 0561 { 0562 warning() << QLatin1String( "Unable to find stream info: " ) + fileName; 0563 av_close_input_file( pFormatCtx ); 0564 return 0; 0565 } 0566 0567 audioStream = av_find_best_stream(pFormatCtx, AVMEDIA_TYPE_AUDIO, -1, -1, &pCodec, 0); 0568 if( audioStream < 0 ) 0569 { 0570 warning() << QLatin1String( "Unable to find stream: " ) + fileName; 0571 av_close_input_file( pFormatCtx ); 0572 return 0; 0573 } 0574 0575 if( !pCodec ) 0576 { 0577 warning() << QLatin1String( "Unable to find decoder: " ) + fileName; 0578 av_close_input_file( pFormatCtx ); 0579 return 0; 0580 } 0581 0582 pCodecCtx = pFormatCtx->streams[audioStream]->codec; 0583 0584 if( avcodec_open2( pCodecCtx, pCodec, NULL ) < 0 ) 0585 { 0586 warning() << QLatin1String( "Unable to open codec " ) + fileName; 0587 av_close_input_file( pFormatCtx ); 0588 return 0; 0589 } 0590 0591 streamTimeBase = pFormatCtx->streams[audioStream]->time_base; 0592 0593 data->setSampleRate( pCodecCtx->sample_rate ); 0594 data->setChannels( ( pCodecCtx->channels > 1 )? 1 : 0 ); 0595 0596 av_init_packet( &avpkt ); 0597 while( !av_read_frame( pFormatCtx, &packet ) && isOk ) 0598 { 0599 if( packet.stream_index == audioStream ) 0600 { 0601 avpkt.size = packet.size; 0602 avpkt.data = packet.data; 0603 while( avpkt.size > 0 ) 0604 { 0605 if( !decodedFrame ) 0606 { 0607 decodedFrame = av_frame_alloc(); 0608 if( !decodedFrame ) 0609 { 0610 warning() << "Unable to allocate enough memory to decode file."; 0611 isOk = false; 0612 break; 0613 } 0614 else 0615 av_frame_unref( decodedFrame ); 0616 } 0617 0618 decoderRet = avcodec_decode_audio4( pCodecCtx, decodedFrame, &gotFrame, &avpkt ); 0619 if( decoderRet < 0 ) 0620 { 0621 warning() << "Error while decoding."; 0622 isOk = false; 0623 break; 0624 } 0625 0626 if( gotFrame ) 0627 { 0628 0629 av_samples_get_buffer_size( &planeSize, pCodecCtx->channels, decodedFrame->nb_samples, pCodecCtx->sample_fmt, 1); 0630 for( int i = 0; i < qMin( pCodecCtx->channels, 2 ); i++ ) 0631 data->appendData( const_cast<const quint8 *>( decodedFrame->extended_data[i] ), planeSize ); 0632 } 0633 0634 avpkt.size -= decoderRet; 0635 avpkt.data += decoderRet; 0636 } 0637 0638 data->addTime( av_rescale_q( packet.duration, streamTimeBase, localTimeBase ) ); 0639 } 0640 0641 av_free_packet( &packet ); 0642 0643 if( data->duration() >= length ) 0644 break; 0645 } 0646 0647 av_free_packet( &avpkt ); 0648 0649 avcodec_close( pCodecCtx ); 0650 av_close_input_file( pFormatCtx ); 0651 av_free( decodedFrame ); 0652 0653 return data->duration(); 0654 } 0655 #elif LIBAVCODEC_VERSION_MAJOR == 53 && LIBAVCODEC_VERSION_MINOR >= 7 // ffmpeg 0.8 0656 { 0657 AVFormatContext *pFormatCtx = NULL; 0658 AVCodecContext *pCodecCtx = NULL; 0659 AVCodec *pCodec = NULL; 0660 AVPacket packet, avpkt; 0661 AVRational streamTimeBase = { 1, 1000000 }; 0662 AVRational localTimeBase = { 1, 1000 }; 0663 0664 qint8 *buffer = new qint8[AVCODEC_MAX_AUDIO_FRAME_SIZE + FF_INPUT_BUFFER_PADDING_SIZE]; 0665 qint32 bufferSize = AVCODEC_MAX_AUDIO_FRAME_SIZE; 0666 0667 int outSize = 0; 0668 0669 int audioStream = 0; 0670 int decoderRet = 0; 0671 0672 bool isOk = true; 0673 0674 if( avformat_open_input( &pFormatCtx, fileName.toLocal8Bit(), NULL, NULL ) < 0 ) 0675 { 0676 warning() << QLatin1String( "Unable to open input file: " ) + fileName; 0677 return 0; 0678 } 0679 0680 if( av_find_stream_info( pFormatCtx ) < 0 ) 0681 { 0682 warning() << QLatin1String( "Unable to find stream info: " ) + fileName; 0683 av_close_input_file( pFormatCtx ); 0684 return 0; 0685 } 0686 0687 audioStream = av_find_best_stream(pFormatCtx, AVMEDIA_TYPE_AUDIO, -1, -1, &pCodec, 0); 0688 if( audioStream < 0 ) 0689 { 0690 warning() << QLatin1String( "Unable to find stream: " ) + fileName; 0691 av_close_input_file( pFormatCtx ); 0692 return 0; 0693 } 0694 0695 if( !pCodec ) 0696 { 0697 warning() << QLatin1String( "Unable to find decoder: " ) + fileName; 0698 av_close_input_file( pFormatCtx ); 0699 return 0; 0700 } 0701 0702 pCodecCtx = pFormatCtx->streams[audioStream]->codec; 0703 0704 if( avcodec_open( pCodecCtx, pCodec ) < 0 ) 0705 { 0706 warning() << QLatin1String( "Unable to open codec " ) + fileName; 0707 av_close_input_file( pFormatCtx ); 0708 return 0; 0709 } 0710 0711 streamTimeBase = pFormatCtx->streams[audioStream]->time_base; 0712 0713 data->setSampleRate( pCodecCtx->sample_rate ); 0714 data->setChannels( ( pCodecCtx->channels > 1 )? 1 : 0 ); 0715 0716 av_init_packet( &avpkt ); 0717 while( !av_read_frame( pFormatCtx, &packet ) && isOk ) 0718 { 0719 if( packet.stream_index == audioStream ) 0720 { 0721 avpkt.size = packet.size; 0722 avpkt.data = packet.data; 0723 while( avpkt.size > 0 ) 0724 { 0725 if( bufferSize < qMax( AVCODEC_MAX_AUDIO_FRAME_SIZE, avpkt.size*2 ) ) 0726 { 0727 bufferSize = qMax( AVCODEC_MAX_AUDIO_FRAME_SIZE, avpkt.size*2 ); 0728 delete [] buffer; 0729 buffer = new qint8[bufferSize+FF_INPUT_BUFFER_PADDING_SIZE]; 0730 } 0731 0732 outSize = bufferSize; 0733 decoderRet = avcodec_decode_audio3( pCodecCtx, ( qint16 * )buffer, &outSize, &avpkt ); 0734 if( decoderRet < 0 ) 0735 { 0736 warning() << "Error while decoding."; 0737 isOk = false; 0738 break; 0739 } 0740 0741 if( outSize > 0 ) 0742 { 0743 data->appendData( ( const quint8 *)buffer, outSize ); 0744 } 0745 0746 avpkt.size -= decoderRet; 0747 avpkt.data += decoderRet; 0748 } 0749 0750 data->addTime( av_rescale_q( packet.duration, streamTimeBase, localTimeBase ) ); 0751 } 0752 0753 av_free_packet( &packet ); 0754 0755 if( data->duration() >= length ) 0756 break; 0757 } 0758 0759 delete [] buffer; 0760 0761 av_free_packet( &avpkt ); 0762 0763 avcodec_close( pCodecCtx ); 0764 av_close_input_file( pFormatCtx ); 0765 0766 return data->duration(); 0767 } 0768 #elif LIBAVCODEC_VERSION_MAJOR == 52 && LIBAVCODEC_VERSION_MINOR >= 122 // ffmpeg 0.7 0769 { 0770 AVFormatContext *pFormatCtx = NULL; 0771 AVCodecContext *pCodecCtx = NULL; 0772 AVCodec *pCodec = NULL; 0773 AVPacket packet, avpkt; 0774 AVRational streamTimeBase = { 1, 1000000 }; 0775 AVRational localTimeBase = { 1, 1000 }; 0776 0777 qint8 *buffer = new qint8[AVCODEC_MAX_AUDIO_FRAME_SIZE + FF_INPUT_BUFFER_PADDING_SIZE]; 0778 qint32 bufferSize = AVCODEC_MAX_AUDIO_FRAME_SIZE; 0779 0780 int outSize = 0; 0781 0782 int audioStream = 0; 0783 int decoderRet = 0; 0784 0785 bool isOk = true; 0786 0787 if( avformat_open_input( &pFormatCtx, fileName.toLocal8Bit(), NULL, NULL ) < 0 ) 0788 { 0789 warning() << QLatin1String( "Unable to open input file: " ) + fileName; 0790 return 0; 0791 } 0792 0793 if( av_find_stream_info( pFormatCtx ) < 0 ) 0794 { 0795 warning() << QLatin1String( "Unable to find stream info: " ) + fileName; 0796 av_close_input_file( pFormatCtx ); 0797 return 0; 0798 } 0799 0800 audioStream = av_find_best_stream(pFormatCtx, AVMEDIA_TYPE_AUDIO, -1, -1, &pCodec, 0); 0801 if( audioStream < 0 ) 0802 { 0803 warning() << QLatin1String( "Unable to find stream: " ) + fileName; 0804 av_close_input_file( pFormatCtx ); 0805 return 0; 0806 } 0807 0808 if( !pCodec ) 0809 { 0810 warning() << QLatin1String( "Unable to find decoder: " ) + fileName; 0811 av_close_input_file( pFormatCtx ); 0812 return 0; 0813 } 0814 0815 pCodecCtx = pFormatCtx->streams[audioStream]->codec; 0816 0817 if( avcodec_open( pCodecCtx, pCodec ) < 0 ) 0818 { 0819 warning() << QLatin1String( "Unable to open codec " ) + fileName; 0820 av_close_input_file( pFormatCtx ); 0821 return 0; 0822 } 0823 0824 streamTimeBase = pFormatCtx->streams[audioStream]->time_base; 0825 0826 data->setSampleRate( pCodecCtx->sample_rate ); 0827 data->setChannels( ( pCodecCtx->channels > 1 )? 1 : 0 ); 0828 0829 av_init_packet( &avpkt ); 0830 while( !av_read_frame( pFormatCtx, &packet ) && isOk ) 0831 { 0832 if( packet.stream_index == audioStream ) 0833 { 0834 avpkt.size = packet.size; 0835 avpkt.data = packet.data; 0836 while( avpkt.size > 0 ) 0837 { 0838 if( bufferSize < qMax( AVCODEC_MAX_AUDIO_FRAME_SIZE, avpkt.size*2 ) ) 0839 { 0840 bufferSize = qMax( AVCODEC_MAX_AUDIO_FRAME_SIZE, avpkt.size*2 ); 0841 delete [] buffer; 0842 buffer = new qint8[bufferSize+FF_INPUT_BUFFER_PADDING_SIZE]; 0843 } 0844 0845 outSize = bufferSize; 0846 decoderRet = avcodec_decode_audio3( pCodecCtx, ( qint16 * )buffer, &outSize, &avpkt ); 0847 if( decoderRet < 0 ) 0848 { 0849 warning() << "Error while decoding."; 0850 isOk = false; 0851 break; 0852 } 0853 0854 if( outSize > 0 ) 0855 { 0856 data->appendData( ( const quint8 *)buffer, outSize ); 0857 } 0858 0859 avpkt.size -= decoderRet; 0860 avpkt.data += decoderRet; 0861 } 0862 0863 data->addTime( av_rescale_q( packet.duration, streamTimeBase, localTimeBase ) ); 0864 } 0865 0866 av_free_packet( &packet ); 0867 0868 if( data->duration() >= length ) 0869 break; 0870 } 0871 0872 delete [] buffer; 0873 0874 av_free_packet( &avpkt ); 0875 0876 avcodec_close( pCodecCtx ); 0877 av_close_input_file( pFormatCtx ); 0878 0879 return data->duration(); 0880 } 0881 #else 0882 { 0883 Q_UNUSED( fileName ) 0884 Q_UNUSED( data ) 0885 0886 warning() << QLatin1String( "Unsupported ffmpeg version. Decoding is abandoned." ); 0887 0888 return 0; 0889 } 0890 #endif 0891 0892