2018-02-26 20:17:00 +01:00
|
|
|
/* -----------------------------------------------------------------------------
|
2012-07-11 19:15:24 +02:00
|
|
|
Software License for The Fraunhofer FDK AAC Codec Library for Android
|
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten
|
|
|
|
Forschung e.V. All rights reserved.
|
2012-07-11 19:15:24 +02:00
|
|
|
|
|
|
|
1. INTRODUCTION
|
2018-02-26 20:17:00 +01:00
|
|
|
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.
|
2012-07-11 19:15:24 +02:00
|
|
|
|
|
|
|
2. COPYRIGHT LICENSE
|
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
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:
|
2012-07-11 19:15:24 +02:00
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
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.
|
2012-07-11 19:15:24 +02:00
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
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
|
2012-07-11 19:15:24 +02:00
|
|
|
modifications thereto to recipients of copies in binary form.
|
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
The name of Fraunhofer may not be used to endorse or promote products derived
|
|
|
|
from this library without prior written permission.
|
2012-07-11 19:15:24 +02:00
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
You may not charge copyright license fees for anyone to use, copy or distribute
|
|
|
|
the FDK AAC Codec software or your modifications thereto.
|
2012-07-11 19:15:24 +02:00
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
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."
|
2012-07-11 19:15:24 +02:00
|
|
|
|
|
|
|
3. NO PATENT LICENSE
|
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
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.
|
2012-07-11 19:15:24 +02:00
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
You may use this FDK AAC Codec software or modifications thereto only for
|
|
|
|
purposes that are authorized by appropriate patent licenses.
|
2012-07-11 19:15:24 +02:00
|
|
|
|
|
|
|
4. DISCLAIMER
|
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
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.
|
2012-07-11 19:15:24 +02:00
|
|
|
|
|
|
|
5. CONTACT INFORMATION
|
|
|
|
|
|
|
|
Fraunhofer Institute for Integrated Circuits IIS
|
|
|
|
Attention: Audio and Multimedia Departments - FDK AAC LL
|
|
|
|
Am Wolfsmantel 33
|
|
|
|
91058 Erlangen, Germany
|
|
|
|
|
|
|
|
www.iis.fraunhofer.de/amm
|
|
|
|
amm-info@iis.fraunhofer.de
|
2018-02-26 20:17:00 +01:00
|
|
|
----------------------------------------------------------------------------- */
|
2012-07-11 19:15:24 +02:00
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
/**************************** AAC decoder library ******************************
|
2012-07-11 19:15:24 +02:00
|
|
|
|
|
|
|
Author(s): Josef Hoepfl
|
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
Description:
|
2012-07-11 19:15:24 +02:00
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
*******************************************************************************/
|
2012-07-11 19:15:24 +02:00
|
|
|
|
|
|
|
/*!
|
|
|
|
\page default General Overview of the AAC Decoder Implementation
|
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
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.
|
2012-07-11 19:15:24 +02:00
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
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.
|
2012-07-11 19:15:24 +02:00
|
|
|
|
|
|
|
<h2>1 Bitstream deformatter</h2>
|
2018-02-26 20:17:00 +01:00
|
|
|
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().
|
2012-07-11 19:15:24 +02:00
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
The bitstream deformatter also includes many bitfield operations. Profiling on
|
|
|
|
the target will determine required optimizations.
|
2012-07-11 19:15:24 +02:00
|
|
|
|
|
|
|
<h2>2 Actual decoding to retain the time domain output</h2>
|
2018-02-26 20:17:00 +01:00
|
|
|
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.
|
2012-07-11 19:15:24 +02:00
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
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,
|
2012-07-11 19:15:24 +02:00
|
|
|
|
|
|
|
<h3>2.1 Stereo processing for CPE elements</h3>
|
2018-02-26 20:17:00 +01:00
|
|
|
CChannelPairElement_Decode() first calles the joint stereo tools in
|
|
|
|
stereo.cpp when required.
|
2012-07-11 19:15:24 +02:00
|
|
|
|
|
|
|
<h3>2.2 Scaling of spectral data</h3>
|
|
|
|
CBlock_ScaleSpectralData().
|
|
|
|
|
|
|
|
<h3>2.3 Apply additional coding tools</h3>
|
2018-02-26 20:17:00 +01:00
|
|
|
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.
|
2012-07-11 19:15:24 +02:00
|
|
|
|
|
|
|
<h2>3 Frequency-To-Time conversion</h3>
|
2018-02-26 20:17:00 +01:00
|
|
|
The filterbank is called using CBlock_FrequencyToTime() using the MDCT module
|
|
|
|
from the FDK Tools
|
2012-07-11 19:15:24 +02:00
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "aacdecoder.h"
|
|
|
|
|
|
|
|
#include "aac_rom.h"
|
|
|
|
#include "aac_ram.h"
|
|
|
|
#include "channel.h"
|
|
|
|
#include "FDK_audio.h"
|
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
#include "aacdec_pns.h"
|
2012-07-11 19:15:24 +02:00
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
#include "sbrdecoder.h"
|
2012-07-11 19:15:24 +02:00
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
#include "sac_dec_lib.h"
|
2012-07-11 19:15:24 +02:00
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
#include "aacdec_hcr.h"
|
|
|
|
#include "rvlc.h"
|
2012-07-11 19:15:24 +02:00
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
#include "usacdec_lpd.h"
|
2012-07-11 19:15:24 +02:00
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
#include "ac_arith_coder.h"
|
2012-07-11 19:15:24 +02:00
|
|
|
|
|
|
|
#include "tpdec_lib.h"
|
|
|
|
|
|
|
|
#include "conceal.h"
|
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
#include "FDK_crc.h"
|
|
|
|
#define PS_IS_EXPLICITLY_DISABLED(aot, flags) \
|
|
|
|
(((aot) == AOT_DRM_AAC) && !(flags & AC_PS_PRESENT))
|
2012-07-11 19:15:24 +02:00
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
#define IS_STEREO_SBR(el_id, stereoConfigIndex) \
|
|
|
|
(((el_id) == ID_USAC_CPE && (stereoConfigIndex) == 0) || \
|
|
|
|
((el_id) == ID_USAC_CPE && (stereoConfigIndex) == 3))
|
2012-07-11 19:15:24 +02:00
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
void CAacDecoder_SyncQmfMode(HANDLE_AACDECODER self) {
|
|
|
|
FDK_ASSERT(
|
|
|
|
!((self->flags[0] & AC_MPS_PRESENT) && (self->flags[0] & AC_PS_PRESENT)));
|
2012-07-11 19:15:24 +02:00
|
|
|
|
|
|
|
/* Assign user requested mode */
|
|
|
|
self->qmfModeCurr = self->qmfModeUser;
|
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
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))))) {
|
2012-07-11 19:15:24 +02:00
|
|
|
self->qmfModeCurr = MODE_HQ;
|
|
|
|
} else {
|
|
|
|
self->qmfModeCurr = MODE_LP;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
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;
|
|
|
|
}
|
2018-10-19 16:37:31 +02:00
|
|
|
}
|
|
|
|
FDK_FALLTHROUGH;
|
2018-02-26 20:17:00 +01:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-07-11 19:15:24 +02:00
|
|
|
|
|
|
|
/* Set SBR to current QMF mode. Error does not matter. */
|
2018-02-26 20:17:00 +01:00
|
|
|
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));
|
2012-07-11 19:15:24 +02:00
|
|
|
}
|
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
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;
|
2012-07-11 19:15:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
\brief Reset ancillary data struct. Call before parsing a new frame.
|
|
|
|
|
|
|
|
\ancData Pointer to ancillary data structure
|
|
|
|
|
|
|
|
\return Error code
|
|
|
|
*/
|
2018-02-26 20:17:00 +01:00
|
|
|
static AAC_DECODER_ERROR CAacDecoder_AncDataReset(CAncData *ancData) {
|
2012-07-11 19:15:24 +02:00
|
|
|
int i;
|
2018-02-26 20:17:00 +01:00
|
|
|
for (i = 0; i < 8; i++) {
|
2012-07-11 19:15:24 +02:00
|
|
|
ancData->offset[i] = 0;
|
|
|
|
}
|
|
|
|
ancData->nrElements = 0;
|
|
|
|
|
|
|
|
return AAC_DEC_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
\brief Initialize ancillary buffer
|
|
|
|
|
|
|
|
\ancData Pointer to ancillary data structure
|
|
|
|
\buffer Pointer to (external) anc data buffer
|
|
|
|
\size Size of the buffer pointed on by buffer in bytes
|
|
|
|
|
|
|
|
\return Error code
|
|
|
|
*/
|
2018-02-26 20:17:00 +01:00
|
|
|
AAC_DECODER_ERROR CAacDecoder_AncDataInit(CAncData *ancData,
|
|
|
|
unsigned char *buffer, int size) {
|
2012-07-11 19:15:24 +02:00
|
|
|
if (size >= 0) {
|
|
|
|
ancData->buffer = buffer;
|
|
|
|
ancData->bufferSize = size;
|
|
|
|
|
|
|
|
CAacDecoder_AncDataReset(ancData);
|
|
|
|
|
|
|
|
return AAC_DEC_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
return AAC_DEC_ANC_DATA_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
\brief Get one ancillary data element
|
|
|
|
|
|
|
|
\ancData Pointer to ancillary data structure
|
|
|
|
\index Index of the anc data element to get
|
|
|
|
\ptr Pointer to a buffer receiving a pointer to the requested anc data element
|
2018-02-26 20:17:00 +01:00
|
|
|
\size Pointer to a buffer receiving the length of the requested anc data
|
|
|
|
element in bytes
|
2012-07-11 19:15:24 +02:00
|
|
|
|
|
|
|
\return Error code
|
|
|
|
*/
|
2018-02-26 20:17:00 +01:00
|
|
|
AAC_DECODER_ERROR CAacDecoder_AncDataGet(CAncData *ancData, int index,
|
|
|
|
unsigned char **ptr, int *size) {
|
2012-07-11 19:15:24 +02:00
|
|
|
AAC_DECODER_ERROR error = AAC_DEC_OK;
|
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
*ptr = NULL;
|
2012-07-11 19:15:24 +02:00
|
|
|
*size = 0;
|
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
if (index >= 0 && index < 8 - 1 && index < ancData->nrElements) {
|
|
|
|
*ptr = &ancData->buffer[ancData->offset[index]];
|
|
|
|
*size = ancData->offset[index + 1] - ancData->offset[index];
|
2012-07-11 19:15:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
\brief Parse ancillary data
|
|
|
|
|
|
|
|
\ancData Pointer to ancillary data structure
|
|
|
|
\hBs Handle to FDK bitstream
|
|
|
|
\ancBytes Length of ancillary data to read from the bitstream
|
|
|
|
|
|
|
|
\return Error code
|
|
|
|
*/
|
2018-02-26 20:17:00 +01:00
|
|
|
static AAC_DECODER_ERROR CAacDecoder_AncDataParse(CAncData *ancData,
|
|
|
|
HANDLE_FDK_BITSTREAM hBs,
|
|
|
|
const int ancBytes) {
|
2012-07-11 19:15:24 +02:00
|
|
|
AAC_DECODER_ERROR error = AAC_DEC_OK;
|
|
|
|
int readBytes = 0;
|
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
if (ancData->buffer != NULL) {
|
2012-07-11 19:15:24 +02:00
|
|
|
if (ancBytes > 0) {
|
|
|
|
/* write ancillary data to external buffer */
|
|
|
|
int offset = ancData->offset[ancData->nrElements];
|
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
if ((offset + ancBytes) > ancData->bufferSize) {
|
2012-07-11 19:15:24 +02:00
|
|
|
error = AAC_DEC_TOO_SMALL_ANC_BUFFER;
|
2018-02-26 20:17:00 +01:00
|
|
|
} else if (ancData->nrElements >= 8 - 1) {
|
2012-07-11 19:15:24 +02:00
|
|
|
error = AAC_DEC_TOO_MANY_ANC_ELEMENTS;
|
2018-02-26 20:17:00 +01:00
|
|
|
} else {
|
2012-07-11 19:15:24 +02:00
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < ancBytes; i++) {
|
2018-02-26 20:17:00 +01:00
|
|
|
ancData->buffer[i + offset] = FDKreadBits(hBs, 8);
|
2012-07-11 19:15:24 +02:00
|
|
|
readBytes++;
|
|
|
|
}
|
|
|
|
|
|
|
|
ancData->nrElements++;
|
2018-02-26 20:17:00 +01:00
|
|
|
ancData->offset[ancData->nrElements] =
|
|
|
|
ancBytes + ancData->offset[ancData->nrElements - 1];
|
2012-07-11 19:15:24 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
readBytes = ancBytes - readBytes;
|
|
|
|
|
|
|
|
if (readBytes > 0) {
|
|
|
|
/* skip data */
|
2018-02-26 20:17:00 +01:00
|
|
|
FDKpushFor(hBs, readBytes << 3);
|
2012-07-11 19:15:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
\brief Read Stream Data Element
|
|
|
|
|
|
|
|
\bs Bitstream Handle
|
|
|
|
|
|
|
|
\return Error code
|
|
|
|
*/
|
2018-02-26 20:17:00 +01:00
|
|
|
static AAC_DECODER_ERROR CDataStreamElement_Read(HANDLE_AACDECODER self,
|
|
|
|
HANDLE_FDK_BITSTREAM bs,
|
|
|
|
UCHAR *elementInstanceTag,
|
|
|
|
UINT alignmentAnchor) {
|
2012-07-11 19:15:24 +02:00
|
|
|
AAC_DECODER_ERROR error = AAC_DEC_OK;
|
2018-05-09 13:32:45 +02:00
|
|
|
UINT dseBits;
|
|
|
|
INT dataStart;
|
2012-07-11 19:15:24 +02:00
|
|
|
int dataByteAlignFlag, count;
|
|
|
|
|
2013-12-28 01:13:22 +01:00
|
|
|
FDK_ASSERT(self != NULL);
|
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
int crcReg = transportDec_CrcStartReg(self->hInput, 0);
|
2012-07-11 19:15:24 +02:00
|
|
|
|
|
|
|
/* Element Instance Tag */
|
2018-02-26 20:17:00 +01:00
|
|
|
*elementInstanceTag = FDKreadBits(bs, 4);
|
2012-07-11 19:15:24 +02:00
|
|
|
/* Data Byte Align Flag */
|
2018-02-26 20:17:00 +01:00
|
|
|
dataByteAlignFlag = FDKreadBits(bs, 1);
|
2012-07-11 19:15:24 +02:00
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
count = FDKreadBits(bs, 8);
|
2012-07-11 19:15:24 +02:00
|
|
|
|
|
|
|
if (count == 255) {
|
2018-02-26 20:17:00 +01:00
|
|
|
count += FDKreadBits(bs, 8); /* EscCount */
|
2012-07-11 19:15:24 +02:00
|
|
|
}
|
2018-02-26 20:17:00 +01:00
|
|
|
dseBits = count * 8;
|
2012-07-11 19:15:24 +02:00
|
|
|
|
|
|
|
if (dataByteAlignFlag) {
|
|
|
|
FDKbyteAlign(bs, alignmentAnchor);
|
|
|
|
}
|
|
|
|
|
2018-05-09 13:32:45 +02:00
|
|
|
dataStart = (INT)FDKgetValidBits(bs);
|
2012-07-11 19:15:24 +02:00
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
error = CAacDecoder_AncDataParse(&self->ancData, bs, count);
|
|
|
|
transportDec_CrcEndReg(self->hInput, crcReg);
|
2012-07-11 19:15:24 +02:00
|
|
|
|
|
|
|
{
|
2018-02-26 20:17:00 +01:00
|
|
|
/* Move to the beginning of the data chunk */
|
2018-05-09 13:32:45 +02:00
|
|
|
FDKpushBack(bs, dataStart - (INT)FDKgetValidBits(bs));
|
2012-07-11 19:15:24 +02:00
|
|
|
|
|
|
|
/* Read Anc data if available */
|
2018-02-26 20:17:00 +01:00
|
|
|
aacDecoder_drcMarkPayload(self->hDrcInfo, bs, DVB_DRC_ANC_DATA);
|
2013-12-28 01:13:22 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
PCMDMX_ERROR dmxErr = PCMDMX_OK;
|
2012-07-11 19:15:24 +02:00
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
/* Move to the beginning of the data chunk */
|
2018-05-09 13:32:45 +02:00
|
|
|
FDKpushBack(bs, dataStart - (INT)FDKgetValidBits(bs));
|
2013-12-28 01:13:22 +01:00
|
|
|
|
|
|
|
/* Read DMX meta-data */
|
2018-02-26 20:17:00 +01:00
|
|
|
dmxErr = pcmDmx_Parse(self->hPcmUtils, bs, dseBits, 0 /* not mpeg2 */);
|
|
|
|
if (error == AAC_DEC_OK && dmxErr != PCMDMX_OK) {
|
|
|
|
error = AAC_DEC_UNKNOWN;
|
2012-07-11 19:15:24 +02:00
|
|
|
}
|
2018-02-26 20:17:00 +01:00
|
|
|
}
|
2013-12-28 01:13:22 +01:00
|
|
|
|
|
|
|
/* Move to the very end of the element. */
|
2018-05-09 13:32:45 +02:00
|
|
|
FDKpushBiDirectional(bs, (INT)FDKgetValidBits(bs) - dataStart + (INT)dseBits);
|
2012-07-11 19:15:24 +02:00
|
|
|
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
\brief Read Program Config Element
|
|
|
|
|
|
|
|
\bs Bitstream Handle
|
2013-08-28 01:28:09 +02:00
|
|
|
\pTp Transport decoder handle for CRC handling
|
|
|
|
\pce Pointer to PCE buffer
|
|
|
|
\channelConfig Current channel configuration
|
|
|
|
\alignAnchor Anchor for byte alignment
|
2012-07-11 19:15:24 +02:00
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
\return PCE status (-1: fail, 0: no new PCE, 1: PCE updated, 2: PCE updated
|
|
|
|
need re-config).
|
2012-07-11 19:15:24 +02:00
|
|
|
*/
|
2018-02-26 20:17:00 +01:00
|
|
|
static int CProgramConfigElement_Read(HANDLE_FDK_BITSTREAM bs,
|
|
|
|
HANDLE_TRANSPORTDEC pTp,
|
|
|
|
CProgramConfig *pce,
|
|
|
|
const UINT channelConfig,
|
|
|
|
const UINT alignAnchor) {
|
2013-08-28 01:28:09 +02:00
|
|
|
int pceStatus = 0;
|
2012-07-11 19:15:24 +02:00
|
|
|
int crcReg;
|
|
|
|
|
|
|
|
/* read PCE to temporal buffer first */
|
|
|
|
C_ALLOC_SCRATCH_START(tmpPce, CProgramConfig, 1);
|
2013-08-28 01:28:09 +02:00
|
|
|
|
2012-07-11 19:15:24 +02:00
|
|
|
CProgramConfig_Init(tmpPce);
|
|
|
|
|
|
|
|
crcReg = transportDec_CrcStartReg(pTp, 0);
|
|
|
|
|
|
|
|
CProgramConfig_Read(tmpPce, bs, alignAnchor);
|
|
|
|
|
|
|
|
transportDec_CrcEndReg(pTp, crcReg);
|
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
if (CProgramConfig_IsValid(tmpPce) && (tmpPce->Profile == 1)) {
|
|
|
|
if (!CProgramConfig_IsValid(pce) && (channelConfig > 0)) {
|
2013-08-28 01:28:09 +02:00
|
|
|
/* Create a standard channel config PCE to compare with */
|
2018-02-26 20:17:00 +01:00
|
|
|
CProgramConfig_GetDefault(pce, channelConfig);
|
2013-08-28 01:28:09 +02:00
|
|
|
}
|
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
if (CProgramConfig_IsValid(pce)) {
|
2013-08-28 01:28:09 +02:00
|
|
|
/* Compare the new and the old PCE (tags ignored) */
|
2018-02-26 20:17:00 +01:00
|
|
|
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;
|
2018-12-20 15:52:46 +01:00
|
|
|
case 2: /* The number of channels are identical but not the config */
|
2018-02-26 20:17:00 +01:00
|
|
|
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;
|
2013-08-28 01:28:09 +02:00
|
|
|
}
|
|
|
|
}
|
2012-07-11 19:15:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
C_ALLOC_SCRATCH_END(tmpPce, CProgramConfig, 1);
|
|
|
|
|
2013-08-28 01:28:09 +02:00
|
|
|
return pceStatus;
|
2012-07-11 19:15:24 +02:00
|
|
|
}
|
2018-02-26 20:17:00 +01:00
|
|
|
|
|
|
|
/*!
|
|
|
|
\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) {
|
2018-06-29 16:34:34 +02:00
|
|
|
prerollAUOffset[i] = auStartAnchor - (INT)FDKgetValidBits(hBs);
|
2018-02-26 20:17:00 +01:00
|
|
|
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;
|
|
|
|
}
|
2012-07-11 19:15:24 +02:00
|
|
|
|
|
|
|
/*!
|
|
|
|
\brief Parse Extension Payload
|
|
|
|
|
|
|
|
\self Handle of AAC decoder
|
|
|
|
\count Pointer to bit counter.
|
|
|
|
\previous_element ID of previous element (required by some extension payloads)
|
|
|
|
|
|
|
|
\return Error code
|
|
|
|
*/
|
2018-02-26 20:17:00 +01:00
|
|
|
static AAC_DECODER_ERROR CAacDecoder_ExtPayloadParse(
|
|
|
|
HANDLE_AACDECODER self, HANDLE_FDK_BITSTREAM hBs, int *count,
|
|
|
|
MP4_ELEMENT_ID previous_element, int elIndex, int fIsFillElement) {
|
2012-07-11 19:15:24 +02:00
|
|
|
AAC_DECODER_ERROR error = AAC_DEC_OK;
|
|
|
|
EXT_PAYLOAD_TYPE extension_type;
|
|
|
|
int bytes = (*count) >> 3;
|
|
|
|
int crcFlag = 0;
|
|
|
|
|
|
|
|
if (*count < 4) {
|
|
|
|
return AAC_DEC_PARSE_ERROR;
|
|
|
|
} else if ((INT)FDKgetValidBits(hBs) < *count) {
|
|
|
|
return AAC_DEC_DECODE_FRAME_ERROR;
|
|
|
|
}
|
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
extension_type =
|
|
|
|
(EXT_PAYLOAD_TYPE)FDKreadBits(hBs, 4); /* bs_extension_type */
|
2012-07-11 19:15:24 +02:00
|
|
|
*count -= 4;
|
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
/* 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 */
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (extension_type) {
|
|
|
|
case EXT_DYNAMIC_RANGE: {
|
|
|
|
INT readBits =
|
|
|
|
aacDecoder_drcMarkPayload(self->hDrcInfo, hBs, MPEG_DRC_EXT_DATA);
|
2012-07-11 19:15:24 +02:00
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
if (readBits > *count) { /* Read too much. Something went wrong! */
|
2012-07-11 19:15:24 +02:00
|
|
|
error = AAC_DEC_PARSE_ERROR;
|
|
|
|
}
|
|
|
|
*count -= readBits;
|
2018-02-26 20:17:00 +01:00
|
|
|
} 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;
|
|
|
|
}
|
2012-07-11 19:15:24 +02:00
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
drcErr = FDK_drcDec_SetCodecMode(self->hUniDrcDecoder, drcDecCodecMode);
|
|
|
|
if (drcErr) {
|
|
|
|
error = AAC_DEC_PARSE_ERROR;
|
|
|
|
goto bail;
|
|
|
|
}
|
2012-07-11 19:15:24 +02:00
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
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;
|
2012-07-11 19:15:24 +02:00
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
if (self->flags[0] & AC_PS_PRESENT) {
|
|
|
|
error = AAC_DEC_PARSE_ERROR;
|
|
|
|
goto bail;
|
|
|
|
}
|
2012-07-11 19:15:24 +02:00
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
/* 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;
|
2012-07-11 19:15:24 +02:00
|
|
|
}
|
2018-02-26 20:17:00 +01:00
|
|
|
/* 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);
|
2012-07-11 19:15:24 +02:00
|
|
|
*count = 0;
|
2018-02-26 20:17:00 +01:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case EXT_SBR_DATA_CRC:
|
|
|
|
crcFlag = 1;
|
2018-10-19 16:37:31 +02:00
|
|
|
FDK_FALLTHROUGH;
|
2018-02-26 20:17:00 +01:00
|
|
|
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;
|
|
|
|
}
|
2012-07-11 19:15:24 +02:00
|
|
|
}
|
2018-02-26 20:17:00 +01:00
|
|
|
} else {
|
|
|
|
error = AAC_DEC_PARSE_ERROR;
|
2012-07-11 19:15:24 +02:00
|
|
|
}
|
2018-02-26 20:17:00 +01:00
|
|
|
break;
|
2012-07-11 19:15:24 +02:00
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
case EXT_FILL_DATA: {
|
2012-07-11 19:15:24 +02:00
|
|
|
int temp;
|
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
temp = FDKreadBits(hBs, 4);
|
2012-07-11 19:15:24 +02:00
|
|
|
bytes--;
|
|
|
|
if (temp != 0) {
|
|
|
|
error = AAC_DEC_PARSE_ERROR;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
while (bytes > 0) {
|
2018-02-26 20:17:00 +01:00
|
|
|
temp = FDKreadBits(hBs, 8);
|
2012-07-11 19:15:24 +02:00
|
|
|
bytes--;
|
|
|
|
if (temp != 0xa5) {
|
|
|
|
error = AAC_DEC_PARSE_ERROR;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2018-02-26 20:17:00 +01:00
|
|
|
*count = bytes << 3;
|
|
|
|
} break;
|
2012-07-11 19:15:24 +02:00
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
case EXT_DATA_ELEMENT: {
|
2012-07-11 19:15:24 +02:00
|
|
|
int dataElementVersion;
|
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
dataElementVersion = FDKreadBits(hBs, 4);
|
2012-07-11 19:15:24 +02:00
|
|
|
*count -= 4;
|
|
|
|
if (dataElementVersion == 0) /* ANC_DATA */
|
|
|
|
{
|
|
|
|
int temp, dataElementLength = 0;
|
|
|
|
do {
|
2018-02-26 20:17:00 +01:00
|
|
|
temp = FDKreadBits(hBs, 8);
|
2012-07-11 19:15:24 +02:00
|
|
|
*count -= 8;
|
|
|
|
dataElementLength += temp;
|
2018-02-26 20:17:00 +01:00
|
|
|
} while (temp == 255);
|
2012-07-11 19:15:24 +02:00
|
|
|
|
|
|
|
CAacDecoder_AncDataParse(&self->ancData, hBs, dataElementLength);
|
2018-02-26 20:17:00 +01:00
|
|
|
*count -= (dataElementLength << 3);
|
2012-07-11 19:15:24 +02:00
|
|
|
} else {
|
|
|
|
/* align = 0 */
|
|
|
|
error = AAC_DEC_PARSE_ERROR;
|
|
|
|
goto bail;
|
|
|
|
}
|
2018-02-26 20:17:00 +01:00
|
|
|
} 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;
|
2012-07-11 19:15:24 +02:00
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
if (add_len == 255) {
|
|
|
|
len += FDKreadBits(hBs, 16);
|
|
|
|
*count -= 16;
|
|
|
|
}
|
2012-07-11 19:15:24 +02:00
|
|
|
}
|
2018-02-26 20:17:00 +01:00
|
|
|
len <<= 3;
|
|
|
|
bitCnt = len;
|
2012-07-11 19:15:24 +02:00
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
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);
|
2012-07-11 19:15:24 +02:00
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
error = CAacDecoder_ExtPayloadParse(
|
|
|
|
self, hBs, &bitCnt, previous_element, elIndex,
|
|
|
|
1); /* Treat same as fill element */
|
2012-07-11 19:15:24 +02:00
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
*count -= len - bitCnt;
|
|
|
|
}
|
|
|
|
/* Note: the fall through in case the if statement above is not taken is
|
|
|
|
* intentional. */
|
|
|
|
break;
|
2012-07-11 19:15:24 +02:00
|
|
|
}
|
2018-10-19 16:37:31 +02:00
|
|
|
FDK_FALLTHROUGH;
|
2012-07-11 19:15:24 +02:00
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
case EXT_FIL:
|
2012-07-11 19:15:24 +02:00
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
default:
|
|
|
|
/* align = 4 */
|
|
|
|
FDKpushFor(hBs, *count);
|
|
|
|
*count = 0;
|
|
|
|
break;
|
2012-07-11 19:15:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bail:
|
2018-02-26 20:17:00 +01:00
|
|
|
if ((error != AAC_DEC_OK) &&
|
|
|
|
fIsFillElement) { /* Skip the remaining extension bytes */
|
2012-07-11 19:15:24 +02:00
|
|
|
FDKpushBiDirectional(hBs, *count);
|
|
|
|
*count = 0;
|
|
|
|
/* Patch error code because decoding can go on. */
|
|
|
|
error = AAC_DEC_OK;
|
|
|
|
/* Be sure that parsing errors have been stored. */
|
|
|
|
}
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
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;
|
2012-07-11 19:15:24 +02:00
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
/* get the remaining bits of this frame */
|
|
|
|
bitCnt = transportDec_GetAuBitsRemaining(self->hInput, 0);
|
2012-07-11 19:15:24 +02:00
|
|
|
|
2018-10-19 16:41:27 +02:00
|
|
|
if ((self->flags[0] & AC_SBR_PRESENT) &&
|
2018-02-26 20:17:00 +01:00
|
|
|
(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];
|
2018-10-19 16:41:27 +02:00
|
|
|
INT bitCntTmp = bitCnt;
|
2012-07-11 19:15:24 +02:00
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
if (self->flags[0] & AC_USAC) {
|
|
|
|
chElIdx = numChElements - 1;
|
|
|
|
} else {
|
|
|
|
chElIdx = 0; /* ELD case */
|
|
|
|
}
|
2012-07-11 19:15:24 +02:00
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
for (; chElIdx < numChElements; chElIdx += 1) {
|
|
|
|
MP4_ELEMENT_ID sbrType;
|
2018-10-19 16:41:27 +02:00
|
|
|
SBR_ERROR errTmp;
|
2018-02-26 20:17:00 +01:00
|
|
|
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];
|
2018-10-19 16:41:27 +02:00
|
|
|
errTmp = sbrDecoder_Parse(self->hSbrDecoder, bs, self->pDrmBsBuffer,
|
|
|
|
self->drmBsBufferSize, &bitCnt, -1,
|
|
|
|
self->flags[0] & AC_SBRCRC, sbrType, chElIdx,
|
|
|
|
self->flags[0], self->elFlags);
|
|
|
|
if (errTmp != SBRDEC_OK) {
|
|
|
|
err = errTmp;
|
|
|
|
bitCntTmp = bitCnt;
|
|
|
|
bitCnt = 0;
|
2018-02-26 20:17:00 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
switch (err) {
|
|
|
|
case SBRDEC_PARSE_ERROR:
|
|
|
|
/* Can not go on parsing because we do not
|
|
|
|
know the length of the SBR extension data. */
|
2018-10-19 16:41:27 +02:00
|
|
|
FDKpushFor(bs, bitCntTmp);
|
2018-02-26 20:17:00 +01:00
|
|
|
bitCnt = 0;
|
|
|
|
break;
|
|
|
|
case SBRDEC_OK:
|
|
|
|
self->sbrEnabled = 1;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
self->frameOK = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2014-05-21 02:24:06 +02:00
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
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.
|
|
|
|
*/
|
|
|
|
static void CStreamInfoInit(CStreamInfo *pStreamInfo) {
|
|
|
|
pStreamInfo->aacSampleRate = 0;
|
|
|
|
pStreamInfo->profile = -1;
|
|
|
|
pStreamInfo->aot = AOT_NONE;
|
|
|
|
|
|
|
|
pStreamInfo->channelConfig = -1;
|
|
|
|
pStreamInfo->bitRate = 0;
|
|
|
|
pStreamInfo->aacSamplesPerFrame = 0;
|
|
|
|
|
|
|
|
pStreamInfo->extAot = AOT_NONE;
|
|
|
|
pStreamInfo->extSamplingRate = 0;
|
|
|
|
|
|
|
|
pStreamInfo->flags = 0;
|
|
|
|
|
|
|
|
pStreamInfo->epConfig = -1; /* default: no ER */
|
|
|
|
|
|
|
|
pStreamInfo->numChannels = 0;
|
|
|
|
pStreamInfo->sampleRate = 0;
|
|
|
|
pStreamInfo->frameSize = 0;
|
|
|
|
|
|
|
|
pStreamInfo->outputDelay = 0;
|
2014-05-21 02:29:03 +02:00
|
|
|
|
|
|
|
/* DRC */
|
2018-02-26 20:17:00 +01:00
|
|
|
pStreamInfo->drcProgRefLev =
|
|
|
|
-1; /* set program reference level to not indicated */
|
|
|
|
pStreamInfo->drcPresMode = -1; /* default: presentation mode not indicated */
|
2012-07-11 19:15:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
\brief Initialization of AacDecoderChannelInfo
|
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
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
|
2012-07-11 19:15:24 +02:00
|
|
|
|
|
|
|
\return AACDECODER instance
|
|
|
|
*/
|
2018-02-26 20:17:00 +01:00
|
|
|
LINKSPEC_CPP HANDLE_AACDECODER CAacDecoder_Open(
|
|
|
|
TRANSPORT_TYPE bsFormat) /*!< bitstream format (adif,adts,loas,...). */
|
2012-07-11 19:15:24 +02:00
|
|
|
{
|
|
|
|
HANDLE_AACDECODER self;
|
|
|
|
|
|
|
|
self = GetAacDecoder();
|
|
|
|
if (self == NULL) {
|
|
|
|
goto bail;
|
|
|
|
}
|
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
FDK_QmfDomain_ClearRequested(&self->qmfDomain.globalConf);
|
|
|
|
|
|
|
|
/* Assign channel mapping info arrays (doing so removes dependency of settings
|
|
|
|
* header in API header). */
|
2012-07-11 19:15:24 +02:00
|
|
|
self->streamInfo.pChannelIndices = self->channelIndices;
|
|
|
|
self->streamInfo.pChannelType = self->channelType;
|
2018-02-26 20:17:00 +01:00
|
|
|
self->downscaleFactor = 1;
|
|
|
|
self->downscaleFactorInBS = 1;
|
2012-07-11 19:15:24 +02:00
|
|
|
|
|
|
|
/* initialize anc data */
|
|
|
|
CAacDecoder_AncDataInit(&self->ancData, NULL, 0);
|
|
|
|
|
|
|
|
/* initialize stream info */
|
|
|
|
CStreamInfoInit(&self->streamInfo);
|
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
/* initialize progam config */
|
|
|
|
CProgramConfig_Init(&self->pce);
|
|
|
|
|
2012-07-11 19:15:24 +02:00
|
|
|
/* initialize error concealment common data */
|
|
|
|
CConcealment_InitCommonData(&self->concealCommonData);
|
2018-02-26 20:17:00 +01:00
|
|
|
self->concealMethodUser = ConcealMethodNone; /* undefined -> auto mode */
|
2012-07-11 19:15:24 +02:00
|
|
|
|
|
|
|
self->hDrcInfo = GetDrcInfo();
|
|
|
|
if (self->hDrcInfo == NULL) {
|
|
|
|
goto bail;
|
|
|
|
}
|
|
|
|
/* Init common DRC structure */
|
2018-02-26 20:17:00 +01:00
|
|
|
aacDecoder_drcInit(self->hDrcInfo);
|
2012-07-11 19:15:24 +02:00
|
|
|
/* Set default frame delay */
|
2018-02-26 20:17:00 +01:00
|
|
|
aacDecoder_drcSetParam(self->hDrcInfo, DRC_BS_DELAY,
|
|
|
|
CConcealment_GetDelay(&self->concealCommonData));
|
2012-07-11 19:15:24 +02:00
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
self->workBufferCore2 = GetWorkBufferCore2();
|
|
|
|
if (self->workBufferCore2 == NULL) goto bail;
|
2012-07-11 19:15:24 +02:00
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
/* When RSVD60 is active use dedicated memory for core decoding */
|
|
|
|
self->pTimeData2 = GetWorkBufferCore5();
|
|
|
|
self->timeData2Size = GetRequiredMemWorkBufferCore5();
|
|
|
|
if (self->pTimeData2 == NULL) {
|
2012-07-11 19:15:24 +02:00
|
|
|
goto bail;
|
2018-02-26 20:17:00 +01:00
|
|
|
}
|
2012-07-11 19:15:24 +02:00
|
|
|
|
|
|
|
return self;
|
|
|
|
|
|
|
|
bail:
|
2018-02-26 20:17:00 +01:00
|
|
|
CAacDecoder_Close(self);
|
2012-07-11 19:15:24 +02:00
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
/* Revert CAacDecoder_Init() */
|
|
|
|
static void CAacDecoder_DeInit(HANDLE_AACDECODER self,
|
|
|
|
const int subStreamIndex) {
|
2012-07-11 19:15:24 +02:00
|
|
|
int ch;
|
2018-02-26 20:17:00 +01:00
|
|
|
int aacChannelOffset = 0, aacChannels = (8);
|
|
|
|
int numElements = (((8)) + (8)), elementOffset = 0;
|
|
|
|
|
|
|
|
if (self == NULL) return;
|
2012-07-11 19:15:24 +02:00
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
{
|
|
|
|
self->ascChannels[0] = 0;
|
|
|
|
self->elements[0] = ID_END;
|
|
|
|
}
|
2012-07-11 19:15:24 +02:00
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
2012-07-11 19:15:24 +02:00
|
|
|
if (self->pAacDecoderStaticChannelInfo[ch] != NULL) {
|
2013-08-28 01:28:09 +02:00
|
|
|
if (self->pAacDecoderStaticChannelInfo[ch]->pOverlapBuffer != NULL) {
|
2018-02-26 20:17:00 +01:00
|
|
|
FreeOverlapBuffer(
|
|
|
|
&self->pAacDecoderStaticChannelInfo[ch]->pOverlapBuffer);
|
2013-08-28 01:28:09 +02:00
|
|
|
}
|
2018-02-26 20:17:00 +01:00
|
|
|
if (self->pAacDecoderStaticChannelInfo[ch]->hArCo != NULL) {
|
|
|
|
CArco_Destroy(self->pAacDecoderStaticChannelInfo[ch]->hArCo);
|
2013-08-28 01:28:09 +02:00
|
|
|
}
|
2018-02-26 20:17:00 +01:00
|
|
|
FreeAacDecoderStaticChannelInfo(&self->pAacDecoderStaticChannelInfo[ch]);
|
2012-07-11 19:15:24 +02:00
|
|
|
}
|
|
|
|
if (self->pAacDecoderChannelInfo[ch] != NULL) {
|
2018-02-26 20:17:00 +01:00
|
|
|
FreeAacDecoderChannelInfo(&self->pAacDecoderChannelInfo[ch]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
int el;
|
|
|
|
for (el = elementOffset; el < elementOffset + numElements; el++) {
|
|
|
|
if (self->cpeStaticData[el] != NULL) {
|
|
|
|
FreeCpePersistentData(&self->cpeStaticData[el]);
|
|
|
|
}
|
2012-07-11 19:15:24 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
FDK_Delay_Destroy(&self->usacResidualDelay);
|
|
|
|
|
2012-07-11 19:15:24 +02:00
|
|
|
self->aacChannels = 0;
|
2018-02-26 20:17:00 +01:00
|
|
|
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]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-07-11 19:15:24 +02:00
|
|
|
|
|
|
|
if (self->hDrcInfo) {
|
|
|
|
FreeDrcInfo(&self->hDrcInfo);
|
|
|
|
}
|
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
/* Free WorkBufferCore2 */
|
|
|
|
if (self->workBufferCore2 != NULL) {
|
|
|
|
FreeWorkBufferCore2(&self->workBufferCore2);
|
2013-08-28 01:28:09 +02:00
|
|
|
}
|
2018-02-26 20:17:00 +01:00
|
|
|
if (self->pTimeData2 != NULL) {
|
|
|
|
FreeWorkBufferCore5(&self->pTimeData2);
|
2013-08-28 01:28:09 +02:00
|
|
|
}
|
2012-07-11 19:15:24 +02:00
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
FDK_QmfDomain_Close(&self->qmfDomain);
|
2012-07-11 19:15:24 +02:00
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
FreeAacDecoder(&self);
|
|
|
|
}
|
2012-07-11 19:15:24 +02:00
|
|
|
|
|
|
|
/*!
|
|
|
|
\brief Initialization of decoder instance
|
|
|
|
|
|
|
|
The function initializes the decoder.
|
|
|
|
|
|
|
|
\return error status: 0 for success, <>0 for unsupported configurations
|
|
|
|
*/
|
2018-02-26 20:17:00 +01:00
|
|
|
LINKSPEC_CPP AAC_DECODER_ERROR
|
|
|
|
CAacDecoder_Init(HANDLE_AACDECODER self, const CSAudioSpecificConfig *asc,
|
|
|
|
UCHAR configMode, UCHAR *configChanged) {
|
2012-07-11 19:15:24 +02:00
|
|
|
AAC_DECODER_ERROR err = AAC_DEC_OK;
|
2018-02-26 20:17:00 +01:00
|
|
|
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;
|
2012-07-11 19:15:24 +02:00
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
if (!self) return AAC_DEC_INVALID_HANDLE;
|
|
|
|
|
|
|
|
UCHAR downscaleFactor = self->downscaleFactor;
|
|
|
|
UCHAR downscaleFactorInBS = self->downscaleFactorInBS;
|
2012-07-11 19:15:24 +02:00
|
|
|
|
|
|
|
// set profile and check for supported aot
|
2018-02-26 20:17:00 +01:00
|
|
|
// leave profile on default (=-1) for all other supported MPEG-4 aot's except
|
|
|
|
// aot=2 (=AAC-LC)
|
2012-07-11 19:15:24 +02:00
|
|
|
switch (asc->m_aot) {
|
2018-02-26 20:17:00 +01:00
|
|
|
case AOT_AAC_LC:
|
|
|
|
self->streamInfo.profile = 1;
|
2018-10-19 16:37:31 +02:00
|
|
|
FDK_FALLTHROUGH;
|
2018-02-26 20:17:00 +01:00
|
|
|
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;
|
|
|
|
}
|
2018-10-19 16:37:31 +02:00
|
|
|
FDK_FALLTHROUGH;
|
2018-02-26 20:17:00 +01:00
|
|
|
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;
|
2012-07-11 19:15:24 +02:00
|
|
|
}
|
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
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);
|
|
|
|
}
|
2012-07-11 19:15:24 +02:00
|
|
|
|
|
|
|
/* set channels */
|
|
|
|
switch (asc->m_channelConfiguration) {
|
2018-02-26 20:17:00 +01:00
|
|
|
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;
|
2012-07-11 19:15:24 +02:00
|
|
|
}
|
2018-02-26 20:17:00 +01:00
|
|
|
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 (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 */
|
|
|
|
}
|
2012-07-11 19:15:24 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
aacChannelsOffset = 0;
|
|
|
|
aacChannelsOffsetIdx = 0;
|
|
|
|
elementOffset = 0;
|
2018-06-08 18:07:14 +02:00
|
|
|
if ((ascChannels <= 0) || (ascChannels > (8)) ||
|
|
|
|
(asc->m_channelConfiguration > AACDEC_MAX_CH_CONF)) {
|
|
|
|
return AAC_DEC_UNSUPPORTED_CHANNELCONFIG;
|
2013-12-28 01:13:22 +01:00
|
|
|
}
|
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
/* 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;
|
|
|
|
}
|
2012-07-11 19:15:24 +02:00
|
|
|
}
|
2018-02-26 20:17:00 +01:00
|
|
|
|
|
|
|
{
|
|
|
|
int ch;
|
|
|
|
|
|
|
|
for (ch = 0; ch < ascChannels; ch++) {
|
|
|
|
self->chMapping[ch] = ch;
|
|
|
|
}
|
|
|
|
for (; ch < (8); ch++) {
|
|
|
|
self->chMapping[ch] = 255;
|
|
|
|
}
|
2012-07-11 19:15:24 +02:00
|
|
|
}
|
2018-02-26 20:17:00 +01:00
|
|
|
|
2013-12-28 01:13:22 +01:00
|
|
|
self->chMapIndex = asc->m_channelConfiguration;
|
2018-02-26 20:17:00 +01:00
|
|
|
} else {
|
2012-10-02 19:16:04 +02:00
|
|
|
if (CProgramConfig_IsValid(&asc->m_progrConfigElement)) {
|
|
|
|
/* Set matrix mixdown infos if available from PCE. */
|
2018-02-26 20:17:00 +01:00
|
|
|
pcmDmx_SetMatrixMixdownFromPce(
|
|
|
|
self->hPcmUtils, asc->m_progrConfigElement.MatrixMixdownIndexPresent,
|
|
|
|
asc->m_progrConfigElement.MatrixMixdownIndex,
|
|
|
|
asc->m_progrConfigElement.PseudoSurroundEnable);
|
2012-10-02 19:16:04 +02:00
|
|
|
}
|
|
|
|
}
|
2012-07-11 19:15:24 +02:00
|
|
|
|
|
|
|
self->streamInfo.channelConfig = asc->m_channelConfiguration;
|
|
|
|
|
|
|
|
if (self->streamInfo.aot != asc->m_aot) {
|
2018-02-26 20:17:00 +01:00
|
|
|
if (configMode & AC_CM_ALLOC_MEM) {
|
|
|
|
self->streamInfo.aot = asc->m_aot;
|
|
|
|
}
|
2012-07-11 19:15:24 +02:00
|
|
|
ascChanged = 1;
|
|
|
|
}
|
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
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;
|
|
|
|
}
|
2012-07-11 19:15:24 +02:00
|
|
|
ascChanged = 1;
|
|
|
|
}
|
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
if ((INT)asc->m_samplesPerFrame % downscaleFactor != 0) {
|
|
|
|
return AAC_DEC_UNSUPPORTED_SAMPLINGRATE; /* frameSize/dsf must be an integer
|
|
|
|
number */
|
|
|
|
}
|
|
|
|
|
|
|
|
self->streamInfo.bitRate = 0;
|
2012-07-11 19:15:24 +02:00
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
2012-07-11 19:15:24 +02:00
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
2012-07-11 19:15:24 +02:00
|
|
|
|
|
|
|
/* --------- vcb11 ------------ */
|
2018-02-26 20:17:00 +01:00
|
|
|
self->flags[streamIndex] |= (asc->m_vcb11Flag) ? AC_ER_VCB11 : 0;
|
2012-07-11 19:15:24 +02:00
|
|
|
|
|
|
|
/* ---------- rvlc ------------ */
|
2018-02-26 20:17:00 +01:00
|
|
|
self->flags[streamIndex] |= (asc->m_rvlcFlag) ? AC_ER_RVLC : 0;
|
2012-07-11 19:15:24 +02:00
|
|
|
|
|
|
|
/* ----------- hcr ------------ */
|
2018-02-26 20:17:00 +01:00
|
|
|
self->flags[streamIndex] |= (asc->m_hcrFlag) ? AC_ER_HCR : 0;
|
2012-07-11 19:15:24 +02:00
|
|
|
|
|
|
|
if (asc->m_aot == AOT_ER_AAC_ELD) {
|
2018-02-26 20:17:00 +01:00
|
|
|
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;
|
|
|
|
}
|
2012-07-11 19:15:24 +02:00
|
|
|
}
|
2018-02-26 20:17:00 +01:00
|
|
|
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;
|
2016-04-08 21:05:12 +02:00
|
|
|
}
|
2018-02-26 20:17:00 +01:00
|
|
|
if (asc->m_aot == AOT_DRM_AAC) {
|
|
|
|
self->flags[streamIndex] |= AC_DRM | AC_SBRCRC | AC_SCALABLE;
|
2016-04-08 21:05:12 +02:00
|
|
|
}
|
2018-02-26 20:17:00 +01:00
|
|
|
if (asc->m_aot == AOT_DRM_SURROUND) {
|
|
|
|
self->flags[streamIndex] |=
|
|
|
|
AC_DRM | AC_SBRCRC | AC_SCALABLE | AC_MPS_PRESENT;
|
|
|
|
FDK_ASSERT(!asc->m_psPresentFlag);
|
2012-07-11 19:15:24 +02:00
|
|
|
}
|
2018-02-26 20:17:00 +01:00
|
|
|
if ((asc->m_aot == AOT_AAC_SCAL) || (asc->m_aot == AOT_ER_AAC_SCAL)) {
|
|
|
|
self->flags[streamIndex] |= AC_SCALABLE;
|
2012-07-11 19:15:24 +02:00
|
|
|
}
|
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
if ((asc->m_epConfig >= 0) && (asc->m_channelConfiguration <= 0)) {
|
|
|
|
/* we have to know the number of channels otherwise no decoding is possible
|
|
|
|
*/
|
2012-07-11 19:15:24 +02:00
|
|
|
return AAC_DEC_UNSUPPORTED_ER_FORMAT;
|
|
|
|
}
|
|
|
|
|
|
|
|
self->streamInfo.epConfig = asc->m_epConfig;
|
|
|
|
/* self->hInput->asc.m_epConfig = asc->m_epConfig; */
|
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
if (asc->m_epConfig > 1) return AAC_DEC_UNSUPPORTED_ER_FORMAT;
|
|
|
|
|
|
|
|
/* Check if samplerate changed. */
|
|
|
|
if ((self->samplingRateInfo[streamIndex].samplingRate !=
|
|
|
|
asc->m_samplingFrequency) ||
|
|
|
|
(self->streamInfo.aacSamplesPerFrame !=
|
|
|
|
(INT)asc->m_samplesPerFrame / downscaleFactor)) {
|
|
|
|
AAC_DECODER_ERROR error;
|
|
|
|
|
|
|
|
ascChanged = 1;
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check if amount of channels has changed. */
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
for (int _el = 0; _el < _numElements; _el++) {
|
|
|
|
int el_channels = 0;
|
|
|
|
int el = elementOffset + _el;
|
|
|
|
|
|
|
|
if (self->flags[streamIndex] &
|
2018-08-15 14:33:56 +02:00
|
|
|
(AC_ER | AC_LD | AC_ELD | AC_RSV603DA | AC_USAC | AC_RSVD50)) {
|
2018-02-26 20:17:00 +01:00
|
|
|
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) {
|
2018-08-15 14:33:56 +02:00
|
|
|
if (ch >= (8) - 1) {
|
|
|
|
return AAC_DEC_UNSUPPORTED_CHANNELCONFIG;
|
|
|
|
}
|
2018-02-26 20:17:00 +01:00
|
|
|
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[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 (*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;
|
2012-07-11 19:15:24 +02:00
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
/* Reset DRC control data for this channel */
|
|
|
|
aacDecoder_drcInitChannelData(
|
|
|
|
&self->pAacDecoderStaticChannelInfo[ch]->drcData);
|
2012-07-11 19:15:24 +02:00
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
/* Delete mixdown metadata from the past */
|
|
|
|
pcmDmx_Reset(self->hPcmUtils, PCMDMX_RESET_BS_DATA);
|
2012-07-11 19:15:24 +02:00
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
/* 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++;
|
2012-07-11 19:15:24 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
/* Update externally visible copy of 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;
|
2012-07-11 19:15:24 +02:00
|
|
|
}
|
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
if (FDK_drcDec_Init(self->hUniDrcDecoder, drcDecFrameSize, drcDecSampleRate,
|
|
|
|
self->aacChannels) != 0)
|
|
|
|
goto bail;
|
2012-07-11 19:15:24 +02:00
|
|
|
}
|
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
if (asc->m_aot == AOT_USAC) {
|
|
|
|
pcmLimiter_SetAttack(self->hLimiter, (5));
|
|
|
|
pcmLimiter_SetThreshold(self->hLimiter, FL2FXCONST_DBL(0.89125094f));
|
2012-07-11 19:15:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return err;
|
|
|
|
|
|
|
|
bail:
|
2018-02-26 20:17:00 +01:00
|
|
|
CAacDecoder_DeInit(self, 0);
|
2012-07-11 19:15:24 +02:00
|
|
|
return AAC_DEC_OUT_OF_MEMORY;
|
|
|
|
}
|
|
|
|
|
|
|
|
LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
|
2018-02-26 20:17:00 +01:00
|
|
|
HANDLE_AACDECODER self, const UINT flags, FIXP_PCM *pTimeData,
|
|
|
|
const INT timeDataSize, const int timeDataChannelOffset) {
|
2012-07-11 19:15:24 +02:00
|
|
|
AAC_DECODER_ERROR ErrorStatus = AAC_DEC_OK;
|
|
|
|
|
|
|
|
CProgramConfig *pce;
|
|
|
|
HANDLE_FDK_BITSTREAM bs = transportDec_GetBitstream(self->hInput, 0);
|
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
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 */
|
2012-07-11 19:15:24 +02:00
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
INT auStartAnchor = (INT)FDKgetValidBits(
|
|
|
|
bs); /* AU start bit buffer position for AU byte alignment */
|
2012-07-11 19:15:24 +02:00
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
INT checkSampleRate = self->streamInfo.aacSampleRate;
|
|
|
|
|
|
|
|
INT CConceal_TDFading_Applied[(8)] = {
|
|
|
|
0}; /* Initialize status of Time Domain fading */
|
|
|
|
|
|
|
|
if (self->aacChannels <= 0) {
|
|
|
|
return AAC_DEC_UNSUPPORTED_CHANNELCONFIG;
|
|
|
|
}
|
2012-07-11 19:15:24 +02:00
|
|
|
|
|
|
|
/* Any supported base layer valid AU will require more than 16 bits. */
|
2018-02-26 20:17:00 +01:00
|
|
|
if ((transportDec_GetAuBitsRemaining(self->hInput, 0) < 15) &&
|
|
|
|
(flags & (AACDEC_CONCEAL | AACDEC_FLUSH)) == 0) {
|
2012-07-11 19:15:24 +02:00
|
|
|
self->frameOK = 0;
|
|
|
|
ErrorStatus = AAC_DEC_DECODE_FRAME_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Reset Program Config structure */
|
|
|
|
pce = &self->pce;
|
|
|
|
CProgramConfig_Reset(pce);
|
|
|
|
|
|
|
|
CAacDecoder_AncDataReset(&self->ancData);
|
2018-02-26 20:17:00 +01:00
|
|
|
if (!(flags & (AACDEC_CONCEAL | AACDEC_FLUSH)) &&
|
|
|
|
!(self->flags[0] & (AC_USAC | AC_RSV603DA))) {
|
2012-07-11 19:15:24 +02:00
|
|
|
int ch;
|
|
|
|
if (self->streamInfo.channelConfig == 0) {
|
|
|
|
/* Init Channel/Element mapping table */
|
2018-02-26 20:17:00 +01:00
|
|
|
for (ch = 0; ch < (8); ch++) {
|
2012-07-11 19:15:24 +02:00
|
|
|
self->chMapping[ch] = 255;
|
|
|
|
}
|
|
|
|
if (!CProgramConfig_IsValid(pce)) {
|
|
|
|
int el;
|
2018-02-26 20:17:00 +01:00
|
|
|
for (el = 0; el < (3 * ((8) * 2) + (((8) * 2)) / 2 + 4 * (1) + 1);
|
|
|
|
el++) {
|
2012-07-11 19:15:24 +02:00
|
|
|
self->elements[el] = ID_NONE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2012-07-11 19:15:24 +02:00
|
|
|
/* Check sampling frequency */
|
2018-02-26 20:17:00 +01:00
|
|
|
if (self->streamInfo.aacSampleRate <= 0) {
|
|
|
|
/* Instance maybe uninitialized! */
|
|
|
|
return AAC_DEC_UNSUPPORTED_SAMPLINGRATE;
|
|
|
|
}
|
|
|
|
switch (checkSampleRate) {
|
2016-04-08 21:05:12 +02:00
|
|
|
case 96000:
|
|
|
|
case 88200:
|
|
|
|
case 64000:
|
2012-07-11 19:15:24 +02:00
|
|
|
case 16000:
|
|
|
|
case 12000:
|
2018-02-26 20:17:00 +01:00
|
|
|
case 11025:
|
|
|
|
case 8000:
|
|
|
|
case 7350:
|
2012-07-11 19:15:24 +02:00
|
|
|
case 48000:
|
|
|
|
case 44100:
|
|
|
|
case 32000:
|
|
|
|
case 24000:
|
|
|
|
case 22050:
|
|
|
|
break;
|
|
|
|
default:
|
2018-02-26 20:17:00 +01:00
|
|
|
if (!(self->flags[0] & (AC_USAC | AC_RSVD50 | AC_RSV603DA))) {
|
2012-07-11 19:15:24 +02:00
|
|
|
return AAC_DEC_UNSUPPORTED_SAMPLINGRATE;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
2012-07-11 19:15:24 +02:00
|
|
|
}
|
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
int pceRead = 0; /* Flag indicating a PCE in the current raw_data_block() */
|
2012-07-11 19:15:24 +02:00
|
|
|
|
|
|
|
INT hdaacDecoded = 0;
|
2018-02-26 20:17:00 +01:00
|
|
|
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) {
|
2012-07-11 19:15:24 +02:00
|
|
|
int el_channels;
|
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
if (!(self->flags[0] &
|
|
|
|
(AC_USAC | AC_RSVD50 | AC_RSV603DA | AC_ELD | AC_SCALABLE | AC_ER)))
|
|
|
|
type = (MP4_ELEMENT_ID)FDKreadBits(bs, 3);
|
2018-08-15 14:35:00 +02:00
|
|
|
else {
|
|
|
|
if (element_count >= (3 * ((8) * 2) + (((8) * 2)) / 2 + 4 * (1) + 1)) {
|
|
|
|
self->frameOK = 0;
|
|
|
|
ErrorStatus = AAC_DEC_PARSE_ERROR;
|
|
|
|
break;
|
|
|
|
}
|
2012-07-11 19:15:24 +02:00
|
|
|
type = self->elements[element_count];
|
2018-08-15 14:35:00 +02:00
|
|
|
}
|
2012-07-11 19:15:24 +02:00
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
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;
|
|
|
|
}
|
2012-07-11 19:15:24 +02:00
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
/* 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++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-07-11 19:15:24 +02:00
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
if ((INT)FDKgetValidBits(bs) < 0) {
|
2012-07-11 19:15:24 +02:00
|
|
|
self->frameOK = 0;
|
2018-02-26 20:17:00 +01:00
|
|
|
}
|
2012-07-11 19:15:24 +02:00
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
switch (type) {
|
2012-07-11 19:15:24 +02:00
|
|
|
case ID_SCE:
|
|
|
|
case ID_CPE:
|
|
|
|
case ID_LFE:
|
2018-02-26 20:17:00 +01:00
|
|
|
case ID_USAC_SCE:
|
|
|
|
case ID_USAC_CPE:
|
|
|
|
case ID_USAC_LFE:
|
2018-08-15 14:35:00 +02:00
|
|
|
if (element_count >= (3 * ((8) * 2) + (((8) * 2)) / 2 + 4 * (1) + 1)) {
|
|
|
|
self->frameOK = 0;
|
|
|
|
ErrorStatus = AAC_DEC_PARSE_ERROR;
|
|
|
|
break;
|
|
|
|
}
|
2018-02-26 20:17:00 +01:00
|
|
|
|
|
|
|
el_channels = CAacDecoder_GetELChannels(
|
|
|
|
type, self->usacStereoConfigIndex[element_count]);
|
|
|
|
|
2012-07-11 19:15:24 +02:00
|
|
|
/*
|
|
|
|
Consistency check
|
2018-02-26 20:17:00 +01:00
|
|
|
*/
|
|
|
|
{
|
|
|
|
int totalAscChannels = 0;
|
2012-07-11 19:15:24 +02:00
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
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;
|
|
|
|
}
|
2012-07-11 19:15:24 +02:00
|
|
|
}
|
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
if (!(self->flags[streamIndex] & (AC_USAC | AC_RSVD50 | AC_RSV603DA))) {
|
2012-07-11 19:15:24 +02:00
|
|
|
int ch;
|
2018-02-26 20:17:00 +01:00
|
|
|
for (ch = 0; ch < el_channels; ch += 1) {
|
|
|
|
CPns_ResetData(&self->pAacDecoderChannelInfo[aacChannels + ch]
|
|
|
|
->data.aac.PnsData,
|
|
|
|
&self->pAacDecoderChannelInfo[aacChannels + ch]
|
|
|
|
->pComData->pnsInterChannelData);
|
2012-07-11 19:15:24 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
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) {
|
2012-07-11 19:15:24 +02:00
|
|
|
self->frameOK = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
if (self->frameOK) {
|
|
|
|
/* Lookup the element and decode it only if it belongs to the current
|
|
|
|
* program */
|
|
|
|
if (CProgramConfig_LookupElement(
|
|
|
|
pce, self->streamInfo.channelConfig,
|
2012-07-11 19:15:24 +02:00
|
|
|
self->pAacDecoderChannelInfo[aacChannels]->ElementInstanceTag,
|
2018-02-26 20:17:00 +01:00
|
|
|
aacChannels, self->chMapping, self->channelType,
|
|
|
|
self->channelIndices, (8), &previous_element_index,
|
|
|
|
self->elements, type)) {
|
|
|
|
channel_elements[channel_element_count++] = type;
|
|
|
|
aacChannels += el_channels;
|
|
|
|
} else {
|
2012-07-11 19:15:24 +02:00
|
|
|
self->frameOK = 0;
|
|
|
|
}
|
2013-08-28 01:28:09 +02:00
|
|
|
/* Create SBR element for SBR for upsampling for LFE elements,
|
2018-02-26 20:17:00 +01:00
|
|
|
and if SBR was implicitly signaled, because the first frame(s)
|
2013-08-28 01:28:09 +02:00
|
|
|
may not contain SBR payload (broken encoder, bit errors). */
|
2018-02-26 20:17:00 +01:00
|
|
|
if (self->frameOK &&
|
|
|
|
((self->flags[streamIndex] & AC_SBR_PRESENT) ||
|
|
|
|
(self->sbrEnabled == 1)) &&
|
|
|
|
!(self->flags[streamIndex] &
|
|
|
|
AC_USAC) /* Is done during explicit config set up */
|
|
|
|
) {
|
2012-07-11 19:15:24 +02:00
|
|
|
SBR_ERROR sbrError;
|
2018-02-26 20:17:00 +01:00
|
|
|
UCHAR configMode = 0;
|
|
|
|
UCHAR configChanged = 0;
|
|
|
|
configMode |= AC_CM_ALLOC_MEM;
|
2012-07-11 19:15:24 +02:00
|
|
|
|
|
|
|
sbrError = sbrDecoder_InitElement(
|
2018-02-26 20:17:00 +01:00
|
|
|
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);
|
2012-07-11 19:15:24 +02:00
|
|
|
if (sbrError != SBRDEC_OK) {
|
2018-02-26 20:17:00 +01:00
|
|
|
/* Do not try to apply SBR because initializing the element
|
|
|
|
* failed. */
|
2012-07-11 19:15:24 +02:00
|
|
|
self->sbrEnabled = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
el_cnt[type]++;
|
2018-02-26 20:17:00 +01:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
2012-07-11 19:15:24 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case ID_CCE:
|
|
|
|
/*
|
|
|
|
Consistency check
|
|
|
|
*/
|
2018-02-26 20:17:00 +01:00
|
|
|
if (el_cnt[type] > self->ascChannels[streamIndex]) {
|
2012-07-11 19:15:24 +02:00
|
|
|
ErrorStatus = AAC_DEC_DECODE_FRAME_ERROR;
|
|
|
|
self->frameOK = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
if (self->frameOK) {
|
|
|
|
CAacDecoderCommonData commonData;
|
|
|
|
CAacDecoderCommonStaticData commonStaticData;
|
|
|
|
CWorkBufferCore1 workBufferCore1;
|
|
|
|
commonStaticData.pWorkBufferCore1 = &workBufferCore1;
|
2012-07-11 19:15:24 +02:00
|
|
|
/* memory for spectral lines temporal on scratch */
|
2018-02-26 20:17:00 +01:00
|
|
|
C_AALLOC_SCRATCH_START(mdctSpec, FIXP_DBL, 1024);
|
2012-07-11 19:15:24 +02:00
|
|
|
|
|
|
|
/* create dummy channel for CCE parsing on stack */
|
2018-02-26 20:17:00 +01:00
|
|
|
CAacDecoderChannelInfo tmpAacDecoderChannelInfo,
|
|
|
|
*pTmpAacDecoderChannelInfo;
|
2012-07-11 19:15:24 +02:00
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
FDKmemclear(mdctSpec, 1024 * sizeof(FIXP_DBL));
|
2012-07-11 19:15:24 +02:00
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
tmpAacDecoderChannelInfo.pDynData = commonData.pAacDecoderDynamicData;
|
|
|
|
tmpAacDecoderChannelInfo.pComData = &commonData;
|
|
|
|
tmpAacDecoderChannelInfo.pComStaticData = &commonStaticData;
|
|
|
|
tmpAacDecoderChannelInfo.pSpectralCoefficient =
|
|
|
|
(SPECTRAL_PTR)mdctSpec;
|
2012-07-11 19:15:24 +02:00
|
|
|
/* Assume AAC-LC */
|
2018-02-26 20:17:00 +01:00
|
|
|
tmpAacDecoderChannelInfo.granuleLength =
|
|
|
|
self->streamInfo.aacSamplesPerFrame / 8;
|
2012-07-11 19:15:24 +02:00
|
|
|
/* Reset PNS data. */
|
2018-02-26 20:17:00 +01:00
|
|
|
CPns_ResetData(
|
|
|
|
&tmpAacDecoderChannelInfo.data.aac.PnsData,
|
|
|
|
&tmpAacDecoderChannelInfo.pComData->pnsInterChannelData);
|
2012-07-11 19:15:24 +02:00
|
|
|
pTmpAacDecoderChannelInfo = &tmpAacDecoderChannelInfo;
|
|
|
|
/* do CCE parsing */
|
2018-02-26 20:17:00 +01:00
|
|
|
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);
|
2012-07-11 19:15:24 +02:00
|
|
|
|
|
|
|
if (ErrorStatus) {
|
|
|
|
self->frameOK = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (self->frameOK) {
|
2018-02-26 20:17:00 +01:00
|
|
|
/* Lookup the element and decode it only if it belongs to the
|
|
|
|
* current program */
|
2012-07-11 19:15:24 +02:00
|
|
|
if (CProgramConfig_LookupElement(
|
2018-02-26 20:17:00 +01:00
|
|
|
pce, self->streamInfo.channelConfig,
|
|
|
|
pTmpAacDecoderChannelInfo->ElementInstanceTag, 0,
|
|
|
|
self->chMapping, self->channelType, self->channelIndices,
|
|
|
|
(8), &previous_element_index, self->elements, type)) {
|
2012-07-11 19:15:24 +02:00
|
|
|
/* decoding of CCE not supported */
|
2018-02-26 20:17:00 +01:00
|
|
|
} else {
|
2012-07-11 19:15:24 +02:00
|
|
|
self->frameOK = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
el_cnt[type]++;
|
|
|
|
break;
|
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
case ID_DSE: {
|
|
|
|
UCHAR element_instance_tag;
|
2012-07-11 19:15:24 +02:00
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
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;
|
2012-07-11 19:15:24 +02:00
|
|
|
}
|
2018-02-26 20:17:00 +01:00
|
|
|
/* 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;
|
2013-08-28 01:28:09 +02:00
|
|
|
}
|
2012-07-11 19:15:24 +02:00
|
|
|
}
|
2018-02-26 20:17:00 +01:00
|
|
|
pceRead = (result >= 0) ? 1 : 0;
|
|
|
|
} break;
|
2012-07-11 19:15:24 +02:00
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
case ID_FIL: {
|
|
|
|
int bitCnt = FDKreadBits(bs, 4); /* bs_count */
|
2012-07-11 19:15:24 +02:00
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
if (bitCnt == 15) {
|
|
|
|
int esc_count = FDKreadBits(bs, 8); /* bs_esc_count */
|
|
|
|
bitCnt = esc_count + 14;
|
|
|
|
}
|
2012-07-11 19:15:24 +02:00
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
/* Convert to bits */
|
|
|
|
bitCnt <<= 3;
|
2012-07-11 19:15:24 +02:00
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
while (bitCnt > 0) {
|
|
|
|
ErrorStatus = CAacDecoder_ExtPayloadParse(
|
|
|
|
self, bs, &bitCnt, previous_element, previous_element_index, 1);
|
|
|
|
if (ErrorStatus != AAC_DEC_OK) {
|
|
|
|
self->frameOK = 0;
|
|
|
|
break;
|
2012-07-11 19:15:24 +02:00
|
|
|
}
|
|
|
|
}
|
2018-02-26 20:17:00 +01:00
|
|
|
} break;
|
2012-07-11 19:15:24 +02:00
|
|
|
|
|
|
|
case ID_EXT:
|
2018-08-15 14:35:00 +02:00
|
|
|
if (element_count >= (3 * ((8) * 2) + (((8) * 2)) / 2 + 4 * (1) + 1)) {
|
|
|
|
self->frameOK = 0;
|
|
|
|
ErrorStatus = AAC_DEC_PARSE_ERROR;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
ErrorStatus = aacDecoder_ParseExplicitMpsAndSbr(
|
|
|
|
self, bs, previous_element, previous_element_index, element_count,
|
|
|
|
el_cnt);
|
|
|
|
break;
|
2012-07-11 19:15:24 +02:00
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
case ID_USAC_EXT: {
|
2018-08-15 14:35:00 +02:00
|
|
|
if ((element_count - element_count_prev_streams) >=
|
|
|
|
TP_USAC_MAX_ELEMENTS) {
|
|
|
|
self->frameOK = 0;
|
|
|
|
ErrorStatus = AAC_DEC_PARSE_ERROR;
|
|
|
|
break;
|
|
|
|
}
|
2018-02-26 20:17:00 +01:00
|
|
|
/* 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;
|
2012-07-11 19:15:24 +02:00
|
|
|
}
|
|
|
|
}
|
2018-02-26 20:17:00 +01:00
|
|
|
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; */
|
|
|
|
}
|
2012-07-11 19:15:24 +02:00
|
|
|
|
2018-05-23 18:26:27 +02:00
|
|
|
usacExtBitPos = (INT)FDKgetValidBits(bs);
|
2012-07-11 19:15:24 +02:00
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
USAC_EXT_ELEMENT_TYPE usacExtElementType =
|
|
|
|
self->pUsacConfig[streamIndex]
|
|
|
|
->element[element_count - element_count_prev_streams]
|
|
|
|
.extElement.usacExtElementType;
|
2016-04-08 21:05:12 +02:00
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
2012-07-11 19:15:24 +02:00
|
|
|
break;
|
2018-02-26 20:17:00 +01:00
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Skip any remaining bits of extension payload */
|
|
|
|
usacExtBitPos = (usacExtElementPayloadLength * 8) -
|
2018-05-23 18:26:27 +02:00
|
|
|
(usacExtBitPos - (INT)FDKgetValidBits(bs));
|
2018-02-26 20:17:00 +01:00
|
|
|
if (usacExtBitPos < 0) {
|
|
|
|
self->frameOK = 0;
|
|
|
|
ErrorStatus = AAC_DEC_PARSE_ERROR;
|
2012-07-11 19:15:24 +02:00
|
|
|
}
|
2018-02-26 20:17:00 +01:00
|
|
|
FDKpushBiDirectional(bs, usacExtBitPos);
|
2012-07-11 19:15:24 +02:00
|
|
|
}
|
|
|
|
}
|
2018-02-26 20:17:00 +01:00
|
|
|
} break;
|
2012-07-11 19:15:24 +02:00
|
|
|
case ID_END:
|
2018-02-26 20:17:00 +01:00
|
|
|
case ID_USAC_END:
|
2012-07-11 19:15:24 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
ErrorStatus = AAC_DEC_DECODE_FRAME_ERROR;
|
|
|
|
self->frameOK = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
previous_element = type;
|
|
|
|
element_count++;
|
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
} /* while ( (type != ID_END) ... ) */
|
2012-07-11 19:15:24 +02:00
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
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 */
|
2012-07-11 19:15:24 +02:00
|
|
|
/* Byte alignment with respect to the first bit of the raw_data_block(). */
|
2018-02-26 20:17:00 +01:00
|
|
|
if (!(self->flags[streamIndex] & (AC_RSVD50 | AC_USAC)) ||
|
|
|
|
(self->prerollAULength[self->accessUnit]) /* indicates preroll */
|
|
|
|
) {
|
2012-07-11 19:15:24 +02:00
|
|
|
FDKbyteAlign(bs, auStartAnchor);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check if all bits of the raw_data_block() have been read. */
|
2018-02-26 20:17:00 +01:00
|
|
|
if (transportDec_GetAuBitsTotal(self->hInput, 0) > 0) {
|
2012-07-11 19:15:24 +02:00
|
|
|
INT unreadBits = transportDec_GetAuBitsRemaining(self->hInput, 0);
|
2018-02-26 20:17:00 +01:00
|
|
|
/* 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;
|
|
|
|
}
|
2012-07-11 19:15:24 +02:00
|
|
|
|
|
|
|
/* Do not overwrite current error */
|
|
|
|
if (ErrorStatus == AAC_DEC_OK && self->frameOK == 0) {
|
|
|
|
ErrorStatus = AAC_DEC_PARSE_ERROR;
|
|
|
|
}
|
2018-02-26 20:17:00 +01:00
|
|
|
/* Always put the bitbuffer at the right position after the current
|
|
|
|
* Access Unit. */
|
2012-07-11 19:15:24 +02:00
|
|
|
FDKpushBiDirectional(bs, unreadBits);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
/* 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) {
|
2012-07-11 19:15:24 +02:00
|
|
|
/* Do not overwrite current error */
|
|
|
|
if (ErrorStatus == AAC_DEC_OK) {
|
|
|
|
ErrorStatus = AAC_DEC_PARSE_ERROR;
|
|
|
|
}
|
|
|
|
self->frameOK = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
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;
|
2012-07-11 19:15:24 +02:00
|
|
|
}
|
|
|
|
}
|
2018-02-26 20:17:00 +01:00
|
|
|
|
|
|
|
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++;
|
2012-07-11 19:15:24 +02:00
|
|
|
}
|
2018-02-26 20:17:00 +01:00
|
|
|
|
|
|
|
/* More AAC channels than specified by the ASC not allowed. */
|
|
|
|
if ((aacChannels == 0 || aacChannels > self->aacChannels) &&
|
|
|
|
!(flags & (AACDEC_CONCEAL | AACDEC_FLUSH))) {
|
2012-07-11 19:15:24 +02:00
|
|
|
/* Do not overwrite current error */
|
|
|
|
if (ErrorStatus == AAC_DEC_OK) {
|
2018-02-26 20:17:00 +01:00
|
|
|
ErrorStatus = AAC_DEC_DECODE_FRAME_ERROR;
|
2012-07-11 19:15:24 +02:00
|
|
|
}
|
|
|
|
self->frameOK = 0;
|
|
|
|
aacChannels = 0;
|
|
|
|
}
|
|
|
|
|
2018-10-19 16:45:56 +02:00
|
|
|
if (!(flags & (AACDEC_CONCEAL | AACDEC_FLUSH))) {
|
|
|
|
if (TRANSPORTDEC_OK != transportDec_CrcCheck(self->hInput)) {
|
|
|
|
ErrorStatus = AAC_DEC_CRC_ERROR;
|
|
|
|
self->frameOK = 0;
|
|
|
|
}
|
2012-07-11 19:15:24 +02:00
|
|
|
}
|
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
/* 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;
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
2012-07-11 19:15:24 +02:00
|
|
|
} else {
|
2018-02-26 20:17:00 +01:00
|
|
|
/* 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;
|
|
|
|
}
|
|
|
|
}
|
2012-07-11 19:15:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Update number of output channels */
|
2013-08-28 01:17:45 +02:00
|
|
|
self->streamInfo.aacNumChannels = aacChannels;
|
2012-07-11 19:15:24 +02:00
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
/* Ensure consistency of IS_OUTPUT_VALID() macro. */
|
|
|
|
if (aacChannels == 0) {
|
|
|
|
ErrorStatus = AAC_DEC_UNKNOWN;
|
|
|
|
}
|
|
|
|
|
2012-10-02 19:16:04 +02:00
|
|
|
if (pceRead == 1 && CProgramConfig_IsValid(pce)) {
|
2012-07-11 19:15:24 +02:00
|
|
|
/* Set matrix mixdown infos if available from PCE. */
|
2018-02-26 20:17:00 +01:00
|
|
|
pcmDmx_SetMatrixMixdownFromPce(
|
|
|
|
self->hPcmUtils, pce->MatrixMixdownIndexPresent,
|
|
|
|
pce->MatrixMixdownIndex, pce->PseudoSurroundEnable);
|
|
|
|
;
|
2012-07-11 19:15:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* If there is no valid data to transfrom into time domain, return. */
|
2018-02-26 20:17:00 +01:00
|
|
|
if (!IS_OUTPUT_VALID(ErrorStatus)) {
|
2012-07-11 19:15:24 +02:00
|
|
|
return ErrorStatus;
|
|
|
|
}
|
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
/* 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
|
2013-12-28 01:13:22 +01:00
|
|
|
* ---+-------+-----+--------+------------------
|
2018-02-26 20:17:00 +01:00
|
|
|
* 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".
|
2013-12-28 01:13:22 +01:00
|
|
|
*/
|
2018-02-26 20:17:00 +01:00
|
|
|
if ((self->streamInfo.channelConfig == 0) && !pce->isValid) {
|
|
|
|
self->chMapIndex = (aacChannels < 7) ? aacChannels : 0;
|
|
|
|
}
|
2013-12-28 01:13:22 +01:00
|
|
|
|
2012-07-11 19:15:24 +02:00
|
|
|
/*
|
|
|
|
Inverse transform
|
|
|
|
*/
|
|
|
|
{
|
2018-02-26 20:17:00 +01:00
|
|
|
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));
|
|
|
|
}
|
2012-07-11 19:15:24 +02:00
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
/* 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;
|
|
|
|
}
|
2012-07-11 19:15:24 +02:00
|
|
|
}
|
2018-02-26 20:17:00 +01:00
|
|
|
Reverse_chMapping[c] = d;
|
|
|
|
}
|
2012-07-11 19:15:24 +02:00
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
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];
|
2012-07-11 19:15:24 +02:00
|
|
|
} else {
|
2018-02-26 20:17:00 +01:00
|
|
|
type = channel_elements[el];
|
|
|
|
}
|
2012-07-11 19:15:24 +02:00
|
|
|
|
|
|
|
{
|
2018-02-26 20:17:00 +01:00
|
|
|
int nElementChannels;
|
|
|
|
|
|
|
|
nElementChannels =
|
|
|
|
CAacDecoder_GetELChannels(type, self->usacStereoConfigIndex[el]);
|
|
|
|
|
|
|
|
el_channels += nElementChannels;
|
|
|
|
|
|
|
|
if (nElementChannels == 0) {
|
|
|
|
continue;
|
|
|
|
}
|
2012-07-11 19:15:24 +02:00
|
|
|
}
|
2018-02-26 20:17:00 +01:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
2012-07-11 19:15:24 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
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++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-07-11 19:15:24 +02:00
|
|
|
|
|
|
|
/* Extract DRC control data and map it to channels (with bitstream delay) */
|
2018-02-26 20:17:00 +01:00
|
|
|
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;
|
|
|
|
}
|
2012-07-11 19:15:24 +02:00
|
|
|
}
|
|
|
|
|
2014-05-21 02:24:06 +02:00
|
|
|
/* Add additional concealment delay */
|
2018-02-26 20:17:00 +01:00
|
|
|
self->streamInfo.outputDelay +=
|
|
|
|
CConcealment_GetDelay(&self->concealCommonData) *
|
|
|
|
self->streamInfo.aacSamplesPerFrame;
|
2012-07-11 19:15:24 +02:00
|
|
|
|
2014-05-21 02:29:03 +02:00
|
|
|
/* Map DRC data to StreamInfo structure */
|
2018-02-26 20:17:00 +01:00
|
|
|
aacDecoder_drcGetInfo(self->hDrcInfo, &self->streamInfo.drcPresMode,
|
|
|
|
&self->streamInfo.drcProgRefLev);
|
2014-05-21 02:29:03 +02:00
|
|
|
|
2012-07-11 19:15:24 +02:00
|
|
|
/* Reorder channel type information tables. */
|
2018-02-26 20:17:00 +01:00
|
|
|
if (!(self->flags[0] & AC_RSV603DA)) {
|
2013-12-28 01:13:22 +01:00
|
|
|
AUDIO_CHANNEL_TYPE types[(8)];
|
|
|
|
UCHAR idx[(8)];
|
2012-07-11 19:15:24 +02:00
|
|
|
int c;
|
2018-02-26 20:17:00 +01:00
|
|
|
int mapValue;
|
2012-07-11 19:15:24 +02:00
|
|
|
|
|
|
|
FDK_ASSERT(sizeof(self->channelType) == sizeof(types));
|
|
|
|
FDK_ASSERT(sizeof(self->channelIndices) == sizeof(idx));
|
|
|
|
|
|
|
|
FDKmemcpy(types, self->channelType, sizeof(types));
|
|
|
|
FDKmemcpy(idx, self->channelIndices, sizeof(idx));
|
|
|
|
|
2018-02-26 20:17:00 +01:00
|
|
|
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];
|
2012-07-11 19:15:24 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
self->blockNumber++;
|
|
|
|
|
|
|
|
return ErrorStatus;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
\brief returns the streaminfo pointer
|
|
|
|
|
|
|
|
The function hands back a pointer to the streaminfo structure
|
|
|
|
|
|
|
|
\return pointer to the struct
|
|
|
|
*/
|
2018-02-26 20:17:00 +01:00
|
|
|
LINKSPEC_CPP CStreamInfo *CAacDecoder_GetStreamInfo(HANDLE_AACDECODER self) {
|
2012-07-11 19:15:24 +02:00
|
|
|
if (!self) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
return &self->streamInfo;
|
|
|
|
}
|