diff options
author | Dave Burke <daveburke@google.com> | 2012-04-17 09:51:45 -0700 |
---|---|---|
committer | Dave Burke <daveburke@google.com> | 2012-04-17 23:04:43 -0700 |
commit | 9bf37cc9712506b2483650c82d3c41152337ef7e (patch) | |
tree | 77db44e2bae06e3d144b255628be2b7a55c581d3 /libAACdec/src/aacdecoder.cpp | |
parent | a37315fe10ee143d6d0b28c19d41a476a23e63ea (diff) | |
download | fdk-aac-9bf37cc9712506b2483650c82d3c41152337ef7e.tar.gz fdk-aac-9bf37cc9712506b2483650c82d3c41152337ef7e.tar.bz2 fdk-aac-9bf37cc9712506b2483650c82d3c41152337ef7e.zip |
Fraunhofer AAC codec.
License boilerplate update to follow.
Change-Id: I2810460c11a58b6d148d84673cc031f3685e79b5
Diffstat (limited to 'libAACdec/src/aacdecoder.cpp')
-rw-r--r-- | libAACdec/src/aacdecoder.cpp | 1667 |
1 files changed, 1667 insertions, 0 deletions
diff --git a/libAACdec/src/aacdecoder.cpp b/libAACdec/src/aacdecoder.cpp new file mode 100644 index 0000000..534d48f --- /dev/null +++ b/libAACdec/src/aacdecoder.cpp @@ -0,0 +1,1667 @@ +/***************************** MPEG-4 AAC Decoder ************************** + + (C) Copyright Fraunhofer IIS (2004) + All Rights Reserved + + Please be advised that this software and/or program delivery is + Confidential Information of Fraunhofer and subject to and covered by the + + Fraunhofer IIS Software Evaluation Agreement + between Google Inc. and Fraunhofer + effective and in full force since March 1, 2012. + + You may use this software and/or program only under the terms and + conditions described in the above mentioned Fraunhofer IIS Software + Evaluation Agreement. Any other and/or further use requires a separate agreement. + + + $Id$ + Author(s): Josef Hoepfl + Description: + + This software and/or program is protected by copyright law and international + treaties. Any reproduction or distribution of this software and/or program, + or any portion of it, may result in severe civil and criminal penalties, and + will be prosecuted to the maximum extent possible under law. + +******************************************************************************/ + + +/*! + \page default General Overview of the AAC Decoder Implementation + + The main entry point to decode a AAC frame is CAacDecoder_DecodeFrame(). It handles the different + transport multiplexes and bitstream formats supported by this implementation. It extracts the + AAC_raw_data_blocks from these bitstreams to further process then in the actual decoding stages. + + Note: Click on a function of file in the above image to see details about the function. Also note, that + this is just an overview of the most important functions and not a complete call graph. + + <h2>1 Bitstream deformatter</h2> + The basic bit stream parser function CChannelElement_Read() is called. It uses other subcalls in order + to parse and unpack the bitstreams. Note, that this includes huffmann decoding of the coded spectral data. + This operation can be computational significant specifically at higher bitrates. Optimization is likely in + CBlock_ReadSpectralData(). + + The bitstream deformatter also includes many bitfield operations. Profiling on the target will determine + required optimizations. + + <h2>2 Actual decoding to retain the time domain output</h2> + The basic bitstream deformatter function CChannelElement_Decode() for CPE elements and SCE elements are called. + Except for the stereo processing (2.1) which is only used for CPE elements, the function calls for CPE or SCE + are similar, except that CPE always processes to independent channels while SCE only processes one channel. + + Often there is the distinction between long blocks and short blocks. However, computational expensive functions + that ususally require optimization are being shared by these two groups, + + <h3>2.1 Stereo processing for CPE elements</h3> + CChannelPairElement_Decode() first calles the joint stereo tools in stereo.cpp when required. + + <h3>2.2 Scaling of spectral data</h3> + CBlock_ScaleSpectralData(). + + <h3>2.3 Apply additional coding tools</h3> + ApplyTools() calles the PNS tools in case of MPEG-4 bitstreams, and TNS filtering CTns_Apply() for MPEG-2 and MPEG-4 bitstreams. + The function TnsFilterIIR() which is called by CTns_Apply() (2.3.1) might require some optimization. + + <h2>3 Frequency-To-Time conversion</h3> + The filterbank is called using CBlock_FrequencyToTime() using the MDCT module from the FDK Tools + +*/ + + + +#include "aacdecoder.h" + +#include "aac_rom.h" +#include "aac_ram.h" +#include "channel.h" +#include "FDK_audio.h" + +#include "FDK_tools_rom.h" + + #include "aacdec_pns.h" + +/*#ifdef AACDEC_HDAAC_ENABLE +#include "slsdecifc.h" +#endif +*/ + + #include "sbrdecoder.h" + + + + + #include "aacdec_hcr.h" + #include "rvlc.h" + + +#include "tpdec_lib.h" + +#include "conceal.h" + + + +#define CAN_DO_PS(aot) \ + ((aot) == AOT_AAC_LC \ +|| (aot) == AOT_SBR \ +|| (aot) == AOT_PS \ +|| (aot) == AOT_ER_BSAC \ +|| (aot) == AOT_DRM_AAC) + +#define IS_USAC(aot) \ + ((aot) == AOT_USAC \ +|| (aot) == AOT_RSVD50) + +#define IS_LOWDELAY(aot) \ + ((aot) == AOT_ER_AAC_LD \ +|| (aot) == AOT_ER_AAC_ELD) + +void CAacDecoder_SyncQmfMode(HANDLE_AACDECODER self) +{ + + /* Assign user requested mode */ + self->qmfModeCurr = self->qmfModeUser; + + if ( self->qmfModeCurr == NOT_DEFINED ) + { + if ( (IS_LOWDELAY(self->streamInfo.aot) && (self->flags & AC_MPS_PRESENT)) + || ( (self->ascChannels == 1) + && ( (CAN_DO_PS(self->streamInfo.aot) && !(self->flags & AC_MPS_PRESENT)) + || ( IS_USAC(self->streamInfo.aot) && (self->flags & AC_MPS_PRESENT)) ) ) ) + { + self->qmfModeCurr = MODE_HQ; + } else { + self->qmfModeCurr = MODE_LP; + } + } + + + /* Set SBR to current QMF mode. Error does not matter. */ + sbrDecoder_SetParam(self->hSbrDecoder, SBR_QMF_MODE, (self->qmfModeCurr == MODE_LP)); + self->psPossible = ((CAN_DO_PS(self->streamInfo.aot) && self->aacChannels == 1 && ! (self->flags & AC_MPS_PRESENT))) && self->qmfModeCurr == MODE_HQ ; + FDK_ASSERT( ! ( (self->flags & AC_MPS_PRESENT) && self->psPossible ) ); +} + +void CAacDecoder_SignalInterruption(HANDLE_AACDECODER self) +{ +} + +/*! + \brief Reset ancillary data struct. Call before parsing a new frame. + + \ancData Pointer to ancillary data structure + + \return Error code +*/ +static AAC_DECODER_ERROR CAacDecoder_AncDataReset(CAncData *ancData) +{ + int i; + for (i=0; i<8; i++) + { + ancData->offset[i] = 0; + } + ancData->nrElements = 0; + + return AAC_DEC_OK; +} + +/*! + \brief Initialize ancillary buffer + + \ancData Pointer to ancillary data structure + \buffer Pointer to (external) anc data buffer + \size Size of the buffer pointed on by buffer in bytes + + \return Error code +*/ +AAC_DECODER_ERROR CAacDecoder_AncDataInit(CAncData *ancData, unsigned char *buffer, int size) +{ + if (size >= 0) { + ancData->buffer = buffer; + ancData->bufferSize = size; + + CAacDecoder_AncDataReset(ancData); + + return AAC_DEC_OK; + } + + return AAC_DEC_ANC_DATA_ERROR; +} + +/*! + \brief Get one ancillary data element + + \ancData Pointer to ancillary data structure + \index Index of the anc data element to get + \ptr Pointer to a buffer receiving a pointer to the requested anc data element + \size Pointer to a buffer receiving the length of the requested anc data element in bytes + + \return Error code +*/ +AAC_DECODER_ERROR CAacDecoder_AncDataGet(CAncData *ancData, int index, unsigned char **ptr, int *size) +{ + AAC_DECODER_ERROR error = AAC_DEC_OK; + + *ptr = NULL; + *size = 0; + + if (index >= 0 && index < 8 && index < ancData->nrElements) + { + *ptr = &ancData->buffer[ancData->offset[index]]; + *size = ancData->offset[index+1] - ancData->offset[index]; + } + + return error; +} + + +/*! + \brief Parse ancillary data + + \ancData Pointer to ancillary data structure + \hBs Handle to FDK bitstream + \ancBytes Length of ancillary data to read from the bitstream + + \return Error code +*/ +static +AAC_DECODER_ERROR CAacDecoder_AncDataParse ( + CAncData *ancData, + HANDLE_FDK_BITSTREAM hBs, + const int ancBytes ) +{ + AAC_DECODER_ERROR error = AAC_DEC_OK; + int readBytes = 0; + + if (ancData->buffer != NULL) + { + if (ancBytes > 0) { + /* write ancillary data to external buffer */ + int offset = ancData->offset[ancData->nrElements]; + + if ((offset + ancBytes) > ancData->bufferSize) + { + error = AAC_DEC_TOO_SMALL_ANC_BUFFER; + } + else if (ancData->nrElements >= 8-1) + { + error = AAC_DEC_TOO_MANY_ANC_ELEMENTS; + } + else + { + int i; + + for (i = 0; i < ancBytes; i++) { + ancData->buffer[i+offset] = FDKreadBits(hBs, 8); + readBytes++; + } + + ancData->nrElements++; + ancData->offset[ancData->nrElements] = ancBytes + ancData->offset[ancData->nrElements-1]; + } + } + } + + readBytes = ancBytes - readBytes; + + if (readBytes > 0) { + /* skip data */ + FDKpushFor(hBs, readBytes<<3); + } + + return error; +} + +/*! + \brief Read Stream Data Element + + \bs Bitstream Handle + + \return Error code +*/ +static AAC_DECODER_ERROR CDataStreamElement_Read ( + HANDLE_FDK_BITSTREAM bs, + CAncData *ancData, + HANDLE_AAC_DRC hDrcInfo, + HANDLE_TRANSPORTDEC pTp, + UCHAR *elementInstanceTag, + UINT alignmentAnchor ) +{ + AAC_DECODER_ERROR error = AAC_DEC_OK; + UINT dataStart; + int dataByteAlignFlag, count; + + int crcReg = transportDec_CrcStartReg(pTp, 0); + + /* Element Instance Tag */ + *elementInstanceTag = FDKreadBits(bs,4); + /* Data Byte Align Flag */ + dataByteAlignFlag = FDKreadBits(bs,1); + + count = FDKreadBits(bs,8); + + if (count == 255) { + count += FDKreadBits(bs,8); /* EscCount */ + } + + if (dataByteAlignFlag) { + FDKbyteAlign(bs, alignmentAnchor); + } + + dataStart = FDKgetValidBits(bs); + + error = CAacDecoder_AncDataParse(ancData, bs, count); + transportDec_CrcEndReg(pTp, crcReg); + + { + INT readBits, dataBits = count<<3; + + /* Move to the beginning of the data junk */ + FDKpushBack(bs, dataStart-FDKgetValidBits(bs)); + + /* Read Anc data if available */ + readBits = aacDecoder_drcMarkPayload( hDrcInfo, bs, DVB_DRC_ANC_DATA ); + + if (readBits != dataBits) { + /* Move to the end again. */ + FDKpushBiDirectional(bs, FDKgetValidBits(bs)-dataStart+dataBits); + } + } + + return error; +} + +#ifdef TP_PCE_ENABLE +/*! + \brief Read Program Config Element + + \bs Bitstream Handle + \count Pointer to program config element. + + \return Error code +*/ +static AAC_DECODER_ERROR CProgramConfigElement_Read ( + HANDLE_FDK_BITSTREAM bs, + HANDLE_TRANSPORTDEC pTp, + CProgramConfig *pce, + UINT alignAnchor ) +{ + AAC_DECODER_ERROR error = AAC_DEC_OK; + int crcReg; + + /* read PCE to temporal buffer first */ + C_ALLOC_SCRATCH_START(tmpPce, CProgramConfig, 1); + + CProgramConfig_Init(tmpPce); + CProgramConfig_Reset(tmpPce); + + crcReg = transportDec_CrcStartReg(pTp, 0); + + CProgramConfig_Read(tmpPce, bs, alignAnchor); + + transportDec_CrcEndReg(pTp, crcReg); + + if (!pce->isValid && tmpPce->NumChannels <= (6) && tmpPce->Profile == 1) { + /* store PCE data */ + FDKmemcpy(pce, tmpPce, sizeof(CProgramConfig)); + } + + C_ALLOC_SCRATCH_END(tmpPce, CProgramConfig, 1); + + return error; +} +#endif + +/*! + \brief Parse Extension Payload + + \self Handle of AAC decoder + \count Pointer to bit counter. + \previous_element ID of previous element (required by some extension payloads) + + \return Error code +*/ +static +AAC_DECODER_ERROR CAacDecoder_ExtPayloadParse (HANDLE_AACDECODER self, + HANDLE_FDK_BITSTREAM hBs, + int *count, + MP4_ELEMENT_ID previous_element, + int elIndex, + int fIsFillElement) +{ + AAC_DECODER_ERROR error = AAC_DEC_OK; + EXT_PAYLOAD_TYPE extension_type; + int bytes = (*count) >> 3; + int crcFlag = 0; + + if (*count < 4) { + return AAC_DEC_PARSE_ERROR; + } else if ((INT)FDKgetValidBits(hBs) < *count) { + return AAC_DEC_DECODE_FRAME_ERROR; + } + + extension_type = (EXT_PAYLOAD_TYPE) FDKreadBits(hBs, 4); /* bs_extension_type */ + *count -= 4; + + switch (extension_type) + { + case EXT_DYNAMIC_RANGE: + { + INT readBits = aacDecoder_drcMarkPayload( self->hDrcInfo, hBs, MPEG_DRC_EXT_DATA ); + + if (readBits > *count) + { + FDKpushBack(hBs, readBits - *count); + error = AAC_DEC_PARSE_ERROR; + return error; + } + else + { + *count -= (readBits+7) & ~0x7; + } + } + break; + case EXT_LDSAC_DATA: + case EXT_SAC_DATA: + /* Skip MPEG Surround Extension payload */ + FDKpushFor(hBs, *count); + *count = 0; + break; + + case EXT_SBR_DATA_CRC: + crcFlag = 1; + + case EXT_SBR_DATA: + { + SBR_ERROR sbrError; + + CAacDecoder_SyncQmfMode(self); + + sbrError = sbrDecoder_InitElement( + self->hSbrDecoder, + self->streamInfo.aacSampleRate, + self->streamInfo.extSamplingRate, + self->streamInfo.aacSamplesPerFrame, + self->streamInfo.aot, + previous_element, + elIndex + ); + + if (sbrError == SBRDEC_OK) { + sbrError = sbrDecoder_Parse ( + self->hSbrDecoder, + hBs, + count, + *count, + crcFlag, + previous_element, + elIndex, + self->flags & AC_INDEP ); + /* Enable SBR for implicit SBR signalling. */ + if (sbrError == SBRDEC_OK) { + self->sbrEnabled = 1; + } + } else { + /* Do not try to apply SBR because initializing the element failed. */ + self->sbrEnabled = 0; + } + /* Citation from ISO/IEC 14496-3 chapter 4.5.2.1.5.2 + Fill elements containing an extension_payload() with an extension_type of EXT_SBR_DATA + or EXT_SBR_DATA_CRC shall not contain any other extension_payload of any other extension_type. + */ + if (fIsFillElement) { + FDKpushBiDirectional(hBs, *count); + *count = 0; + } else { + /* If this is not a fill element with a known length, we are screwed an no further parsing makes sense. */ + if (sbrError != SBRDEC_OK) { + self->frameOK = 0; + } + } + } + break; + + case EXT_FILL_DATA: + { + int temp; + + temp = FDKreadBits(hBs,4); + bytes--; + if (temp != 0) { + error = AAC_DEC_PARSE_ERROR; + break; + } + while (bytes > 0) { + temp = FDKreadBits(hBs,8); + bytes--; + if (temp != 0xa5) { + error = AAC_DEC_PARSE_ERROR; + break; + } + } + *count = bytes<<3; + } + break; + + case EXT_DATA_ELEMENT: + { + int dataElementVersion; + + dataElementVersion = FDKreadBits(hBs,4); + *count -= 4; + if (dataElementVersion == 0) /* ANC_DATA */ + { + int temp, dataElementLength = 0; + do { + temp = FDKreadBits(hBs,8); + *count -= 8; + dataElementLength += temp; + } while (temp == 255 ); + + CAacDecoder_AncDataParse(&self->ancData, hBs, dataElementLength); + *count -= (dataElementLength<<3); + } else { + /* align = 0 */ + FDKpushFor(hBs, (*count)<<3); + *count = 0; + } + } + break; + + case EXT_DATA_LENGTH: + { + int bitCnt, len = FDKreadBits(hBs, 4); + *count -= 4; + + if (len == 15) { + int add_len = FDKreadBits(hBs, 8); + *count -= 8; + len += add_len; + + if (add_len == 255) { + len += FDKreadBits(hBs, 16); + *count -= 16; + } + } + len <<= 3; + bitCnt = len; + + if ( (EXT_PAYLOAD_TYPE)FDKreadBits(hBs, 4) == EXT_DATA_LENGTH ) { + /* Check NOTE 2: The extension_payload() included here must + not have extension_type == EXT_DATA_LENGTH. */ + error = AAC_DEC_PARSE_ERROR; + } else { + /* rewind and call myself again. */ + FDKpushBack(hBs, 4); + + error = + CAacDecoder_ExtPayloadParse ( + self, + hBs, + &bitCnt, + previous_element, + elIndex, + 0 ); + + *count -= len - bitCnt; + } + } + break; + + case EXT_FIL: + + default: + /* align = 4 */ + FDKpushFor(hBs, *count); + *count = 0; + break; + } + + return error; +} + +/* Stream Configuration and Information. + + This class holds configuration and information data for a stream to be decoded. It + provides the calling application as well as the decoder with substantial information, + e.g. profile, sampling rate, number of channels found in the bitstream etc. +*/ +static +void CStreamInfoInit(CStreamInfo *pStreamInfo) +{ + pStreamInfo->aacSampleRate = 0; + pStreamInfo->profile = -1; + pStreamInfo->aot = AOT_NONE; + + pStreamInfo->channelConfig = -1; + pStreamInfo->bitRate = 0; + pStreamInfo->aacSamplesPerFrame = 0; + + pStreamInfo->extAot = AOT_NONE; + pStreamInfo->extSamplingRate = 0; + + pStreamInfo->flags = 0; + + pStreamInfo->epConfig = -1; /* default is no ER */ + + pStreamInfo->numChannels = 0; + pStreamInfo->sampleRate = 0; + pStreamInfo->frameSize = 0; +} + +/*! + \brief Initialization of AacDecoderChannelInfo + + The function initializes the pointers to AacDecoderChannelInfo for each channel, + set the start values for window shape and window sequence of overlap&add to zero, + set the overlap buffer to zero and initializes the pointers to the window coefficients. + \param bsFormat is the format of the AAC bitstream + + \return AACDECODER instance +*/ +LINKSPEC_CPP HANDLE_AACDECODER CAacDecoder_Open(TRANSPORT_TYPE bsFormat) /*!< bitstream format (adif,adts,loas,...). */ +{ + HANDLE_AACDECODER self; + + self = GetAacDecoder(); + if (self == NULL) { + goto bail; + } + + /* Assign channel mapping info arrays (doing so removes dependency of settings header in API header). */ + self->streamInfo.pChannelIndices = self->channelIndices; + self->streamInfo.pChannelType = self->channelType; + + /* set default output mode */ + self->outputInterleaved = 1; /* interleaved */ + + /* initialize anc data */ + CAacDecoder_AncDataInit(&self->ancData, NULL, 0); + + /* initialize stream info */ + CStreamInfoInit(&self->streamInfo); + + /* initialize error concealment common data */ + CConcealment_InitCommonData(&self->concealCommonData); + + self->hDrcInfo = GetDrcInfo(); + if (self->hDrcInfo == NULL) { + goto bail; + } + /* Init common DRC structure */ + aacDecoder_drcInit( self->hDrcInfo ); + /* Set default frame delay */ + aacDecoder_drcSetParam ( + self->hDrcInfo, + DRC_BS_DELAY, + CConcealment_GetDelay(&self->concealCommonData) + ); + + + self->aacCommonData.workBufferCore1 = GetWorkBufferCore1(); + self->aacCommonData.workBufferCore2 = GetWorkBufferCore2(); + if (self->aacCommonData.workBufferCore1 == NULL + ||self->aacCommonData.workBufferCore2 == NULL ) + goto bail; + + return self; + +bail: + CAacDecoder_Close( self ); + + return NULL; +} + +/* Destroy aac decoder */ +LINKSPEC_CPP void CAacDecoder_Close(HANDLE_AACDECODER self) +{ + int ch; + + if (self == NULL) + return; + + for (ch=0; ch<(6); ch++) { + if (self->pAacDecoderStaticChannelInfo[ch] != NULL) { + FreeOverlapBuffer (&self->pAacDecoderStaticChannelInfo[ch]->pOverlapBuffer); + FreeAacDecoderStaticChannelInfo (&self->pAacDecoderStaticChannelInfo[ch]); + } + if (self->pAacDecoderChannelInfo[ch] != NULL) { + FreeAacDecoderChannelInfo (&self->pAacDecoderChannelInfo[ch]); + } + } + + self->aacChannels = 0; + + if (self->hDrcInfo) { + FreeDrcInfo(&self->hDrcInfo); + } + + FreeWorkBufferCore1 (&self->aacCommonData.workBufferCore1); + FreeWorkBufferCore2 (&self->aacCommonData.workBufferCore2); + + FreeAacDecoder ( &self); +} + + +/*! + \brief Initialization of decoder instance + + The function initializes the decoder. + + \return error status: 0 for success, <>0 for unsupported configurations +*/ +LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_Init(HANDLE_AACDECODER self, const CSAudioSpecificConfig *asc) +{ + AAC_DECODER_ERROR err = AAC_DEC_OK; + INT ascChannels, ch, ascChanged = 0; + + if (!self) + return AAC_DEC_INVALID_HANDLE; + + // set profile and check for supported aot + // leave profile on default (=-1) for all other supported MPEG-4 aot's except aot=2 (=AAC-LC) + switch (asc->m_aot) { + case AOT_AAC_LC: + self->streamInfo.profile = 1; + break; + + case AOT_SBR: + case AOT_PS: + case AOT_ER_AAC_LD: + case AOT_ER_AAC_ELD: + break; + + default: + return AAC_DEC_UNSUPPORTED_AOT; + } + + CProgramConfig_Init(&self->pce); + + /* set channels */ + switch (asc->m_channelConfiguration) { + case 0: +#ifdef TP_PCE_ENABLE + /* get channels from program config (ASC) */ + if (CProgramConfig_IsValid(&asc->m_progrConfigElement)) { + ascChannels = asc->m_progrConfigElement.NumChannels; + if (ascChannels > 0) { + int el; + /* valid number of channels -> copy program config element (PCE) from ASC */ + FDKmemcpy(&self->pce, &asc->m_progrConfigElement, sizeof(CProgramConfig)); + /* Built element table */ + el = CProgramConfig_GetElementTable(&asc->m_progrConfigElement, self->elements); + for (; el<7; el++) { + self->elements[el] = ID_NONE; + } + } else { + return AAC_DEC_UNSUPPORTED_CHANNELCONFIG; + } + } else { + if (transportDec_GetFormat(self->hInput) == TT_MP4_ADTS) { + /* set default max_channels for memory allocation because in implicit channel mapping mode + we don't know the actual number of channels until we processed at least one raw_data_block(). */ + ascChannels = (6); + } else { + return AAC_DEC_UNSUPPORTED_CHANNELCONFIG; + } + } +#else /* TP_PCE_ENABLE */ + return AAC_DEC_UNSUPPORTED_CHANNELCONFIG; +#endif /* TP_PCE_ENABLE */ + break; + case 1: case 2: case 3: case 4: case 5: case 6: + ascChannels = asc->m_channelConfiguration; + break; + case 7: + ascChannels = 8; + break; + default: + return AAC_DEC_UNSUPPORTED_CHANNELCONFIG; + } + + /* Initialize constant mappings for channel config 1-7 */ + if (asc->m_channelConfiguration > 0) { + int el; + FDKmemcpy(self->elements, elementsTab[asc->m_channelConfiguration-1], sizeof(MP4_ELEMENT_ID)*FDKmin(7,7)); + for (el=7; el<7; el++) { + self->elements[el] = ID_NONE; + } + for (ch=0; ch<ascChannels; ch++) { + self->chMapping[ch] = ch; + } + for (; ch<(6); ch++) { + self->chMapping[ch] = 255; + } + } + + self->streamInfo.channelConfig = asc->m_channelConfiguration; + + if (ascChannels > (6)) { + return AAC_DEC_UNSUPPORTED_CHANNELCONFIG; + } + if (self->streamInfo.aot != asc->m_aot) { + self->streamInfo.aot = asc->m_aot; + ascChanged = 1; + } + + if (self->streamInfo.aacSamplesPerFrame != (INT)asc->m_samplesPerFrame) { + self->streamInfo.aacSamplesPerFrame = asc->m_samplesPerFrame; + ascChanged = 1; + } + + self->streamInfo.bitRate = 0; + + /* Set syntax flags */ + self->flags = 0; + + self->streamInfo.extAot = asc->m_extensionAudioObjectType; + self->streamInfo.extSamplingRate = asc->m_extensionSamplingFrequency; + self->flags |= (asc->m_sbrPresentFlag) ? AC_SBR_PRESENT : 0; + self->flags |= (asc->m_psPresentFlag) ? AC_PS_PRESENT : 0; + self->sbrEnabled = 0; + + /* --------- vcb11 ------------ */ + self->flags |= (asc->m_vcb11Flag) ? AC_ER_VCB11 : 0; + + /* ---------- rvlc ------------ */ + self->flags |= (asc->m_rvlcFlag) ? AC_ER_RVLC : 0; + + /* ----------- hcr ------------ */ + self->flags |= (asc->m_hcrFlag) ? AC_ER_HCR : 0; + + if (asc->m_aot == AOT_ER_AAC_ELD) { + self->flags |= AC_ELD; + self->flags |= (asc->m_sc.m_eldSpecificConfig.m_sbrCrcFlag) ? AC_SBRCRC : 0; + self->flags |= (asc->m_sc.m_eldSpecificConfig.m_useLdQmfTimeAlign) ? AC_LD_MPS : 0; + } + self->flags |= (asc->m_aot == AOT_ER_AAC_LD) ? AC_LD : 0; + self->flags |= (asc->m_epConfig >= 0) ? AC_ER : 0; + + + if (asc->m_sbrPresentFlag) { + self->sbrEnabled = 1; + self->sbrEnabledPrev = 1; + } + if (asc->m_psPresentFlag) { + self->flags |= AC_PS_PRESENT; + } + + if ( (asc->m_epConfig >= 0) + && (asc->m_channelConfiguration <= 0) ) { + /* we have to know the number of channels otherwise no decoding is possible */ + return AAC_DEC_UNSUPPORTED_ER_FORMAT; + } + + self->streamInfo.epConfig = asc->m_epConfig; + /* self->hInput->asc.m_epConfig = asc->m_epConfig; */ + + if (asc->m_epConfig > 1) + return AAC_DEC_UNSUPPORTED_ER_FORMAT; + + /* Check if samplerate changed. */ + if (self->streamInfo.aacSampleRate != (INT)asc->m_samplingFrequency) { + AAC_DECODER_ERROR error; + + ascChanged = 1; + + /* Update samplerate info. */ + error = getSamplingRateInfo(&self->samplingRateInfo, asc->m_samplesPerFrame, asc->m_samplingFrequencyIndex, asc->m_samplingFrequency); + if (error != AAC_DEC_OK) { + return error; + } + self->streamInfo.aacSampleRate = self->samplingRateInfo.samplingRate; + } + + /* Check if amount of channels has changed. */ + if (self->ascChannels != ascChannels) + { + ascChanged = 1; + + /* Allocate all memory structures for each channel */ + { + for (ch = 0; ch < ascChannels; ch++) { + CAacDecoderDynamicData *aacDecoderDynamicData = &self->aacCommonData.workBufferCore1->pAacDecoderDynamicData[ch%2]; + + /* initialize pointer to CAacDecoderChannelInfo */ + if (self->pAacDecoderChannelInfo[ch] == NULL) { + self->pAacDecoderChannelInfo[ch] = GetAacDecoderChannelInfo(ch); + /* This is temporary until the DynamicData is split into two or more regions! + The memory could be reused after completed core decoding. */ + if (self->pAacDecoderChannelInfo[ch] == NULL) { + goto bail; + } + /* Hook shared work memory into channel data structure */ + self->pAacDecoderChannelInfo[ch]->pDynData = aacDecoderDynamicData; + self->pAacDecoderChannelInfo[ch]->pComData = &self->aacCommonData; + } + + /* Allocate persistent channel memory */ + if (self->pAacDecoderStaticChannelInfo[ch] == NULL) { + self->pAacDecoderStaticChannelInfo[ch] = GetAacDecoderStaticChannelInfo(ch); + if (self->pAacDecoderStaticChannelInfo[ch] == NULL) { + goto bail; + } + self->pAacDecoderStaticChannelInfo[ch]->pOverlapBuffer = GetOverlapBuffer(ch); /* This area size depends on the AOT */ + if (self->pAacDecoderStaticChannelInfo[ch]->pOverlapBuffer == NULL) { + goto bail; + } + self->pAacDecoderChannelInfo[ch]->pSpectralCoefficient = (SPECTRAL_PTR) &self->aacCommonData.workBufferCore2[ch*1024]; + + } + CPns_InitPns(&self->pAacDecoderChannelInfo[ch]->data.aac.PnsData, &self->aacCommonData.pnsInterChannelData, &self->aacCommonData.pnsCurrentSeed, self->aacCommonData.pnsRandomSeed); + } + + + HcrInitRom(&self->aacCommonData.overlay.aac.erHcrInfo); + setHcrType(&self->aacCommonData.overlay.aac.erHcrInfo, ID_SCE); + + /* Make allocated channel count persistent in decoder context. */ + self->aacChannels = ascChannels; + } + + /* Make amount of signalled channels persistent in decoder context. */ + self->ascChannels = ascChannels; + } + + /* Update structures */ + if (ascChanged) { + + /* Things to be done for each channel, which do not involved allocating memory. */ + for (ch = 0; ch < ascChannels; ch++) { + switch (self->streamInfo.aot) { + case AOT_ER_AAC_ELD: + case AOT_ER_AAC_LD: + self->pAacDecoderChannelInfo[ch]->granuleLength = self->streamInfo.aacSamplesPerFrame; + break; + default: + self->pAacDecoderChannelInfo[ch]->granuleLength = self->streamInfo.aacSamplesPerFrame / 8; + break; + } + mdct_init( &self->pAacDecoderStaticChannelInfo[ch]->IMdct, + self->pAacDecoderStaticChannelInfo[ch]->pOverlapBuffer, + OverlapBufferSize ); + + + /* Reset DRC control data for this channel */ + aacDecoder_drcInitChannelData ( &self->pAacDecoderStaticChannelInfo[ch]->drcData ); + + /* Reset concealment only if ASC changed. Otherwise it will be done with any config callback. + E.g. every time the LATM SMC is present. */ + CConcealment_InitChannelData(&self->pAacDecoderStaticChannelInfo[ch]->concealmentInfo, + &self->concealCommonData, + self->streamInfo.aacSamplesPerFrame ); + } + } + + /* Update externally visible copy of flags */ + self->streamInfo.flags = self->flags; + + return err; + +bail: + aacDecoder_Close( self ); + return AAC_DEC_OUT_OF_MEMORY; +} + + +LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame( + HANDLE_AACDECODER self, + const UINT flags, + INT_PCM *pTimeData, + const INT timeDataSize, + const INT interleaved + ) +{ + AAC_DECODER_ERROR ErrorStatus = AAC_DEC_OK; + + CProgramConfig *pce; + HANDLE_FDK_BITSTREAM bs = transportDec_GetBitstream(self->hInput, 0); + + MP4_ELEMENT_ID type = ID_NONE; /* Current element type */ + INT aacChannels=0; /* Channel counter for channels found in the bitstream */ + + INT auStartAnchor = (INT)FDKgetValidBits(bs); /* AU start bit buffer position for AU byte alignment */ + + self->frameOK = 1; + + /* Any supported base layer valid AU will require more than 16 bits. */ + if ( (transportDec_GetAuBitsRemaining(self->hInput, 0) < 15) && (flags & (AACDEC_CONCEAL|AACDEC_FLUSH)) == 0) { + self->frameOK = 0; + ErrorStatus = AAC_DEC_DECODE_FRAME_ERROR; + } + + + /* Reset Program Config structure */ + pce = &self->pce; + CProgramConfig_Reset(pce); + + CAacDecoder_AncDataReset(&self->ancData); + + { + int ch; + + if (self->streamInfo.channelConfig == 0) { + /* Init Channel/Element mapping table */ + for (ch=0; ch<(6); ch++) { + self->chMapping[ch] = 255; + } + if (!CProgramConfig_IsValid(pce)) { + int el; + for (el=0; el<7; el++) { + self->elements[el] = ID_NONE; + } + } + } + } + + /* Check sampling frequency */ + switch ( self->streamInfo.aacSampleRate ) { + case 16000: + case 12000: + case 11025: + case 8000: + case 7350: + case 48000: + case 44100: + case 32000: + case 24000: + case 22050: + break; + default: + if ( ! (self->flags & (AC_USAC|AC_RSVD50)) ) { + return AAC_DEC_UNSUPPORTED_SAMPLINGRATE; + } + break; + } + + + if ( flags & AACDEC_CLRHIST ) + { + int ch; + /* Clear history */ + for (ch = 0; ch < self->aacChannels; ch++) { + /* Reset concealment */ + CConcealment_InitChannelData(&self->pAacDecoderStaticChannelInfo[ch]->concealmentInfo, + &self->concealCommonData, + self->streamInfo.aacSamplesPerFrame ); + /* Clear concealment buffers to get rid of the complete history */ + FDKmemclear(self->pAacDecoderStaticChannelInfo[ch]->concealmentInfo.spectralCoefficient, 1024 * sizeof(FIXP_CNCL)); + FDKmemclear(self->pAacDecoderStaticChannelInfo[ch]->concealmentInfo.specScale, 8 * sizeof(SHORT)); + /* Clear overlap-add buffers to avoid clicks. */ + FDKmemclear(self->pAacDecoderStaticChannelInfo[ch]->IMdct.overlap.freq, OverlapBufferSize*sizeof(FIXP_DBL)); + } + } + + + +#ifdef TP_PCE_ENABLE + int pceRead = 0; /* Flag indicating a PCE in the current raw_data_block() */ +#endif + + + INT hdaacDecoded = 0; + MP4_ELEMENT_ID previous_element = ID_END; /* Last element ID (required for extension payload mapping */ + UCHAR previous_element_index = 0; /* Canonical index of last element */ + int element_count = 0; /* Element counter for elements found in the bitstream */ + int el_cnt[ID_LAST] = { 0 }; /* element counter ( robustness ) */ + + while ( (type != ID_END) && (! (flags & (AACDEC_CONCEAL | AACDEC_FLUSH))) && self->frameOK ) + { + int el_channels; + + if (! (self->flags & (AC_USAC|AC_RSVD50|AC_ELD|AC_SCALABLE|AC_ER))) + type = (MP4_ELEMENT_ID) FDKreadBits(bs,3); + else + type = self->elements[element_count]; + + setHcrType(&self->aacCommonData.overlay.aac.erHcrInfo, type); + + + if ((INT)FDKgetValidBits(bs) < 0) + self->frameOK = 0; + + switch (type) + { + case ID_SCE: + case ID_CPE: + case ID_LFE: + /* + Consistency check + */ + + if (type == ID_CPE) { + el_channels = 2; + } else { + el_channels = 1; + } + + if ( (el_cnt[type] >= (self->ascChannels>>(el_channels-1))) || (aacChannels > (self->ascChannels-el_channels)) ) { + ErrorStatus = AAC_DEC_DECODE_FRAME_ERROR; + self->frameOK = 0; + break; + } + + if ( !(self->flags & (AC_USAC|AC_RSVD50)) ) { + int ch; + for (ch=0; ch < el_channels; ch+=1) { + CPns_ResetData(&self->pAacDecoderChannelInfo[aacChannels+ch]->data.aac.PnsData, + &self->pAacDecoderChannelInfo[aacChannels+ch]->pComData->pnsInterChannelData); + } + } + + if(self->frameOK) { + ErrorStatus = CChannelElement_Read( bs, + &self->pAacDecoderChannelInfo[aacChannels], + &self->pAacDecoderStaticChannelInfo[aacChannels], + self->streamInfo.aot, + &self->samplingRateInfo, + self->flags, + self->streamInfo.aacSamplesPerFrame, + el_channels, + self->streamInfo.epConfig, + self->hInput + ); + if (ErrorStatus) { + self->frameOK = 0; + } + } + + + if ( self->frameOK) { + /* Lookup the element and decode it only if it belongs to the current program */ + if ( CProgramConfig_LookupElement( + pce, + self->streamInfo.channelConfig, + self->pAacDecoderChannelInfo[aacChannels]->ElementInstanceTag, + aacChannels, + self->chMapping, + self->channelType, + self->channelIndices, + &previous_element_index, + self->elements, + type) ) + { + if ( !hdaacDecoded ) { + CChannelElement_Decode( + &self->pAacDecoderChannelInfo[aacChannels], + &self->pAacDecoderStaticChannelInfo[aacChannels], + &self->samplingRateInfo, + self->flags, + el_channels + ); + } + aacChannels += 1; + if (type == ID_CPE) { + aacChannels += 1; + } + } + else { + self->frameOK = 0; + } + /* Create SBR element for SBR for upsampling. */ + if ( (type == ID_LFE) + && ( (self->flags & AC_SBR_PRESENT) + || (self->sbrEnabled == 1) ) ) + { + SBR_ERROR sbrError; + + sbrError = sbrDecoder_InitElement( + self->hSbrDecoder, + self->streamInfo.aacSampleRate, + self->streamInfo.extSamplingRate, + self->streamInfo.aacSamplesPerFrame, + self->streamInfo.aot, + ID_LFE, + previous_element_index + ); + if (sbrError != SBRDEC_OK) { + /* Do not try to apply SBR because initializing the element failed. */ + self->sbrEnabled = 0; + } + } + } + + el_cnt[type]++; + break; + + case ID_CCE: + /* + Consistency check + */ + if ( el_cnt[type] > self->ascChannels ) { + ErrorStatus = AAC_DEC_DECODE_FRAME_ERROR; + self->frameOK = 0; + break; + } + + if (self->frameOK) + { + /* memory for spectral lines temporal on scratch */ + C_ALLOC_SCRATCH_START(mdctSpec, FIXP_DBL, 1024); + + /* create dummy channel for CCE parsing on stack */ + CAacDecoderChannelInfo tmpAacDecoderChannelInfo, *pTmpAacDecoderChannelInfo; + + FDKmemclear(mdctSpec, 1024*sizeof(FIXP_DBL)); + + tmpAacDecoderChannelInfo.pDynData = self->aacCommonData.workBufferCore1->pAacDecoderDynamicData; + tmpAacDecoderChannelInfo.pComData = &self->aacCommonData; + tmpAacDecoderChannelInfo.pSpectralCoefficient = (SPECTRAL_PTR)mdctSpec; + /* Assume AAC-LC */ + tmpAacDecoderChannelInfo.granuleLength = self->streamInfo.aacSamplesPerFrame / 8; + + /* Reset PNS data. */ + CPns_ResetData(&tmpAacDecoderChannelInfo.data.aac.PnsData, &tmpAacDecoderChannelInfo.pComData->pnsInterChannelData); + + pTmpAacDecoderChannelInfo = &tmpAacDecoderChannelInfo; + /* do CCE parsing */ + ErrorStatus = CChannelElement_Read( bs, + &pTmpAacDecoderChannelInfo, + NULL, + self->streamInfo.aot, + &self->samplingRateInfo, + self->flags, + self->streamInfo.aacSamplesPerFrame, + 1, + self->streamInfo.epConfig, + self->hInput + ); + + C_ALLOC_SCRATCH_END(mdctSpec, FIXP_DBL, 1024); + + if (ErrorStatus) { + self->frameOK = 0; + } + + if (self->frameOK) { + /* Lookup the element and decode it only if it belongs to the current program */ + if (CProgramConfig_LookupElement( + pce, + self->streamInfo.channelConfig, + pTmpAacDecoderChannelInfo->ElementInstanceTag, + 0, + self->chMapping, + self->channelType, + self->channelIndices, + &previous_element_index, + self->elements, + type) ) + { + /* decoding of CCE not supported */ + } + else { + self->frameOK = 0; + } + } + } + el_cnt[type]++; + break; + + case ID_DSE: + { + UCHAR element_instance_tag; + + CDataStreamElement_Read( bs, + &self->ancData, + self->hDrcInfo, + self->hInput, + &element_instance_tag, + auStartAnchor ); + + if (!CProgramConfig_LookupElement( + pce, + self->streamInfo.channelConfig, + element_instance_tag, + 0, + self->chMapping, + self->channelType, + self->channelIndices, + &previous_element_index, + self->elements, + type) ) + { + /* most likely an error in bitstream occured */ + //self->frameOK = 0; + } + } + +#if defined(PCM_POSTPROCESS_ENABLE) && defined(DVB_MIXDOWN_ENABLE) && defined(AACDEC_DVB_SUPPORT_ENABLE) + { + UCHAR *pDvbAncData = NULL; + AAC_DECODER_ERROR ancErr; + int ancIndex; + int dvbAncDataSize = 0; + + /* Ask how many anc data elements are in buffer */ + ancIndex = self->ancData.nrElements - 1; + /* Get the last one (if available) */ + ancErr = CAacDecoder_AncDataGet( &self->ancData, + ancIndex, + &pDvbAncData, + &dvbAncDataSize ); + + if (ancErr == AAC_DEC_OK) { + pcmDmx_ReadDvbAncData ( + self->hPcmUtils, + pDvbAncData, + dvbAncDataSize, + 0 /* not mpeg2 */ ); + } + } +#endif /* PCM_POSTPROCESS_ENABLE && DVB_MIXDOWN_ENABLE && AACDEC_DVB_SUPPORT_ENABLE */ + break; + +#ifdef TP_PCE_ENABLE + case ID_PCE: + + if ( CProgramConfigElement_Read( bs, + self->hInput, + pce, + auStartAnchor ) ) + { /* Built element table */ + int elIdx = CProgramConfig_GetElementTable(pce, self->elements); + /* Reset the remaining tabs */ + for ( ; elIdx<7; elIdx++) { + self->elements[elIdx] = ID_NONE; + } + /* Make new number of channel persistant */ + self->ascChannels = pce->NumChannels; + /* If PCE is not first element conceal this frame to avoid inconsistencies */ + if ( element_count != 0 ) { + self->frameOK = 0; + } + } + pceRead = 1; + break; +#endif /* TP_PCE_ENABLE */ + + case ID_FIL: + { + int bitCnt = FDKreadBits(bs,4); /* bs_count */ + + if (bitCnt == 15) + { + int esc_count = FDKreadBits(bs,8); /* bs_esc_count */ + bitCnt = esc_count + 14; + } + + /* Convert to bits */ + bitCnt <<= 3; + + while (bitCnt > 0) { + ErrorStatus = CAacDecoder_ExtPayloadParse(self, bs, &bitCnt, previous_element, previous_element_index, 1); + if (ErrorStatus != AAC_DEC_OK) { + self->frameOK = 0; + break; + } + } + } + break; + + case ID_EXT: + { + INT bitCnt = 0; + + /* get the remaining bits of this frame */ + bitCnt = transportDec_GetAuBitsRemaining(self->hInput, 0); + + if ( (bitCnt > 0) && (self->flags & AC_SBR_PRESENT) && (self->flags & (AC_USAC|AC_RSVD50|AC_ELD)) ) + { + SBR_ERROR err; + int elIdx, numChElements = el_cnt[ID_SCE] + el_cnt[ID_CPE]; + + for (elIdx = 0; elIdx < numChElements; elIdx += 1) + { + err = sbrDecoder_Parse ( + self->hSbrDecoder, + bs, + &bitCnt, + -1, + self->flags & AC_SBRCRC, + self->elements[elIdx], + elIdx, + self->flags & AC_INDEP ); + + if (err != SBRDEC_OK) { + break; + } + } + if (err == SBRDEC_OK) { + self->sbrEnabled = 1; + } else { + self->frameOK = 0; + } + } + + + if ( ! (self->flags & (AC_USAC|AC_RSVD50|AC_DRM)) ) + { + while ( bitCnt > 7 ) { + ErrorStatus = CAacDecoder_ExtPayloadParse(self, bs, &bitCnt, previous_element, previous_element_index, 0); + if (ErrorStatus != AAC_DEC_OK) { + self->frameOK = 0; + ErrorStatus = AAC_DEC_PARSE_ERROR; + break; + } + } + } + } + break; + + case ID_END: + break; + + default: + ErrorStatus = AAC_DEC_DECODE_FRAME_ERROR; + self->frameOK = 0; + break; + } + + previous_element = type; + element_count++; + + } /* while ( (type != ID_END) ... ) */ + + if ( !(flags & (AACDEC_CONCEAL|AACDEC_FLUSH)) ) + { + /* Byte alignment with respect to the first bit of the raw_data_block(). */ + { + FDKbyteAlign(bs, auStartAnchor); + } + + /* Check if all bits of the raw_data_block() have been read. */ + if ( transportDec_GetAuBitsTotal(self->hInput, 0) > 0 ) { + INT unreadBits = transportDec_GetAuBitsRemaining(self->hInput, 0); + if ( unreadBits != 0 ) { + + self->frameOK = 0; + /* Do not overwrite current error */ + if (ErrorStatus == AAC_DEC_OK && self->frameOK == 0) { + ErrorStatus = AAC_DEC_PARSE_ERROR; + } + /* Always put the bitbuffer at the right position after the current Access Unit. */ + FDKpushBiDirectional(bs, unreadBits); + } + } + + /* Check the last element. The terminator (ID_END) has to be the last one (even if ER syntax is used). */ + if ( self->frameOK && type != ID_END ) { + /* Do not overwrite current error */ + if (ErrorStatus == AAC_DEC_OK) { + ErrorStatus = AAC_DEC_PARSE_ERROR; + } + self->frameOK = 0; + } + } + + /* More AAC channels than specified by the ASC not allowed. */ + if ( (aacChannels == 0 || aacChannels > self->aacChannels) && !(flags & (AACDEC_CONCEAL|AACDEC_FLUSH)) ) { + { + /* Do not overwrite current error */ + if (ErrorStatus == AAC_DEC_OK) { + ErrorStatus = AAC_DEC_DECODE_FRAME_ERROR; + } + self->frameOK = 0; + } + aacChannels = 0; + } + else if ( aacChannels > self->ascChannels ) { + /* Do not overwrite current error */ + if (ErrorStatus == AAC_DEC_OK) { + ErrorStatus = AAC_DEC_UNSUPPORTED_FORMAT; + } + self->frameOK = 0; + aacChannels = 0; + } + + if ( TRANSPORTDEC_OK != transportDec_CrcCheck(self->hInput) ) + { + self->frameOK=0; + } + + /* store or restore the number of channels */ + if ( self->frameOK && !(flags &(AACDEC_CONCEAL|AACDEC_FLUSH)) ) { + self->concealChannels = aacChannels; /* store */ + self->sbrEnabledPrev = self->sbrEnabled; + } else { + if (self->aacChannels > 0) { + aacChannels = self->concealChannels; /* restore */ + self->sbrEnabled = self->sbrEnabledPrev; + } + } + + /* Update number of output channels */ + self->streamInfo.numChannels = aacChannels; + +#if defined(TP_PCE_ENABLE) && defined(PCM_POSTPROCESS_ENABLE) && defined(MPEG_PCE_MIXDOWN_ENABLE) + if (pceRead == 1 || CProgramConfig_IsValid(pce)) { + /* Set matrix mixdown infos if available from PCE. */ + pcmDmx_SetMatrixMixdownFromPce ( self->hPcmUtils, + pce->MatrixMixdownIndexPresent, + pce->MatrixMixdownIndex, + pce->PseudoSurroundEnable ); + } +#endif + + /* If there is no valid data to transfrom into time domain, return. */ + if ( ! IS_OUTPUT_VALID(ErrorStatus) ) { + return ErrorStatus; + } + + /* + Inverse transform + */ + { + int stride, offset, c; + + /* Extract DRC control data and map it to channels (without bitstream delay) */ + aacDecoder_drcProlog ( + self->hDrcInfo, + bs, + self->pAacDecoderStaticChannelInfo, + self->pce.ElementInstanceTag, + self->chMapping, + aacChannels + ); + + /* "c" iterates in canonical MPEG channel order */ + for (c=0; c < aacChannels; c++) + { + CAacDecoderChannelInfo *pAacDecoderChannelInfo; + + /* Select correct pAacDecoderChannelInfo for current channel */ + if (self->chMapping[c] >= aacChannels) { + pAacDecoderChannelInfo = self->pAacDecoderChannelInfo[c]; + } else { + pAacDecoderChannelInfo = self->pAacDecoderChannelInfo[self->chMapping[c]]; + } + + /* Setup offset and stride for time buffer traversal. */ + if (interleaved) { + stride = aacChannels; + offset = self->channelOutputMapping[aacChannels-1][c]; + } else { + stride = 1; + offset = self->channelOutputMapping[aacChannels-1][c] * self->streamInfo.aacSamplesPerFrame; + } + + + /* + Conceal defective spectral data + */ + CConcealment_Apply(&self->pAacDecoderStaticChannelInfo[c]->concealmentInfo, + pAacDecoderChannelInfo, + self->pAacDecoderStaticChannelInfo[c], + &self->samplingRateInfo, + self->streamInfo.aacSamplesPerFrame, + 0, + (self->frameOK && !(flags&AACDEC_CONCEAL)), + self->flags + ); + + + if (flags & (AACDEC_INTR|AACDEC_CLRHIST)) { + /* Reset DRC control data for this channel */ + aacDecoder_drcInitChannelData ( &self->pAacDecoderStaticChannelInfo[c]->drcData ); + } + /* DRC processing */ + aacDecoder_drcApply ( + self->hDrcInfo, + self->hSbrDecoder, + pAacDecoderChannelInfo, + &self->pAacDecoderStaticChannelInfo[c]->drcData, + c, + self->streamInfo.aacSamplesPerFrame, + self->sbrEnabled + ); + + if ( flags&AACDEC_FLUSH ) { + FDKmemclear(pAacDecoderChannelInfo->pSpectralCoefficient, sizeof(FIXP_DBL)*self->streamInfo.aacSamplesPerFrame); + } + + switch (pAacDecoderChannelInfo->renderMode) + { + case AACDEC_RENDER_IMDCT: + CBlock_FrequencyToTime( + self->pAacDecoderStaticChannelInfo[c], + pAacDecoderChannelInfo, + pTimeData + offset, + self->streamInfo.aacSamplesPerFrame, + stride, + (self->frameOK && !(flags&AACDEC_CONCEAL)), + self->aacCommonData.workBufferCore1->mdctOutTemp + ); + break; + case AACDEC_RENDER_ELDFB: + CBlock_FrequencyToTimeLowDelay( + self->pAacDecoderStaticChannelInfo[c], + pAacDecoderChannelInfo, + pTimeData + offset, + self->streamInfo.aacSamplesPerFrame, + stride + ); + break; + default: + ErrorStatus = AAC_DEC_UNKNOWN; + break; + } + if ( flags&AACDEC_FLUSH ) { + FDKmemclear(self->pAacDecoderStaticChannelInfo[c]->pOverlapBuffer, OverlapBufferSize*sizeof(FIXP_DBL)); + } + } + + + /* Extract DRC control data and map it to channels (with bitstream delay) */ + aacDecoder_drcEpilog ( + self->hDrcInfo, + bs, + self->pAacDecoderStaticChannelInfo, + self->pce.ElementInstanceTag, + self->chMapping, + aacChannels + ); + } + + + /* Reorder channel type information tables. */ + { + AUDIO_CHANNEL_TYPE types[(6)]; + UCHAR idx[(6)]; + int c; + + FDK_ASSERT(sizeof(self->channelType) == sizeof(types)); + FDK_ASSERT(sizeof(self->channelIndices) == sizeof(idx)); + + FDKmemcpy(types, self->channelType, sizeof(types)); + FDKmemcpy(idx, self->channelIndices, sizeof(idx)); + + for (c=0; c<aacChannels; c++) { + self->channelType[self->channelOutputMapping[aacChannels-1][c]] = types[c]; + self->channelIndices[self->channelOutputMapping[aacChannels-1][c]] = idx[c]; + } + } + + self->blockNumber++; + + return ErrorStatus; +} + +/*! + \brief returns the streaminfo pointer + + The function hands back a pointer to the streaminfo structure + + \return pointer to the struct +*/ +LINKSPEC_CPP CStreamInfo* CAacDecoder_GetStreamInfo ( HANDLE_AACDECODER self ) +{ + if (!self) { + return NULL; + } + return &self->streamInfo; +} + + + + |