| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476 | /* ***** 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 "profile.h"#define PROFILE_START(x)#define PROFILE_END()/************************************************************************************** * 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;}HAACDecoder AACInitDecoderPre(void *ptr, int sz){        AACDecInfo *aacDecInfo;        aacDecInfo = AllocateBuffersPre(&ptr, &sz);        if (!aacDecInfo)                return 0;#ifdef AAC_ENABLE_SBR        if (InitSBRPre(aacDecInfo, &ptr, &sz)) {                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->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->bitRate =       aacDecInfo->bitRate;		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;	}}/************************************************************************************** * 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;	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, elementChans;	unsigned char *inptr;	AACDecInfo *aacDecInfo = (AACDecInfo *)hAACDecoder;#ifdef AAC_ENABLE_SBR	int baseChanSBR, 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;			err = UnpackADIFHeader(aacDecInfo, &inptr, &bitOffset, &bitsAvail);			if (err)				return err;		} else {			/* assume ADTS by default */			aacDecInfo->format = AAC_FF_ADTS;		}	} 			/* 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) {			offset = AACFindSyncWord(inptr, bitsAvail >> 3);			if (offset < 0)				return 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;	}	/* check for valid number of channels */	if (aacDecInfo->nChans > AAC_MAX_NCHANS || aacDecInfo->nChans <= 0)		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;#ifdef AAC_ENABLE_SBR		baseChanSBR = 0;#endif		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++) {      PROFILE_START("noiseless decoder");			err = DecodeNoiselessData(aacDecInfo, &inptr, &bitOffset, &bitsAvail, ch);      PROFILE_END();      						if (err)				return err;			PROFILE_START("dequant");			if (Dequantize(aacDecInfo, ch))				return ERR_AAC_DEQUANT;      PROFILE_END();		}    PROFILE_START("mid-side and intensity stereo");		/* mid-side and intensity stereo */		if (aacDecInfo->currBlockID == AAC_ID_CPE) {			if (StereoProcess(aacDecInfo))				return ERR_AAC_STEREO_PROCESS;		}    PROFILE_END();		/* PNS, TNS, inverse transform */		for (ch = 0; ch < elementChans; ch++) {      PROFILE_START("PNS");			if (PNS(aacDecInfo, ch))				return ERR_AAC_PNS;      PROFILE_END();			if (aacDecInfo->sbDeinterleaveReqd[ch]) {				/* deinterleave short blocks, if required */				if (DeinterleaveShortBlocks(aacDecInfo, ch))					return ERR_AAC_SHORT_BLOCK_DEINT;				aacDecInfo->sbDeinterleaveReqd[ch] = 0;			}      PROFILE_START("TNS");			if (TNSFilter(aacDecInfo, ch))				return ERR_AAC_TNS;      PROFILE_END();	      PROFILE_START("IMDCT");			if (IMDCT(aacDecInfo, ch, baseChan + ch, outbuf))				return ERR_AAC_IMDCT;      PROFILE_END();		}#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 */	aacDecInfo->frameCount++;	*bytesLeft -= (inptr - *inbuf);	*inbuf = inptr;	return ERR_AAC_NONE;}
 |