blob: de452d41f8a6caf437fee2395e99ff04fc8b460d [file] [log] [blame]
/*
** Copyright 2003-2010, VisualOn, Inc.
**
** 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.
*/
/*******************************************************************************
File: aacenc_core.c
Content: aac encoder core functions
*******************************************************************************/
#include "typedef.h"
#include "aacenc_core.h"
#include "bitenc.h"
#include "psy_configuration.h"
#include "psy_main.h"
#include "qc_main.h"
#include "psy_main.h"
#include "channel_map.h"
#include "aac_rom.h"
/********************************************************************************
*
* function name: AacInitDefaultConfig
* description: gives reasonable default configuration
*
**********************************************************************************/
void AacInitDefaultConfig(AACENC_CONFIG *config)
{
/* default configurations */
config->adtsUsed = 1;
config->nChannelsIn = 2;
config->nChannelsOut = 2;
config->bitRate = 128000;
config->bandWidth = 0;
}
/********************************************************************************
*
* function name: AacEncOpen
* description: allocate and initialize a new encoder instance
* returns: 0 if success
*
**********************************************************************************/
Word16 AacEncOpen( AAC_ENCODER* hAacEnc, /* pointer to an encoder handle, initialized on return */
const AACENC_CONFIG config /* pre-initialized config struct */
)
{
Word32 error = 0;
Word16 profile = 1;
ELEMENT_INFO *elInfo = NULL;
if (hAacEnc==0) {
error=1;
}
if (!error) {
hAacEnc->config = config;
}
if (!error) {
error = InitElementInfo (config.nChannelsOut,
&hAacEnc->elInfo);
}
if (!error) {
elInfo = &hAacEnc->elInfo;
}
if (!error) {
/* use or not tns tool for long and short block */
Word16 tnsMask=3;
/* init encoder psychoacoustic */
error = psyMainInit(&hAacEnc->psyKernel,
config.sampleRate,
config.bitRate,
elInfo->nChannelsInEl,
tnsMask,
hAacEnc->config.bandWidth);
}
/* use or not adts header */
if(!error) {
hAacEnc->qcOut.qcElement.adtsUsed = config.adtsUsed;
}
/* init encoder quantization */
if (!error) {
struct QC_INIT qcInit;
/*qcInit.channelMapping = &hAacEnc->channelMapping;*/
qcInit.elInfo = &hAacEnc->elInfo;
qcInit.maxBits = (Word16) (MAXBITS_COEF*elInfo->nChannelsInEl);
qcInit.bitRes = qcInit.maxBits;
qcInit.averageBits = (Word16) ((config.bitRate * FRAME_LEN_LONG) / config.sampleRate);
qcInit.padding.paddingRest = config.sampleRate;
qcInit.meanPe = (Word16) ((10 * FRAME_LEN_LONG * hAacEnc->config.bandWidth) /
(config.sampleRate>>1));
qcInit.maxBitFac = (Word16) ((100 * (MAXBITS_COEF-MINBITS_COEF)* elInfo->nChannelsInEl)/
(qcInit.averageBits?qcInit.averageBits:1));
qcInit.bitrate = config.bitRate;
error = QCInit(&hAacEnc->qcKernel, &qcInit);
}
/* init bitstream encoder */
if (!error) {
hAacEnc->bseInit.nChannels = elInfo->nChannelsInEl;
hAacEnc->bseInit.bitrate = config.bitRate;
hAacEnc->bseInit.sampleRate = config.sampleRate;
hAacEnc->bseInit.profile = profile;
}
return error;
}
/********************************************************************************
*
* function name: AacEncEncode
* description: encode pcm to aac data core function
* returns: 0 if success
*
**********************************************************************************/
Word16 AacEncEncode(AAC_ENCODER *aacEnc, /*!< an encoder handle */
Word16 *timeSignal, /*!< BLOCKSIZE*nChannels audio samples, interleaved */
const UWord8 *ancBytes, /*!< pointer to ancillary data bytes */
Word16 *numAncBytes, /*!< number of ancillary Data Bytes */
UWord8 *outBytes, /*!< pointer to output buffer (must be large MINBITS_COEF/8*MAX_CHANNELS bytes) */
VO_U32 *numOutBytes /*!< number of bytes in output buffer after processing */
)
{
ELEMENT_INFO *elInfo = &aacEnc->elInfo;
Word16 globUsedBits;
Word16 ancDataBytes, ancDataBytesLeft;
ancDataBytes = ancDataBytesLeft = *numAncBytes;
/* init output aac data buffer and length */
aacEnc->hBitStream = CreateBitBuffer(&aacEnc->bitStream, outBytes, *numOutBytes);
/* psychoacoustic process */
psyMain(aacEnc->config.nChannelsOut,
elInfo,
timeSignal,
&aacEnc->psyKernel.psyData[elInfo->ChannelIndex[0]],
&aacEnc->psyKernel.tnsData[elInfo->ChannelIndex[0]],
&aacEnc->psyKernel.psyConfLong,
&aacEnc->psyKernel.psyConfShort,
&aacEnc->psyOut.psyOutChannel[elInfo->ChannelIndex[0]],
&aacEnc->psyOut.psyOutElement,
aacEnc->psyKernel.pScratchTns,
aacEnc->config.sampleRate);
/* adjust bitrate and frame length */
AdjustBitrate(&aacEnc->qcKernel,
aacEnc->config.bitRate,
aacEnc->config.sampleRate);
/* quantization and coding process */
QCMain(&aacEnc->qcKernel,
&aacEnc->qcKernel.elementBits,
&aacEnc->qcKernel.adjThr.adjThrStateElem,
&aacEnc->psyOut.psyOutChannel[elInfo->ChannelIndex[0]],
&aacEnc->psyOut.psyOutElement,
&aacEnc->qcOut.qcChannel[elInfo->ChannelIndex[0]],
&aacEnc->qcOut.qcElement,
elInfo->nChannelsInEl,
min(ancDataBytesLeft,ancDataBytes));
ancDataBytesLeft = ancDataBytesLeft - ancDataBytes;
globUsedBits = FinalizeBitConsumption(&aacEnc->qcKernel,
&aacEnc->qcOut);
/* write bitstream process */
WriteBitstream(aacEnc->hBitStream,
*elInfo,
&aacEnc->qcOut,
&aacEnc->psyOut,
&globUsedBits,
ancBytes,
aacEnc->psyKernel.sampleRateIdx);
updateBitres(&aacEnc->qcKernel,
&aacEnc->qcOut);
/* write out the bitstream */
*numOutBytes = GetBitsAvail(aacEnc->hBitStream) >> 3;
return 0;
}
/********************************************************************************
*
* function name:AacEncClose
* description: deallocate an encoder instance
*
**********************************************************************************/
void AacEncClose (AAC_ENCODER* hAacEnc, VO_MEM_OPERATOR *pMemOP)
{
if (hAacEnc) {
QCDelete(&hAacEnc->qcKernel, pMemOP);
QCOutDelete(&hAacEnc->qcOut, pMemOP);
PsyDelete(&hAacEnc->psyKernel, pMemOP);
PsyOutDelete(&hAacEnc->psyOut, pMemOP);
DeleteBitBuffer(&hAacEnc->hBitStream);
if(hAacEnc->intbuf)
{
mem_free(pMemOP, hAacEnc->intbuf, VO_INDEX_ENC_AAC);
hAacEnc->intbuf = NULL;
}
}
}