/*
 ** Copyright 2003-2010, VisualOn, Inc.
 **
 ** Licensed under the Apache License, Version 2.0 (the "License");
 ** you may not use this file except in compliance with the License.
 ** You may obtain a copy of the License at
 **
 **     http://www.apache.org/licenses/LICENSE-2.0
 **
 ** Unless required by applicable law or agreed to in writing, software
 ** distributed under the License is distributed on an "AS IS" BASIS,
 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 ** See the License for the specific language governing permissions and
 ** limitations under the License.
 */
/*******************************************************************************
	File:		aacenc.c

	Content:	aac encoder interface functions

*******************************************************************************/

#include "voAAC.h"
#include "typedef.h"
#include "aacenc_core.h"
#include "aac_rom.h"
#include "cmnMemory.h"
#include "memalign.h"

#define UNUSED(x) (void)(x)

/**
* Init the audio codec module and return codec handle
* \param phCodec [OUT] Return the video codec handle
* \param vType	[IN] The codec type if the module support multi codec.
* \param pUserData	[IN] The init param. It is memory operator or alloced memory
* \retval VO_ERR_NONE Succeeded.
*/
VO_U32 VO_API voAACEncInit(VO_HANDLE * phCodec,VO_AUDIO_CODINGTYPE vType, VO_CODEC_INIT_USERDATA *pUserData)
{
	AAC_ENCODER*hAacEnc;
	AACENC_CONFIG config;
	int error;

#ifdef USE_DEAULT_MEM
	VO_MEM_OPERATOR voMemoprator;
#endif
	VO_MEM_OPERATOR *pMemOP;
	int interMem;

        UNUSED(vType);

	interMem = 0;
	error = 0;

	/* init the memory operator */
	if(pUserData == NULL || pUserData->memflag != VO_IMF_USERMEMOPERATOR || pUserData->memData == NULL )
	{
#ifdef USE_DEAULT_MEM
		voMemoprator.Alloc = cmnMemAlloc;
		voMemoprator.Copy = cmnMemCopy;
		voMemoprator.Free = cmnMemFree;
		voMemoprator.Set = cmnMemSet;
		voMemoprator.Check = cmnMemCheck;

		interMem = 1;

		pMemOP = &voMemoprator;
#else
		*phCodec = NULL;
		return VO_ERR_INVALID_ARG;
#endif
	}
	else
	{
		pMemOP = (VO_MEM_OPERATOR *)pUserData->memData;
	}

	/* init the aac encoder handle */
	hAacEnc = (AAC_ENCODER*)mem_malloc(pMemOP, sizeof(AAC_ENCODER), 32, VO_INDEX_ENC_AAC);
	if(NULL == hAacEnc)
	{
		error = 1;
	}

	if(!error)
	{
		/* init the aac encoder intra memory */
		hAacEnc->intbuf = (short *)mem_malloc(pMemOP, AACENC_BLOCKSIZE*MAX_CHANNELS*sizeof(short), 32, VO_INDEX_ENC_AAC);
		if(NULL == hAacEnc->intbuf)
		{
			error = 1;
		}
	}

	if (!error) {
		/* init the aac encoder psychoacoustic */
		error = (PsyNew(&hAacEnc->psyKernel, MAX_CHANNELS, pMemOP) ||
			PsyOutNew(&hAacEnc->psyOut, pMemOP));
	}

	if (!error) {
		/* init the aac encoder quantization elements */
		error = QCOutNew(&hAacEnc->qcOut,MAX_CHANNELS, pMemOP);
	}

	if (!error) {
		/* init the aac encoder quantization state */
		error = QCNew(&hAacEnc->qcKernel, pMemOP);
	}

	/* uninit the aac encoder if error is nozero */
	if(error)
	{
		AacEncClose(hAacEnc, pMemOP);
		if(hAacEnc)
		{
			mem_free(pMemOP, hAacEnc, VO_INDEX_ENC_AAC);
			hAacEnc = NULL;
		}
		*phCodec = NULL;
		return VO_ERR_OUTOF_MEMORY;
	}

	/* init the aac encoder memory operator  */
#ifdef USE_DEAULT_MEM
	if(interMem)
	{
		hAacEnc->voMemoprator.Alloc = cmnMemAlloc;
		hAacEnc->voMemoprator.Copy = cmnMemCopy;
		hAacEnc->voMemoprator.Free = cmnMemFree;
		hAacEnc->voMemoprator.Set = cmnMemSet;
		hAacEnc->voMemoprator.Check = cmnMemCheck;

		pMemOP = &hAacEnc->voMemoprator;
	}
#endif
	/* init the aac encoder default parameter  */
	if(hAacEnc->initOK == 0)
	{
		 AACENC_CONFIG config;
		 config.adtsUsed = 1;
		 config.bitRate = 128000;
		 config.nChannelsIn = 2;
		 config.nChannelsOut = 2;
		 config.sampleRate = 44100;
		 config.bandWidth = 20000;

		 AacEncOpen(hAacEnc, config);
	}

	hAacEnc->voMemop = pMemOP;

	*phCodec = hAacEnc;

	return VO_ERR_NONE;
}

