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 */
voAACEncInit(VO_HANDLE * phCodec,VO_AUDIO_CODINGTYPE vType,VO_CODEC_INIT_USERDATA * pUserData)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 */
voAACEncSetInputData(VO_HANDLE hCodec,VO_CODECBUFFER * pInput)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 */
voAACEncGetOutputData(VO_HANDLE hCodec,VO_CODECBUFFER * pOutput,VO_AUDIO_OUTPUTINFO * pOutInfo)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 */
voAACEncUninit(VO_HANDLE hCodec)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 */
voAACEncSetParam(VO_HANDLE hCodec,VO_S32 uParamID,VO_PTR pData)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 */
voAACEncGetParam(VO_HANDLE hCodec,VO_S32 uParamID,VO_PTR pData)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  */
voGetAACEncAPI(VO_AUDIO_CODECAPI * pDecHandle)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