/*
 ** 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;
	int error;

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

#ifdef USE_DEAULT_MEM
	int interMem;
        interMem = 0;
#endif

        UNUSED(vType);

	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 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;
}
