aboutsummaryrefslogtreecommitdiffstats
path: root/libAACdec/src/aacdecoder.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libAACdec/src/aacdecoder.cpp')
-rw-r--r--libAACdec/src/aacdecoder.cpp3699
1 files changed, 2649 insertions, 1050 deletions
diff --git a/libAACdec/src/aacdecoder.cpp b/libAACdec/src/aacdecoder.cpp
index 579e470..64adb56 100644
--- a/libAACdec/src/aacdecoder.cpp
+++ b/libAACdec/src/aacdecoder.cpp
@@ -1,74 +1,85 @@
-
-/* -----------------------------------------------------------------------------------------------------------
+/* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
-© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
- All rights reserved.
+© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten
+Forschung e.V. All rights reserved.
1. INTRODUCTION
-The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements
-the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio.
-This FDK AAC Codec software is intended to be used on a wide variety of Android devices.
-
-AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual
-audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by
-independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part
-of the MPEG specifications.
-
-Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer)
-may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners
-individually for the purpose of encoding or decoding bit streams in products that are compliant with
-the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license
-these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec
-software may already be covered under those patent licenses when it is used for those licensed purposes only.
-
-Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality,
-are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional
-applications information and documentation.
+The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software
+that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding
+scheme for digital audio. This FDK AAC Codec software is intended to be used on
+a wide variety of Android devices.
+
+AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient
+general perceptual audio codecs. AAC-ELD is considered the best-performing
+full-bandwidth communications codec by independent studies and is widely
+deployed. AAC has been standardized by ISO and IEC as part of the MPEG
+specifications.
+
+Patent licenses for necessary patent claims for the FDK AAC Codec (including
+those of Fraunhofer) may be obtained through Via Licensing
+(www.vialicensing.com) or through the respective patent owners individually for
+the purpose of encoding or decoding bit streams in products that are compliant
+with the ISO/IEC MPEG audio standards. Please note that most manufacturers of
+Android devices already license these patent claims through Via Licensing or
+directly from the patent owners, and therefore FDK AAC Codec software may
+already be covered under those patent licenses when it is used for those
+licensed purposes only.
+
+Commercially-licensed AAC software libraries, including floating-point versions
+with enhanced sound quality, are also available from Fraunhofer. Users are
+encouraged to check the Fraunhofer website for additional applications
+information and documentation.
2. COPYRIGHT LICENSE
-Redistribution and use in source and binary forms, with or without modification, are permitted without
-payment of copyright license fees provided that you satisfy the following conditions:
+Redistribution and use in source and binary forms, with or without modification,
+are permitted without payment of copyright license fees provided that you
+satisfy the following conditions:
-You must retain the complete text of this software license in redistributions of the FDK AAC Codec or
-your modifications thereto in source code form.
+You must retain the complete text of this software license in redistributions of
+the FDK AAC Codec or your modifications thereto in source code form.
-You must retain the complete text of this software license in the documentation and/or other materials
-provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form.
-You must make available free of charge copies of the complete source code of the FDK AAC Codec and your
+You must retain the complete text of this software license in the documentation
+and/or other materials provided with redistributions of the FDK AAC Codec or
+your modifications thereto in binary form. You must make available free of
+charge copies of the complete source code of the FDK AAC Codec and your
modifications thereto to recipients of copies in binary form.
-The name of Fraunhofer may not be used to endorse or promote products derived from this library without
-prior written permission.
+The name of Fraunhofer may not be used to endorse or promote products derived
+from this library without prior written permission.
-You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec
-software or your modifications thereto.
+You may not charge copyright license fees for anyone to use, copy or distribute
+the FDK AAC Codec software or your modifications thereto.
-Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software
-and the date of any change. For modified versions of the FDK AAC Codec, the term
-"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term
-"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android."
+Your modified versions of the FDK AAC Codec must carry prominent notices stating
+that you changed the software and the date of any change. For modified versions
+of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android"
+must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK
+AAC Codec Library for Android."
3. NO PATENT LICENSE
-NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer,
-ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with
-respect to this software.
+NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without
+limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE.
+Fraunhofer provides no warranty of patent non-infringement with respect to this
+software.
-You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized
-by appropriate patent licenses.
+You may use this FDK AAC Codec software or modifications thereto only for
+purposes that are authorized by appropriate patent licenses.
4. DISCLAIMER
-This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors
-"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties
-of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
-CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages,
-including but not limited to procurement of substitute goods or services; loss of use, data, or profits,
-or business interruption, however caused and on any theory of liability, whether in contract, strict
-liability, or tort (including negligence), arising in any way out of the use of this software, even if
-advised of the possibility of such damage.
+This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright
+holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
+including but not limited to the implied warranties of merchantability and
+fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary,
+or consequential damages, including but not limited to procurement of substitute
+goods or services; loss of use, data, or profits, or business interruption,
+however caused and on any theory of liability, whether in contract, strict
+liability, or tort (including negligence), arising in any way out of the use of
+this software, even if advised of the possibility of such damage.
5. CONTACT INFORMATION
@@ -79,60 +90,68 @@ Am Wolfsmantel 33
www.iis.fraunhofer.de/amm
amm-info@iis.fraunhofer.de
------------------------------------------------------------------------------------------------------------ */
+----------------------------------------------------------------------------- */
-/***************************** MPEG-4 AAC Decoder **************************
+/**************************** AAC decoder library ******************************
Author(s): Josef Hoepfl
- Description:
-******************************************************************************/
+ Description:
+*******************************************************************************/
/*!
\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.
+ 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.
+ 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 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.
+ 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.
+ 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,
+ 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.
+ 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.
+ 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
+ The filterbank is called using CBlock_FrequencyToTime() using the MDCT module
+ from the FDK Tools
*/
-
-
#include "aacdecoder.h"
#include "aac_rom.h"
@@ -140,54 +159,155 @@ amm-info@iis.fraunhofer.de
#include "channel.h"
#include "FDK_audio.h"
-#include "FDK_tools_rom.h"
-
- #include "aacdec_pns.h"
-
- #include "sbrdecoder.h"
+#include "aacdec_pns.h"
+#include "sbrdecoder.h"
+#include "sac_dec_lib.h"
+#include "aacdec_hcr.h"
+#include "rvlc.h"
- #include "aacdec_hcr.h"
- #include "rvlc.h"
+#include "usacdec_lpd.h"
+#include "ac_arith_coder.h"
#include "tpdec_lib.h"
#include "conceal.h"
- #include "FDK_crc.h"
+#include "FDK_crc.h"
+#define PS_IS_EXPLICITLY_DISABLED(aot, flags) \
+ (((aot) == AOT_DRM_AAC) && !(flags & AC_PS_PRESENT))
+#define IS_STEREO_SBR(el_id, stereoConfigIndex) \
+ (((el_id) == ID_USAC_CPE && (stereoConfigIndex) == 0) || \
+ ((el_id) == ID_USAC_CPE && (stereoConfigIndex) == 3))
-void CAacDecoder_SyncQmfMode(HANDLE_AACDECODER self)
-{
+void CAacDecoder_SyncQmfMode(HANDLE_AACDECODER self) {
+ FDK_ASSERT(
+ !((self->flags[0] & AC_MPS_PRESENT) && (self->flags[0] & AC_PS_PRESENT)));
/* 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->streamInfo.aacNumChannels == 1)
- && ( (CAN_DO_PS(self->streamInfo.aot) && !(self->flags & AC_MPS_PRESENT))
- || ( IS_USAC(self->streamInfo.aot) && (self->flags & AC_MPS_PRESENT)) ) ) )
- {
+ if (IS_USAC(self->streamInfo.aot)) {
+ self->qmfModeCurr = MODE_HQ;
+ }
+
+ if (self->qmfModeCurr == NOT_DEFINED) {
+ if ((IS_LOWDELAY(self->streamInfo.aot) &&
+ (self->flags[0] & AC_MPS_PRESENT)) ||
+ ((self->streamInfo.aacNumChannels == 1) &&
+ ((CAN_DO_PS(self->streamInfo.aot) &&
+ !(self->flags[0] & AC_MPS_PRESENT)) ||
+ (IS_USAC(self->streamInfo.aot))))) {
self->qmfModeCurr = MODE_HQ;
} else {
self->qmfModeCurr = MODE_LP;
}
}
+ if (self->mpsEnableCurr) {
+ if (IS_LOWDELAY(self->streamInfo.aot) &&
+ (self->qmfModeCurr == MODE_LP)) { /* Overrule user requested QMF mode */
+ self->qmfModeCurr = MODE_HQ;
+ }
+ /* Set and check if MPS decoder allows the current mode */
+ switch (mpegSurroundDecoder_SetParam(
+ (CMpegSurroundDecoder *)self->pMpegSurroundDecoder,
+ SACDEC_PARTIALLY_COMPLEX, self->qmfModeCurr == MODE_LP)) {
+ case MPS_OK:
+ break;
+ case MPS_INVALID_PARAMETER: { /* Only one mode supported. Find out which
+ one: */
+ LIB_INFO libInfo[FDK_MODULE_LAST];
+ UINT mpsCaps;
+
+ FDKinitLibInfo(libInfo);
+ mpegSurroundDecoder_GetLibInfo(libInfo);
+ mpsCaps = FDKlibInfo_getCapabilities(libInfo, FDK_MPSDEC);
+
+ if (((mpsCaps & CAPF_MPS_LP) && (self->qmfModeCurr == MODE_LP)) ||
+ ((mpsCaps & CAPF_MPS_HQ) &&
+ (self->qmfModeCurr ==
+ MODE_HQ))) { /* MPS decoder does support the requested mode. */
+ break;
+ }
+ } /* Fall-through: */
+ default:
+ if (self->qmfModeUser == NOT_DEFINED) {
+ /* Revert in case mpegSurroundDecoder_SetParam() fails. */
+ self->qmfModeCurr =
+ (self->qmfModeCurr == MODE_LP) ? MODE_HQ : MODE_LP;
+ } else {
+ /* in case specific mode was requested we disable MPS and playout the
+ * downmix */
+ self->mpsEnableCurr = 0;
+ }
+ }
+ }
/* 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->streamInfo.aacNumChannels == 1 && ! (self->flags & AC_MPS_PRESENT))) && self->qmfModeCurr == MODE_HQ ;
- FDK_ASSERT( ! ( (self->flags & AC_MPS_PRESENT) && self->psPossible ) );
+ sbrDecoder_SetParam(self->hSbrDecoder, SBR_QMF_MODE,
+ (self->qmfModeCurr == MODE_LP));
+ self->psPossible =
+ ((CAN_DO_PS(self->streamInfo.aot) &&
+ !PS_IS_EXPLICITLY_DISABLED(self->streamInfo.aot, self->flags[0]) &&
+ self->streamInfo.aacNumChannels == 1 &&
+ !(self->flags[0] & AC_MPS_PRESENT))) &&
+ self->qmfModeCurr == MODE_HQ;
+ FDK_ASSERT(!((self->flags[0] & AC_MPS_PRESENT) && self->psPossible));
}
-void CAacDecoder_SignalInterruption(HANDLE_AACDECODER self)
-{
+void CAacDecoder_SignalInterruption(HANDLE_AACDECODER self) {
+ if (self->flags[0] & (AC_USAC | AC_RSVD50 | AC_RSV603DA)) {
+ int i;
+
+ for (i = 0; i < fMin(self->aacChannels, (8)); i++) {
+ if (self->pAacDecoderStaticChannelInfo
+ [i]) { /* number of active channels can be smaller */
+ self->pAacDecoderStaticChannelInfo[i]->hArCo->m_numberLinesPrev = 0;
+ }
+ }
+ }
+}
+
+/*!
+ \brief Calculates the number of element channels
+
+ \type channel type
+ \usacStereoConfigIndex usac stereo config index
+
+ \return element channels
+*/
+static int CAacDecoder_GetELChannels(MP4_ELEMENT_ID type,
+ UCHAR usacStereoConfigIndex) {
+ int el_channels = 0;
+
+ switch (type) {
+ case ID_USAC_CPE:
+ if (usacStereoConfigIndex == 1) {
+ el_channels = 1;
+ } else {
+ el_channels = 2;
+ }
+ break;
+ case ID_CPE:
+ el_channels = 2;
+ break;
+ case ID_USAC_SCE:
+ case ID_USAC_LFE:
+ case ID_SCE:
+ case ID_LFE:
+ el_channels = 1;
+ break;
+ default:
+ el_channels = 0;
+ break;
+ }
+
+ return el_channels;
}
/*!
@@ -197,11 +317,9 @@ void CAacDecoder_SignalInterruption(HANDLE_AACDECODER self)
\return Error code
*/
-static AAC_DECODER_ERROR CAacDecoder_AncDataReset(CAncData *ancData)
-{
+static AAC_DECODER_ERROR CAacDecoder_AncDataReset(CAncData *ancData) {
int i;
- for (i=0; i<8; i++)
- {
+ for (i = 0; i < 8; i++) {
ancData->offset[i] = 0;
}
ancData->nrElements = 0;
@@ -218,8 +336,8 @@ static AAC_DECODER_ERROR CAacDecoder_AncDataReset(CAncData *ancData)
\return Error code
*/
-AAC_DECODER_ERROR CAacDecoder_AncDataInit(CAncData *ancData, unsigned char *buffer, int size)
-{
+AAC_DECODER_ERROR CAacDecoder_AncDataInit(CAncData *ancData,
+ unsigned char *buffer, int size) {
if (size >= 0) {
ancData->buffer = buffer;
ancData->bufferSize = size;
@@ -238,27 +356,26 @@ AAC_DECODER_ERROR CAacDecoder_AncDataInit(CAncData *ancData, unsigned char *buff
\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
+ \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 CAacDecoder_AncDataGet(CAncData *ancData, int index,
+ unsigned char **ptr, int *size) {
AAC_DECODER_ERROR error = AAC_DEC_OK;
- *ptr = NULL;
+ *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];
+ if (index >= 0 && index < 8 - 1 && index < ancData->nrElements) {
+ *ptr = &ancData->buffer[ancData->offset[index]];
+ *size = ancData->offset[index + 1] - ancData->offset[index];
}
return error;
}
-
/*!
\brief Parse ancillary data
@@ -268,40 +385,32 @@ AAC_DECODER_ERROR CAacDecoder_AncDataGet(CAncData *ancData, int index, unsigned
\return Error code
*/
-static
-AAC_DECODER_ERROR CAacDecoder_AncDataParse (
- CAncData *ancData,
- HANDLE_FDK_BITSTREAM hBs,
- const int ancBytes )
-{
+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 (ancData->buffer != NULL) {
if (ancBytes > 0) {
/* write ancillary data to external buffer */
int offset = ancData->offset[ancData->nrElements];
- if ((offset + ancBytes) > ancData->bufferSize)
- {
+ if ((offset + ancBytes) > ancData->bufferSize) {
error = AAC_DEC_TOO_SMALL_ANC_BUFFER;
- }
- else if (ancData->nrElements >= 8-1)
- {
+ } else if (ancData->nrElements >= 8 - 1) {
error = AAC_DEC_TOO_MANY_ANC_ELEMENTS;
- }
- else
- {
+ } else {
int i;
for (i = 0; i < ancBytes; i++) {
- ancData->buffer[i+offset] = FDKreadBits(hBs, 8);
+ ancData->buffer[i + offset] = FDKreadBits(hBs, 8);
readBytes++;
}
ancData->nrElements++;
- ancData->offset[ancData->nrElements] = ancBytes + ancData->offset[ancData->nrElements-1];
+ ancData->offset[ancData->nrElements] =
+ ancBytes + ancData->offset[ancData->nrElements - 1];
}
}
}
@@ -310,7 +419,7 @@ AAC_DECODER_ERROR CAacDecoder_AncDataParse (
if (readBytes > 0) {
/* skip data */
- FDKpushFor(hBs, readBytes<<3);
+ FDKpushFor(hBs, readBytes << 3);
}
return error;
@@ -323,36 +432,29 @@ AAC_DECODER_ERROR CAacDecoder_AncDataParse (
\return Error code
*/
-static AAC_DECODER_ERROR CDataStreamElement_Read (
- HANDLE_AACDECODER self,
- HANDLE_FDK_BITSTREAM bs,
- UCHAR *elementInstanceTag,
- UINT alignmentAnchor )
-{
- HANDLE_TRANSPORTDEC pTp;
- CAncData *ancData;
+static AAC_DECODER_ERROR CDataStreamElement_Read(HANDLE_AACDECODER self,
+ HANDLE_FDK_BITSTREAM bs,
+ UCHAR *elementInstanceTag,
+ UINT alignmentAnchor) {
AAC_DECODER_ERROR error = AAC_DEC_OK;
UINT dataStart, dseBits;
int dataByteAlignFlag, count;
FDK_ASSERT(self != NULL);
- ancData = &self->ancData;
- pTp = self->hInput;
-
- int crcReg = transportDec_CrcStartReg(pTp, 0);
+ int crcReg = transportDec_CrcStartReg(self->hInput, 0);
/* Element Instance Tag */
- *elementInstanceTag = FDKreadBits(bs,4);
+ *elementInstanceTag = FDKreadBits(bs, 4);
/* Data Byte Align Flag */
- dataByteAlignFlag = FDKreadBits(bs,1);
+ dataByteAlignFlag = FDKreadBits(bs, 1);
- count = FDKreadBits(bs,8);
+ count = FDKreadBits(bs, 8);
if (count == 255) {
- count += FDKreadBits(bs,8); /* EscCount */
+ count += FDKreadBits(bs, 8); /* EscCount */
}
- dseBits = count*8;
+ dseBits = count * 8;
if (dataByteAlignFlag) {
FDKbyteAlign(bs, alignmentAnchor);
@@ -360,38 +462,37 @@ static AAC_DECODER_ERROR CDataStreamElement_Read (
dataStart = FDKgetValidBits(bs);
- error = CAacDecoder_AncDataParse(ancData, bs, count);
- transportDec_CrcEndReg(pTp, crcReg);
+ error = CAacDecoder_AncDataParse(&self->ancData, bs, count);
+ transportDec_CrcEndReg(self->hInput, crcReg);
{
- /* Move to the beginning of the data junk */
- FDKpushBack(bs, dataStart-FDKgetValidBits(bs));
+ /* Move to the beginning of the data chunk */
+ FDKpushBack(bs, dataStart - FDKgetValidBits(bs));
/* Read Anc data if available */
- aacDecoder_drcMarkPayload( self->hDrcInfo, bs, DVB_DRC_ANC_DATA );
+ aacDecoder_drcMarkPayload(self->hDrcInfo, bs, DVB_DRC_ANC_DATA);
}
{
PCMDMX_ERROR dmxErr = PCMDMX_OK;
- /* Move to the beginning of the data junk */
- FDKpushBack(bs, dataStart-FDKgetValidBits(bs));
+ /* Move to the beginning of the data chunk */
+ FDKpushBack(bs, dataStart - FDKgetValidBits(bs));
/* Read DMX meta-data */
- dmxErr = pcmDmx_Parse (
- self->hPcmUtils,
- bs,
- dseBits,
- 0 /* not mpeg2 */ );
+ dmxErr = pcmDmx_Parse(self->hPcmUtils, bs, dseBits, 0 /* not mpeg2 */);
+ if (error == AAC_DEC_OK && dmxErr != PCMDMX_OK) {
+ error = AAC_DEC_UNKNOWN;
}
+ }
/* Move to the very end of the element. */
- FDKpushBiDirectional(bs, FDKgetValidBits(bs)-dataStart+dseBits);
+ FDKpushBiDirectional(
+ bs, (INT)FDKgetValidBits(bs) - (INT)dataStart + (INT)dseBits);
return error;
}
-#ifdef TP_PCE_ENABLE
/*!
\brief Read Program Config Element
@@ -401,15 +502,14 @@ static AAC_DECODER_ERROR CDataStreamElement_Read (
\channelConfig Current channel configuration
\alignAnchor Anchor for byte alignment
- \return PCE status (-1: fail, 0: no new PCE, 1: PCE updated, 2: PCE updated need re-config).
+ \return PCE status (-1: fail, 0: no new PCE, 1: PCE updated, 2: PCE updated
+ need re-config).
*/
-static int CProgramConfigElement_Read (
- HANDLE_FDK_BITSTREAM bs,
- HANDLE_TRANSPORTDEC pTp,
- CProgramConfig *pce,
- const UINT channelConfig,
- const UINT alignAnchor )
-{
+static int CProgramConfigElement_Read(HANDLE_FDK_BITSTREAM bs,
+ HANDLE_TRANSPORTDEC pTp,
+ CProgramConfig *pce,
+ const UINT channelConfig,
+ const UINT alignAnchor) {
int pceStatus = 0;
int crcReg;
@@ -417,7 +517,6 @@ static int CProgramConfigElement_Read (
C_ALLOC_SCRATCH_START(tmpPce, CProgramConfig, 1);
CProgramConfig_Init(tmpPce);
- CProgramConfig_Reset(tmpPce);
crcReg = transportDec_CrcStartReg(pTp, 0);
@@ -425,35 +524,34 @@ static int CProgramConfigElement_Read (
transportDec_CrcEndReg(pTp, crcReg);
- if ( CProgramConfig_IsValid(tmpPce)
- && (tmpPce->Profile == 1) )
- {
- if ( !pce->isValid && (channelConfig > 0) ) {
+ if (CProgramConfig_IsValid(tmpPce) && (tmpPce->Profile == 1)) {
+ if (!CProgramConfig_IsValid(pce) && (channelConfig > 0)) {
/* Create a standard channel config PCE to compare with */
- CProgramConfig_GetDefault( pce, channelConfig );
+ CProgramConfig_GetDefault(pce, channelConfig);
}
- if (pce->isValid) {
+ if (CProgramConfig_IsValid(pce)) {
/* Compare the new and the old PCE (tags ignored) */
- switch ( CProgramConfig_Compare( pce, tmpPce ) )
- {
- case 1: /* Channel configuration not changed. Just new metadata. */
- FDKmemcpy(pce, tmpPce, sizeof(CProgramConfig)); /* Store the complete PCE */
- pceStatus = 1; /* New PCE but no change of config */
- break;
- case 2: /* The number of channels are identical but not the config */
- if (channelConfig == 0) {
- FDKmemcpy(pce, tmpPce, sizeof(CProgramConfig)); /* Store the complete PCE */
- pceStatus = 2; /* Decoder needs re-configuration */
- }
- break;
- case -1: /* The channel configuration is completely different */
- pceStatus = -1; /* Not supported! */
- break;
- case 0: /* Nothing to do because PCE matches the old one exactly. */
- default:
- /* pceStatus = 0; */
- break;
+ switch (CProgramConfig_Compare(pce, tmpPce)) {
+ case 1: /* Channel configuration not changed. Just new metadata. */
+ FDKmemcpy(pce, tmpPce,
+ sizeof(CProgramConfig)); /* Store the complete PCE */
+ pceStatus = 1; /* New PCE but no change of config */
+ break;
+ case 2: /* The number of channels are identical but not the config */
+ if (channelConfig == 0) {
+ FDKmemcpy(pce, tmpPce,
+ sizeof(CProgramConfig)); /* Store the complete PCE */
+ pceStatus = 2; /* Decoder needs re-configuration */
+ }
+ break;
+ case -1: /* The channel configuration is completely different */
+ pceStatus = -1; /* Not supported! */
+ break;
+ case 0: /* Nothing to do because PCE matches the old one exactly. */
+ default:
+ /* pceStatus = 0; */
+ break;
}
}
}
@@ -462,7 +560,243 @@ static int CProgramConfigElement_Read (
return pceStatus;
}
-#endif /* TP_PCE_ENABLE */
+
+/*!
+ \brief Prepares crossfade for USAC DASH IPF config change
+
+ \pTimeData Pointer to time data
+ \pTimeDataFlush Pointer to flushed time data
+ \numChannels Number of channels
+ \frameSize Size of frame
+ \interleaved Indicates if time data is interleaved
+
+ \return Error code
+*/
+LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_PrepareCrossFade(
+ const INT_PCM *pTimeData, INT_PCM **pTimeDataFlush, const INT numChannels,
+ const INT frameSize, const INT interleaved) {
+ int i, ch, s1, s2;
+ AAC_DECODER_ERROR ErrorStatus;
+
+ ErrorStatus = AAC_DEC_OK;
+
+ if (interleaved) {
+ s1 = 1;
+ s2 = numChannels;
+ } else {
+ s1 = frameSize;
+ s2 = 1;
+ }
+
+ for (ch = 0; ch < numChannels; ch++) {
+ const INT_PCM *pIn = &pTimeData[ch * s1];
+ for (i = 0; i < TIME_DATA_FLUSH_SIZE; i++) {
+ pTimeDataFlush[ch][i] = *pIn;
+ pIn += s2;
+ }
+ }
+
+ return ErrorStatus;
+}
+
+/*!
+ \brief Applies crossfade for USAC DASH IPF config change
+
+ \pTimeData Pointer to time data
+ \pTimeDataFlush Pointer to flushed time data
+ \numChannels Number of channels
+ \frameSize Size of frame
+ \interleaved Indicates if time data is interleaved
+
+ \return Error code
+*/
+LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_ApplyCrossFade(
+ INT_PCM *pTimeData, INT_PCM **pTimeDataFlush, const INT numChannels,
+ const INT frameSize, const INT interleaved) {
+ int i, ch, s1, s2;
+ AAC_DECODER_ERROR ErrorStatus;
+
+ ErrorStatus = AAC_DEC_OK;
+
+ if (interleaved) {
+ s1 = 1;
+ s2 = numChannels;
+ } else {
+ s1 = frameSize;
+ s2 = 1;
+ }
+
+ for (ch = 0; ch < numChannels; ch++) {
+ INT_PCM *pIn = &pTimeData[ch * s1];
+ for (i = 0; i < TIME_DATA_FLUSH_SIZE; i++) {
+ FIXP_SGL alpha = (FIXP_SGL)i
+ << (FRACT_BITS - 1 - TIME_DATA_FLUSH_SIZE_SF);
+ FIXP_DBL time = FX_PCM2FX_DBL(*pIn);
+ FIXP_DBL timeFlush = FX_PCM2FX_DBL(pTimeDataFlush[ch][i]);
+
+ *pIn = (INT_PCM)(FIXP_PCM)FX_DBL2FX_PCM(
+ timeFlush - fMult(timeFlush, alpha) + fMult(time, alpha));
+ pIn += s2;
+ }
+ }
+
+ return ErrorStatus;
+}
+
+/*!
+ \brief Parse PreRoll Extension Payload
+
+ \self Handle of AAC decoder
+ \numPrerollAU Number of preRoll AUs
+ \prerollAUOffset Offset to each preRoll AU
+ \prerollAULength Length of each preRoll AU
+
+ \return Error code
+*/
+LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_PreRollExtensionPayloadParse(
+ HANDLE_AACDECODER self, UINT *numPrerollAU, UINT *prerollAUOffset,
+ UINT *prerollAULength) {
+ FDK_BITSTREAM bs;
+ HANDLE_FDK_BITSTREAM hBs;
+ AAC_DECODER_ERROR ErrorStatus;
+
+ INT auStartAnchor;
+ UINT independencyFlag;
+ UINT extPayloadPresentFlag;
+ UINT useDefaultLengthFlag;
+ UINT configLength = 0;
+ UINT preRollPossible = 1;
+ UINT i;
+ UCHAR configChanged = 0;
+ UCHAR config[TP_USAC_MAX_CONFIG_LEN] = {0};
+ UCHAR
+ implicitExplicitCfgDiff = 0; /* in case implicit and explicit config is
+ equal preroll AU's should be processed
+ after decoder reset */
+
+ ErrorStatus = AAC_DEC_OK;
+
+ hBs = transportDec_GetBitstream(self->hInput, 0);
+ bs = *hBs;
+
+ auStartAnchor = (INT)FDKgetValidBits(hBs);
+ if (auStartAnchor <= 0) {
+ ErrorStatus = AAC_DEC_NOT_ENOUGH_BITS;
+ goto bail;
+ }
+
+ /* Independency flag */
+ FDKreadBit(hBs);
+
+ /* Payload present flag of extension ID_EXT_ELE_AUDIOPREROLL must be one */
+ extPayloadPresentFlag = FDKreadBits(hBs, 1);
+ if (!extPayloadPresentFlag) {
+ preRollPossible = 0;
+ }
+
+ /* Default length flag of extension ID_EXT_ELE_AUDIOPREROLL must be zero */
+ useDefaultLengthFlag = FDKreadBits(hBs, 1);
+ if (useDefaultLengthFlag) {
+ preRollPossible = 0;
+ }
+
+ if (preRollPossible) { /* extPayloadPresentFlag && !useDefaultLengthFlag */
+ /* Read overall ext payload length, useDefaultLengthFlag must be zero. */
+ escapedValue(hBs, 8, 16, 0);
+
+ /* Read RSVD60 Config size */
+ configLength = escapedValue(hBs, 4, 4, 8);
+
+ /* Avoid decoding pre roll frames if there was no config change and no
+ * config is included in the pre roll ext payload. */
+ }
+
+ /* If pre roll not possible then exit. */
+ if (preRollPossible == 0) {
+ /* Sanity check: if flushing is switched on, preRollPossible must be 1 */
+ if (self->flushStatus != AACDEC_FLUSH_OFF) {
+ /* Mismatch of current payload and flushing status */
+ self->flushStatus = AACDEC_FLUSH_OFF;
+ ErrorStatus = AAC_DEC_PARSE_ERROR;
+ }
+ goto bail;
+ }
+
+ if (self->flags[0] & AC_USAC) {
+ if (configLength > 0) {
+ /* DASH IPF USAC Config Change: Read new config and compare with current
+ * config. Apply reconfiguration if config's are different. */
+ for (i = 0; i < configLength; i++) {
+ config[i] = FDKreadBits(hBs, 8);
+ }
+ TRANSPORTDEC_ERROR terr;
+ terr = transportDec_InBandConfig(self->hInput, config, configLength,
+ self->buildUpStatus, &configChanged, 0,
+ &implicitExplicitCfgDiff);
+ if (terr != TRANSPORTDEC_OK) {
+ ErrorStatus = AAC_DEC_PARSE_ERROR;
+ goto bail;
+ }
+ }
+ }
+
+ /* For the first frame buildUpStatus is not set and no flushing is performed
+ * but preroll AU's should processed. */
+ /* For USAC there is no idle state. */
+ if ((self->streamInfo.numChannels == 0) && !implicitExplicitCfgDiff &&
+ (self->flags[0] & AC_USAC)) {
+ self->buildUpStatus = AACDEC_USAC_BUILD_UP_ON;
+ /* sanity check: if buildUp status on -> flushing must be off */
+ if (self->flushStatus != AACDEC_FLUSH_OFF) {
+ self->flushStatus = AACDEC_FLUSH_OFF;
+ ErrorStatus = AAC_DEC_PARSE_ERROR;
+ goto bail;
+ }
+ }
+
+ if (self->flags[0] & AC_USAC) {
+ /* We are interested in preroll AUs if an explicit or an implicit config
+ * change is signalized in other words if the build up status is set. */
+ if (self->buildUpStatus == AACDEC_USAC_BUILD_UP_ON) {
+ self->applyCrossfade |= FDKreadBit(hBs);
+ FDKreadBit(hBs); /* reserved */
+ /* Read num preroll AU's */
+ *numPrerollAU = escapedValue(hBs, 2, 4, 0);
+ /* check limits for USAC */
+ if (*numPrerollAU > AACDEC_MAX_NUM_PREROLL_AU_USAC) {
+ *numPrerollAU = 0;
+ ErrorStatus = AAC_DEC_PARSE_ERROR;
+ goto bail;
+ }
+ }
+ }
+
+ for (i = 0; i < *numPrerollAU; i++) {
+ /* For every AU get length and offset in the bitstream */
+ prerollAULength[i] = escapedValue(hBs, 16, 16, 0);
+ if (prerollAULength[i] > 0) {
+ prerollAUOffset[i] = auStartAnchor - FDKgetValidBits(hBs);
+ independencyFlag = FDKreadBit(hBs);
+ if (i == 0 && !independencyFlag) {
+ *numPrerollAU = 0;
+ ErrorStatus = AAC_DEC_PARSE_ERROR;
+ goto bail;
+ }
+ FDKpushFor(hBs, prerollAULength[i] * 8 - 1);
+ self->prerollAULength[i] = (prerollAULength[i] * 8) + prerollAUOffset[i];
+ } else {
+ *numPrerollAU = 0;
+ ErrorStatus = AAC_DEC_PARSE_ERROR; /* Something is wrong */
+ goto bail;
+ }
+ }
+
+bail:
+
+ *hBs = bs;
+
+ return ErrorStatus;
+}
/*!
\brief Parse Extension Payload
@@ -473,14 +807,9 @@ static int CProgramConfigElement_Read (
\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)
-{
+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;
@@ -492,182 +821,274 @@ AAC_DECODER_ERROR CAacDecoder_ExtPayloadParse (HANDLE_AACDECODER self,
return AAC_DEC_DECODE_FRAME_ERROR;
}
- extension_type = (EXT_PAYLOAD_TYPE) FDKreadBits(hBs, 4); /* bs_extension_type */
+ 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 );
+ /* For ELD, the SBR signaling is explicit and parsed in
+ aacDecoder_ParseExplicitMpsAndSbr(), therefore skip SBR if implicit
+ present. */
+ if ((self->flags[0] & AC_ELD) && ((extension_type == EXT_SBR_DATA_CRC) ||
+ (extension_type == EXT_SBR_DATA))) {
+ extension_type = EXT_FIL; /* skip sbr data */
+ }
- if (readBits > *count)
- { /* Read too much. Something went wrong! */
+ switch (extension_type) {
+ case EXT_DYNAMIC_RANGE: {
+ INT readBits =
+ aacDecoder_drcMarkPayload(self->hDrcInfo, hBs, MPEG_DRC_EXT_DATA);
+
+ if (readBits > *count) { /* Read too much. Something went wrong! */
error = AAC_DEC_PARSE_ERROR;
}
*count -= readBits;
- }
- break;
+ } break;
+ case EXT_UNI_DRC: {
+ DRC_DEC_ERROR drcErr = DRC_DEC_OK;
+ DRC_DEC_CODEC_MODE drcDecCodecMode = DRC_DEC_CODEC_MODE_UNDEFINED;
+ INT nBitsRemaining = FDKgetValidBits(hBs);
+ INT readBits;
+
+ switch (self->streamInfo.aot) {
+ case AOT_AAC_LC:
+ case AOT_SBR:
+ case AOT_PS:
+ drcDecCodecMode = DRC_DEC_MPEG_4_AAC;
+ break;
+ default:
+ error = AAC_DEC_PARSE_ERROR;
+ goto bail;
+ }
+ drcErr = FDK_drcDec_SetCodecMode(self->hUniDrcDecoder, drcDecCodecMode);
+ if (drcErr) {
+ error = AAC_DEC_PARSE_ERROR;
+ goto bail;
+ }
- case EXT_SBR_DATA_CRC:
- crcFlag = 1;
- case EXT_SBR_DATA:
- if (IS_CHANNEL_ELEMENT(previous_element)) {
- SBR_ERROR sbrError;
+ drcErr = FDK_drcDec_ReadUniDrc(self->hUniDrcDecoder, hBs);
+ if (drcErr) {
+ error = AAC_DEC_PARSE_ERROR;
+ goto bail;
+ }
+ readBits = (INT)nBitsRemaining - (INT)FDKgetValidBits(hBs);
+ if (readBits > *count) { /* Read too much. Something went wrong! */
+ error = AAC_DEC_PARSE_ERROR;
+ }
+ *count -= readBits;
+ /* Skip any trailing bits */
+ FDKpushFor(hBs, *count);
+ *count = 0;
+ } break;
+ case EXT_LDSAC_DATA:
+ case EXT_SAC_DATA:
+ /* Read MPEG Surround Extension payload */
+ {
+ int err, mpsSampleRate, mpsFrameSize;
- CAacDecoder_SyncQmfMode(self);
+ if (self->flags[0] & AC_PS_PRESENT) {
+ error = AAC_DEC_PARSE_ERROR;
+ goto bail;
+ }
- 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 but only if no severe error happend. */
- if ( (sbrError == SBRDEC_OK)
- || (sbrError == SBRDEC_PARSE_ERROR) ) {
- self->sbrEnabled = 1;
+ /* Handle SBR dual rate case */
+ if (self->streamInfo.extSamplingRate != 0) {
+ mpsSampleRate = self->streamInfo.extSamplingRate;
+ mpsFrameSize = self->streamInfo.aacSamplesPerFrame *
+ (self->streamInfo.extSamplingRate /
+ self->streamInfo.aacSampleRate);
+ } else {
+ mpsSampleRate = self->streamInfo.aacSampleRate;
+ mpsFrameSize = self->streamInfo.aacSamplesPerFrame;
}
- } 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);
+ /* Setting of internal MPS state; may be reset in
+ CAacDecoder_SyncQmfMode if decoder is unable to decode with user
+ defined qmfMode */
+ if (!(self->flags[0] & (AC_USAC | AC_RSVD50 | AC_ELD))) {
+ self->mpsEnableCurr = self->mpsEnableUser;
+ }
+ if (self->mpsEnableCurr) {
+ if (!self->qmfDomain.globalConf.qmfDomainExplicitConfig) {
+ /* if not done yet, allocate full MPEG Surround decoder instance */
+ if (mpegSurroundDecoder_IsFullMpegSurroundDecoderInstanceAvailable(
+ (CMpegSurroundDecoder *)self->pMpegSurroundDecoder) ==
+ SAC_INSTANCE_NOT_FULL_AVAILABLE) {
+ if (mpegSurroundDecoder_Open(
+ (CMpegSurroundDecoder **)&self->pMpegSurroundDecoder, -1,
+ &self->qmfDomain)) {
+ return AAC_DEC_OUT_OF_MEMORY;
+ }
+ }
+ }
+ err = mpegSurroundDecoder_Parse(
+ (CMpegSurroundDecoder *)self->pMpegSurroundDecoder, hBs, count,
+ self->streamInfo.aot, mpsSampleRate, mpsFrameSize,
+ self->flags[0] & AC_INDEP);
+ if (err == MPS_OK) {
+ self->flags[0] |= AC_MPS_PRESENT;
+ } else {
+ error = AAC_DEC_PARSE_ERROR;
+ }
+ }
+ /* Skip any trailing bytes */
+ FDKpushFor(hBs, *count);
*count = 0;
- } else {
- /* If this is not a fill element with a known length, we are screwed and further parsing makes no sense. */
- if (sbrError != SBRDEC_OK) {
- self->frameOK = 0;
+ }
+ break;
+
+ case EXT_SBR_DATA_CRC:
+ crcFlag = 1;
+ case EXT_SBR_DATA:
+ if (IS_CHANNEL_ELEMENT(previous_element)) {
+ SBR_ERROR sbrError;
+ UCHAR configMode = 0;
+ UCHAR configChanged = 0;
+
+ CAacDecoder_SyncQmfMode(self);
+
+ configMode |= AC_CM_ALLOC_MEM;
+
+ sbrError = sbrDecoder_InitElement(
+ self->hSbrDecoder, self->streamInfo.aacSampleRate,
+ self->streamInfo.extSamplingRate,
+ self->streamInfo.aacSamplesPerFrame, self->streamInfo.aot,
+ previous_element, elIndex,
+ 2, /* Signalize that harmonicSBR shall be ignored in the config
+ change detection */
+ 0, configMode, &configChanged, self->downscaleFactor);
+
+ if (sbrError == SBRDEC_OK) {
+ sbrError = sbrDecoder_Parse(self->hSbrDecoder, hBs,
+ self->pDrmBsBuffer, self->drmBsBufferSize,
+ count, *count, crcFlag, previous_element,
+ elIndex, self->flags[0], self->elFlags);
+ /* Enable SBR for implicit SBR signalling but only if no severe error
+ * happend. */
+ if ((sbrError == SBRDEC_OK) || (sbrError == SBRDEC_PARSE_ERROR)) {
+ 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
+ * and further parsing makes no sense. */
+ if (sbrError != SBRDEC_OK) {
+ self->frameOK = 0;
+ }
+ }
+ } else {
+ error = AAC_DEC_PARSE_ERROR;
}
- } else {
- error = AAC_DEC_PARSE_ERROR;
- }
- break;
+ break;
- case EXT_FILL_DATA:
- {
+ case EXT_FILL_DATA: {
int temp;
- temp = FDKreadBits(hBs,4);
+ temp = FDKreadBits(hBs, 4);
bytes--;
if (temp != 0) {
error = AAC_DEC_PARSE_ERROR;
break;
}
while (bytes > 0) {
- temp = FDKreadBits(hBs,8);
+ temp = FDKreadBits(hBs, 8);
bytes--;
if (temp != 0xa5) {
error = AAC_DEC_PARSE_ERROR;
break;
}
}
- *count = bytes<<3;
- }
- break;
+ *count = bytes << 3;
+ } break;
- case EXT_DATA_ELEMENT:
- {
+ case EXT_DATA_ELEMENT: {
int dataElementVersion;
- dataElementVersion = FDKreadBits(hBs,4);
+ dataElementVersion = FDKreadBits(hBs, 4);
*count -= 4;
if (dataElementVersion == 0) /* ANC_DATA */
{
int temp, dataElementLength = 0;
do {
- temp = FDKreadBits(hBs,8);
+ temp = FDKreadBits(hBs, 8);
*count -= 8;
dataElementLength += temp;
- } while (temp == 255 );
+ } while (temp == 255);
CAacDecoder_AncDataParse(&self->ancData, hBs, dataElementLength);
- *count -= (dataElementLength<<3);
+ *count -= (dataElementLength << 3);
} else {
/* align = 0 */
error = AAC_DEC_PARSE_ERROR;
goto bail;
}
- }
- break;
-
- case EXT_DATA_LENGTH:
- if ( !fIsFillElement /* Makes no sens to have an additional length in a fill ... */
- && (self->flags & AC_ER) ) /* ... element because this extension payload type was ... */
- { /* ... created to circumvent the missing length in ER-Syntax. */
- int bitCnt, len = FDKreadBits(hBs, 4);
- *count -= 4;
-
- if (len == 15) {
- int add_len = FDKreadBits(hBs, 8);
- *count -= 8;
- len += add_len;
+ } break;
+
+ case EXT_DATA_LENGTH:
+ if (!fIsFillElement /* Makes no sens to have an additional length in a
+ fill ... */
+ &&
+ (self->flags[0] &
+ AC_ER)) /* ... element because this extension payload type was ... */
+ { /* ... created to circumvent the missing length in ER-Syntax. */
+ 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;
+ if (add_len == 255) {
+ len += FDKreadBits(hBs, 16);
+ *count -= 16;
+ }
}
- }
- len <<= 3;
- bitCnt = len;
+ 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);
+ 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;
+ goto bail;
+ } else {
+ /* rewind and call myself again. */
+ FDKpushBack(hBs, 4);
- error =
- CAacDecoder_ExtPayloadParse (
- self,
- hBs,
- &bitCnt,
- previous_element,
- elIndex,
- 0 );
+ error = CAacDecoder_ExtPayloadParse(
+ self, hBs, &bitCnt, previous_element, elIndex,
+ 1); /* Treat same as fill element */
- *count -= len - bitCnt;
+ *count -= len - bitCnt;
+ }
+ /* Note: the fall through in case the if statement above is not taken is
+ * intentional. */
+ break;
}
- /* Note: the fall through in case the if statement above is not taken is intentional. */
- break;
- }
- case EXT_FIL:
+ case EXT_FIL:
- default:
- /* align = 4 */
- FDKpushFor(hBs, *count);
- *count = 0;
- break;
+ default:
+ /* align = 4 */
+ FDKpushFor(hBs, *count);
+ *count = 0;
+ break;
}
bail:
- if ( (error != AAC_DEC_OK)
- && fIsFillElement )
- { /* Skip the remaining extension bytes */
+ if ((error != AAC_DEC_OK) &&
+ fIsFillElement) { /* Skip the remaining extension bytes */
FDKpushBiDirectional(hBs, *count);
*count = 0;
/* Patch error code because decoding can go on. */
@@ -677,15 +1098,107 @@ bail:
return error;
}
+static AAC_DECODER_ERROR aacDecoder_ParseExplicitMpsAndSbr(
+ HANDLE_AACDECODER self, HANDLE_FDK_BITSTREAM bs,
+ const MP4_ELEMENT_ID previous_element, const int previous_element_index,
+ const int element_index, const int el_cnt[]) {
+ AAC_DECODER_ERROR ErrorStatus = AAC_DEC_OK;
+ INT bitCnt = 0;
+
+ /* get the remaining bits of this frame */
+ bitCnt = transportDec_GetAuBitsRemaining(self->hInput, 0);
+
+ if ((bitCnt > 0) && (self->flags[0] & AC_SBR_PRESENT) &&
+ (self->flags[0] & (AC_USAC | AC_RSVD50 | AC_ELD | AC_DRM))) {
+ SBR_ERROR err = SBRDEC_OK;
+ int chElIdx, numChElements = el_cnt[ID_SCE] + el_cnt[ID_CPE] +
+ el_cnt[ID_LFE] + el_cnt[ID_USAC_SCE] +
+ el_cnt[ID_USAC_CPE] + el_cnt[ID_USAC_LFE];
+
+ if (self->flags[0] & AC_USAC) {
+ chElIdx = numChElements - 1;
+ } else {
+ chElIdx = 0; /* ELD case */
+ }
+
+ for (; chElIdx < numChElements; chElIdx += 1) {
+ MP4_ELEMENT_ID sbrType;
+ if (self->flags[0] & (AC_USAC)) {
+ FDK_ASSERT((self->elements[element_index] == ID_USAC_SCE) ||
+ (self->elements[element_index] == ID_USAC_CPE));
+ sbrType = IS_STEREO_SBR(self->elements[element_index],
+ self->usacStereoConfigIndex[element_index])
+ ? ID_CPE
+ : ID_SCE;
+ } else
+ sbrType = self->elements[chElIdx];
+ err = sbrDecoder_Parse(self->hSbrDecoder, bs, self->pDrmBsBuffer,
+ self->drmBsBufferSize, &bitCnt, -1,
+ self->flags[0] & AC_SBRCRC, sbrType, chElIdx,
+ self->flags[0], self->elFlags);
+ if (err != SBRDEC_OK) {
+ break;
+ }
+ }
+ switch (err) {
+ case SBRDEC_PARSE_ERROR:
+ /* Can not go on parsing because we do not
+ know the length of the SBR extension data. */
+ FDKpushFor(bs, bitCnt);
+ bitCnt = 0;
+ break;
+ case SBRDEC_OK:
+ self->sbrEnabled = 1;
+ break;
+ default:
+ self->frameOK = 0;
+ break;
+ }
+ }
+
+ if ((bitCnt > 0) && (self->flags[0] & (AC_USAC | AC_RSVD50))) {
+ if ((self->flags[0] & AC_MPS_PRESENT) ||
+ (self->elFlags[element_index] & AC_EL_USAC_MPS212)) {
+ int err;
+
+ err = mpegSurroundDecoder_ParseNoHeader(
+ (CMpegSurroundDecoder *)self->pMpegSurroundDecoder, bs, &bitCnt,
+ self->flags[0] & AC_INDEP);
+ if (err != MPS_OK) {
+ self->frameOK = 0;
+ ErrorStatus = AAC_DEC_PARSE_ERROR;
+ }
+ }
+ }
+
+ if (self->flags[0] & AC_DRM) {
+ if ((bitCnt = (INT)FDKgetValidBits(bs)) != 0) {
+ FDKpushBiDirectional(bs, bitCnt);
+ }
+ }
+
+ if (!(self->flags[0] & (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;
+ }
+ }
+ }
+ return ErrorStatus;
+}
+
/* 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.
+ 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)
-{
+static void CStreamInfoInit(CStreamInfo *pStreamInfo) {
pStreamInfo->aacSampleRate = 0;
pStreamInfo->profile = -1;
pStreamInfo->aot = AOT_NONE;
@@ -694,12 +1207,12 @@ void CStreamInfoInit(CStreamInfo *pStreamInfo)
pStreamInfo->bitRate = 0;
pStreamInfo->aacSamplesPerFrame = 0;
- pStreamInfo->extAot = AOT_NONE;
+ pStreamInfo->extAot = AOT_NONE;
pStreamInfo->extSamplingRate = 0;
pStreamInfo->flags = 0;
- pStreamInfo->epConfig = -1; /* default is no ER */
+ pStreamInfo->epConfig = -1; /* default: no ER */
pStreamInfo->numChannels = 0;
pStreamInfo->sampleRate = 0;
@@ -708,21 +1221,24 @@ void CStreamInfoInit(CStreamInfo *pStreamInfo)
pStreamInfo->outputDelay = 0;
/* DRC */
- pStreamInfo->drcProgRefLev = -1; /* set program reference level to not indicated */
- pStreamInfo->drcPresMode = -1; /* default: presentation mode not indicated */
+ pStreamInfo->drcProgRefLev =
+ -1; /* set program reference level to not indicated */
+ pStreamInfo->drcPresMode = -1; /* default: presentation mode not indicated */
}
/*!
\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
+ 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,...). */
+LINKSPEC_CPP HANDLE_AACDECODER CAacDecoder_Open(
+ TRANSPORT_TYPE bsFormat) /*!< bitstream format (adif,adts,loas,...). */
{
HANDLE_AACDECODER self;
@@ -731,12 +1247,14 @@ LINKSPEC_CPP HANDLE_AACDECODER CAacDecoder_Open(TRANSPORT_TYPE bsFormat) /*!<
goto bail;
}
- /* Assign channel mapping info arrays (doing so removes dependency of settings header in API header). */
+ FDK_QmfDomain_ClearRequested(&self->qmfDomain.globalConf);
+
+ /* 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 */
+ self->downscaleFactor = 1;
+ self->downscaleFactorInBS = 1;
/* initialize anc data */
CAacDecoder_AncDataInit(&self->ancData, NULL, 0);
@@ -744,75 +1262,208 @@ LINKSPEC_CPP HANDLE_AACDECODER CAacDecoder_Open(TRANSPORT_TYPE bsFormat) /*!<
/* initialize stream info */
CStreamInfoInit(&self->streamInfo);
+ /* initialize progam config */
+ CProgramConfig_Init(&self->pce);
+
/* initialize error concealment common data */
CConcealment_InitCommonData(&self->concealCommonData);
+ self->concealMethodUser = ConcealMethodNone; /* undefined -> auto mode */
self->hDrcInfo = GetDrcInfo();
if (self->hDrcInfo == NULL) {
goto bail;
}
/* Init common DRC structure */
- aacDecoder_drcInit( self->hDrcInfo );
+ aacDecoder_drcInit(self->hDrcInfo);
/* Set default frame delay */
- aacDecoder_drcSetParam (
- self->hDrcInfo,
- DRC_BS_DELAY,
- CConcealment_GetDelay(&self->concealCommonData)
- );
+ aacDecoder_drcSetParam(self->hDrcInfo, DRC_BS_DELAY,
+ CConcealment_GetDelay(&self->concealCommonData));
+ self->workBufferCore2 = GetWorkBufferCore2();
+ if (self->workBufferCore2 == NULL) goto bail;
- self->aacCommonData.workBufferCore1 = GetWorkBufferCore1();
- self->aacCommonData.workBufferCore2 = GetWorkBufferCore2();
- if (self->aacCommonData.workBufferCore1 == NULL
- ||self->aacCommonData.workBufferCore2 == NULL )
+ /* When RSVD60 is active use dedicated memory for core decoding */
+ self->pTimeData2 = GetWorkBufferCore5();
+ self->timeData2Size = GetRequiredMemWorkBufferCore5();
+ if (self->pTimeData2 == NULL) {
goto bail;
+ }
return self;
bail:
- CAacDecoder_Close( self );
+ CAacDecoder_Close(self);
return NULL;
}
-/* Destroy aac decoder */
-LINKSPEC_CPP void CAacDecoder_Close(HANDLE_AACDECODER self)
-{
+/* Revert CAacDecoder_Init() */
+static void CAacDecoder_DeInit(HANDLE_AACDECODER self,
+ const int subStreamIndex) {
int ch;
+ int aacChannelOffset = 0, aacChannels = (8);
+ int numElements = (((8)) + (8)), elementOffset = 0;
+
+ if (self == NULL) return;
- if (self == NULL)
- return;
+ {
+ self->ascChannels[0] = 0;
+ self->elements[0] = ID_END;
+ }
- for (ch=0; ch<(8); ch++) {
+ for (ch = aacChannelOffset; ch < aacChannelOffset + aacChannels; ch++) {
+ if (self->pAacDecoderChannelInfo[ch] != NULL) {
+ if (self->pAacDecoderChannelInfo[ch]->pComStaticData != NULL) {
+ if (self->pAacDecoderChannelInfo[ch]
+ ->pComStaticData->pWorkBufferCore1 != NULL) {
+ if (ch == aacChannelOffset) {
+ FreeWorkBufferCore1(&self->pAacDecoderChannelInfo[ch]
+ ->pComStaticData->pWorkBufferCore1);
+ }
+ }
+ if (self->pAacDecoderChannelInfo[ch]
+ ->pComStaticData->cplxPredictionData != NULL) {
+ FreeCplxPredictionData(&self->pAacDecoderChannelInfo[ch]
+ ->pComStaticData->cplxPredictionData);
+ }
+ /* Avoid double free of linked pComStaticData in case of CPE by settings
+ * pointer to NULL. */
+ if (ch < (8) - 1) {
+ if ((self->pAacDecoderChannelInfo[ch + 1] != NULL) &&
+ (self->pAacDecoderChannelInfo[ch + 1]->pComStaticData ==
+ self->pAacDecoderChannelInfo[ch]->pComStaticData)) {
+ self->pAacDecoderChannelInfo[ch + 1]->pComStaticData = NULL;
+ }
+ }
+ FDKfree(self->pAacDecoderChannelInfo[ch]->pComStaticData);
+ self->pAacDecoderChannelInfo[ch]->pComStaticData = NULL;
+ }
+ if (self->pAacDecoderChannelInfo[ch]->pComData != NULL) {
+ /* Avoid double free of linked pComData in case of CPE by settings
+ * pointer to NULL. */
+ if (ch < (8) - 1) {
+ if ((self->pAacDecoderChannelInfo[ch + 1] != NULL) &&
+ (self->pAacDecoderChannelInfo[ch + 1]->pComData ==
+ self->pAacDecoderChannelInfo[ch]->pComData)) {
+ self->pAacDecoderChannelInfo[ch + 1]->pComData = NULL;
+ }
+ }
+ if (ch == aacChannelOffset) {
+ FreeWorkBufferCore6(
+ (SCHAR **)&self->pAacDecoderChannelInfo[ch]->pComData);
+ } else {
+ FDKafree(self->pAacDecoderChannelInfo[ch]->pComData);
+ }
+ self->pAacDecoderChannelInfo[ch]->pComData = NULL;
+ }
+ }
if (self->pAacDecoderStaticChannelInfo[ch] != NULL) {
if (self->pAacDecoderStaticChannelInfo[ch]->pOverlapBuffer != NULL) {
- FreeOverlapBuffer (&self->pAacDecoderStaticChannelInfo[ch]->pOverlapBuffer);
+ FreeOverlapBuffer(
+ &self->pAacDecoderStaticChannelInfo[ch]->pOverlapBuffer);
}
- if (self->pAacDecoderStaticChannelInfo[ch] != NULL) {
- FreeAacDecoderStaticChannelInfo (&self->pAacDecoderStaticChannelInfo[ch]);
+ if (self->pAacDecoderStaticChannelInfo[ch]->hArCo != NULL) {
+ CArco_Destroy(self->pAacDecoderStaticChannelInfo[ch]->hArCo);
}
+ FreeAacDecoderStaticChannelInfo(&self->pAacDecoderStaticChannelInfo[ch]);
}
if (self->pAacDecoderChannelInfo[ch] != NULL) {
- FreeAacDecoderChannelInfo (&self->pAacDecoderChannelInfo[ch]);
+ FreeAacDecoderChannelInfo(&self->pAacDecoderChannelInfo[ch]);
+ }
+ }
+
+ {
+ int el;
+ for (el = elementOffset; el < elementOffset + numElements; el++) {
+ if (self->cpeStaticData[el] != NULL) {
+ FreeCpePersistentData(&self->cpeStaticData[el]);
+ }
}
}
+ FDK_Delay_Destroy(&self->usacResidualDelay);
+
self->aacChannels = 0;
+ self->streamInfo.aacSampleRate = 0;
+ self->streamInfo.sampleRate = 0;
+ /* This samplerate value is checked for configuration change, not the others
+ * above. */
+ self->samplingRateInfo[subStreamIndex].samplingRate = 0;
+}
+
+/*!
+ * \brief CAacDecoder_CtrlCFGChange Set config change parameters.
+ *
+ * \param self [i] handle to AACDECODER structure
+ * \param flushStatus [i] flush status: on|off
+ * \param flushCnt [i] flush frame counter
+ * \param buildUpStatus [i] build up status: on|off
+ * \param buildUpCnt [i] build up frame counter
+ *
+ * \return error
+ */
+LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_CtrlCFGChange(HANDLE_AACDECODER self,
+ UCHAR flushStatus,
+ SCHAR flushCnt,
+ UCHAR buildUpStatus,
+ SCHAR buildUpCnt) {
+ AAC_DECODER_ERROR err = AAC_DEC_OK;
+
+ self->flushStatus = flushStatus;
+ self->flushCnt = flushCnt;
+ self->buildUpStatus = buildUpStatus;
+ self->buildUpCnt = buildUpCnt;
+
+ return (err);
+}
+
+/*!
+ * \brief CAacDecoder_FreeMem Free config dependent AAC memory.
+ *
+ * \param self [i] handle to AACDECODER structure
+ *
+ * \return error
+ */
+LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_FreeMem(HANDLE_AACDECODER self,
+ const int subStreamIndex) {
+ AAC_DECODER_ERROR err = AAC_DEC_OK;
+
+ CAacDecoder_DeInit(self, subStreamIndex);
+
+ return (err);
+}
+
+/* Destroy aac decoder */
+LINKSPEC_CPP void CAacDecoder_Close(HANDLE_AACDECODER self) {
+ if (self == NULL) return;
+
+ CAacDecoder_DeInit(self, 0);
+
+ {
+ int ch;
+ for (ch = 0; ch < (8); ch++) {
+ if (self->pTimeDataFlush[ch] != NULL) {
+ FreeTimeDataFlush(&self->pTimeDataFlush[ch]);
+ }
+ }
+ }
if (self->hDrcInfo) {
FreeDrcInfo(&self->hDrcInfo);
}
- if (self->aacCommonData.workBufferCore1 != NULL) {
- FreeWorkBufferCore1 (&self->aacCommonData.workBufferCore1);
+ /* Free WorkBufferCore2 */
+ if (self->workBufferCore2 != NULL) {
+ FreeWorkBufferCore2(&self->workBufferCore2);
}
- if (self->aacCommonData.workBufferCore2 != NULL) {
- FreeWorkBufferCore2 (&self->aacCommonData.workBufferCore2);
+ if (self->pTimeData2 != NULL) {
+ FreeWorkBufferCore5(&self->pTimeData2);
}
- FreeAacDecoder ( &self);
-}
+ FDK_QmfDomain_Close(&self->qmfDomain);
+ FreeAacDecoder(&self);
+}
/*!
\brief Initialization of decoder instance
@@ -821,357 +1472,997 @@ LINKSPEC_CPP void CAacDecoder_Close(HANDLE_AACDECODER self)
\return error status: 0 for success, <>0 for unsupported configurations
*/
-LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_Init(HANDLE_AACDECODER self, const CSAudioSpecificConfig *asc)
-{
+LINKSPEC_CPP AAC_DECODER_ERROR
+CAacDecoder_Init(HANDLE_AACDECODER self, const CSAudioSpecificConfig *asc,
+ UCHAR configMode, UCHAR *configChanged) {
AAC_DECODER_ERROR err = AAC_DEC_OK;
- INT ascChannels, ch, ascChanged = 0;
+ INT ascChannels, ascChanged = 0;
+ AACDEC_RENDER_MODE initRenderMode = AACDEC_RENDER_INVALID;
+ SCHAR usacStereoConfigIndex = -1;
+ int usacResidualDelayCompSamples = 0;
+ int elementOffset, aacChannelsOffset, aacChannelsOffsetIdx;
+ const int streamIndex = 0;
+ INT flushChannels = 0;
- if (!self)
- return AAC_DEC_INVALID_HANDLE;
+ if (!self) return AAC_DEC_INVALID_HANDLE;
+
+ UCHAR downscaleFactor = self->downscaleFactor;
+ UCHAR downscaleFactorInBS = self->downscaleFactorInBS;
// 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)
+ // 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;
-
- case AOT_ER_AAC_SCAL:
- if (asc->m_sc.m_gaSpecificConfig.m_layer > 0) {
- /* aac_scalable_extension_element() currently not supported. */
- return AAC_DEC_UNSUPPORTED_FORMAT;
- }
-
- case AOT_SBR:
- case AOT_PS:
- case AOT_ER_AAC_LD:
- case AOT_ER_AAC_ELD:
- case AOT_DRM_AAC:
- break;
-
- default:
- return AAC_DEC_UNSUPPORTED_AOT;
+ case AOT_AAC_LC:
+ self->streamInfo.profile = 1;
+ case AOT_ER_AAC_SCAL:
+ if (asc->m_sc.m_gaSpecificConfig.m_layer > 0) {
+ /* aac_scalable_extension_element() currently not supported. */
+ return AAC_DEC_UNSUPPORTED_FORMAT;
+ }
+ case AOT_SBR:
+ case AOT_PS:
+ case AOT_ER_AAC_LC:
+ case AOT_ER_AAC_LD:
+ case AOT_DRM_AAC:
+ case AOT_DRM_SURROUND:
+ initRenderMode = AACDEC_RENDER_IMDCT;
+ break;
+ case AOT_ER_AAC_ELD:
+ initRenderMode = AACDEC_RENDER_ELDFB;
+ break;
+ case AOT_USAC:
+ initRenderMode = AACDEC_RENDER_IMDCT;
+ break;
+ default:
+ return AAC_DEC_UNSUPPORTED_AOT;
}
- CProgramConfig_Init(&self->pce);
+ if (CProgramConfig_IsValid(&self->pce) && (asc->m_channelConfiguration > 0)) {
+ /* Compare the stored (old) PCE with a default PCE created from the (new)
+ channel_config (on a temporal buffer) to find out wheter we can keep it
+ (and its metadata) or not. */
+ int pceCmpResult;
+ C_ALLOC_SCRATCH_START(tmpPce, CProgramConfig, 1);
+
+ CProgramConfig_GetDefault(tmpPce, asc->m_channelConfiguration);
+ pceCmpResult = CProgramConfig_Compare(&self->pce, tmpPce);
+ if ((pceCmpResult < 0) /* Reset if PCEs are completely different ... */
+ ||
+ (pceCmpResult > 1)) { /* ... or have a different layout. */
+ CProgramConfig_Init(&self->pce);
+ } /* Otherwise keep the PCE (and its metadata). */
+ C_ALLOC_SCRATCH_END(tmpPce, CProgramConfig, 1);
+ } else {
+ 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, (8), &self->chMapIndex);
- for (; el<(8); el++) {
- self->elements[el] = ID_NONE;
- }
- } else {
- return AAC_DEC_UNSUPPORTED_CHANNELCONFIG;
+ case 0:
+ switch (asc->m_aot) {
+ case AOT_USAC:
+ self->chMapIndex = 0;
+ ascChannels = asc->m_sc.m_usacConfig.m_nUsacChannels;
+ break;
+ default:
+ /* get channels from program config (ASC) */
+ if (CProgramConfig_IsValid(&asc->m_progrConfigElement)) {
+ ascChannels = asc->m_progrConfigElement.NumChannels;
+ if (ascChannels > 0) {
+ int el_tmp;
+ /* valid number of channels -> copy program config element (PCE)
+ * from ASC */
+ FDKmemcpy(&self->pce, &asc->m_progrConfigElement,
+ sizeof(CProgramConfig));
+ /* Built element table */
+ el_tmp = CProgramConfig_GetElementTable(
+ &asc->m_progrConfigElement, self->elements, (((8)) + (8)),
+ &self->chMapIndex);
+ for (; el_tmp < (3 * ((8) * 2) + (((8) * 2)) / 2 + 4 * (1) + 1);
+ el_tmp++) {
+ self->elements[el_tmp] = ID_NONE;
+ }
+ } else {
+ return AAC_DEC_UNSUPPORTED_CHANNELCONFIG;
+ }
+ } else {
+ self->chMapIndex = 0;
+ return AAC_DEC_UNSUPPORTED_CHANNELCONFIG;
+ }
+ break;
}
- } else {
- self->chMapIndex = 0;
- 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 = (8);
- } else {
- return AAC_DEC_UNSUPPORTED_CHANNELCONFIG;
+ break;
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ ascChannels = asc->m_channelConfiguration;
+ break;
+ case 11:
+ ascChannels = 7;
+ break;
+ case 7:
+ case 12:
+ case 14:
+ ascChannels = 8;
+ break;
+ case 13: /* 22.2 setup */
+ ascChannels = 24;
+ break;
+ default:
+ return AAC_DEC_UNSUPPORTED_CHANNELCONFIG;
+ }
+
+ if (asc->m_aot == AOT_USAC) {
+ flushChannels = fMin(ascChannels, (8));
+ INT numChannel;
+ pcmDmx_GetParam(self->hPcmUtils, MIN_NUMBER_OF_OUTPUT_CHANNELS,
+ &numChannel);
+ flushChannels = fMin(fMax(numChannel, flushChannels), (8));
+ }
+
+ if (IS_USAC(asc->m_aot)) {
+ for (int el = 0; el < (INT)asc->m_sc.m_usacConfig.m_usacNumElements; el++) {
+ /* fix number of core channels aka ascChannels for stereoConfigIndex = 1
+ * cases */
+ if (asc->m_sc.m_usacConfig.element[el].m_stereoConfigIndex == 1) {
+ ascChannels--; /* stereoConfigIndex == 1 stereo cases do actually
+ contain only a mono core channel. */
+ } else if (asc->m_sc.m_usacConfig.element[el].m_stereoConfigIndex == 2) {
+ /* In this case it is necessary to follow up the DMX signal delay caused
+ by HBE also with the residual signal (2nd core channel). The SBR
+ overlap delay is not regarded here, this is handled by the MPS212
+ implementation.
+ */
+ if (asc->m_sc.m_usacConfig.element[el].m_harmonicSBR) {
+ usacResidualDelayCompSamples += asc->m_samplesPerFrame;
+ }
+ if (asc->m_sc.m_usacConfig.m_coreSbrFrameLengthIndex == 4) {
+ usacResidualDelayCompSamples +=
+ 6 * 16; /* difference between 12 SBR
+ overlap slots from SBR and 6
+ slots delayed in MPS212 */
+ }
}
}
-#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 11:
- ascChannels = 7;
- break;
- case 7: case 12: case 14:
- ascChannels = 8;
- break;
- default:
- return AAC_DEC_UNSUPPORTED_CHANNELCONFIG;
}
- if (ascChannels > (8)) {
- return AAC_DEC_UNSUPPORTED_CHANNELCONFIG;
+ aacChannelsOffset = 0;
+ aacChannelsOffsetIdx = 0;
+ elementOffset = 0;
+ if (configMode & AC_CM_ALLOC_MEM) {
+ if ((ascChannels <= 0) ||
+ (asc->m_channelConfiguration > AACDEC_MAX_CH_CONF)) {
+ return AAC_DEC_UNSUPPORTED_CHANNELCONFIG;
+ }
+ if ((ascChannels + aacChannelsOffsetIdx) > ((8) * 2)) {
+ return AAC_DEC_UNSUPPORTED_CHANNELCONFIG;
+ }
+ if ((ascChannels + aacChannelsOffset) > (8)) {
+ 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,(8)));
- for (el=7; el<(8); el++) {
- self->elements[el] = ID_NONE;
- }
- for (ch=0; ch<ascChannels; ch++) {
- self->chMapping[ch] = ch;
+ /* Set syntax flags */
+ self->flags[streamIndex] = 0;
+ { FDKmemclear(self->elFlags, sizeof(self->elFlags)); }
+
+ if ((asc->m_channelConfiguration > 0) || IS_USAC(asc->m_aot)) {
+ if (IS_USAC(asc->m_aot)) {
+ /* copy pointer to usac config
+ (this is preliminary since there's an ongoing discussion about storing
+ the config-part of the bitstream rather than the complete decoded
+ configuration) */
+ self->pUsacConfig[streamIndex] = &asc->m_sc.m_usacConfig;
+
+ /* copy list of elements */
+ if (self->pUsacConfig[streamIndex]->m_usacNumElements >
+ (3 * ((8) * 2) + (((8) * 2)) / 2 + 4 * (1) + 1)) {
+ goto bail;
+ }
+
+ if (self->numUsacElements[streamIndex] !=
+ asc->m_sc.m_usacConfig.m_usacNumElements) {
+ ascChanged = 1;
+ }
+
+ if (configMode & AC_CM_ALLOC_MEM) {
+ self->numUsacElements[streamIndex] =
+ asc->m_sc.m_usacConfig.m_usacNumElements;
+ }
+
+ self->mpsEnableCurr = 0;
+ for (int _el = 0;
+ _el < (int)self->pUsacConfig[streamIndex]->m_usacNumElements;
+ _el++) {
+ int el = _el + elementOffset;
+ if (self->elements[el] !=
+ self->pUsacConfig[streamIndex]->element[_el].usacElementType) {
+ ascChanged = 1;
+ }
+ if (self->usacStereoConfigIndex[el] !=
+ asc->m_sc.m_usacConfig.element[_el].m_stereoConfigIndex) {
+ ascChanged = 1;
+ }
+ if (configMode & AC_CM_ALLOC_MEM) {
+ self->elements[el] =
+ self->pUsacConfig[streamIndex]->element[_el].usacElementType;
+ /* for Unified Stereo Coding */
+ self->usacStereoConfigIndex[el] =
+ asc->m_sc.m_usacConfig.element[_el].m_stereoConfigIndex;
+ if (self->elements[el] == ID_USAC_CPE) {
+ self->mpsEnableCurr |= self->usacStereoConfigIndex[el] ? 1 : 0;
+ }
+ }
+
+ self->elFlags[el] |=
+ (asc->m_sc.m_usacConfig.element[_el].m_noiseFilling)
+ ? AC_EL_USAC_NOISE
+ : 0;
+ self->elFlags[el] |=
+ (asc->m_sc.m_usacConfig.element[_el].m_stereoConfigIndex > 0)
+ ? AC_EL_USAC_MPS212
+ : 0;
+ self->elFlags[el] |= (asc->m_sc.m_usacConfig.element[_el].m_interTes)
+ ? AC_EL_USAC_ITES
+ : 0;
+ self->elFlags[el] |=
+ (asc->m_sc.m_usacConfig.element[_el].m_pvc) ? AC_EL_USAC_PVC : 0;
+ self->elFlags[el] |=
+ (asc->m_sc.m_usacConfig.element[_el].usacElementType == ID_USAC_LFE)
+ ? AC_EL_USAC_LFE
+ : 0;
+ self->elFlags[el] |=
+ (asc->m_sc.m_usacConfig.element[_el].usacElementType == ID_USAC_LFE)
+ ? AC_EL_LFE
+ : 0;
+ if ((asc->m_sc.m_usacConfig.element[_el].usacElementType ==
+ ID_USAC_CPE) &&
+ ((self->usacStereoConfigIndex[el] == 0))) {
+ self->elFlags[el] |= AC_EL_USAC_CP_POSSIBLE;
+ }
+ }
+
+ self->hasAudioPreRoll = 0;
+ if (self->pUsacConfig[streamIndex]->m_usacNumElements) {
+ self->hasAudioPreRoll = asc->m_sc.m_usacConfig.element[0]
+ .extElement.usacExtElementHasAudioPreRoll;
+ }
+ if (configMode & AC_CM_ALLOC_MEM) {
+ self->elements[elementOffset +
+ self->pUsacConfig[streamIndex]->m_usacNumElements] =
+ ID_END;
+ }
+ } else {
+ /* Initialize constant mappings for channel config 1-7 */
+ int i;
+ for (i = 0; i < AACDEC_CH_ELEMENTS_TAB_SIZE; i++) {
+ self->elements[i] = elementsTab[asc->m_channelConfiguration - 1][i];
+ }
+ for (; i < (3 * ((8) * 2) + (((8) * 2)) / 2 + 4 * (1) + 1); i++) {
+ self->elements[i] = ID_NONE;
+ }
}
- for (; ch<(8); ch++) {
- self->chMapping[ch] = 255;
+
+ {
+ int ch;
+
+ for (ch = 0; ch < ascChannels; ch++) {
+ self->chMapping[ch] = ch;
+ }
+ for (; ch < (8); ch++) {
+ self->chMapping[ch] = 255;
+ }
}
+
self->chMapIndex = asc->m_channelConfiguration;
- }
- #ifdef TP_PCE_ENABLE
- else {
+ } else {
if (CProgramConfig_IsValid(&asc->m_progrConfigElement)) {
/* Set matrix mixdown infos if available from PCE. */
- pcmDmx_SetMatrixMixdownFromPce ( self->hPcmUtils,
- asc->m_progrConfigElement.MatrixMixdownIndexPresent,
- asc->m_progrConfigElement.MatrixMixdownIndex,
- asc->m_progrConfigElement.PseudoSurroundEnable );
+ pcmDmx_SetMatrixMixdownFromPce(
+ self->hPcmUtils, asc->m_progrConfigElement.MatrixMixdownIndexPresent,
+ asc->m_progrConfigElement.MatrixMixdownIndex,
+ asc->m_progrConfigElement.PseudoSurroundEnable);
}
}
- #endif
self->streamInfo.channelConfig = asc->m_channelConfiguration;
if (self->streamInfo.aot != asc->m_aot) {
- self->streamInfo.aot = asc->m_aot;
+ if (configMode & AC_CM_ALLOC_MEM) {
+ self->streamInfo.aot = asc->m_aot;
+ }
ascChanged = 1;
}
- if (self->streamInfo.aacSamplesPerFrame != (INT)asc->m_samplesPerFrame) {
- self->streamInfo.aacSamplesPerFrame = asc->m_samplesPerFrame;
+ if (asc->m_aot == AOT_ER_AAC_ELD &&
+ asc->m_sc.m_eldSpecificConfig.m_downscaledSamplingFrequency != 0) {
+ if (self->samplingRateInfo[0].samplingRate !=
+ asc->m_sc.m_eldSpecificConfig.m_downscaledSamplingFrequency ||
+ self->samplingRateInfo[0].samplingRate * self->downscaleFactor !=
+ asc->m_samplingFrequency) {
+ /* get downscaledSamplingFrequency from ESC and compute the downscale
+ * factor */
+ downscaleFactorInBS =
+ asc->m_samplingFrequency /
+ asc->m_sc.m_eldSpecificConfig.m_downscaledSamplingFrequency;
+ if (downscaleFactorInBS == 1 || downscaleFactorInBS == 2 ||
+ downscaleFactorInBS == 3 || downscaleFactorInBS == 4) {
+ downscaleFactor = downscaleFactorInBS;
+ }
+ }
+ } else {
+ downscaleFactorInBS = 1;
+ downscaleFactor = 1;
+ }
+
+ if (self->downscaleFactorInBS != downscaleFactorInBS) {
+ if (configMode & AC_CM_ALLOC_MEM) {
+ self->downscaleFactorInBS = downscaleFactorInBS;
+ self->downscaleFactor = downscaleFactor;
+ }
ascChanged = 1;
}
- self->streamInfo.bitRate = 0;
+ if ((INT)asc->m_samplesPerFrame % downscaleFactor != 0) {
+ return AAC_DEC_UNSUPPORTED_SAMPLINGRATE; /* frameSize/dsf must be an integer
+ number */
+ }
- /* Set syntax flags */
- self->flags = 0;
+ self->streamInfo.bitRate = 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;
+ if (asc->m_aot == AOT_ER_AAC_ELD) {
+ if (self->useLdQmfTimeAlign !=
+ asc->m_sc.m_eldSpecificConfig.m_useLdQmfTimeAlign) {
+ ascChanged = 1;
+ }
+ if (configMode & AC_CM_ALLOC_MEM) {
+ self->useLdQmfTimeAlign =
+ asc->m_sc.m_eldSpecificConfig.m_useLdQmfTimeAlign;
+ }
+ }
+
+ self->streamInfo.extAot = asc->m_extensionAudioObjectType;
+ if (self->streamInfo.extSamplingRate !=
+ (INT)asc->m_extensionSamplingFrequency) {
+ ascChanged = 1;
+ }
+ if (configMode & AC_CM_ALLOC_MEM) {
+ self->streamInfo.extSamplingRate = asc->m_extensionSamplingFrequency;
+ }
+ self->flags[streamIndex] |= (asc->m_sbrPresentFlag) ? AC_SBR_PRESENT : 0;
+ self->flags[streamIndex] |= (asc->m_psPresentFlag) ? AC_PS_PRESENT : 0;
+ if (asc->m_sbrPresentFlag) {
+ self->sbrEnabled = 1;
+ self->sbrEnabledPrev = 1;
+ } else {
+ self->sbrEnabled = 0;
+ self->sbrEnabledPrev = 0;
+ }
+ if (self->sbrEnabled && asc->m_extensionSamplingFrequency) {
+ if (downscaleFactor != 1 && (downscaleFactor)&1) {
+ return AAC_DEC_UNSUPPORTED_SAMPLINGRATE; /* SBR needs an even downscale
+ factor */
+ }
+ if (configMode & AC_CM_ALLOC_MEM) {
+ self->streamInfo.extSamplingRate =
+ self->streamInfo.extSamplingRate / self->downscaleFactor;
+ }
+ }
/* --------- vcb11 ------------ */
- self->flags |= (asc->m_vcb11Flag) ? AC_ER_VCB11 : 0;
+ self->flags[streamIndex] |= (asc->m_vcb11Flag) ? AC_ER_VCB11 : 0;
/* ---------- rvlc ------------ */
- self->flags |= (asc->m_rvlcFlag) ? AC_ER_RVLC : 0;
+ self->flags[streamIndex] |= (asc->m_rvlcFlag) ? AC_ER_RVLC : 0;
/* ----------- hcr ------------ */
- self->flags |= (asc->m_hcrFlag) ? AC_ER_HCR : 0;
+ self->flags[streamIndex] |= (asc->m_hcrFlag) ? AC_ER_HCR : 0;
if (asc->m_aot == AOT_ER_AAC_ELD) {
- self->flags |= AC_ELD;
- self->flags |= (asc->m_sbrPresentFlag) ? AC_SBR_PRESENT : 0; /* Need to set the SBR flag for backward-compatibility
- reasons. Even if SBR is not supported. */
- 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->mpsEnableCurr = 0;
+ self->flags[streamIndex] |= AC_ELD;
+ self->flags[streamIndex] |=
+ (asc->m_sbrPresentFlag)
+ ? AC_SBR_PRESENT
+ : 0; /* Need to set the SBR flag for backward-compatibility
+ reasons. Even if SBR is not supported. */
+ self->flags[streamIndex] |=
+ (asc->m_sc.m_eldSpecificConfig.m_sbrCrcFlag) ? AC_SBRCRC : 0;
+ self->flags[streamIndex] |=
+ (asc->m_sc.m_eldSpecificConfig.m_useLdQmfTimeAlign) ? AC_MPS_PRESENT
+ : 0;
+ if (self->mpsApplicable) {
+ self->mpsEnableCurr = asc->m_sc.m_eldSpecificConfig.m_useLdQmfTimeAlign;
+ }
}
- self->flags |= (asc->m_aot == AOT_ER_AAC_LD) ? AC_LD : 0;
- self->flags |= (asc->m_epConfig >= 0) ? AC_ER : 0;
- if ( asc->m_aot == AOT_DRM_AAC ) {
- self->flags |= AC_DRM|AC_SBRCRC|AC_SCALABLE;
+ self->flags[streamIndex] |= (asc->m_aot == AOT_ER_AAC_LD) ? AC_LD : 0;
+ self->flags[streamIndex] |= (asc->m_epConfig >= 0) ? AC_ER : 0;
+
+ if (asc->m_aot == AOT_USAC) {
+ self->flags[streamIndex] |= AC_USAC;
+ self->flags[streamIndex] |=
+ (asc->m_sc.m_usacConfig.element[0].m_stereoConfigIndex > 0)
+ ? AC_MPS_PRESENT
+ : 0;
}
- if ( (asc->m_aot == AOT_AAC_SCAL)
- || (asc->m_aot == AOT_ER_AAC_SCAL) ) {
- self->flags |= AC_SCALABLE;
+ if (asc->m_aot == AOT_DRM_AAC) {
+ self->flags[streamIndex] |= AC_DRM | AC_SBRCRC | AC_SCALABLE;
}
-
-
- if (asc->m_sbrPresentFlag) {
- self->sbrEnabled = 1;
- self->sbrEnabledPrev = 1;
+ if (asc->m_aot == AOT_DRM_SURROUND) {
+ self->flags[streamIndex] |=
+ AC_DRM | AC_SBRCRC | AC_SCALABLE | AC_MPS_PRESENT;
+ FDK_ASSERT(!asc->m_psPresentFlag);
}
- if (asc->m_psPresentFlag) {
- self->flags |= AC_PS_PRESENT;
+ if ((asc->m_aot == AOT_AAC_SCAL) || (asc->m_aot == AOT_ER_AAC_SCAL)) {
+ self->flags[streamIndex] |= AC_SCALABLE;
}
- if ( (asc->m_epConfig >= 0)
- && (asc->m_channelConfiguration <= 0) ) {
- /* we have to know the number of channels otherwise no decoding is possible */
+ 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;
+ if (asc->m_epConfig > 1) return AAC_DEC_UNSUPPORTED_ER_FORMAT;
/* Check if samplerate changed. */
- if (self->streamInfo.aacSampleRate != (INT)asc->m_samplingFrequency) {
+ if ((self->samplingRateInfo[streamIndex].samplingRate !=
+ asc->m_samplingFrequency) ||
+ (self->streamInfo.aacSamplesPerFrame !=
+ (INT)asc->m_samplesPerFrame / downscaleFactor)) {
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;
+ if (configMode & AC_CM_ALLOC_MEM) {
+ /* Update samplerate info. */
+ error = getSamplingRateInfo(
+ &self->samplingRateInfo[streamIndex], asc->m_samplesPerFrame,
+ asc->m_samplingFrequencyIndex, asc->m_samplingFrequency);
+ if (error != AAC_DEC_OK) {
+ return error;
+ }
+ self->streamInfo.aacSampleRate =
+ self->samplingRateInfo[0].samplingRate / self->downscaleFactor;
+ self->streamInfo.aacSamplesPerFrame =
+ asc->m_samplesPerFrame / self->downscaleFactor;
}
- 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);
- }
-
- if (ascChannels > self->aacChannels)
- {
- /* Make allocated channel count persistent in decoder context. */
- self->aacChannels = ascChannels;
- }
-
- HcrInitRom(&self->aacCommonData.overlay.aac.erHcrInfo);
- setHcrType(&self->aacCommonData.overlay.aac.erHcrInfo, ID_SCE);
+ if (self->ascChannels[streamIndex] != ascChannels) {
+ ascChanged = 1;
+ }
+
+ /* detect config change */
+ if (configMode & AC_CM_DET_CFG_CHANGE) {
+ if (ascChanged != 0) {
+ *configChanged = 1;
+ }
+ return err;
+ }
+
+ /* set AC_USAC_SCFGI3 globally if any usac element uses */
+ switch (asc->m_aot) {
+ case AOT_USAC:
+ if (self->sbrEnabled) {
+ for (int _el = 0;
+ _el < (int)self->pUsacConfig[streamIndex]->m_usacNumElements;
+ _el++) {
+ int el = elementOffset + _el;
+ if (IS_USAC_CHANNEL_ELEMENT(self->elements[el])) {
+ if (usacStereoConfigIndex < 0) {
+ usacStereoConfigIndex = self->usacStereoConfigIndex[el];
+ } else {
+ if ((usacStereoConfigIndex != self->usacStereoConfigIndex[el]) ||
+ (self->usacStereoConfigIndex[el] > 0)) {
+ goto bail;
+ }
+ }
+ }
+ }
+
+ if (usacStereoConfigIndex < 0) {
+ goto bail;
+ }
+
+ if (usacStereoConfigIndex == 3) {
+ self->flags[streamIndex] |= AC_USAC_SCFGI3;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (*configChanged) {
+ /* Set up QMF domain for AOTs with explicit signalling of SBR and or MPS.
+ This is to be able to play out the first frame alway with the correct
+ frame size and sampling rate even in case of concealment.
+ */
+ switch (asc->m_aot) {
+ case AOT_USAC:
+ if (self->sbrEnabled) {
+ const UCHAR map_sbrRatio_2_nAnaBands[] = {16, 24, 32};
+
+ FDK_ASSERT(asc->m_sc.m_usacConfig.m_sbrRatioIndex > 0);
+ FDK_ASSERT(streamIndex == 0);
+
+ self->qmfDomain.globalConf.nInputChannels_requested = ascChannels;
+ self->qmfDomain.globalConf.nOutputChannels_requested =
+ (usacStereoConfigIndex == 1) ? 2 : ascChannels;
+ self->qmfDomain.globalConf.flags_requested = 0;
+ self->qmfDomain.globalConf.nBandsAnalysis_requested =
+ map_sbrRatio_2_nAnaBands[asc->m_sc.m_usacConfig.m_sbrRatioIndex -
+ 1];
+ self->qmfDomain.globalConf.nBandsSynthesis_requested = 64;
+ self->qmfDomain.globalConf.nQmfTimeSlots_requested =
+ (asc->m_sc.m_usacConfig.m_sbrRatioIndex == 1) ? 64 : 32;
+ self->qmfDomain.globalConf.nQmfOvTimeSlots_requested =
+ (asc->m_sc.m_usacConfig.m_sbrRatioIndex == 1) ? 12 : 6;
+ self->qmfDomain.globalConf.nQmfProcBands_requested = 64;
+ self->qmfDomain.globalConf.nQmfProcChannels_requested = 1;
+ self->qmfDomain.globalConf.parkChannel =
+ (usacStereoConfigIndex == 3) ? 1 : 0;
+ self->qmfDomain.globalConf.parkChannel_requested =
+ (usacStereoConfigIndex == 3) ? 1 : 0;
+ self->qmfDomain.globalConf.qmfDomainExplicitConfig = 1;
+ }
+ break;
+ case AOT_ER_AAC_ELD:
+ if (self->mpsEnableCurr &&
+ asc->m_sc.m_eldSpecificConfig.m_useLdQmfTimeAlign) {
+ SAC_INPUT_CONFIG sac_interface =
+ (self->sbrEnabled && self->hSbrDecoder) ? SAC_INTERFACE_QMF
+ : SAC_INTERFACE_TIME;
+ mpegSurroundDecoder_ConfigureQmfDomain(
+ (CMpegSurroundDecoder *)self->pMpegSurroundDecoder, sac_interface,
+ (UINT)self->streamInfo.aacSampleRate, asc->m_aot);
+ self->qmfDomain.globalConf.qmfDomainExplicitConfig = 1;
+ }
+ break;
+ default:
+ self->qmfDomain.globalConf.qmfDomainExplicitConfig =
+ 0; /* qmfDomain is initialized by SBR and MPS init functions if
+ required */
+ break;
+ }
+
+ /* Allocate all memory structures for each channel */
+ {
+ int ch = aacChannelsOffset;
+ for (int _ch = 0; _ch < ascChannels; _ch++) {
+ if (ch >= (8)) {
+ goto bail;
+ }
+ 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;
+ }
+ ch++;
+ }
+
+ int chIdx = aacChannelsOffsetIdx;
+ ch = aacChannelsOffset;
+ int _numElements;
+ _numElements = (((8)) + (8));
+ if (self->flags[streamIndex] & (AC_RSV603DA | AC_USAC)) {
+ _numElements = (int)asc->m_sc.m_usacConfig.m_usacNumElements;
+ }
+ if (self->flags[streamIndex] & (AC_ER | AC_LD | AC_ELD)) {
+ _numElements = (asc->m_channelConfiguration == 7)
+ ? 8
+ : asc->m_channelConfiguration;
+ }
+ for (int _el = 0; _el < _numElements; _el++) {
+ int el_channels = 0;
+ int el = elementOffset + _el;
+
+ if (self->flags[streamIndex] &
+ (AC_ELD | AC_RSV603DA | AC_USAC | AC_RSVD50)) {
+ if (ch >= ascChannels) {
+ break;
+ }
+ }
+
+ switch (self->elements[el]) {
+ case ID_SCE:
+ case ID_CPE:
+ case ID_LFE:
+ case ID_USAC_SCE:
+ case ID_USAC_CPE:
+ case ID_USAC_LFE:
+
+ el_channels = CAacDecoder_GetELChannels(
+ self->elements[el], self->usacStereoConfigIndex[el]);
+
+ {
+ self->pAacDecoderChannelInfo[ch]->pComStaticData =
+ (CAacDecoderCommonStaticData *)FDKcalloc(
+ 1, sizeof(CAacDecoderCommonStaticData));
+ if (self->pAacDecoderChannelInfo[ch]->pComStaticData == NULL) {
+ goto bail;
+ }
+ if (ch == aacChannelsOffset) {
+ self->pAacDecoderChannelInfo[ch]->pComData =
+ (CAacDecoderCommonData *)GetWorkBufferCore6();
+ self->pAacDecoderChannelInfo[ch]
+ ->pComStaticData->pWorkBufferCore1 = GetWorkBufferCore1();
+ } else {
+ self->pAacDecoderChannelInfo[ch]->pComData =
+ (CAacDecoderCommonData *)FDKaalloc(
+ sizeof(CAacDecoderCommonData), ALIGNMENT_DEFAULT);
+ self->pAacDecoderChannelInfo[ch]
+ ->pComStaticData->pWorkBufferCore1 =
+ self->pAacDecoderChannelInfo[aacChannelsOffset]
+ ->pComStaticData->pWorkBufferCore1;
+ }
+ if ((self->pAacDecoderChannelInfo[ch]->pComData == NULL) ||
+ (self->pAacDecoderChannelInfo[ch]
+ ->pComStaticData->pWorkBufferCore1 == NULL)) {
+ goto bail;
+ }
+ self->pAacDecoderChannelInfo[ch]->pDynData =
+ &(self->pAacDecoderChannelInfo[ch]
+ ->pComData->pAacDecoderDynamicData[0]);
+ self->pAacDecoderChannelInfo[ch]->pSpectralCoefficient =
+ (SPECTRAL_PTR)&self->workBufferCore2[ch * 1024];
+
+ if (el_channels == 2) {
+ FDK_ASSERT(ch < (8) - 1);
+ self->pAacDecoderChannelInfo[ch + 1]->pComData =
+ self->pAacDecoderChannelInfo[ch]->pComData;
+ self->pAacDecoderChannelInfo[ch + 1]->pComStaticData =
+ self->pAacDecoderChannelInfo[ch]->pComStaticData;
+ self->pAacDecoderChannelInfo[ch + 1]
+ ->pComStaticData->pWorkBufferCore1 =
+ self->pAacDecoderChannelInfo[ch]
+ ->pComStaticData->pWorkBufferCore1;
+ self->pAacDecoderChannelInfo[ch + 1]->pDynData =
+ &(self->pAacDecoderChannelInfo[ch]
+ ->pComData->pAacDecoderDynamicData[1]);
+ self->pAacDecoderChannelInfo[ch + 1]->pSpectralCoefficient =
+ (SPECTRAL_PTR)&self->workBufferCore2[(ch + 1) * 1024];
+ }
+
+ ch += el_channels;
+ }
+ chIdx += el_channels;
+ break;
+
+ default:
+ break;
+ }
+
+ if (self->elements[el] == ID_END) {
+ break;
+ }
+
+ el++;
+ }
+
+ chIdx = aacChannelsOffsetIdx;
+ ch = aacChannelsOffset;
+ for (int _ch = 0; _ch < ascChannels; _ch++) {
+ /* Allocate persistent channel memory */
+ {
+ 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;
+ }
+ if (self->flags[streamIndex] &
+ (AC_USAC | AC_RSVD50 | AC_RSV603DA /*|AC_BSAC*/)) {
+ self->pAacDecoderStaticChannelInfo[ch]->hArCo = CArco_Create();
+ if (self->pAacDecoderStaticChannelInfo[ch]->hArCo == NULL) {
+ goto bail;
+ }
+ }
+
+ if (!(self->flags[streamIndex] & (AC_USAC | AC_RSV603DA))) {
+ CPns_UpdateNoiseState(
+ &self->pAacDecoderChannelInfo[ch]->data.aac.PnsData,
+ &self->pAacDecoderStaticChannelInfo[ch]->pnsCurrentSeed,
+ self->pAacDecoderChannelInfo[ch]->pComData->pnsRandomSeed);
+ }
+ ch++;
+ }
+ chIdx++;
+ }
+
+ if (self->flags[streamIndex] & AC_USAC) {
+ for (int _ch = 0; _ch < flushChannels; _ch++) {
+ ch = aacChannelsOffset + _ch;
+ if (self->pTimeDataFlush[ch] == NULL) {
+ self->pTimeDataFlush[ch] = GetTimeDataFlush(ch);
+ if (self->pTimeDataFlush[ch] == NULL) {
+ goto bail;
+ }
+ }
+ }
+ }
+
+ if (self->flags[streamIndex] & (AC_USAC | AC_RSV603DA)) {
+ int complexStereoPredPossible = 0;
+ ch = aacChannelsOffset;
+ chIdx = aacChannelsOffsetIdx;
+ for (int _el2 = 0; _el2 < (int)asc->m_sc.m_usacConfig.m_usacNumElements;
+ _el2++) {
+ int el2 = elementOffset + _el2;
+ int elCh = 0, ch2;
+
+ if ((self->elements[el2] == ID_USAC_CPE) &&
+ !(self->usacStereoConfigIndex[el2] == 1)) {
+ elCh = 2;
+ } else if (IS_CHANNEL_ELEMENT(self->elements[el2])) {
+ elCh = 1;
+ }
+
+ if (self->elFlags[el2] & AC_EL_USAC_CP_POSSIBLE) {
+ complexStereoPredPossible = 1;
+ if (self->cpeStaticData[el2] == NULL) {
+ self->cpeStaticData[el2] = GetCpePersistentData();
+ if (self->cpeStaticData[el2] == NULL) {
+ goto bail;
+ }
+ }
+ }
+
+ for (ch2 = 0; ch2 < elCh; ch2++) {
+ /* Hook element specific cpeStaticData into channel specific
+ * aacDecoderStaticChannelInfo */
+ self->pAacDecoderStaticChannelInfo[ch]->pCpeStaticData =
+ self->cpeStaticData[el2];
+ if (self->pAacDecoderStaticChannelInfo[ch]->pCpeStaticData !=
+ NULL) {
+ self->pAacDecoderStaticChannelInfo[ch]
+ ->pCpeStaticData->jointStereoPersistentData
+ .spectralCoeffs[ch2] =
+ self->pAacDecoderStaticChannelInfo[ch]
+ ->concealmentInfo.spectralCoefficient;
+ self->pAacDecoderStaticChannelInfo[ch]
+ ->pCpeStaticData->jointStereoPersistentData.specScale[ch2] =
+ self->pAacDecoderStaticChannelInfo[ch]
+ ->concealmentInfo.specScale;
+ self->pAacDecoderStaticChannelInfo[ch]
+ ->pCpeStaticData->jointStereoPersistentData.scratchBuffer =
+ (FIXP_DBL *)self->pTimeData2;
+ }
+ chIdx++;
+ ch++;
+ } /* for each channel in current element */
+ if (complexStereoPredPossible && (elCh == 2)) {
+ /* needed once for all channels */
+ if (self->pAacDecoderChannelInfo[ch - 1]
+ ->pComStaticData->cplxPredictionData == NULL) {
+ self->pAacDecoderChannelInfo[ch - 1]
+ ->pComStaticData->cplxPredictionData =
+ GetCplxPredictionData();
+ }
+ if (self->pAacDecoderChannelInfo[ch - 1]
+ ->pComStaticData->cplxPredictionData == NULL) {
+ goto bail;
+ }
+ }
+ if (elCh > 0) {
+ self->pAacDecoderStaticChannelInfo[ch - elCh]->nfRandomSeed =
+ (ULONG)0x3039;
+ if (self->elements[el2] == ID_USAC_CPE) {
+ if (asc->m_sc.m_usacConfig.element[el2].m_stereoConfigIndex !=
+ 1) {
+ self->pAacDecoderStaticChannelInfo[ch - elCh + 1]
+ ->nfRandomSeed = (ULONG)0x10932;
+ }
+ }
+ }
+ } /* for each element */
+ }
+
+ if (ascChannels != self->aacChannels) {
+ /* Make allocated channel count persistent in decoder context. */
+ self->aacChannels = aacChannelsOffset + ch;
+ }
+ }
+
+ if (usacResidualDelayCompSamples) {
+ INT delayErr = FDK_Delay_Create(&self->usacResidualDelay,
+ (USHORT)usacResidualDelayCompSamples, 1);
+ if (delayErr) {
+ goto bail;
+ }
}
/* Make amount of signalled channels persistent in decoder context. */
- self->ascChannels = ascChannels;
+ self->ascChannels[streamIndex] = ascChannels;
+ /* Init the previous channel count values. This is required to avoid a
+ mismatch of memory accesses in the error concealment module and the
+ allocated channel structures in this function. */
+ self->aacChannelsPrev = 0;
+ }
+
+ if (self->pAacDecoderChannelInfo[0] != NULL) {
+ self->pDrmBsBuffer = self->pAacDecoderChannelInfo[0]
+ ->pComStaticData->pWorkBufferCore1->DrmBsBuffer;
+ self->drmBsBufferSize = DRM_BS_BUFFER_SIZE;
}
/* Update structures */
- if (ascChanged) {
-
- /* Things to be done for each channel, which do not involve allocating memory.
- Doing these things only on the channels needed for the current configuration
- (ascChannels) could lead to memory access violation later (error concealment). */
- for (ch = 0; ch < self->aacChannels; 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 );
- }
+ if (*configChanged) {
+ /* Things to be done for each channel, which do not involve allocating
+ memory. Doing these things only on the channels needed for the current
+ configuration (ascChannels) could lead to memory access violation later
+ (error concealment). */
+ int ch = 0;
+ int chIdx = 0;
+ for (int _ch = 0; _ch < self->ascChannels[streamIndex]; _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;
+ }
+ self->pAacDecoderChannelInfo[ch]->renderMode = initRenderMode;
+
+ mdct_init(&self->pAacDecoderStaticChannelInfo[ch]->IMdct,
+ self->pAacDecoderStaticChannelInfo[ch]->pOverlapBuffer,
+ OverlapBufferSize);
+
+ self->pAacDecoderStaticChannelInfo[ch]->last_core_mode = FD_LONG;
+ self->pAacDecoderStaticChannelInfo[ch]->last_lpd_mode = 255;
+
+ self->pAacDecoderStaticChannelInfo[ch]->last_tcx_pitch = L_DIV;
+
+ /* Reset DRC control data for this channel */
+ aacDecoder_drcInitChannelData(
+ &self->pAacDecoderStaticChannelInfo[ch]->drcData);
+
+ /* Delete mixdown metadata from the past */
+ pcmDmx_Reset(self->hPcmUtils, PCMDMX_RESET_BS_DATA);
+
+ /* 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, initRenderMode,
+ self->streamInfo.aacSamplesPerFrame);
+ ch++;
+ chIdx++;
+ }
}
/* Update externally visible copy of flags */
- self->streamInfo.flags = self->flags;
+ self->streamInfo.flags = self->flags[0];
+
+ if (*configChanged) {
+ int drcDecSampleRate, drcDecFrameSize;
+
+ if (self->streamInfo.extSamplingRate != 0) {
+ drcDecSampleRate = self->streamInfo.extSamplingRate;
+ drcDecFrameSize = (self->streamInfo.aacSamplesPerFrame *
+ self->streamInfo.extSamplingRate) /
+ self->streamInfo.aacSampleRate;
+ } else {
+ drcDecSampleRate = self->streamInfo.aacSampleRate;
+ drcDecFrameSize = self->streamInfo.aacSamplesPerFrame;
+ }
+
+ if (FDK_drcDec_Init(self->hUniDrcDecoder, drcDecFrameSize, drcDecSampleRate,
+ self->aacChannels) != 0)
+ goto bail;
+ }
+
+ if (asc->m_aot == AOT_USAC) {
+ pcmLimiter_SetAttack(self->hLimiter, (5));
+ pcmLimiter_SetThreshold(self->hLimiter, FL2FXCONST_DBL(0.89125094f));
+ }
return err;
bail:
- aacDecoder_Close( self );
+ CAacDecoder_DeInit(self, 0);
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
- )
-{
+ HANDLE_AACDECODER self, const UINT flags, FIXP_PCM *pTimeData,
+ const INT timeDataSize, const int timeDataChannelOffset) {
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 chOutMapIdx; /* Output channel mapping index (see comment below) */
+ MP4_ELEMENT_ID type = ID_NONE; /* Current element type */
+ INT aacChannels = 0; /* Channel counter for channels found in the bitstream */
+ const int streamIndex = 0; /* index of the current substream */
+
+ INT auStartAnchor = (INT)FDKgetValidBits(
+ bs); /* AU start bit buffer position for AU byte alignment */
- INT auStartAnchor = (INT)FDKgetValidBits(bs); /* AU start bit buffer position for AU byte alignment */
+ INT checkSampleRate = self->streamInfo.aacSampleRate;
- self->frameOK = 1;
+ INT CConceal_TDFading_Applied[(8)] = {
+ 0}; /* Initialize status of Time Domain fading */
+
+ if (self->aacChannels <= 0) {
+ return AAC_DEC_UNSUPPORTED_CHANNELCONFIG;
+ }
/* 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) {
+ 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);
-
- {
+ if (!(flags & (AACDEC_CONCEAL | AACDEC_FLUSH)) &&
+ !(self->flags[0] & (AC_USAC | AC_RSV603DA))) {
int ch;
-
if (self->streamInfo.channelConfig == 0) {
/* Init Channel/Element mapping table */
- for (ch=0; ch<(8); ch++) {
+ for (ch = 0; ch < (8); ch++) {
self->chMapping[ch] = 255;
}
if (!CProgramConfig_IsValid(pce)) {
int el;
- for (el=0; el<(8); el++) {
+ for (el = 0; el < (3 * ((8) * 2) + (((8) * 2)) / 2 + 4 * (1) + 1);
+ el++) {
self->elements[el] = ID_NONE;
}
}
}
}
+ if (self->downscaleFactor > 1 && (self->flags[0] & AC_ELD)) {
+ self->flags[0] |= AC_ELD_DOWNSCALE;
+ } else {
+ self->flags[0] &= ~AC_ELD_DOWNSCALE;
+ }
+ /* unsupported dsf (aacSampleRate has not yet been divided by dsf) -> divide
+ */
+ if (self->downscaleFactorInBS > 1 &&
+ (self->flags[0] & AC_ELD_DOWNSCALE) == 0) {
+ checkSampleRate =
+ self->streamInfo.aacSampleRate / self->downscaleFactorInBS;
+ }
+
/* Check sampling frequency */
- switch ( self->streamInfo.aacSampleRate ) {
+ if (self->streamInfo.aacSampleRate <= 0) {
+ /* Instance maybe uninitialized! */
+ return AAC_DEC_UNSUPPORTED_SAMPLINGRATE;
+ }
+ switch (checkSampleRate) {
case 96000:
case 88200:
case 64000:
case 16000:
case 12000:
- case 11025:
- case 8000:
- case 7350:
+ case 11025:
+ case 8000:
+ case 7350:
case 48000:
case 44100:
case 32000:
@@ -1179,225 +2470,263 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
case 22050:
break;
default:
- if ( ! (self->flags & (AC_USAC|AC_RSVD50)) ) {
+ if (!(self->flags[0] & (AC_USAC | AC_RSVD50 | AC_RSV603DA))) {
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 overlap-add buffers to avoid clicks. */
- FDKmemclear(self->pAacDecoderStaticChannelInfo[ch]->pOverlapBuffer, OverlapBufferSize*sizeof(FIXP_DBL));
- }
+ if (flags & AACDEC_CLRHIST) {
+ if (!(self->flags[0] & AC_USAC)) {
+ int ch;
+ /* Clear history */
+ for (ch = 0; ch < self->aacChannels; ch++) {
+ /* Reset concealment */
+ CConcealment_InitChannelData(
+ &self->pAacDecoderStaticChannelInfo[ch]->concealmentInfo,
+ &self->concealCommonData,
+ self->pAacDecoderChannelInfo[0]->renderMode,
+ self->streamInfo.aacSamplesPerFrame);
+ /* Clear overlap-add buffers to avoid clicks. */
+ FDKmemclear(self->pAacDecoderStaticChannelInfo[ch]->pOverlapBuffer,
+ OverlapBufferSize * sizeof(FIXP_DBL));
+ }
+ if (self->streamInfo.channelConfig > 0) {
+ /* Declare the possibly adopted old PCE (with outdated metadata)
+ * invalid. */
+ CProgramConfig_Init(pce);
+ }
+ }
}
-
-
-#ifdef TP_PCE_ENABLE
- int pceRead = 0; /* Flag indicating a PCE in the current raw_data_block() */
-#endif
-
+ int pceRead = 0; /* Flag indicating a PCE in the current raw_data_block() */
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 )
- {
+ 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 channel_element_count = 0; /* Channel element counter */
+ MP4_ELEMENT_ID
+ channel_elements[(3 * ((8) * 2) + (((8) * 2)) / 2 + 4 * (1) +
+ 1)]; /* Channel elements in bit stream order. */
+ int el_cnt[ID_LAST] = {0}; /* element counter ( robustness ) */
+ int element_count_prev_streams =
+ 0; /* Element count of all previous sub streams. */
+
+ 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
+ if (!(self->flags[0] &
+ (AC_USAC | AC_RSVD50 | AC_RSV603DA | 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 ((self->flags[streamIndex] & (AC_USAC | AC_RSVD50) &&
+ element_count == 0) ||
+ (self->flags[streamIndex] & AC_RSV603DA)) {
+ self->flags[streamIndex] &= ~AC_INDEP;
+ if (FDKreadBit(bs)) {
+ self->flags[streamIndex] |= AC_INDEP;
+ }
+
+ int ch = aacChannels;
+ for (int chIdx = aacChannels; chIdx < self->ascChannels[streamIndex];
+ chIdx++) {
+ {
+ /* Robustness check */
+ if (ch >= self->aacChannels) {
+ return AAC_DEC_UNKNOWN;
+ }
+
+ /* if last frame was broken and this frame is no independent frame,
+ * correct decoding is impossible we need to trigger concealment */
+ if ((CConcealment_GetLastFrameOk(
+ &self->pAacDecoderStaticChannelInfo[ch]->concealmentInfo,
+ 1) == 0) &&
+ !(self->flags[streamIndex] & AC_INDEP)) {
+ self->frameOK = 0;
+ }
+ ch++;
+ }
+ }
+ }
- if ((INT)FDKgetValidBits(bs) < 0)
+ if ((INT)FDKgetValidBits(bs) < 0) {
self->frameOK = 0;
+ }
- switch (type)
- {
+ switch (type) {
case ID_SCE:
case ID_CPE:
case ID_LFE:
+ case ID_USAC_SCE:
+ case ID_USAC_CPE:
+ case ID_USAC_LFE:
+
+ el_channels = CAacDecoder_GetELChannels(
+ type, self->usacStereoConfigIndex[element_count]);
+
/*
Consistency check
- */
-
- if (type == ID_CPE) {
- el_channels = 2;
- } else {
- el_channels = 1;
- }
+ */
+ {
+ int totalAscChannels = 0;
- if ( (el_cnt[type] >= (self->ascChannels>>(el_channels-1))) || (aacChannels > (self->ascChannels-el_channels)) ) {
- ErrorStatus = AAC_DEC_DECODE_FRAME_ERROR;
- self->frameOK = 0;
- break;
+ for (int i = 0; i < (1 * 1); i++) {
+ totalAscChannels += self->ascChannels[i];
+ }
+ if ((el_cnt[type] >= (totalAscChannels >> (el_channels - 1))) ||
+ (aacChannels > (totalAscChannels - el_channels))) {
+ ErrorStatus = AAC_DEC_DECODE_FRAME_ERROR;
+ self->frameOK = 0;
+ break;
+ }
}
- if ( !(self->flags & (AC_USAC|AC_RSVD50)) ) {
+ if (!(self->flags[streamIndex] & (AC_USAC | AC_RSVD50 | AC_RSV603DA))) {
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);
+ 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) {
+ if (self->frameOK) {
+ ErrorStatus = CChannelElement_Read(
+ bs, &self->pAacDecoderChannelInfo[aacChannels],
+ &self->pAacDecoderStaticChannelInfo[aacChannels],
+ self->streamInfo.aot, &self->samplingRateInfo[streamIndex],
+ self->flags[streamIndex], self->elFlags[element_count],
+ self->streamInfo.aacSamplesPerFrame, el_channels,
+ self->streamInfo.epConfig, self->hInput);
+ if (ErrorStatus != AAC_DEC_OK) {
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,
+ 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 {
+ aacChannels, self->chMapping, self->channelType,
+ self->channelIndices, (8), &previous_element_index,
+ self->elements, type)) {
+ channel_elements[channel_element_count++] = type;
+ aacChannels += el_channels;
+ } else {
self->frameOK = 0;
}
/* Create SBR element for SBR for upsampling for LFE elements,
- and if SBR was explicitly signaled, because the first frame(s)
+ and if SBR was implicitly signaled, because the first frame(s)
may not contain SBR payload (broken encoder, bit errors). */
- if ( (self->flags & AC_SBR_PRESENT) || (self->sbrEnabled == 1) )
- {
+ if (self->frameOK &&
+ ((self->flags[streamIndex] & AC_SBR_PRESENT) ||
+ (self->sbrEnabled == 1)) &&
+ !(self->flags[streamIndex] &
+ AC_USAC) /* Is done during explicit config set up */
+ ) {
SBR_ERROR sbrError;
+ UCHAR configMode = 0;
+ UCHAR configChanged = 0;
+ configMode |= AC_CM_ALLOC_MEM;
sbrError = sbrDecoder_InitElement(
- self->hSbrDecoder,
- self->streamInfo.aacSampleRate,
- self->streamInfo.extSamplingRate,
- self->streamInfo.aacSamplesPerFrame,
- self->streamInfo.aot,
- type,
- previous_element_index
- );
+ self->hSbrDecoder, self->streamInfo.aacSampleRate,
+ self->streamInfo.extSamplingRate,
+ self->streamInfo.aacSamplesPerFrame, self->streamInfo.aot, type,
+ previous_element_index, 2, /* Signalize that harmonicSBR shall
+ be ignored in the config change
+ detection */
+ 0, configMode, &configChanged, self->downscaleFactor);
if (sbrError != SBRDEC_OK) {
- /* Do not try to apply SBR because initializing the element failed. */
+ /* Do not try to apply SBR because initializing the element
+ * failed. */
self->sbrEnabled = 0;
}
}
}
el_cnt[type]++;
+ if (self->frameOK && (self->flags[streamIndex] & AC_USAC) &&
+ (type == ID_USAC_CPE || type == ID_USAC_SCE)) {
+ ErrorStatus = aacDecoder_ParseExplicitMpsAndSbr(
+ self, bs, previous_element, previous_element_index, element_count,
+ el_cnt);
+ if (ErrorStatus != AAC_DEC_OK) {
+ self->frameOK = 0;
+ }
+ }
break;
case ID_CCE:
/*
Consistency check
*/
- if ( el_cnt[type] > self->ascChannels ) {
+ if (el_cnt[type] > self->ascChannels[streamIndex]) {
ErrorStatus = AAC_DEC_DECODE_FRAME_ERROR;
self->frameOK = 0;
break;
}
- if (self->frameOK)
- {
+ if (self->frameOK) {
+ CAacDecoderCommonData commonData;
+ CAacDecoderCommonStaticData commonStaticData;
+ CWorkBufferCore1 workBufferCore1;
+ commonStaticData.pWorkBufferCore1 = &workBufferCore1;
/* memory for spectral lines temporal on scratch */
- C_ALLOC_SCRATCH_START(mdctSpec, FIXP_DBL, 1024);
+ C_AALLOC_SCRATCH_START(mdctSpec, FIXP_DBL, 1024);
/* create dummy channel for CCE parsing on stack */
- CAacDecoderChannelInfo tmpAacDecoderChannelInfo, *pTmpAacDecoderChannelInfo;
+ CAacDecoderChannelInfo tmpAacDecoderChannelInfo,
+ *pTmpAacDecoderChannelInfo;
- FDKmemclear(mdctSpec, 1024*sizeof(FIXP_DBL));
+ FDKmemclear(mdctSpec, 1024 * sizeof(FIXP_DBL));
- tmpAacDecoderChannelInfo.pDynData = self->aacCommonData.workBufferCore1->pAacDecoderDynamicData;
- tmpAacDecoderChannelInfo.pComData = &self->aacCommonData;
- tmpAacDecoderChannelInfo.pSpectralCoefficient = (SPECTRAL_PTR)mdctSpec;
+ tmpAacDecoderChannelInfo.pDynData = commonData.pAacDecoderDynamicData;
+ tmpAacDecoderChannelInfo.pComData = &commonData;
+ tmpAacDecoderChannelInfo.pComStaticData = &commonStaticData;
+ tmpAacDecoderChannelInfo.pSpectralCoefficient =
+ (SPECTRAL_PTR)mdctSpec;
/* Assume AAC-LC */
- tmpAacDecoderChannelInfo.granuleLength = self->streamInfo.aacSamplesPerFrame / 8;
-
+ tmpAacDecoderChannelInfo.granuleLength =
+ self->streamInfo.aacSamplesPerFrame / 8;
/* Reset PNS data. */
- CPns_ResetData(&tmpAacDecoderChannelInfo.data.aac.PnsData, &tmpAacDecoderChannelInfo.pComData->pnsInterChannelData);
-
+ 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);
+ ErrorStatus = CChannelElement_Read(
+ bs, &pTmpAacDecoderChannelInfo, NULL, self->streamInfo.aot,
+ &self->samplingRateInfo[streamIndex], self->flags[streamIndex],
+ AC_EL_GA_CCE, self->streamInfo.aacSamplesPerFrame, 1,
+ self->streamInfo.epConfig, self->hInput);
+
+ C_AALLOC_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 */
+ /* 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) )
- {
+ pce, self->streamInfo.channelConfig,
+ pTmpAacDecoderChannelInfo->ElementInstanceTag, 0,
+ self->chMapping, self->channelType, self->channelIndices,
+ (8), &previous_element_index, self->elements, type)) {
/* decoding of CCE not supported */
- }
- else {
+ } else {
self->frameOK = 0;
}
}
@@ -1405,156 +2734,145 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
el_cnt[type]++;
break;
- case ID_DSE:
- {
- UCHAR element_instance_tag;
-
- CDataStreamElement_Read( self,
- bs,
- &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;
- }
- }
- break;
+ case ID_DSE: {
+ UCHAR element_instance_tag;
-#ifdef TP_PCE_ENABLE
- case ID_PCE:
- {
- int result = CProgramConfigElement_Read(
- bs,
- self->hInput,
- pce,
- self->streamInfo.channelConfig,
- auStartAnchor );
- if ( result < 0 ) {
- /* Something went wrong */
- ErrorStatus = AAC_DEC_PARSE_ERROR;
- self->frameOK = 0;
+ CDataStreamElement_Read(self, bs, &element_instance_tag, auStartAnchor);
+
+ if (!CProgramConfig_LookupElement(
+ pce, self->streamInfo.channelConfig, element_instance_tag, 0,
+ self->chMapping, self->channelType, self->channelIndices, (8),
+ &previous_element_index, self->elements, type)) {
+ /* most likely an error in bitstream occured */
+ // self->frameOK = 0;
+ }
+ } break;
+
+ case ID_PCE: {
+ int result = CProgramConfigElement_Read(bs, self->hInput, pce,
+ self->streamInfo.channelConfig,
+ auStartAnchor);
+ if (result < 0) {
+ /* Something went wrong */
+ ErrorStatus = AAC_DEC_PARSE_ERROR;
+ self->frameOK = 0;
+ } else if (result > 1) {
+ /* Built element table */
+ int elIdx = CProgramConfig_GetElementTable(
+ pce, self->elements, (((8)) + (8)), &self->chMapIndex);
+ /* Reset the remaining tabs */
+ for (; elIdx < (3 * ((8) * 2) + (((8) * 2)) / 2 + 4 * (1) + 1);
+ elIdx++) {
+ self->elements[elIdx] = ID_NONE;
}
- else if ( result > 1 ) {
- /* Built element table */
- int elIdx = CProgramConfig_GetElementTable(pce, self->elements, (8), &self->chMapIndex);
- /* Reset the remaining tabs */
- for ( ; elIdx<(8); 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;
- }
+ /* Make new number of channel persistent */
+ self->ascChannels[streamIndex] = pce->NumChannels;
+ /* If PCE is not first element conceal this frame to avoid
+ * inconsistencies */
+ if (element_count != 0) {
+ self->frameOK = 0;
}
- pceRead = (result>=0) ? 1 : 0;
}
- break;
-#endif /* TP_PCE_ENABLE */
+ pceRead = (result >= 0) ? 1 : 0;
+ } break;
- case ID_FIL:
- {
- int bitCnt = FDKreadBits(bs,4); /* bs_count */
+ 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;
- }
+ if (bitCnt == 15) {
+ int esc_count = FDKreadBits(bs, 8); /* bs_esc_count */
+ bitCnt = esc_count + 14;
+ }
- /* Convert to bits */
- bitCnt <<= 3;
+ /* 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;
- }
+ 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;
+ } 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|AC_DRM)) )
- {
- SBR_ERROR err = SBRDEC_OK;
- int elIdx, numChElements = el_cnt[ID_SCE] + el_cnt[ID_CPE];
+ ErrorStatus = aacDecoder_ParseExplicitMpsAndSbr(
+ self, bs, previous_element, previous_element_index, element_count,
+ el_cnt);
+ break;
- 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;
- }
- }
- switch (err) {
- case SBRDEC_PARSE_ERROR:
- /* Can not go on parsing because we do not
- know the length of the SBR extension data. */
- FDKpushFor(bs, bitCnt);
- bitCnt = 0;
- break;
- case SBRDEC_OK:
- self->sbrEnabled = 1;
- break;
- default:
- self->frameOK = 0;
- break;
+ case ID_USAC_EXT: {
+ /* parse extension element payload
+ q.v. rsv603daExtElement() ISO/IEC DIS 23008-3 Table 30
+ or UsacExElement() ISO/IEC FDIS 23003-3:2011(E) Table 21
+ */
+ int usacExtElementPayloadLength;
+ /* int usacExtElementStart, usacExtElementStop; */
+
+ if (FDKreadBit(bs)) { /* usacExtElementPresent */
+ if (FDKreadBit(bs)) { /* usacExtElementUseDefaultLength */
+ usacExtElementPayloadLength =
+ self->pUsacConfig[streamIndex]
+ ->element[element_count - element_count_prev_streams]
+ .extElement.usacExtElementDefaultLength;
+ } else {
+ usacExtElementPayloadLength = FDKreadBits(bs, 8);
+ if (usacExtElementPayloadLength == (UINT)(1 << 8) - 1) {
+ UINT valueAdd = FDKreadBits(bs, 16);
+ usacExtElementPayloadLength += (INT)valueAdd - 2;
}
}
+ if (usacExtElementPayloadLength > 0) {
+ int usacExtBitPos;
+
+ if (self->pUsacConfig[streamIndex]
+ ->element[element_count - element_count_prev_streams]
+ .extElement.usacExtElementPayloadFrag) {
+ /* usacExtElementStart = */ FDKreadBit(bs);
+ /* usacExtElementStop = */ FDKreadBit(bs);
+ } else {
+ /* usacExtElementStart = 1; */
+ /* usacExtElementStop = 1; */
+ }
+ usacExtBitPos = FDKgetValidBits(bs);
- if (self->flags & AC_DRM)
- {
- if ((bitCnt = (INT)FDKgetValidBits(bs)) != 0) {
- FDKpushBiDirectional(bs, bitCnt);
- }
- }
+ USAC_EXT_ELEMENT_TYPE usacExtElementType =
+ self->pUsacConfig[streamIndex]
+ ->element[element_count - element_count_prev_streams]
+ .extElement.usacExtElementType;
- 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;
+ switch (usacExtElementType) {
+ case ID_EXT_ELE_UNI_DRC: /* uniDrcGain() */
+ if (streamIndex == 0) {
+ int drcErr;
+
+ drcErr = FDK_drcDec_ReadUniDrcGain(self->hUniDrcDecoder, bs);
+ if (drcErr != 0) {
+ ErrorStatus = AAC_DEC_PARSE_ERROR;
+ }
+ }
break;
- }
+
+ default:
+ break;
+ }
+
+ /* Skip any remaining bits of extension payload */
+ usacExtBitPos = (usacExtElementPayloadLength * 8) -
+ (usacExtBitPos - FDKgetValidBits(bs));
+ if (usacExtBitPos < 0) {
+ self->frameOK = 0;
+ ErrorStatus = AAC_DEC_PARSE_ERROR;
}
+ FDKpushBiDirectional(bs, usacExtBitPos);
}
}
- break;
-
+ } break;
case ID_END:
+ case ID_USAC_END:
break;
default:
@@ -1566,32 +2884,56 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
previous_element = type;
element_count++;
- } /* while ( (type != ID_END) ... ) */
+ } /* while ( (type != ID_END) ... ) */
- if ( !(flags & (AACDEC_CONCEAL|AACDEC_FLUSH)) )
- {
+ if (!(flags & (AACDEC_CONCEAL | AACDEC_FLUSH))) {
+ /* float decoder checks if bitsLeft is in range 0-7; only prerollAUs are
+ * byteAligned with respect to the first bit */
/* Byte alignment with respect to the first bit of the raw_data_block(). */
- {
+ if (!(self->flags[streamIndex] & (AC_RSVD50 | AC_USAC)) ||
+ (self->prerollAULength[self->accessUnit]) /* indicates preroll */
+ ) {
FDKbyteAlign(bs, auStartAnchor);
}
/* Check if all bits of the raw_data_block() have been read. */
- if ( transportDec_GetAuBitsTotal(self->hInput, 0) > 0 ) {
+ if (transportDec_GetAuBitsTotal(self->hInput, 0) > 0) {
INT unreadBits = transportDec_GetAuBitsRemaining(self->hInput, 0);
- if ( unreadBits != 0 ) {
+ /* for pre-roll frames pre-roll length has to be used instead of total AU
+ * lenght */
+ /* unreadBits regarding preroll bounds */
+ if (self->prerollAULength[self->accessUnit]) {
+ unreadBits = unreadBits - transportDec_GetAuBitsTotal(self->hInput, 0) +
+ (INT)self->prerollAULength[self->accessUnit];
+ }
+ if (((self->flags[streamIndex] & (AC_RSVD50 | AC_USAC)) &&
+ ((unreadBits < 0) || (unreadBits > 7)) &&
+ !(self->prerollAULength[self->accessUnit])) ||
+ ((!(self->flags[streamIndex] & (AC_RSVD50 | AC_USAC)) ||
+ (self->prerollAULength[self->accessUnit])) &&
+ (unreadBits != 0))) {
+ if ((((unreadBits < 0) || (unreadBits > 7)) && self->frameOK) &&
+ ((transportDec_GetFormat(self->hInput) == TT_DRM) &&
+ (self->flags[streamIndex] & AC_USAC))) {
+ /* Set frame OK because of fill bits. */
+ self->frameOK = 1;
+ } else {
+ self->frameOK = 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. */
+ /* 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 ) {
+ /* 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;
@@ -1600,219 +2942,479 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
}
}
- /* 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;
+ if (!(flags & (AACDEC_CONCEAL | AACDEC_FLUSH)) && self->frameOK) {
+ channel_elements[channel_element_count++] = ID_END;
+ }
+ element_count = 0;
+ aacChannels = 0;
+ type = ID_NONE;
+ previous_element_index = 0;
+
+ while (type != ID_END &&
+ element_count < (3 * ((8) * 2) + (((8) * 2)) / 2 + 4 * (1) + 1)) {
+ int el_channels;
+
+ if ((flags & (AACDEC_CONCEAL | AACDEC_FLUSH)) || !self->frameOK) {
+ channel_elements[element_count] = self->elements[element_count];
+ if (channel_elements[element_count] == ID_NONE) {
+ channel_elements[element_count] = ID_END;
}
- self->frameOK = 0;
}
- aacChannels = 0;
+
+ if (self->flags[streamIndex] & (AC_USAC | AC_RSV603DA | AC_BSAC)) {
+ type = self->elements[element_count];
+ } else {
+ type = channel_elements[element_count];
+ }
+
+ if (!(flags & (AACDEC_CONCEAL | AACDEC_FLUSH)) && self->frameOK) {
+ switch (type) {
+ case ID_SCE:
+ case ID_CPE:
+ case ID_LFE:
+ case ID_USAC_SCE:
+ case ID_USAC_CPE:
+ case ID_USAC_LFE:
+
+ el_channels = CAacDecoder_GetELChannels(
+ type, self->usacStereoConfigIndex[element_count]);
+
+ if (!hdaacDecoded) {
+ if (self->pAacDecoderStaticChannelInfo[aacChannels]
+ ->pCpeStaticData != NULL) {
+ self->pAacDecoderStaticChannelInfo[aacChannels]
+ ->pCpeStaticData->jointStereoPersistentData.scratchBuffer =
+ (FIXP_DBL *)pTimeData;
+ }
+ CChannelElement_Decode(
+ &self->pAacDecoderChannelInfo[aacChannels],
+ &self->pAacDecoderStaticChannelInfo[aacChannels],
+ &self->samplingRateInfo[streamIndex], self->flags[streamIndex],
+ self->elFlags[element_count], el_channels);
+ }
+ aacChannels += el_channels;
+ break;
+ case ID_NONE:
+ type = ID_END;
+ break;
+ default:
+ break;
+ }
+ }
+ element_count++;
}
- else if ( aacChannels > self->ascChannels ) {
+
+ /* 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_UNSUPPORTED_FORMAT;
+ ErrorStatus = AAC_DEC_DECODE_FRAME_ERROR;
}
self->frameOK = 0;
aacChannels = 0;
}
- if ( TRANSPORTDEC_OK != transportDec_CrcCheck(self->hInput) )
- {
- self->frameOK=0;
+ if (TRANSPORTDEC_OK != transportDec_CrcCheck(self->hInput)) {
+ ErrorStatus = AAC_DEC_CRC_ERROR;
+ self->frameOK = 0;
+ }
+
+ /* Ensure that in case of concealment a proper error status is set. */
+ if ((self->frameOK == 0) && (ErrorStatus == AAC_DEC_OK)) {
+ ErrorStatus = AAC_DEC_DECODE_FRAME_ERROR;
}
- /* store or restore the number of channels and the corresponding info */
- if ( self->frameOK && !(flags &(AACDEC_CONCEAL|AACDEC_FLUSH)) ) {
- self->aacChannelsPrev = aacChannels; /* store */
- FDKmemcpy(self->channelTypePrev, self->channelType, (8)*sizeof(AUDIO_CHANNEL_TYPE)); /* store */
- FDKmemcpy(self->channelIndicesPrev, self->channelIndices, (8)*sizeof(UCHAR)); /* store */
- self->sbrEnabledPrev = self->sbrEnabled;
+ if (self->frameOK && (flags & AACDEC_FLUSH)) {
+ aacChannels = self->aacChannelsPrev;
+ /* Because the downmix could be active, its necessary to restore the channel
+ * type and indices. */
+ FDKmemcpy(self->channelType, self->channelTypePrev,
+ (8) * sizeof(AUDIO_CHANNEL_TYPE)); /* restore */
+ FDKmemcpy(self->channelIndices, self->channelIndicesPrev,
+ (8) * sizeof(UCHAR)); /* restore */
+ self->sbrEnabled = self->sbrEnabledPrev;
} else {
- if (self->aacChannels > 0) {
- aacChannels = self->aacChannelsPrev; /* restore */
- FDKmemcpy(self->channelType, self->channelTypePrev, (8)*sizeof(AUDIO_CHANNEL_TYPE)); /* restore */
- FDKmemcpy(self->channelIndices, self->channelIndicesPrev, (8)*sizeof(UCHAR)); /* restore */
- self->sbrEnabled = self->sbrEnabledPrev;
- }
+ /* store or restore the number of channels and the corresponding info */
+ if (self->frameOK && !(flags & AACDEC_CONCEAL)) {
+ self->aacChannelsPrev = aacChannels; /* store */
+ FDKmemcpy(self->channelTypePrev, self->channelType,
+ (8) * sizeof(AUDIO_CHANNEL_TYPE)); /* store */
+ FDKmemcpy(self->channelIndicesPrev, self->channelIndices,
+ (8) * sizeof(UCHAR)); /* store */
+ self->sbrEnabledPrev = self->sbrEnabled;
+ } else {
+ if (self->aacChannels > 0) {
+ if ((self->buildUpStatus == AACDEC_RSV60_BUILD_UP_ON) ||
+ (self->buildUpStatus == AACDEC_RSV60_BUILD_UP_ON_IN_BAND) ||
+ (self->buildUpStatus == AACDEC_USAC_BUILD_UP_ON)) {
+ aacChannels = self->aacChannels;
+ self->aacChannelsPrev = aacChannels; /* store */
+ } else {
+ aacChannels = self->aacChannelsPrev; /* restore */
+ }
+ FDKmemcpy(self->channelType, self->channelTypePrev,
+ (8) * sizeof(AUDIO_CHANNEL_TYPE)); /* restore */
+ FDKmemcpy(self->channelIndices, self->channelIndicesPrev,
+ (8) * sizeof(UCHAR)); /* restore */
+ self->sbrEnabled = self->sbrEnabledPrev;
+ }
+ }
}
/* Update number of output channels */
self->streamInfo.aacNumChannels = aacChannels;
- #ifdef TP_PCE_ENABLE
+ /* Ensure consistency of IS_OUTPUT_VALID() macro. */
+ if (aacChannels == 0) {
+ ErrorStatus = AAC_DEC_UNKNOWN;
+ }
+
if (pceRead == 1 && CProgramConfig_IsValid(pce)) {
/* Set matrix mixdown infos if available from PCE. */
- pcmDmx_SetMatrixMixdownFromPce ( self->hPcmUtils,
- pce->MatrixMixdownIndexPresent,
- pce->MatrixMixdownIndex,
- pce->PseudoSurroundEnable );
+ 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) ) {
+ if (!IS_OUTPUT_VALID(ErrorStatus)) {
return ErrorStatus;
}
- /* Setup the output channel mapping. The table below shows the four possibilities:
- * # | chCfg | PCE | cChCfg | chOutMapIdx
- * ---+-------+-----+--------+------------------
- * 1 | > 0 | no | - | chCfg
- * 2 | 0 | yes | > 0 | cChCfg
- * 3 | 0 | yes | 0 | aacChannels || 0
- * 4 | 0 | no | - | aacChannels || 0
+ /* Setup the output channel mapping. The table below shows the three
+ * possibilities: # | chCfg | PCE | chMapIndex
+ * ---+-------+-----+------------------
+ * 1 | > 0 | no | chCfg
+ * 2 | 0 | yes | cChCfg
+ * 3 | 0 | no | aacChannels || 0
* ---+-------+-----+--------+------------------
- * Where chCfg is the channel configuration index from ASC and cChCfg is a corresponding chCfg
- * derived from a given PCE. The variable aacChannels represents the number of channel found
- * during bitstream decoding. Due to the structure of the mapping table it can only be used for
- * mapping if its value is smaller than 7. Otherwise we use the fallback (0) which is a simple
- * pass-through. The possibility #4 should appear only with MPEG-2 (ADTS) streams. This is
- * mode is called "implicit channel mapping".
+ * Where chCfg is the channel configuration index from ASC and cChCfg is a
+ * corresponding chCfg derived from a given PCE. The variable aacChannels
+ * represents the number of channel found during bitstream decoding. Due to
+ * the structure of the mapping table it can only be used for mapping if its
+ * value is smaller than 7. Otherwise we use the fallback (0) which is a
+ * simple pass-through. The possibility #3 should appear only with MPEG-2
+ * (ADTS) streams. This is mode is called "implicit channel mapping".
*/
- chOutMapIdx = ((self->chMapIndex==0) && (aacChannels<7)) ? aacChannels : self->chMapIndex;
+ if ((self->streamInfo.channelConfig == 0) && !pce->isValid) {
+ self->chMapIndex = (aacChannels < 7) ? aacChannels : 0;
+ }
/*
Inverse transform
*/
{
- int stride, offset, c;
-
- /* Turn on/off DRC modules level normalization in digital domain depending on the limiter status. */
- aacDecoder_drcSetParam( self->hDrcInfo, APPLY_NORMALIZATION, (self->limiterEnableCurr) ? 0 : 1 );
- /* 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;
+ int c, cIdx;
+ int mapped, fCopyChMap = 1;
+ UCHAR drcChMap[(8)];
+
+ if ((self->streamInfo.channelConfig == 0) && CProgramConfig_IsValid(pce)) {
+ /* ISO/IEC 14496-3 says:
+ If a PCE is present, the exclude_mask bits correspond to the audio
+ channels in the SCE, CPE, CCE and LFE syntax elements in the order of
+ their appearance in the PCE. In the case of a CPE, the first
+ transmitted mask bit corresponds to the first channel in the CPE, the
+ second transmitted mask bit to the second channel. In the case of a
+ CCE, a mask bit is transmitted only if the coupling channel is
+ specified to be an independently switched coupling channel. Thus we
+ have to convert the internal channel mapping from "canonical" MPEG to
+ PCE order: */
+ UCHAR tmpChMap[(8)];
+ if (CProgramConfig_GetPceChMap(pce, tmpChMap, (8)) == 0) {
+ for (c = 0; c < aacChannels; c += 1) {
+ drcChMap[c] =
+ (self->chMapping[c] == 255) ? 255 : tmpChMap[self->chMapping[c]];
+ }
+ fCopyChMap = 0;
+ }
+ }
+ if (fCopyChMap != 0) {
+ FDKmemcpy(drcChMap, self->chMapping, (8) * sizeof(UCHAR));
+ }
- /* Select correct pAacDecoderChannelInfo for current channel */
- if (self->chMapping[c] >= aacChannels) {
- pAacDecoderChannelInfo = self->pAacDecoderChannelInfo[c];
- } else {
- pAacDecoderChannelInfo = self->pAacDecoderChannelInfo[self->chMapping[c]];
+ /* Turn on/off DRC modules level normalization in digital domain depending
+ * on the limiter status. */
+ aacDecoder_drcSetParam(self->hDrcInfo, APPLY_NORMALIZATION,
+ (self->limiterEnableCurr) ? 0 : 1);
+
+ /* deactivate legacy DRC in case uniDrc is active, i.e. uniDrc payload is
+ * present and one of DRC or Loudness Normalization is switched on */
+ aacDecoder_drcSetParam(
+ self->hDrcInfo, UNIDRC_PRECEDENCE,
+ FDK_drcDec_GetParam(self->hUniDrcDecoder, DRC_DEC_IS_ACTIVE));
+
+ /* Extract DRC control data and map it to channels (without bitstream delay)
+ */
+ mapped = aacDecoder_drcProlog(
+ self->hDrcInfo, bs, self->pAacDecoderStaticChannelInfo,
+ pce->ElementInstanceTag, drcChMap, aacChannels);
+ if (mapped > 0) {
+ /* If at least one DRC thread has been mapped to a channel threre was DRC
+ * data in the bitstream. */
+ self->flags[streamIndex] |= AC_DRC_PRESENT;
+ }
+
+ /* Create a reverse mapping table */
+ UCHAR Reverse_chMapping[((8) * 2)];
+ for (c = 0; c < aacChannels; c++) {
+ int d;
+ for (d = 0; d < aacChannels - 1; d++) {
+ if (self->chMapping[d] == c) {
+ break;
+ }
}
+ Reverse_chMapping[c] = d;
+ }
- /* Setup offset and stride for time buffer traversal. */
- if (interleaved) {
- stride = aacChannels;
- offset = self->channelOutputMapping[chOutMapIdx][c];
+ int el;
+ int el_channels;
+ c = 0;
+ cIdx = 0;
+ el_channels = 0;
+ for (el = 0; el < element_count; el++) {
+ int frameOk_butConceal =
+ 0; /* Force frame concealment during mute release active state. */
+ int concealApplyReturnCode;
+
+ if (self->flags[streamIndex] & (AC_USAC | AC_RSV603DA | AC_BSAC)) {
+ type = self->elements[el];
} else {
- stride = 1;
- offset = self->channelOutputMapping[chOutMapIdx][c] * self->streamInfo.aacSamplesPerFrame;
- }
-
-
- if ( flags&AACDEC_FLUSH ) {
- /* Clear pAacDecoderChannelInfo->pSpectralCoefficient because with AACDEC_FLUSH set it contains undefined data. */
- FDKmemclear(pAacDecoderChannelInfo->pSpectralCoefficient, sizeof(FIXP_DBL)*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 );
- }
- /* The DRC module demands to be called with the gain field holding the gain scale. */
- self->extGain[0] = (FIXP_DBL)TDL_GAIN_SCALING;
- /* DRC processing */
- aacDecoder_drcApply (
- self->hDrcInfo,
- self->hSbrDecoder,
- pAacDecoderChannelInfo,
- &self->pAacDecoderStaticChannelInfo[c]->drcData,
- self->extGain,
- c,
- self->streamInfo.aacSamplesPerFrame,
- self->sbrEnabled
- );
+ type = channel_elements[el];
+ }
- 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
- );
- self->extGainDelay = self->streamInfo.aacSamplesPerFrame;
- break;
- case AACDEC_RENDER_ELDFB:
- CBlock_FrequencyToTimeLowDelay(
- self->pAacDecoderStaticChannelInfo[c],
- pAacDecoderChannelInfo,
- pTimeData + offset,
- self->streamInfo.aacSamplesPerFrame,
- stride
- );
- self->extGainDelay = (self->streamInfo.aacSamplesPerFrame*2 - self->streamInfo.aacSamplesPerFrame/2 - 1)/2;
- break;
- default:
- ErrorStatus = AAC_DEC_UNKNOWN;
- break;
+ int nElementChannels;
+
+ nElementChannels =
+ CAacDecoder_GetELChannels(type, self->usacStereoConfigIndex[el]);
+
+ el_channels += nElementChannels;
+
+ if (nElementChannels == 0) {
+ continue;
+ }
}
- if ( flags&AACDEC_FLUSH ) {
- FDKmemclear(pAacDecoderChannelInfo->pSpectralCoefficient, sizeof(FIXP_DBL)*self->streamInfo.aacSamplesPerFrame);
- FDKmemclear(self->pAacDecoderStaticChannelInfo[c]->pOverlapBuffer, OverlapBufferSize*sizeof(FIXP_DBL));
+
+ int offset;
+ int elCh = 0;
+ /* "c" iterates in canonical MPEG channel order */
+ for (; cIdx < el_channels; c++, cIdx++, elCh++) {
+ /* Robustness check */
+ if (c >= aacChannels) {
+ return AAC_DEC_UNKNOWN;
+ }
+
+ CAacDecoderChannelInfo *pAacDecoderChannelInfo =
+ self->pAacDecoderChannelInfo[c];
+ CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo =
+ self->pAacDecoderStaticChannelInfo[c];
+
+ /* Setup offset for time buffer traversal. */
+ {
+ pAacDecoderStaticChannelInfo =
+ self->pAacDecoderStaticChannelInfo[Reverse_chMapping[c]];
+ offset =
+ FDK_chMapDescr_getMapValue(
+ &self->mapDescr, Reverse_chMapping[cIdx], self->chMapIndex) *
+ timeDataChannelOffset;
+ }
+
+ if (flags & AACDEC_FLUSH) {
+ /* Clear pAacDecoderChannelInfo->pSpectralCoefficient because with
+ * AACDEC_FLUSH set it contains undefined data. */
+ FDKmemclear(pAacDecoderChannelInfo->pSpectralCoefficient,
+ sizeof(FIXP_DBL) * self->streamInfo.aacSamplesPerFrame);
+ }
+
+ /* if The ics info is not valid and it will be stored and used in the
+ * following concealment method, mark the frame as erroneous */
+ {
+ CIcsInfo *pIcsInfo = &pAacDecoderChannelInfo->icsInfo;
+ CConcealmentInfo *hConcealmentInfo =
+ &pAacDecoderStaticChannelInfo->concealmentInfo;
+ const int mute_release_active =
+ (self->frameOK && !(flags & AACDEC_CONCEAL)) &&
+ ((hConcealmentInfo->concealState >= ConcealState_Mute) &&
+ (hConcealmentInfo->cntValidFrames + 1 <=
+ hConcealmentInfo->pConcealParams->numMuteReleaseFrames));
+ const int icsIsInvalid = (GetScaleFactorBandsTransmitted(pIcsInfo) >
+ GetScaleFactorBandsTotal(pIcsInfo));
+ const int icsInfoUsedinFadeOut =
+ !(pAacDecoderChannelInfo->renderMode == AACDEC_RENDER_LPD &&
+ pAacDecoderStaticChannelInfo->last_lpd_mode == 0);
+ if (icsInfoUsedinFadeOut && icsIsInvalid && !mute_release_active) {
+ self->frameOK = 0;
+ }
+ }
+
+ /*
+ Conceal defective spectral data
+ */
+ {
+ CAacDecoderChannelInfo **ppAacDecoderChannelInfo =
+ &pAacDecoderChannelInfo;
+ CAacDecoderStaticChannelInfo **ppAacDecoderStaticChannelInfo =
+ &pAacDecoderStaticChannelInfo;
+ {
+ concealApplyReturnCode = CConcealment_Apply(
+ &(*ppAacDecoderStaticChannelInfo)->concealmentInfo,
+ *ppAacDecoderChannelInfo, *ppAacDecoderStaticChannelInfo,
+ &self->samplingRateInfo[streamIndex],
+ self->streamInfo.aacSamplesPerFrame,
+ pAacDecoderStaticChannelInfo->last_lpd_mode,
+ (self->frameOK && !(flags & AACDEC_CONCEAL)),
+ self->flags[streamIndex]);
+ }
+ }
+ if (concealApplyReturnCode == -1) {
+ frameOk_butConceal = 1;
+ }
+
+ if (flags & (AACDEC_INTR)) {
+ /* Reset DRC control data for this channel */
+ aacDecoder_drcInitChannelData(&pAacDecoderStaticChannelInfo->drcData);
+ }
+ if (flags & (AACDEC_CLRHIST)) {
+ if (!(self->flags[0] & AC_USAC)) {
+ /* Reset DRC control data for this channel */
+ aacDecoder_drcInitChannelData(
+ &pAacDecoderStaticChannelInfo->drcData);
+ }
+ }
+ /* The DRC module demands to be called with the gain field holding the
+ * gain scale. */
+ self->extGain[0] = (FIXP_DBL)TDL_GAIN_SCALING;
+ /* DRC processing */
+ aacDecoder_drcApply(
+ self->hDrcInfo, self->hSbrDecoder, pAacDecoderChannelInfo,
+ &pAacDecoderStaticChannelInfo->drcData, self->extGain, c,
+ self->streamInfo.aacSamplesPerFrame, self->sbrEnabled
+
+ );
+
+ if (timeDataSize < timeDataChannelOffset * self->aacChannels) {
+ ErrorStatus = AAC_DEC_OUTPUT_BUFFER_TOO_SMALL;
+ break;
+ }
+ if (self->flushStatus && (self->flushCnt > 0) &&
+ !(flags & AACDEC_CONCEAL)) {
+ FDKmemclear(pTimeData + offset,
+ sizeof(FIXP_PCM) * self->streamInfo.aacSamplesPerFrame);
+ } else
+ switch (pAacDecoderChannelInfo->renderMode) {
+ case AACDEC_RENDER_IMDCT:
+
+ CBlock_FrequencyToTime(
+ pAacDecoderStaticChannelInfo, pAacDecoderChannelInfo,
+ pTimeData + offset, self->streamInfo.aacSamplesPerFrame,
+ (self->frameOK && !(flags & AACDEC_CONCEAL) &&
+ !frameOk_butConceal),
+ pAacDecoderChannelInfo->pComStaticData->pWorkBufferCore1
+ ->mdctOutTemp,
+ self->elFlags[el], elCh);
+
+ self->extGainDelay = self->streamInfo.aacSamplesPerFrame;
+ break;
+ case AACDEC_RENDER_ELDFB: {
+ CBlock_FrequencyToTimeLowDelay(
+ pAacDecoderStaticChannelInfo, pAacDecoderChannelInfo,
+ pTimeData + offset, self->streamInfo.aacSamplesPerFrame);
+ self->extGainDelay =
+ (self->streamInfo.aacSamplesPerFrame * 2 -
+ self->streamInfo.aacSamplesPerFrame / 2 - 1) /
+ 2;
+ } break;
+ case AACDEC_RENDER_LPD:
+
+ CLpd_RenderTimeSignal(
+ pAacDecoderStaticChannelInfo, pAacDecoderChannelInfo,
+ pTimeData + offset, self->streamInfo.aacSamplesPerFrame,
+ &self->samplingRateInfo[streamIndex],
+ (self->frameOK && !(flags & AACDEC_CONCEAL) &&
+ !frameOk_butConceal),
+ flags, self->flags[streamIndex]);
+
+ self->extGainDelay = self->streamInfo.aacSamplesPerFrame;
+ break;
+ default:
+ ErrorStatus = AAC_DEC_UNKNOWN;
+ break;
+ }
+ /* TimeDomainFading */
+ if (!CConceal_TDFading_Applied[c]) {
+ CConceal_TDFading_Applied[c] = CConcealment_TDFading(
+ self->streamInfo.aacSamplesPerFrame,
+ &self->pAacDecoderStaticChannelInfo[c], pTimeData + offset, 0);
+ if (c + 1 < (8) && c < aacChannels - 1) {
+ /* update next TDNoise Seed to avoid muting in case of Parametric
+ * Stereo */
+ self->pAacDecoderStaticChannelInfo[c + 1]
+ ->concealmentInfo.TDNoiseSeed =
+ self->pAacDecoderStaticChannelInfo[c]
+ ->concealmentInfo.TDNoiseSeed;
+ }
+ }
}
}
+ if (self->flags[streamIndex] & AC_USAC) {
+ int bsPseudoLr = 0;
+ mpegSurroundDecoder_IsPseudoLR(
+ (CMpegSurroundDecoder *)self->pMpegSurroundDecoder, &bsPseudoLr);
+ /* ISO/IEC 23003-3, 7.11.2.6 Modification of core decoder output (pseudo
+ * LR) */
+ if ((aacChannels == 2) && bsPseudoLr) {
+ int i, offset2;
+ const FIXP_SGL invSqrt2 = FL2FXCONST_SGL(0.707106781186547f);
+ FIXP_PCM *pTD = pTimeData;
+
+ offset2 = timeDataChannelOffset;
+
+ for (i = 0; i < self->streamInfo.aacSamplesPerFrame; i++) {
+ FIXP_DBL L = FX_PCM2FX_DBL(pTD[0]);
+ FIXP_DBL R = FX_PCM2FX_DBL(pTD[offset2]);
+ L = fMult(L, invSqrt2);
+ R = fMult(R, invSqrt2);
+#if (SAMPLE_BITS == 16)
+ pTD[0] = FX_DBL2FX_PCM(fAddSaturate(L + R, (FIXP_DBL)0x8000));
+ pTD[offset2] = FX_DBL2FX_PCM(fAddSaturate(L - R, (FIXP_DBL)0x8000));
+#else
+ pTD[0] = FX_DBL2FX_PCM(L + R);
+ pTD[offset2] = FX_DBL2FX_PCM(L - R);
+#endif
+ pTD++;
+ }
+ }
+ }
/* 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
- );
+ mapped = aacDecoder_drcEpilog(
+ self->hDrcInfo, bs, self->pAacDecoderStaticChannelInfo,
+ pce->ElementInstanceTag, drcChMap, aacChannels);
+ if (mapped > 0) {
+ /* If at least one DRC thread has been mapped to a channel threre was DRC
+ * data in the bitstream. */
+ self->flags[streamIndex] |= AC_DRC_PRESENT;
+ }
}
/* Add additional concealment delay */
- self->streamInfo.outputDelay += CConcealment_GetDelay(&self->concealCommonData) * self->streamInfo.aacSamplesPerFrame;
+ self->streamInfo.outputDelay +=
+ CConcealment_GetDelay(&self->concealCommonData) *
+ self->streamInfo.aacSamplesPerFrame;
/* Map DRC data to StreamInfo structure */
- aacDecoder_drcGetInfo (
- self->hDrcInfo,
- &self->streamInfo.drcPresMode,
- &self->streamInfo.drcProgRefLev
- );
+ aacDecoder_drcGetInfo(self->hDrcInfo, &self->streamInfo.drcPresMode,
+ &self->streamInfo.drcProgRefLev);
/* Reorder channel type information tables. */
- {
+ if (!(self->flags[0] & AC_RSV603DA)) {
AUDIO_CHANNEL_TYPE types[(8)];
UCHAR idx[(8)];
int c;
+ int mapValue;
FDK_ASSERT(sizeof(self->channelType) == sizeof(types));
FDK_ASSERT(sizeof(self->channelIndices) == sizeof(idx));
@@ -1820,9 +3422,11 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
FDKmemcpy(types, self->channelType, sizeof(types));
FDKmemcpy(idx, self->channelIndices, sizeof(idx));
- for (c=0; c<aacChannels; c++) {
- self->channelType[self->channelOutputMapping[chOutMapIdx][c]] = types[c];
- self->channelIndices[self->channelOutputMapping[chOutMapIdx][c]] = idx[c];
+ for (c = 0; c < aacChannels; c++) {
+ mapValue =
+ FDK_chMapDescr_getMapValue(&self->mapDescr, c, self->chMapIndex);
+ self->channelType[mapValue] = types[c];
+ self->channelIndices[mapValue] = idx[c];
}
}
@@ -1838,14 +3442,9 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
\return pointer to the struct
*/
-LINKSPEC_CPP CStreamInfo* CAacDecoder_GetStreamInfo ( HANDLE_AACDECODER self )
-{
+LINKSPEC_CPP CStreamInfo *CAacDecoder_GetStreamInfo(HANDLE_AACDECODER self) {
if (!self) {
return NULL;
}
return &self->streamInfo;
}
-
-
-
-