Enable the support for decoding audio with AAC+ and eAAC+ features

bug - 282684

Change-Id: I73c8377af3cc4edd3ee7cea86dc3b1c369fbd78b
diff --git a/media/libstagefright/codecs/aacdec/AACDecoder.cpp b/media/libstagefright/codecs/aacdec/AACDecoder.cpp
index 2bc4448..f3b281f 100644
--- a/media/libstagefright/codecs/aacdec/AACDecoder.cpp
+++ b/media/libstagefright/codecs/aacdec/AACDecoder.cpp
@@ -15,6 +15,7 @@
  */
 
 #include "AACDecoder.h"
+#define LOG_TAG "AACDecoder"
 
 #include "../../include/ESDS.h"
 
@@ -36,26 +37,33 @@
       mAnchorTimeUs(0),
       mNumSamplesOutput(0),
       mInputBuffer(NULL) {
-}
 
-AACDecoder::~AACDecoder() {
-    if (mStarted) {
-        stop();
+    sp<MetaData> srcFormat = mSource->getFormat();
+
+    int32_t sampleRate;
+    CHECK(srcFormat->findInt32(kKeySampleRate, &sampleRate));
+
+    mMeta = new MetaData;
+    mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
+
+    // We'll always output stereo, regardless of how many channels are
+    // present in the input due to decoder limitations.
+    mMeta->setInt32(kKeyChannelCount, 2);
+    mMeta->setInt32(kKeySampleRate, sampleRate);
+
+    int64_t durationUs;
+    if (srcFormat->findInt64(kKeyDuration, &durationUs)) {
+        mMeta->setInt64(kKeyDuration, durationUs);
     }
+    mMeta->setCString(kKeyDecoderComponent, "AACDecoder");
 
-    delete mConfig;
-    mConfig = NULL;
+    mInitCheck = initCheck();
 }
 
-status_t AACDecoder::start(MetaData *params) {
-    CHECK(!mStarted);
-
-    mBufferGroup = new MediaBufferGroup;
-    mBufferGroup->add_buffer(new MediaBuffer(2048 * 2));
-
+status_t AACDecoder::initCheck() {
+    memset(mConfig, 0, sizeof(tPVMP4AudioDecoderExternal));
     mConfig->outputFormat = OUTPUTFORMAT_16PCM_INTERLEAVED;
-    mConfig->aacPlusUpsamplingFactor = 0;
-    mConfig->aacPlusEnabled = false;
+    mConfig->aacPlusEnabled = 1;
 
     // The software decoder doesn't properly support mono output on
     // AACplus files. Always output stereo.
@@ -64,8 +72,11 @@
     UInt32 memRequirements = PVMP4AudioDecoderGetMemRequirements();
     mDecoderBuf = malloc(memRequirements);
 
-    CHECK_EQ(PVMP4AudioDecoderInitLibrary(mConfig, mDecoderBuf),
-             MP4AUDEC_SUCCESS);
+    status_t err = PVMP4AudioDecoderInitLibrary(mConfig, mDecoderBuf);
+    if (err != MP4AUDEC_SUCCESS) {
+        LOGE("Failed to initialize MP4 audio decoder");
+        return UNKNOWN_ERROR;
+    }
 
     uint32_t type;
     const void *data;
@@ -83,18 +94,38 @@
         mConfig->pInputBuffer = (UChar *)codec_specific_data;
         mConfig->inputBufferCurrentLength = codec_specific_data_size;
         mConfig->inputBufferMaxLength = 0;
-        mConfig->inputBufferUsedLength = 0;
-        mConfig->remainderBits = 0;
-
-        mConfig->pOutputBuffer = NULL;
-        mConfig->pOutputBuffer_plus = NULL;
-        mConfig->repositionFlag = false;
 
         if (PVMP4AudioDecoderConfig(mConfig, mDecoderBuf)
                 != 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;
+}
+
+AACDecoder::~AACDecoder() {
+    if (mStarted) {
+        stop();
+    }
+
+    delete mConfig;
+    mConfig = NULL;
+}
+
+status_t AACDecoder::start(MetaData *params) {
+    CHECK(!mStarted);
+
+    mBufferGroup = new MediaBufferGroup;
+    mBufferGroup->add_buffer(new MediaBuffer(4096 * 2));
 
     mSource->start();
 
@@ -127,28 +158,7 @@
 }
 
 sp<MetaData> AACDecoder::getFormat() {
-    sp<MetaData> srcFormat = mSource->getFormat();
-
-    int32_t sampleRate;
-    CHECK(srcFormat->findInt32(kKeySampleRate, &sampleRate));
-
-    sp<MetaData> meta = new MetaData;
-    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
-
-    // We'll always output stereo, regardless of how many channels are
-    // present in the input due to decoder limitations.
-    meta->setInt32(kKeyChannelCount, 2);
-
-    meta->setInt32(kKeySampleRate, sampleRate);
-
-    int64_t durationUs;
-    if (srcFormat->findInt64(kKeyDuration, &durationUs)) {
-        meta->setInt64(kKeyDuration, durationUs);
-    }
-
-    meta->setCString(kKeyDecoderComponent, "AACDecoder");
-
-    return meta;
+    return mMeta;
 }
 
 status_t AACDecoder::read(
@@ -200,13 +210,19 @@
     mConfig->remainderBits = 0;
 
     mConfig->pOutputBuffer = static_cast<Int16 *>(buffer->data());
-    mConfig->pOutputBuffer_plus = NULL;
+    mConfig->pOutputBuffer_plus = &mConfig->pOutputBuffer[2048];
     mConfig->repositionFlag = false;
 
     Int decoderErr = PVMP4AudioDecodeFrame(mConfig, mDecoderBuf);
 
     size_t numOutBytes =
         mConfig->frameLength * sizeof(int16_t) * mConfig->desiredChannels;
+    if (mConfig->aacPlusUpsamplingFactor == 2) {
+        if (mConfig->desiredChannels == 1) {
+            memcpy(&mConfig->pOutputBuffer[1024], &mConfig->pOutputBuffer[2048], numOutBytes * 2);
+        }
+        numOutBytes *= 2;
+    }
 
     if (decoderErr != MP4AUDEC_SUCCESS) {
         LOGW("AAC decoder returned error %d, substituting silence", decoderErr);
diff --git a/media/libstagefright/include/AACDecoder.h b/media/libstagefright/include/AACDecoder.h
index f09addd..200f93c 100644
--- a/media/libstagefright/include/AACDecoder.h
+++ b/media/libstagefright/include/AACDecoder.h
@@ -25,6 +25,7 @@
 namespace android {
 
 struct MediaBufferGroup;
+struct MetaData;
 
 struct AACDecoder : public MediaSource {
     AACDecoder(const sp<MediaSource> &source);
@@ -41,6 +42,7 @@
     virtual ~AACDecoder();
 
 private:
+    sp<MetaData>    mMeta;
     sp<MediaSource> mSource;
     bool mStarted;
 
@@ -50,9 +52,11 @@
     void *mDecoderBuf;
     int64_t mAnchorTimeUs;
     int64_t mNumSamplesOutput;
+    status_t mInitCheck;
 
     MediaBuffer *mInputBuffer;
 
+    status_t initCheck();
     AACDecoder(const AACDecoder &);
     AACDecoder &operator=(const AACDecoder &);
 };