From a9e05b911f978dc3f25d4b1e35e51383dc4f9fc7 Mon Sep 17 00:00:00 2001 From: Jason Simmons Date: Wed, 6 Apr 2011 18:16:12 -0700 Subject: In the MP3 extractor, compute timestamps based on sample count instead of byte count. This fixes timestamp accuracy on VBR streams. Change-Id: I73a30309536919cbeb5e5163f2f1340e2b9fa4b1 --- media/libstagefright/MP3Extractor.cpp | 38 +++++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-) (limited to 'media/libstagefright/MP3Extractor.cpp') diff --git a/media/libstagefright/MP3Extractor.cpp b/media/libstagefright/MP3Extractor.cpp index 03ce202..4bdfc6f 100644 --- a/media/libstagefright/MP3Extractor.cpp +++ b/media/libstagefright/MP3Extractor.cpp @@ -48,7 +48,7 @@ static const uint32_t kMask = 0xfffe0c00; bool MP3Extractor::get_mp3_frame_size( uint32_t header, size_t *frame_size, int *out_sampling_rate, int *out_channels, - int *out_bitrate) { + int *out_bitrate, int *out_num_samples) { *frame_size = 0; if (out_sampling_rate) { @@ -63,6 +63,10 @@ bool MP3Extractor::get_mp3_frame_size( *out_bitrate = 0; } + if (out_num_samples) { + *out_num_samples = 1152; + } + if ((header & 0xffe00000) != 0xffe00000) { return false; } @@ -127,6 +131,10 @@ bool MP3Extractor::get_mp3_frame_size( } *frame_size = (12000 * bitrate / sampling_rate + padding) * 4; + + if (out_num_samples) { + *out_num_samples = 384; + } } else { // layer II or III @@ -150,10 +158,17 @@ bool MP3Extractor::get_mp3_frame_size( bitrate = (layer == 2 /* L2 */) ? kBitrateV1L2[bitrate_index - 1] : kBitrateV1L3[bitrate_index - 1]; + + if (out_num_samples) { + *out_num_samples = 1152; + } } else { // V2 (or 2.5) bitrate = kBitrateV2[bitrate_index - 1]; + if (out_num_samples) { + *out_num_samples = 576; + } } if (out_bitrate) { @@ -374,6 +389,9 @@ private: sp mSeeker; MediaBufferGroup *mGroup; + int64_t mBasisTimeUs; + int64_t mSamplesRead; + MP3Source(const MP3Source &); MP3Source &operator=(const MP3Source &); }; @@ -489,7 +507,9 @@ MP3Source::MP3Source( mCurrentTimeUs(0), mStarted(false), mSeeker(seeker), - mGroup(NULL) { + mGroup(NULL), + mBasisTimeUs(0), + mSamplesRead(0) { } MP3Source::~MP3Source() { @@ -509,6 +529,9 @@ status_t MP3Source::start(MetaData *) { mCurrentPos = mFirstFramePos; mCurrentTimeUs = 0; + mBasisTimeUs = mCurrentTimeUs; + mSamplesRead = 0; + mStarted = true; return OK; @@ -552,6 +575,9 @@ status_t MP3Source::read( } else { mCurrentTimeUs = actualSeekTimeUs; } + + mBasisTimeUs = mCurrentTimeUs; + mSamplesRead = 0; } MediaBuffer *buffer; @@ -562,6 +588,8 @@ status_t MP3Source::read( size_t frame_size; int bitrate; + int num_samples; + int sample_rate; for (;;) { ssize_t n = mDataSource->readAt(mCurrentPos, buffer->data(), 4); if (n < 4) { @@ -575,7 +603,7 @@ status_t MP3Source::read( if ((header & kMask) == (mFixedHeader & kMask) && MP3Extractor::get_mp3_frame_size( - header, &frame_size, NULL, NULL, &bitrate)) { + header, &frame_size, &sample_rate, NULL, &bitrate, &num_samples)) { break; } @@ -613,7 +641,9 @@ status_t MP3Source::read( buffer->meta_data()->setInt32(kKeyIsSyncFrame, 1); mCurrentPos += frame_size; - mCurrentTimeUs += frame_size * 8000ll / bitrate; + + mSamplesRead += num_samples; + mCurrentTimeUs = mBasisTimeUs + ((mSamplesRead * 1000000) / sample_rate); *out = buffer; -- cgit v1.1