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(¶ms, 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, ¶ms)) { 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