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