506 lines
13 KiB
C
506 lines
13 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.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_DEFAULT_MEM
|
|
VO_MEM_OPERATOR voMemoprator;
|
|
#endif
|
|
VO_MEM_OPERATOR *pMemOP;
|
|
|
|
#ifdef USE_DEFAULT_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_DEFAULT_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_DEFAULT_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;
|
|
}
|