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
1572720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen            if (!isValidOMXParam(formatParams)) {
1582720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen                return OMX_ErrorBadParameter;
1592720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen            }
1602720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen
1612b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            if (formatParams->nPortIndex > 1) {
1622b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                return OMX_ErrorUndefined;
1632b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            }
1642b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
1652b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            if (formatParams->nIndex > 0) {
1662b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                return OMX_ErrorNoMore;
1672b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            }
1682b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
1692b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            formatParams->eEncoding =
1702b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                (formatParams->nPortIndex == 0)
1712b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                    ? OMX_AUDIO_CodingPCM : OMX_AUDIO_CodingAAC;
1722b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
1732b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            return OMX_ErrorNone;
1742b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        }
1752b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
1762b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        case OMX_IndexParamAudioAac:
1772b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        {
1782b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            OMX_AUDIO_PARAM_AACPROFILETYPE *aacParams =
1792b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                (OMX_AUDIO_PARAM_AACPROFILETYPE *)params;
1802b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
1812720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen            if (!isValidOMXParam(aacParams)) {
1822720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen                return OMX_ErrorBadParameter;
1832720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen            }
1842720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen
1852b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            if (aacParams->nPortIndex != 1) {
1862b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                return OMX_ErrorUndefined;
1872b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            }
1882b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
1892b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            aacParams->nBitRate = mBitRate;
1902b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            aacParams->nAudioBandWidth = 0;
1912b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            aacParams->nAACtools = 0;
1922b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            aacParams->nAACERtools = 0;
1932b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            aacParams->eAACProfile = OMX_AUDIO_AACObjectMain;
1942b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            aacParams->eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4FF;
1952b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            aacParams->eChannelMode = OMX_AUDIO_ChannelModeStereo;
1962b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
1972b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            aacParams->nChannels = mNumChannels;
1982b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            aacParams->nSampleRate = mSampleRate;
1992b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            aacParams->nFrameLength = 0;
2002b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
2012b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            return OMX_ErrorNone;
2022b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        }
2032b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
2042b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        case OMX_IndexParamAudioPcm:
2052b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        {
2062b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
2072b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
2082b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
2092720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen            if (!isValidOMXParam(pcmParams)) {
2102720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen                return OMX_ErrorBadParameter;
2112720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen            }
2122720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen
2132b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            if (pcmParams->nPortIndex != 0) {
2142b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                return OMX_ErrorUndefined;
2152b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            }
2162b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
2172b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            pcmParams->eNumData = OMX_NumericalDataSigned;
2182b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            pcmParams->eEndian = OMX_EndianBig;
2192b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            pcmParams->bInterleaved = OMX_TRUE;
2202b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            pcmParams->nBitPerSample = 16;
2212b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear;
2222b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            pcmParams->eChannelMapping[0] = OMX_AUDIO_ChannelLF;
2232b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            pcmParams->eChannelMapping[1] = OMX_AUDIO_ChannelRF;
2242b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
2252b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            pcmParams->nChannels = mNumChannels;
2262b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            pcmParams->nSamplingRate = mSampleRate;
2272b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
2282b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            return OMX_ErrorNone;
2292b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        }
2302b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
2312b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        default:
2322b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            return SimpleSoftOMXComponent::internalGetParameter(index, params);
2332b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    }
2342b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber}
2352b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
2362b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas HuberOMX_ERRORTYPE SoftAACEncoder::internalSetParameter(
2372b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        OMX_INDEXTYPE index, const OMX_PTR params) {
2382b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    switch (index) {
2392b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        case OMX_IndexParamStandardComponentRole:
2402b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        {
2412b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            const OMX_PARAM_COMPONENTROLETYPE *roleParams =
2422b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                (const OMX_PARAM_COMPONENTROLETYPE *)params;
2432b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
2442720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen            if (!isValidOMXParam(roleParams)) {
2452720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen                return OMX_ErrorBadParameter;
2462720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen            }
2472720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen
2482b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            if (strncmp((const char *)roleParams->cRole,
2492b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                        "audio_encoder.aac",
2502b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                        OMX_MAX_STRINGNAME_SIZE - 1)) {
2512b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                return OMX_ErrorUndefined;
2522b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            }
2532b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
2542b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            return OMX_ErrorNone;
2552b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        }
2562b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
2572b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        case OMX_IndexParamAudioPortFormat:
2582b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        {
2592b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            const OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams =
2602b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                (const OMX_AUDIO_PARAM_PORTFORMATTYPE *)params;
2612b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
2622720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen            if (!isValidOMXParam(formatParams)) {
2632720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen                return OMX_ErrorBadParameter;
2642720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen            }
2652720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen
2662b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            if (formatParams->nPortIndex > 1) {
2672b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                return OMX_ErrorUndefined;
2682b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            }
2692b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
2702b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            if (formatParams->nIndex > 0) {
2712b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                return OMX_ErrorNoMore;
2722b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            }
2732b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
2742b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            if ((formatParams->nPortIndex == 0
2752b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                        && formatParams->eEncoding != OMX_AUDIO_CodingPCM)
2762b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                || (formatParams->nPortIndex == 1
2772b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                        && formatParams->eEncoding != OMX_AUDIO_CodingAAC)) {
2782b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                return OMX_ErrorUndefined;
2792b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            }
2802b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
2812b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            return OMX_ErrorNone;
2822b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        }
2832b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
2842b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        case OMX_IndexParamAudioAac:
2852b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        {
2862b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            OMX_AUDIO_PARAM_AACPROFILETYPE *aacParams =
2872b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                (OMX_AUDIO_PARAM_AACPROFILETYPE *)params;
2882b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
2892720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen            if (!isValidOMXParam(aacParams)) {
2902720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen                return OMX_ErrorBadParameter;
2912720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen            }
2922720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen
2932b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            if (aacParams->nPortIndex != 1) {
2942b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                return OMX_ErrorUndefined;
2952b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            }
2962b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
2972b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            mBitRate = aacParams->nBitRate;
2982b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            mNumChannels = aacParams->nChannels;
2992b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            mSampleRate = aacParams->nSampleRate;
3002b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
3012b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            if (setAudioParams() != OK) {
3022b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                return OMX_ErrorUndefined;
3032b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            }
3042b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
3052b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            return OMX_ErrorNone;
3062b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        }
3072b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
3082b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        case OMX_IndexParamAudioPcm:
3092b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        {
3102b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
3112b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
3122b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
3132720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen            if (!isValidOMXParam(pcmParams)) {
3142720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen                return OMX_ErrorBadParameter;
3152720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen            }
3162720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen
3172b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            if (pcmParams->nPortIndex != 0) {
3182b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                return OMX_ErrorUndefined;
3192b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            }
3202b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
3212b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            mNumChannels = pcmParams->nChannels;
3222b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            mSampleRate = pcmParams->nSamplingRate;
3232b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
3242b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            if (setAudioParams() != OK) {
3252b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                return OMX_ErrorUndefined;
3262b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            }
3272b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
3282b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            return OMX_ErrorNone;
3292b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        }
3302b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
3312b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
3322b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        default:
3332b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            return SimpleSoftOMXComponent::internalSetParameter(index, params);
3342b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    }
3352b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber}
3362b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
3372b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huberstatus_t SoftAACEncoder::setAudioParams() {
3382b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    // We call this whenever sample rate, number of channels or bitrate change
3392b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    // in reponse to setParameter calls.
3402b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
3412b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    ALOGV("setAudioParams: %lu Hz, %lu channels, %lu bps",
3422b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber         mSampleRate, mNumChannels, mBitRate);
3432b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
3442b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    status_t err = setAudioSpecificConfigData();
3452b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
3462b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    if (err != OK) {
3472b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        return err;
3482b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    }
3492b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
3502b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    AACENC_PARAM params;
3512b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    memset(&params, 0, sizeof(params));
3522b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    params.sampleRate = mSampleRate;
3532b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    params.bitRate = mBitRate;
3542b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    params.nChannels = mNumChannels;
3552b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    params.adtsUsed = 0;  // We add adts header in the file writer if needed.
3562b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    if (VO_ERR_NONE != mApiHandle->SetParam(
3572b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                mEncoderHandle, VO_PID_AAC_ENCPARAM,  &params)) {
3582b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        ALOGE("Failed to set AAC encoder parameters");
3592b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        return UNKNOWN_ERROR;
3602b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    }
3612b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
3622b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    return OK;
3632b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber}
3642b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
3652b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huberstatic status_t getSampleRateTableIndex(int32_t sampleRate, int32_t &index) {
3662b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    static const int32_t kSampleRateTable[] = {
3672b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        96000, 88200, 64000, 48000, 44100, 32000,
3682b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        24000, 22050, 16000, 12000, 11025, 8000
3692b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    };
3702b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    const int32_t tableSize =
3712b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        sizeof(kSampleRateTable) / sizeof(kSampleRateTable[0]);
3722b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
3732b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    for (int32_t i = 0; i < tableSize; ++i) {
3742b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        if (sampleRate == kSampleRateTable[i]) {
3752b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            index = i;
3762b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            return OK;
3772b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        }
3782b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    }
3792b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
3802b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    return UNKNOWN_ERROR;
3812b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber}
3822b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
3832b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huberstatus_t SoftAACEncoder::setAudioSpecificConfigData() {
3842b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    // The AAC encoder's audio specific config really only encodes
3852b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    // number of channels and the sample rate (mapped to an index into
3862b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    // a fixed sample rate table).
3872b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
3882b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    int32_t index;
3892b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    status_t err = getSampleRateTableIndex(mSampleRate, index);
3902b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    if (err != OK) {
3912b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        ALOGE("Unsupported sample rate (%lu Hz)", mSampleRate);
3922b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        return err;
3932b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    }
3942b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
3952b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    if (mNumChannels > 2 || mNumChannels <= 0) {
3962b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        ALOGE("Unsupported number of channels(%lu)", mNumChannels);
3972b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        return UNKNOWN_ERROR;
3982b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    }
3992b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
4002b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    // OMX_AUDIO_AACObjectLC
4012b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    mAudioSpecificConfigData[0] = ((0x02 << 3) | (index >> 1));
4022b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    mAudioSpecificConfigData[1] = ((index & 0x01) << 7) | (mNumChannels << 3);
4032b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
4042b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    return OK;
4052b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber}
4062b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
4072b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Hubervoid SoftAACEncoder::onQueueFilled(OMX_U32 portIndex) {
4082b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    if (mSignalledError) {
4092b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        return;
4102b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    }
4112b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
4122b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    List<BufferInfo *> &inQueue = getPortQueue(0);
4132b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    List<BufferInfo *> &outQueue = getPortQueue(1);
4142b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
4152b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    if (!mSentCodecSpecificData) {
4162b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        // The very first thing we want to output is the codec specific
4172b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        // data. It does not require any input data but we will need an
4182b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        // output buffer to store it in.
4192b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
4202b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        if (outQueue.empty()) {
4212b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            return;
4222b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        }
4232b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
4242b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        BufferInfo *outInfo = *outQueue.begin();
4252b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
4262b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        outHeader->nFilledLen = sizeof(mAudioSpecificConfigData);
4272b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        outHeader->nFlags = OMX_BUFFERFLAG_CODECCONFIG;
4282b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
4292b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        uint8_t *out = outHeader->pBuffer + outHeader->nOffset;
4302b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        memcpy(out, mAudioSpecificConfigData, sizeof(mAudioSpecificConfigData));
4312b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
4322b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber#if 0
4332b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        ALOGI("sending codec specific data.");
4342b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        hexdump(out, sizeof(mAudioSpecificConfigData));
4352b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber#endif
4362b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
4372b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        outQueue.erase(outQueue.begin());
4382b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        outInfo->mOwnedByUs = false;
4392b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        notifyFillBufferDone(outHeader);
4402b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
4412b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        mSentCodecSpecificData = true;
4422b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    }
4432b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
4442b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    size_t numBytesPerInputFrame =
4452b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        mNumChannels * kNumSamplesPerFrame * sizeof(int16_t);
4462b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
4472b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    for (;;) {
4482b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        // We do the following until we run out of buffers.
4492b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
4502b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        while (mInputSize < numBytesPerInputFrame) {
4512b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            // As long as there's still input data to be read we
4522b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            // will drain "kNumSamplesPerFrame * mNumChannels" samples
4532b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            // into the "mInputFrame" buffer and then encode those
4542b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            // as a unit into an output buffer.
4552b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
4562b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            if (mSawInputEOS || inQueue.empty()) {
4572b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                return;
4582b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            }
4592b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
4602b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            BufferInfo *inInfo = *inQueue.begin();
4612b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
4622b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
4632b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            const void *inData = inHeader->pBuffer + inHeader->nOffset;
4642b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
4652b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            size_t copy = numBytesPerInputFrame - mInputSize;
4662b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            if (copy > inHeader->nFilledLen) {
4672b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                copy = inHeader->nFilledLen;
4682b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            }
4692b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
4702b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            if (mInputFrame == NULL) {
4712b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                mInputFrame = new int16_t[kNumSamplesPerFrame * mNumChannels];
4722b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            }
4732b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
4742b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            if (mInputSize == 0) {
4752b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                mInputTimeUs = inHeader->nTimeStamp;
4762b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            }
4772b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
4782b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            memcpy((uint8_t *)mInputFrame + mInputSize, inData, copy);
4792b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            mInputSize += copy;
4802b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
4812b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            inHeader->nOffset += copy;
4822b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            inHeader->nFilledLen -= copy;
4832b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
4842b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            // "Time" on the input buffer has in effect advanced by the
4852b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            // number of audio frames we just advanced nOffset by.
4862b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            inHeader->nTimeStamp +=
4872b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                (copy * 1000000ll / mSampleRate)
4882b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                    / (mNumChannels * sizeof(int16_t));
4892b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
4902b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            if (inHeader->nFilledLen == 0) {
4912b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
4922b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                    ALOGV("saw input EOS");
4932b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                    mSawInputEOS = true;
4942b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
4952b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                    // Pad any remaining data with zeroes.
4962b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                    memset((uint8_t *)mInputFrame + mInputSize,
4972b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                           0,
4982b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                           numBytesPerInputFrame - mInputSize);
4992b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
5002b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                    mInputSize = numBytesPerInputFrame;
5012b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                }
5022b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
5032b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                inQueue.erase(inQueue.begin());
5042b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                inInfo->mOwnedByUs = false;
5052b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                notifyEmptyBufferDone(inHeader);
5062b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
5072b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                inData = NULL;
5082b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                inHeader = NULL;
5092b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                inInfo = NULL;
5102b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            }
5112b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        }
5122b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
5132b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        // At this  point we have all the input data necessary to encode
5142b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        // a single frame, all we need is an output buffer to store the result
5152b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        // in.
5162b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
5172b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        if (outQueue.empty()) {
5182b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            return;
5192b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        }
5202b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
5212b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        BufferInfo *outInfo = *outQueue.begin();
5222b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
5232b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
5242b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        VO_CODECBUFFER inputData;
5252b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        memset(&inputData, 0, sizeof(inputData));
5262b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        inputData.Buffer = (unsigned char *)mInputFrame;
5272b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        inputData.Length = numBytesPerInputFrame;
5282b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        CHECK(VO_ERR_NONE ==
5292b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                mApiHandle->SetInputData(mEncoderHandle, &inputData));
5302b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
5312b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        VO_CODECBUFFER outputData;
5322b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        memset(&outputData, 0, sizeof(outputData));
5332b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        VO_AUDIO_OUTPUTINFO outputInfo;
5342b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        memset(&outputInfo, 0, sizeof(outputInfo));
5352b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
5362b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        uint8_t *outPtr = (uint8_t *)outHeader->pBuffer + outHeader->nOffset;
5372b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        size_t outAvailable = outHeader->nAllocLen - outHeader->nOffset;
5382b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
5392b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        VO_U32 ret = VO_ERR_NONE;
5402b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        size_t nOutputBytes = 0;
5412b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        do {
5422b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            outputData.Buffer = outPtr;
5432b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            outputData.Length = outAvailable - nOutputBytes;
5442b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            ret = mApiHandle->GetOutputData(
5452b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                    mEncoderHandle, &outputData, &outputInfo);
5462b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            if (ret == VO_ERR_NONE) {
5472b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                outPtr += outputData.Length;
5482b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber                nOutputBytes += outputData.Length;
5492b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            }
5502b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        } while (ret != VO_ERR_INPUT_BUFFER_SMALL);
5512b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
5522b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        outHeader->nFilledLen = nOutputBytes;
5532b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
5542b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        outHeader->nFlags = OMX_BUFFERFLAG_ENDOFFRAME;
5552b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
5562b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        if (mSawInputEOS) {
5572b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            // We also tag this output buffer with EOS if it corresponds
5582b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            // to the final input buffer.
5592b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber            outHeader->nFlags = OMX_BUFFERFLAG_EOS;
5602b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        }
5612b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
5622b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        outHeader->nTimeStamp = mInputTimeUs;
5632b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
5642b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber#if 0
5652b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        ALOGI("sending %d bytes of data (time = %lld us, flags = 0x%08lx)",
5662b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber              nOutputBytes, mInputTimeUs, outHeader->nFlags);
5672b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
5682b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        hexdump(outHeader->pBuffer + outHeader->nOffset, outHeader->nFilledLen);
5692b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber#endif
5702b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
5712b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        outQueue.erase(outQueue.begin());
5722b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        outInfo->mOwnedByUs = false;
5732b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        notifyFillBufferDone(outHeader);
5742b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
5752b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        outHeader = NULL;
5762b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        outInfo = NULL;
5772b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
5782b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        mInputSize = 0;
5792b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    }
5802b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber}
5812b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
5822b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber}  // namespace android
5832b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber
5842b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huberandroid::SoftOMXComponent *createSoftOMXComponent(
5852b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        const char *name, const OMX_CALLBACKTYPE *callbacks,
5862b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber        OMX_PTR appData, OMX_COMPONENTTYPE **component) {
5872b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber    return new android::SoftAACEncoder(name, callbacks, appData, component);
5882b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber}
589