Merge "Fix MPEG4Extractor to extract sampling frequency correctly when SBR is enabled." into gingerbread
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index 0c2f1e6..65d0146 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -1287,6 +1287,11 @@
     uint32_t freqIndex = (csd[0] & 7) << 1 | (csd[1] >> 7);
     int32_t sampleRate = 0;
     int32_t numChannels = 0;
+    uint8_t offset = 0;
+    static uint32_t kSamplingRate[] = {
+        96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
+        16000, 12000, 11025, 8000, 7350
+    };
     if (freqIndex == 15) {
         if (csd_size < 5) {
             return ERROR_MALFORMED;
@@ -1298,11 +1303,8 @@
                         | (csd[4] >> 7);
 
         numChannels = (csd[4] >> 3) & 15;
+        offset = 4;
     } else {
-        static uint32_t kSamplingRate[] = {
-            96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
-            16000, 12000, 11025, 8000, 7350
-        };
 
         if (freqIndex == 13 || freqIndex == 14) {
             return ERROR_MALFORMED;
@@ -1310,6 +1312,66 @@
 
         sampleRate = kSamplingRate[freqIndex];
         numChannels = (csd[1] >> 3) & 15;
+        offset = 1;
+    }
+
+    uint8_t sbrPresentFlag = -1;
+    uint8_t extensionAudioObjectType = 0;
+    if (objectType == 5) {
+        extensionAudioObjectType = objectType;
+        sbrPresentFlag = 1;
+        freqIndex = ((csd[offset] & 7) << 1) | (csd[offset + 1] >> 7);
+        offset += 1;
+        if (freqIndex == 15) {
+            sampleRate = (((csd[offset] & 0x7f) << 17)
+                            | (csd[offset + 1] << 9)
+                            | (csd[offset + 2] << 1)
+                            | (csd[offset + 3] >> 7));
+            offset += 3;
+        }
+        objectType = csd[offset] >> 3;
+    }
+
+    if (((objectType >= 1 && objectType <= 4) ||
+         (objectType >= 6 && objectType <= 7) ||
+         (objectType == 17) ||
+         (objectType >= 19 || objectType <= 23)) &&
+        (0x00 == (csd[offset] & 7)) &&
+        numChannels != 0) {
+
+        // XXX: We are not handling coreCoderDelay,
+        //      program_config_element(),
+        //      extensionFlag, scalable profile, etc.
+        if (objectType != 6 && objectType != 20) {
+            if (objectType != 5 && csd_size - offset >= 2) {
+                uint32_t syncExtensionType =
+                    (csd[offset + 1] << 3) | (csd[offset + 2] >> 5);
+                if (syncExtensionType == 0x2b7) {
+                    extensionAudioObjectType =
+                            csd[offset + 2] & 0x1F;
+                    if (extensionAudioObjectType == 0x05) {
+                        if (csd_size - offset < 3) {
+                            return ERROR_MALFORMED;
+                        }
+                        uint8_t sbrPresentFlag = csd[offset + 3] & 0x80;
+                        if (sbrPresentFlag) {
+                            freqIndex = (csd[offset + 3] & 0x78) >> 3;
+                            if (freqIndex == 15) {
+                                if (csd_size - offset < 6) {
+                                    return ERROR_MALFORMED;
+                                }
+                                sampleRate = (csd[offset + 3] & 0x07) << 21
+                                        | csd[offset + 4] << 13
+                                        | csd[offset + 5] << 5
+                                        | csd[offset + 6] >> 3;
+                            } else {
+                                sampleRate = kSamplingRate[freqIndex];
+                            }
+                        }
+                    }
+                }
+            }
+        }
     }
 
     if (numChannels == 0) {
diff --git a/media/libstagefright/codecs/aacdec/AACDecoder.cpp b/media/libstagefright/codecs/aacdec/AACDecoder.cpp
index f3b281f..8ae1135 100644
--- a/media/libstagefright/codecs/aacdec/AACDecoder.cpp
+++ b/media/libstagefright/codecs/aacdec/AACDecoder.cpp
@@ -99,15 +99,6 @@
                 != MP4AUDEC_SUCCESS) {
             return ERROR_UNSUPPORTED;
         }
-
-        // Check on the sampling rate to see whether it is changed.
-        int32_t sampleRate;
-        CHECK(mMeta->findInt32(kKeySampleRate, &sampleRate));
-        if (mConfig->samplingRate != sampleRate) {
-            mMeta->setInt32(kKeySampleRate, mConfig->samplingRate);
-            LOGW("Sample rate was %d, but now is %d",
-                    sampleRate, mConfig->samplingRate);
-        }
     }
     return OK;
 }
@@ -215,6 +206,19 @@
 
     Int decoderErr = PVMP4AudioDecodeFrame(mConfig, mDecoderBuf);
 
+    // Check on the sampling rate to see whether it is changed.
+    int32_t sampleRate;
+    CHECK(mMeta->findInt32(kKeySampleRate, &sampleRate));
+    if (mConfig->samplingRate != sampleRate) {
+        mMeta->setInt32(kKeySampleRate, mConfig->samplingRate);
+        LOGW("Sample rate was %d, but now is %d",
+                sampleRate, mConfig->samplingRate);
+        buffer->release();
+        mInputBuffer->release();
+        mInputBuffer = NULL;
+        return INFO_FORMAT_CHANGED;
+    }
+
     size_t numOutBytes =
         mConfig->frameLength * sizeof(int16_t) * mConfig->desiredChannels;
     if (mConfig->aacPlusUpsamplingFactor == 2) {