summaryrefslogtreecommitdiffstats
path: root/libAACdec/src/aacdecoder.cpp
diff options
context:
space:
mode:
authorDave Burke <daveburke@google.com>2012-04-17 09:51:45 -0700
committerDave Burke <daveburke@google.com>2012-04-17 23:04:43 -0700
commit9bf37cc9712506b2483650c82d3c41152337ef7e (patch)
tree77db44e2bae06e3d144b255628be2b7a55c581d3 /libAACdec/src/aacdecoder.cpp
parenta37315fe10ee143d6d0b28c19d41a476a23e63ea (diff)
downloadfdk-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.cpp1667
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;
+}
+
+
+
+