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	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*/
166VO_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*/
212VO_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*/
291VO_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*/
315VO_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*/
476VO_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 */
490VO_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