diff options
Diffstat (limited to 'media/libstagefright/codecs/aacenc/src/aacenc.c')
-rw-r--r-- | media/libstagefright/codecs/aacenc/src/aacenc.c | 495 |
1 files changed, 495 insertions, 0 deletions
diff --git a/media/libstagefright/codecs/aacenc/src/aacenc.c b/media/libstagefright/codecs/aacenc/src/aacenc.c new file mode 100644 index 0000000..ad2f29a --- /dev/null +++ b/media/libstagefright/codecs/aacenc/src/aacenc.c @@ -0,0 +1,495 @@ +/* + ** 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" + +/** +* 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; + AACENC_CONFIG config; + int error; + +#ifdef USE_DEAULT_MEM + VO_MEM_OPERATOR voMemoprator; +#endif + VO_MEM_OPERATOR *pMemOP; + int interMem; + + interMem = 0; + 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 ret, 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) +{ + 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; +} |