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() {
655443b57cc54f2e46b35246637be26a69e9f493e1Wonsik Kim    onReset();
662b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
672b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    if (mEncoderHandle) {
682b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        CHECK_EQ(VO_ERR_NONE, mApiHandle->Uninit(mEncoderHandle));
692b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        mEncoderHandle = NULL;
702b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    }
712b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
722b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    delete mApiHandle;
732b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    mApiHandle = NULL;
742b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
752b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    delete mMemOperator;
762b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    mMemOperator = NULL;
772b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber}
782b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
792b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Hubervoid SoftAACEncoder::initPorts() {
802b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    OMX_PARAM_PORTDEFINITIONTYPE def;
812b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    InitOMXParams(&def);
822b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
832b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    def.nPortIndex = 0;
842b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    def.eDir = OMX_DirInput;
852b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    def.nBufferCountMin = kNumBuffers;
862b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    def.nBufferCountActual = def.nBufferCountMin;
872b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    def.nBufferSize = kNumSamplesPerFrame * sizeof(int16_t) * 2;
882b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    def.bEnabled = OMX_TRUE;
892b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    def.bPopulated = OMX_FALSE;
902b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    def.eDomain = OMX_PortDomainAudio;
912b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    def.bBuffersContiguous = OMX_FALSE;
922b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    def.nBufferAlignment = 1;
932b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
942b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    def.format.audio.cMIMEType = const_cast<char *>("audio/raw");
952b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    def.format.audio.pNativeRender = NULL;
962b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    def.format.audio.bFlagErrorConcealment = OMX_FALSE;
972b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
982b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
992b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    addPort(def);
1002b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
1012b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    def.nPortIndex = 1;
1022b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    def.eDir = OMX_DirOutput;
1032b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    def.nBufferCountMin = kNumBuffers;
1042b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    def.nBufferCountActual = def.nBufferCountMin;
1052b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    def.nBufferSize = 8192;
1062b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    def.bEnabled = OMX_TRUE;
1072b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    def.bPopulated = OMX_FALSE;
1082b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    def.eDomain = OMX_PortDomainAudio;
1092b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    def.bBuffersContiguous = OMX_FALSE;
1102b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    def.nBufferAlignment = 2;
1112b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
1122b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    def.format.audio.cMIMEType = const_cast<char *>("audio/aac");
1132b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    def.format.audio.pNativeRender = NULL;
1142b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    def.format.audio.bFlagErrorConcealment = OMX_FALSE;
1152b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    def.format.audio.eEncoding = OMX_AUDIO_CodingAAC;
1162b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
1172b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    addPort(def);
1182b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber}
1192b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
1202b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huberstatus_t SoftAACEncoder::initEncoder() {
1212b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    mApiHandle = new VO_AUDIO_CODECAPI;
1222b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
1232b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    if (VO_ERR_NONE != voGetAACEncAPI(mApiHandle)) {
1242b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        ALOGE("Failed to get api handle");
1252b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        return UNKNOWN_ERROR;
1262b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    }
1272b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
1282b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    mMemOperator = new VO_MEM_OPERATOR;
1292b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    mMemOperator->Alloc = cmnMemAlloc;
1302b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    mMemOperator->Copy = cmnMemCopy;
1312b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    mMemOperator->Free = cmnMemFree;
1322b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    mMemOperator->Set = cmnMemSet;
1332b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    mMemOperator->Check = cmnMemCheck;
1342b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
1352b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    VO_CODEC_INIT_USERDATA userData;
1362b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    memset(&userData, 0, sizeof(userData));
1372b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    userData.memflag = VO_IMF_USERMEMOPERATOR;
1382b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    userData.memData = (VO_PTR) mMemOperator;
1392b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    if (VO_ERR_NONE !=
1402b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            mApiHandle->Init(&mEncoderHandle, VO_AUDIO_CodingAAC, &userData)) {
1412b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        ALOGE("Failed to init AAC encoder");
1422b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        return UNKNOWN_ERROR;
1432b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    }
1442b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
1452b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    return OK;
1462b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber}
1472b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
1482b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas HuberOMX_ERRORTYPE SoftAACEncoder::internalGetParameter(
1492b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        OMX_INDEXTYPE index, OMX_PTR params) {
1502b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    switch (index) {
1512b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        case OMX_IndexParamAudioPortFormat:
1522b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        {
1532b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams =
1542b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                (OMX_AUDIO_PARAM_PORTFORMATTYPE *)params;
1552b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
156423766ca07beb7e3e9cd301385708ca13fcce3e1Marco Nelissen            if (!isValidOMXParam(formatParams)) {
157423766ca07beb7e3e9cd301385708ca13fcce3e1Marco Nelissen                return OMX_ErrorBadParameter;
158423766ca07beb7e3e9cd301385708ca13fcce3e1Marco Nelissen            }
159423766ca07beb7e3e9cd301385708ca13fcce3e1Marco Nelissen
1602b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            if (formatParams->nPortIndex > 1) {
1612b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                return OMX_ErrorUndefined;
1622b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            }
1632b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
1642b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            if (formatParams->nIndex > 0) {
1652b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                return OMX_ErrorNoMore;
1662b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            }
1672b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
1682b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            formatParams->eEncoding =
1692b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                (formatParams->nPortIndex == 0)
1702b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                    ? OMX_AUDIO_CodingPCM : OMX_AUDIO_CodingAAC;
1712b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
1722b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            return OMX_ErrorNone;
1732b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        }
1742b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
1752b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        case OMX_IndexParamAudioAac:
1762b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        {
1772b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            OMX_AUDIO_PARAM_AACPROFILETYPE *aacParams =
1782b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                (OMX_AUDIO_PARAM_AACPROFILETYPE *)params;
1792b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
180423766ca07beb7e3e9cd301385708ca13fcce3e1Marco Nelissen            if (!isValidOMXParam(aacParams)) {
181423766ca07beb7e3e9cd301385708ca13fcce3e1Marco Nelissen                return OMX_ErrorBadParameter;
182423766ca07beb7e3e9cd301385708ca13fcce3e1Marco Nelissen            }
183423766ca07beb7e3e9cd301385708ca13fcce3e1Marco Nelissen
1842b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            if (aacParams->nPortIndex != 1) {
1852b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                return OMX_ErrorUndefined;
1862b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            }
1872b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
1882b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            aacParams->nBitRate = mBitRate;
1892b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            aacParams->nAudioBandWidth = 0;
1902b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            aacParams->nAACtools = 0;
1912b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            aacParams->nAACERtools = 0;
1922b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            aacParams->eAACProfile = OMX_AUDIO_AACObjectMain;
1932b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            aacParams->eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4FF;
1942b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            aacParams->eChannelMode = OMX_AUDIO_ChannelModeStereo;
1952b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
1962b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            aacParams->nChannels = mNumChannels;
1972b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            aacParams->nSampleRate = mSampleRate;
1982b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            aacParams->nFrameLength = 0;
1992b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
2002b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            return OMX_ErrorNone;
2012b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        }
2022b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
2032b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        case OMX_IndexParamAudioPcm:
2042b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        {
2052b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
2062b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
2072b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
208423766ca07beb7e3e9cd301385708ca13fcce3e1Marco Nelissen            if (!isValidOMXParam(pcmParams)) {
209423766ca07beb7e3e9cd301385708ca13fcce3e1Marco Nelissen                return OMX_ErrorBadParameter;
210423766ca07beb7e3e9cd301385708ca13fcce3e1Marco Nelissen            }
211423766ca07beb7e3e9cd301385708ca13fcce3e1Marco Nelissen
2122b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            if (pcmParams->nPortIndex != 0) {
2132b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                return OMX_ErrorUndefined;
2142b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            }
2152b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
2162b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            pcmParams->eNumData = OMX_NumericalDataSigned;
2172b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            pcmParams->eEndian = OMX_EndianBig;
2182b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            pcmParams->bInterleaved = OMX_TRUE;
2192b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            pcmParams->nBitPerSample = 16;
2202b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear;
2212b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            pcmParams->eChannelMapping[0] = OMX_AUDIO_ChannelLF;
2222b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            pcmParams->eChannelMapping[1] = OMX_AUDIO_ChannelRF;
2232b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
2242b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            pcmParams->nChannels = mNumChannels;
2252b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            pcmParams->nSamplingRate = mSampleRate;
2262b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
2272b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            return OMX_ErrorNone;
2282b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        }
2292b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
2302b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        default:
2312b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            return SimpleSoftOMXComponent::internalGetParameter(index, params);
2322b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    }
2332b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber}
2342b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
2352b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas HuberOMX_ERRORTYPE SoftAACEncoder::internalSetParameter(
2362b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        OMX_INDEXTYPE index, const OMX_PTR params) {
2372b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    switch (index) {
2382b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        case OMX_IndexParamStandardComponentRole:
2392b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        {
2402b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            const OMX_PARAM_COMPONENTROLETYPE *roleParams =
2412b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                (const OMX_PARAM_COMPONENTROLETYPE *)params;
2422b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
243423766ca07beb7e3e9cd301385708ca13fcce3e1Marco Nelissen            if (!isValidOMXParam(roleParams)) {
244423766ca07beb7e3e9cd301385708ca13fcce3e1Marco Nelissen                return OMX_ErrorBadParameter;
245423766ca07beb7e3e9cd301385708ca13fcce3e1Marco Nelissen            }
246423766ca07beb7e3e9cd301385708ca13fcce3e1Marco Nelissen
2472b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            if (strncmp((const char *)roleParams->cRole,
2482b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                        "audio_encoder.aac",
2492b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                        OMX_MAX_STRINGNAME_SIZE - 1)) {
2502b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                return OMX_ErrorUndefined;
2512b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            }
2522b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
2532b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            return OMX_ErrorNone;
2542b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        }
2552b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
2562b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        case OMX_IndexParamAudioPortFormat:
2572b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        {
2582b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            const OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams =
2592b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                (const OMX_AUDIO_PARAM_PORTFORMATTYPE *)params;
2602b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
261423766ca07beb7e3e9cd301385708ca13fcce3e1Marco Nelissen            if (!isValidOMXParam(formatParams)) {
262423766ca07beb7e3e9cd301385708ca13fcce3e1Marco Nelissen                return OMX_ErrorBadParameter;
263423766ca07beb7e3e9cd301385708ca13fcce3e1Marco Nelissen            }
264423766ca07beb7e3e9cd301385708ca13fcce3e1Marco Nelissen
2652b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            if (formatParams->nPortIndex > 1) {
2662b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                return OMX_ErrorUndefined;
2672b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            }
2682b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
2692b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            if ((formatParams->nPortIndex == 0
2702b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                        && formatParams->eEncoding != OMX_AUDIO_CodingPCM)
2712b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                || (formatParams->nPortIndex == 1
2722b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                        && formatParams->eEncoding != OMX_AUDIO_CodingAAC)) {
2732b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                return OMX_ErrorUndefined;
2742b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            }
2752b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
2762b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            return OMX_ErrorNone;
2772b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        }
2782b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
2792b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        case OMX_IndexParamAudioAac:
2802b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        {
2812b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            OMX_AUDIO_PARAM_AACPROFILETYPE *aacParams =
2822b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                (OMX_AUDIO_PARAM_AACPROFILETYPE *)params;
2832b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
284423766ca07beb7e3e9cd301385708ca13fcce3e1Marco Nelissen            if (!isValidOMXParam(aacParams)) {
285423766ca07beb7e3e9cd301385708ca13fcce3e1Marco Nelissen                return OMX_ErrorBadParameter;
286423766ca07beb7e3e9cd301385708ca13fcce3e1Marco Nelissen            }
287423766ca07beb7e3e9cd301385708ca13fcce3e1Marco Nelissen
2882b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            if (aacParams->nPortIndex != 1) {
2892b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                return OMX_ErrorUndefined;
2902b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            }
2912b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
2922b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            mBitRate = aacParams->nBitRate;
2932b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            mNumChannels = aacParams->nChannels;
2942b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            mSampleRate = aacParams->nSampleRate;
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        case OMX_IndexParamAudioPcm:
3042b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        {
3052b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
3062b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
3072b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
308423766ca07beb7e3e9cd301385708ca13fcce3e1Marco Nelissen            if (!isValidOMXParam(pcmParams)) {
309423766ca07beb7e3e9cd301385708ca13fcce3e1Marco Nelissen                return OMX_ErrorBadParameter;
310423766ca07beb7e3e9cd301385708ca13fcce3e1Marco Nelissen            }
311423766ca07beb7e3e9cd301385708ca13fcce3e1Marco Nelissen
3122b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            if (pcmParams->nPortIndex != 0) {
3132b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                return OMX_ErrorUndefined;
3142b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            }
3152b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
3162b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            mNumChannels = pcmParams->nChannels;
3172b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            mSampleRate = pcmParams->nSamplingRate;
3182b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
3192b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            if (setAudioParams() != OK) {
3202b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                return OMX_ErrorUndefined;
3212b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            }
3222b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
3232b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            return OMX_ErrorNone;
3242b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        }
3252b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
3262b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
3272b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        default:
3282b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            return SimpleSoftOMXComponent::internalSetParameter(index, params);
3292b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    }
3302b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber}
3312b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
3322b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huberstatus_t SoftAACEncoder::setAudioParams() {
3332b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    // We call this whenever sample rate, number of channels or bitrate change
3342b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    // in reponse to setParameter calls.
3352b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
3362b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    ALOGV("setAudioParams: %lu Hz, %lu channels, %lu bps",
3372b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber         mSampleRate, mNumChannels, mBitRate);
3382b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
3392b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    status_t err = setAudioSpecificConfigData();
3402b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
3412b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    if (err != OK) {
3422b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        return err;
3432b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    }
3442b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
3452b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    AACENC_PARAM params;
3462b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    memset(&params, 0, sizeof(params));
3472b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    params.sampleRate = mSampleRate;
3482b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    params.bitRate = mBitRate;
3492b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    params.nChannels = mNumChannels;
3502b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    params.adtsUsed = 0;  // We add adts header in the file writer if needed.
3512b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    if (VO_ERR_NONE != mApiHandle->SetParam(
3522b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                mEncoderHandle, VO_PID_AAC_ENCPARAM,  &params)) {
3532b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        ALOGE("Failed to set AAC encoder parameters");
3542b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        return UNKNOWN_ERROR;
3552b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    }
3562b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
3572b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    return OK;
3582b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber}
3592b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
3602b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huberstatic status_t getSampleRateTableIndex(int32_t sampleRate, int32_t &index) {
3612b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    static const int32_t kSampleRateTable[] = {
3622b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        96000, 88200, 64000, 48000, 44100, 32000,
3632b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        24000, 22050, 16000, 12000, 11025, 8000
3642b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    };
3652b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    const int32_t tableSize =
3662b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        sizeof(kSampleRateTable) / sizeof(kSampleRateTable[0]);
3672b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
3682b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    for (int32_t i = 0; i < tableSize; ++i) {
3692b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        if (sampleRate == kSampleRateTable[i]) {
3702b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            index = i;
3712b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            return OK;
3722b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        }
3732b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    }
3742b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
3752b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    return UNKNOWN_ERROR;
3762b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber}
3772b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
3782b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huberstatus_t SoftAACEncoder::setAudioSpecificConfigData() {
3792b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    // The AAC encoder's audio specific config really only encodes
3802b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    // number of channels and the sample rate (mapped to an index into
3812b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    // a fixed sample rate table).
3822b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
3832b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    int32_t index;
3842b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    status_t err = getSampleRateTableIndex(mSampleRate, index);
3852b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    if (err != OK) {
3862b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        ALOGE("Unsupported sample rate (%lu Hz)", mSampleRate);
3872b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        return err;
3882b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    }
3892b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
3902b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    if (mNumChannels > 2 || mNumChannels <= 0) {
3912b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        ALOGE("Unsupported number of channels(%lu)", mNumChannels);
3922b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        return UNKNOWN_ERROR;
3932b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    }
3942b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
3952b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    // OMX_AUDIO_AACObjectLC
3962b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    mAudioSpecificConfigData[0] = ((0x02 << 3) | (index >> 1));
3972b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    mAudioSpecificConfigData[1] = ((index & 0x01) << 7) | (mNumChannels << 3);
3982b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
3992b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    return OK;
4002b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber}
4012b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
4022b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Hubervoid SoftAACEncoder::onQueueFilled(OMX_U32 portIndex) {
4032b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    if (mSignalledError) {
4042b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        return;
4052b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    }
4062b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
4072b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    List<BufferInfo *> &inQueue = getPortQueue(0);
4082b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    List<BufferInfo *> &outQueue = getPortQueue(1);
4092b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
4102b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    if (!mSentCodecSpecificData) {
4112b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        // The very first thing we want to output is the codec specific
4122b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        // data. It does not require any input data but we will need an
4132b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        // output buffer to store it in.
4142b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
4152b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        if (outQueue.empty()) {
4162b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            return;
4172b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        }
4182b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
4192b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        BufferInfo *outInfo = *outQueue.begin();
4202b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
4212b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        outHeader->nFilledLen = sizeof(mAudioSpecificConfigData);
4222b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        outHeader->nFlags = OMX_BUFFERFLAG_CODECCONFIG;
4232b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
4242b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        uint8_t *out = outHeader->pBuffer + outHeader->nOffset;
4252b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        memcpy(out, mAudioSpecificConfigData, sizeof(mAudioSpecificConfigData));
4262b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
4272b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber#if 0
4282b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        ALOGI("sending codec specific data.");
4292b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        hexdump(out, sizeof(mAudioSpecificConfigData));
4302b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber#endif
4312b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
4322b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        outQueue.erase(outQueue.begin());
4332b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        outInfo->mOwnedByUs = false;
4342b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        notifyFillBufferDone(outHeader);
4352b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
4362b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        mSentCodecSpecificData = true;
4372b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    }
4382b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
4392b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    size_t numBytesPerInputFrame =
4402b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        mNumChannels * kNumSamplesPerFrame * sizeof(int16_t);
4412b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
4422b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    for (;;) {
4432b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        // We do the following until we run out of buffers.
4442b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
4452b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        while (mInputSize < numBytesPerInputFrame) {
4462b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            // As long as there's still input data to be read we
4472b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            // will drain "kNumSamplesPerFrame * mNumChannels" samples
4482b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            // into the "mInputFrame" buffer and then encode those
4492b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            // as a unit into an output buffer.
4502b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
4512b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            if (mSawInputEOS || inQueue.empty()) {
4522b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                return;
4532b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            }
4542b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
4552b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            BufferInfo *inInfo = *inQueue.begin();
4562b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
4572b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
4582b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            const void *inData = inHeader->pBuffer + inHeader->nOffset;
4592b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
4602b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            size_t copy = numBytesPerInputFrame - mInputSize;
4612b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            if (copy > inHeader->nFilledLen) {
4622b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                copy = inHeader->nFilledLen;
4632b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            }
4642b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
4652b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            if (mInputFrame == NULL) {
4662b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                mInputFrame = new int16_t[kNumSamplesPerFrame * mNumChannels];
4672b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            }
4682b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
4692b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            if (mInputSize == 0) {
4702b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                mInputTimeUs = inHeader->nTimeStamp;
4712b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            }
4722b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
4732b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            memcpy((uint8_t *)mInputFrame + mInputSize, inData, copy);
4742b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            mInputSize += copy;
4752b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
4762b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            inHeader->nOffset += copy;
4772b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            inHeader->nFilledLen -= copy;
4782b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
4792b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            // "Time" on the input buffer has in effect advanced by the
4802b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            // number of audio frames we just advanced nOffset by.
4812b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            inHeader->nTimeStamp +=
4822b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                (copy * 1000000ll / mSampleRate)
4832b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                    / (mNumChannels * sizeof(int16_t));
4842b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
4852b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            if (inHeader->nFilledLen == 0) {
4862b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
4872b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                    ALOGV("saw input EOS");
4882b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                    mSawInputEOS = true;
4892b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
4902b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                    // Pad any remaining data with zeroes.
4912b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                    memset((uint8_t *)mInputFrame + mInputSize,
4922b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                           0,
4932b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                           numBytesPerInputFrame - mInputSize);
4942b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
4952b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                    mInputSize = numBytesPerInputFrame;
4962b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                }
4972b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
4982b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                inQueue.erase(inQueue.begin());
4992b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                inInfo->mOwnedByUs = false;
5002b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                notifyEmptyBufferDone(inHeader);
5012b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
5022b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                inData = NULL;
5032b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                inHeader = NULL;
5042b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                inInfo = NULL;
5052b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            }
5062b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        }
5072b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
5082b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        // At this  point we have all the input data necessary to encode
5092b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        // a single frame, all we need is an output buffer to store the result
5102b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        // in.
5112b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
5122b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        if (outQueue.empty()) {
5132b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            return;
5142b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        }
5152b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
5162b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        BufferInfo *outInfo = *outQueue.begin();
5172b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
5182b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
5192b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        VO_CODECBUFFER inputData;
5202b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        memset(&inputData, 0, sizeof(inputData));
5212b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        inputData.Buffer = (unsigned char *)mInputFrame;
5222b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        inputData.Length = numBytesPerInputFrame;
5232b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        CHECK(VO_ERR_NONE ==
5242b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                mApiHandle->SetInputData(mEncoderHandle, &inputData));
5252b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
5262b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        VO_CODECBUFFER outputData;
5272b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        memset(&outputData, 0, sizeof(outputData));
5282b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        VO_AUDIO_OUTPUTINFO outputInfo;
5292b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        memset(&outputInfo, 0, sizeof(outputInfo));
5302b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
5312b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        uint8_t *outPtr = (uint8_t *)outHeader->pBuffer + outHeader->nOffset;
5322b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        size_t outAvailable = outHeader->nAllocLen - outHeader->nOffset;
5332b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
5342b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        VO_U32 ret = VO_ERR_NONE;
5352b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        size_t nOutputBytes = 0;
5362b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        do {
5372b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            outputData.Buffer = outPtr;
5382b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            outputData.Length = outAvailable - nOutputBytes;
5392b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            ret = mApiHandle->GetOutputData(
5402b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                    mEncoderHandle, &outputData, &outputInfo);
5412b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            if (ret == VO_ERR_NONE) {
5422b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                outPtr += outputData.Length;
5432b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                nOutputBytes += outputData.Length;
5442b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            }
5452b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        } while (ret != VO_ERR_INPUT_BUFFER_SMALL);
5462b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
5472b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        outHeader->nFilledLen = nOutputBytes;
5482b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
5492b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        outHeader->nFlags = OMX_BUFFERFLAG_ENDOFFRAME;
5502b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
5512b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        if (mSawInputEOS) {
5522b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            // We also tag this output buffer with EOS if it corresponds
5532b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            // to the final input buffer.
5542b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            outHeader->nFlags = OMX_BUFFERFLAG_EOS;
5552b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        }
5562b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
5572b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        outHeader->nTimeStamp = mInputTimeUs;
5582b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
5592b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber#if 0
5602b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        ALOGI("sending %d bytes of data (time = %lld us, flags = 0x%08lx)",
5612b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber              nOutputBytes, mInputTimeUs, outHeader->nFlags);
5622b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
5632b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        hexdump(outHeader->pBuffer + outHeader->nOffset, outHeader->nFilledLen);
5642b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber#endif
5652b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
5662b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        outQueue.erase(outQueue.begin());
5672b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        outInfo->mOwnedByUs = false;
5682b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        notifyFillBufferDone(outHeader);
5692b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
5702b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        outHeader = NULL;
5712b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        outInfo = NULL;
5722b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
5732b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        mInputSize = 0;
5742b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    }
5752b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber}
5762b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
5775443b57cc54f2e46b35246637be26a69e9f493e1Wonsik Kimvoid SoftAACEncoder::onReset() {
5785443b57cc54f2e46b35246637be26a69e9f493e1Wonsik Kim    delete[] mInputFrame;
5795443b57cc54f2e46b35246637be26a69e9f493e1Wonsik Kim    mInputFrame = NULL;
5805443b57cc54f2e46b35246637be26a69e9f493e1Wonsik Kim    mInputSize = 0;
5815443b57cc54f2e46b35246637be26a69e9f493e1Wonsik Kim
5825443b57cc54f2e46b35246637be26a69e9f493e1Wonsik Kim    mSentCodecSpecificData = false;
5835443b57cc54f2e46b35246637be26a69e9f493e1Wonsik Kim    mInputTimeUs = -1ll;
5845443b57cc54f2e46b35246637be26a69e9f493e1Wonsik Kim    mSawInputEOS = false;
5855443b57cc54f2e46b35246637be26a69e9f493e1Wonsik Kim    mSignalledError = false;
5865443b57cc54f2e46b35246637be26a69e9f493e1Wonsik Kim}
5875443b57cc54f2e46b35246637be26a69e9f493e1Wonsik Kim
5882b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber}  // namespace android
5892b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
5902b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huberandroid::SoftOMXComponent *createSoftOMXComponent(
5912b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        const char *name, const OMX_CALLBACKTYPE *callbacks,
5922b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        OMX_PTR appData, OMX_COMPONENTTYPE **component) {
5932b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    return new android::SoftAACEncoder(name, callbacks, appData, component);
5942b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber}
595