Merge "In the MP3 extractor, compute timestamps based on sample count instead of byte count. This fixes timestamp accuracy on VBR streams."
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 @@
 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 @@
         *out_bitrate = 0;
     }
 
+    if (out_num_samples) {
+        *out_num_samples = 1152;
+    }
+
     if ((header & 0xffe00000) != 0xffe00000) {
         return false;
     }
@@ -127,6 +131,10 @@
         }
 
         *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 @@
             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 @@
     sp<MP3Seeker> mSeeker;
     MediaBufferGroup *mGroup;
 
+    int64_t mBasisTimeUs;
+    int64_t mSamplesRead;
+
     MP3Source(const MP3Source &);
     MP3Source &operator=(const MP3Source &);
 };
@@ -489,7 +507,9 @@
       mCurrentTimeUs(0),
       mStarted(false),
       mSeeker(seeker),
-      mGroup(NULL) {
+      mGroup(NULL),
+      mBasisTimeUs(0),
+      mSamplesRead(0) {
 }
 
 MP3Source::~MP3Source() {
@@ -509,6 +529,9 @@
     mCurrentPos = mFirstFramePos;
     mCurrentTimeUs = 0;
 
+    mBasisTimeUs = mCurrentTimeUs;
+    mSamplesRead = 0;
+
     mStarted = true;
 
     return OK;
@@ -552,6 +575,9 @@
         } else {
             mCurrentTimeUs = actualSeekTimeUs;
         }
+
+        mBasisTimeUs = mCurrentTimeUs;
+        mSamplesRead = 0;
     }
 
     MediaBuffer *buffer;
@@ -562,6 +588,8 @@
 
     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 @@
 
         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 @@
     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;
 
diff --git a/media/libstagefright/include/MP3Extractor.h b/media/libstagefright/include/MP3Extractor.h
index ef71b8f..cf1146b 100644
--- a/media/libstagefright/include/MP3Extractor.h
+++ b/media/libstagefright/include/MP3Extractor.h
@@ -42,7 +42,7 @@
     static bool get_mp3_frame_size(
             uint32_t header, size_t *frame_size,
             int *out_sampling_rate = NULL, int *out_channels = NULL,
-            int *out_bitrate = NULL);
+            int *out_bitrate = NULL, int *out_num_samples = NULL);
 
 private:
     status_t mInitCheck;