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
This commit is contained in:
@@ -634,6 +634,7 @@ status_t MP3Source::read(
|
|||||||
}
|
}
|
||||||
|
|
||||||
size_t frame_size;
|
size_t frame_size;
|
||||||
|
int bitrate;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
ssize_t n = mDataSource->readAt(mCurrentPos, buffer->data(), 4);
|
ssize_t n = mDataSource->readAt(mCurrentPos, buffer->data(), 4);
|
||||||
if (n < 4) {
|
if (n < 4) {
|
||||||
@@ -646,7 +647,7 @@ status_t MP3Source::read(
|
|||||||
uint32_t header = U32_AT((const uint8_t *)buffer->data());
|
uint32_t header = U32_AT((const uint8_t *)buffer->data());
|
||||||
|
|
||||||
if ((header & kMask) == (mFixedHeader & kMask)
|
if ((header & kMask) == (mFixedHeader & kMask)
|
||||||
&& get_mp3_frame_size(header, &frame_size)) {
|
&& get_mp3_frame_size(header, &frame_size, NULL, NULL, &bitrate)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -683,7 +684,7 @@ status_t MP3Source::read(
|
|||||||
buffer->meta_data()->setInt64(kKeyTime, mCurrentTimeUs);
|
buffer->meta_data()->setInt64(kKeyTime, mCurrentTimeUs);
|
||||||
|
|
||||||
mCurrentPos += frame_size;
|
mCurrentPos += frame_size;
|
||||||
mCurrentTimeUs += 1152 * 1000000 / 44100;
|
mCurrentTimeUs += frame_size * 8000ll / bitrate;
|
||||||
|
|
||||||
*out = buffer;
|
*out = buffer;
|
||||||
|
|
||||||
|
|||||||
@@ -27,13 +27,35 @@ namespace android {
|
|||||||
|
|
||||||
MP3Decoder::MP3Decoder(const sp<MediaSource> &source)
|
MP3Decoder::MP3Decoder(const sp<MediaSource> &source)
|
||||||
: mSource(source),
|
: mSource(source),
|
||||||
|
mNumChannels(0),
|
||||||
mStarted(false),
|
mStarted(false),
|
||||||
mBufferGroup(NULL),
|
mBufferGroup(NULL),
|
||||||
mConfig(new tPVMP3DecoderExternal),
|
mConfig(new tPVMP3DecoderExternal),
|
||||||
mDecoderBuf(NULL),
|
mDecoderBuf(NULL),
|
||||||
mAnchorTimeUs(0),
|
mAnchorTimeUs(0),
|
||||||
mNumSamplesOutput(0),
|
mNumFramesOutput(0),
|
||||||
mInputBuffer(NULL) {
|
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() {
|
MP3Decoder::~MP3Decoder() {
|
||||||
@@ -62,7 +84,7 @@ status_t MP3Decoder::start(MetaData *params) {
|
|||||||
mSource->start();
|
mSource->start();
|
||||||
|
|
||||||
mAnchorTimeUs = 0;
|
mAnchorTimeUs = 0;
|
||||||
mNumSamplesOutput = 0;
|
mNumFramesOutput = 0;
|
||||||
mStarted = true;
|
mStarted = true;
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
@@ -90,26 +112,7 @@ status_t MP3Decoder::stop() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sp<MetaData> MP3Decoder::getFormat() {
|
sp<MetaData> MP3Decoder::getFormat() {
|
||||||
sp<MetaData> srcFormat = mSource->getFormat();
|
return mMeta;
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t MP3Decoder::read(
|
status_t MP3Decoder::read(
|
||||||
@@ -122,7 +125,7 @@ status_t MP3Decoder::read(
|
|||||||
if (options && options->getSeekTo(&seekTimeUs)) {
|
if (options && options->getSeekTo(&seekTimeUs)) {
|
||||||
CHECK(seekTimeUs >= 0);
|
CHECK(seekTimeUs >= 0);
|
||||||
|
|
||||||
mNumSamplesOutput = 0;
|
mNumFramesOutput = 0;
|
||||||
|
|
||||||
if (mInputBuffer) {
|
if (mInputBuffer) {
|
||||||
mInputBuffer->release();
|
mInputBuffer->release();
|
||||||
@@ -142,7 +145,7 @@ status_t MP3Decoder::read(
|
|||||||
int64_t timeUs;
|
int64_t timeUs;
|
||||||
if (mInputBuffer->meta_data()->findInt64(kKeyTime, &timeUs)) {
|
if (mInputBuffer->meta_data()->findInt64(kKeyTime, &timeUs)) {
|
||||||
mAnchorTimeUs = timeUs;
|
mAnchorTimeUs = timeUs;
|
||||||
mNumSamplesOutput = 0;
|
mNumFramesOutput = 0;
|
||||||
} else {
|
} else {
|
||||||
// We must have a new timestamp after seeking.
|
// We must have a new timestamp after seeking.
|
||||||
CHECK(seekTimeUs < 0);
|
CHECK(seekTimeUs < 0);
|
||||||
@@ -179,7 +182,7 @@ status_t MP3Decoder::read(
|
|||||||
|
|
||||||
// This is recoverable, just ignore the current frame and
|
// This is recoverable, just ignore the current frame and
|
||||||
// play silence instead.
|
// play silence instead.
|
||||||
memset(buffer->data(), 0, mConfig->outputFrameSize);
|
memset(buffer->data(), 0, mConfig->outputFrameSize * sizeof(int16_t));
|
||||||
mConfig->inputBufferUsedLength = mInputBuffer->range_length();
|
mConfig->inputBufferUsedLength = mInputBuffer->range_length();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -198,9 +201,9 @@ status_t MP3Decoder::read(
|
|||||||
buffer->meta_data()->setInt64(
|
buffer->meta_data()->setInt64(
|
||||||
kKeyTime,
|
kKeyTime,
|
||||||
mAnchorTimeUs
|
mAnchorTimeUs
|
||||||
+ (mNumSamplesOutput * 1000000) / mConfig->samplingRate);
|
+ (mNumFramesOutput * 1000000) / mConfig->samplingRate);
|
||||||
|
|
||||||
mNumSamplesOutput += mConfig->outputFrameSize / sizeof(int16_t);
|
mNumFramesOutput += mConfig->outputFrameSize / mNumChannels;
|
||||||
|
|
||||||
*out = buffer;
|
*out = buffer;
|
||||||
|
|
||||||
|
|||||||
@@ -42,6 +42,9 @@ protected:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
sp<MediaSource> mSource;
|
sp<MediaSource> mSource;
|
||||||
|
sp<MetaData> mMeta;
|
||||||
|
int32_t mNumChannels;
|
||||||
|
|
||||||
bool mStarted;
|
bool mStarted;
|
||||||
|
|
||||||
MediaBufferGroup *mBufferGroup;
|
MediaBufferGroup *mBufferGroup;
|
||||||
@@ -49,10 +52,12 @@ private:
|
|||||||
tPVMP3DecoderExternal *mConfig;
|
tPVMP3DecoderExternal *mConfig;
|
||||||
void *mDecoderBuf;
|
void *mDecoderBuf;
|
||||||
int64_t mAnchorTimeUs;
|
int64_t mAnchorTimeUs;
|
||||||
int64_t mNumSamplesOutput;
|
int64_t mNumFramesOutput;
|
||||||
|
|
||||||
MediaBuffer *mInputBuffer;
|
MediaBuffer *mInputBuffer;
|
||||||
|
|
||||||
|
void init();
|
||||||
|
|
||||||
MP3Decoder(const MP3Decoder &);
|
MP3Decoder(const MP3Decoder &);
|
||||||
MP3Decoder &operator=(const MP3Decoder &);
|
MP3Decoder &operator=(const MP3Decoder &);
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user