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