12b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber/*
22b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber * Copyright (C) 2012 The Android Open Source Project
32b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber *
42b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
52b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber * you may not use this file except in compliance with the License.
62b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber * You may obtain a copy of the License at
72b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber *
82b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
92b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber *
102b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber * Unless required by applicable law or agreed to in writing, software
112b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
122b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber * See the License for the specific language governing permissions and
142b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber * limitations under the License.
152b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber */
162b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
172b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber//#define LOG_NDEBUG 0
182b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber#define LOG_TAG "SoftAACEncoder"
192b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber#include <utils/Log.h>
202b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
212b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber#include "SoftAACEncoder.h"
222b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
232b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber#include "voAAC.h"
242b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber#include "cmnMemory.h"
252b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
262b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber#include <media/stagefright/foundation/ADebug.h>
272b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber#include <media/stagefright/foundation/hexdump.h>
282b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
292b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Hubernamespace android {
302b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
312b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Hubertemplate<class T>
322b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huberstatic void InitOMXParams(T *params) {
332b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    params->nSize = sizeof(T);
342b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    params->nVersion.s.nVersionMajor = 1;
352b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    params->nVersion.s.nVersionMinor = 0;
362b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    params->nVersion.s.nRevision = 0;
372b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    params->nVersion.s.nStep = 0;
382b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber}
392b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
402b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas HuberSoftAACEncoder::SoftAACEncoder(
412b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        const char *name,
422b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        const OMX_CALLBACKTYPE *callbacks,
432b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        OMX_PTR appData,
442b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        OMX_COMPONENTTYPE **component)
452b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    : SimpleSoftOMXComponent(name, callbacks, appData, component),
462b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber      mEncoderHandle(NULL),
472b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber      mApiHandle(NULL),
482b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber      mMemOperator(NULL),
492b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber      mNumChannels(1),
502b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber      mSampleRate(44100),
512b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber      mBitRate(0),
522b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber      mSentCodecSpecificData(false),
532b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber      mInputSize(0),
542b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber      mInputFrame(NULL),
552b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber      mInputTimeUs(-1ll),
562b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber      mSawInputEOS(false),
572b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber      mSignalledError(false) {
582b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    initPorts();
592b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    CHECK_EQ(initEncoder(), (status_t)OK);
602b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
612b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    setAudioParams();
622b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber}
632b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
642b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas HuberSoftAACEncoder::~SoftAACEncoder() {
652b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    delete[] mInputFrame;
662b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    mInputFrame = NULL;
672b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
682b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    if (mEncoderHandle) {
692b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        CHECK_EQ(VO_ERR_NONE, mApiHandle->Uninit(mEncoderHandle));
702b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        mEncoderHandle = NULL;
712b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    }
722b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
732b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    delete mApiHandle;
742b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    mApiHandle = NULL;
752b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
762b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    delete mMemOperator;
772b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    mMemOperator = NULL;
782b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber}
792b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
802b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Hubervoid SoftAACEncoder::initPorts() {
812b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    OMX_PARAM_PORTDEFINITIONTYPE def;
822b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    InitOMXParams(&def);
832b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
842b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    def.nPortIndex = 0;
852b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    def.eDir = OMX_DirInput;
862b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    def.nBufferCountMin = kNumBuffers;
872b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    def.nBufferCountActual = def.nBufferCountMin;
882b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    def.nBufferSize = kNumSamplesPerFrame * sizeof(int16_t) * 2;
892b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    def.bEnabled = OMX_TRUE;
902b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    def.bPopulated = OMX_FALSE;
912b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    def.eDomain = OMX_PortDomainAudio;
922b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    def.bBuffersContiguous = OMX_FALSE;
932b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    def.nBufferAlignment = 1;
942b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
952b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    def.format.audio.cMIMEType = const_cast<char *>("audio/raw");
962b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    def.format.audio.pNativeRender = NULL;
972b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    def.format.audio.bFlagErrorConcealment = OMX_FALSE;
982b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
992b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
1002b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    addPort(def);
1012b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
1022b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    def.nPortIndex = 1;
1032b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    def.eDir = OMX_DirOutput;
1042b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    def.nBufferCountMin = kNumBuffers;
1052b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    def.nBufferCountActual = def.nBufferCountMin;
1062b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    def.nBufferSize = 8192;
1072b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    def.bEnabled = OMX_TRUE;
1082b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    def.bPopulated = OMX_FALSE;
1092b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    def.eDomain = OMX_PortDomainAudio;
1102b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    def.bBuffersContiguous = OMX_FALSE;
1112b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    def.nBufferAlignment = 2;
1122b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
1132b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    def.format.audio.cMIMEType = const_cast<char *>("audio/aac");
1142b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    def.format.audio.pNativeRender = NULL;
1152b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    def.format.audio.bFlagErrorConcealment = OMX_FALSE;
1162b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    def.format.audio.eEncoding = OMX_AUDIO_CodingAAC;
1172b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
1182b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    addPort(def);
1192b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber}
1202b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
1212b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huberstatus_t SoftAACEncoder::initEncoder() {
1222b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    mApiHandle = new VO_AUDIO_CODECAPI;
1232b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
1242b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    if (VO_ERR_NONE != voGetAACEncAPI(mApiHandle)) {
1252b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        ALOGE("Failed to get api handle");
1262b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        return UNKNOWN_ERROR;
1272b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    }
1282b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
1292b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    mMemOperator = new VO_MEM_OPERATOR;
1302b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    mMemOperator->Alloc = cmnMemAlloc;
1312b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    mMemOperator->Copy = cmnMemCopy;
1322b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    mMemOperator->Free = cmnMemFree;
1332b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    mMemOperator->Set = cmnMemSet;
1342b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    mMemOperator->Check = cmnMemCheck;
1352b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
1362b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    VO_CODEC_INIT_USERDATA userData;
1372b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    memset(&userData, 0, sizeof(userData));
1382b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    userData.memflag = VO_IMF_USERMEMOPERATOR;
1392b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    userData.memData = (VO_PTR) mMemOperator;
1402b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    if (VO_ERR_NONE !=
1412b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            mApiHandle->Init(&mEncoderHandle, VO_AUDIO_CodingAAC, &userData)) {
1422b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        ALOGE("Failed to init AAC encoder");
1432b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        return UNKNOWN_ERROR;
1442b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    }
1452b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
1462b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    return OK;
1472b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber}
1482b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
1492b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas HuberOMX_ERRORTYPE SoftAACEncoder::internalGetParameter(
1502b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        OMX_INDEXTYPE index, OMX_PTR params) {
1512b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    switch (index) {
1522b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        case OMX_IndexParamAudioPortFormat:
1532b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        {
1542b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams =
1552b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                (OMX_AUDIO_PARAM_PORTFORMATTYPE *)params;
1562b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
1572b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            if (formatParams->nPortIndex > 1) {
1582b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                return OMX_ErrorUndefined;
1592b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            }
1602b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
1612b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            if (formatParams->nIndex > 0) {
1622b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                return OMX_ErrorNoMore;
1632b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            }
1642b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
1652b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            formatParams->eEncoding =
1662b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                (formatParams->nPortIndex == 0)
1672b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                    ? OMX_AUDIO_CodingPCM : OMX_AUDIO_CodingAAC;
1682b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
1692b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            return OMX_ErrorNone;
1702b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        }
1712b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
1722b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        case OMX_IndexParamAudioAac:
1732b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        {
1742b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            OMX_AUDIO_PARAM_AACPROFILETYPE *aacParams =
1752b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                (OMX_AUDIO_PARAM_AACPROFILETYPE *)params;
1762b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
1772b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            if (aacParams->nPortIndex != 1) {
1782b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                return OMX_ErrorUndefined;
1792b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            }
1802b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
1812b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            aacParams->nBitRate = mBitRate;
1822b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            aacParams->nAudioBandWidth = 0;
1832b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            aacParams->nAACtools = 0;
1842b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            aacParams->nAACERtools = 0;
1852b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            aacParams->eAACProfile = OMX_AUDIO_AACObjectMain;
1862b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            aacParams->eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4FF;
1872b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            aacParams->eChannelMode = OMX_AUDIO_ChannelModeStereo;
1882b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
1892b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            aacParams->nChannels = mNumChannels;
1902b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            aacParams->nSampleRate = mSampleRate;
1912b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            aacParams->nFrameLength = 0;
1922b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
1932b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            return OMX_ErrorNone;
1942b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        }
1952b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
1962b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        case OMX_IndexParamAudioPcm:
1972b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        {
1982b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
1992b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
2002b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
2012b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            if (pcmParams->nPortIndex != 0) {
2022b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                return OMX_ErrorUndefined;
2032b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            }
2042b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
2052b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            pcmParams->eNumData = OMX_NumericalDataSigned;
2062b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            pcmParams->eEndian = OMX_EndianBig;
2072b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            pcmParams->bInterleaved = OMX_TRUE;
2082b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            pcmParams->nBitPerSample = 16;
2092b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear;
2102b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            pcmParams->eChannelMapping[0] = OMX_AUDIO_ChannelLF;
2112b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            pcmParams->eChannelMapping[1] = OMX_AUDIO_ChannelRF;
2122b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
2132b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            pcmParams->nChannels = mNumChannels;
2142b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            pcmParams->nSamplingRate = mSampleRate;
2152b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
2162b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            return OMX_ErrorNone;
2172b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        }
2182b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
2192b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        default:
2202b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            return SimpleSoftOMXComponent::internalGetParameter(index, params);
2212b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    }
2222b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber}
2232b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
2242b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas HuberOMX_ERRORTYPE SoftAACEncoder::internalSetParameter(
2252b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        OMX_INDEXTYPE index, const OMX_PTR params) {
2262b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    switch (index) {
2272b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        case OMX_IndexParamStandardComponentRole:
2282b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        {
2292b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            const OMX_PARAM_COMPONENTROLETYPE *roleParams =
2302b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                (const OMX_PARAM_COMPONENTROLETYPE *)params;
2312b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
2322b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            if (strncmp((const char *)roleParams->cRole,
2332b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                        "audio_encoder.aac",
2342b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                        OMX_MAX_STRINGNAME_SIZE - 1)) {
2352b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                return OMX_ErrorUndefined;
2362b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            }
2372b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
2382b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            return OMX_ErrorNone;
2392b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        }
2402b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
2412b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        case OMX_IndexParamAudioPortFormat:
2422b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        {
2432b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            const OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams =
2442b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                (const OMX_AUDIO_PARAM_PORTFORMATTYPE *)params;
2452b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
2462b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            if (formatParams->nPortIndex > 1) {
2472b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                return OMX_ErrorUndefined;
2482b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            }
2492b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
2502b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            if (formatParams->nIndex > 0) {
2512b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                return OMX_ErrorNoMore;
2522b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            }
2532b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
2542b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            if ((formatParams->nPortIndex == 0
2552b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                        && formatParams->eEncoding != OMX_AUDIO_CodingPCM)
2562b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                || (formatParams->nPortIndex == 1
2572b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                        && formatParams->eEncoding != OMX_AUDIO_CodingAAC)) {
2582b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                return OMX_ErrorUndefined;
2592b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            }
2602b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
2612b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            return OMX_ErrorNone;
2622b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        }
2632b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
2642b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        case OMX_IndexParamAudioAac:
2652b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        {
2662b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            OMX_AUDIO_PARAM_AACPROFILETYPE *aacParams =
2672b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                (OMX_AUDIO_PARAM_AACPROFILETYPE *)params;
2682b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
2692b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            if (aacParams->nPortIndex != 1) {
2702b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                return OMX_ErrorUndefined;
2712b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            }
2722b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
2732b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            mBitRate = aacParams->nBitRate;
2742b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            mNumChannels = aacParams->nChannels;
2752b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            mSampleRate = aacParams->nSampleRate;
2762b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
2772b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            if (setAudioParams() != OK) {
2782b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                return OMX_ErrorUndefined;
2792b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            }
2802b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
2812b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            return OMX_ErrorNone;
2822b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        }
2832b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
2842b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        case OMX_IndexParamAudioPcm:
2852b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        {
2862b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
2872b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
2882b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
2892b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            if (pcmParams->nPortIndex != 0) {
2902b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                return OMX_ErrorUndefined;
2912b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            }
2922b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
2932b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            mNumChannels = pcmParams->nChannels;
2942b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            mSampleRate = pcmParams->nSamplingRate;
2952b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
2962b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            if (setAudioParams() != OK) {
2972b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                return OMX_ErrorUndefined;
2982b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            }
2992b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
3002b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            return OMX_ErrorNone;
3012b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        }
3022b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
3032b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
3042b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        default:
3052b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            return SimpleSoftOMXComponent::internalSetParameter(index, params);
3062b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    }
3072b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber}
3082b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
3092b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huberstatus_t SoftAACEncoder::setAudioParams() {
3102b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    // We call this whenever sample rate, number of channels or bitrate change
3112b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    // in reponse to setParameter calls.
3122b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
3132b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    ALOGV("setAudioParams: %lu Hz, %lu channels, %lu bps",
3142b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber         mSampleRate, mNumChannels, mBitRate);
3152b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
3162b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    status_t err = setAudioSpecificConfigData();
3172b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
3182b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    if (err != OK) {
3192b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        return err;
3202b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    }
3212b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
3222b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    AACENC_PARAM params;
3232b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    memset(&params, 0, sizeof(params));
3242b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    params.sampleRate = mSampleRate;
3252b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    params.bitRate = mBitRate;
3262b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    params.nChannels = mNumChannels;
3272b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    params.adtsUsed = 0;  // We add adts header in the file writer if needed.
3282b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    if (VO_ERR_NONE != mApiHandle->SetParam(
3292b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                mEncoderHandle, VO_PID_AAC_ENCPARAM,  &params)) {
3302b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        ALOGE("Failed to set AAC encoder parameters");
3312b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        return UNKNOWN_ERROR;
3322b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    }
3332b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
3342b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    return OK;
3352b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber}
3362b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
3372b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huberstatic status_t getSampleRateTableIndex(int32_t sampleRate, int32_t &index) {
3382b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    static const int32_t kSampleRateTable[] = {
3392b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        96000, 88200, 64000, 48000, 44100, 32000,
3402b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        24000, 22050, 16000, 12000, 11025, 8000
3412b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    };
3422b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    const int32_t tableSize =
3432b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        sizeof(kSampleRateTable) / sizeof(kSampleRateTable[0]);
3442b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
3452b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    for (int32_t i = 0; i < tableSize; ++i) {
3462b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        if (sampleRate == kSampleRateTable[i]) {
3472b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            index = i;
3482b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            return OK;
3492b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        }
3502b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    }
3512b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
3522b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    return UNKNOWN_ERROR;
3532b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber}
3542b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
3552b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huberstatus_t SoftAACEncoder::setAudioSpecificConfigData() {
3562b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    // The AAC encoder's audio specific config really only encodes
3572b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    // number of channels and the sample rate (mapped to an index into
3582b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    // a fixed sample rate table).
3592b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
3602b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    int32_t index;
3612b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    status_t err = getSampleRateTableIndex(mSampleRate, index);
3622b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    if (err != OK) {
3632b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        ALOGE("Unsupported sample rate (%lu Hz)", mSampleRate);
3642b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        return err;
3652b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    }
3662b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
3672b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    if (mNumChannels > 2 || mNumChannels <= 0) {
3682b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        ALOGE("Unsupported number of channels(%lu)", mNumChannels);
3692b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        return UNKNOWN_ERROR;
3702b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    }
3712b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
3722b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    // OMX_AUDIO_AACObjectLC
3732b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    mAudioSpecificConfigData[0] = ((0x02 << 3) | (index >> 1));
3742b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    mAudioSpecificConfigData[1] = ((index & 0x01) << 7) | (mNumChannels << 3);
3752b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
3762b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    return OK;
3772b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber}
3782b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
3792b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Hubervoid SoftAACEncoder::onQueueFilled(OMX_U32 portIndex) {
3802b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    if (mSignalledError) {
3812b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        return;
3822b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    }
3832b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
3842b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    List<BufferInfo *> &inQueue = getPortQueue(0);
3852b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    List<BufferInfo *> &outQueue = getPortQueue(1);
3862b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
3872b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    if (!mSentCodecSpecificData) {
3882b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        // The very first thing we want to output is the codec specific
3892b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        // data. It does not require any input data but we will need an
3902b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        // output buffer to store it in.
3912b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
3922b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        if (outQueue.empty()) {
3932b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            return;
3942b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        }
3952b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
3962b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        BufferInfo *outInfo = *outQueue.begin();
3972b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
3982b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        outHeader->nFilledLen = sizeof(mAudioSpecificConfigData);
3992b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        outHeader->nFlags = OMX_BUFFERFLAG_CODECCONFIG;
4002b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
4012b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        uint8_t *out = outHeader->pBuffer + outHeader->nOffset;
4022b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        memcpy(out, mAudioSpecificConfigData, sizeof(mAudioSpecificConfigData));
4032b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
4042b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber#if 0
4052b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        ALOGI("sending codec specific data.");
4062b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        hexdump(out, sizeof(mAudioSpecificConfigData));
4072b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber#endif
4082b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
4092b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        outQueue.erase(outQueue.begin());
4102b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        outInfo->mOwnedByUs = false;
4112b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        notifyFillBufferDone(outHeader);
4122b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
4132b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        mSentCodecSpecificData = true;
4142b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    }
4152b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
4162b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    size_t numBytesPerInputFrame =
4172b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        mNumChannels * kNumSamplesPerFrame * sizeof(int16_t);
4182b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
4192b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    for (;;) {
4202b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        // We do the following until we run out of buffers.
4212b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
4222b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        while (mInputSize < numBytesPerInputFrame) {
4232b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            // As long as there's still input data to be read we
4242b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            // will drain "kNumSamplesPerFrame * mNumChannels" samples
4252b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            // into the "mInputFrame" buffer and then encode those
4262b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            // as a unit into an output buffer.
4272b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
4282b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            if (mSawInputEOS || inQueue.empty()) {
4292b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                return;
4302b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            }
4312b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
4322b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            BufferInfo *inInfo = *inQueue.begin();
4332b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
4342b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
4352b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            const void *inData = inHeader->pBuffer + inHeader->nOffset;
4362b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
4372b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            size_t copy = numBytesPerInputFrame - mInputSize;
4382b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            if (copy > inHeader->nFilledLen) {
4392b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                copy = inHeader->nFilledLen;
4402b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            }
4412b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
4422b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            if (mInputFrame == NULL) {
4432b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                mInputFrame = new int16_t[kNumSamplesPerFrame * mNumChannels];
4442b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            }
4452b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
4462b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            if (mInputSize == 0) {
4472b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                mInputTimeUs = inHeader->nTimeStamp;
4482b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            }
4492b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
4502b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            memcpy((uint8_t *)mInputFrame + mInputSize, inData, copy);
4512b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            mInputSize += copy;
4522b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
4532b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            inHeader->nOffset += copy;
4542b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            inHeader->nFilledLen -= copy;
4552b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
4562b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            // "Time" on the input buffer has in effect advanced by the
4572b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            // number of audio frames we just advanced nOffset by.
4582b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            inHeader->nTimeStamp +=
4592b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                (copy * 1000000ll / mSampleRate)
4602b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                    / (mNumChannels * sizeof(int16_t));
4612b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
4622b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            if (inHeader->nFilledLen == 0) {
4632b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
4642b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                    ALOGV("saw input EOS");
4652b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                    mSawInputEOS = true;
4662b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
4672b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                    // Pad any remaining data with zeroes.
4682b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                    memset((uint8_t *)mInputFrame + mInputSize,
4692b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                           0,
4702b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                           numBytesPerInputFrame - mInputSize);
4712b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
4722b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                    mInputSize = numBytesPerInputFrame;
4732b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                }
4742b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
4752b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                inQueue.erase(inQueue.begin());
4762b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                inInfo->mOwnedByUs = false;
4772b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                notifyEmptyBufferDone(inHeader);
4782b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
4792b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                inData = NULL;
4802b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                inHeader = NULL;
4812b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                inInfo = NULL;
4822b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            }
4832b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        }
4842b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
4852b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        // At this  point we have all the input data necessary to encode
4862b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        // a single frame, all we need is an output buffer to store the result
4872b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        // in.
4882b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
4892b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        if (outQueue.empty()) {
4902b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            return;
4912b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        }
4922b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
4932b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        BufferInfo *outInfo = *outQueue.begin();
4942b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
4952b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
4962b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        VO_CODECBUFFER inputData;
4972b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        memset(&inputData, 0, sizeof(inputData));
4982b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        inputData.Buffer = (unsigned char *)mInputFrame;
4992b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        inputData.Length = numBytesPerInputFrame;
5002b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        CHECK(VO_ERR_NONE ==
5012b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                mApiHandle->SetInputData(mEncoderHandle, &inputData));
5022b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
5032b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        VO_CODECBUFFER outputData;
5042b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        memset(&outputData, 0, sizeof(outputData));
5052b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        VO_AUDIO_OUTPUTINFO outputInfo;
5062b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        memset(&outputInfo, 0, sizeof(outputInfo));
5072b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
5082b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        uint8_t *outPtr = (uint8_t *)outHeader->pBuffer + outHeader->nOffset;
5092b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        size_t outAvailable = outHeader->nAllocLen - outHeader->nOffset;
5102b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
5112b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        VO_U32 ret = VO_ERR_NONE;
5122b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        size_t nOutputBytes = 0;
5132b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        do {
5142b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            outputData.Buffer = outPtr;
5152b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            outputData.Length = outAvailable - nOutputBytes;
5162b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            ret = mApiHandle->GetOutputData(
5172b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                    mEncoderHandle, &outputData, &outputInfo);
5182b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            if (ret == VO_ERR_NONE) {
5192b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                outPtr += outputData.Length;
5202b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                nOutputBytes += outputData.Length;
5212b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            }
5222b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        } while (ret != VO_ERR_INPUT_BUFFER_SMALL);
5232b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
5242b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        outHeader->nFilledLen = nOutputBytes;
5252b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
5262b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        outHeader->nFlags = OMX_BUFFERFLAG_ENDOFFRAME;
5272b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
5282b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        if (mSawInputEOS) {
5292b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            // We also tag this output buffer with EOS if it corresponds
5302b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            // to the final input buffer.
5312b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            outHeader->nFlags = OMX_BUFFERFLAG_EOS;
5322b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        }
5332b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
5342b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        outHeader->nTimeStamp = mInputTimeUs;
5352b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
5362b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber#if 0
5372b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        ALOGI("sending %d bytes of data (time = %lld us, flags = 0x%08lx)",
5382b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber              nOutputBytes, mInputTimeUs, outHeader->nFlags);
5392b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
5402b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        hexdump(outHeader->pBuffer + outHeader->nOffset, outHeader->nFilledLen);
5412b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber#endif
5422b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
5432b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        outQueue.erase(outQueue.begin());
5442b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        outInfo->mOwnedByUs = false;
5452b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        notifyFillBufferDone(outHeader);
5462b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
5472b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        outHeader = NULL;
5482b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        outInfo = NULL;
5492b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
5502b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        mInputSize = 0;
5512b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    }
5522b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber}
5532b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
5542b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber}  // namespace android
5552b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
5562b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huberandroid::SoftOMXComponent *createSoftOMXComponent(
5572b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        const char *name, const OMX_CALLBACKTYPE *callbacks,
5582b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        OMX_PTR appData, OMX_COMPONENTTYPE **component) {
5592b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    return new android::SoftAACEncoder(name, callbacks, appData, component);
5602b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber}
561