blob: da8675874ed1652cf424a78488f8e32d67b2891f [file] [log] [blame]
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
//#define LOG_NDEBUG 0
#define LOG_TAG "SoftXAAC"
#include <utils/Log.h>
#include "SoftXAAC.h"
#include <OMX_AudioExt.h>
#include <OMX_IndexExt.h>
#include <cutils/properties.h>
#include <math.h>
#include <media/stagefright/MediaErrors.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/hexdump.h>
#include <utils/misc.h>
/* 64*-0.25dB = -16 dB below full scale for mobile conf */
#define DRC_DEFAULT_MOBILE_REF_LEVEL 64
/* maximum compression of dynamic range for mobile conf */
#define DRC_DEFAULT_MOBILE_DRC_CUT 127
/* maximum compression of dynamic range for mobile conf */
#define DRC_DEFAULT_MOBILE_DRC_BOOST 127
/* switch for heavy compression for mobile conf */
#define DRC_DEFAULT_MOBILE_DRC_HEAVY 1
/* encoder target level; -1 => the value is unknown,
* otherwise dB step value (e.g. 64 for -16 dB) */
#define DRC_DEFAULT_MOBILE_ENC_LEVEL (-1)
/* Default Effect type is "Limited playback" */
#define DRC_KEY_AAC_DRC_EFFECT_TYPE (3)
/* REF_LEVEL of 64 pairs well with EFFECT_TYPE of 3. */
/* Default loudness value for MPEG-D DRC */
#define DRC_DEFAULT_MOBILE_LOUDNESS_LEVEL (64)
#define PROP_DRC_OVERRIDE_REF_LEVEL "aac_drc_reference_level"
#define PROP_DRC_OVERRIDE_CUT "aac_drc_cut"
#define PROP_DRC_OVERRIDE_BOOST "aac_drc_boost"
#define PROP_DRC_OVERRIDE_HEAVY "aac_drc_heavy"
#define PROP_DRC_OVERRIDE_ENC_LEVEL "aac_drc_enc_target_level"
#define PROP_DRC_OVERRIDE_EFFECT_TYPE "ro.aac_drc_effect_type"
/* maximum number of audio channels that can be decoded */
#define MAX_CHANNEL_COUNT 8
#define RETURN_IF_FATAL(retval, str) \
if (retval & IA_FATAL_ERROR) { \
ALOGE("Error in %s: Returned: %d", str, retval); \
return retval; \
} else if (retval != IA_NO_ERROR) { \
ALOGW("Warning in %s: Returned: %d", str, retval); \
}
namespace android {
template <class T>
static void InitOMXParams(T* params) {
params->nSize = sizeof(T);
params->nVersion.s.nVersionMajor = 1;
params->nVersion.s.nVersionMinor = 0;
params->nVersion.s.nRevision = 0;
params->nVersion.s.nStep = 0;
}
static const OMX_U32 kSupportedProfiles[] = {
OMX_AUDIO_AACObjectLC, OMX_AUDIO_AACObjectHE, OMX_AUDIO_AACObjectHE_PS,
OMX_AUDIO_AACObjectLD, OMX_AUDIO_AACObjectELD, OMX_AUDIO_AACObjectXHE
};
SoftXAAC::SoftXAAC(const char* name, const OMX_CALLBACKTYPE* callbacks, OMX_PTR appData,
OMX_COMPONENTTYPE** component)
: SimpleSoftOMXComponent(name, callbacks, appData, component),
mIsADTS(false),
mInputBufferCount(0),
mOutputBufferCount(0),
mSignalledError(false),
mLastInHeader(NULL),
mPrevTimestamp(0),
mCurrentTimestamp(0),
mOutputPortSettingsChange(NONE),
mXheaacCodecHandle(NULL),
mMpegDDrcHandle(NULL),
mInputBufferSize(0),
mOutputFrameLength(1024),
mInputBuffer(NULL),
mOutputBuffer(NULL),
mSampFreq(0),
mNumChannels(0),
mPcmWdSz(0),
mChannelMask(0),
mIsCodecInitialized(false),
mIsCodecConfigFlushRequired(false),
mMpegDDRCPresent(0),
mDRCFlag(0)
{
initPorts();
mMemoryVec.clear();
mDrcMemoryVec.clear();
CHECK_EQ(initDecoder(), IA_NO_ERROR);
}
SoftXAAC::~SoftXAAC() {
IA_ERRORCODE err_code = deInitXAACDecoder();
if (IA_NO_ERROR != err_code) {
ALOGE("deInitXAACDecoder() failed %d", err_code);
}
err_code = deInitMPEGDDDrc();
if (IA_NO_ERROR != err_code) {
ALOGE("deInitMPEGDDDrc() failed %d", err_code);
}
mIsCodecInitialized = false;
mIsCodecConfigFlushRequired = false;
}
void SoftXAAC::initPorts() {
OMX_PARAM_PORTDEFINITIONTYPE def;
InitOMXParams(&def);
def.nPortIndex = 0;
def.eDir = OMX_DirInput;
def.nBufferCountMin = kNumInputBuffers;
def.nBufferCountActual = def.nBufferCountMin;
def.nBufferSize = 8192;
def.bEnabled = OMX_TRUE;
def.bPopulated = OMX_FALSE;
def.eDomain = OMX_PortDomainAudio;
def.bBuffersContiguous = OMX_FALSE;
def.nBufferAlignment = 1;
def.format.audio.cMIMEType = const_cast<char*>("audio/aac");
def.format.audio.pNativeRender = NULL;
def.format.audio.bFlagErrorConcealment = OMX_FALSE;
def.format.audio.eEncoding = OMX_AUDIO_CodingAAC;
addPort(def);
def.nPortIndex = 1;
def.eDir = OMX_DirOutput;
def.nBufferCountMin = kNumOutputBuffers;
def.nBufferCountActual = def.nBufferCountMin;
def.nBufferSize = 4096 * MAX_CHANNEL_COUNT;
def.bEnabled = OMX_TRUE;
def.bPopulated = OMX_FALSE;
def.eDomain = OMX_PortDomainAudio;
def.bBuffersContiguous = OMX_FALSE;
def.nBufferAlignment = 2;
def.format.audio.cMIMEType = const_cast<char*>("audio/raw");
def.format.audio.pNativeRender = NULL;
def.format.audio.bFlagErrorConcealment = OMX_FALSE;
def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
addPort(def);
}
IA_ERRORCODE SoftXAAC::initDecoder() {
int ui_drc_val;
IA_ERRORCODE err_code = IA_NO_ERROR;
int loop = 0;
err_code = initXAACDecoder();
if (err_code != IA_NO_ERROR) {
ALOGE("initXAACDecoder failed with error %d", err_code);
deInitXAACDecoder();
return err_code;
}
mEndOfInput = false;
mEndOfOutput = false;
char value[PROPERTY_VALUE_MAX];
if (property_get(PROP_DRC_OVERRIDE_REF_LEVEL, value, NULL)) {
ui_drc_val = atoi(value);
ALOGV("AAC decoder using desired DRC target reference level of %d instead of %d",
ui_drc_val, DRC_DEFAULT_MOBILE_REF_LEVEL);
} else {
ui_drc_val = DRC_DEFAULT_MOBILE_REF_LEVEL;
}
err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_SET_CONFIG_PARAM,
IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_TARGET_LEVEL, &ui_drc_val);
RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_TARGET_LEVEL");
#ifdef ENABLE_MPEG_D_DRC
/* Use ui_drc_val from PROP_DRC_OVERRIDE_REF_LEVEL or DRC_DEFAULT_MOBILE_REF_LEVEL
* for IA_ENHAACPLUS_DEC_DRC_TARGET_LOUDNESS too */
err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_SET_CONFIG_PARAM,
IA_ENHAACPLUS_DEC_DRC_TARGET_LOUDNESS, &ui_drc_val);
RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_DRC_TARGET_LOUDNESS");
#endif
if (property_get(PROP_DRC_OVERRIDE_CUT, value, NULL)) {
ui_drc_val = atoi(value);
ALOGV("AAC decoder using desired DRC attenuation factor of %d instead of %d", ui_drc_val,
DRC_DEFAULT_MOBILE_DRC_CUT);
} else {
ui_drc_val = DRC_DEFAULT_MOBILE_DRC_CUT;
}
err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_SET_CONFIG_PARAM,
IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_CUT, &ui_drc_val);
RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_CUT");
if (property_get(PROP_DRC_OVERRIDE_BOOST, value, NULL)) {
ui_drc_val = atoi(value);
ALOGV("AAC decoder using desired DRC boost factor of %d instead of %d", ui_drc_val,
DRC_DEFAULT_MOBILE_DRC_BOOST);
} else {
ui_drc_val = DRC_DEFAULT_MOBILE_DRC_BOOST;
}
err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_SET_CONFIG_PARAM,
IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_BOOST, &ui_drc_val);
RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_BOOST");
if (property_get(PROP_DRC_OVERRIDE_HEAVY, value, NULL)) {
ui_drc_val = atoi(value);
ALOGV("AAC decoder using desired Heavy compression factor of %d instead of %d", ui_drc_val,
DRC_DEFAULT_MOBILE_DRC_HEAVY);
} else {
ui_drc_val = DRC_DEFAULT_MOBILE_DRC_HEAVY;
}
err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_SET_CONFIG_PARAM,
IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_HEAVY_COMP, &ui_drc_val);
RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_HEAVY_COMP");
#ifdef ENABLE_MPEG_D_DRC
if (property_get(PROP_DRC_OVERRIDE_EFFECT_TYPE, value, NULL)) {
ui_drc_val = atoi(value);
ALOGV("AAC decoder using desired DRC effect type of %d instead of %d", ui_drc_val,
DRC_KEY_AAC_DRC_EFFECT_TYPE);
} else {
ui_drc_val = DRC_KEY_AAC_DRC_EFFECT_TYPE;
}
err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_SET_CONFIG_PARAM,
IA_ENHAACPLUS_DEC_DRC_EFFECT_TYPE, &ui_drc_val);
RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_DRC_EFFECT_TYPE");
#endif
return IA_NO_ERROR;
}
OMX_ERRORTYPE SoftXAAC::internalGetParameter(OMX_INDEXTYPE index, OMX_PTR params) {
switch ((OMX_U32)index) {
case OMX_IndexParamAudioPortFormat: {
OMX_AUDIO_PARAM_PORTFORMATTYPE* formatParams = (OMX_AUDIO_PARAM_PORTFORMATTYPE*)params;
if (!isValidOMXParam(formatParams)) {
return OMX_ErrorBadParameter;
}
if (formatParams->nPortIndex > 1) {
return OMX_ErrorUndefined;
}
if (formatParams->nIndex > 0) {
return OMX_ErrorNoMore;
}
formatParams->eEncoding =
(formatParams->nPortIndex == 0) ? OMX_AUDIO_CodingAAC : OMX_AUDIO_CodingPCM;
return OMX_ErrorNone;
}
case OMX_IndexParamAudioAac: {
OMX_AUDIO_PARAM_AACPROFILETYPE* aacParams = (OMX_AUDIO_PARAM_AACPROFILETYPE*)params;
if (!isValidOMXParam(aacParams)) {
return OMX_ErrorBadParameter;
}
if (aacParams->nPortIndex != 0) {
return OMX_ErrorUndefined;
}
aacParams->nBitRate = 0;
aacParams->nAudioBandWidth = 0;
aacParams->nAACtools = 0;
aacParams->nAACERtools = 0;
aacParams->eAACProfile = OMX_AUDIO_AACObjectMain;
aacParams->eAACStreamFormat =
mIsADTS ? OMX_AUDIO_AACStreamFormatMP4ADTS : OMX_AUDIO_AACStreamFormatMP4FF;
aacParams->eChannelMode = OMX_AUDIO_ChannelModeStereo;
if (!isConfigured()) {
aacParams->nChannels = 1;
aacParams->nSampleRate = 44100;
aacParams->nFrameLength = 0;
} else {
aacParams->nChannels = mNumChannels;
aacParams->nSampleRate = mSampFreq;
aacParams->nFrameLength = mOutputFrameLength;
}
return OMX_ErrorNone;
}
case OMX_IndexParamAudioPcm: {
OMX_AUDIO_PARAM_PCMMODETYPE* pcmParams = (OMX_AUDIO_PARAM_PCMMODETYPE*)params;
if (!isValidOMXParam(pcmParams)) {
return OMX_ErrorBadParameter;
}
if (pcmParams->nPortIndex != 1) {
return OMX_ErrorUndefined;
}
pcmParams->eNumData = OMX_NumericalDataSigned;
pcmParams->eEndian = OMX_EndianBig;
pcmParams->bInterleaved = OMX_TRUE;
pcmParams->nBitPerSample = 16;
pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear;
pcmParams->eChannelMapping[0] = OMX_AUDIO_ChannelLF;
pcmParams->eChannelMapping[1] = OMX_AUDIO_ChannelRF;
pcmParams->eChannelMapping[2] = OMX_AUDIO_ChannelCF;
pcmParams->eChannelMapping[3] = OMX_AUDIO_ChannelLFE;
pcmParams->eChannelMapping[4] = OMX_AUDIO_ChannelLS;
pcmParams->eChannelMapping[5] = OMX_AUDIO_ChannelRS;
if (!isConfigured()) {
pcmParams->nChannels = 1;
pcmParams->nSamplingRate = 44100;
} else {
pcmParams->nChannels = mNumChannels;
pcmParams->nSamplingRate = mSampFreq;
}
return OMX_ErrorNone;
}
case OMX_IndexParamAudioProfileQuerySupported: {
OMX_AUDIO_PARAM_ANDROID_PROFILETYPE* profileParams =
(OMX_AUDIO_PARAM_ANDROID_PROFILETYPE*)params;
if (!isValidOMXParam(profileParams)) {
return OMX_ErrorBadParameter;
}
if (profileParams->nPortIndex != 0) {
return OMX_ErrorUndefined;
}
if (profileParams->nProfileIndex >= NELEM(kSupportedProfiles)) {
return OMX_ErrorNoMore;
}
profileParams->eProfile = kSupportedProfiles[profileParams->nProfileIndex];
return OMX_ErrorNone;
}
default:
return SimpleSoftOMXComponent::internalGetParameter(index, params);
}
}
OMX_ERRORTYPE SoftXAAC::internalSetParameter(OMX_INDEXTYPE index, const OMX_PTR params) {
switch ((int)index) {
case OMX_IndexParamStandardComponentRole: {
const OMX_PARAM_COMPONENTROLETYPE* roleParams =
(const OMX_PARAM_COMPONENTROLETYPE*)params;
if (!isValidOMXParam(roleParams)) {
return OMX_ErrorBadParameter;
}
if (strncmp((const char*)roleParams->cRole, "audio_decoder.aac",
OMX_MAX_STRINGNAME_SIZE - 1)) {
return OMX_ErrorUndefined;
}
return OMX_ErrorNone;
}
case OMX_IndexParamAudioPortFormat: {
const OMX_AUDIO_PARAM_PORTFORMATTYPE* formatParams =
(const OMX_AUDIO_PARAM_PORTFORMATTYPE*)params;
if (!isValidOMXParam(formatParams)) {
return OMX_ErrorBadParameter;
}
if (formatParams->nPortIndex > 1) {
return OMX_ErrorUndefined;
}
if ((formatParams->nPortIndex == 0 && formatParams->eEncoding != OMX_AUDIO_CodingAAC) ||
(formatParams->nPortIndex == 1 && formatParams->eEncoding != OMX_AUDIO_CodingPCM)) {
return OMX_ErrorUndefined;
}
return OMX_ErrorNone;
}
case OMX_IndexParamAudioAac: {
const OMX_AUDIO_PARAM_AACPROFILETYPE* aacParams =
(const OMX_AUDIO_PARAM_AACPROFILETYPE*)params;
if (!isValidOMXParam(aacParams)) {
return OMX_ErrorBadParameter;
}
if (aacParams->nPortIndex != 0) {
return OMX_ErrorUndefined;
}
if (aacParams->eAACStreamFormat == OMX_AUDIO_AACStreamFormatMP4FF) {
mIsADTS = false;
} else if (aacParams->eAACStreamFormat == OMX_AUDIO_AACStreamFormatMP4ADTS) {
mIsADTS = true;
} else {
return OMX_ErrorUndefined;
}
return OMX_ErrorNone;
}
case OMX_IndexParamAudioAndroidAacDrcPresentation: {
const OMX_AUDIO_PARAM_ANDROID_AACDRCPRESENTATIONTYPE* aacPresParams =
(const OMX_AUDIO_PARAM_ANDROID_AACDRCPRESENTATIONTYPE*)params;
if (!isValidOMXParam(aacPresParams)) {
ALOGE("set OMX_ErrorBadParameter");
return OMX_ErrorBadParameter;
}
// for the following parameters of the OMX_AUDIO_PARAM_AACPROFILETYPE structure,
// a value of -1 implies the parameter is not set by the application:
// nMaxOutputChannels -1 by default
// nDrcCut uses default platform properties, see initDecoder()
// nDrcBoost idem
// nHeavyCompression idem
// nTargetReferenceLevel idem
// nEncodedTargetLevel idem
if (aacPresParams->nMaxOutputChannels >= 0) {
int max;
if (aacPresParams->nMaxOutputChannels >= 8) {
max = 8;
} else if (aacPresParams->nMaxOutputChannels >= 6) {
max = 6;
} else if (aacPresParams->nMaxOutputChannels >= 2) {
max = 2;
} else {
// -1 or 0: disable downmix, 1: mono
max = aacPresParams->nMaxOutputChannels;
}
}
/* Apply DRC Changes */
IA_ERRORCODE err_code = setXAACDRCInfo(aacPresParams->nDrcCut, aacPresParams->nDrcBoost,
aacPresParams->nTargetReferenceLevel,
aacPresParams->nHeavyCompression
#ifdef ENABLE_MPEG_D_DRC
,
aacPresParams->nDrcEffectType
#endif
); // TOD0 : Revert this change
if (err_code != IA_NO_ERROR) {
ALOGE("Error in OMX_IndexParamAudioAndroidAacDrcPresentation");
return OMX_ErrorBadParameter;
}
return OMX_ErrorNone;
}
case OMX_IndexParamAudioPcm: {
const OMX_AUDIO_PARAM_PCMMODETYPE* pcmParams = (OMX_AUDIO_PARAM_PCMMODETYPE*)params;
if (!isValidOMXParam(pcmParams)) {
return OMX_ErrorBadParameter;
}
if (pcmParams->nPortIndex != 1) {
return OMX_ErrorUndefined;
}
return OMX_ErrorNone;
}
default:
return SimpleSoftOMXComponent::internalSetParameter(index, params);
}
}
bool SoftXAAC::isConfigured() const {
return mInputBufferCount > 0;
}
void SoftXAAC::onQueueFilled(OMX_U32 /* portIndex */) {
if (mSignalledError || mOutputPortSettingsChange != NONE) {
ALOGE("onQueueFilled do not process %d %d", mSignalledError, mOutputPortSettingsChange);
return;
}
uint8_t* inBuffer = NULL;
uint32_t inBufferLength = 0;
List<BufferInfo*>& inQueue = getPortQueue(0);
List<BufferInfo*>& outQueue = getPortQueue(1);
signed int numOutBytes = 0;
/* If decoder call fails in between, then mOutputFrameLength is used */
/* Decoded output for AAC is 1024/2048 samples / channel */
/* TODO: For USAC mOutputFrameLength can go up to 4096 */
/* Note: entire buffer logic to save and retrieve assumes 2 bytes per*/
/* sample currently */
if (mIsCodecInitialized) {
numOutBytes = mOutputFrameLength * (mPcmWdSz / 8) * mNumChannels;
}
while ((!inQueue.empty() || mEndOfInput) && !outQueue.empty()) {
if (!inQueue.empty()) {
BufferInfo* inInfo = *inQueue.begin();
OMX_BUFFERHEADERTYPE* inHeader = inInfo->mHeader;
/* No need to check inHeader != NULL, as inQueue is not empty */
mEndOfInput = (inHeader->nFlags & OMX_BUFFERFLAG_EOS) != 0;
if (mInputBufferCount == 0 && !(inHeader->nFlags & OMX_BUFFERFLAG_CODECCONFIG)) {
ALOGW("first buffer should have OMX_BUFFERFLAG_CODECCONFIG set");
inHeader->nFlags |= OMX_BUFFERFLAG_CODECCONFIG;
}
if ((inHeader->nFlags & OMX_BUFFERFLAG_CODECCONFIG) != 0) {
inBuffer = inHeader->pBuffer + inHeader->nOffset;
inBufferLength = inHeader->nFilledLen;
/* GA header configuration sent to Decoder! */
IA_ERRORCODE err_code = configXAACDecoder(inBuffer, inBufferLength);
if (IA_NO_ERROR != err_code) {
ALOGW("configXAACDecoder err_code = %d", err_code);
mSignalledError = true;
notify(OMX_EventError, OMX_ErrorUndefined, err_code, NULL);
return;
}
mInputBufferCount++;
mOutputBufferCount++; // fake increase of outputBufferCount to keep the counters
// aligned
inInfo->mOwnedByUs = false;
inQueue.erase(inQueue.begin());
mLastInHeader = NULL;
inInfo = NULL;
notifyEmptyBufferDone(inHeader);
inHeader = NULL;
// Only send out port settings changed event if both sample rate
// and mNumChannels are valid.
if (mSampFreq && mNumChannels && !mIsCodecConfigFlushRequired) {
ALOGV("Configuring decoder: %d Hz, %d channels", mSampFreq, mNumChannels);
notify(OMX_EventPortSettingsChanged, 1, 0, NULL);
mOutputPortSettingsChange = AWAITING_DISABLED;
}
return;
}
if (inHeader->nFilledLen == 0) {
inInfo->mOwnedByUs = false;
inQueue.erase(inQueue.begin());
mLastInHeader = NULL;
inInfo = NULL;
notifyEmptyBufferDone(inHeader);
inHeader = NULL;
continue;
}
// Restore Offset and Length for Port reconfig case
size_t tempOffset = inHeader->nOffset;
size_t tempFilledLen = inHeader->nFilledLen;
if (mIsADTS) {
size_t adtsHeaderSize = 0;
// skip 30 bits, aac_frame_length follows.
// ssssssss ssssiiip ppffffPc ccohCCll llllllll lll?????
const uint8_t* adtsHeader = inHeader->pBuffer + inHeader->nOffset;
bool signalError = false;
if (inHeader->nFilledLen < 7) {
ALOGE(
"Audio data too short to contain even the ADTS header. "
"Got %d bytes.",
inHeader->nFilledLen);
hexdump(adtsHeader, inHeader->nFilledLen);
signalError = true;
} else {
bool protectionAbsent = (adtsHeader[1] & 1);
unsigned aac_frame_length =
((adtsHeader[3] & 3) << 11) | (adtsHeader[4] << 3) | (adtsHeader[5] >> 5);
if (inHeader->nFilledLen < aac_frame_length) {
ALOGE(
"Not enough audio data for the complete frame. "
"Got %d bytes, frame size according to the ADTS "
"header is %u bytes.",
inHeader->nFilledLen, aac_frame_length);
hexdump(adtsHeader, inHeader->nFilledLen);
signalError = true;
} else {
adtsHeaderSize = (protectionAbsent ? 7 : 9);
if (aac_frame_length < adtsHeaderSize) {
signalError = true;
} else {
inBuffer = (uint8_t*)adtsHeader + adtsHeaderSize;
inBufferLength = aac_frame_length - adtsHeaderSize;
inHeader->nOffset += adtsHeaderSize;
inHeader->nFilledLen -= adtsHeaderSize;
}
}
}
if (signalError) {
mSignalledError = true;
notify(OMX_EventError, OMX_ErrorStreamCorrupt, ERROR_MALFORMED, NULL);
return;
}
// insert buffer size and time stamp
if (mLastInHeader != inHeader) {
mCurrentTimestamp = inHeader->nTimeStamp;
mLastInHeader = inHeader;
} else {
mCurrentTimestamp = mPrevTimestamp + mOutputFrameLength * 1000000LL / mSampFreq;
}
} else {
inBuffer = inHeader->pBuffer + inHeader->nOffset;
inBufferLength = inHeader->nFilledLen;
mLastInHeader = inHeader;
mCurrentTimestamp = inHeader->nTimeStamp;
}
int numLoops = 0;
signed int prevSampleRate = mSampFreq;
signed int prevNumChannels = mNumChannels;
/* XAAC decoder expects first frame to be fed via configXAACDecoder API */
/* which should initialize the codec. Once this state is reached, call the */
/* decodeXAACStream API with same frame to decode! */
if (!mIsCodecInitialized) {
IA_ERRORCODE err_code = configXAACDecoder(inBuffer, inBufferLength);
if (IA_NO_ERROR != err_code) {
ALOGW("configXAACDecoder Failed 2 err_code = %d", err_code);
mSignalledError = true;
notify(OMX_EventError, OMX_ErrorUndefined, err_code, NULL);
return;
}
}
if (!mSampFreq || !mNumChannels) {
if ((mInputBufferCount > 2) && (mOutputBufferCount <= 1)) {
ALOGW("Invalid AAC stream");
ALOGW("mSampFreq %d mNumChannels %d ", mSampFreq, mNumChannels);
mSignalledError = true;
notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
return;
}
} else if ((mSampFreq != prevSampleRate) || (mNumChannels != prevNumChannels)) {
ALOGV("Reconfiguring decoder: %d->%d Hz, %d->%d channels", prevSampleRate,
mSampFreq, prevNumChannels, mNumChannels);
inHeader->nOffset = tempOffset;
inHeader->nFilledLen = tempFilledLen;
notify(OMX_EventPortSettingsChanged, 1, 0, NULL);
mOutputPortSettingsChange = AWAITING_DISABLED;
return;
}
signed int bytesConsumed = 0;
int errorCode = 0;
if (mIsCodecInitialized) {
mIsCodecConfigFlushRequired = true;
errorCode =
decodeXAACStream(inBuffer, inBufferLength, &bytesConsumed, &numOutBytes);
} else if (!mIsCodecConfigFlushRequired) {
ALOGW("Assumption that first frame after header initializes decoder failed!");
mSignalledError = true;
notify(OMX_EventError, OMX_ErrorUndefined, -1, NULL);
return;
}
inHeader->nFilledLen -= bytesConsumed;
inHeader->nOffset += bytesConsumed;
if (inHeader->nFilledLen != 0) {
ALOGE("All data not consumed");
}
/* In case of error, decoder would have given out empty buffer */
if ((0 != errorCode) && (0 == numOutBytes) && mIsCodecInitialized) {
numOutBytes = mOutputFrameLength * (mPcmWdSz / 8) * mNumChannels;
}
numLoops++;
if (0 == bytesConsumed) {
ALOGW("bytesConsumed is zero");
}
if (errorCode) {
/* Clear buffer for output buffer is done inside XAAC codec */
/* TODO - Check if below memset is on top of reset inside codec */
memset(mOutputBuffer, 0, numOutBytes); // TODO: check for overflow, ASAN
// Discard input buffer.
inHeader->nFilledLen = 0;
// fall through
}
if (inHeader->nFilledLen == 0) {
inInfo->mOwnedByUs = false;
mInputBufferCount++;
inQueue.erase(inQueue.begin());
mLastInHeader = NULL;
inInfo = NULL;
notifyEmptyBufferDone(inHeader);
inHeader = NULL;
} else {
ALOGV("inHeader->nFilledLen = %d", inHeader->nFilledLen);
}
if (!outQueue.empty() && numOutBytes) {
BufferInfo* outInfo = *outQueue.begin();
OMX_BUFFERHEADERTYPE* outHeader = outInfo->mHeader;
if (outHeader->nOffset != 0) {
ALOGE("outHeader->nOffset != 0 is not handled");
mSignalledError = true;
notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
return;
}
signed short* outBuffer =
reinterpret_cast<signed short*>(outHeader->pBuffer + outHeader->nOffset);
int samplesize = mNumChannels * sizeof(int16_t);
if (outHeader->nOffset + mOutputFrameLength * samplesize > outHeader->nAllocLen) {
ALOGE("buffer overflow");
mSignalledError = true;
notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
return;
}
memcpy(outBuffer, mOutputBuffer, numOutBytes);
outHeader->nFilledLen = numOutBytes;
if (mEndOfInput && !outQueue.empty()) {
outHeader->nFlags = OMX_BUFFERFLAG_EOS;
mEndOfOutput = true;
} else {
outHeader->nFlags = 0;
}
outHeader->nTimeStamp = mCurrentTimestamp;
mPrevTimestamp = mCurrentTimestamp;
mOutputBufferCount++;
outInfo->mOwnedByUs = false;
outQueue.erase(outQueue.begin());
outInfo = NULL;
notifyFillBufferDone(outHeader);
outHeader = NULL;
}
}
if (mEndOfInput) {
if (!outQueue.empty()) {
if (!mEndOfOutput) {
ALOGV(" empty block signaling EOS");
// send partial or empty block signaling EOS
mEndOfOutput = true;
BufferInfo* outInfo = *outQueue.begin();
OMX_BUFFERHEADERTYPE* outHeader = outInfo->mHeader;
outHeader->nFilledLen = 0;
outHeader->nFlags = OMX_BUFFERFLAG_EOS;
outHeader->nTimeStamp = mPrevTimestamp;
mOutputBufferCount++;
outInfo->mOwnedByUs = false;
outQueue.erase(outQueue.begin());
outInfo = NULL;
notifyFillBufferDone(outHeader);
outHeader = NULL;
}
break; // if outQueue not empty but no more output
}
}
}
}
void SoftXAAC::onPortFlushCompleted(OMX_U32 portIndex) {
if (portIndex == 0) {
// Make sure that the next buffer output does not still
// depend on fragments from the last one decoded.
// drain all existing data
if (mIsCodecInitialized) {
IA_ERRORCODE err_code = configflushDecode();
if (err_code != IA_NO_ERROR) {
ALOGE("Error in configflushDecode: Error %d", err_code);
}
}
drainDecoder();
mLastInHeader = NULL;
mEndOfInput = false;
} else {
mEndOfOutput = false;
}
}
IA_ERRORCODE SoftXAAC::configflushDecode() {
IA_ERRORCODE err_code;
UWORD32 ui_init_done;
uint32_t inBufferLength = 8203;
err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_INIT, IA_CMD_TYPE_FLUSH_MEM, NULL);
RETURN_IF_FATAL(err_code, "IA_CMD_TYPE_FLUSH_MEM");
err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_SET_INPUT_BYTES, 0, &inBufferLength);
RETURN_IF_FATAL(err_code, "IA_API_CMD_SET_INPUT_BYTES");
err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_INIT, IA_CMD_TYPE_FLUSH_MEM, NULL);
RETURN_IF_FATAL(err_code, "IA_CMD_TYPE_FLUSH_MEM");
err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_INIT, IA_CMD_TYPE_INIT_DONE_QUERY,
&ui_init_done);
RETURN_IF_FATAL(err_code, "IA_CMD_TYPE_INIT_DONE_QUERY");
if (ui_init_done) {
err_code = getXAACStreamInfo();
RETURN_IF_FATAL(err_code, "getXAACStreamInfo");
ALOGV(
"Found Codec with below config---\nsampFreq %d\nnumChannels %d\npcmWdSz "
"%d\nchannelMask %d\noutputFrameLength %d",
mSampFreq, mNumChannels, mPcmWdSz, mChannelMask, mOutputFrameLength);
mIsCodecInitialized = true;
}
return IA_NO_ERROR;
}
IA_ERRORCODE SoftXAAC::drainDecoder() {
return IA_NO_ERROR;
}
void SoftXAAC::onReset() {
drainDecoder();
// reset the "configured" state
mInputBufferCount = 0;
mOutputBufferCount = 0;
mEndOfInput = false;
mEndOfOutput = false;
mLastInHeader = NULL;
mSignalledError = false;
mOutputPortSettingsChange = NONE;
}
void SoftXAAC::onPortEnableCompleted(OMX_U32 portIndex, bool enabled) {
if (portIndex != 1) {
return;
}
switch (mOutputPortSettingsChange) {
case NONE:
break;
case AWAITING_DISABLED: {
CHECK(!enabled);
mOutputPortSettingsChange = AWAITING_ENABLED;
break;
}
default: {
CHECK_EQ((int)mOutputPortSettingsChange, (int)AWAITING_ENABLED);
CHECK(enabled);
mOutputPortSettingsChange = NONE;
break;
}
}
}
IA_ERRORCODE SoftXAAC::initXAACDecoder() {
LOOPIDX i;
/* Error code */
IA_ERRORCODE err_code = IA_NO_ERROR;
/* First part */
/* Error Handler Init */
/* Get Library Name, Library Version and API Version */
/* Initialize API structure + Default config set */
/* Set config params from user */
/* Initialize memory tables */
/* Get memory information and allocate memory */
/* Memory variables */
UWORD32 ui_proc_mem_tabs_size;
/* API size */
UWORD32 pui_api_size;
pVOID pv_alloc_ptr;
mInputBufferSize = 0;
mInputBuffer = 0;
mOutputBuffer = 0;
/* Process struct initing end */
/* ******************************************************************/
/* Initialize API structure and set config params to default */
/* ******************************************************************/
/* Get the API size */
err_code = ixheaacd_dec_api(NULL, IA_API_CMD_GET_API_SIZE, 0, &pui_api_size);
RETURN_IF_FATAL(err_code, "IA_API_CMD_GET_API_SIZE");
/* Allocate memory for API */
mXheaacCodecHandle = memalign(4, pui_api_size);
if (mXheaacCodecHandle == NULL) {
ALOGE("malloc for pui_api_size + 4 >> %d Failed", pui_api_size + 4);
return IA_FATAL_ERROR;
}
mMemoryVec.push(mXheaacCodecHandle);
/* Set the config params to default values */
err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_INIT,
IA_CMD_TYPE_INIT_API_PRE_CONFIG_PARAMS, NULL);
RETURN_IF_FATAL(err_code, "IA_CMD_TYPE_INIT_API_PRE_CONFIG_PARAMS");
#ifdef ENABLE_MPEG_D_DRC
/* Get the API size */
err_code = ia_drc_dec_api(NULL, IA_API_CMD_GET_API_SIZE, 0, &pui_api_size);
RETURN_IF_FATAL(err_code, "IA_API_CMD_GET_API_SIZE");
/* Allocate memory for API */
mMpegDDrcHandle = memalign(4, pui_api_size);
if (mMpegDDrcHandle == NULL) {
ALOGE("malloc for drc api structure Failed");
return IA_FATAL_ERROR;
}
mMemoryVec.push(mMpegDDrcHandle);
memset(mMpegDDrcHandle, 0, pui_api_size);
/* Set the config params to default values */
err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_INIT,
IA_CMD_TYPE_INIT_API_PRE_CONFIG_PARAMS, NULL);
RETURN_IF_FATAL(err_code, "IA_CMD_TYPE_INIT_API_PRE_CONFIG_PARAMS");
#endif
/* ******************************************************************/
/* Set config parameters */
/* ******************************************************************/
UWORD32 ui_mp4_flag = 1;
err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_SET_CONFIG_PARAM,
IA_ENHAACPLUS_DEC_CONFIG_PARAM_ISMP4, &ui_mp4_flag);
RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_CONFIG_PARAM_ISMP4");
/* ******************************************************************/
/* Initialize Memory info tables */
/* ******************************************************************/
/* Get memory info tables size */
err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_MEMTABS_SIZE, 0,
&ui_proc_mem_tabs_size);
RETURN_IF_FATAL(err_code, "IA_API_CMD_GET_MEMTABS_SIZE");
pv_alloc_ptr = memalign(4, ui_proc_mem_tabs_size);
if (pv_alloc_ptr == NULL) {
ALOGE("Malloc for size (ui_proc_mem_tabs_size + 4) = %d failed!",
ui_proc_mem_tabs_size + 4);
return IA_FATAL_ERROR;
}
mMemoryVec.push(pv_alloc_ptr);
/* Set pointer for process memory tables */
err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_SET_MEMTABS_PTR, 0, pv_alloc_ptr);
RETURN_IF_FATAL(err_code, "IA_API_CMD_SET_MEMTABS_PTR");
/* initialize the API, post config, fill memory tables */
err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_INIT,
IA_CMD_TYPE_INIT_API_POST_CONFIG_PARAMS, NULL);
RETURN_IF_FATAL(err_code, "IA_CMD_TYPE_INIT_API_POST_CONFIG_PARAMS");
/* ******************************************************************/
/* Allocate Memory with info from library */
/* ******************************************************************/
/* There are four different types of memories, that needs to be allocated */
/* persistent,scratch,input and output */
for (i = 0; i < 4; i++) {
int ui_size = 0, ui_alignment = 0, ui_type = 0;
pVOID pv_alloc_ptr;
/* Get memory size */
err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_MEM_INFO_SIZE, i, &ui_size);
RETURN_IF_FATAL(err_code, "IA_API_CMD_GET_MEM_INFO_SIZE");
/* Get memory alignment */
err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_MEM_INFO_ALIGNMENT, i,
&ui_alignment);
RETURN_IF_FATAL(err_code, "IA_API_CMD_GET_MEM_INFO_ALIGNMENT");
/* Get memory type */
err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_MEM_INFO_TYPE, i, &ui_type);
RETURN_IF_FATAL(err_code, "IA_API_CMD_GET_MEM_INFO_TYPE");
pv_alloc_ptr = memalign(ui_alignment, ui_size);
if (pv_alloc_ptr == NULL) {
ALOGE("Malloc for size (ui_size + ui_alignment) = %d failed!", ui_size + ui_alignment);
return IA_FATAL_ERROR;
}
mMemoryVec.push(pv_alloc_ptr);
/* Set the buffer pointer */
err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_SET_MEM_PTR, i, pv_alloc_ptr);
RETURN_IF_FATAL(err_code, "IA_API_CMD_SET_MEM_PTR");
if (ui_type == IA_MEMTYPE_INPUT) {
mInputBuffer = (pWORD8)pv_alloc_ptr;
mInputBufferSize = ui_size;
}
if (ui_type == IA_MEMTYPE_OUTPUT) {
mOutputBuffer = (pWORD8)pv_alloc_ptr;
}
}
/* End first part */
return IA_NO_ERROR;
}
IA_ERRORCODE SoftXAAC::configXAACDecoder(uint8_t* inBuffer, uint32_t inBufferLength) {
UWORD32 ui_init_done;
int32_t i_bytes_consumed;
if (mInputBufferSize < inBufferLength) {
ALOGE("Cannot config AAC, input buffer size %d < inBufferLength %d", mInputBufferSize,
inBufferLength);
return false;
}
/* Copy the buffer passed by Android plugin to codec input buffer */
memcpy(mInputBuffer, inBuffer, inBufferLength);
/* Set number of bytes to be processed */
IA_ERRORCODE err_code =
ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_SET_INPUT_BYTES, 0, &inBufferLength);
RETURN_IF_FATAL(err_code, "IA_API_CMD_SET_INPUT_BYTES");
if (mIsCodecConfigFlushRequired) {
/* If codec is already initialized, then GA header is passed again */
/* Need to call the Flush API instead of INIT_PROCESS */
mIsCodecInitialized = false; /* Codec needs to be Reinitialized after flush */
err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_INIT, IA_CMD_TYPE_GA_HDR, NULL);
RETURN_IF_FATAL(err_code, "IA_CMD_TYPE_GA_HDR");
} else {
/* Initialize the process */
err_code =
ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_INIT, IA_CMD_TYPE_INIT_PROCESS, NULL);
RETURN_IF_FATAL(err_code, "IA_CMD_TYPE_INIT_PROCESS");
}
/* Checking for end of initialization */
err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_INIT, IA_CMD_TYPE_INIT_DONE_QUERY,
&ui_init_done);
RETURN_IF_FATAL(err_code, "IA_CMD_TYPE_INIT_DONE_QUERY");
/* How much buffer is used in input buffers */
err_code =
ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_CURIDX_INPUT_BUF, 0, &i_bytes_consumed);
RETURN_IF_FATAL(err_code, "IA_API_CMD_GET_CURIDX_INPUT_BUF");
if (ui_init_done) {
err_code = getXAACStreamInfo();
RETURN_IF_FATAL(err_code, "getXAACStreamInfo");
ALOGI(
"Found Codec with below config---\nsampFreq %d\nnumChannels %d\npcmWdSz "
"%d\nchannelMask %d\noutputFrameLength %d",
mSampFreq, mNumChannels, mPcmWdSz, mChannelMask, mOutputFrameLength);
mIsCodecInitialized = true;
#ifdef ENABLE_MPEG_D_DRC
err_code = configMPEGDDrc();
RETURN_IF_FATAL(err_code, "configMPEGDDrc");
#endif
}
return IA_NO_ERROR;
}
IA_ERRORCODE SoftXAAC::initMPEGDDDrc() {
IA_ERRORCODE err_code = IA_NO_ERROR;
int i;
for (i = 0; i < (WORD32)2; i++) {
WORD32 ui_size, ui_alignment, ui_type;
pVOID pv_alloc_ptr;
/* Get memory size */
err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_GET_MEM_INFO_SIZE, i, &ui_size);
RETURN_IF_FATAL(err_code, "IA_API_CMD_GET_MEM_INFO_SIZE");
/* Get memory alignment */
err_code =
ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_GET_MEM_INFO_ALIGNMENT, i, &ui_alignment);
RETURN_IF_FATAL(err_code, "IA_API_CMD_GET_MEM_INFO_ALIGNMENT");
/* Get memory type */
err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_GET_MEM_INFO_TYPE, i, &ui_type);
RETURN_IF_FATAL(err_code, "IA_API_CMD_GET_MEM_INFO_TYPE");
pv_alloc_ptr = memalign(4, ui_size);
if (pv_alloc_ptr == NULL) {
ALOGE(" Cannot create requested memory %d", ui_size);
return IA_FATAL_ERROR;
}
mDrcMemoryVec.push(pv_alloc_ptr);
/* Set the buffer pointer */
err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_MEM_PTR, i, pv_alloc_ptr);
RETURN_IF_FATAL(err_code, "IA_API_CMD_SET_MEM_PTR");
}
WORD32 ui_size;
ui_size = 8192 * 2;
mDrcInBuf = (int8_t*)memalign(4, ui_size);
if (mDrcInBuf == NULL) {
ALOGE(" Cannot create requested memory %d", ui_size);
return IA_FATAL_ERROR;
}
mDrcMemoryVec.push(mDrcInBuf);
err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_MEM_PTR, 2, mDrcInBuf);
RETURN_IF_FATAL(err_code, "IA_API_CMD_SET_MEM_PTR");
mDrcOutBuf = (int8_t*)memalign(4, ui_size);
if (mDrcOutBuf == NULL) {
ALOGE(" Cannot create requested memory %d", ui_size);
return IA_FATAL_ERROR;
}
mDrcMemoryVec.push(mDrcOutBuf);
err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_MEM_PTR, 3, mDrcOutBuf);
RETURN_IF_FATAL(err_code, "IA_API_CMD_SET_MEM_PTR");
return IA_NO_ERROR;
}
IA_ERRORCODE SoftXAAC::configMPEGDDrc() {
IA_ERRORCODE err_code = IA_NO_ERROR;
int i_effect_type;
int i_loud_norm;
int i_target_loudness;
unsigned int i_sbr_mode;
int i;
int ui_proc_mem_tabs_size = 0;
pVOID pv_alloc_ptr = NULL;
#ifdef ENABLE_MPEG_D_DRC
{
/* Sampling Frequency */
err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_CONFIG_PARAM,
IA_DRC_DEC_CONFIG_PARAM_SAMP_FREQ, &mSampFreq);
RETURN_IF_FATAL(err_code, "IA_DRC_DEC_CONFIG_PARAM_SAMP_FREQ");
/* Total Number of Channels */
err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_CONFIG_PARAM,
IA_DRC_DEC_CONFIG_PARAM_NUM_CHANNELS, &mNumChannels);
RETURN_IF_FATAL(err_code, "IA_DRC_DEC_CONFIG_PARAM_NUM_CHANNELS");
/* PCM word size */
err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_CONFIG_PARAM,
IA_DRC_DEC_CONFIG_PARAM_PCM_WDSZ, &mPcmWdSz);
RETURN_IF_FATAL(err_code, "IA_DRC_DEC_CONFIG_PARAM_PCM_WDSZ");
/*Set Effect Type*/
err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_CONFIG_PARAM,
IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_EFFECT_TYPE, &i_effect_type);
RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_EFFECT_TYPE");
err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_CONFIG_PARAM,
IA_DRC_DEC_CONFIG_DRC_EFFECT_TYPE, &i_effect_type);
RETURN_IF_FATAL(err_code, "IA_DRC_DEC_CONFIG_DRC_EFFECT_TYPE");
/*Set target loudness */
err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_CONFIG_PARAM,
IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_TARGET_LOUDNESS,
&i_target_loudness);
RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_TARGET_LOUDNESS");
err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_CONFIG_PARAM,
IA_DRC_DEC_CONFIG_DRC_TARGET_LOUDNESS, &i_target_loudness);
RETURN_IF_FATAL(err_code, "IA_DRC_DEC_CONFIG_DRC_TARGET_LOUDNESS");
/*Set loud_norm_flag*/
err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_CONFIG_PARAM,
IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_LOUD_NORM, &i_loud_norm);
RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_LOUD_NORM");
err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_CONFIG_PARAM,
IA_DRC_DEC_CONFIG_DRC_LOUD_NORM, &i_loud_norm);
RETURN_IF_FATAL(err_code, "IA_DRC_DEC_CONFIG_DRC_LOUD_NORM");
err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_CONFIG_PARAM,
IA_ENHAACPLUS_DEC_CONFIG_PARAM_SBR_MODE, &i_sbr_mode);
RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_CONFIG_PARAM_SBR_MODE");
/* Get memory info tables size */
err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_GET_MEMTABS_SIZE, 0,
&ui_proc_mem_tabs_size);
RETURN_IF_FATAL(err_code, "IA_API_CMD_GET_MEMTABS_SIZE");
pv_alloc_ptr = memalign(4, ui_proc_mem_tabs_size);
if (pv_alloc_ptr == NULL) {
ALOGE("Cannot create requested memory %d", ui_proc_mem_tabs_size);
return IA_FATAL_ERROR;
}
memset(pv_alloc_ptr, 0, ui_proc_mem_tabs_size);
mMemoryVec.push(pv_alloc_ptr);
/* Set pointer for process memory tables */
err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_MEMTABS_PTR, 0,
pv_alloc_ptr);
RETURN_IF_FATAL(err_code, "IA_API_CMD_SET_MEMTABS_PTR");
err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_INIT,
IA_CMD_TYPE_INIT_API_POST_CONFIG_PARAMS, NULL);
RETURN_IF_FATAL(err_code, "IA_CMD_TYPE_INIT_API_POST_CONFIG_PARAMS");
/* Free any memory that is allocated for MPEG D Drc so far */
deInitMPEGDDDrc();
err_code = initMPEGDDDrc();
if (err_code != IA_NO_ERROR) {
ALOGE("initMPEGDDDrc failed with error %d", err_code);
deInitMPEGDDDrc();
return err_code;
}
/* DRC buffers
buf[0] - contains extension element pay load loudness related
buf[1] - contains extension element pay load*/
{
VOID* p_array[2][16];
WORD32 ii;
WORD32 buf_sizes[2][16];
WORD32 num_elements;
WORD32 num_config_ext;
WORD32 bit_str_fmt = 1;
WORD32 uo_num_chan;
memset(buf_sizes, 0, 32 * sizeof(WORD32));
err_code =
ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_CONFIG_PARAM,
IA_ENHAACPLUS_DEC_CONFIG_EXT_ELE_BUF_SIZES, &buf_sizes[0][0]);
RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_CONFIG_EXT_ELE_BUF_SIZES");
err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_CONFIG_PARAM,
IA_ENHAACPLUS_DEC_CONFIG_EXT_ELE_PTR, &p_array);
RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_CONFIG_EXT_ELE_PTR");
err_code =
ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_INIT, IA_CMD_TYPE_INIT_SET_BUFF_PTR, 0);
RETURN_IF_FATAL(err_code, "IA_CMD_TYPE_INIT_SET_BUFF_PTR");
err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_CONFIG_PARAM,
IA_ENHAACPLUS_DEC_CONFIG_NUM_ELE, &num_elements);
RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_CONFIG_NUM_ELE");
err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_CONFIG_PARAM,
IA_ENHAACPLUS_DEC_CONFIG_NUM_CONFIG_EXT, &num_config_ext);
RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_CONFIG_NUM_CONFIG_EXT");
for (ii = 0; ii < num_config_ext; ii++) {
/*copy loudness bitstream*/
if (buf_sizes[0][ii] > 0) {
memcpy(mDrcInBuf, p_array[0][ii], buf_sizes[0][ii]);
/*Set bitstream_split_format */
err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_CONFIG_PARAM,
IA_DRC_DEC_CONFIG_PARAM_BITS_FORMAT, &bit_str_fmt);
RETURN_IF_FATAL(err_code, "IA_DRC_DEC_CONFIG_PARAM_BITS_FORMAT");
/* Set number of bytes to be processed */
err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_INPUT_BYTES_IL_BS, 0,
&buf_sizes[0][ii]);
RETURN_IF_FATAL(err_code, "IA_API_CMD_SET_INPUT_BYTES_IL_BS");
/* Execute process */
err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_INIT,
IA_CMD_TYPE_INIT_CPY_IL_BSF_BUFF, NULL);
RETURN_IF_FATAL(err_code, "IA_CMD_TYPE_INIT_CPY_IL_BSF_BUFF");
mDRCFlag = 1;
}
}
for (ii = 0; ii < num_elements; ii++) {
/*copy config bitstream*/
if (buf_sizes[1][ii] > 0) {
memcpy(mDrcInBuf, p_array[1][ii], buf_sizes[1][ii]);
/* Set number of bytes to be processed */
/*Set bitstream_split_format */
err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_CONFIG_PARAM,
IA_DRC_DEC_CONFIG_PARAM_BITS_FORMAT, &bit_str_fmt);
RETURN_IF_FATAL(err_code, "IA_DRC_DEC_CONFIG_PARAM_BITS_FORMAT");
err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_INPUT_BYTES_IC_BS, 0,
&buf_sizes[1][ii]);
RETURN_IF_FATAL(err_code, "IA_API_CMD_SET_INPUT_BYTES_IC_BS");
/* Execute process */
err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_INIT,
IA_CMD_TYPE_INIT_CPY_IC_BSF_BUFF, NULL);
RETURN_IF_FATAL(err_code, "IA_CMD_TYPE_INIT_CPY_IC_BSF_BUFF");
mDRCFlag = 1;
}
}
if (mDRCFlag == 1) {
mMpegDDRCPresent = 1;
} else {
mMpegDDRCPresent = 0;
}
/*Read interface buffer config file bitstream*/
if (mMpegDDRCPresent == 1) {
WORD32 interface_is_present = 1;
WORD32 frame_length;
if (i_sbr_mode != 0) {
if (i_sbr_mode == 1) {
frame_length = 2048;
} else if (i_sbr_mode == 3) {
frame_length = 4096;
} else {
frame_length = 1024;
}
} else {
frame_length = 4096;
}
err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_CONFIG_PARAM,
IA_DRC_DEC_CONFIG_PARAM_FRAME_SIZE, &frame_length);
RETURN_IF_FATAL(err_code, "IA_DRC_DEC_CONFIG_PARAM_FRAME_SIZE");
err_code =
ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_CONFIG_PARAM,
IA_DRC_DEC_CONFIG_PARAM_INT_PRESENT, &interface_is_present);
RETURN_IF_FATAL(err_code, "IA_DRC_DEC_CONFIG_PARAM_INT_PRESENT");
/* Execute process */
err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_INIT,
IA_CMD_TYPE_INIT_CPY_IN_BSF_BUFF, NULL);
RETURN_IF_FATAL(err_code, "IA_CMD_TYPE_INIT_CPY_IN_BSF_BUFF");
err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_INIT,
IA_CMD_TYPE_INIT_PROCESS, NULL);
RETURN_IF_FATAL(err_code, "IA_CMD_TYPE_INIT_PROCESS");
err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_GET_CONFIG_PARAM,
IA_DRC_DEC_CONFIG_PARAM_NUM_CHANNELS, &uo_num_chan);
RETURN_IF_FATAL(err_code, "IA_DRC_DEC_CONFIG_PARAM_NUM_CHANNELS");
}
}
}
#endif
return IA_NO_ERROR;
}
IA_ERRORCODE SoftXAAC::decodeXAACStream(uint8_t* inBuffer, uint32_t inBufferLength,
int32_t* bytesConsumed, int32_t* outBytes) {
if (mInputBufferSize < inBufferLength) {
ALOGE("Cannot config AAC, input buffer size %d < inBufferLength %d", mInputBufferSize,
inBufferLength);
return -1;
}
/* Copy the buffer passed by Android plugin to codec input buffer */
memcpy(mInputBuffer, inBuffer, inBufferLength);
/* Set number of bytes to be processed */
IA_ERRORCODE err_code =
ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_SET_INPUT_BYTES, 0, &inBufferLength);
RETURN_IF_FATAL(err_code, "IA_API_CMD_SET_INPUT_BYTES");
/* Execute process */
err_code =
ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_EXECUTE, IA_CMD_TYPE_DO_EXECUTE, NULL);
RETURN_IF_FATAL(err_code, "IA_CMD_TYPE_DO_EXECUTE");
UWORD32 ui_exec_done;
/* Checking for end of processing */
err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_EXECUTE, IA_CMD_TYPE_DONE_QUERY,
&ui_exec_done);
RETURN_IF_FATAL(err_code, "IA_CMD_TYPE_DONE_QUERY");
#ifdef ENABLE_MPEG_D_DRC
{
if (ui_exec_done != 1) {
VOID* p_array; // ITTIAM:buffer to handle gain payload
WORD32 buf_size = 0; // ITTIAM:gain payload length
WORD32 bit_str_fmt = 1;
WORD32 gain_stream_flag = 1;
err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_CONFIG_PARAM,
IA_ENHAACPLUS_DEC_CONFIG_GAIN_PAYLOAD_LEN, &buf_size);
RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_CONFIG_GAIN_PAYLOAD_LEN");
err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_CONFIG_PARAM,
IA_ENHAACPLUS_DEC_CONFIG_GAIN_PAYLOAD_BUF, &p_array);
RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_CONFIG_GAIN_PAYLOAD_BUF");
if (buf_size > 0) {
/*Set bitstream_split_format */
err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_CONFIG_PARAM,
IA_DRC_DEC_CONFIG_PARAM_BITS_FORMAT, &bit_str_fmt);
RETURN_IF_FATAL(err_code, "IA_DRC_DEC_CONFIG_PARAM_BITS_FORMAT");
memcpy(mDrcInBuf, p_array, buf_size);
/* Set number of bytes to be processed */
err_code =
ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_INPUT_BYTES_BS, 0, &buf_size);
RETURN_IF_FATAL(err_code, "IA_DRC_DEC_CONFIG_PARAM_BITS_FORMAT");
err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_CONFIG_PARAM,
IA_DRC_DEC_CONFIG_GAIN_STREAM_FLAG, &gain_stream_flag);
RETURN_IF_FATAL(err_code, "IA_DRC_DEC_CONFIG_PARAM_BITS_FORMAT");
/* Execute process */
err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_INIT,
IA_CMD_TYPE_INIT_CPY_BSF_BUFF, NULL);
RETURN_IF_FATAL(err_code, "IA_DRC_DEC_CONFIG_PARAM_BITS_FORMAT");
mMpegDDRCPresent = 1;
}
}
}
#endif
/* How much buffer is used in input buffers */
err_code =
ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_CURIDX_INPUT_BUF, 0, bytesConsumed);
RETURN_IF_FATAL(err_code, "IA_API_CMD_GET_CURIDX_INPUT_BUF");
/* Get the output bytes */
err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_OUTPUT_BYTES, 0, outBytes);
RETURN_IF_FATAL(err_code, "IA_API_CMD_GET_OUTPUT_BYTES");
#ifdef ENABLE_MPEG_D_DRC
if (mMpegDDRCPresent == 1) {
memcpy(mDrcInBuf, mOutputBuffer, *outBytes);
err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_INPUT_BYTES, 0, outBytes);
RETURN_IF_FATAL(err_code, "IA_API_CMD_SET_INPUT_BYTES");
err_code =
ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_EXECUTE, IA_CMD_TYPE_DO_EXECUTE, NULL);
RETURN_IF_FATAL(err_code, "IA_CMD_TYPE_DO_EXECUTE");
memcpy(mOutputBuffer, mDrcOutBuf, *outBytes);
}
#endif
return IA_NO_ERROR;
}
IA_ERRORCODE SoftXAAC::deInitXAACDecoder() {
ALOGI("deInitXAACDecoder");
/* Tell that the input is over in this buffer */
IA_ERRORCODE err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_INPUT_OVER, 0, NULL);
/* Irrespective of error returned in IA_API_CMD_INPUT_OVER, free allocated memory */
for (void* buf : mMemoryVec) {
free(buf);
}
mMemoryVec.clear();
return err_code;
}
IA_ERRORCODE SoftXAAC::deInitMPEGDDDrc() {
ALOGI("deInitMPEGDDDrc");
for (void* buf : mDrcMemoryVec) {
free(buf);
}
mDrcMemoryVec.clear();
return IA_NO_ERROR;
}
IA_ERRORCODE SoftXAAC::getXAACStreamInfo() {
IA_ERRORCODE err_code = IA_NO_ERROR;
/* Sampling frequency */
err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_CONFIG_PARAM,
IA_ENHAACPLUS_DEC_CONFIG_PARAM_SAMP_FREQ, &mSampFreq);
RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_CONFIG_PARAM_SAMP_FREQ");
/* Total Number of Channels */
err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_CONFIG_PARAM,
IA_ENHAACPLUS_DEC_CONFIG_PARAM_NUM_CHANNELS, &mNumChannels);
RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_CONFIG_PARAM_NUM_CHANNELS");
if (mNumChannels > MAX_CHANNEL_COUNT) {
ALOGE(" No of channels are more than max channels\n");
return IA_FATAL_ERROR;
}
/* PCM word size */
err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_CONFIG_PARAM,
IA_ENHAACPLUS_DEC_CONFIG_PARAM_PCM_WDSZ, &mPcmWdSz);
RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_CONFIG_PARAM_PCM_WDSZ");
if ((mPcmWdSz / 8) != 2) {
ALOGE("Invalid Number of bytes per sample: %d, Expected is 2", mPcmWdSz);
return IA_FATAL_ERROR;
}
/* channel mask to tell the arrangement of channels in bit stream */
err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_CONFIG_PARAM,
IA_ENHAACPLUS_DEC_CONFIG_PARAM_CHANNEL_MASK, &mChannelMask);
RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_CONFIG_PARAM_CHANNEL_MASK");
/* Channel mode to tell MONO/STEREO/DUAL-MONO/NONE_OF_THESE */
UWORD32 ui_channel_mode;
err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_CONFIG_PARAM,
IA_ENHAACPLUS_DEC_CONFIG_PARAM_CHANNEL_MODE, &ui_channel_mode);
RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_CONFIG_PARAM_CHANNEL_MODE");
if (ui_channel_mode == 0)
ALOGV("Channel Mode: MONO_OR_PS\n");
else if (ui_channel_mode == 1)
ALOGV("Channel Mode: STEREO\n");
else if (ui_channel_mode == 2)
ALOGV("Channel Mode: DUAL-MONO\n");
else
ALOGV("Channel Mode: NONE_OF_THESE or MULTICHANNEL\n");
/* Channel mode to tell SBR PRESENT/NOT_PRESENT */
UWORD32 ui_sbr_mode;
err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_CONFIG_PARAM,
IA_ENHAACPLUS_DEC_CONFIG_PARAM_SBR_MODE, &ui_sbr_mode);
RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_CONFIG_PARAM_SBR_MODE");
if (ui_sbr_mode == 0)
ALOGV("SBR Mode: NOT_PRESENT\n");
else if (ui_sbr_mode == 1)
ALOGV("SBR Mode: PRESENT\n");
else
ALOGV("SBR Mode: ILLEGAL\n");
/* mOutputFrameLength = 1024 * (1 + SBR_MODE) for AAC */
/* For USAC it could be 1024 * 3 , support to query */
/* not yet added in codec */
mOutputFrameLength = 1024 * (1 + ui_sbr_mode);
ALOGI("mOutputFrameLength %d ui_sbr_mode %d", mOutputFrameLength, ui_sbr_mode);
return IA_NO_ERROR;
}
IA_ERRORCODE SoftXAAC::setXAACDRCInfo(int32_t drcCut, int32_t drcBoost, int32_t drcRefLevel,
int32_t drcHeavyCompression
#ifdef ENABLE_MPEG_D_DRC
,
int32_t drEffectType
#endif
) {
IA_ERRORCODE err_code = IA_NO_ERROR;
int32_t ui_drc_enable = 1;
int32_t i_effect_type, i_target_loudness, i_loud_norm;
err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_SET_CONFIG_PARAM,
IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_ENABLE, &ui_drc_enable);
RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_ENABLE");
if (drcCut != -1) {
err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_SET_CONFIG_PARAM,
IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_CUT, &drcCut);
RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_CUT");
}
if (drcBoost != -1) {
err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_SET_CONFIG_PARAM,
IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_BOOST, &drcBoost);
RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_BOOST");
}
if (drcRefLevel != -1) {
err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_SET_CONFIG_PARAM,
IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_TARGET_LEVEL, &drcRefLevel);
RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_TARGET_LEVEL");
}
#ifdef ENABLE_MPEG_D_DRC
if (drcRefLevel != -1) {
err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_SET_CONFIG_PARAM,
IA_ENHAACPLUS_DEC_DRC_TARGET_LOUDNESS, &drcRefLevel);
RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_DRC_TARGET_LOUDNESS");
}
#endif
if (drcHeavyCompression != -1) {
err_code =
ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_SET_CONFIG_PARAM,
IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_HEAVY_COMP, &drcHeavyCompression);
RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_HEAVY_COMP");
}
#ifdef ENABLE_MPEG_D_DRC
err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_SET_CONFIG_PARAM,
IA_ENHAACPLUS_DEC_DRC_EFFECT_TYPE, &drEffectType);
RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_DRC_EFFECT_TYPE");
#endif
#ifdef ENABLE_MPEG_D_DRC
/*Set Effect Type*/
err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_CONFIG_PARAM,
IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_EFFECT_TYPE, &i_effect_type);
RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_EFFECT_TYPE");
err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_CONFIG_PARAM,
IA_DRC_DEC_CONFIG_DRC_EFFECT_TYPE, &i_effect_type);
RETURN_IF_FATAL(err_code, "IA_DRC_DEC_CONFIG_DRC_EFFECT_TYPE");
/*Set target loudness */
err_code =
ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_CONFIG_PARAM,
IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_TARGET_LOUDNESS, &i_target_loudness);
RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_TARGET_LOUDNESS");
err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_CONFIG_PARAM,
IA_DRC_DEC_CONFIG_DRC_TARGET_LOUDNESS, &i_target_loudness);
RETURN_IF_FATAL(err_code, "IA_DRC_DEC_CONFIG_DRC_TARGET_LOUDNESS");
/*Set loud_norm_flag*/
err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_CONFIG_PARAM,
IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_LOUD_NORM, &i_loud_norm);
RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_LOUD_NORM");
err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_CONFIG_PARAM,
IA_DRC_DEC_CONFIG_DRC_LOUD_NORM, &i_loud_norm);
RETURN_IF_FATAL(err_code, "IA_DRC_DEC_CONFIG_DRC_LOUD_NORM");
#endif
return IA_NO_ERROR;
}
} // namespace android
android::SoftOMXComponent* createSoftOMXComponent(const char* name,
const OMX_CALLBACKTYPE* callbacks,
OMX_PTR appData, OMX_COMPONENTTYPE** component) {
ALOGI("createSoftOMXComponent for SoftXAACDEC");
return new android::SoftXAAC(name, callbacks, appData, component);
}