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