am b64af9a2: 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.
Merge commit 'b64af9a221c1df4853ab7c7766d5f956c61b8765' into gingerbread-plus-aosp * commit 'b64af9a221c1df4853ab7c7766d5f956c61b8765': 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.
This commit is contained in:
@@ -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;
|
||||
|
||||
|
||||
@@ -27,13 +27,35 @@ namespace android {
|
||||
|
||||
MP3Decoder::MP3Decoder(const sp<MediaSource> &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<MetaData> 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<MetaData> MP3Decoder::getFormat() {
|
||||
sp<MetaData> srcFormat = mSource->getFormat();
|
||||
|
||||
int32_t numChannels;
|
||||
int32_t sampleRate;
|
||||
CHECK(srcFormat->findInt32(kKeyChannelCount, &numChannels));
|
||||
CHECK(srcFormat->findInt32(kKeySampleRate, &sampleRate));
|
||||
|
||||
sp<MetaData> 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;
|
||||
|
||||
|
||||
@@ -42,6 +42,9 @@ protected:
|
||||
|
||||
private:
|
||||
sp<MediaSource> mSource;
|
||||
sp<MetaData> 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 &);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user