239 lines
7.4 KiB
C
239 lines
7.4 KiB
C
/*
|
|
** 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;
|
|
}
|
|
}
|
|
}
|