/* * Copyright ., Ltd. 2019-2020. All rights reserved. * * File Name: aacdec_interface.c * Description: audio transcode function interface as example */ #include #include #include #include #include #include "fdkaac/libAACdec/include/aacdecoder_lib.h" #include "fdkaac/libAACenc/include/aacenc_lib.h" #include "cvi_type.h" #include "cvi_aacdec.h" #define _VERSION_TAG_ "audio_aac_fdkaac_dec_20210407A" #ifndef AAC_MAX_NCHANS #define AAC_MAX_NCHANS 2 #endif #define AAC_MAX_NSAMPS 1024 #define AAC_MAINBUF_SIZE (768 * AAC_MAX_NCHANS) /**aVersion, (const char *)_VERSION_TAG_); printf("[%s][%s]\n", __func__, _VERSION_TAG_); return 0; } /** *brief create and initial decoder device. *attention *N/A *param[in] enTranType : transport type *retval ::CVIAACDecoder : init success, return non-NULL handle. *retval ::NULL : init failure, return NULL *see *N/A */ CVIAACDecoder AACInitDecoder(AACDECTransportType enTranType) { HANDLE_AACDECODER decoder; //AAC_DECODER_ERROR err; if (enTranType == AACDEC_ADTS) { printf("[%s][%s]\n", __func__, _VERSION_TAG_); decoder = aacDecoder_Open(TT_MP4_ADTS, 1); printf("ADTS header decoder set\n"); } else if (enTranType == AACDEC_LOAS) decoder = aacDecoder_Open(TT_MP4_LOAS, 1); else if (enTranType == AACDEC_LATM_MCP1) decoder = aacDecoder_Open(TT_MP4_LATM_MCP1, 1); else { printf("[Warning]set TransportType[%d] to RawMode\n", (int)enTranType); decoder = aacDecoder_Open(TT_MP4_RAW, 1); printf("set to TT_MP4_RAW\n"); } if (decoder == NULL) { printf("[Error][%s][%d]\n", __func__, __LINE__); return NULL; } return (void *)decoder; } /** *brief destroy AAC-Decoder, free the memory. *attention \n *N/A *param[in] CVIAACDecoder : AAC-Decoder handle *see \n *N/A */ CVI_VOID AACFreeDecoder(CVIAACDecoder CVIAACDecoder) { if (CVIAACDecoder != NULL) aacDecoder_Close((HANDLE_AACDECODER)CVIAACDecoder); } /** *brief set RawMode before decode Raw Format aac bitstream(Reserved API, unused now.) *attention \n *N/A *param[in] CVIAACDecoder : AAC-Decoder handle *param[in] Chans : inout channels *param[in] sampRate : input sample rate *retval ::CVI_FAILURE : RESERVED API, always return CVI_FAILURE. *see \n *N/A */ CVI_S32 AACSetRawMode(CVIAACDecoder CVIAACDecoder, CVI_S32 nChans, CVI_S32 sampRate) { UCHAR conf[4] = {0xFF, 0xFF, 0xFF, 0xFF}; UCHAR* conf_array[1] = { conf }; UINT length = 4; //Step1: Find the config data HANDLE_AACENCODER tmp_enchandle; AACENC_InfoStruct tmp_info = { 0 }; if (aacEncOpen(&tmp_enchandle, 0, nChans) != AACENC_OK) { printf("[Error][%s][%d]\n", __func__, __LINE__); return (-1); } if (nChans == 1) { if (aacEncoder_SetParam(tmp_enchandle, AACENC_CHANNELMODE, MODE_1) != AACENC_OK) { printf("[Error]Unable to set the channel mode[%s][%d]\n", __func__, __LINE__); return (-1); } } else { if (aacEncoder_SetParam(tmp_enchandle, AACENC_CHANNELMODE, MODE_2) != AACENC_OK) { printf("[Error]Unable to set the channel mode[%s][%d]\n", __func__, __LINE__); return (-1); } } if (aacEncoder_SetParam(tmp_enchandle, AACENC_AOT, 2) != AACENC_OK) { printf("[Error][%s][%d]\n", __func__, __LINE__); return (-1); } if (aacEncoder_SetParam(tmp_enchandle, AACENC_SAMPLERATE, sampRate) != AACENC_OK) { printf("[Error]Unable to set the AOT[%s][%d]\n", __func__, __LINE__); return (-1); } if (aacEncoder_SetParam(tmp_enchandle, AACENC_AFTERBURNER, 1) != AACENC_OK) { printf("[Error]Unable to set the afterburner mode[%s][%d]\n", __func__, __LINE__); return (-1); } if (aacEncEncode(tmp_enchandle, NULL, NULL, NULL, NULL) != AACENC_OK) { printf("[Error]Unable to initialize the encoder[%s][%d]\n", __func__, __LINE__); return (-1); } if (aacEncInfo(tmp_enchandle, &tmp_info) != AACENC_OK) { printf("[Error]Unable to get the encoder info[%s][%d]\n", __func__, __LINE__); return (-1); } memcpy(conf, tmp_info.confBuf, 4); conf_array[1] = { conf }; printf("[%s]print out config size[%d] buffer[0x%x] [0x%x] [0x%x] [0x%x] [0x%x]\n", __func__, tmp_info.confSize, conf[0],conf[1], conf[2], conf[3], conf[4]); //Step2 : Update the config data AAC_DECODER_ERROR err = AAC_DEC_OK; err = aacDecoder_ConfigRaw((HANDLE_AACDECODER)CVIAACDecoder, conf_array, &length); if (err != AAC_DEC_OK) { printf("[Error][%s][%d]\n", __func__, __LINE__); printf("err = [0x%x]\n", err); } return 0; } int get_one_ADTS_frame(unsigned char *buffer, size_t buf_size, size_t *data_size) { size_t size = 0; size_t save_buf_size = buf_size; if (!buffer || !data_size) return -1; while (1) { if (buf_size < 7) return -1; if ((buffer[0] == 0xff) && ((buffer[1] & 0xf0) == 0xf0)) { size |= ((buffer[3] & 0x03) << 11); //high 2 bit size |= buffer[4]<<3; //middle 8 bit size |= ((buffer[5] & 0xe0)>>5); //low 3bit //printf("adts-->header[0x%x][0x%x][0x%x][0x%x]\n", buffer[0], buffer[1], buffer[2], buffer[3]); break; } --buf_size; ++buffer; } if (buf_size < size) { printf("[%s] no header...\n", __func__); return -1; } //memcpy(data, buffer, size); //printf("aft getOneFrame[0x%x][0x%x][0x%x][0x%x]\n", data[0], data[1], data[2], data[3]); *data_size = size;//parsing size from header //printf("[%s]require size[%d] left check[%d]\n", __func__, size, (2048 - size)); return (save_buf_size - size); //return bytes left } /** *brief look for valid AAC sync header *attention \n *N/A *param[in] CVIAACDecoder : AAC-Decoder handle *param[in/out] ppInbufPtr : address of the pointer of start-point of the bitstream *param[in/out] pBytesLeft : pointer to BytesLeft that indicates bitstream numbers at input buffer *retval ::<0 : err, always return ERR_AAC_INDATA_UNDERFLOW *retval ::other : Success, return number bytes of current frame *see \n *N/A */ CVI_S32 AACDecodeFindSyncHeader(CVIAACDecoder CVIAACDecoder, CVI_U8 **ppInbufPtr, CVI_S32 *pBytesLeft) { #if 0 1024 990 sample for AAC_LC 2048 or 1920 for HE-AAC (v2) 512 or 480 for AAC-LD and AAC-ELD 768, 1024, 2048 or 4096 for USAC #endif AAC_DECODER_ERROR err = AAC_DEC_OK; UINT bytes_valid; unsigned int input_sizebytes = *pBytesLeft; int current_index = 0; unsigned char *inBufferArray[1]; unsigned int inBuffReaded[1]; //step 1: wrap the input data to array inBufferArray[0] = (unsigned char *)(*ppInbufPtr); inBuffReaded[0] = input_sizebytes; bytes_valid = input_sizebytes; //step2 : fill the aacDecoder_Fill and check the return valid_bytes err = aacDecoder_Fill((HANDLE_AACDECODER)CVIAACDecoder, inBufferArray, inBuffReaded, &bytes_valid); printf("aacDecoder_Fill->bytes_valid[%d]\n", bytes_valid); if (err == AAC_DEC_OK) printf("aacDecoder_Fill return ok\n"); else { printf("err=[%d]\n", (int)err); current_index = input_sizebytes - bytes_valid; *pBytesLeft = bytes_valid; } return current_index; } /** *brief decoding AAC frame and output 1024(LC) OR *2048(HEAAC/eAAC/eAAC+) 16bit PCM samples per channel. *attention \n *param[in] CVIAACDecoder : AAC-Decoder handle *param[in] ppInbufPtr : address of the pointer of start-point of the bitstream *param[in/out] pBytesLeft : pointer to BytesLeft that indicates *bitstream numbers at input buffer,indicates the left bytes *param[in] pOutPcm : the address of the out pcm buffer, *pcm data in noninterlaced fotmat: L/L/L/... R/R/R/... *retval :: SUCCESS : Success *retval :: ERROR_CODE : FAILURE, return error_code. *see \n */ CVI_S32 AACDecodeFrame(CVIAACDecoder CVIAACDecoder, CVI_U8 **ppInbufPtr, CVI_S32 *pBytesLeft, CVI_S16 *pOutPcm) { AAC_DECODER_ERROR err = AAC_DEC_OK; CStreamInfo *theInfo = NULL; unsigned char *inBufferArray[1]; unsigned int inBuffReaded[1]; unsigned int byte_left; //CVI_U8 *tmpcheck; //tmpcheck = (CVI_U8 *)(*ppInbufPtr); //printf("in [0x%x] [0x%x] [0x%x] inbytes[%d] \n", tmpcheck[0], tmpcheck[1], tmpcheck[2], *pBytesLeft); inBufferArray[0] = (unsigned char *)(*ppInbufPtr); inBuffReaded[0] = *pBytesLeft; byte_left = *pBytesLeft; #if 0 unsigned char fake_inputdata[10240] = {0}; unsigned char fake_outputdata[10240] = {0}; int inputbytes = byte_left; memcpy(fake_inputdata, inBufferArray[0] , inputbytes); #endif err = aacDecoder_Fill((HANDLE_AACDECODER)CVIAACDecoder, inBufferArray, inBuffReaded, &byte_left); if (err != AAC_DEC_OK) { printf("[Error][%s][%d]\n", __func__, __LINE__); printf("err = [0x%x]\n", err); } else { //printf("[xxxx]aacDecoder_Fill after byte left[%d]\n", byte_left); //sleep(1); } #if 0//AAC ADTS header check int fake = 0; int fake_byteleft = 0; printf("fake_inputdata[0x%x] [0x%x]\n", fake_inputdata[0], fake_inputdata[1]); fake_byteleft = get_one_ADTS_frame( fake_inputdata, inputbytes, (size_t *)&fake); if (fake_byteleft < 0) printf("[xxxxx]fake_byteleft no header\n"); else printf("[xxxxxx]fake_byteleft[%d] data size[%d]\n", fake_byteleft, fake); #else //printf("no self check\n"); #endif err = aacDecoder_DecodeFrame((HANDLE_AACDECODER)CVIAACDecoder, (INT_PCM *) pOutPcm, (1024 * 30), 0); if (err != AAC_DEC_OK) { printf("[Error][%s][%d]\n", __func__, __LINE__); printf("err = [0x%x]\n", err); if (err == AAC_DEC_NOT_ENOUGH_BITS) printf("err[%s][%d]AAC_DEC_NOT_ENOUGH_BITS\n", __func__, __LINE__); if (err == AAC_DEC_TRANSPORT_ERROR) printf("err[%s][%d]AAC_DEC_TRANSPORT_ERROR\n", __func__, __LINE__); return err; } else { //for debug usage //printf("out [0x%x] [0x%x] [0x%x]\n", pOutPcm[0], pOutPcm[1], pOutPcm[2]); } theInfo = aacDecoder_GetStreamInfo((HANDLE_AACDECODER)CVIAACDecoder); if (theInfo == NULL) { printf("[Error]Get null info[%s][%d]\n", __func__, __LINE__); //sleep(1); } //printf("aacDecoder_DecodeFrame theInfo->frameSize[%d]\n", // theInfo->frameSize); *pBytesLeft = byte_left; return 0; } /** *brief get the frame information. *attention \n *param[in] CVIAACDecoder : AAC-Decoder handle *param[out] aacFrameInfo : frame information *retval :: CVI_SUCCESS : Success *retval :: ERROR_CODE : FAILURE, return error_code. *see \n *N/A */ CVI_S32 AACGetLastFrameInfo(CVIAACDecoder CVIAACDecoder, AACFrameInfo *aacFrameInfo) { HANDLE_AACDECODER decoder = (HANDLE_AACDECODER)CVIAACDecoder; CStreamInfo* info = aacDecoder_GetStreamInfo(decoder); aacFrameInfo->bitRate = info->bitRate; aacFrameInfo->nChans = info->numChannels; aacFrameInfo->sampRateCore = info->aacSampleRate; aacFrameInfo->sampRateOut = info->sampleRate; aacFrameInfo->bitsPerSample = 16; aacFrameInfo->outputSamps = info->frameSize; aacFrameInfo->profile = info->profile; aacFrameInfo->tnsUsed = 0; aacFrameInfo->pnsUsed = 0; aacFrameInfo->bytespassDec = info->numTotalBytes; // printf("aacDecoder_GetStreamInfo br[%d] ch[%d] sr[%d] total bytes pass[%ld]aacsr[%d]\n", // info->bitRate, // info->numChannels, // info->sampleRate, // info->numTotalBytes, // info->aacSampleRate); return 0; } /** *brief set eosflag. *attention \n *param[in] CVIAACDecoder : AAC-Decoder handle *param[in] s32Eosflag : end flag *retval :: CVI_SUCCESS : Success *retval :: ERROR_CODE : FAILURE, return error_code. *see \n *N/A */ CVI_S32 AACDecoderSetEosFlag(CVIAACDecoder CVIAACDecoder, CVI_S32 s32Eosflag) { //TODO: return 0; } /** *brief flush internal codec state (after seeking, for example) *attention \n *param[in] CVIAACDecoder : AAC-Decoder handle *retval :: CVI_SUCCESS : Success *retval :: ERROR_CODE : FAILURE, return error_code. *see \n *N/A */ CVI_S32 AACFlushCodec(CVIAACDecoder CVIAACDecoder) { //TODO: return 0; }