diff options
| author | trialuser02 <trialuser02@90c681e8-e032-0410-971d-27865f9a5e38> | 2008-08-13 14:10:55 +0000 |
|---|---|---|
| committer | trialuser02 <trialuser02@90c681e8-e032-0410-971d-27865f9a5e38> | 2008-08-13 14:10:55 +0000 |
| commit | b5833f9423ecdc673f653dbb3f4bca6dacc918c1 (patch) | |
| tree | 3ab466ec064339c789fc6f43d15c085659621413 /src/plugins/Input | |
| parent | e16f15ff12eb654d2c09f5a280d28389a3ad74fc (diff) | |
| download | qmmp-b5833f9423ecdc673f653dbb3f4bca6dacc918c1.tar.gz qmmp-b5833f9423ecdc673f653dbb3f4bca6dacc918c1.tar.bz2 qmmp-b5833f9423ecdc673f653dbb3f4bca6dacc918c1.zip | |
imported 0.2 fixes
git-svn-id: http://svn.code.sf.net/p/qmmp-dev/code/trunk/qmmp@495 90c681e8-e032-0410-971d-27865f9a5e38
Diffstat (limited to 'src/plugins/Input')
| -rw-r--r-- | src/plugins/Input/mad/decoder_mad.cpp | 151 | ||||
| -rw-r--r-- | src/plugins/Input/mad/decoder_mad.h | 49 |
2 files changed, 119 insertions, 81 deletions
diff --git a/src/plugins/Input/mad/decoder_mad.cpp b/src/plugins/Input/mad/decoder_mad.cpp index d29781622..7c8cc8f1b 100644 --- a/src/plugins/Input/mad/decoder_mad.cpp +++ b/src/plugins/Input/mad/decoder_mad.cpp @@ -122,9 +122,15 @@ bool DecoderMAD::initialize() if (! findHeader()) { - qDebug("DecoderMAD: Cannot find a valid MPEG header."); + qDebug("DecoderMAD: Can't find a valid MPEG header."); return FALSE; } + mad_stream_buffer(&stream, (unsigned char *) input_buf, input_bytes); + stream.error = MAD_ERROR_NONE; + stream.error = MAD_ERROR_BUFLEN; + mad_frame_mute (&frame); + stream.next_frame = NULL; + stream.sync = 0; configure(freq, channels, 16, bitrate); inited = TRUE; @@ -221,78 +227,116 @@ fail: bool DecoderMAD::findHeader() { - bool result = false; + bool result = FALSE; int count = 0; + bool has_xing = FALSE; + bool is_vbr = FALSE; + mad_timer_t duration = mad_timer_zero; + struct mad_header header; + mad_header_init (&header); - while (1) + while (TRUE) { - if (input_bytes < globalBufferSize) + input_bytes = 0; + if (stream.error == MAD_ERROR_BUFLEN || !stream.buffer) { - int bytes = input()->read(input_buf + input_bytes, - globalBufferSize - input_bytes); - if (bytes <= 0) + size_t remaining = 0; + + if (!stream.next_frame) { - if (bytes == -1) - result = false; - ; - break; + remaining = stream.bufend - stream.next_frame; + memmove (input_buf, stream.next_frame, remaining); } - input_bytes += bytes; - } - mad_stream_buffer(&stream, (unsigned char *) input_buf, input_bytes); + input_bytes = input()->read(input_buf + remaining, globalBufferSize - remaining); - bool done = false; - while (! done) + if (input_bytes <= 0) + break; + + mad_stream_buffer(&stream, (unsigned char *) input_buf + remaining, input_bytes); + stream.error = MAD_ERROR_NONE; + } + + if (mad_header_decode(&header, &stream) == -1) { - if (mad_frame_decode(&frame, &stream) != -1) - done = true; - else if (!MAD_RECOVERABLE(stream.error)) + if (stream.error == MAD_ERROR_BUFLEN) + continue; + else if (MAD_RECOVERABLE(stream.error)) + continue; + else { - qWarning("DecoderMAD: Can't decode frame"); + qDebug ("DecoderMAD: Can't decode header: %s", mad_stream_errorstr(&stream)); break; } - - count++; } + result = TRUE; - findXingHeader(stream.anc_ptr, stream.anc_bitlen); - result = done; - if ((stream.error != MAD_ERROR_BUFLEN)) + if (input()->isSequential()) break; - input_bytes = &input_buf[input_bytes] - (char *) stream.next_frame; - memmove(input_buf, stream.next_frame, input_bytes); - } + count ++; + //try to detect xing header + if (count == 1) + { + frame.header = header; + if (mad_frame_decode(&frame, &stream) != -1 && + findXingHeader(stream.anc_ptr, stream.anc_bitlen)) + { + is_vbr = TRUE; - if (result && count) - { - freq = frame.header.samplerate; - channels = MAD_NCHANNELS(&frame.header); - bitrate = frame.header.bitrate / 1000; - calcLength(&frame.header); - } + qDebug ("DecoderMAD: Xing header detected"); - return result; -} + if (xing.flags & XING_FRAMES) + { + has_xing = TRUE; + count = xing.frames; + break; + } + } + } + //try to detect VBR + if (!is_vbr && !(count > 15)) + { + if (bitrate && header.bitrate != bitrate) + { + qDebug ("DecoderMAD: VBR detected"); + is_vbr = TRUE; + } + else + bitrate = header.bitrate; + } + else if (!is_vbr) + { + qDebug ("DecoderMAD: Fixed rate detected"); + break; + } + mad_timer_add (&duration, header.duration); + } -void DecoderMAD::calcLength(struct mad_header *header) -{ - if (! input() || input()->isSequential()) - return; + if (!result) + return FALSE; - totalTime = 0.; - if (xing.flags & XING_FRAMES) + if (!is_vbr) { - mad_timer_t timer; - - timer = header->duration; - mad_timer_multiply(&timer, xing.frames); - - totalTime = double(mad_timer_count(timer, MAD_UNITS_MILLISECONDS)) / 1000.; + double time = (input()->size() * 8.0) / (header.bitrate); + double timefrac = (double)time - ((long)(time)); + mad_timer_set(&duration, (long)time, (long)(timefrac*100), 100); + } + else if (has_xing) + { + mad_timer_multiply (&header.duration, count); + duration = header.duration; } - else if (header->bitrate > 0) - totalTime = input()->size() * 8 / header->bitrate; + + totalTime = mad_timer_count(duration, MAD_UNITS_SECONDS); + qDebug ("DecoderMAD: Total time: %ld", long(totalTime)); + freq = header.samplerate; + channels = MAD_NCHANNELS(&header); + bitrate = header.bitrate / 1000; + mad_header_finish(&header); + input()->seek(0); + input_bytes = 0; + return TRUE; } double DecoderMAD::lengthInSeconds() @@ -352,7 +396,7 @@ void DecoderMAD::flush(bool final) void DecoderMAD::run() { - int skip_frames = 0; + int skip_frames = 1; //skip first frame mutex()->lock(); if (! inited) @@ -429,6 +473,9 @@ void DecoderMAD::run() { if (mad_frame_decode(&frame, &stream) == -1) { + if (stream.error == MAD_ERROR_LOSTSYNC) + continue; + if (stream.error == MAD_ERROR_BUFLEN) break; diff --git a/src/plugins/Input/mad/decoder_mad.h b/src/plugins/Input/mad/decoder_mad.h index 313af2e0f..f37016657 100644 --- a/src/plugins/Input/mad/decoder_mad.h +++ b/src/plugins/Input/mad/decoder_mad.h @@ -12,7 +12,8 @@ class DecoderMAD; #include <qmmp/decoder.h> #include "decodermadfactory.h" -extern "C" { +extern "C" +{ #include <mad.h> } @@ -20,8 +21,8 @@ extern "C" { class DecoderMAD : public Decoder { public: - DecoderMAD(QObject *parent = 0, DecoderFactory *d = 0, - QIODevice *i = 0, Output *o = 0); + DecoderMAD(QObject *parent = 0, DecoderFactory *d = 0, + QIODevice *i = 0, Output *o = 0); virtual ~DecoderMAD(); // standard decoder API @@ -30,17 +31,6 @@ public: void seek(double); void stop(); - // Equalizer - //bool isEQSupported() const { return TRUE; } - //void setEQEnabled(bool); - //void setEQ(const EqPreset &); - - static const int maxDecodeRetries; - static const int maxFrameSize; - static const int maxFrameCheck; - static const int initialFrameSize; - - private: // thread run function void run(); @@ -53,12 +43,11 @@ private: void deinit(); bool findHeader(); bool findXingHeader(struct mad_bitptr, unsigned int); - void calcLength(struct mad_header *); - bool inited, user_stop, done, finish, derror, eof, useeq; double totalTime, seekTime; int channels; - long bitrate, freq, len; + unsigned long bitrate; + long freq, len; unsigned int bks; mad_fixed_t eqbands[32]; @@ -71,19 +60,21 @@ private: unsigned long output_bytes, output_at, output_size; // MAD decoder - struct { - int flags; - unsigned long frames; - unsigned long bytes; - unsigned char toc[100]; - long scale; + struct + { + int flags; + unsigned long frames; + unsigned long bytes; + unsigned char toc[100]; + long scale; } xing; - enum { - XING_FRAMES = 0x0001, - XING_BYTES = 0x0002, - XING_TOC = 0x0004, - XING_SCALE = 0x0008 + enum + { + XING_FRAMES = 0x0001, + XING_BYTES = 0x0002, + XING_TOC = 0x0004, + XING_SCALE = 0x0008 }; struct mad_stream stream; @@ -92,4 +83,4 @@ private: }; -#endif // __decoder_mad_h +#endif // DECODER_MAD_H |
