From b64af9a221c1df4853ab7c7766d5f956c61b8765 Mon Sep 17 00:00:00 2001 From: Andreas Huber Date: Wed, 23 Jun 2010 11:11:58 -0700 Subject: [PATCH] Fix a number of timestamp mismatches in the mp3 extractor and decoder that would lead to invalid reporting of the current playback time for mono and/or non-44100 kHz mp3s. Change-Id: I11abc05b62a958ffbc99ca997cd184a2f2199352 related-to-bug: 2667479 --- media/libstagefright/MP3Extractor.cpp | 5 +- .../codecs/mp3dec/MP3Decoder.cpp | 57 ++++++++++--------- media/libstagefright/include/MP3Decoder.h | 7 ++- 3 files changed, 39 insertions(+), 30 deletions(-) diff --git a/media/libstagefright/MP3Extractor.cpp b/media/libstagefright/MP3Extractor.cpp index f9251e1c8f446..69c3a72f55703 100644 --- a/media/libstagefright/MP3Extractor.cpp +++ b/media/libstagefright/MP3Extractor.cpp @@ -634,6 +634,7 @@ status_t MP3Source::read( } size_t frame_size; + int bitrate; for (;;) { ssize_t n = mDataSource->readAt(mCurrentPos, buffer->data(), 4); if (n < 4) { @@ -646,7 +647,7 @@ status_t MP3Source::read( uint32_t header = U32_AT((const uint8_t *)buffer->data()); if ((header & kMask) == (mFixedHeader & kMask) - && get_mp3_frame_size(header, &frame_size)) { + && get_mp3_frame_size(header, &frame_size, NULL, NULL, &bitrate)) { break; } @@ -683,7 +684,7 @@ status_t MP3Source::read( buffer->meta_data()->setInt64(kKeyTime, mCurrentTimeUs); mCurrentPos += frame_size; - mCurrentTimeUs += 1152 * 1000000 / 44100; + mCurrentTimeUs += frame_size * 8000ll / bitrate; *out = buffer; diff --git a/media/libstagefright/codecs/mp3dec/MP3Decoder.cpp b/media/libstagefright/codecs/mp3dec/MP3Decoder.cpp index efcb4764c5538..f40bd11f1e222 100644 --- a/media/libstagefright/codecs/mp3dec/MP3Decoder.cpp +++ b/media/libstagefright/codecs/mp3dec/MP3Decoder.cpp @@ -27,13 +27,35 @@ namespace android { MP3Decoder::MP3Decoder(const sp &source) : mSource(source), + mNumChannels(0), mStarted(false), mBufferGroup(NULL), mConfig(new tPVMP3DecoderExternal), mDecoderBuf(NULL), mAnchorTimeUs(0), - mNumSamplesOutput(0), + mNumFramesOutput(0), mInputBuffer(NULL) { + init(); +} + +void MP3Decoder::init() { + sp srcFormat = mSource->getFormat(); + + int32_t sampleRate; + CHECK(srcFormat->findInt32(kKeyChannelCount, &mNumChannels)); + CHECK(srcFormat->findInt32(kKeySampleRate, &sampleRate)); + + mMeta = new MetaData; + mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW); + mMeta->setInt32(kKeyChannelCount, mNumChannels); + mMeta->setInt32(kKeySampleRate, sampleRate); + + int64_t durationUs; + if (srcFormat->findInt64(kKeyDuration, &durationUs)) { + mMeta->setInt64(kKeyDuration, durationUs); + } + + mMeta->setCString(kKeyDecoderComponent, "MP3Decoder"); } MP3Decoder::~MP3Decoder() { @@ -62,7 +84,7 @@ status_t MP3Decoder::start(MetaData *params) { mSource->start(); mAnchorTimeUs = 0; - mNumSamplesOutput = 0; + mNumFramesOutput = 0; mStarted = true; return OK; @@ -90,26 +112,7 @@ status_t MP3Decoder::stop() { } sp MP3Decoder::getFormat() { - sp srcFormat = mSource->getFormat(); - - int32_t numChannels; - int32_t sampleRate; - CHECK(srcFormat->findInt32(kKeyChannelCount, &numChannels)); - CHECK(srcFormat->findInt32(kKeySampleRate, &sampleRate)); - - sp meta = new MetaData; - meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW); - meta->setInt32(kKeyChannelCount, numChannels); - meta->setInt32(kKeySampleRate, sampleRate); - - int64_t durationUs; - if (srcFormat->findInt64(kKeyDuration, &durationUs)) { - meta->setInt64(kKeyDuration, durationUs); - } - - meta->setCString(kKeyDecoderComponent, "MP3Decoder"); - - return meta; + return mMeta; } status_t MP3Decoder::read( @@ -122,7 +125,7 @@ status_t MP3Decoder::read( if (options && options->getSeekTo(&seekTimeUs)) { CHECK(seekTimeUs >= 0); - mNumSamplesOutput = 0; + mNumFramesOutput = 0; if (mInputBuffer) { mInputBuffer->release(); @@ -142,7 +145,7 @@ status_t MP3Decoder::read( int64_t timeUs; if (mInputBuffer->meta_data()->findInt64(kKeyTime, &timeUs)) { mAnchorTimeUs = timeUs; - mNumSamplesOutput = 0; + mNumFramesOutput = 0; } else { // We must have a new timestamp after seeking. CHECK(seekTimeUs < 0); @@ -179,7 +182,7 @@ status_t MP3Decoder::read( // This is recoverable, just ignore the current frame and // play silence instead. - memset(buffer->data(), 0, mConfig->outputFrameSize); + memset(buffer->data(), 0, mConfig->outputFrameSize * sizeof(int16_t)); mConfig->inputBufferUsedLength = mInputBuffer->range_length(); } @@ -198,9 +201,9 @@ status_t MP3Decoder::read( buffer->meta_data()->setInt64( kKeyTime, mAnchorTimeUs - + (mNumSamplesOutput * 1000000) / mConfig->samplingRate); + + (mNumFramesOutput * 1000000) / mConfig->samplingRate); - mNumSamplesOutput += mConfig->outputFrameSize / sizeof(int16_t); + mNumFramesOutput += mConfig->outputFrameSize / mNumChannels; *out = buffer; diff --git a/media/libstagefright/include/MP3Decoder.h b/media/libstagefright/include/MP3Decoder.h index 88aa4c602d61d..4086fb603b539 100644 --- a/media/libstagefright/include/MP3Decoder.h +++ b/media/libstagefright/include/MP3Decoder.h @@ -42,6 +42,9 @@ protected: private: sp mSource; + sp mMeta; + int32_t mNumChannels; + bool mStarted; MediaBufferGroup *mBufferGroup; @@ -49,10 +52,12 @@ private: tPVMP3DecoderExternal *mConfig; void *mDecoderBuf; int64_t mAnchorTimeUs; - int64_t mNumSamplesOutput; + int64_t mNumFramesOutput; MediaBuffer *mInputBuffer; + void init(); + MP3Decoder(const MP3Decoder &); MP3Decoder &operator=(const MP3Decoder &); };