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