/**
* Set input audio data.
* \param hCodec [IN]] The Codec Handle which was created by Init function.
* \param pInput [IN] The input buffer param.
* \param pOutBuffer [OUT] The output buffer info.
* \retval VO_ERR_NONE Succeeded.
*/
VO_U32 VO_API voAACEncSetInputData(VO_HANDLE hCodec, VO_CODECBUFFER * pInput)
{
	AAC_ENCODER *hAacEnc;
	int  length;

	if(NULL == hCodec || NULL == pInput || NULL == pInput->Buffer)
	{
		return VO_ERR_INVALID_ARG;
	}

	hAacEnc = (AAC_ENCODER *)hCodec;

	/* init input pcm buffer and length*/
	hAacEnc->inbuf = (short *)pInput->Buffer;
	hAacEnc->inlen = pInput->Length / sizeof(short);
	hAacEnc->uselength = 0;

	hAacEnc->encbuf = hAacEnc->inbuf;
	hAacEnc->enclen = hAacEnc->inlen;

	/* rebuild intra pcm buffer and length*/
	if(hAacEnc->intlen)
	{
		length = min(hAacEnc->config.nChannelsIn*AACENC_BLOCKSIZE - hAacEnc->intlen, hAacEnc->inlen);
		hAacEnc->voMemop->Copy(VO_INDEX_ENC_AAC, hAacEnc->intbuf + hAacEnc->intlen,
			hAacEnc->inbuf, length*sizeof(short));

		hAacEnc->encbuf = hAacEnc->intbuf;
		hAacEnc->enclen = hAacEnc->intlen + length;

		hAacEnc->inbuf += length;
		hAacEnc->inlen -= length;
	}

	return VO_ERR_NONE;
}

/**
* Get the outut audio data
* \param hCodec [IN]] The Codec Handle which was created by Init function.
* \param pOutBuffer [OUT] The output audio data
* \param pOutInfo [OUT] The dec module filled audio format and used the input size.
*						 pOutInfo->InputUsed is total used the input size.
* \retval  VO_ERR_NONE Succeeded.
*			VO_ERR_INPUT_BUFFER_SMALL. The input was finished or the input data was not enought.
*/
VO_U32 VO_API voAACEncGetOutputData(VO_HANDLE hCodec, VO_CODECBUFFER * pOutput, VO_AUDIO_OUTPUTINFO * pOutInfo)
{
	AAC_ENCODER* hAacEnc = (AAC_ENCODER*)hCodec;
	Word16 numAncDataBytes=0;
	Word32  inbuflen;
	int ret, length;
	if(NULL == hAacEnc)
		return VO_ERR_INVALID_ARG;

	 inbuflen = AACENC_BLOCKSIZE*hAacEnc->config.nChannelsIn;

	 /* check the input pcm buffer and length*/
	 if(NULL == hAacEnc->encbuf || hAacEnc->enclen < inbuflen)
	 {
		length = hAacEnc->enclen;
		if(hAacEnc->intlen == 0)
		{
			hAacEnc->voMemop->Copy(VO_INDEX_ENC_AAC, hAacEnc->intbuf,
				hAacEnc->encbuf, length*sizeof(short));
			hAacEnc->uselength += length*sizeof(short);
		}
		else
		{
			hAacEnc->uselength += (length - hAacEnc->intlen)*sizeof(short);
		}

		hAacEnc->intlen = length;

		pOutput->Length = 0;
		if(pOutInfo)
			pOutInfo->InputUsed = hAacEnc->uselength;
		return VO_ERR_INPUT_BUFFER_SMALL;
	 }

	 /* check the output aac buffer and length*/
	 if(NULL == pOutput || NULL == pOutput->Buffer || pOutput->Length < (6144/8)*hAacEnc->config.nChannelsOut/(sizeof(Word32)))
		 return VO_ERR_OUTPUT_BUFFER_SMALL;

	 /* aac encoder core function */
	 AacEncEncode( hAacEnc,
			(Word16*)hAacEnc->encbuf,
			NULL,
			&numAncDataBytes,
			pOutput->Buffer,
			&pOutput->Length);

	 /* update the input pcm buffer and length*/
	 if(hAacEnc->intlen)
	 {
		length = inbuflen - hAacEnc->intlen;
		hAacEnc->encbuf = hAacEnc->inbuf;
		hAacEnc->enclen = hAacEnc->inlen;
		hAacEnc->uselength += length*sizeof(short);
		hAacEnc->intlen = 0;
	 }
	 else
	 {
		 hAacEnc->encbuf = hAacEnc->encbuf + inbuflen;
		 hAacEnc->enclen = hAacEnc->enclen - inbuflen;
		 hAacEnc->uselength += inbuflen*sizeof(short);
	 }

	 /* update the output aac information */
	if(pOutInfo)
	{
		pOutInfo->Format.Channels = hAacEnc->config.nChannelsOut;
		pOutInfo->Format.SampleRate = hAacEnc->config.sampleRate;
		pOutInfo->Format.SampleBits = 16;
		pOutInfo->InputUsed = hAacEnc->uselength;
	}

	 return VO_ERR_NONE;
}

