// ****************** Copyright (c) 2013 by Gigaset Communications GmbH ******
// Filename : tdav_codec_fsl_amr_decwrapper.c
// Owner    : Souparna Lodh [STC]
//-------------------------------------------------------------------------
// Defintion : FSL AMR-NB and AMR-WB codecs.
// Freescale Enhanced Software AMR codec wrapper for decoding
//-------------------------------------------------------------------------
// 30-07-2013, Gigaset Communications GmbH
// Added FSL AMR-NB and AMR-WB codec plugin to Doubango Framework
//*************************************************************************

/*
* This file is part of Open Source Doubango Framework.
*
* DOUBANGO is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*	
* DOUBANGO is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*	
* You should have received a copy of the GNU General Public License
* along with DOUBANGO.
*
*/

#include "tdav_codec_fsl_amr_wrapper.h"

int32_t nbAMRDecInstanceInit(AMRDecWrapper_t *pDecWrapper)
{
    //__android_log_print("Teleca", "FSL AMR", "nbAMRDecInstanceInit in\n");
    int32_t mem_count, i;
    uint32_t BufferSize;
    uint8_t *pBuffer;
    eAMRDReturnType AmrRet;

    TSK_DEBUG_INFO("%s++\n", __FUNCTION__);
    pDecWrapper->pNbAmrDecConfig = (sAMRDDecoderConfigType *)tsk_calloc(sizeof(sAMRDDecoderConfigType), sizeof(uint8_t));
    if (pDecWrapper->pNbAmrDecConfig == NULL) {
	    TSK_DEBUG_ERROR("Can't get memory.\n");
        //__android_log_print("Teleca", "FSL AMR", "nbAMRDecInstanceInit out - 1\n");
	    return -1;
    }
    
    AmrRet = eAMRDQueryMem(pDecWrapper->pNbAmrDecConfig );
    if (AmrRet != E_NBAMRD_OK) {
	    TSK_DEBUG_ERROR("Amr decoder query memory fail.\n");
        //__android_log_print("Teleca", "FSL AMR", "nbAMRDecInstanceInit out - 2\n");
	    return -1;
    }

    mem_count = pDecWrapper->pNbAmrDecConfig->sAMRDMemInfo.s32AMRDNumMemReqs;
    for (i = 0; i < mem_count; i ++) {
	    BufferSize = pDecWrapper->pNbAmrDecConfig ->sAMRDMemInfo.asMemInfoSub[i].s32AMRDSize;
	    pBuffer = (uint8_t *)tsk_calloc(BufferSize, sizeof(uint8_t));
	    if (pBuffer == NULL) {
	        TSK_DEBUG_ERROR("Failed to allocate memory[%d] Size : %d\n", i, BufferSize);
            //__android_log_print("Teleca", "FSL AMR", "nbAMRDecInstanceInit out - 3\n");
	        return -1;
	    }
        pDecWrapper->pNbAmrDecConfig->sAMRDMemInfo.asMemInfoSub[i].pvAPPDBasePtr = pBuffer;
    }

    pDecWrapper->amrFrameFormatType = E_AMRFF_MMS;

    TSK_DEBUG_INFO("%s--\n", __FUNCTION__);
    //__android_log_print("Teleca", "FSL AMR", "nbAMRDecInstanceInit out\n");
    return 0;
}

int32_t nbAMRDecoderInit(AMRDecWrapper_t *pDecWrapper)
{
    __android_log_print("Teleca", "FSL AMR", "nbAMRDecoderInit in\n");
    eAMRDReturnType AmrRet;
    TSK_DEBUG_INFO("%s++\n", __FUNCTION__);

    switch(pDecWrapper->amrFrameFormatType) {
        case E_AMRFF_Conformance:
            //__android_log_print("Teleca", "FSL AMR", "nbAMRDecoderInit Setting Conformance\n");
			pDecWrapper->pNbAmrDecConfig->u8BitStreamFormat = NBAMR_ETSI;
            break;
        case E_AMRFF_MMS:
            //__android_log_print("Teleca", "FSL AMR", "nbAMRDecoderInit Setting MMS\n");
			pDecWrapper->pNbAmrDecConfig->u8BitStreamFormat = NBAMR_MMSIO;
            break;
        case E_AMRFF_IF1:
            //__android_log_print("Teleca", "FSL AMR", "nbAMRDecoderInit Setting IF1\n");
			pDecWrapper->pNbAmrDecConfig->u8BitStreamFormat = NBAMR_IF1IO;
            break;
        case E_AMRFF_IF2:
            //__android_log_print("Teleca", "FSL AMR", "nbAMRDecoderInit Setting IF2\n");
			pDecWrapper->pNbAmrDecConfig->u8BitStreamFormat = NBAMR_IF2IO;
            break;
        default:
            //__android_log_print("Teleca", "FSL AMR", "nbAMRDecoderInit out - no BRSTTEAMFormat set\n");
            return -1;
    }

    pDecWrapper->pNbAmrDecConfig->pvAMRDDecodeInfoPtr         = NULL;
    pDecWrapper->pNbAmrDecConfig->pu8APPDInitializedDataStart = NULL;
    pDecWrapper->pNbAmrDecConfig->u8RXFrameType               = 0;
    pDecWrapper->pNbAmrDecConfig->u8NumFrameToDecode          = FRAMESPERLOOP;

    AmrRet = eAMRDDecodeInit(pDecWrapper->pNbAmrDecConfig);
    if (AmrRet != E_NBAMRD_OK) {
	    TSK_DEBUG_ERROR("Amr decoder initialize fail.\n");
        //__android_log_print("Teleca", "FSL AMR", "nbAMRDecoderInit out - 1\n");
	    return -1;
    }
    TSK_DEBUG_INFO("%s--\n", __FUNCTION__);
    __android_log_print("Teleca", "FSL AMR", "nbAMRDecoderInit out\n");
    return 0;
}

