blob: df177872166e8b42e2119d3ed75d0c83e31812f6 [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.c
Content: aac encoder interface functions
*******************************************************************************/
#include "voAAC.h"
#include "typedef.h"
#include "aacenc_core.h"
#include "aac_rom.h"
#include "cmnMemory.h"
#include "memalign.h"
#define UNUSED(x) (void)(x)
/**
* Init the audio codec module and return codec handle
* \param phCodec [OUT] Return the video codec handle
* \param vType [IN] The codec type if the module support multi codec.
* \param pUserData [IN] The init param. It is memory operator or alloced memory
* \retval VO_ERR_NONE Succeeded.
*/
VO_U32 VO_API voAACEncInit(VO_HANDLE * phCodec,VO_AUDIO_CODINGTYPE vType, VO_CODEC_INIT_USERDATA *pUserData)
{
AAC_ENCODER*hAacEnc;
int error;
#ifdef USE_DEAULT_MEM
VO_MEM_OPERATOR voMemoprator;
#endif
VO_MEM_OPERATOR *pMemOP;
#ifdef USE_DEAULT_MEM
int interMem;
interMem = 0;
#endif
UNUSED(vType);
error = 0;
/* init the memory operator */
if(pUserData == NULL || pUserData->memflag != VO_IMF_USERMEMOPERATOR || pUserData->memData == NULL )
{
#ifdef USE_DEAULT_MEM
voMemoprator.Alloc = cmnMemAlloc;
voMemoprator.Copy = cmnMemCopy;
voMemoprator.Free = cmnMemFree;
voMemoprator.Set = cmnMemSet;
voMemoprator.Check = cmnMemCheck;
interMem = 1;
pMemOP = &voMemoprator;
#else
*phCodec = NULL;
return VO_ERR_INVALID_ARG;
#endif
}
else
{
pMemOP = (VO_MEM_OPERATOR *)pUserData->memData;
}
/* init the aac encoder handle */
hAacEnc = (AAC_ENCODER*)mem_malloc(pMemOP, sizeof(AAC_ENCODER), 32, VO_INDEX_ENC_AAC);
if(NULL == hAacEnc)
{
error = 1;
}
if(!error)
{
/* init the aac encoder intra memory */
hAacEnc->intbuf = (short *)mem_malloc(pMemOP, AACENC_BLOCKSIZE*MAX_CHANNELS*sizeof(short), 32, VO_INDEX_ENC_AAC);
if(NULL == hAacEnc->intbuf)
{
error = 1;
}
}
if (!error) {
/* init the aac encoder psychoacoustic */
error = (PsyNew(&hAacEnc->psyKernel, MAX_CHANNELS, pMemOP) ||
PsyOutNew(&hAacEnc->psyOut, pMemOP));
}
if (!error) {
/* init the aac encoder quantization elements */
error = QCOutNew(&hAacEnc->qcOut,MAX_CHANNELS, pMemOP);
}
if (!error) {
/* init the aac encoder quantization state */
error = QCNew(&hAacEnc->qcKernel, pMemOP);
}
/* uninit the aac encoder if error is nozero */
if(error)
{
AacEncClose(hAacEnc, pMemOP);
if(hAacEnc)
{
mem_free(pMemOP, hAacEnc, VO_INDEX_ENC_AAC);
hAacEnc = NULL;
}
*phCodec = NULL;
return VO_ERR_OUTOF_MEMORY;
}
/* init the aac encoder memory operator */
#ifdef USE_DEAULT_MEM
if(interMem)
{
hAacEnc->voMemoprator.Alloc = cmnMemAlloc;
hAacEnc->voMemoprator.Copy = cmnMemCopy;
hAacEnc->voMemoprator.Free = cmnMemFree;
hAacEnc->voMemoprator.Set = cmnMemSet;
hAacEnc->voMemoprator.Check = cmnMemCheck;
pMemOP = &hAacEnc->voMemoprator;
}
#endif
/* init the aac encoder default parameter */
if(hAacEnc->initOK == 0)
{
AACENC_CONFIG config;
config.adtsUsed = 1;
config.bitRate = 128000;
config.nChannelsIn = 2;
config.nChannelsOut = 2;
config.sampleRate = 44100;
config.bandWidth = 20000;
AacEncOpen(hAacEnc, config);
}
hAacEnc->voMemop = pMemOP;
*phCodec = hAacEnc;
return VO_ERR_NONE;
}
/**
* Set input audio data.
* \param hCodec [IN]] The Codec Handle which was created by Init function.
* \param pInput [IN] The input buffer param.
* \param pOutBuffer [OUT] The output buffer info.
* \retval VO_ERR_NONE Succeeded.
*/
VO_U32 VO_API voAACEncSetInputData(VO_HANDLE hCodec, VO_CODECBUFFER * pInput)
{
AAC_ENCODER *hAacEnc;
int length;
if(NULL == hCodec || NULL == pInput || NULL == pInput->Buffer)
{
return VO_ERR_INVALID_ARG;
}
hAacEnc = (AAC_ENCODER *)hCodec;
/* init input pcm buffer and length*/
hAacEnc->inbuf = (short *)pInput->Buffer;
hAacEnc->inlen = pInput->Length / sizeof(short);
hAacEnc->uselength = 0;
hAacEnc->encbuf = hAacEnc->inbuf;
hAacEnc->enclen = hAacEnc->inlen;
/* rebuild intra pcm buffer and length*/
if(hAacEnc->intlen)
{
length = min(hAacEnc->config.nChannelsIn*AACENC_BLOCKSIZE - hAacEnc->intlen, hAacEnc->inlen);
hAacEnc->voMemop->Copy(VO_INDEX_ENC_AAC, hAacEnc->intbuf + hAacEnc->intlen,
hAacEnc->inbuf, length*sizeof(short));
hAacEnc->encbuf = hAacEnc->intbuf;
hAacEnc->enclen = hAacEnc->intlen + length;
hAacEnc->inbuf += length;
hAacEnc->inlen -= length;
}
return VO_ERR_NONE;
}
/**
* Get the outut audio data
* \param hCodec [IN]] The Codec Handle which was created by Init function.
* \param pOutBuffer [OUT] The output audio data
* \param pOutInfo [OUT] The dec module filled audio format and used the input size.
* pOutInfo->InputUsed is total used the input size.
* \retval VO_ERR_NONE Succeeded.
* VO_ERR_INPUT_BUFFER_SMALL. The input was finished or the input data was not enought.
*/
VO_U32 VO_API voAACEncGetOutputData(VO_HANDLE hCodec, VO_CODECBUFFER * pOutput, VO_AUDIO_OUTPUTINFO * pOutInfo)
{
AAC_ENCODER* hAacEnc = (AAC_ENCODER*)hCodec;
Word16 numAncDataBytes=0;
Word32 inbuflen;
int length;
if(NULL == hAacEnc)
return VO_ERR_INVALID_ARG;
inbuflen = AACENC_BLOCKSIZE*hAacEnc->config.nChannelsIn;
/* check the input pcm buffer and length*/
if(NULL == hAacEnc->encbuf || hAacEnc->enclen < inbuflen)
{
length = hAacEnc->enclen;
if(hAacEnc->intlen == 0)
{
hAacEnc->voMemop->Copy(VO_INDEX_ENC_AAC, hAacEnc->intbuf,
hAacEnc->encbuf, length*sizeof(short));
hAacEnc->uselength += length*sizeof(short);
}
else
{
hAacEnc->uselength += (length - hAacEnc->intlen)*sizeof(short);
}
hAacEnc->intlen = length;
pOutput->Length = 0;
if(pOutInfo)
pOutInfo->InputUsed = hAacEnc->uselength;
return VO_ERR_INPUT_BUFFER_SMALL;
}
/* check the output aac buffer and length*/
if(NULL == pOutput || NULL == pOutput->Buffer || pOutput->Length < (6144/8)*hAacEnc->config.nChannelsOut/(sizeof(Word32)))
return VO_ERR_OUTPUT_BUFFER_SMALL;
/* aac encoder core function */
AacEncEncode( hAacEnc,
(Word16*)hAacEnc->encbuf,
NULL,
&numAncDataBytes,
pOutput->Buffer,
&pOutput->Length);
/* update the input pcm buffer and length*/
if(hAacEnc->intlen)
{
length = inbuflen - hAacEnc->intlen;
hAacEnc->encbuf = hAacEnc->inbuf;
hAacEnc->enclen = hAacEnc->inlen;
hAacEnc->uselength += length*sizeof(short);
hAacEnc->intlen = 0;
}
else
{
hAacEnc->encbuf = hAacEnc->encbuf + inbuflen;
hAacEnc->enclen = hAacEnc->enclen - inbuflen;
hAacEnc->uselength += inbuflen*sizeof(short);
}
/* update the output aac information */
if(pOutInfo)
{
pOutInfo->Format.Channels = hAacEnc->config.nChannelsOut;
pOutInfo->Format.SampleRate = hAacEnc->config.sampleRate;
pOutInfo->Format.SampleBits = 16;
pOutInfo->InputUsed = hAacEnc->uselength;
}
return VO_ERR_NONE;
}
/**
* Uninit the Codec.
* \param hCodec [IN]] The Codec Handle which was created by Init function.
* \retval VO_ERR_NONE Succeeded.
*/
VO_U32 VO_API voAACEncUninit(VO_HANDLE hCodec)
{
AAC_ENCODER* hAacEnc = (AAC_ENCODER*)hCodec;
if(NULL != hAacEnc)
{
/* close the aac encoder */
AacEncClose(hAacEnc, hAacEnc->voMemop);
/* free the aac encoder handle*/
mem_free(hAacEnc->voMemop, hAacEnc, VO_INDEX_ENC_AAC);
hAacEnc = NULL;
}
return VO_ERR_NONE;
}
/**
* Set the param for special target.
* \param hCodec [IN]] The Codec Handle which was created by Init function.
* \param uParamID [IN] The param ID.
* \param pData [IN] The param value depend on the ID>
* \retval VO_ERR_NONE Succeeded.
*/
VO_U32 VO_API voAACEncSetParam(VO_HANDLE hCodec, VO_S32 uParamID, VO_PTR pData)
{
AACENC_CONFIG config;
AACENC_PARAM* pAAC_param;
VO_AUDIO_FORMAT *pWAV_Format;
AAC_ENCODER* hAacEnc = (AAC_ENCODER*)hCodec;
int ret, i, bitrate, tmp;
int SampleRateIdx;
if(NULL == hAacEnc)
return VO_ERR_INVALID_ARG;
switch(uParamID)
{
case VO_PID_AAC_ENCPARAM: /* init aac encoder parameter*/
AacInitDefaultConfig(&config);
if(pData == NULL)
return VO_ERR_INVALID_ARG;
pAAC_param = (AACENC_PARAM*)pData;
config.adtsUsed = pAAC_param->adtsUsed;
config.bitRate = pAAC_param->bitRate;
config.nChannelsIn = pAAC_param->nChannels;
config.nChannelsOut = pAAC_param->nChannels;
config.sampleRate = pAAC_param->sampleRate;
/* check the channel */
if(config.nChannelsIn< 1 || config.nChannelsIn > MAX_CHANNELS ||
config.nChannelsOut < 1 || config.nChannelsOut > MAX_CHANNELS || config.nChannelsIn < config.nChannelsOut)
return VO_ERR_AUDIO_UNSCHANNEL;
/* check the samplerate */
ret = -1;
for(i = 0; i < NUM_SAMPLE_RATES; i++)
{
if(config.sampleRate == sampRateTab[i])
{
ret = 0;
break;
}
}
if(ret < 0)
return VO_ERR_AUDIO_UNSSAMPLERATE;
SampleRateIdx = i;
tmp = 441;
if(config.sampleRate%8000 == 0)
tmp =480;
/* check the bitrate */
if(config.bitRate!=0 && ((config.bitRate/config.nChannelsOut < 4000) ||
(config.bitRate/config.nChannelsOut > 160000) ||
(config.bitRate > config.sampleRate*6*config.nChannelsOut)))
{
config.bitRate = 640*config.sampleRate/tmp*config.nChannelsOut;
if(config.bitRate/config.nChannelsOut < 4000)
config.bitRate = 4000 * config.nChannelsOut;
else if(config.bitRate > config.sampleRate*6*config.nChannelsOut)
config.bitRate = config.sampleRate*6*config.nChannelsOut;
else if(config.bitRate/config.nChannelsOut > 160000)
config.bitRate = config.nChannelsOut*160000;
}
/* check the bandwidth */
bitrate = config.bitRate / config.nChannelsOut;
bitrate = bitrate * tmp / config.sampleRate;
for (i = 0; rates[i]; i++)
{
if (rates[i] >= bitrate)
break;
}
config.bandWidth = BandwithCoefTab[i][SampleRateIdx];
/* init aac encoder core */
ret = AacEncOpen(hAacEnc, config);
if(ret)
return VO_ERR_AUDIO_UNSFEATURE;
break;
case VO_PID_AUDIO_FORMAT: /* init pcm channel and samplerate*/
AacInitDefaultConfig(&config);
if(pData == NULL)
return VO_ERR_INVALID_ARG;
pWAV_Format = (VO_AUDIO_FORMAT*)pData;
config.adtsUsed = 1;
config.nChannelsIn = pWAV_Format->Channels;
config.nChannelsOut = pWAV_Format->Channels;
config.sampleRate = pWAV_Format->SampleRate;
/* check the channel */
if(config.nChannelsIn< 1 || config.nChannelsIn > MAX_CHANNELS ||
config.nChannelsOut < 1 || config.nChannelsOut > MAX_CHANNELS || config.nChannelsIn < config.nChannelsOut)
return VO_ERR_AUDIO_UNSCHANNEL;
/* check the samplebits */
if(pWAV_Format->SampleBits != 16)
{
return VO_ERR_AUDIO_UNSFEATURE;
}
/* check the samplerate */
ret = -1;
for(i = 0; i < NUM_SAMPLE_RATES; i++)
{
if(config.sampleRate == sampRateTab[i])
{
ret = 0;
break;
}
}
if(ret < 0)
return VO_ERR_AUDIO_UNSSAMPLERATE;
SampleRateIdx = i;
/* update the bitrates */
tmp = 441;
if(config.sampleRate%8000 == 0)
tmp =480;
config.bitRate = 640*config.sampleRate/tmp*config.nChannelsOut;
if(config.bitRate/config.nChannelsOut < 4000)
config.bitRate = 4000 * config.nChannelsOut;
else if(config.bitRate > config.sampleRate*6*config.nChannelsOut)
config.bitRate = config.sampleRate*6*config.nChannelsOut;
else if(config.bitRate/config.nChannelsOut > 160000)
config.bitRate = config.nChannelsOut*160000;
/* check the bandwidth */
bitrate = config.bitRate / config.nChannelsOut;
bitrate = bitrate * tmp / config.sampleRate;
for (i = 0; rates[i]; i++)
{
if (rates[i] >= bitrate)
break;
}
config.bandWidth = BandwithCoefTab[i][SampleRateIdx];
/* init aac encoder core */
ret = AacEncOpen(hAacEnc, config);
if(ret)
return VO_ERR_AUDIO_UNSFEATURE;
break;
default:
return VO_ERR_WRONG_PARAM_ID;
}
return VO_ERR_NONE;
}
/**
* Get the param for special target.
* \param hCodec [IN]] The Codec Handle which was created by Init function.
* \param uParamID [IN] The param ID.
* \param pData [IN] The param value depend on the ID>
* \retval VO_ERR_NONE Succeeded.
*/
VO_U32 VO_API voAACEncGetParam(VO_HANDLE hCodec, VO_S32 uParamID, VO_PTR pData)
{
UNUSED(hCodec);
UNUSED(uParamID);
UNUSED(pData);
return VO_ERR_NONE;
}
/**
* Get audio codec API interface
* \param pEncHandle [out] Return the AAC Encoder handle.
* \retval VO_ERR_OK Succeeded.
*/
VO_S32 VO_API voGetAACEncAPI(VO_AUDIO_CODECAPI * pDecHandle)
{
if(pDecHandle == NULL)
return VO_ERR_INVALID_ARG;
pDecHandle->Init = voAACEncInit;
pDecHandle->SetInputData = voAACEncSetInputData;
pDecHandle->GetOutputData = voAACEncGetOutputData;
pDecHandle->SetParam = voAACEncSetParam;
pDecHandle->GetParam = voAACEncGetParam;
pDecHandle->Uninit = voAACEncUninit;
return VO_ERR_NONE;
}