/**
* Uninit the Codec.
* \param hCodec [IN]] The Codec Handle which was created by Init function.
* \retval VO_ERR_NONE Succeeded.
*/
VO_U32 VO_API voAACEncUninit(VO_HANDLE hCodec)
{
	AAC_ENCODER* hAacEnc = (AAC_ENCODER*)hCodec;

	if(NULL != hAacEnc)
	{
		/* close the aac encoder */
		AacEncClose(hAacEnc, hAacEnc->voMemop);

		/* free the aac encoder handle*/
		mem_free(hAacEnc->voMemop, hAacEnc, VO_INDEX_ENC_AAC);
		hAacEnc = NULL;
	}

	return VO_ERR_NONE;
}

/**
* Set the param for special target.
* \param hCodec [IN]] The Codec Handle which was created by Init function.
* \param uParamID [IN] The param ID.
* \param pData [IN] The param value depend on the ID>
* \retval VO_ERR_NONE Succeeded.
*/
VO_U32 VO_API voAACEncSetParam(VO_HANDLE hCodec, VO_S32 uParamID, VO_PTR pData)
{
	AACENC_CONFIG config;
	AACENC_PARAM* pAAC_param;
	VO_AUDIO_FORMAT *pWAV_Format;
	AAC_ENCODER* hAacEnc = (AAC_ENCODER*)hCodec;
	int ret, i, bitrate, tmp;
	int SampleRateIdx;

	if(NULL == hAacEnc)
		return VO_ERR_INVALID_ARG;

	switch(uParamID)
	{
	case VO_PID_AAC_ENCPARAM:  /* init aac encoder parameter*/
		AacInitDefaultConfig(&config);
		if(pData == NULL)
			return VO_ERR_INVALID_ARG;
		pAAC_param = (AACENC_PARAM*)pData;
		config.adtsUsed = pAAC_param->adtsUsed;
		config.bitRate = pAAC_param->bitRate;
		config.nChannelsIn = pAAC_param->nChannels;
		config.nChannelsOut = pAAC_param->nChannels;
		config.sampleRate = pAAC_param->sampleRate;

		/* check the channel */
		if(config.nChannelsIn< 1  || config.nChannelsIn > MAX_CHANNELS  ||
             config.nChannelsOut < 1 || config.nChannelsOut > MAX_CHANNELS || config.nChannelsIn < config.nChannelsOut)
			 return VO_ERR_AUDIO_UNSCHANNEL;

		/* check the samplerate */
		ret = -1;
		for(i = 0; i < NUM_SAMPLE_RATES; i++)
		{
			if(config.sampleRate == sampRateTab[i])
			{
				ret = 0;
				break;
			}
		}
		if(ret < 0)
			return VO_ERR_AUDIO_UNSSAMPLERATE;

		SampleRateIdx = i;

		tmp = 441;
		if(config.sampleRate%8000 == 0)
			tmp =480;
		/* check the bitrate */
		if(config.bitRate!=0 && ((config.bitRate/config.nChannelsOut < 4000) ||
           (config.bitRate/config.nChannelsOut > 160000) ||
		   (config.bitRate > config.sampleRate*6*config.nChannelsOut)))
		{
			config.bitRate = 640*config.sampleRate/tmp*config.nChannelsOut;

			if(config.bitRate/config.nChannelsOut < 4000)
				config.bitRate = 4000 * config.nChannelsOut;
			else if(config.bitRate > config.sampleRate*6*config.nChannelsOut)
				config.bitRate = config.sampleRate*6*config.nChannelsOut;
			else if(config.bitRate/config.nChannelsOut > 160000)
				config.bitRate = config.nChannelsOut*160000;
		}

		/* check the bandwidth */
		bitrate = config.bitRate / config.nChannelsOut;
		bitrate = bitrate * tmp / config.sampleRate;

		for (i = 0; rates[i]; i++)
		{
			if (rates[i] >= bitrate)
				break;
		}

		config.bandWidth = BandwithCoefTab[i][SampleRateIdx];

		/* init aac encoder core */
		ret = AacEncOpen(hAacEnc, config);
		if(ret)
			return VO_ERR_AUDIO_UNSFEATURE;
		break;
	case VO_PID_AUDIO_FORMAT:	/* init pcm channel and samplerate*/
		AacInitDefaultConfig(&config);
		if(pData == NULL)
			return VO_ERR_INVALID_ARG;
		pWAV_Format = (VO_AUDIO_FORMAT*)pData;
		config.adtsUsed = 1;
		config.nChannelsIn = pWAV_Format->Channels;
		config.nChannelsOut = pWAV_Format->Channels;
		config.sampleRate = pWAV_Format->SampleRate;

		/* check the channel */
		if(config.nChannelsIn< 1  || config.nChannelsIn > MAX_CHANNELS  ||
             config.nChannelsOut < 1 || config.nChannelsOut > MAX_CHANNELS || config.nChannelsIn < config.nChannelsOut)
			 return VO_ERR_AUDIO_UNSCHANNEL;

		/* check the samplebits */
		if(pWAV_Format->SampleBits != 16)
		{
			return VO_ERR_AUDIO_UNSFEATURE;
		}

		/* check the samplerate */
		ret = -1;
		for(i = 0; i < NUM_SAMPLE_RATES; i++)
		{
			if(config.sampleRate == sampRateTab[i])
			{
				ret = 0;
				break;
			}
		}
		if(ret < 0)
			return VO_ERR_AUDIO_UNSSAMPLERATE;

		SampleRateIdx = i;

		/* update the bitrates */
		tmp = 441;
		if(config.sampleRate%8000 == 0)
			tmp =480;

		config.bitRate = 640*config.sampleRate/tmp*config.nChannelsOut;

		if(config.bitRate/config.nChannelsOut < 4000)
			config.bitRate = 4000 * config.nChannelsOut;
		else if(config.bitRate > config.sampleRate*6*config.nChannelsOut)
			config.bitRate = config.sampleRate*6*config.nChannelsOut;
		else if(config.bitRate/config.nChannelsOut > 160000)
			config.bitRate = config.nChannelsOut*160000;

		/* check the bandwidth */
		bitrate = config.bitRate / config.nChannelsOut;
		bitrate = bitrate * tmp / config.sampleRate;

		for (i = 0; rates[i]; i++)
		{
			if (rates[i] >= bitrate)
				break;
		}

		config.bandWidth = BandwithCoefTab[i][SampleRateIdx];

		/* init aac encoder core */
		ret = AacEncOpen(hAacEnc, config);
		if(ret)
			return VO_ERR_AUDIO_UNSFEATURE;
		break;
	default:
		return VO_ERR_WRONG_PARAM_ID;
	}

	return VO_ERR_NONE;
}

