Home | History | Annotate | Download | only in src
      1 /*
      2  ** Copyright 2003-2010, VisualOn, Inc.
      3  **
      4  ** Licensed under the Apache License, Version 2.0 (the "License");
      5  ** you may not use this file except in compliance with the License.
      6  ** You may obtain a copy of the License at
      7  **
      8  **     http://www.apache.org/licenses/LICENSE-2.0
      9  **
     10  ** Unless required by applicable law or agreed to in writing, software
     11  ** distributed under the License is distributed on an "AS IS" BASIS,
     12  ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  ** See the License for the specific language governing permissions and
     14  ** limitations under the License.
     15  */
     16 /*******************************************************************************
     17 	File:		aacenc.c
     18 
     19 	Content:	aac encoder interface functions
     20 
     21 *******************************************************************************/
     22 
     23 #include "voAAC.h"
     24 #include "typedef.h"
     25 #include "aacenc_core.h"
     26 #include "aac_rom.h"
     27 #include "cmnMemory.h"
     28 #include "memalign.h"
     29 
     30 #define UNUSED(x) (void)(x)
     31 
     32 /**
     33 * Init the audio codec module and return codec handle
     34 * \param phCodec [OUT] Return the video codec handle
     35 * \param vType	[IN] The codec type if the module support multi codec.
     36 * \param pUserData	[IN] The init param. It is memory operator or alloced memory
     37 * \retval VO_ERR_NONE Succeeded.
     38 */
     39 VO_U32 VO_API voAACEncInit(VO_HANDLE * phCodec,VO_AUDIO_CODINGTYPE vType, VO_CODEC_INIT_USERDATA *pUserData)
     40 {
     41 	AAC_ENCODER*hAacEnc;
     42 	AACENC_CONFIG config;
     43 	int error;
     44 
     45 #ifdef USE_DEAULT_MEM
     46 	VO_MEM_OPERATOR voMemoprator;
     47 #endif
     48 	VO_MEM_OPERATOR *pMemOP;
     49 	int interMem;
     50 
     51         UNUSED(vType);
     52 
     53 	interMem = 0;
     54 	error = 0;
     55 
     56 	/* init the memory operator */
     57 	if(pUserData == NULL || pUserData->memflag != VO_IMF_USERMEMOPERATOR || pUserData->memData == NULL )
     58 	{
     59 #ifdef USE_DEAULT_MEM
     60 		voMemoprator.Alloc = cmnMemAlloc;
     61 		voMemoprator.Copy = cmnMemCopy;
     62 		voMemoprator.Free = cmnMemFree;
     63 		voMemoprator.Set = cmnMemSet;
     64 		voMemoprator.Check = cmnMemCheck;
     65 
     66 		interMem = 1;
     67 
     68 		pMemOP = &voMemoprator;
     69 #else
     70 		*phCodec = NULL;
     71 		return VO_ERR_INVALID_ARG;
     72 #endif
     73 	}
     74 	else
     75 	{
     76 		pMemOP = (VO_MEM_OPERATOR *)pUserData->memData;
     77 	}
     78 
     79 	/* init the aac encoder handle */
     80 	hAacEnc = (AAC_ENCODER*)mem_malloc(pMemOP, sizeof(AAC_ENCODER), 32, VO_INDEX_ENC_AAC);
     81 	if(NULL == hAacEnc)
     82 	{
     83 		error = 1;
     84 	}
     85 
     86 	if(!error)
     87 	{
     88 		/* init the aac encoder intra memory */
     89 		hAacEnc->intbuf = (short *)mem_malloc(pMemOP, AACENC_BLOCKSIZE*MAX_CHANNELS*sizeof(short), 32, VO_INDEX_ENC_AAC);
     90 		if(NULL == hAacEnc->intbuf)
     91 		{
     92 			error = 1;
     93 		}
     94 	}
     95 
     96 	if (!error) {
     97 		/* init the aac encoder psychoacoustic */
     98 		error = (PsyNew(&hAacEnc->psyKernel, MAX_CHANNELS, pMemOP) ||
     99 			PsyOutNew(&hAacEnc->psyOut, pMemOP));
    100 	}
    101 
    102 	if (!error) {
    103 		/* init the aac encoder quantization elements */
    104 		error = QCOutNew(&hAacEnc->qcOut,MAX_CHANNELS, pMemOP);
    105 	}
    106 
    107 	if (!error) {
    108 		/* init the aac encoder quantization state */
    109 		error = QCNew(&hAacEnc->qcKernel, pMemOP);
    110 	}
    111 
    112 	/* uninit the aac encoder if error is nozero */
    113 	if(error)
    114 	{
    115 		AacEncClose(hAacEnc, pMemOP);
    116 		if(hAacEnc)
    117 		{
    118 			mem_free(pMemOP, hAacEnc, VO_INDEX_ENC_AAC);
    119 			hAacEnc = NULL;
    120 		}
    121 		*phCodec = NULL;
    122 		return VO_ERR_OUTOF_MEMORY;
    123 	}
    124 
    125 	/* init the aac encoder memory operator  */
    126 #ifdef USE_DEAULT_MEM
    127 	if(interMem)
    128 	{
    129 		hAacEnc->voMemoprator.Alloc = cmnMemAlloc;
    130 		hAacEnc->voMemoprator.Copy = cmnMemCopy;
    131 		hAacEnc->voMemoprator.Free = cmnMemFree;
    132 		hAacEnc->voMemoprator.Set = cmnMemSet;
    133 		hAacEnc->voMemoprator.Check = cmnMemCheck;
    134 
    135 		pMemOP = &hAacEnc->voMemoprator;
    136 	}
    137 #endif
    138 	/* init the aac encoder default parameter  */
    139 	if(hAacEnc->initOK == 0)
    140 	{
    141 		 AACENC_CONFIG config;
    142 		 config.adtsUsed = 1;
    143 		 config.bitRate = 128000;
    144 		 config.nChannelsIn = 2;
    145 		 config.nChannelsOut = 2;
    146 		 config.sampleRate = 44100;
    147 		 config.bandWidth = 20000;
    148 
    149 		 AacEncOpen(hAacEnc, config);
    150 	}
    151 
    152 	hAacEnc->voMemop = pMemOP;
    153 
    154 	*phCodec = hAacEnc;
    155 
    156 	return VO_ERR_NONE;
    157 }
    158 
    159 /**
    160 * Set input audio data.
    161 * \param hCodec [IN]] The Codec Handle which was created by Init function.
    162 * \param pInput [IN] The input buffer param.
    163 * \param pOutBuffer [OUT] The output buffer info.
    164 * \retval VO_ERR_NONE Succeeded.
    165 */
    166 VO_U32 VO_API voAACEncSetInputData(VO_HANDLE hCodec, VO_CODECBUFFER * pInput)
    167 {
    168 	AAC_ENCODER *hAacEnc;
    169 	int  length;
    170 
    171 	if(NULL == hCodec || NULL == pInput || NULL == pInput->Buffer)
    172 	{
    173 		return VO_ERR_INVALID_ARG;
    174 	}
    175 
    176 	hAacEnc = (AAC_ENCODER *)hCodec;
    177 
    178 	/* init input pcm buffer and length*/
    179 	hAacEnc->inbuf = (short *)pInput->Buffer;
    180 	hAacEnc->inlen = pInput->Length / sizeof(short);
    181 	hAacEnc->uselength = 0;
    182 
    183 	hAacEnc->encbuf = hAacEnc->inbuf;
    184 	hAacEnc->enclen = hAacEnc->inlen;
    185 
    186 	/* rebuild intra pcm buffer and length*/
    187 	if(hAacEnc->intlen)
    188 	{
    189 		length = min(hAacEnc->config.nChannelsIn*AACENC_BLOCKSIZE - hAacEnc->intlen, hAacEnc->inlen);
    190 		hAacEnc->voMemop->Copy(VO_INDEX_ENC_AAC, hAacEnc->intbuf + hAacEnc->intlen,
    191 			hAacEnc->inbuf, length*sizeof(short));
    192 
    193 		hAacEnc->encbuf = hAacEnc->intbuf;
    194 		hAacEnc->enclen = hAacEnc->intlen + length;
    195 
    196 		hAacEnc->inbuf += length;
    197 		hAacEnc->inlen -= length;
    198 	}
    199 
    200 	return VO_ERR_NONE;
    201 }
    202 
    203 /**
    204 * Get the outut audio data
    205 * \param hCodec [IN]] The Codec Handle which was created by Init function.
    206 * \param pOutBuffer [OUT] The output audio data
    207 * \param pOutInfo [OUT] The dec module filled audio format and used the input size.
    208 *						 pOutInfo->InputUsed is total used the input size.
    209 * \retval  VO_ERR_NONE Succeeded.
    210 *			VO_ERR_INPUT_BUFFER_SMALL. The input was finished or the input data was not enought.
    211 */
    212 VO_U32 VO_API voAACEncGetOutputData(VO_HANDLE hCodec, VO_CODECBUFFER * pOutput, VO_AUDIO_OUTPUTINFO * pOutInfo)
    213 {
    214 	AAC_ENCODER* hAacEnc = (AAC_ENCODER*)hCodec;
    215 	Word16 numAncDataBytes=0;
    216 	Word32  inbuflen;
    217 	int ret, length;
    218 	if(NULL == hAacEnc)
    219 		return VO_ERR_INVALID_ARG;
    220 
    221 	 inbuflen = AACENC_BLOCKSIZE*hAacEnc->config.nChannelsIn;
    222 
    223 	 /* check the input pcm buffer and length*/
    224 	 if(NULL == hAacEnc->encbuf || hAacEnc->enclen < inbuflen)
    225 	 {
    226 		length = hAacEnc->enclen;
    227 		if(hAacEnc->intlen == 0)
    228 		{
    229 			hAacEnc->voMemop->Copy(VO_INDEX_ENC_AAC, hAacEnc->intbuf,
    230 				hAacEnc->encbuf, length*sizeof(short));
    231 			hAacEnc->uselength += length*sizeof(short);
    232 		}
    233 		else
    234 		{
    235 			hAacEnc->uselength += (length - hAacEnc->intlen)*sizeof(short);
    236 		}
    237 
    238 		hAacEnc->intlen = length;
    239 
    240 		pOutput->Length = 0;
    241 		if(pOutInfo)
    242 			pOutInfo->InputUsed = hAacEnc->uselength;
    243 		return VO_ERR_INPUT_BUFFER_SMALL;
    244 	 }
    245 
    246 	 /* check the output aac buffer and length*/
    247 	 if(NULL == pOutput || NULL == pOutput->Buffer || pOutput->Length < (6144/8)*hAacEnc->config.nChannelsOut/(sizeof(Word32)))
    248 		 return VO_ERR_OUTPUT_BUFFER_SMALL;
    249 
    250 	 /* aac encoder core function */
    251 	 AacEncEncode( hAacEnc,
    252 			(Word16*)hAacEnc->encbuf,
    253 			NULL,
    254 			&numAncDataBytes,
    255 			pOutput->Buffer,
    256 			&pOutput->Length);
    257 
    258 	 /* update the input pcm buffer and length*/
    259 	 if(hAacEnc->intlen)
    260 	 {
    261 		length = inbuflen - hAacEnc->intlen;
    262 		hAacEnc->encbuf = hAacEnc->inbuf;
    263 		hAacEnc->enclen = hAacEnc->inlen;
    264 		hAacEnc->uselength += length*sizeof(short);
    265 		hAacEnc->intlen = 0;
    266 	 }
    267 	 else
    268 	 {
    269 		 hAacEnc->encbuf = hAacEnc->encbuf + inbuflen;
    270 		 hAacEnc->enclen = hAacEnc->enclen - inbuflen;
    271 		 hAacEnc->uselength += inbuflen*sizeof(short);
    272 	 }
    273 
    274 	 /* update the output aac information */
    275 	if(pOutInfo)
    276 	{
    277 		pOutInfo->Format.Channels = hAacEnc->config.nChannelsOut;
    278 		pOutInfo->Format.SampleRate = hAacEnc->config.sampleRate;
    279 		pOutInfo->Format.SampleBits = 16;
    280 		pOutInfo->InputUsed = hAacEnc->uselength;
    281 	}
    282 
    283 	 return VO_ERR_NONE;
    284 }
    285 
    286 /**
    287 * Uninit the Codec.
    288 * \param hCodec [IN]] The Codec Handle which was created by Init function.
    289 * \retval VO_ERR_NONE Succeeded.
    290 */
    291 VO_U32 VO_API voAACEncUninit(VO_HANDLE hCodec)
    292 {
    293 	AAC_ENCODER* hAacEnc = (AAC_ENCODER*)hCodec;
    294 
    295 	if(NULL != hAacEnc)
    296 	{
    297 		/* close the aac encoder */
    298 		AacEncClose(hAacEnc, hAacEnc->voMemop);
    299 
    300 		/* free the aac encoder handle*/
    301 		mem_free(hAacEnc->voMemop, hAacEnc, VO_INDEX_ENC_AAC);
    302 		hAacEnc = NULL;
    303 	}
    304 
    305 	return VO_ERR_NONE;
    306 }
    307 
    308 /**
    309 * Set the param for special target.
    310 * \param hCodec [IN]] The Codec Handle which was created by Init function.
    311 * \param uParamID [IN] The param ID.
    312 * \param pData [IN] The param value depend on the ID>
    313 * \retval VO_ERR_NONE Succeeded.
    314 */
    315 VO_U32 VO_API voAACEncSetParam(VO_HANDLE hCodec, VO_S32 uParamID, VO_PTR pData)
    316 {
    317 	AACENC_CONFIG config;
    318 	AACENC_PARAM* pAAC_param;
    319 	VO_AUDIO_FORMAT *pWAV_Format;
    320 	AAC_ENCODER* hAacEnc = (AAC_ENCODER*)hCodec;
    321 	int ret, i, bitrate, tmp;
    322 	int SampleRateIdx;
    323 
    324 	if(NULL == hAacEnc)
    325 		return VO_ERR_INVALID_ARG;
    326 
    327 	switch(uParamID)
    328 	{
    329 	case VO_PID_AAC_ENCPARAM:  /* init aac encoder parameter*/
    330 		AacInitDefaultConfig(&config);
    331 		if(pData == NULL)
    332 			return VO_ERR_INVALID_ARG;
    333 		pAAC_param = (AACENC_PARAM*)pData;
    334 		config.adtsUsed = pAAC_param->adtsUsed;
    335 		config.bitRate = pAAC_param->bitRate;
    336 		config.nChannelsIn = pAAC_param->nChannels;
    337 		config.nChannelsOut = pAAC_param->nChannels;
    338 		config.sampleRate = pAAC_param->sampleRate;
    339 
    340 		/* check the channel */
    341 		if(config.nChannelsIn< 1  || config.nChannelsIn > MAX_CHANNELS  ||
    342              config.nChannelsOut < 1 || config.nChannelsOut > MAX_CHANNELS || config.nChannelsIn < config.nChannelsOut)
    343 			 return VO_ERR_AUDIO_UNSCHANNEL;
    344 
    345 		/* check the samplerate */
    346 		ret = -1;
    347 		for(i = 0; i < NUM_SAMPLE_RATES; i++)
    348 		{
    349 			if(config.sampleRate == sampRateTab[i])
    350 			{
    351 				ret = 0;
    352 				break;
    353 			}
    354 		}
    355 		if(ret < 0)
    356 			return VO_ERR_AUDIO_UNSSAMPLERATE;
    357 
    358 		SampleRateIdx = i;
    359 
    360 		tmp = 441;
    361 		if(config.sampleRate%8000 == 0)
    362 			tmp =480;
    363 		/* check the bitrate */
    364 		if(config.bitRate!=0 && ((config.bitRate/config.nChannelsOut < 4000) ||
    365            (config.bitRate/config.nChannelsOut > 160000) ||
    366 		   (config.bitRate > config.sampleRate*6*config.nChannelsOut)))
    367 		{
    368 			config.bitRate = 640*config.sampleRate/tmp*config.nChannelsOut;
    369 
    370 			if(config.bitRate/config.nChannelsOut < 4000)
    371 				config.bitRate = 4000 * config.nChannelsOut;
    372 			else if(config.bitRate > config.sampleRate*6*config.nChannelsOut)
    373 				config.bitRate = config.sampleRate*6*config.nChannelsOut;
    374 			else if(config.bitRate/config.nChannelsOut > 160000)
    375 				config.bitRate = config.nChannelsOut*160000;
    376 		}
    377 
    378 		/* check the bandwidth */
    379 		bitrate = config.bitRate / config.nChannelsOut;
    380 		bitrate = bitrate * tmp / config.sampleRate;
    381 
    382 		for (i = 0; rates[i]; i++)
    383 		{
    384 			if (rates[i] >= bitrate)
    385 				break;
    386 		}
    387 
    388 		config.bandWidth = BandwithCoefTab[i][SampleRateIdx];
    389 
    390 		/* init aac encoder core */
    391 		ret = AacEncOpen(hAacEnc, config);
    392 		if(ret)
    393 			return VO_ERR_AUDIO_UNSFEATURE;
    394 		break;
    395 	case VO_PID_AUDIO_FORMAT:	/* init pcm channel and samplerate*/
    396 		AacInitDefaultConfig(&config);
    397 		if(pData == NULL)
    398 			return VO_ERR_INVALID_ARG;
    399 		pWAV_Format = (VO_AUDIO_FORMAT*)pData;
    400 		config.adtsUsed = 1;
    401 		config.nChannelsIn = pWAV_Format->Channels;
    402 		config.nChannelsOut = pWAV_Format->Channels;
    403 		config.sampleRate = pWAV_Format->SampleRate;
    404 
    405 		/* check the channel */
    406 		if(config.nChannelsIn< 1  || config.nChannelsIn > MAX_CHANNELS  ||
    407              config.nChannelsOut < 1 || config.nChannelsOut > MAX_CHANNELS || config.nChannelsIn < config.nChannelsOut)
    408 			 return VO_ERR_AUDIO_UNSCHANNEL;
    409 
    410 		/* check the samplebits */
    411 		if(pWAV_Format->SampleBits != 16)
    412 		{
    413 			return VO_ERR_AUDIO_UNSFEATURE;
    414 		}
    415 
    416 		/* check the samplerate */
    417 		ret = -1;
    418 		for(i = 0; i < NUM_SAMPLE_RATES; i++)
    419 		{
    420 			if(config.sampleRate == sampRateTab[i])
    421 			{
    422 				ret = 0;
    423 				break;
    424 			}
    425 		}
    426 		if(ret < 0)
    427 			return VO_ERR_AUDIO_UNSSAMPLERATE;
    428 
    429 		SampleRateIdx = i;
    430 
    431 		/* update the bitrates */
    432 		tmp = 441;
    433 		if(config.sampleRate%8000 == 0)
    434 			tmp =480;
    435 
    436 		config.bitRate = 640*config.sampleRate/tmp*config.nChannelsOut;
    437 
    438 		if(config.bitRate/config.nChannelsOut < 4000)
    439 			config.bitRate = 4000 * config.nChannelsOut;
    440 		else if(config.bitRate > config.sampleRate*6*config.nChannelsOut)
    441 			config.bitRate = config.sampleRate*6*config.nChannelsOut;
    442 		else if(config.bitRate/config.nChannelsOut > 160000)
    443 			config.bitRate = config.nChannelsOut*160000;
    444 
    445 		/* check the bandwidth */
    446 		bitrate = config.bitRate / config.nChannelsOut;
    447 		bitrate = bitrate * tmp / config.sampleRate;
    448 
    449 		for (i = 0; rates[i]; i++)
    450 		{
    451 			if (rates[i] >= bitrate)
    452 				break;
    453 		}
    454 
    455 		config.bandWidth = BandwithCoefTab[i][SampleRateIdx];
    456 
    457 		/* init aac encoder core */
    458 		ret = AacEncOpen(hAacEnc, config);
    459 		if(ret)
    460 			return VO_ERR_AUDIO_UNSFEATURE;
    461 		break;
    462 	default:
    463 		return VO_ERR_WRONG_PARAM_ID;
    464 	}
    465 
    466 	return VO_ERR_NONE;
    467 }
    468 
    469 /**
    470 * Get the param for special target.
    471 * \param hCodec [IN]] The Codec Handle which was created by Init function.
    472 * \param uParamID [IN] The param ID.
    473 * \param pData [IN] The param value depend on the ID>
    474 * \retval VO_ERR_NONE Succeeded.
    475 */
    476 VO_U32 VO_API voAACEncGetParam(VO_HANDLE hCodec, VO_S32 uParamID, VO_PTR pData)
    477 {
    478         UNUSED(hCodec);
    479         UNUSED(uParamID);
    480         UNUSED(pData);
    481 
    482 	return VO_ERR_NONE;
    483 }
    484 
    485 /**
    486  * Get audio codec API interface
    487  * \param pEncHandle [out] Return the AAC Encoder handle.
    488  * \retval VO_ERR_OK Succeeded.
    489  */
    490 VO_S32 VO_API voGetAACEncAPI(VO_AUDIO_CODECAPI * pDecHandle)
    491 {
    492 	if(pDecHandle == NULL)
    493 		return VO_ERR_INVALID_ARG;
    494 
    495 	pDecHandle->Init = voAACEncInit;
    496 	pDecHandle->SetInputData = voAACEncSetInputData;
    497 	pDecHandle->GetOutputData = voAACEncGetOutputData;
    498 	pDecHandle->SetParam = voAACEncSetParam;
    499 	pDecHandle->GetParam = voAACEncGetParam;
    500 	pDecHandle->Uninit = voAACEncUninit;
    501 
    502 	return VO_ERR_NONE;
    503 }
    504