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