diff options
| -rw-r--r-- | src/plugins/Input/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | src/plugins/Input/Input.pro | 2 | ||||
| -rw-r--r-- | src/plugins/Input/ffmpeg/decoder_ffmpeg.cpp | 256 | ||||
| -rw-r--r-- | src/plugins/Input/ffmpeg/decoder_ffmpeg.h | 36 |
4 files changed, 73 insertions, 223 deletions
diff --git a/src/plugins/Input/CMakeLists.txt b/src/plugins/Input/CMakeLists.txt index b17164880..3c2c97cfb 100644 --- a/src/plugins/Input/CMakeLists.txt +++ b/src/plugins/Input/CMakeLists.txt @@ -29,7 +29,7 @@ add_subdirectory(vorbis) ENDIF(USE_VORBIS AND TAGLIB_FOUND) IF(USE_FFMPEG) -#add_subdirectory(ffmpeg) +add_subdirectory(ffmpeg) ENDIF(USE_FFMPEG) IF(USE_MPC AND TAGLIB_FOUND) diff --git a/src/plugins/Input/Input.pro b/src/plugins/Input/Input.pro index 7cdba20aa..5ba975d6d 100644 --- a/src/plugins/Input/Input.pro +++ b/src/plugins/Input/Input.pro @@ -27,7 +27,7 @@ contains(CONFIG, FLAC_PLUGIN){ } contains(CONFIG, FFMPEG_PLUGIN){ - #SUBDIRS += ffmpeg + SUBDIRS += ffmpeg message(*************************) message(* FFMPEG plugin enabled *) message(*************************) diff --git a/src/plugins/Input/ffmpeg/decoder_ffmpeg.cpp b/src/plugins/Input/ffmpeg/decoder_ffmpeg.cpp index 678aa3ddb..2a1c1a9d4 100644 --- a/src/plugins/Input/ffmpeg/decoder_ffmpeg.cpp +++ b/src/plugins/Input/ffmpeg/decoder_ffmpeg.cpp @@ -21,7 +21,6 @@ #include <QObject> #include <QFile> -#include <qmmp/constants.h> #include <qmmp/buffer.h> #include <qmmp/output.h> #include <qmmp/recycler.h> @@ -33,102 +32,30 @@ DecoderFFmpeg::DecoderFFmpeg(QObject *parent, DecoderFactory *d, Output *o, const QString &path) : Decoder(parent, d, o) { - inited = FALSE; - user_stop = FALSE; - output_buf = 0; - output_bytes = 0; - output_at = 0; - bks = 0; - done = FALSE; - m_finish = FALSE; - freq = 0; - bitrate = 0; - seekTime = -1.0; - m_totalTime = 0.0; - chan = 0; - output_size = 0; + m_bitrate = 0; + seekTime = -1; + m_totalTime = 0; ic = 0; - wma_outbuf = 0; m_path = path; + m_size = 0; } DecoderFFmpeg::~DecoderFFmpeg() { - deinit(); - if (wma_outbuf) - { - delete [] wma_outbuf; - wma_outbuf = 0; - } - if (output_buf) - delete [] output_buf; - output_buf = 0; - + m_bitrate = 0; if (ic) av_close_input_file(ic); + if(m_pkt.data) + av_free_packet(&m_pkt); } - -void DecoderFFmpeg::stop() -{ - user_stop = TRUE; -} - - -void DecoderFFmpeg::flush(bool final) -{ - ulong min = final ? 0 : bks; - - while ((! done && ! m_finish) && output_bytes > min) - { - output()->recycler()->mutex()->lock (); - - while ((! done && ! m_finish) && output()->recycler()->full()) - { - mutex()->unlock(); - output()->recycler()->cond()->wait(output()->recycler()->mutex()); - mutex()->lock (); - done = user_stop; - } - - if (user_stop || m_finish) - { - inited = FALSE; - done = TRUE; - } - else - { - output_bytes -= produceSound(output_buf, output_bytes, bitrate, chan); - output_size += bks; - output_at = output_bytes; - } - - if (output()->recycler()->full()) - { - output()->recycler()->cond()->wakeOne(); - } - - output()->recycler()->mutex()->unlock(); - } -} - - bool DecoderFFmpeg::initialize() { - bks = Buffer::size(); - inited = user_stop = done = m_finish = FALSE; - freq = bitrate = 0; - chan = 0; - output_size = 0; - seekTime = -1.0; + m_bitrate = 0; + seekTime = -1; m_totalTime = 0.0; - if (!output_buf) - output_buf = new char[globalBufferSize]; - output_at = 0; - output_bytes = 0; - avcodec_init(); avcodec_register_all(); av_register_all(); @@ -143,7 +70,7 @@ bool DecoderFFmpeg::initialize() av_find_stream_info(ic); av_read_play(ic); - for (wma_idx = 0; wma_idx < ic->nb_streams; wma_idx++) + for (wma_idx = 0; wma_idx < (int)ic->nb_streams; wma_idx++) { c = ic->streams[wma_idx]->codec; if (c->codec_type == CODEC_TYPE_AUDIO) break; @@ -166,11 +93,7 @@ bool DecoderFFmpeg::initialize() m_totalTime = ic->duration * 1000 / AV_TIME_BASE; configure(c->sample_rate, c->channels, 16); - - bitrate = c->bit_rate; - chan = c->channels; - wma_outbuf = new uint8_t[AVCODEC_MAX_AUDIO_FRAME_SIZE*sizeof(int16_t) + globalBufferSize]; - inited = TRUE; + m_bitrate = c->bit_rate; qDebug("DecoderFFmpeg: initialize succes"); return TRUE; } @@ -178,135 +101,70 @@ bool DecoderFFmpeg::initialize() qint64 DecoderFFmpeg::totalTime() { - if (! inited) - return 0; - return m_totalTime; } -void DecoderFFmpeg::seek(qint64 pos) -{ - seekTime = pos; -} - - -void DecoderFFmpeg::deinit() +int DecoderFFmpeg::bitrate() { - inited = user_stop = done = m_finish = FALSE; - freq = bitrate = 0; - chan = 0; - output_size = 0; + return m_bitrate; } -void DecoderFFmpeg::run() +qint64 DecoderFFmpeg::readAudio(char *audio, qint64 maxSize) { - uint8_t *inbuf_ptr; - int out_size, size; - AVPacket pkt; - - mutex()->lock (); - - if (!inited) + if(seekTime == 1) { - mutex()->unlock(); - return; + if(!m_size) + fillBuffer(); + if(!m_size) + return 0; + while(m_size > 0) + ffmpeg_decode(audio, maxSize); + seekTime = -1; } - mutex()->unlock(); - - while (!done && !m_finish) - { - mutex()->lock (); - // decode - - if (seekTime >= 0.0) - { - int64_t timestamp; - timestamp = int64_t(seekTime)*AV_TIME_BASE/1000; - if (ic->start_time != AV_NOPTS_VALUE) - timestamp += ic->start_time; - av_seek_frame(ic, -1, timestamp, AVSEEK_FLAG_BACKWARD); - avcodec_flush_buffers(c); - seekTime = -1.0; - } - - int l = 0; - if (av_read_frame(ic, &pkt) < 0) - { - m_finish = TRUE; - goto end; - } - size = pkt.size; - inbuf_ptr = pkt.data; - out_size = 0; - - while (size > 0 && (pkt.stream_index == wma_idx)) - { - out_size = AVCODEC_MAX_AUDIO_FRAME_SIZE*sizeof(int16_t); - l = avcodec_decode_audio2(c, (int16_t *)(wma_outbuf), &out_size, inbuf_ptr, size); - - if (l < 0) - goto end; - ffmpeg_out(out_size); - size -= l; - inbuf_ptr += l; - if (pkt.data) - av_free_packet(&pkt); - } - bitrate = c->bit_rate/1024; -end: - if (m_finish) - { - flush(TRUE); - - if (output()) - { - output()->recycler()->mutex()->lock (); - // end of stream - while (! output()->recycler()->empty() && ! user_stop) - { - output()->recycler()->cond()->wakeOne(); - mutex()->unlock(); - output()->recycler()->cond()->wait(output()->recycler()->mutex()); - mutex()->lock (); - } - output()->recycler()->mutex()->unlock(); - } - - done = TRUE; - if (! user_stop) - { - m_finish = TRUE; - } - } + if(!m_size) + fillBuffer(); + if(!m_size) + return 0; + return ffmpeg_decode(audio, maxSize); +} - mutex()->unlock(); +qint64 DecoderFFmpeg::ffmpeg_decode(char *audio, qint64 maxSize) +{ + int out_size = maxSize; + if((m_pkt.stream_index == wma_idx)) + { + int l = avcodec_decode_audio2(c, (int16_t *)(audio), &out_size, m_inbuf_ptr, m_size); + if(l < 0) + return 0; + m_inbuf_ptr += l; + m_size -= l; } + if (!m_size && m_pkt.data) + av_free_packet(&m_pkt); - mutex()->lock (); - if (m_finish) - finish(); - mutex()->unlock(); - deinit(); + return out_size; +} + +void DecoderFFmpeg::seekAudio(qint64 pos) +{ + int64_t timestamp = int64_t(pos)*AV_TIME_BASE/1000; + if (ic->start_time != AV_NOPTS_VALUE) + timestamp += ic->start_time; + av_seek_frame(ic, -1, timestamp, AVSEEK_FLAG_BACKWARD); + avcodec_flush_buffers(c); + seekTime = 1; } -void DecoderFFmpeg::ffmpeg_out(int size) +void DecoderFFmpeg::fillBuffer() { - if (size == 0) - return; - int at = 0; - int to_copy = 0; - while ((size > 0) && !user_stop && (seekTime < 0)) //ape fast seeking hack + if (av_read_frame(ic, &m_pkt) < 0) { - to_copy = qMin(int(globalBufferSize - output_at), int(size) ); - memmove ( (char *) (output_buf + output_at), wma_outbuf + at, to_copy); - at += to_copy; - size -= to_copy; - output_at += to_copy; - output_bytes += to_copy; - if (output()) - flush(); + m_size = 0; + m_inbuf_ptr = 0; } + m_size = m_pkt.size; + m_inbuf_ptr = m_pkt.data; } diff --git a/src/plugins/Input/ffmpeg/decoder_ffmpeg.h b/src/plugins/Input/ffmpeg/decoder_ffmpeg.h index 5c789d24d..bd4dddfb9 100644 --- a/src/plugins/Input/ffmpeg/decoder_ffmpeg.h +++ b/src/plugins/Input/ffmpeg/decoder_ffmpeg.h @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2006-2008 by Ilya Kotov * + * Copyright (C) 2006-2009 by Ilya Kotov * * forkotov02@hotmail.ru * * * * This program is free software; you can redistribute it and/or modify * @@ -51,34 +51,26 @@ public: // Standard Decoder API bool initialize(); qint64 totalTime(); - void seek(qint64); - void stop(); + int bitrate(); private: - // thread run function - void run(); - // helper functions - void flush(bool = FALSE); - void deinit(); - void ffmpeg_out(int size); - bool inited, user_stop; - - // output buffer - char *output_buf; - qint64 output_bytes, output_at; + qint64 readAudio(char *audio, qint64 maxSize); + void seekAudio(qint64 time); + //helper functions + void fillBuffer(); + qint64 ffmpeg_decode(char *audio, qint64 maxSize); AVFormatContext *ic; AVCodecContext *c; - uint wma_st_buff, wma_idx, wma_idx2; - uint8_t *wma_outbuf; + uint wma_st_buff, wma_idx2; + int m_bitrate, wma_idx; + QString m_path; - unsigned int bks; - bool done, m_finish; - long freq, bitrate; - int chan; - qint64 output_size; qint64 m_totalTime, seekTime; - QString m_path; + + AVPacket m_pkt; + uint8_t *m_inbuf_ptr; + int m_size; }; |
