545 files changed, 230976 insertions, 0 deletions
diff --git a/audio_codec/libfaad/helixaac/aacdec.c b/audio_codec/libfaad/helixaac/aacdec.c new file mode 100644 index 0000000..e8297a4 --- a/dev/null +++ b/audio_codec/libfaad/helixaac/aacdec.c @@ -0,0 +1,508 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Source last modified: $Id: aacdec.c,v 1.1 2005/02/26 01:47:31 jrecker Exp $ + * + * Portions Copyright (c) 1995-2005 RealNetworks, Inc. All Rights Reserved. + * + * The contents of this file, and the files included with this file, + * are subject to the current version of the RealNetworks Public + * Source License (the "RPSL") available at + * http://www.helixcommunity.org/content/rpsl unless you have licensed + * the file under the current version of the RealNetworks Community + * Source License (the "RCSL") available at + * http://www.helixcommunity.org/content/rcsl, in which case the RCSL + * will apply. You may also obtain the license terms directly from + * RealNetworks. You may not use this file except in compliance with + * the RPSL or, if you have a valid RCSL with RealNetworks applicable + * to this file, the RCSL. Please see the applicable RPSL or RCSL for + * the rights, obligations and limitations governing use of the + * contents of the file. + * + * This file is part of the Helix DNA Technology. RealNetworks is the + * developer of the Original Code and owns the copyrights in the + * portions it created. + * + * This file, and the files included with this file, is distributed + * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY + * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS + * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET + * ENJOYMENT OR NON-INFRINGEMENT. + * + * Technology Compatibility Kit Test Suite(s) Location: + * http://www.helixcommunity.org/content/tck + * + * Contributor(s): + * + * ***** END LICENSE BLOCK ***** */ + +/************************************************************************************** + * Fixed-point HE-AAC decoder + * Jon Recker (jrecker@real.com), Ken Cooke (kenc@real.com) + * February 2005 + * + * aacdec.c - platform-independent top level decoder API + **************************************************************************************/ +#include "aaccommon.h" +#include "bitstream.h" +#include <stdio.h> +#include "aacdec.h" + +#define HELIX_MAX_DECODE_CH_NUM (6) + +/************************************************************************************** + * Function: AACInitDecoder + * + * Description: allocate memory for platform-specific data + * clear all the user-accessible fields + * initialize SBR decoder if enabled + * + * Inputs: none + * + * Outputs: none + * + * Return: handle to AAC decoder instance, 0 if malloc fails + **************************************************************************************/ +HAACDecoder AACInitDecoder(void) +{ + AACDecInfo *aacDecInfo; + + aacDecInfo = AllocateBuffers(); + if (!aacDecInfo) { + return 0; + } + +#ifdef AAC_ENABLE_SBR + if (InitSBR(aacDecInfo)) { + AACFreeDecoder(aacDecInfo); + return 0; + } +#endif + + return (HAACDecoder)aacDecInfo; +} + +/************************************************************************************** + * Function: AACFreeDecoder + * + * Description: free platform-specific data allocated by AACInitDecoder + * free SBR decoder if enabled + * + * Inputs: valid AAC decoder instance pointer (HAACDecoder) + * + * Outputs: none + * + * Return: none + **************************************************************************************/ +void AACFreeDecoder(HAACDecoder hAACDecoder) +{ + AACDecInfo *aacDecInfo = (AACDecInfo *)hAACDecoder; + + if (!aacDecInfo) { + return; + } + +#ifdef AAC_ENABLE_SBR + FreeSBR(aacDecInfo); +#endif + FreeBuffers(aacDecInfo); +} + +/************************************************************************************** + * Function: AACFindSyncWord + * + * Description: locate the next byte-alinged sync word in the raw AAC stream + * + * Inputs: buffer to search for sync word + * max number of bytes to search in buffer + * + * Outputs: none + * + * Return: offset to first sync word (bytes from start of buf) + * -1 if sync not found after searching nBytes + **************************************************************************************/ +int AACFindSyncWord(unsigned char *buf, int nBytes) +{ + int i; + + /* find byte-aligned syncword (12 bits = 0xFFF) */ + for (i = 0; i < nBytes - 1; i++) { + if ((buf[i + 0] & SYNCWORDH) == SYNCWORDH && (buf[i + 1] & SYNCWORDL) == SYNCWORDL) { + return i; + } + } + + return -1; +} + +/************************************************************************************** + * Function: AACGetLastFrameInfo + * + * Description: get info about last AAC frame decoded (number of samples decoded, + * sample rate, bit rate, etc.) + * + * Inputs: valid AAC decoder instance pointer (HAACDecoder) + * pointer to AACFrameInfo struct + * + * Outputs: filled-in AACFrameInfo struct + * + * Return: none + * + * Notes: call this right after calling AACDecode() + **************************************************************************************/ +void AACGetLastFrameInfo(HAACDecoder hAACDecoder, AACFrameInfo *aacFrameInfo) +{ + AACDecInfo *aacDecInfo = (AACDecInfo *)hAACDecoder; + + if (!aacDecInfo) { + aacFrameInfo->format = 0; + aacFrameInfo->bitRate = 0; + aacFrameInfo->nChans = 0; + aacFrameInfo->sampRateCore = 0; + aacFrameInfo->sampRateOut = 0; + aacFrameInfo->bitsPerSample = 0; + aacFrameInfo->outputSamps = 0; + aacFrameInfo->profile = 0; + aacFrameInfo->tnsUsed = 0; + aacFrameInfo->pnsUsed = 0; + } else { + aacFrameInfo->format = aacDecInfo->format; + aacFrameInfo->nChans = aacDecInfo->nChans; + aacFrameInfo->sampRateCore = aacDecInfo->sampRate; + aacFrameInfo->sampRateOut = aacDecInfo->sampRate * (aacDecInfo->sbrEnabled ? 2 : 1); + aacFrameInfo->bitsPerSample = 16; + aacFrameInfo->outputSamps = aacDecInfo->nChans * AAC_MAX_NSAMPS * (aacDecInfo->sbrEnabled ? 2 : 1); + aacFrameInfo->profile = aacDecInfo->profile; + aacFrameInfo->tnsUsed = aacDecInfo->tnsUsed; + aacFrameInfo->pnsUsed = aacDecInfo->pnsUsed; + } +} + +void AACGetDecoderInfo(HAACDecoder hAACDecoder, AACFrameInfo *aacFrameInfo) +{ + AACDecInfo *aacDecInfo = (AACDecInfo *)hAACDecoder; + + if (aacDecInfo) { + aacFrameInfo->format = aacDecInfo->format; + aacFrameInfo->nChans = aacDecInfo->nChans; + aacFrameInfo->sampRateCore = aacDecInfo->sampRate; + aacFrameInfo->sampRateOut = aacDecInfo->sampRate * (aacDecInfo->sbrEnabled ? 2 : 1); + aacFrameInfo->bitsPerSample = 16; + aacFrameInfo->outputSamps = aacDecInfo->nChans * AAC_MAX_NSAMPS * (aacDecInfo->sbrEnabled ? 2 : 1); + aacFrameInfo->profile = aacDecInfo->profile; + aacFrameInfo->tnsUsed = aacDecInfo->tnsUsed; + aacFrameInfo->pnsUsed = aacDecInfo->pnsUsed; + aacFrameInfo->total_byte_parsed = aacDecInfo->byteParsed; + aacFrameInfo->total_sample_decoded = aacDecInfo->sampleDecoded; + + if (aacDecInfo->bitRate) { + aacFrameInfo->bitRate = aacDecInfo->bitRate; + } else if (aacDecInfo->sampleDecoded > 0) { + aacFrameInfo->bitRate = (int)(((float)(aacDecInfo->byteParsed)) / ((float)aacDecInfo->sampleDecoded / (float)aacFrameInfo->sampRateOut)) << 3; + } + } +} + +/************************************************************************************** + * Function: AACSetRawBlockParams + * + * Description: set internal state variables for decoding a stream of raw data blocks + * + * Inputs: valid AAC decoder instance pointer (HAACDecoder) + * flag indicating source of parameters + * AACFrameInfo struct, with the members nChans, sampRate, and profile + * optionally filled-in + * + * Outputs: updated codec state + * + * Return: 0 if successful, error code (< 0) if error + * + * Notes: if copyLast == 1, then the codec sets up its internal state (for + * decoding raw blocks) based on previously-decoded ADTS header info + * if copyLast == 0, then the codec uses the values passed in + * aacFrameInfo to configure its internal state (useful when the + * source is MP4 format, for example) + **************************************************************************************/ +int AACSetRawBlockParams(HAACDecoder hAACDecoder, int copyLast, AACFrameInfo *aacFrameInfo) +{ + AACDecInfo *aacDecInfo = (AACDecInfo *)hAACDecoder; + + if (!aacDecInfo) { + return ERR_AAC_NULL_POINTER; + } + + aacDecInfo->format = AAC_FF_RAW; + aacDecInfo->audio_send_by_frame = aacFrameInfo->audio_send_by_frame; + if (copyLast) { + return SetRawBlockParams(aacDecInfo, 1, 0, 0, 0); + } else { + return SetRawBlockParams(aacDecInfo, 0, aacFrameInfo->nChans, aacFrameInfo->sampRateCore, aacFrameInfo->profile); + } +} + +/************************************************************************************** + * Function: AACFlushCodec + * + * Description: flush internal codec state (after seeking, for example) + * + * Inputs: valid AAC decoder instance pointer (HAACDecoder) + * + * Outputs: updated state variables in aacDecInfo + * + * Return: 0 if successful, error code (< 0) if error + **************************************************************************************/ +int AACFlushCodec(HAACDecoder hAACDecoder) +{ + int ch; + AACDecInfo *aacDecInfo = (AACDecInfo *)hAACDecoder; + + if (!aacDecInfo) { + return ERR_AAC_NULL_POINTER; + } + /* reset common state variables which change per-frame + * don't touch state variables which are (usually) constant for entire clip + * (nChans, sampRate, profile, format, sbrEnabled) + */ + aacDecInfo->prevBlockID = AAC_ID_INVALID; + aacDecInfo->currBlockID = AAC_ID_INVALID; + aacDecInfo->currInstTag = -1; + for (ch = 0; ch < MAX_NCHANS_ELEM; ch++) { + aacDecInfo->sbDeinterleaveReqd[ch] = 0; + } + aacDecInfo->adtsBlocksLeft = 0; + aacDecInfo->tnsUsed = 0; + aacDecInfo->pnsUsed = 0; + + /* reset internal codec state (flush overlap buffers, etc.) */ + FlushCodec(aacDecInfo); +#ifdef AAC_ENABLE_SBR + FlushCodecSBR(aacDecInfo); +#endif + + return ERR_AAC_NONE; +} + +/************************************************************************************** + * Function: AACDecode + * + * Description: decode AAC frame + * + * Inputs: valid AAC decoder instance pointer (HAACDecoder) + * double pointer to buffer of AAC data + * pointer to number of valid bytes remaining in inbuf + * pointer to outbuf, big enough to hold one frame of decoded PCM samples + * (outbuf must be double-sized if SBR enabled) + * + * Outputs: PCM data in outbuf, interleaved LRLRLR... if stereo + * number of output samples = 1024 per channel (2048 if SBR enabled) + * updated inbuf pointer + * updated bytesLeft + * + * Return: 0 if successful, error code (< 0) if error + * + * Notes: inbuf pointer and bytesLeft are not updated until whole frame is + * successfully decoded, so if ERR_AAC_INDATA_UNDERFLOW is returned + * just call AACDecode again with more data in inbuf + **************************************************************************************/ +int AACDecode(HAACDecoder hAACDecoder, unsigned char **inbuf, int *bytesLeft, short *outbuf) +{ + int err, offset, bitOffset, bitsAvail; + int ch, baseChan, baseChanSBR, elementChans; + unsigned char *inptr; + AACDecInfo *aacDecInfo = (AACDecInfo *)hAACDecoder; +#ifdef AAC_ENABLE_SBR + int elementChansSBR; +#endif + + if (!aacDecInfo) { + return ERR_AAC_NULL_POINTER; + } + + /* make local copies (see "Notes" above) */ + inptr = *inbuf; + bitOffset = 0; + bitsAvail = (*bytesLeft) << 3; + + /* first time through figure out what the file format is */ + if (aacDecInfo->format == AAC_FF_Unknown) { + if (bitsAvail < 32) { + return ERR_AAC_INDATA_UNDERFLOW; + } + + if (IS_ADIF(inptr)) { + /* unpack ADIF header */ + aacDecInfo->format = AAC_FF_ADIF; + //printk("ADIF_DBG:ready step into UnpackADIFHeader()!\n"); + err = UnpackADIFHeader(aacDecInfo, &inptr, &bitOffset, &bitsAvail); + if (err) { + return err; + } + } else { + /* assume ADTS by default */ + aacDecInfo->format = AAC_FF_ADTS; + } + } + //printk("ADIF_DBG:aacDecInfo->format1=%d\n",aacDecInfo->format); + + /* if ADTS, search for start of next frame */ + if (aacDecInfo->format == AAC_FF_ADTS) { + /* can have 1-4 raw data blocks per ADTS frame (header only present for first one) */ + if (/*aacDecInfo->adtsBlocksLeft == 0*/1) { + offset = AACFindSyncWord(inptr, bitsAvail >> 3); + if (AACDataSource == 1) { + if (offset < 0) { //not find sync word in current buffer + return ERR_AAC_INVALID_ADTS_SYNCWORD; //ERR_AAC_INDATA_UNDERFLOW; + } + inptr += offset; + bitsAvail -= (offset << 3); + } + err = UnpackADTSHeader(aacDecInfo, &inptr, &bitOffset, &bitsAvail); + if (err) { + return err; + } + + if (aacDecInfo->nChans == -1) { + /* figure out implicit channel mapping if necessary */ + err = GetADTSChannelMapping(aacDecInfo, inptr, bitOffset, bitsAvail); + if (err) { + return err; + } + } + } + aacDecInfo->adtsBlocksLeft--; + } else if (aacDecInfo->format == AAC_FF_RAW) { + err = PrepareRawBlock(aacDecInfo); + if (err) { + return err; + } + } + + //printk("ADIF_DBG:aacDecInfo->nChans=%d aacDecInfo->sampRate=%d\n",aacDecInfo->nChans,aacDecInfo->sampRate); + /* check for valid number of channels */ + if (aacDecInfo->nChans > AAC_MAX_NCHANS || aacDecInfo->nChans <= 0) { + printk("AAC ERR: ERR_AAC_NCHANS_TOO_HIGH\n"); + return ERR_AAC_NCHANS_TOO_HIGH; + } + + /* will be set later if active in this frame */ + aacDecInfo->tnsUsed = 0; + aacDecInfo->pnsUsed = 0; + + bitOffset = 0; + baseChan = 0; + baseChanSBR = 0; + do { + /* parse next syntactic element */ + err = DecodeNextElement(aacDecInfo, &inptr, &bitOffset, &bitsAvail); + if (err) { + return err; + } + + elementChans = elementNumChans[aacDecInfo->currBlockID]; + if (baseChan + elementChans > AAC_MAX_NCHANS) { + return ERR_AAC_NCHANS_TOO_HIGH; + } + + /* noiseless decoder and dequantizer */ + for (ch = 0; ch < elementChans; ch++) { + err = DecodeNoiselessData(aacDecInfo, &inptr, &bitOffset, &bitsAvail, ch); + if (err) { + return err; + } + + if (Dequantize(aacDecInfo, ch)) { + return ERR_AAC_DEQUANT; + } + } + + /* mid-side and intensity stereo */ + if (aacDecInfo->currBlockID == AAC_ID_CPE) { + if (StereoProcess(aacDecInfo)) { + return ERR_AAC_STEREO_PROCESS; + } + } + + /* PNS, TNS, inverse transform */ + for (ch = 0; ch < elementChans; ch++) { + if (PNS(aacDecInfo, ch)) { + return ERR_AAC_PNS; + } + + if (aacDecInfo->sbDeinterleaveReqd[ch]) { + /* deinterleave short blocks, if required */ + if (DeinterleaveShortBlocks(aacDecInfo, ch)) { + return ERR_AAC_SHORT_BLOCK_DEINT; + } + aacDecInfo->sbDeinterleaveReqd[ch] = 0; + } + + if (TNSFilter(aacDecInfo, ch)) { + return ERR_AAC_TNS; + } + + if (IMDCT(aacDecInfo, ch, baseChan + ch, outbuf)) { + return ERR_AAC_IMDCT; + } + } + +#ifdef AAC_ENABLE_SBR + if (aacDecInfo->sbrEnabled && (aacDecInfo->currBlockID == AAC_ID_FIL || aacDecInfo->currBlockID == AAC_ID_LFE)) { + if (aacDecInfo->currBlockID == AAC_ID_LFE) { + elementChansSBR = elementNumChans[AAC_ID_LFE]; + } else if (aacDecInfo->currBlockID == AAC_ID_FIL && (aacDecInfo->prevBlockID == AAC_ID_SCE || aacDecInfo->prevBlockID == AAC_ID_CPE)) { + elementChansSBR = elementNumChans[aacDecInfo->prevBlockID]; + } else { + elementChansSBR = 0; + } + + if (baseChanSBR + elementChansSBR > AAC_MAX_NCHANS) { + return ERR_AAC_SBR_NCHANS_TOO_HIGH; + } + + /* parse SBR extension data if present (contained in a fill element) */ + if (DecodeSBRBitstream(aacDecInfo, baseChanSBR)) { + return ERR_AAC_SBR_BITSTREAM; + } + + /* apply SBR */ + if (DecodeSBRData(aacDecInfo, baseChanSBR, outbuf)) { + return ERR_AAC_SBR_DATA; + } + + baseChanSBR += elementChansSBR; + } +#endif + + baseChan += elementChans; + } while (aacDecInfo->currBlockID != AAC_ID_END); + + /* byte align after each raw_data_block */ + if (bitOffset) { + inptr++; + bitsAvail -= (8 - bitOffset); + bitOffset = 0; + if (bitsAvail < 0) { + return ERR_AAC_INDATA_UNDERFLOW; + } + } + + /* update pointers */ + if (AACDataSource == 1) { + aacDecInfo->frameCount++; + aacDecInfo->byteParsed += inptr - *inbuf; + //printk(" decode one frame cost byte %d \n",inptr - *inbuf); + aacDecInfo->sampleDecoded += AAC_MAX_NSAMPS * (aacDecInfo->sbrEnabled ? 2 : 1); + *bytesLeft -= (inptr - *inbuf); + *inbuf = inptr; + } else { + aacDecInfo->frameCount++; + aacDecInfo->byteParsed = CalcBitsUsed(0, 0, 0) >> 3; + aacDecInfo->sampleDecoded += AAC_MAX_NSAMPS * (aacDecInfo->sbrEnabled ? 2 : 1); + *bytesLeft -= (CalcBitsUsed(0, 0, 0) >> 3); + // *inbuf = *inbuf+; + } + + + + return ERR_AAC_NONE; +} + |