/* ** 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 i; 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; } } }