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