blob: eda0cd83a4c1ec990c537753d5c226db049e5e59 [file] [log] [blame]
/* ------------------------------------------------------------------
* Copyright (C) 1998-2009 PacketVideo
*
* 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.
* -------------------------------------------------------------------
*/
/*----------------------------------------------------------------------------
; INCLUDES
----------------------------------------------------------------------------*/
#include "aac_enc.h"
#ifndef USE_HEAAC
#define BITRATE_DEFAULT 128000
#else
#define BITRATE_DEFAULT 56000
#endif
#define BANDWIDTH_DEFAULT 0
OmxAacEncoder::OmxAacEncoder()
{
iAacEncoder = NULL;
iAacInputBuffer = NULL;
iAacOutputBuffer = NULL;
iAscSize = 12;
iAscFlag = OMX_FALSE;
oscl_memset(&iAacEncConfig, 0, sizeof(ENC_CONFIGURATION));
}
OMX_S32 OmxAacEncoder::AacEncConfigDefaultSettings(ENC_CONFIGURATION* pConfig)
{
pConfig->bitrate = BITRATE_DEFAULT; /* bitstream bitrate */
pConfig->bitrateMode = 0; /* constant bitrate */
pConfig->bandwidth = BANDWIDTH_DEFAULT;
pConfig->dualMono = 0; /* no dualMono by default */
#ifndef USE_HEAAC
pConfig->useAOT = AOT_AAC_LC; /* AAC-LC by default */
#else
pConfig->useAOT = AOT_SBR; /* otherwise AAC/SBR */
#endif
pConfig->useTransmux = TT_MP4_ADTS; /* ADTS header by default */
pConfig->useCRC = 0; /* no CRC by default */
pConfig->useTns = 1; /* TNS activated by default */
pConfig->usePns = 1; /* PNS activated by default.
* Depending on channelBitrate this might be set to 0 later */
#ifdef AFTER_BURNER
pConfig->useRequant = 1; /* Afterburner activated by default */
#endif
pConfig->ancFlag = 0; /* no ancillary data by default */
pConfig->downmix = 0;
return 0;
}
/* Decoder Initialization function */
OMX_BOOL OmxAacEncoder::AacEncInit(OMX_AUDIO_PARAM_PCMMODETYPE aPcmMode,
OMX_AUDIO_PARAM_AACPROFILETYPE aAacParam,
OMX_U32* aInputFrameLength)
{
OMX_S32 Status;
AAC_ENCODER_ERROR ErrorStatus;
// Configure Encoder
Status = aacEncConfigure(&iAacEncoder, &iAacEncConfig);
if (Status)
{
// Failure occurred during initialization so return right away
return OMX_FALSE;
}
// Get default settings
AacEncConfigDefaultSettings(&iAacEncConfig);
//Now Apply the parameter settings from the client
iAacEncConfig.sampleRate = aAacParam.nSampleRate;
iAacEncConfig.nChannelsIn = aPcmMode.nChannels;
iAacEncConfig.nChannelsOut = aAacParam.nChannels;
iAacEncConfig.bitrate = aAacParam.nBitRate;
if (0 != aAacParam.nAudioBandWidth)
{
iAacEncConfig.bandwidth = aAacParam.nAudioBandWidth;
}
if (OMX_AUDIO_ChannelModeDual == aAacParam.eChannelMode)
{
iAacEncConfig.dualMono = 1;
}
if (OMX_AUDIO_ChannelModeMono == aAacParam.eChannelMode)
{
iAacEncConfig.nChannelsOut = 1;
}
if (OMX_AUDIO_AACObjectMain == aAacParam.eAACProfile)
{
iAacEncConfig.useAOT = AOT_AAC_MAIN;
}
else if (OMX_AUDIO_AACObjectLC == aAacParam.eAACProfile)
{
iAacEncConfig.useAOT = AOT_AAC_LC;
}
else if (OMX_AUDIO_AACObjectSSR == aAacParam.eAACProfile)
{
iAacEncConfig.useAOT = AOT_AAC_SSR;
}
else if (OMX_AUDIO_AACObjectLTP == aAacParam.eAACProfile)
{
iAacEncConfig.useAOT = AOT_AAC_LTP;
}
else if (OMX_AUDIO_AACObjectHE == aAacParam.eAACProfile)
{
iAacEncConfig.useAOT = AOT_SBR;
}
else if (OMX_AUDIO_AACObjectScalable == aAacParam.eAACProfile)
{
iAacEncConfig.useAOT = AOT_AAC_SCAL;
}
else if (OMX_AUDIO_AACObjectERLC == aAacParam.eAACProfile)
{
iAacEncConfig.useAOT = AOT_ER_AAC_LC;
}
else if (OMX_AUDIO_AACObjectLD == aAacParam.eAACProfile)
{
iAacEncConfig.useAOT = AOT_ER_AAC_LD;
}
else if (OMX_AUDIO_AACObjectHE_PS == aAacParam.eAACProfile)
{
iAacEncConfig.useAOT = AOT_PS;
}
else
{
return OMX_FALSE;
}
if ((OMX_AUDIO_AACStreamFormatMP2ADTS == aAacParam.eAACStreamFormat) ||
(OMX_AUDIO_AACStreamFormatMP4ADTS == aAacParam.eAACStreamFormat))
{
iAacEncConfig.useTransmux = TT_MP4_ADTS;
}
else if (OMX_AUDIO_AACStreamFormatMP4LOAS == aAacParam.eAACStreamFormat)
{
iAacEncConfig.useTransmux = TT_MP4_LOAS;
}
else if (OMX_AUDIO_AACStreamFormatMP4LATM == aAacParam.eAACStreamFormat)
{
iAacEncConfig.useTransmux = TT_MP4_RAWLATM;
}
else if (OMX_AUDIO_AACStreamFormatADIF == aAacParam.eAACStreamFormat)
{
iAacEncConfig.useTransmux = TT_MP4_ADIF;
}
else if (OMX_AUDIO_AACStreamFormatMP4FF == aAacParam.eAACStreamFormat)
{
iAacEncConfig.useTransmux = TT_MP4_MP4F;
}
else if (OMX_AUDIO_AACStreamFormatRAW == aAacParam.eAACStreamFormat)
{
iAacEncConfig.useTransmux = TT_MP4_RAWPACKETS;
}
else
{
return OMX_FALSE;
}
if (0 == (OMX_AUDIO_AACToolTNS & aAacParam.nAACtools))
{
iAacEncConfig.useTns = 0;
}
if (0 == (OMX_AUDIO_AACToolPNS & aAacParam.nAACtools))
{
iAacEncConfig.usePns = 0;
}
//Allocating memory for input and output buffers
iAacInputBuffer = (OMX_U8*) oscl_malloc(INPUTBUFFER_SIZE * 2 * sizeof(OMX_U8));
iAacOutputBuffer = (OMX_U8*) oscl_malloc(OUTPUTBUFFER_SIZE * sizeof(OMX_U8));
// Initialize and open the encoder
Status = aacEncOpen(iAacEncoder, &iAacEncConfig, (INT_PCM*) iAacInputBuffer, iAacOutputBuffer);
if (Status)
{
// Failure occurred during initialization so return right away
return OMX_FALSE;
}
/* RTP access unit simulation: write access unit length (4 byte) before audio specific config */
if (TT_MP4_RAWPACKETS == iAacEncConfig.useTransmux)
{
ErrorStatus = aacEncGetAsc(iAacEncoder, (UINT*) & iAscSize, iAscBuf);
if (AAC_ENC_OK != ErrorStatus)
{
// Failure occurred during initialization so return right away
return OMX_FALSE;
}
}
*aInputFrameLength = iAacEncConfig.nSamplesRead << 1;
return OMX_TRUE;
}
/* Decoder De-Initialization function */
void OmxAacEncoder::AacEncDeinit()
{
if (iAacInputBuffer)
{
oscl_free(iAacInputBuffer);
iAacInputBuffer = NULL;
}
if (iAacOutputBuffer)
{
oscl_free(iAacOutputBuffer);
iAacOutputBuffer = NULL;
}
if (iAacEncoder)
{
aacEncClose(&iAacEncoder);
iAacEncoder = NULL;
}
}
/* Decode function for all the input formats */
OMX_BOOL OmxAacEncoder::AacEncodeFrame(OMX_U8* aOutputBuffer,
OMX_U32* aOutputLength,
OMX_U8* aInBuffer,
OMX_U32 aInBufSize)
{
OMX_S32 NumImputSamples = iAacEncConfig.nSamplesRead;
OMX_S32 Status;
OMX_S32 OutputOffset = 0;
if (TT_MP4_RAWPACKETS == iAacEncConfig.useTransmux)
{
if (OMX_FALSE == iAscFlag)
{
oscl_memcpy(aOutputBuffer, &iAscSize, 4);
oscl_memcpy((aOutputBuffer + 4), iAscBuf, iAscSize);
iAscFlag = OMX_TRUE;
OutputOffset = 4 + iAscSize;
}
//Four bytes to write the size of frame after it has been encoded
OutputOffset += 4;
}
iAacEncConfig.pOutBuffer = aOutputBuffer + OutputOffset;
if (aInBufSize < NumImputSamples)
{
NumImputSamples = aInBufSize >> 1;
}
oscl_memcpy(iAacEncConfig.pInBuffer, aInBuffer, (NumImputSamples << 1));
// Encode frame
Status = aacEncEncode(iAacEncoder,
&iAacEncConfig,
(INT32*) aOutputLength,
NumImputSamples);
// Check to find if error occurred
if (Status)
{
return OMX_FALSE;
}
if (TT_MP4_RAWPACKETS == iAacEncConfig.useTransmux)
{
oscl_memcpy((aOutputBuffer + (OutputOffset - 4)), &(*aOutputLength), 4);
}
return OMX_TRUE;
}