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*/ 39VO_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*/ 168VO_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*/ 214VO_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*/ 293VO_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*/ 317VO_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*/ 478VO_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 */ 492VO_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