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

Commit 4c9cd95b authored by Dave Burke's avatar Dave Burke Committed by Android (Google) Code Review
Browse files

Merge "Added support for HE-AAC recording" into jb-dev

parents 0c0abd4a f60c660f
Loading
Loading
Loading
Loading
+2 −3
Original line number Diff line number Diff line
@@ -75,9 +75,8 @@ enum audio_encoder {
    AUDIO_ENCODER_AMR_NB = 1,
    AUDIO_ENCODER_AMR_WB = 2,
    AUDIO_ENCODER_AAC = 3,
    AUDIO_ENCODER_AAC_PLUS = 4,
    AUDIO_ENCODER_EAAC_PLUS = 5,
    AUDIO_ENCODER_AAC_ELD = 6,
    AUDIO_ENCODER_HE_AAC = 4,
    AUDIO_ENCODER_AAC_ELD = 5,

    AUDIO_ENCODER_LIST_END // must be the last - used to validate the audio encoder type
};
+2 −1
Original line number Diff line number Diff line
@@ -44,7 +44,8 @@ const MediaProfiles::NameToTagMap MediaProfiles::sAudioEncoderNameMap[] = {
    {"amrnb",  AUDIO_ENCODER_AMR_NB},
    {"amrwb",  AUDIO_ENCODER_AMR_WB},
    {"aac",    AUDIO_ENCODER_AAC},
    {"aaceld", AUDIO_ENCODER_AAC_ELD},
    {"heaac",  AUDIO_ENCODER_HE_AAC},
    {"aaceld", AUDIO_ENCODER_AAC_ELD}
};