/**
* Get the param for special target.
* \param hCodec [IN]] The Codec Handle which was created by Init function.
* \param uParamID [IN] The param ID.
* \param pData [IN] The param value depend on the ID>
* \retval VO_ERR_NONE Succeeded.
*/
VO_U32 VO_API voAACEncGetParam(VO_HANDLE hCodec, VO_S32 uParamID, VO_PTR pData)
{
        UNUSED(hCodec);
        UNUSED(uParamID);
        UNUSED(pData);

	return VO_ERR_NONE;
}

/**
 * Get audio codec API interface
 * \param pEncHandle [out] Return the AAC Encoder handle.
 * \retval VO_ERR_OK Succeeded.
 */
VO_S32 VO_API voGetAACEncAPI(VO_AUDIO_CODECAPI * pDecHandle)
{
	if(pDecHandle == NULL)
		return VO_ERR_INVALID_ARG;

	pDecHandle->Init = voAACEncInit;
	pDecHandle->SetInputData = voAACEncSetInputData;
	pDecHandle->GetOutputData = voAACEncGetOutputData;
	pDecHandle->SetParam = voAACEncSetParam;
	pDecHandle->GetParam = voAACEncGetParam;
	pDecHandle->Uninit = voAACEncUninit;

	return VO_ERR_NONE;
}
