Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6bb14e08 authored by James Dong's avatar James Dong Committed by Android (Google) Code Review
Browse files

Merge "Enable the support for decoding audio with AAC+ and eAAC+ features" into gingerbread

parents f99e27da a7c14078
Loading
Loading
Loading
Loading
+61 −45
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
 */

#include "AACDecoder.h"
#define LOG_TAG "AACDecoder"

#include "../../include/ESDS.h"

@@ -36,26 +37,33 @@ AACDecoder::AACDecoder(const sp<MediaSource> &source)
      mAnchorTimeUs(0),
      mNumSamplesOutput(0),
      mInputBuffer(NULL) {
}

AACDecoder::~AACDecoder() {
    if (mStarted) {
        stop();
    }
    sp<MetaData> srcFormat = mSource->getFormat();

    delete mConfig;
    mConfig = NULL;
}
    int32_t sampleRate;
    CHECK(srcFormat->findInt32(kKeySampleRate, &sampleRate));

status_t AACDecoder::start(MetaData *params) {
    CHECK(!mStarted);
    mMeta = new MetaData;
    mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);

    mBufferGroup = new MediaBufferGroup;
    mBufferGroup->add_buffer(new MediaBuffer(2048 * 2));
    // 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");

    mInitCheck = initCheck();
}

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 @@ status_t AACDecoder::start(MetaData *params) {
    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,19 +94,39 @@ status_t AACDecoder::start(MetaData *params) {
        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();

    mAnchorTimeUs = 0;
@@ -127,28 +158,7 @@ status_t AACDecoder::stop() {
}

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 @@ status_t AACDecoder::read(
    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);
+4 −0
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ struct tPVMP4AudioDecoderExternal;
namespace android {

struct MediaBufferGroup;
struct MetaData;

struct AACDecoder : public MediaSource {
    AACDecoder(const sp<MediaSource> &source);
@@ -41,6 +42,7 @@ protected:
    virtual ~AACDecoder();

private:
    sp<MetaData>    mMeta;
    sp<MediaSource> mSource;
    bool mStarted;

@@ -50,9 +52,11 @@ private:
    void *mDecoderBuf;
    int64_t mAnchorTimeUs;
    int64_t mNumSamplesOutput;
    status_t mInitCheck;

    MediaBuffer *mInputBuffer;

    status_t initCheck();
    AACDecoder(const AACDecoder &);
    AACDecoder &operator=(const AACDecoder &);
};