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

Commit 2d912dd5 authored by Andreas Huber's avatar Andreas Huber Committed by Android (Google) Code Review
Browse files

Merge "Remove old-style software decoders."

parents bd55ab18 a8ccc501
Loading
Loading
Loading
Loading
+0 −26
Original line number Diff line number Diff line
@@ -3,8 +3,6 @@ include $(CLEAR_VARS)

include frameworks/base/media/libstagefright/codecs/common/Config.mk

BUILD_WITH_SOFTWARE_DECODERS := false

LOCAL_SRC_FILES:=                         \
        ACodec.cpp                        \
        AACExtractor.cpp                  \
@@ -96,26 +94,6 @@ LOCAL_STATIC_LIBRARIES := \
        libstagefright_id3 \
        libFLAC \

ifeq ($(BUILD_WITH_SOFTWARE_DECODERS),true)

LOCAL_SRC_FILES += \
        ThreadedSource.cpp                \

LOCAL_STATIC_LIBRARIES += \
        libstagefright_aacdec \
        libstagefright_amrnbdec \
        libstagefright_amrwbdec \
        libstagefright_avcdec \
        libstagefright_g711dec \
        libstagefright_mp3dec \
        libstagefright_m4vh263dec \
        libstagefright_vorbisdec \
        libstagefright_vpxdec \
        libvpx \

endif


################################################################################

# The following was shamelessly copied from external/webkit/Android.mk and
@@ -177,10 +155,6 @@ LOCAL_SHARED_LIBRARIES += \

LOCAL_CFLAGS += -Wno-multichar

ifeq ($(BUILD_WITH_SOFTWARE_DECODERS),true)
    LOCAL_CFLAGS += -DHAVE_SOFTWARE_DECODERS
endif

LOCAL_MODULE:= libstagefright

include $(BUILD_SHARED_LIBRARY)
+7 −85
Original line number Diff line number Diff line
@@ -18,20 +18,11 @@
#define LOG_TAG "OMXCodec"
#include <utils/Log.h>

#include "include/AACDecoder.h"
#include "include/AACEncoder.h"
#include "include/AMRNBDecoder.h"
#include "include/AMRNBEncoder.h"
#include "include/AMRWBDecoder.h"
#include "include/AMRWBEncoder.h"
#include "include/AVCDecoder.h"
#include "include/AVCEncoder.h"
#include "include/G711Decoder.h"
#include "include/M4vH263Decoder.h"
#include "include/M4vH263Encoder.h"
#include "include/MP3Decoder.h"
#include "include/VorbisDecoder.h"
#include "include/VPXDecoder.h"

#include "include/ESDS.h"

@@ -53,10 +44,6 @@
#include <OMX_Audio.h>
#include <OMX_Component.h>

#if HAVE_SOFTWARE_DECODERS
#include "include/ThreadedSource.h"
#endif

#include "include/avc_utils.h"

namespace android {
@@ -79,24 +66,6 @@ FACTORY_CREATE_ENCODER(AACEncoder)
FACTORY_CREATE_ENCODER(AVCEncoder)
FACTORY_CREATE_ENCODER(M4vH263Encoder)

#if HAVE_SOFTWARE_DECODERS

#define FACTORY_CREATE(name) \
static sp<MediaSource> Make##name(const sp<MediaSource> &source) { \
    return new name(source); \
}

FACTORY_CREATE(AMRNBDecoder)
FACTORY_CREATE(AMRWBDecoder)
FACTORY_CREATE(AACDecoder)
FACTORY_CREATE(AVCDecoder)
FACTORY_CREATE(G711Decoder)
FACTORY_CREATE(MP3Decoder)
FACTORY_CREATE(M4vH263Decoder)
FACTORY_CREATE(VorbisDecoder)
FACTORY_CREATE(VPXDecoder)
#endif

