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