aacenc.c revision 956c553ab0ce72f8074ad0fda2ffd66a0305700c
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/**
31* Init the audio codec module and return codec handle
32* \param phCodec [OUT] Return the video codec handle
33* \param vType	[IN] The codec type if the module support multi codec.
34* \param pUserData	[IN] The init param. It is memory operator or alloced memory
35* \retval VO_ERR_NONE Succeeded.
36*/
37VO_U32 VO_API voAACEncInit(VO_HANDLE * phCodec,VO_AUDIO_CODINGTYPE vType, VO_CODEC_INIT_USERDATA *pUserData)
38{
39	AAC_ENCODER*hAacEnc;
40	AACENC_CONFIG config;
41	int error;
42
43#ifdef USE_DEAULT_MEM
44	VO_MEM_OPERATOR voMemoprator;
45#endif
46	VO_MEM_OPERATOR *pMemOP;
47	int interMem;
48
49	interMem = 0;
50	error = 0;
51
52	/* init the memory operator */
53	if(pUserData == NULL || pUserData->memflag != VO_IMF_USERMEMOPERATOR || pUserData->memData == NULL )
54	{
55#ifdef USE_DEAULT_MEM
56		voMemoprator.Alloc = cmnMemAlloc;
57		voMemoprator.Copy = cmnMemCopy;
58		voMemoprator.Free = cmnMemFree;
59		voMemoprator.Set = cmnMemSet;
60		voMemoprator.Check = cmnMemCheck;
61
62		interMem = 1;
63
64		pMemOP = &voMemoprator;
65#else
66		*phCodec = NULL;
67		return VO_ERR_INVALID_ARG;
68#endif
69	}
70	else
71	{
72		pMemOP = (VO_MEM_OPERATOR *)pUserData->memData;
73	}
74
75	/* init the aac encoder handle */
76	hAacEnc = (AAC_ENCODER*)mem_malloc(pMemOP, sizeof(AAC_ENCODER), 32, VO_INDEX_ENC_AAC);
77	if(NULL == hAacEnc)
78	{
79		error = 1;
80	}
81
82	if(!error)
83	{
84		/* init the aac encoder intra memory */
85		hAacEnc->intbuf = (short *)mem_malloc(pMemOP, AACENC_BLOCKSIZE*MAX_CHANNELS*sizeof(short), 32, VO_INDEX_ENC_AAC);
86		if(NULL == hAacEnc->intbuf)
87		{
88			error = 1;
89		}
90	}
91
92	if (!error) {
93		/* init the aac encoder psychoacoustic */
94		error = (PsyNew(&hAacEnc->psyKernel, MAX_CHANNELS, pMemOP) ||
95			PsyOutNew(&hAacEnc->psyOut, pMemOP));
96	}
97
98	if (!error) {
99		/* init the aac encoder quantization elements */
100		error = QCOutNew(&hAacEnc->qcOut,MAX_CHANNELS, pMemOP);
101	}
102
103	if (!error) {
104		/* init the aac encoder quantization state */
105		error = QCNew(&hAacEnc->qcKernel, pMemOP);
106	}
107
108	/* uninit the aac encoder if error is nozero */
109	if(error)
110	{
111		AacEncClose(hAacEnc, pMemOP);
112		if(hAacEnc)
113		{
114			mem_free(pMemOP, hAacEnc, VO_INDEX_ENC_AAC);
115			hAacEnc = NULL;
116		}
117		*phCodec = NULL;
118		return VO_ERR_OUTOF_MEMORY;
119	}
120
121	/* init the aac encoder memory operator  */
122#ifdef USE_DEAULT_MEM
123	if(interMem)
124	{
125		hAacEnc->voMemoprator.Alloc = cmnMemAlloc;
126		hAacEnc->voMemoprator.Copy = cmnMemCopy;
127		hAacEnc->voMemoprator.Free = cmnMemFree;
128		hAacEnc->voMemoprator.Set = cmnMemSet;
129		hAacEnc->voMemoprator.Check = cmnMemCheck;
130
131		pMemOP = &hAacEnc->voMemoprator;
132	}
133#endif
134	/* init the aac encoder default parameter  */
135	if(hAacEnc->initOK == 0)
136	{
137		 AACENC_CONFIG config;
138		 config.adtsUsed = 1;
139		 config.bitRate = 128000;
140		 config.nChannelsIn = 2;
141		 config.nChannelsOut = 2;
142		 config.sampleRate = 44100;
143		 config.bandWidth = 20000;
144
145		 AacEncOpen(hAacEnc, config);
146	}
147
148	hAacEnc->voMemop = pMemOP;
149
150	*phCodec = hAacEnc;
151
152	return VO_ERR_NONE;
153}
154
155/**
156* Set input audio data.
157* \param hCodec [IN]] The Codec Handle which was created by Init function.
158* \param pInput [IN] The input buffer param.
159* \param pOutBuffer [OUT] The output buffer info.
160* \retval VO_ERR_NONE Succeeded.
161*/
162VO_U32 VO_API voAACEncSetInputData(VO_HANDLE hCodec, VO_CODECBUFFER * pInput)
163{
164	AAC_ENCODER *hAacEnc;
165	int  length;
166
167	if(NULL == hCodec || NULL == pInput || NULL == pInput->Buffer)
168	{
169		return VO_ERR_INVALID_ARG;
170	}
171
172	hAacEnc = (AAC_ENCODER *)hCodec;
173
174	/* init input pcm buffer and length*/
175	hAacEnc->inbuf = (short *)pInput->Buffer;
176	hAacEnc->inlen = pInput->Length / sizeof(short);
177	hAacEnc->uselength = 0;
178
179	hAacEnc->encbuf = hAacEnc->inbuf;
180	hAacEnc->enclen = hAacEnc->inlen;
181
182	/* rebuild intra pcm buffer and length*/
183	if(hAacEnc->intlen)
184	{
185		length = min(hAacEnc->config.nChannelsIn*AACENC_BLOCKSIZE - hAacEnc->intlen, hAacEnc->inlen);
186		hAacEnc->voMemop->Copy(VO_INDEX_ENC_AAC, hAacEnc->intbuf + hAacEnc->intlen,
187			hAacEnc->inbuf, length*sizeof(short));
188
189		hAacEnc->encbuf = hAacEnc->intbuf;
190		hAacEnc->enclen = hAacEnc->intlen + length;
191
192		hAacEnc->inbuf += length;
193		hAacEnc->inlen -= length;
194	}
195
196	return VO_ERR_NONE;
197}
198
199/**
200* Get the outut audio data
201* \param hCodec [IN]] The Codec Handle which was created by Init function.
202* \param pOutBuffer [OUT] The output audio data
203* \param pOutInfo [OUT] The dec module filled audio format and used the input size.
204*						 pOutInfo->InputUsed is total used the input size.
205* \retval  VO_ERR_NONE Succeeded.
206*			VO_ERR_INPUT_BUFFER_SMALL. The input was finished or the input data was not enought.
207*/
208VO_U32 VO_API voAACEncGetOutputData(VO_HANDLE hCodec, VO_CODECBUFFER * pOutput, VO_AUDIO_OUTPUTINFO * pOutInfo)
209{
210	AAC_ENCODER* hAacEnc = (AAC_ENCODER*)hCodec;
211	Word16 numAncDataBytes=0;
212	Word32  inbuflen;
213	int ret, length;
214	if(NULL == hAacEnc)
215		return VO_ERR_INVALID_ARG;
216
217	 inbuflen = AACENC_BLOCKSIZE*hAacEnc->config.nChannelsIn;
218
219	 /* check the input pcm buffer and length*/
220	 if(NULL == hAacEnc->encbuf || hAacEnc->enclen < inbuflen)
221	 {
222		length = hAacEnc->enclen;
223		if(hAacEnc->intlen == 0)
224		{
225			hAacEnc->voMemop->Copy(VO_INDEX_ENC_AAC, hAacEnc->intbuf,
226				hAacEnc->encbuf, length*sizeof(short));
227			hAacEnc->uselength += length*sizeof(short);
228		}
229		else
230		{
231			hAacEnc->uselength += (length - hAacEnc->intlen)*sizeof(short);
232		}
233
234		hAacEnc->intlen = length;
235
236		pOutput->Length = 0;
237		if(pOutInfo)
238			pOutInfo->InputUsed = hAacEnc->uselength;
239		return VO_ERR_INPUT_BUFFER_SMALL;
240	 }
241
242	 /* check the output aac buffer and length*/
243	 if(NULL == pOutput || NULL == pOutput->Buffer || pOutput->Length < (6144/8)*hAacEnc->config.nChannelsOut/(sizeof(Word32)))
244		 return VO_ERR_OUTPUT_BUFFER_SMALL;
245
246	 /* aac encoder core function */
247	 AacEncEncode( hAacEnc,
248			(Word16*)hAacEnc->encbuf,
249			NULL,
250			&numAncDataBytes,
251			pOutput->Buffer,
252			&pOutput->Length);
253
254	 /* update the input pcm buffer and length*/
255	 if(hAacEnc->intlen)
256	 {
257		length = inbuflen - hAacEnc->intlen;
258		hAacEnc->encbuf = hAacEnc->inbuf;
259		hAacEnc->enclen = hAacEnc->inlen;
260		hAacEnc->uselength += length*sizeof(short);
261		hAacEnc->intlen = 0;
262	 }
263	 else
264	 {
265		 hAacEnc->encbuf = hAacEnc->encbuf + inbuflen;
266		 hAacEnc->enclen = hAacEnc->enclen - inbuflen;
267		 hAacEnc->uselength += inbuflen*sizeof(short);
268	 }
269
270	 /* update the output aac information */
271	if(pOutInfo)
272	{
273		pOutInfo->Format.Channels = hAacEnc->config.nChannelsOut;
274		pOutInfo->Format.SampleRate = hAacEnc->config.sampleRate;
275		pOutInfo->Format.SampleBits = 16;
276		pOutInfo->InputUsed = hAacEnc->uselength;
277	}
278
279	 return VO_ERR_NONE;
280}
281
282/**
283* Uninit the Codec.
284* \param hCodec [IN]] The Codec Handle which was created by Init function.
285* \retval VO_ERR_NONE Succeeded.
286*/
287VO_U32 VO_API voAACEncUninit(VO_HANDLE hCodec)
288{
289	AAC_ENCODER* hAacEnc = (AAC_ENCODER*)hCodec;
290
291	if(NULL != hAacEnc)
292	{
293		/* close the aac encoder */
294		AacEncClose(hAacEnc, hAacEnc->voMemop);
295
296		/* free the aac encoder handle*/
297		mem_free(hAacEnc->voMemop, hAacEnc, VO_INDEX_ENC_AAC);
298		hAacEnc = NULL;
299	}
300
301	return VO_ERR_NONE;
302}
303
304/**
305* Set the param for special target.
306* \param hCodec [IN]] The Codec Handle which was created by Init function.
307* \param uParamID [IN] The param ID.
308* \param pData [IN] The param value depend on the ID>
309* \retval VO_ERR_NONE Succeeded.
310*/
311VO_U32 VO_API voAACEncSetParam(VO_HANDLE hCodec, VO_S32 uParamID, VO_PTR pData)
312{
313	AACENC_CONFIG config;
314	AACENC_PARAM* pAAC_param;
315	VO_AUDIO_FORMAT *pWAV_Format;
316	AAC_ENCODER* hAacEnc = (AAC_ENCODER*)hCodec;
317	int ret, i, bitrate, tmp;
318	int SampleRateIdx;
319
320	if(NULL == hAacEnc)
321		return VO_ERR_INVALID_ARG;
322
323	switch(uParamID)
324	{
325	case VO_PID_AAC_ENCPARAM:  /* init aac encoder parameter*/
326		AacInitDefaultConfig(&config);
327		if(pData == NULL)
328			return VO_ERR_INVALID_ARG;
329		pAAC_param = (AACENC_PARAM*)pData;
330		config.adtsUsed = pAAC_param->adtsUsed;
331		config.bitRate = pAAC_param->bitRate;
332		config.nChannelsIn = pAAC_param->nChannels;
333		config.nChannelsOut = pAAC_param->nChannels;
334		config.sampleRate = pAAC_param->sampleRate;
335
336		/* check the channel */
337		if(config.nChannelsIn< 1  || config.nChannelsIn > MAX_CHANNELS  ||
338             config.nChannelsOut < 1 || config.nChannelsOut > MAX_CHANNELS || config.nChannelsIn < config.nChannelsOut)
339			 return VO_ERR_AUDIO_UNSCHANNEL;
340
341		/* check the samplerate */
342		ret = -1;
343		for(i = 0; i < NUM_SAMPLE_RATES; i++)
344		{
345			if(config.sampleRate == sampRateTab[i])
346			{
347				ret = 0;
348				break;
349			}
350		}
351		if(ret < 0)
352			return VO_ERR_AUDIO_UNSSAMPLERATE;
353
354		SampleRateIdx = i;
355
356		tmp = 441;
357		if(config.sampleRate%8000 == 0)
358			tmp =480;
359		/* check the bitrate */
360		if(config.bitRate!=0 && (config.bitRate/config.nChannelsOut < 4000) ||
361           (config.bitRate/config.nChannelsOut > 160000) ||
362		   (config.bitRate > config.sampleRate*6*config.nChannelsOut))
363		{
364			config.bitRate = 640*config.sampleRate/tmp*config.nChannelsOut;
365
366			if(config.bitRate/config.nChannelsOut < 4000)
367				config.bitRate = 4000 * config.nChannelsOut;
368			else if(config.bitRate > config.sampleRate*6*config.nChannelsOut)
369				config.bitRate = config.sampleRate*6*config.nChannelsOut;
370			else if(config.bitRate/config.nChannelsOut > 160000)
371				config.bitRate = config.nChannelsOut*160000;
372		}
373
374		/* check the bandwidth */
375		bitrate = config.bitRate / config.nChannelsOut;
376		bitrate = bitrate * tmp / config.sampleRate;
377
378		for (i = 0; rates[i]; i++)
379		{
380			if (rates[i] >= bitrate)
381				break;
382		}
383
384		config.bandWidth = BandwithCoefTab[i][SampleRateIdx];
385
386		/* init aac encoder core */
387		ret = AacEncOpen(hAacEnc, config);
388		if(ret)
389			return VO_ERR_AUDIO_UNSFEATURE;
390		break;
391	case VO_PID_AUDIO_FORMAT:	/* init pcm channel and samplerate*/
392		AacInitDefaultConfig(&config);
393		if(pData == NULL)
394			return VO_ERR_INVALID_ARG;
395		pWAV_Format = (VO_AUDIO_FORMAT*)pData;
396		config.adtsUsed = 1;
397		config.nChannelsIn = pWAV_Format->Channels;
398		config.nChannelsOut = pWAV_Format->Channels;
399		config.sampleRate = pWAV_Format->SampleRate;
400
401		/* check the channel */
402		if(config.nChannelsIn< 1  || config.nChannelsIn > MAX_CHANNELS  ||
403             config.nChannelsOut < 1 || config.nChannelsOut > MAX_CHANNELS || config.nChannelsIn < config.nChannelsOut)
404			 return VO_ERR_AUDIO_UNSCHANNEL;
405
406		/* check the samplebits */
407		if(pWAV_Format->SampleBits != 16)
408		{
409			return VO_ERR_AUDIO_UNSFEATURE;
410		}
411
412		/* check the samplerate */
413		ret = -1;
414		for(i = 0; i < NUM_SAMPLE_RATES; i++)
415		{
416			if(config.sampleRate == sampRateTab[i])
417			{
418				ret = 0;
419				break;
420			}
421		}
422		if(ret < 0)
423			return VO_ERR_AUDIO_UNSSAMPLERATE;
424
425		SampleRateIdx = i;
426
427		/* update the bitrates */
428		tmp = 441;
429		if(config.sampleRate%8000 == 0)
430			tmp =480;
431
432		config.bitRate = 640*config.sampleRate/tmp*config.nChannelsOut;
433
434		if(config.bitRate/config.nChannelsOut < 4000)
435			config.bitRate = 4000 * config.nChannelsOut;
436		else if(config.bitRate > config.sampleRate*6*config.nChannelsOut)
437			config.bitRate = config.sampleRate*6*config.nChannelsOut;
438		else if(config.bitRate/config.nChannelsOut > 160000)
439			config.bitRate = config.nChannelsOut*160000;
440
441		/* check the bandwidth */
442		bitrate = config.bitRate / config.nChannelsOut;
443		bitrate = bitrate * tmp / config.sampleRate;
444
445		for (i = 0; rates[i]; i++)
446		{
447			if (rates[i] >= bitrate)
448				break;
449		}
450
451		config.bandWidth = BandwithCoefTab[i][SampleRateIdx];
452
453		/* init aac encoder core */
454		ret = AacEncOpen(hAacEnc, config);
455		if(ret)
456			return VO_ERR_AUDIO_UNSFEATURE;
457		break;
458	default:
459		return VO_ERR_WRONG_PARAM_ID;
460	}
461
462	return VO_ERR_NONE;
463}
464
465/**
466* Get the param for special target.
467* \param hCodec [IN]] The Codec Handle which was created by Init function.
468* \param uParamID [IN] The param ID.
469* \param pData [IN] The param value depend on the ID>
470* \retval VO_ERR_NONE Succeeded.
471*/
472VO_U32 VO_API voAACEncGetParam(VO_HANDLE hCodec, VO_S32 uParamID, VO_PTR pData)
473{
474	return VO_ERR_NONE;
475}
476
477/**
478 * Get audio codec API interface
479 * \param pEncHandle [out] Return the AAC Encoder handle.
480 * \retval VO_ERR_OK Succeeded.
481 */
482VO_S32 VO_API voGetAACEncAPI(VO_AUDIO_CODECAPI * pDecHandle)
483{
484	if(pDecHandle == NULL)
485		return VO_ERR_INVALID_ARG;
486
487	pDecHandle->Init = voAACEncInit;
488	pDecHandle->SetInputData = voAACEncSetInputData;
489	pDecHandle->GetOutputData = voAACEncGetOutputData;
490	pDecHandle->SetParam = voAACEncSetParam;
491	pDecHandle->GetParam = voAACEncGetParam;
492	pDecHandle->Uninit = voAACEncUninit;
493
494	return VO_ERR_NONE;
495}