int32_t nbAMRDecInstanceDeInit(AMRDecWrapper_t *pDecWrapper)
{
    uint32_t i;
    uint32_t mem_count = pDecWrapper->pNbAmrDecConfig->sAMRDMemInfo.s32AMRDNumMemReqs;
    TSK_DEBUG_INFO("%s++\n", __FUNCTION__);
    for (i = 0; i < mem_count; i ++) {
	    TSK_FREE(pDecWrapper->pNbAmrDecConfig->sAMRDMemInfo.asMemInfoSub[i].pvAPPDBasePtr);
    }

    TSK_FREE(pDecWrapper->pNbAmrDecConfig);
    TSK_DEBUG_INFO("%s--\n", __FUNCTION__);
    return 0;
}

int32_t  nbAMRDecodeFrame(AMRDecWrapper_t *pDecWrapper,
                          uint8_t *pInputBuffer,
                          uint8_t *pOutBuffer,
                          uint32_t inputDataSize,
                          uint32_t *pConsumedSize)
{
    //__android_log_print("Teleca", "FSL AMR", "nbAMRDecodeFrame in\n");
    int32_t ret = 0;
    uint8_t *pSrcCur, Header ;

    eAMRDReturnType AmrRet;

    AmrRet = eAMRDDecodeFrame(pDecWrapper->pNbAmrDecConfig, (NBAMR_S16 *)pInputBuffer/*pDecWrapper->pInBuf*/, (NBAMR_S16 *)pOutBuffer);

    ret = (AmrRet == E_NBAMRD_OK)? 0 : -1;

    //__android_log_print("Teleca", "FSL AMR", "nbAMRDecodeFrame out\n");

    return ret;
}

uint32_t nbAMRDecGetFrameOutputSize(AMRDecWrapper_t *pDecWrapper)
{
    return pDecWrapper->pNbAmrDecConfig->u8NumFrameToDecode * L_FRAME * sizeof(NBAMR_S16);
}

uint32_t nbAMRDecGetBitRate(AMRDecWrapper_t *pDecWrapper, uint32_t InputframeSize)
{
    if(pDecWrapper->pNbAmrDecConfig->u8NumFrameToDecode > 0)
        return (InputframeSize << 3) * 8000 / L_FRAME / pDecWrapper->pNbAmrDecConfig->u8NumFrameToDecode;
    else
        return 0;
}

AMRDecWrapper_t *CreateAMRDecWrapper(tsk_bool_t nbAMR)
{
	AMRDecWrapper_t *pAMRDecWrapper;
    TSK_DEBUG_INFO("%s++\n", __FUNCTION__);

	pAMRDecWrapper = (AMRDecWrapper_t *)tsk_malloc(sizeof(AMRDecWrapper_t));
	if(pAMRDecWrapper == NULL) {
		TSK_DEBUG_ERROR("Failed to allocate memory for AMR DecWrapper\n");
		return NULL;
	}

	if(nbAMR == tsk_true) {
		//initialize nb AMR decoder wrapper
         pAMRDecWrapper->InstanceInit               = nbAMRDecInstanceInit;
         pAMRDecWrapper->CodecInit                  = nbAMRDecoderInit;
         pAMRDecWrapper->InstanceDeInit             = nbAMRDecInstanceDeInit;
         pAMRDecWrapper->decodeFrame                = nbAMRDecodeFrame;
         pAMRDecWrapper->getFrameOutputSize         = nbAMRDecGetFrameOutputSize;
         pAMRDecWrapper->getBitRate                 = nbAMRDecGetBitRate;
    } else {
		//initialize wb AMR decoder wrapper
         pAMRDecWrapper->InstanceInit               = NULL;//wbAMRDecInstanceInit;
         pAMRDecWrapper->CodecInit                  = NULL;//wbAMRDecoderInit;
         pAMRDecWrapper->InstanceDeInit             = NULL;//wbAMRDecInstanceDeInit;
         pAMRDecWrapper->decodeFrame                = NULL;//wbAMRDecodeFrame;
         pAMRDecWrapper->getFrameOutputSize         = NULL;//wbAMRDecGetFrameOutputSize;
         pAMRDecWrapper->getBitRate                 = NULL;//wbAMRDecGetBitRate;
    }

    TSK_DEBUG_INFO("%s--\n", __FUNCTION__);
    return pAMRDecWrapper;
}

void DeleteAMRDecWrapper(AMRDecWrapper_t *pDecWrapper)
{
	if(pDecWrapper != NULL) {
		TSK_FREE(pDecWrapper);
	}
}