const MediaProfiles::NameToTagMap MediaProfiles::sFileFormatMap[] = {
+10 −2
Original line number Diff line number Diff line
@@ -820,10 +820,15 @@ sp<MediaSource> StagefrightRecorder::createAudioSource() {
            mime = MEDIA_MIMETYPE_AUDIO_AAC;
            encMeta->setInt32(kKeyAACProfile, OMX_AUDIO_AACObjectLC);
            break;
        case AUDIO_ENCODER_HE_AAC:
            mime = MEDIA_MIMETYPE_AUDIO_AAC;
            encMeta->setInt32(kKeyAACProfile, OMX_AUDIO_AACObjectHE);
            break;
        case AUDIO_ENCODER_AAC_ELD:
            mime = MEDIA_MIMETYPE_AUDIO_AAC;
            encMeta->setInt32(kKeyAACProfile, OMX_AUDIO_AACObjectELD);
            break;

        default:
            ALOGE("Unknown audio encoder: %d", mAudioEncoder);
            return NULL;
@@ -844,7 +849,6 @@ sp<MediaSource> StagefrightRecorder::createAudioSource() {

    OMXClient client;
    CHECK_EQ(client.connect(), (status_t)OK);

    sp<MediaSource> audioEncoder =
        OMXCodec::Create(client.interface(), encMeta,
                         true /* createEncoder */, audioSource);
@@ -859,6 +863,7 @@ status_t StagefrightRecorder::startAACRecording() {
    CHECK_EQ(mOutputFormat, OUTPUT_FORMAT_AAC_ADTS);

    CHECK(mAudioEncoder == AUDIO_ENCODER_AAC ||
          mAudioEncoder == AUDIO_ENCODER_HE_AAC ||
          mAudioEncoder == AUDIO_ENCODER_AAC_ELD);
    CHECK(mAudioSource != AUDIO_SOURCE_CNT);

@@ -977,7 +982,9 @@ status_t StagefrightRecorder::startMPEG2TSRecording() {
    sp<MediaWriter> writer = new MPEG2TSWriter(mOutputFd);

    if (mAudioSource != AUDIO_SOURCE_CNT) {
        if (mAudioEncoder != AUDIO_ENCODER_AAC) {
        if (mAudioEncoder != AUDIO_ENCODER_AAC &&
            mAudioEncoder != AUDIO_ENCODER_HE_AAC &&
            mAudioEncoder != AUDIO_ENCODER_AAC_ELD) {
            return ERROR_UNSUPPORTED;
        }

@@ -1442,6 +1449,7 @@ status_t StagefrightRecorder::setupAudioEncoder(const sp<MediaWriter>& writer) {
        case AUDIO_ENCODER_AMR_NB:
        case AUDIO_ENCODER_AMR_WB:
        case AUDIO_ENCODER_AAC:
        case AUDIO_ENCODER_HE_AAC:
        case AUDIO_ENCODER_AAC_ELD:
            break;

+30 −20
Original line number Diff line number Diff line
@@ -142,9 +142,9 @@ OMX_ERRORTYPE SoftAAC2::internalGetParameter(
                aacParams->nSampleRate = 44100;
                aacParams->nFrameLength = 0;
            } else {
                aacParams->nChannels = mStreamInfo->channelConfig;
                aacParams->nSampleRate = mStreamInfo->aacSampleRate;
                aacParams->nFrameLength = mStreamInfo->aacSamplesPerFrame;
                aacParams->nChannels = mStreamInfo->numChannels;
                aacParams->nSampleRate = mStreamInfo->sampleRate;
                aacParams->nFrameLength = mStreamInfo->frameSize;
            }

            return OMX_ErrorNone;
@@ -175,7 +175,7 @@ OMX_ERRORTYPE SoftAAC2::internalGetParameter(
                pcmParams->nChannels = 1;
                pcmParams->nSamplingRate = 44100;
            } else {
                pcmParams->nChannels = mStreamInfo->channelConfig;
                pcmParams->nChannels = mStreamInfo->numChannels;
                pcmParams->nSamplingRate = mStreamInfo->sampleRate;
            }

@@ -185,6 +185,7 @@ OMX_ERRORTYPE SoftAAC2::internalGetParameter(
        default:
            return SimpleSoftOMXComponent::internalGetParameter(index, params);
    }

}

OMX_ERRORTYPE SoftAAC2::internalSetParameter(
@@ -254,7 +255,6 @@ void SoftAAC2::onQueueFilled(OMX_U32 portIndex) {
    UCHAR* inBuffer[FILEREAD_MAX_LAYERS];
    UINT inBufferLength[FILEREAD_MAX_LAYERS] = {0};
    UINT bytesValid[FILEREAD_MAX_LAYERS] = {0};
    AAC_DECODER_ERROR decoderErr;

    List<BufferInfo *> &inQueue = getPortQueue(0);
    List<BufferInfo *> &outQueue = getPortQueue(1);
@@ -277,7 +277,6 @@ void SoftAAC2::onQueueFilled(OMX_U32 portIndex) {
            notify(OMX_EventError, OMX_ErrorUndefined, decoderErr, NULL);
            return;
        }

        inQueue.erase(inQueue.begin());
        info->mOwnedByUs = false;
        notifyEmptyBufferDone(header);
@@ -303,10 +302,16 @@ void SoftAAC2::onQueueFilled(OMX_U32 portIndex) {
            // the AACDEC_FLUSH flag set
            INT_PCM *outBuffer =
                    reinterpret_cast<INT_PCM *>(outHeader->pBuffer + outHeader->nOffset);
            decoderErr = aacDecoder_DecodeFrame(mAACDecoder,
            AAC_DECODER_ERROR decoderErr = aacDecoder_DecodeFrame(mAACDecoder,
                                                                  outBuffer,
                                                                  outHeader->nAllocLen,
                                                                  AACDEC_FLUSH);
            if (decoderErr != AAC_DEC_OK) {
                mSignalledError = true;
                notify(OMX_EventError, OMX_ErrorUndefined, decoderErr, NULL);
                return;
            }

            outHeader->nFilledLen =
                    mStreamInfo->frameSize * sizeof(int16_t) * mStreamInfo->numChannels;
            outHeader->nFlags = OMX_BUFFERFLAG_EOS;
@@ -352,14 +357,17 @@ void SoftAAC2::onQueueFilled(OMX_U32 portIndex) {
            inBufferLength[0] = inHeader->nFilledLen;
        }


        // Fill and decode
        INT_PCM *outBuffer = reinterpret_cast<INT_PCM *>(outHeader->pBuffer + outHeader->nOffset);
        bytesValid[0] = inBufferLength[0];

        int flags = mInputDiscontinuity ? AACDEC_INTR : 0;
        int prevSampleRate = mStreamInfo->sampleRate;
        decoderErr = aacDecoder_Fill(mAACDecoder,
        int prevNumChannels = mStreamInfo->numChannels;

        AAC_DECODER_ERROR decoderErr = AAC_DEC_NOT_ENOUGH_BITS;
        while (bytesValid[0] > 0 && decoderErr == AAC_DEC_NOT_ENOUGH_BITS) {
            aacDecoder_Fill(mAACDecoder,
                            inBuffer,
                            inBufferLength,
                            bytesValid);
@@ -369,6 +377,7 @@ void SoftAAC2::onQueueFilled(OMX_U32 portIndex) {
                                                outHeader->nAllocLen,
                                                flags);

        }
        mInputDiscontinuity = false;

        /*
@@ -386,7 +395,8 @@ void SoftAAC2::onQueueFilled(OMX_U32 portIndex) {
         * AAC+/eAAC+ until the first data frame is decoded.
         */
        if (mInputBufferCount <= 2) {
            if (mStreamInfo->sampleRate != prevSampleRate) {
            if (mStreamInfo->sampleRate != prevSampleRate ||
                mStreamInfo->numChannels != prevNumChannels) {
                // We're going to want to revisit this input buffer, but
                // may have already advanced the offset. Undo that if
                // necessary.
+24 −7
Original line number Diff line number Diff line
@@ -239,7 +239,6 @@ OMX_ERRORTYPE SoftAACEncoder2::internalSetParameter(
            mBitRate = aacParams->nBitRate;
            mNumChannels = aacParams->nChannels;
            mSampleRate = aacParams->nSampleRate;

            if (aacParams->eAACProfile != OMX_AUDIO_AACObjectNull) {
                mAACProfile = aacParams->eAACProfile;
            }
@@ -262,7 +261,6 @@ OMX_ERRORTYPE SoftAACEncoder2::internalSetParameter(

            mNumChannels = pcmParams->nChannels;
            mSampleRate = pcmParams->nSamplingRate;

            if (setAudioParams() != OK) {
                return OMX_ErrorUndefined;
            }
@@ -275,7 +273,7 @@ OMX_ERRORTYPE SoftAACEncoder2::internalSetParameter(
    }
}

CHANNEL_MODE getChannelMode(OMX_U32 nChannels) {
static CHANNEL_MODE getChannelMode(OMX_U32 nChannels) {
    CHANNEL_MODE chMode = MODE_INVALID;
    switch (nChannels) {
        case 1: chMode = MODE_1; break;
@@ -289,6 +287,19 @@ CHANNEL_MODE getChannelMode(OMX_U32 nChannels) {
    return chMode;
}

static AUDIO_OBJECT_TYPE getAOTFromProfile(OMX_U32 profile) {
    if (profile == OMX_AUDIO_AACObjectLC) {
        return AOT_AAC_LC;
    } else if (profile == OMX_AUDIO_AACObjectHE) {
        return AOT_SBR;
    } else if (profile == OMX_AUDIO_AACObjectELD) {
        return AOT_ER_AAC_ELD;
    } else {
        ALOGW("Unsupported AAC profile - defaulting to AAC-LC");
        return AOT_AAC_LC;
    }
}

status_t SoftAACEncoder2::setAudioParams() {
    // We call this whenever sample rate, number of channels or bitrate change
    // in reponse to setParameter calls.
@@ -297,7 +308,7 @@ status_t SoftAACEncoder2::setAudioParams() {
         mSampleRate, mNumChannels, mBitRate);

    if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_AOT,
            mAACProfile == OMX_AUDIO_AACObjectELD ? AOT_ER_AAC_ELD : AOT_AAC_LC)) {
            getAOTFromProfile(mAACProfile))) {
        ALOGE("Failed to set AAC encoder parameters");
        return UNKNOWN_ERROR;
    }
@@ -341,12 +352,17 @@ void SoftAACEncoder2::onQueueFilled(OMX_U32 portIndex) {
        }

        if (AACENC_OK != aacEncEncode(mAACEncoder, NULL, NULL, NULL, NULL)) {
            ALOGE("Failed to initialize AAC encoder");
            ALOGE("Unable to initialize encoder for profile / sample-rate / bit-rate / channels");
            notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
            mSignalledError = true;
            return;
        }

        OMX_U32 actualBitRate  = aacEncoder_GetParam(mAACEncoder, AACENC_BITRATE);
        if (mBitRate != actualBitRate) {
            ALOGW("Requested bitrate %lu unsupported, using %lu", mBitRate, actualBitRate);
        }

        AACENC_InfoStruct encInfo;
        if (AACENC_OK != aacEncInfo(mAACEncoder, &encInfo)) {
            ALOGE("Failed to get AAC encoder info");
@@ -373,7 +389,7 @@ void SoftAACEncoder2::onQueueFilled(OMX_U32 portIndex) {
    size_t numBytesPerInputFrame =
        mNumChannels * kNumSamplesPerFrame * sizeof(int16_t);

    // BUGBUG: Fraunhofer's decoder chokes on large chunks of AAC-ELD
    // Limit input size so we only get one ELD frame
    if (mAACProfile == OMX_AUDIO_AACObjectELD && numBytesPerInputFrame > 512) {
        numBytesPerInputFrame = 512;
    }
@@ -402,7 +418,7 @@ void SoftAACEncoder2::onQueueFilled(OMX_U32 portIndex) {
            }

            if (mInputFrame == NULL) {
                mInputFrame = new int16_t[kNumSamplesPerFrame * mNumChannels];
                mInputFrame = new int16_t[numBytesPerInputFrame / sizeof(int16_t)];
            }

            if (mInputSize == 0) {
@@ -490,6 +506,7 @@ void SoftAACEncoder2::onQueueFilled(OMX_U32 portIndex) {
        // Encode the mInputFrame, which is treated as a modulo buffer
        AACENC_ERROR encoderErr = AACENC_OK;
        size_t nOutputBytes = 0;

        do {
            memset(&outargs, 0, sizeof(outargs));