static sp<MediaSource> InstantiateSoftwareEncoder(
        const char *name, const sp<MediaSource> &source,
        const sp<MetaData> &meta) {
@@ -122,40 +91,6 @@ static sp<MediaSource> InstantiateSoftwareEncoder(
    return NULL;
}

static sp<MediaSource> InstantiateSoftwareCodec(
        const char *name, const sp<MediaSource> &source) {
#if HAVE_SOFTWARE_DECODERS
    struct FactoryInfo {
        const char *name;
        sp<MediaSource> (*CreateFunc)(const sp<MediaSource> &);
    };

    static const FactoryInfo kFactoryInfo[] = {
        FACTORY_REF(AMRNBDecoder)
        FACTORY_REF(AMRWBDecoder)
        FACTORY_REF(AACDecoder)
        FACTORY_REF(AVCDecoder)
        FACTORY_REF(G711Decoder)
        FACTORY_REF(MP3Decoder)
        FACTORY_REF(M4vH263Decoder)
        FACTORY_REF(VorbisDecoder)
        FACTORY_REF(VPXDecoder)
    };
    for (size_t i = 0;
         i < sizeof(kFactoryInfo) / sizeof(kFactoryInfo[0]); ++i) {
        if (!strcmp(name, kFactoryInfo[i].name)) {
            if (!strcmp(name, "VPXDecoder")) {
                return new ThreadedSource(
                        (*kFactoryInfo[i].CreateFunc)(source));
            }
            return (*kFactoryInfo[i].CreateFunc)(source);
        }
    }
#endif

    return NULL;
}

#undef FACTORY_REF
#undef FACTORY_CREATE

@@ -163,23 +98,17 @@ static const CodecInfo kDecoderInfo[] = {
    { MEDIA_MIMETYPE_IMAGE_JPEG, "OMX.TI.JPEG.decode" },
//    { MEDIA_MIMETYPE_AUDIO_MPEG, "OMX.TI.MP3.decode" },
    { MEDIA_MIMETYPE_AUDIO_MPEG, "OMX.google.mp3.decoder" },
    { MEDIA_MIMETYPE_AUDIO_MPEG, "MP3Decoder" },
//    { MEDIA_MIMETYPE_AUDIO_AMR_NB, "OMX.TI.AMR.decode" },
//    { MEDIA_MIMETYPE_AUDIO_AMR_NB, "OMX.Nvidia.amr.decoder" },
    { MEDIA_MIMETYPE_AUDIO_AMR_NB, "OMX.google.amrnb.decoder" },
    { MEDIA_MIMETYPE_AUDIO_AMR_NB, "AMRNBDecoder" },
//    { MEDIA_MIMETYPE_AUDIO_AMR_NB, "OMX.Nvidia.amrwb.decoder" },
    { MEDIA_MIMETYPE_AUDIO_AMR_WB, "OMX.TI.WBAMR.decode" },
    { MEDIA_MIMETYPE_AUDIO_AMR_WB, "OMX.google.amrwb.decoder" },
    { MEDIA_MIMETYPE_AUDIO_AMR_WB, "AMRWBDecoder" },
//    { MEDIA_MIMETYPE_AUDIO_AAC, "OMX.Nvidia.aac.decoder" },
    { MEDIA_MIMETYPE_AUDIO_AAC, "OMX.TI.AAC.decode" },
    { MEDIA_MIMETYPE_AUDIO_AAC, "OMX.google.aac.decoder" },
    { MEDIA_MIMETYPE_AUDIO_AAC, "AACDecoder" },
    { MEDIA_MIMETYPE_AUDIO_G711_ALAW, "OMX.google.g711.alaw.decoder" },
    { MEDIA_MIMETYPE_AUDIO_G711_ALAW, "G711Decoder" },
    { MEDIA_MIMETYPE_AUDIO_G711_MLAW, "OMX.google.g711.mlaw.decoder" },
    { MEDIA_MIMETYPE_AUDIO_G711_MLAW, "G711Decoder" },
    { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.TI.DUCATI1.VIDEO.DECODER" },
    { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.Nvidia.mp4.decode" },
    { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.qcom.7x30.video.decoder.mpeg4" },
@@ -187,14 +116,12 @@ static const CodecInfo kDecoderInfo[] = {
    { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.TI.Video.Decoder" },
    { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.SEC.MPEG4.Decoder" },
    { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.google.mpeg4.decoder" },
    { MEDIA_MIMETYPE_VIDEO_MPEG4, "M4vH263Decoder" },
    { MEDIA_MIMETYPE_VIDEO_H263, "OMX.TI.DUCATI1.VIDEO.DECODER" },
    { MEDIA_MIMETYPE_VIDEO_H263, "OMX.Nvidia.h263.decode" },
    { MEDIA_MIMETYPE_VIDEO_H263, "OMX.qcom.7x30.video.decoder.h263" },
    { MEDIA_MIMETYPE_VIDEO_H263, "OMX.qcom.video.decoder.h263" },
    { MEDIA_MIMETYPE_VIDEO_H263, "OMX.SEC.H263.Decoder" },
    { MEDIA_MIMETYPE_VIDEO_H263, "OMX.google.h263.decoder" },
    { MEDIA_MIMETYPE_VIDEO_H263, "M4vH263Decoder" },
    { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.TI.DUCATI1.VIDEO.DECODER" },
    { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.Nvidia.h264.decode" },
    { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.qcom.7x30.video.decoder.avc" },
@@ -203,11 +130,8 @@ static const CodecInfo kDecoderInfo[] = {
    { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.SEC.AVC.Decoder" },
    { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.google.h264.decoder" },
    { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.google.avc.decoder" },
    { MEDIA_MIMETYPE_VIDEO_AVC, "AVCDecoder" },
    { MEDIA_MIMETYPE_AUDIO_VORBIS, "OMX.google.vorbis.decoder" },
    { MEDIA_MIMETYPE_AUDIO_VORBIS, "VorbisDecoder" },
    { MEDIA_MIMETYPE_VIDEO_VPX, "OMX.google.vpx.decoder" },
    { MEDIA_MIMETYPE_VIDEO_VPX, "VPXDecoder" },
    { MEDIA_MIMETYPE_VIDEO_MPEG2, "OMX.Nvidia.mpeg2v.decode" },
};

@@ -518,15 +442,16 @@ sp<MediaSource> OMXCodec::Create(
    for (size_t i = 0; i < matchingCodecs.size(); ++i) {
        componentName = matchingCodecs[i].string();

        sp<MediaSource> softwareCodec = createEncoder?
            InstantiateSoftwareEncoder(componentName, source, meta):
            InstantiateSoftwareCodec(componentName, source);
        if (createEncoder) {
            sp<MediaSource> softwareCodec =
                InstantiateSoftwareEncoder(componentName, source, meta);

            if (softwareCodec != NULL) {
                LOGV("Successfully allocated software codec '%s'", componentName);

                return softwareCodec;
            }
        }

        LOGV("Attempting to allocate OMX node '%s'", componentName);

@@ -4430,12 +4355,9 @@ status_t QueryCodecs(
        if (strncmp(componentName, "OMX.", 4)) {
            // Not an OpenMax component but a software codec.

#if HAVE_SOFTWARE_DECODERS
            results->push();
            CodecCapabilities *caps = &results->editItemAt(results->size() - 1);
            caps->mComponentName = componentName;
#endif

            continue;
        }

+0 −213
Original line number Diff line number Diff line
/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#define LOG_TAG "ThreadedSource"
//#define LOG_NDEBUG 0
#include <utils/Log.h>

#include "include/ThreadedSource.h"

#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/MediaBuffer.h>
#include <media/stagefright/MetaData.h>

namespace android {

static const size_t kMaxQueueSize = 2;

ThreadedSource::ThreadedSource(const sp<MediaSource> &source)
    : mSource(source),
      mReflector(new AHandlerReflector<ThreadedSource>(this)),
      mLooper(new ALooper),
      mStarted(false) {
    mLooper->registerHandler(mReflector);
}

ThreadedSource::~ThreadedSource() {
    if (mStarted) {
        stop();
    }
}

status_t ThreadedSource::start(MetaData *params) {
    CHECK(!mStarted);

    status_t err = mSource->start(params);

    if (err != OK) {
        return err;
    }

    mFinalResult = OK;
    mSeekTimeUs = -1;
    mDecodePending = false;

    Mutex::Autolock autoLock(mLock);
    postDecodeMore_l();

    CHECK_EQ(mLooper->start(), (status_t)OK);

    mStarted = true;

    return OK;
}

status_t ThreadedSource::stop() {
    CHECK(mStarted);

    CHECK_EQ(mLooper->stop(), (status_t)OK);

    Mutex::Autolock autoLock(mLock);
    clearQueue_l();

    status_t err = mSource->stop();

    mStarted = false;

    return err;
}

sp<MetaData> ThreadedSource::getFormat() {
    return mSource->getFormat();
}

status_t ThreadedSource::read(
        MediaBuffer **buffer, const ReadOptions *options) {
    *buffer = NULL;

    Mutex::Autolock autoLock(mLock);

    int64_t seekTimeUs;
    ReadOptions::SeekMode seekMode;
    if (options && options->getSeekTo(&seekTimeUs, &seekMode)) {
        int32_t seekComplete = 0;

        sp<AMessage> msg = new AMessage(kWhatSeek, mReflector->id());
        msg->setInt64("timeUs", seekTimeUs);
        msg->setInt32("mode", seekMode);
        msg->setPointer("complete", &seekComplete);
        msg->post();

        while (!seekComplete) {
            mCondition.wait(mLock);
        }
    }

    while (mQueue.empty() && mFinalResult == OK) {
        mCondition.wait(mLock);
    }

    if (!mQueue.empty()) {
        *buffer = *mQueue.begin();
        mQueue.erase(mQueue.begin());

        if (mFinalResult == OK) {
            postDecodeMore_l();
        }

        return OK;
    }

    return mFinalResult;
}

void ThreadedSource::onMessageReceived(const sp<AMessage> &msg) {
    switch (msg->what()) {
        case kWhatSeek:
        {
            CHECK(msg->findInt64("timeUs", &mSeekTimeUs));
            CHECK_GE(mSeekTimeUs, 0ll);

            int32_t x;
            CHECK(msg->findInt32("mode", &x));
            mSeekMode = (ReadOptions::SeekMode)x;

            int32_t *seekComplete;
            CHECK(msg->findPointer("complete", (void **)&seekComplete));

            Mutex::Autolock autoLock(mLock);
            clearQueue_l();
            mFinalResult = OK;

            *seekComplete = 1;
            mCondition.signal();

            postDecodeMore_l();
            break;
        }

        case kWhatDecodeMore:
        {
            {
                Mutex::Autolock autoLock(mLock);
                mDecodePending = false;

                if (mQueue.size() == kMaxQueueSize) {
                    break;
                }
            }

            MediaBuffer *buffer;
            ReadOptions options;
            if (mSeekTimeUs >= 0) {
                options.setSeekTo(mSeekTimeUs, mSeekMode);
                mSeekTimeUs = -1ll;
            }
            status_t err = mSource->read(&buffer, &options);

            Mutex::Autolock autoLock(mLock);

            if (err != OK) {
                mFinalResult = err;
            } else {
                mQueue.push_back(buffer);

                if (mQueue.size() < kMaxQueueSize) {
                    postDecodeMore_l();
                }
            }

            mCondition.signal();
            break;
        }

        default:
            TRESPASS();
            break;
    }
}

void ThreadedSource::postDecodeMore_l() {
    if (mDecodePending) {
        return;
    }

    mDecodePending = true;
    (new AMessage(kWhatDecodeMore, mReflector->id()))->post();
}

void ThreadedSource::clearQueue_l() {
    while (!mQueue.empty()) {
        MediaBuffer *buffer = *mQueue.begin();
        mQueue.erase(mQueue.begin());

        buffer->release();
        buffer = NULL;
    }
}

}  // namespace android
+0 −335
Original line number Diff line number Diff line
/*
 * Copyright (C) 2009 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

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

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

#include "pvmp4audiodecoder_api.h"

#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/MediaBufferGroup.h>
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MetaData.h>

namespace android {

AACDecoder::AACDecoder(const sp<MediaSource> &source)
    : mSource(source),
      mStarted(false),
      mBufferGroup(NULL),
      mConfig(new tPVMP4AudioDecoderExternal),
      mDecoderBuf(NULL),
      mAnchorTimeUs(0),
      mNumSamplesOutput(0),
      mInputBuffer(NULL) {

    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");

    mInitCheck = initCheck();
}

status_t AACDecoder::initCheck() {
    memset(mConfig, 0, sizeof(tPVMP4AudioDecoderExternal));
    mConfig->outputFormat = OUTPUTFORMAT_16PCM_INTERLEAVED;
    mConfig->aacPlusEnabled = 1;

    // The software decoder doesn't properly support mono output on
    // AACplus files. Always output stereo.
    mConfig->desiredChannels = 2;

    UInt32 memRequirements = PVMP4AudioDecoderGetMemRequirements();
    mDecoderBuf = malloc(memRequirements);

    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;
    size_t size;
    sp<MetaData> meta = mSource->getFormat();
    if (meta->findData(kKeyESDS, &type, &data, &size)) {
        ESDS esds((const char *)data, size);
        CHECK_EQ(esds.InitCheck(), (status_t)OK);

        const void *codec_specific_data;
        size_t codec_specific_data_size;
        esds.getCodecSpecificInfo(
                &codec_specific_data, &codec_specific_data_size);

        mConfig->pInputBuffer = (UChar *)codec_specific_data;
        mConfig->inputBufferCurrentLength = codec_specific_data_size;
        mConfig->inputBufferMaxLength = 0;

        if (PVMP4AudioDecoderConfig(mConfig, mDecoderBuf)
                != MP4AUDEC_SUCCESS) {
            return ERROR_UNSUPPORTED;
        }
    }
    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;
    mNumSamplesOutput = 0;
    mStarted = true;
    mNumDecodedBuffers = 0;
    mUpsamplingFactor = 2;

    return OK;
}

status_t AACDecoder::stop() {
    CHECK(mStarted);

    if (mInputBuffer) {
        mInputBuffer->release();
        mInputBuffer = NULL;
    }

    free(mDecoderBuf);
    mDecoderBuf = NULL;

    delete mBufferGroup;
    mBufferGroup = NULL;

    mSource->stop();

    mStarted = false;

    return OK;
}

sp<MetaData> AACDecoder::getFormat() {
    return mMeta;
}

status_t AACDecoder::read(
        MediaBuffer **out, const ReadOptions *options) {
    status_t err;

    *out = NULL;

    int64_t seekTimeUs;
    ReadOptions::SeekMode mode;
    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
        CHECK(seekTimeUs >= 0);

        mNumSamplesOutput = 0;

        if (mInputBuffer) {
            mInputBuffer->release();
            mInputBuffer = NULL;
        }

        // Make sure that the next buffer output does not still
        // depend on fragments from the last one decoded.
        PVMP4AudioDecoderResetBuffer(mDecoderBuf);
    } else {
        seekTimeUs = -1;
    }

    if (mInputBuffer == NULL) {
        err = mSource->read(&mInputBuffer, options);

        if (err != OK) {
            return err;
        }

        int64_t timeUs;
        if (mInputBuffer->meta_data()->findInt64(kKeyTime, &timeUs)) {
            mAnchorTimeUs = timeUs;
            mNumSamplesOutput = 0;
        } else {
            // We must have a new timestamp after seeking.
            CHECK(seekTimeUs < 0);
        }
    }

    MediaBuffer *buffer;
    CHECK_EQ(mBufferGroup->acquire_buffer(&buffer), (status_t)OK);

    mConfig->pInputBuffer =
        (UChar *)mInputBuffer->data() + mInputBuffer->range_offset();

    mConfig->inputBufferCurrentLength = mInputBuffer->range_length();
    mConfig->inputBufferMaxLength = 0;
    mConfig->inputBufferUsedLength = 0;
    mConfig->remainderBits = 0;

    mConfig->pOutputBuffer = static_cast<Int16 *>(buffer->data());
    mConfig->pOutputBuffer_plus = &mConfig->pOutputBuffer[2048];
    mConfig->repositionFlag = false;

    Int decoderErr = PVMP4AudioDecodeFrame(mConfig, mDecoderBuf);

    /*
     * AAC+/eAAC+ streams can be signalled in two ways: either explicitly
     * or implicitly, according to MPEG4 spec. AAC+/eAAC+ is a dual
     * rate system and the sampling rate in the final output is actually
     * doubled compared with the core AAC decoder sampling rate.
     *
     * Explicit signalling is done by explicitly defining SBR audio object
     * type in the bitstream. Implicit signalling is done by embedding
     * SBR content in AAC extension payload specific to SBR, and hence
     * requires an AAC decoder to perform pre-checks on actual audio frames.
     *
     * Thus, we could not say for sure whether a stream is
     * AAC+/eAAC+ until the first data frame is decoded.
     */
    if (++mNumDecodedBuffers <= 2) {
        LOGV("audio/extended audio object type: %d + %d",
            mConfig->audioObjectType, mConfig->extendedAudioObjectType);
        LOGV("aac+ upsampling factor: %d desired channels: %d",
            mConfig->aacPlusUpsamplingFactor, mConfig->desiredChannels);

        CHECK(mNumDecodedBuffers > 0);

        if (decoderErr != MP4AUDEC_SUCCESS) {
            // If decoding fails this early, the fields in mConfig may
            // not be valid and we cannot recover.

            LOGE("Unable to decode aac content, decoder returned error %d",
                 decoderErr);

            buffer->release();
            buffer = NULL;

            mInputBuffer->release();
            mInputBuffer = NULL;

            return ERROR_UNSUPPORTED;
        }

        if (mNumDecodedBuffers == 1) {
            mUpsamplingFactor = mConfig->aacPlusUpsamplingFactor;
            // 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 Hz, but now is %d Hz",
                        sampleRate, mConfig->samplingRate);
                buffer->release();
                mInputBuffer->release();
                mInputBuffer = NULL;
                return INFO_FORMAT_CHANGED;
            }
        } else {  // mNumDecodedBuffers == 2
            if (mConfig->extendedAudioObjectType == MP4AUDIO_AAC_LC ||
                mConfig->extendedAudioObjectType == MP4AUDIO_LTP) {
                if (mUpsamplingFactor == 2) {
                    // The stream turns out to be not aacPlus mode anyway
                    LOGW("Disable AAC+/eAAC+ since extended audio object type is %d",
                        mConfig->extendedAudioObjectType);
                    mConfig->aacPlusEnabled = 0;
                }
            } else {
                if (mUpsamplingFactor == 1) {
                    // aacPlus mode does not buy us anything, but to cause
                    // 1. CPU load to increase, and
                    // 2. a half speed of decoding
                    LOGW("Disable AAC+/eAAC+ since upsampling factor is 1");
                    mConfig->aacPlusEnabled = 0;
                }
            }
        }
    }

    size_t numOutBytes =
        mConfig->frameLength * sizeof(int16_t) * mConfig->desiredChannels;
    if (mUpsamplingFactor == 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);

        memset(buffer->data(), 0, numOutBytes);

        // Discard input buffer.
        mInputBuffer->release();
        mInputBuffer = NULL;

        // fall through
    }

    buffer->set_range(0, numOutBytes);

    if (mInputBuffer != NULL) {
        mInputBuffer->set_range(
                mInputBuffer->range_offset() + mConfig->inputBufferUsedLength,
                mInputBuffer->range_length() - mConfig->inputBufferUsedLength);

        if (mInputBuffer->range_length() == 0) {
            mInputBuffer->release();
            mInputBuffer = NULL;
        }
    }

    buffer->meta_data()->setInt64(
            kKeyTime,
            mAnchorTimeUs
                + (mNumSamplesOutput * 1000000) / mConfig->samplingRate);

    mNumSamplesOutput += mConfig->frameLength * mUpsamplingFactor;

    *out = buffer;

    return OK;
}

}  // namespace android
+0 −1
Original line number Diff line number Diff line
@@ -143,7 +143,6 @@ LOCAL_SRC_FILES := \
 	unpack_idx.cpp \
 	window_tables_fxp.cpp \
 	pvmp4setaudioconfig.cpp \
        AACDecoder.cpp \

LOCAL_CFLAGS := -DAAC_PLUS -DHQ_SBR -DPARAMETRICSTEREO -DOSCL_IMPORT_REF= -DOSCL_EXPORT_REF= -DOSCL_UNUSED_ARG=

Loading