aboutsummaryrefslogtreecommitdiffstats
path: root/libSBRdec/src/sbrdecoder.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libSBRdec/src/sbrdecoder.cpp')
-rw-r--r--libSBRdec/src/sbrdecoder.cpp1968
1 files changed, 1112 insertions, 856 deletions
diff --git a/libSBRdec/src/sbrdecoder.cpp b/libSBRdec/src/sbrdecoder.cpp
index f9ded54..e2455da 100644
--- a/libSBRdec/src/sbrdecoder.cpp
+++ b/libSBRdec/src/sbrdecoder.cpp
@@ -1,74 +1,85 @@
-
-/* -----------------------------------------------------------------------------------------------------------
+/* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
-© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
- All rights reserved.
+© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten
+Forschung e.V. All rights reserved.
1. INTRODUCTION
-The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements
-the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio.
-This FDK AAC Codec software is intended to be used on a wide variety of Android devices.
-
-AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual
-audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by
-independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part
-of the MPEG specifications.
-
-Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer)
-may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners
-individually for the purpose of encoding or decoding bit streams in products that are compliant with
-the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license
-these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec
-software may already be covered under those patent licenses when it is used for those licensed purposes only.
-
-Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality,
-are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional
-applications information and documentation.
+The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software
+that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding
+scheme for digital audio. This FDK AAC Codec software is intended to be used on
+a wide variety of Android devices.
+
+AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient
+general perceptual audio codecs. AAC-ELD is considered the best-performing
+full-bandwidth communications codec by independent studies and is widely
+deployed. AAC has been standardized by ISO and IEC as part of the MPEG
+specifications.
+
+Patent licenses for necessary patent claims for the FDK AAC Codec (including
+those of Fraunhofer) may be obtained through Via Licensing
+(www.vialicensing.com) or through the respective patent owners individually for
+the purpose of encoding or decoding bit streams in products that are compliant
+with the ISO/IEC MPEG audio standards. Please note that most manufacturers of
+Android devices already license these patent claims through Via Licensing or
+directly from the patent owners, and therefore FDK AAC Codec software may
+already be covered under those patent licenses when it is used for those
+licensed purposes only.
+
+Commercially-licensed AAC software libraries, including floating-point versions
+with enhanced sound quality, are also available from Fraunhofer. Users are
+encouraged to check the Fraunhofer website for additional applications
+information and documentation.
2. COPYRIGHT LICENSE
-Redistribution and use in source and binary forms, with or without modification, are permitted without
-payment of copyright license fees provided that you satisfy the following conditions:
+Redistribution and use in source and binary forms, with or without modification,
+are permitted without payment of copyright license fees provided that you
+satisfy the following conditions:
-You must retain the complete text of this software license in redistributions of the FDK AAC Codec or
-your modifications thereto in source code form.
+You must retain the complete text of this software license in redistributions of
+the FDK AAC Codec or your modifications thereto in source code form.
-You must retain the complete text of this software license in the documentation and/or other materials
-provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form.
-You must make available free of charge copies of the complete source code of the FDK AAC Codec and your
+You must retain the complete text of this software license in the documentation
+and/or other materials provided with redistributions of the FDK AAC Codec or
+your modifications thereto in binary form. You must make available free of
+charge copies of the complete source code of the FDK AAC Codec and your
modifications thereto to recipients of copies in binary form.
-The name of Fraunhofer may not be used to endorse or promote products derived from this library without
-prior written permission.
+The name of Fraunhofer may not be used to endorse or promote products derived
+from this library without prior written permission.
-You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec
-software or your modifications thereto.
+You may not charge copyright license fees for anyone to use, copy or distribute
+the FDK AAC Codec software or your modifications thereto.
-Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software
-and the date of any change. For modified versions of the FDK AAC Codec, the term
-"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term
-"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android."
+Your modified versions of the FDK AAC Codec must carry prominent notices stating
+that you changed the software and the date of any change. For modified versions
+of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android"
+must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK
+AAC Codec Library for Android."
3. NO PATENT LICENSE
-NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer,
-ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with
-respect to this software.
+NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without
+limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE.
+Fraunhofer provides no warranty of patent non-infringement with respect to this
+software.
-You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized
-by appropriate patent licenses.
+You may use this FDK AAC Codec software or modifications thereto only for
+purposes that are authorized by appropriate patent licenses.
4. DISCLAIMER
-This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors
-"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties
-of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
-CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages,
-including but not limited to procurement of substitute goods or services; loss of use, data, or profits,
-or business interruption, however caused and on any theory of liability, whether in contract, strict
-liability, or tort (including negligence), arising in any way out of the use of this software, even if
-advised of the possibility of such damage.
+This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright
+holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
+including but not limited to the implied warranties of merchantability and
+fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary,
+or consequential damages, including but not limited to procurement of substitute
+goods or services; loss of use, data, or profits, or business interruption,
+however caused and on any theory of liability, whether in contract, strict
+liability, or tort (including negligence), arising in any way out of the use of
+this software, even if advised of the possibility of such damage.
5. CONTACT INFORMATION
@@ -79,38 +90,48 @@ Am Wolfsmantel 33
www.iis.fraunhofer.de/amm
amm-info@iis.fraunhofer.de
------------------------------------------------------------------------------------------------------------ */
+----------------------------------------------------------------------------- */
+
+/**************************** SBR decoder library ******************************
+
+ Author(s):
+
+ Description:
+
+*******************************************************************************/
/*!
\file
\brief SBR decoder frontend
- This module provides a frontend to the SBR decoder. The function openSBR() is called for
- initialization. The function sbrDecoder_Apply() is called for each frame. sbr_Apply() will call the
- required functions to decode the raw SBR data (provided by env_extr.cpp), to decode the envelope data and noise floor levels [decodeSbrData()],
- and to finally apply SBR to the current frame [sbr_dec()].
+ This module provides a frontend to the SBR decoder. The function openSBR() is
+ called for initialization. The function sbrDecoder_Apply() is called for each
+ frame. sbr_Apply() will call the required functions to decode the raw SBR data
+ (provided by env_extr.cpp), to decode the envelope data and noise floor levels
+ [decodeSbrData()], and to finally apply SBR to the current frame [sbr_dec()].
\sa sbrDecoder_Apply(), \ref documentationOverview
*/
/*!
- \page documentationOverview Overview of important information resources and source code documentation
+ \page documentationOverview Overview of important information resources and
+ source code documentation
- The primary source code documentation is based on generated and cross-referenced HTML files using
- <a HREF="http://www.doxygen.org">doxygen</a>. As part of this documentation
- you can find more extensive descriptions about key concepts and algorithms at the following locations:
+ As part of this documentation you can find more extensive descriptions about
+ key concepts and algorithms at the following locations:
<h2>Programming</h2>
\li Buffer management: sbrDecoder_Apply() and sbr_dec()
- \li Internal scale factors to maximize SNR on fixed point processors: #QMF_SCALE_FACTOR
- \li Special mantissa-exponent format: Created in requantizeEnvelopeData() and used in calculateSbrEnvelope()
+ \li Internal scale factors to maximize SNR on fixed point processors:
+ #QMF_SCALE_FACTOR \li Special mantissa-exponent format: Created in
+ requantizeEnvelopeData() and used in calculateSbrEnvelope()
<h2>Algorithmic details</h2>
- \li About the SBR data format: \ref SBR_HEADER_ELEMENT and \ref SBR_STANDARD_ELEMENT
- \li Details about the bitstream decoder: env_extr.cpp
- \li Details about the QMF filterbank and the provided polyphase implementation: qmf_dec.cpp
- \li Details about the transposer: lpp_tran.cpp
- \li Details about the envelope adjuster: env_calc.cpp
+ \li About the SBR data format: \ref SBR_HEADER_ELEMENT and \ref
+ SBR_STANDARD_ELEMENT \li Details about the bitstream decoder: env_extr.cpp \li
+ Details about the QMF filterbank and the provided polyphase implementation:
+ qmf_dec.cpp \li Details about the transposer: lpp_tran.cpp \li Details about
+ the envelope adjuster: env_calc.cpp
*/
@@ -134,11 +155,10 @@ amm-info@iis.fraunhofer.de
#include "psbitdec.h"
-
/* Decoder library info */
-#define SBRDECODER_LIB_VL0 2
-#define SBRDECODER_LIB_VL1 2
-#define SBRDECODER_LIB_VL2 12
+#define SBRDECODER_LIB_VL0 3
+#define SBRDECODER_LIB_VL1 0
+#define SBRDECODER_LIB_VL2 0
#define SBRDECODER_LIB_TITLE "SBR Decoder"
#ifdef __ANDROID__
#define SBRDECODER_LIB_BUILD_DATE ""
@@ -148,20 +168,28 @@ amm-info@iis.fraunhofer.de
#define SBRDECODER_LIB_BUILD_TIME __TIME__
#endif
+static void setFrameErrorFlag(SBR_DECODER_ELEMENT *pSbrElement, UCHAR value) {
+ if (pSbrElement != NULL) {
+ switch (value) {
+ case FRAME_ERROR_ALLSLOTS:
+ FDKmemset(pSbrElement->frameErrorFlag, FRAME_ERROR,
+ sizeof(pSbrElement->frameErrorFlag));
+ break;
+ default:
+ pSbrElement->frameErrorFlag[pSbrElement->useFrameSlot] = value;
+ }
+ }
+}
-
-
-static UCHAR getHeaderSlot( UCHAR currentSlot, UCHAR hdrSlotUsage[(1)+1] )
-{
- UINT occupied = 0;
- int s;
+static UCHAR getHeaderSlot(UCHAR currentSlot, UCHAR hdrSlotUsage[(1) + 1]) {
+ UINT occupied = 0;
+ int s;
UCHAR slot = hdrSlotUsage[currentSlot];
- FDK_ASSERT((1)+1 < 32);
+ FDK_ASSERT((1) + 1 < 32);
- for (s = 0; s < (1)+1; s++) {
- if ( (hdrSlotUsage[s] == slot)
- && (s != slot) ) {
+ for (s = 0; s < (1) + 1; s++) {
+ if ((hdrSlotUsage[s] == slot) && (s != slot)) {
occupied = 1;
break;
}
@@ -170,11 +198,11 @@ static UCHAR getHeaderSlot( UCHAR currentSlot, UCHAR hdrSlotUsage[(1)+1] )
if (occupied) {
occupied = 0;
- for (s = 0; s < (1)+1; s++) {
+ for (s = 0; s < (1) + 1; s++) {
occupied |= 1 << hdrSlotUsage[s];
}
- for (s = 0; s < (1)+1; s++) {
- if ( !(occupied & 0x1) ) {
+ for (s = 0; s < (1) + 1; s++) {
+ if (!(occupied & 0x1)) {
slot = s;
break;
}
@@ -185,18 +213,18 @@ static UCHAR getHeaderSlot( UCHAR currentSlot, UCHAR hdrSlotUsage[(1)+1] )
return slot;
}
-static void copySbrHeader( HANDLE_SBR_HEADER_DATA hDst, const HANDLE_SBR_HEADER_DATA hSrc )
-{
+static void copySbrHeader(HANDLE_SBR_HEADER_DATA hDst,
+ const HANDLE_SBR_HEADER_DATA hSrc) {
/* copy the whole header memory (including pointers) */
- FDKmemcpy( hDst, hSrc, sizeof(SBR_HEADER_DATA) );
+ FDKmemcpy(hDst, hSrc, sizeof(SBR_HEADER_DATA));
/* update pointers */
- hDst->freqBandData.freqBandTable[0] = hDst->freqBandData.freqBandTableLo;
+ hDst->freqBandData.freqBandTable[0] = hDst->freqBandData.freqBandTableLo;
hDst->freqBandData.freqBandTable[1] = hDst->freqBandData.freqBandTableHi;
}
-static int compareSbrHeader( const HANDLE_SBR_HEADER_DATA hHdr1, const HANDLE_SBR_HEADER_DATA hHdr2 )
-{
+static int compareSbrHeader(const HANDLE_SBR_HEADER_DATA hHdr1,
+ const HANDLE_SBR_HEADER_DATA hHdr2) {
int result = 0;
/* compare basic data */
@@ -204,25 +232,38 @@ static int compareSbrHeader( const HANDLE_SBR_HEADER_DATA hHdr1, const HANDLE_SB
result |= (hHdr1->status != hHdr2->status) ? 1 : 0;
result |= (hHdr1->frameErrorFlag != hHdr2->frameErrorFlag) ? 1 : 0;
result |= (hHdr1->numberTimeSlots != hHdr2->numberTimeSlots) ? 1 : 0;
- result |= (hHdr1->numberOfAnalysisBands != hHdr2->numberOfAnalysisBands) ? 1 : 0;
+ result |=
+ (hHdr1->numberOfAnalysisBands != hHdr2->numberOfAnalysisBands) ? 1 : 0;
result |= (hHdr1->timeStep != hHdr2->timeStep) ? 1 : 0;
result |= (hHdr1->sbrProcSmplRate != hHdr2->sbrProcSmplRate) ? 1 : 0;
/* compare bitstream data */
- result |= FDKmemcmp( &hHdr1->bs_data, &hHdr2->bs_data, sizeof(SBR_HEADER_DATA_BS) );
- result |= FDKmemcmp( &hHdr1->bs_info, &hHdr2->bs_info, sizeof(SBR_HEADER_DATA_BS_INFO) );
+ result |=
+ FDKmemcmp(&hHdr1->bs_data, &hHdr2->bs_data, sizeof(SBR_HEADER_DATA_BS));
+ result |=
+ FDKmemcmp(&hHdr1->bs_dflt, &hHdr2->bs_dflt, sizeof(SBR_HEADER_DATA_BS));
+ result |= FDKmemcmp(&hHdr1->bs_info, &hHdr2->bs_info,
+ sizeof(SBR_HEADER_DATA_BS_INFO));
/* compare frequency band data */
- result |= FDKmemcmp( &hHdr1->freqBandData, &hHdr2->freqBandData, (8+MAX_NUM_LIMITERS+1)*sizeof(UCHAR) );
- result |= FDKmemcmp( hHdr1->freqBandData.freqBandTableLo, hHdr2->freqBandData.freqBandTableLo, (MAX_FREQ_COEFFS/2+1)*sizeof(UCHAR) );
- result |= FDKmemcmp( hHdr1->freqBandData.freqBandTableHi, hHdr2->freqBandData.freqBandTableHi, (MAX_FREQ_COEFFS+1)*sizeof(UCHAR) );
- result |= FDKmemcmp( hHdr1->freqBandData.freqBandTableNoise, hHdr2->freqBandData.freqBandTableNoise, (MAX_NOISE_COEFFS+1)*sizeof(UCHAR) );
- result |= FDKmemcmp( hHdr1->freqBandData.v_k_master, hHdr2->freqBandData.v_k_master, (MAX_FREQ_COEFFS+1)*sizeof(UCHAR) );
+ result |= FDKmemcmp(&hHdr1->freqBandData, &hHdr2->freqBandData,
+ (8 + MAX_NUM_LIMITERS + 1) * sizeof(UCHAR));
+ result |= FDKmemcmp(hHdr1->freqBandData.freqBandTableLo,
+ hHdr2->freqBandData.freqBandTableLo,
+ (MAX_FREQ_COEFFS / 2 + 1) * sizeof(UCHAR));
+ result |= FDKmemcmp(hHdr1->freqBandData.freqBandTableHi,
+ hHdr2->freqBandData.freqBandTableHi,
+ (MAX_FREQ_COEFFS + 1) * sizeof(UCHAR));
+ result |= FDKmemcmp(hHdr1->freqBandData.freqBandTableNoise,
+ hHdr2->freqBandData.freqBandTableNoise,
+ (MAX_NOISE_COEFFS + 1) * sizeof(UCHAR));
+ result |=
+ FDKmemcmp(hHdr1->freqBandData.v_k_master, hHdr2->freqBandData.v_k_master,
+ (MAX_FREQ_COEFFS + 1) * sizeof(UCHAR));
return result;
}
-
/*!
\brief Reset SBR decoder.
@@ -231,60 +272,54 @@ static int compareSbrHeader( const HANDLE_SBR_HEADER_DATA hHdr1, const HANDLE_SB
\return Error code.
*/
-static
-SBR_ERROR sbrDecoder_ResetElement (
- HANDLE_SBRDECODER self,
- int sampleRateIn,
- int sampleRateOut,
- int samplesPerFrame,
- const MP4_ELEMENT_ID elementID,
- const int elementIndex,
- const int overlap
- )
-{
+static SBR_ERROR sbrDecoder_ResetElement(HANDLE_SBRDECODER self,
+ int sampleRateIn, int sampleRateOut,
+ int samplesPerFrame,
+ const MP4_ELEMENT_ID elementID,
+ const int elementIndex,
+ const int overlap) {
SBR_ERROR sbrError = SBRDEC_OK;
HANDLE_SBR_HEADER_DATA hSbrHeader;
UINT qmfFlags = 0;
int i, synDownsampleFac;
+ /* USAC: assuming theoretical case 8 kHz output sample rate with 4:1 SBR */
+ const int sbr_min_sample_rate_in = IS_USAC(self->coreCodec) ? 2000 : 6400;
+
/* Check in/out samplerates */
- if ( sampleRateIn < 6400
- || sampleRateIn > 48000
- )
- {
+ if (sampleRateIn < sbr_min_sample_rate_in || sampleRateIn > (96000)) {
sbrError = SBRDEC_UNSUPPORTED_CONFIG;
goto bail;
}
- if ( sampleRateOut > 96000 )
- {
+ if (sampleRateOut > (96000)) {
sbrError = SBRDEC_UNSUPPORTED_CONFIG;
goto bail;
}
/* Set QMF mode flags */
- if (self->flags & SBRDEC_LOW_POWER)
- qmfFlags |= QMF_FLAG_LP;
+ if (self->flags & SBRDEC_LOW_POWER) qmfFlags |= QMF_FLAG_LP;
if (self->coreCodec == AOT_ER_AAC_ELD) {
if (self->flags & SBRDEC_LD_MPS_QMF) {
- qmfFlags |= QMF_FLAG_MPSLDFB;
+ qmfFlags |= QMF_FLAG_MPSLDFB;
} else {
- qmfFlags |= QMF_FLAG_CLDFB;
+ qmfFlags |= QMF_FLAG_CLDFB;
}
}
/* Set downsampling factor for synthesis filter bank */
- if (sampleRateOut == 0)
- {
+ if (sampleRateOut == 0) {
/* no single rate mode */
- sampleRateOut = sampleRateIn<<1; /* In case of implicit signalling, assume dual rate SBR */
+ sampleRateOut =
+ sampleRateIn
+ << 1; /* In case of implicit signalling, assume dual rate SBR */
}
- if ( sampleRateIn == sampleRateOut ) {
+ if (sampleRateIn == sampleRateOut) {
synDownsampleFac = 2;
- self->flags |= SBRDEC_DOWNSAMPLE;
+ self->flags |= SBRDEC_DOWNSAMPLE;
} else {
synDownsampleFac = 1;
self->flags &= ~SBRDEC_DOWNSAMPLE;
@@ -294,20 +329,23 @@ SBR_ERROR sbrDecoder_ResetElement (
self->sampleRateOut = sampleRateOut;
{
- int i;
-
- for (i = 0; i < (1)+1; i++)
- {
+ for (i = 0; i < (1) + 1; i++) {
+ int setDflt;
hSbrHeader = &(self->sbrHeader[elementIndex][i]);
+ setDflt = ((hSbrHeader->syncState == SBR_NOT_INITIALIZED) ||
+ (self->flags & SBRDEC_FORCE_RESET))
+ ? 1
+ : 0;
/* init a default header such that we can at least do upsampling later */
- sbrError = initHeaderData(
- hSbrHeader,
- sampleRateIn,
- sampleRateOut,
- samplesPerFrame,
- self->flags
- );
+ sbrError = initHeaderData(hSbrHeader, sampleRateIn, sampleRateOut,
+ self->downscaleFactor, samplesPerFrame,
+ self->flags, setDflt);
+
+ /* Set synchState to UPSAMPLING in case it already is initialized */
+ hSbrHeader->syncState = hSbrHeader->syncState > UPSAMPLING
+ ? UPSAMPLING
+ : hSbrHeader->syncState;
}
}
@@ -315,21 +353,38 @@ SBR_ERROR sbrDecoder_ResetElement (
goto bail;
}
+ if (!self->pQmfDomain->globalConf.qmfDomainExplicitConfig) {
+ self->pQmfDomain->globalConf.flags_requested |= qmfFlags;
+ self->pQmfDomain->globalConf.nBandsAnalysis_requested =
+ self->sbrHeader[elementIndex][0].numberOfAnalysisBands;
+ self->pQmfDomain->globalConf.nBandsSynthesis_requested =
+ (synDownsampleFac == 1) ? 64 : 32; /* may be overwritten by MPS */
+ self->pQmfDomain->globalConf.nBandsSynthesis_requested /=
+ self->downscaleFactor;
+ self->pQmfDomain->globalConf.nQmfTimeSlots_requested =
+ self->sbrHeader[elementIndex][0].numberTimeSlots *
+ self->sbrHeader[elementIndex][0].timeStep;
+ self->pQmfDomain->globalConf.nQmfOvTimeSlots_requested = overlap;
+ self->pQmfDomain->globalConf.nQmfProcBands_requested = 64; /* always 64 */
+ self->pQmfDomain->globalConf.nQmfProcChannels_requested =
+ 1; /* may be overwritten by MPS */
+ }
+
/* Init SBR channels going to be assigned to a SBR element */
{
int ch;
+ for (ch = 0; ch < self->pSbrElement[elementIndex]->nChannels; ch++) {
+ int headerIndex =
+ getHeaderSlot(self->pSbrElement[elementIndex]->useFrameSlot,
+ self->pSbrElement[elementIndex]->useHeaderSlot);
- for (ch=0; ch<self->pSbrElement[elementIndex]->nChannels; ch++)
- {
/* and create sbrDec */
- sbrError = createSbrDec (self->pSbrElement[elementIndex]->pSbrChannel[ch],
- hSbrHeader,
- &self->pSbrElement[elementIndex]->transposerSettings,
- synDownsampleFac,
- qmfFlags,
- self->flags,
- overlap,
- ch );
+ sbrError =
+ createSbrDec(self->pSbrElement[elementIndex]->pSbrChannel[ch],
+ &self->sbrHeader[elementIndex][headerIndex],
+ &self->pSbrElement[elementIndex]->transposerSettings,
+ synDownsampleFac, qmfFlags, self->flags, overlap, ch,
+ self->codecFrameSize);
if (sbrError != SBRDEC_OK) {
goto bail;
@@ -337,28 +392,29 @@ SBR_ERROR sbrDecoder_ResetElement (
}
}
- //FDKmemclear(sbr_OverlapBuffer, sizeof(sbr_OverlapBuffer));
+ // FDKmemclear(sbr_OverlapBuffer, sizeof(sbr_OverlapBuffer));
if (self->numSbrElements == 1) {
- switch ( self->coreCodec ) {
- case AOT_AAC_LC:
- case AOT_SBR:
- case AOT_PS:
- case AOT_ER_AAC_SCAL:
- case AOT_DRM_AAC:
- if (CreatePsDec ( &self->hParametricStereoDec, samplesPerFrame )) {
- sbrError = SBRDEC_CREATE_ERROR;
- goto bail;
- }
- break;
- default:
- break;
+ switch (self->coreCodec) {
+ case AOT_AAC_LC:
+ case AOT_SBR:
+ case AOT_PS:
+ case AOT_ER_AAC_SCAL:
+ case AOT_DRM_AAC:
+ case AOT_DRM_SURROUND:
+ if (CreatePsDec(&self->hParametricStereoDec, samplesPerFrame)) {
+ sbrError = SBRDEC_CREATE_ERROR;
+ goto bail;
+ }
+ break;
+ default:
+ break;
}
}
/* Init frame delay slot handling */
self->pSbrElement[elementIndex]->useFrameSlot = 0;
- for (i = 0; i < ((1)+1); i++) {
+ for (i = 0; i < ((1) + 1); i++) {
self->pSbrElement[elementIndex]->useHeaderSlot[i] = i;
}
@@ -367,11 +423,37 @@ bail:
return sbrError;
}
+/*!
+ \brief Assign QMF domain provided QMF channels to SBR channels.
+
+ \return void
+*/
+static void sbrDecoder_AssignQmfChannels2SbrChannels(HANDLE_SBRDECODER self) {
+ int ch, el, absCh_offset = 0;
+ for (el = 0; el < self->numSbrElements; el++) {
+ if (self->pSbrElement[el] != NULL) {
+ for (ch = 0; ch < self->pSbrElement[el]->nChannels; ch++) {
+ FDK_ASSERT(((absCh_offset + ch) < ((8) + (1))) &&
+ ((absCh_offset + ch) < ((8) + (1))));
+ self->pSbrElement[el]->pSbrChannel[ch]->SbrDec.qmfDomainInCh =
+ &self->pQmfDomain->QmfDomainIn[absCh_offset + ch];
+ self->pSbrElement[el]->pSbrChannel[ch]->SbrDec.qmfDomainOutCh =
+ &self->pQmfDomain->QmfDomainOut[absCh_offset + ch];
+ }
+ absCh_offset += self->pSbrElement[el]->nChannels;
+ }
+ }
+}
-SBR_ERROR sbrDecoder_Open ( HANDLE_SBRDECODER * pSelf )
-{
- HANDLE_SBRDECODER self = NULL;
+SBR_ERROR sbrDecoder_Open(HANDLE_SBRDECODER *pSelf,
+ HANDLE_FDK_QMF_DOMAIN pQmfDomain) {
+ HANDLE_SBRDECODER self = NULL;
SBR_ERROR sbrError = SBRDEC_OK;
+ int elIdx;
+
+ if ((pSelf == NULL) || (pQmfDomain == NULL)) {
+ return SBRDEC_INVALID_ARGUMENT;
+ }
/* Get memory for this instance */
self = GetRam_SbrDecoder();
@@ -380,15 +462,7 @@ SBR_ERROR sbrDecoder_Open ( HANDLE_SBRDECODER * pSelf )
goto bail;
}
- self->workBuffer1 = GetRam_SbrDecWorkBuffer1();
- self->workBuffer2 = GetRam_SbrDecWorkBuffer2();
-
- if ( self->workBuffer1 == NULL
- || self->workBuffer2 == NULL )
- {
- sbrError = SBRDEC_MEM_ALLOC_FAILED;
- goto bail;
- }
+ self->pQmfDomain = pQmfDomain;
/*
Already zero because of calloc
@@ -397,7 +471,15 @@ SBR_ERROR sbrDecoder_Open ( HANDLE_SBRDECODER * pSelf )
self->codecFrameSize = 0;
*/
- self->numDelayFrames = (1); /* set to the max value by default */
+ self->numDelayFrames = (1); /* set to the max value by default */
+
+ /* Initialize header sync state */
+ for (elIdx = 0; elIdx < (8); elIdx += 1) {
+ int i;
+ for (i = 0; i < (1) + 1; i += 1) {
+ self->sbrHeader[elIdx][i].syncState = SBR_NOT_INITIALIZED;
+ }
+ }
*pSelf = self;
@@ -410,9 +492,7 @@ bail:
* \param coreCodec core codec audio object type.
* \return 1 if SBR can be processed, 0 if SBR cannot be processed/applied.
*/
-static
-int sbrDecoder_isCoreCodecValid(AUDIO_OBJECT_TYPE coreCodec)
-{
+static int sbrDecoder_isCoreCodecValid(AUDIO_OBJECT_TYPE coreCodec) {
switch (coreCodec) {
case AOT_AAC_LC:
case AOT_SBR:
@@ -420,80 +500,109 @@ int sbrDecoder_isCoreCodecValid(AUDIO_OBJECT_TYPE coreCodec)
case AOT_ER_AAC_SCAL:
case AOT_ER_AAC_ELD:
case AOT_DRM_AAC:
+ case AOT_DRM_SURROUND:
+ case AOT_USAC:
return 1;
default:
return 0;
}
}
-static
-void sbrDecoder_DestroyElement (
- HANDLE_SBRDECODER self,
- const int elementIndex
- )
-{
+static void sbrDecoder_DestroyElement(HANDLE_SBRDECODER self,
+ const int elementIndex) {
if (self->pSbrElement[elementIndex] != NULL) {
int ch;
- for (ch=0; ch<SBRDEC_MAX_CH_PER_ELEMENT; ch++) {
+ for (ch = 0; ch < SBRDEC_MAX_CH_PER_ELEMENT; ch++) {
if (self->pSbrElement[elementIndex]->pSbrChannel[ch] != NULL) {
- deleteSbrDec( self->pSbrElement[elementIndex]->pSbrChannel[ch] );
- FreeRam_SbrDecChannel( &self->pSbrElement[elementIndex]->pSbrChannel[ch] );
+ deleteSbrDec(self->pSbrElement[elementIndex]->pSbrChannel[ch]);
+ FreeRam_SbrDecChannel(
+ &self->pSbrElement[elementIndex]->pSbrChannel[ch]);
self->numSbrChannels -= 1;
}
}
- FreeRam_SbrDecElement( &self->pSbrElement[elementIndex] );
+ FreeRam_SbrDecElement(&self->pSbrElement[elementIndex]);
self->numSbrElements -= 1;
}
}
-
-SBR_ERROR sbrDecoder_InitElement (
- HANDLE_SBRDECODER self,
- const int sampleRateIn,
- const int sampleRateOut,
- const int samplesPerFrame,
- const AUDIO_OBJECT_TYPE coreCodec,
- const MP4_ELEMENT_ID elementID,
- const int elementIndex
- )
-{
+SBR_ERROR sbrDecoder_InitElement(
+ HANDLE_SBRDECODER self, const int sampleRateIn, const int sampleRateOut,
+ const int samplesPerFrame, const AUDIO_OBJECT_TYPE coreCodec,
+ const MP4_ELEMENT_ID elementID, const int elementIndex,
+ const UCHAR harmonicSBR, const UCHAR stereoConfigIndex,
+ const UCHAR configMode, UCHAR *configChanged, const INT downscaleFactor) {
SBR_ERROR sbrError = SBRDEC_OK;
- int chCnt=0;
- int nSbrElementsStart = self->numSbrElements;
+ int chCnt = 0;
+ int nSbrElementsStart;
+ int nSbrChannelsStart;
+ if (self == NULL) {
+ return SBRDEC_INVALID_ARGUMENT;
+ }
+
+ nSbrElementsStart = self->numSbrElements;
+ nSbrChannelsStart = self->numSbrChannels;
/* Check core codec AOT */
- if (! sbrDecoder_isCoreCodecValid(coreCodec) || elementIndex >= (8)) {
+ if (!sbrDecoder_isCoreCodecValid(coreCodec) || elementIndex >= (8)) {
sbrError = SBRDEC_UNSUPPORTED_CONFIG;
goto bail;
}
- if ( elementID != ID_SCE && elementID != ID_CPE && elementID != ID_LFE )
- {
+ if (elementID != ID_SCE && elementID != ID_CPE && elementID != ID_LFE) {
sbrError = SBRDEC_UNSUPPORTED_CONFIG;
goto bail;
}
- if ( self->sampleRateIn == sampleRateIn
- && self->codecFrameSize == samplesPerFrame
- && self->coreCodec == coreCodec
- && self->pSbrElement[elementIndex] != NULL
- && self->pSbrElement[elementIndex]->elementID == elementID
- && !(self->flags & SBRDEC_FORCE_RESET)
- )
- {
- /* Nothing to do */
- return SBRDEC_OK;
+ if (self->sampleRateIn == sampleRateIn &&
+ self->codecFrameSize == samplesPerFrame && self->coreCodec == coreCodec &&
+ self->pSbrElement[elementIndex] != NULL &&
+ self->pSbrElement[elementIndex]->elementID == elementID &&
+ !(self->flags & SBRDEC_FORCE_RESET) &&
+ ((sampleRateOut == 0) ? 1 : (self->sampleRateOut == sampleRateOut)) &&
+ ((harmonicSBR == 2) ? 1
+ : (self->harmonicSBR ==
+ harmonicSBR)) /* The value 2 signalizes that
+ harmonicSBR shall be ignored in
+ the config change detection */
+ ) {
+ /* Nothing to do */
+ return SBRDEC_OK;
+ } else {
+ if (configMode & AC_CM_DET_CFG_CHANGE) {
+ *configChanged = 1;
+ }
}
- self->sampleRateIn = sampleRateIn;
- self->codecFrameSize = samplesPerFrame;
- self->coreCodec = coreCodec;
+ /* reaching this point the SBR-decoder gets (re-)configured */
- self->flags = 0;
+ /* The flags field is used for all elements! */
+ self->flags &=
+ (SBRDEC_FORCE_RESET | SBRDEC_FLUSH); /* Keep the global flags. They will
+ be reset after decoding. */
+ self->flags |= (downscaleFactor > 1) ? SBRDEC_ELD_DOWNSCALE : 0;
self->flags |= (coreCodec == AOT_ER_AAC_ELD) ? SBRDEC_ELD_GRID : 0;
self->flags |= (coreCodec == AOT_ER_AAC_SCAL) ? SBRDEC_SYNTAX_SCAL : 0;
- self->flags |= (coreCodec == AOT_DRM_AAC) ? SBRDEC_SYNTAX_SCAL|SBRDEC_SYNTAX_DRM : 0;
+ self->flags |=
+ (coreCodec == AOT_DRM_AAC) ? SBRDEC_SYNTAX_SCAL | SBRDEC_SYNTAX_DRM : 0;
+ self->flags |= (coreCodec == AOT_DRM_SURROUND)
+ ? SBRDEC_SYNTAX_SCAL | SBRDEC_SYNTAX_DRM
+ : 0;
+ self->flags |= (coreCodec == AOT_USAC) ? SBRDEC_SYNTAX_USAC : 0;
+ /* Robustness: Take integer division rounding into consideration. E.g. 22050
+ * Hz with 4:1 SBR => 5512 Hz core sampling rate. */
+ self->flags |= (sampleRateIn == sampleRateOut / 4) ? SBRDEC_QUAD_RATE : 0;
+ self->flags |= (harmonicSBR == 1) ? SBRDEC_USAC_HARMONICSBR : 0;
+
+ if (configMode & AC_CM_DET_CFG_CHANGE) {
+ return SBRDEC_OK;
+ }
+
+ self->sampleRateIn = sampleRateIn;
+ self->codecFrameSize = samplesPerFrame;
+ self->coreCodec = coreCodec;
+ self->harmonicSBR = harmonicSBR;
+ self->downscaleFactor = downscaleFactor;
/* Init SBR elements */
{
@@ -505,34 +614,39 @@ SBR_ERROR sbrDecoder_InitElement (
sbrError = SBRDEC_MEM_ALLOC_FAILED;
goto bail;
}
- self->numSbrElements ++;
+ self->numSbrElements++;
} else {
self->numSbrChannels -= self->pSbrElement[elementIndex]->nChannels;
}
- /* Save element ID for sanity checks and to have a fallback for concealment. */
+ /* Save element ID for sanity checks and to have a fallback for concealment.
+ */
self->pSbrElement[elementIndex]->elementID = elementID;
/* Determine amount of channels for this element */
switch (elementID) {
case ID_NONE:
- case ID_CPE: elChannels=2;
+ case ID_CPE:
+ elChannels = 2;
break;
case ID_LFE:
- case ID_SCE: elChannels=1;
+ case ID_SCE:
+ elChannels = 1;
break;
- default: elChannels=0;
+ default:
+ elChannels = 0;
break;
}
/* Handle case of Parametric Stereo */
- if ( elementIndex == 0 && elementID == ID_SCE ) {
+ if (elementIndex == 0 && elementID == ID_SCE) {
switch (coreCodec) {
case AOT_AAC_LC:
case AOT_SBR:
case AOT_PS:
case AOT_ER_AAC_SCAL:
case AOT_DRM_AAC:
+ case AOT_DRM_SURROUND:
elChannels = 2;
break;
default:
@@ -540,57 +654,76 @@ SBR_ERROR sbrDecoder_InitElement (
}
}
+ /* Sanity check to avoid memory leaks */
+ if (elChannels < self->pSbrElement[elementIndex]->nChannels) {
+ self->numSbrChannels += self->pSbrElement[elementIndex]->nChannels;
+ sbrError = SBRDEC_PARSE_ERROR;
+ goto bail;
+ }
+
self->pSbrElement[elementIndex]->nChannels = elChannels;
- for (ch=0; ch<elChannels; ch++)
- {
+ for (ch = 0; ch < elChannels; ch++) {
if (self->pSbrElement[elementIndex]->pSbrChannel[ch] == NULL) {
- self->pSbrElement[elementIndex]->pSbrChannel[ch] = GetRam_SbrDecChannel(chCnt);
+ self->pSbrElement[elementIndex]->pSbrChannel[ch] =
+ GetRam_SbrDecChannel(chCnt);
if (self->pSbrElement[elementIndex]->pSbrChannel[ch] == NULL) {
sbrError = SBRDEC_MEM_ALLOC_FAILED;
goto bail;
}
}
- self->numSbrChannels ++;
+ self->numSbrChannels++;
- sbrDecoder_drcInitChannel( &self->pSbrElement[elementIndex]->pSbrChannel[ch]->SbrDec.sbrDrcChannel );
+ sbrDecoder_drcInitChannel(&self->pSbrElement[elementIndex]
+ ->pSbrChannel[ch]
+ ->SbrDec.sbrDrcChannel);
- /* Add reference pointer to workbuffers. */
- self->pSbrElement[elementIndex]->pSbrChannel[ch]->SbrDec.WorkBuffer1 = self->workBuffer1;
- self->pSbrElement[elementIndex]->pSbrChannel[ch]->SbrDec.WorkBuffer2 = self->workBuffer2;
chCnt++;
}
- if (elChannels == 1 && self->pSbrElement[elementIndex]->pSbrChannel[ch] != NULL) {
- deleteSbrDec( self->pSbrElement[elementIndex]->pSbrChannel[ch] );
- FreeRam_SbrDecChannel( &self->pSbrElement[elementIndex]->pSbrChannel[ch] );
- }
}
- /* clear error flags for all delay slots */
- FDKmemclear(self->pSbrElement[elementIndex]->frameErrorFlag, ((1)+1)*sizeof(UCHAR));
+ if (!self->pQmfDomain->globalConf.qmfDomainExplicitConfig) {
+ self->pQmfDomain->globalConf.nInputChannels_requested =
+ self->numSbrChannels;
+ self->pQmfDomain->globalConf.nOutputChannels_requested =
+ fMax((INT)self->numSbrChannels,
+ (INT)self->pQmfDomain->globalConf.nOutputChannels_requested);
+ }
- /* Initialize this instance */
- sbrError = sbrDecoder_ResetElement(
- self,
- sampleRateIn,
- sampleRateOut,
- samplesPerFrame,
- elementID,
- elementIndex,
- (coreCodec == AOT_ER_AAC_ELD) ? 0 : (6)
- );
+ /* Make sure each SBR channel has one QMF channel assigned even if
+ * numSbrChannels or element set-up has changed. */
+ sbrDecoder_AssignQmfChannels2SbrChannels(self);
+ /* clear error flags for all delay slots */
+ FDKmemclear(self->pSbrElement[elementIndex]->frameErrorFlag,
+ ((1) + 1) * sizeof(UCHAR));
+ {
+ int overlap;
+
+ if (coreCodec == AOT_ER_AAC_ELD) {
+ overlap = 0;
+ } else if (self->flags & SBRDEC_QUAD_RATE) {
+ overlap = (3 * 4);
+ } else {
+ overlap = (3 * 2);
+ }
+ /* Initialize this instance */
+ sbrError = sbrDecoder_ResetElement(self, sampleRateIn, sampleRateOut,
+ samplesPerFrame, elementID, elementIndex,
+ overlap);
+ }
bail:
if (sbrError != SBRDEC_OK) {
- if (nSbrElementsStart < self->numSbrElements) {
+ if ((nSbrElementsStart < self->numSbrElements) ||
+ (nSbrChannelsStart < self->numSbrChannels)) {
/* Free the memory allocated for this element */
- sbrDecoder_DestroyElement( self, elementIndex );
- } else if ( (self->pSbrElement[elementIndex] != NULL)
- && (elementIndex < (8)))
- { /* Set error flag to trigger concealment */
- self->pSbrElement[elementIndex]->frameErrorFlag[self->pSbrElement[elementIndex]->useFrameSlot] = 1;
+ sbrDecoder_DestroyElement(self, elementIndex);
+ } else if ((elementIndex < (8)) &&
+ (self->pSbrElement[elementIndex] !=
+ NULL)) { /* Set error flag to trigger concealment */
+ setFrameErrorFlag(self->pSbrElement[elementIndex], FRAME_ERROR);
}
}
@@ -598,22 +731,43 @@ bail:
}
/**
+ * \brief Free config dependent SBR memory.
+ * \param self SBR decoder instance handle
+ */
+SBR_ERROR sbrDecoder_FreeMem(HANDLE_SBRDECODER *self) {
+ int i;
+ int elIdx;
+
+ if (self != NULL && *self != NULL) {
+ for (i = 0; i < (8); i++) {
+ sbrDecoder_DestroyElement(*self, i);
+ }
+
+ for (elIdx = 0; elIdx < (8); elIdx += 1) {
+ for (i = 0; i < (1) + 1; i += 1) {
+ (*self)->sbrHeader[elIdx][i].syncState = SBR_NOT_INITIALIZED;
+ }
+ }
+ }
+
+ return SBRDEC_OK;
+}
+
+/**
* \brief Apply decoded SBR header for one element.
* \param self SBR decoder instance handle
* \param hSbrHeader SBR header handle to be processed.
- * \param hSbrChannel pointer array to the SBR element channels corresponding to the SBR header.
+ * \param hSbrChannel pointer array to the SBR element channels corresponding to
+ * the SBR header.
* \param headerStatus header status value returned from SBR header parser.
- * \param numElementChannels amount of channels for the SBR element whos header is to be processed.
+ * \param numElementChannels amount of channels for the SBR element whos header
+ * is to be processed.
*/
-static
-SBR_ERROR sbrDecoder_HeaderUpdate(
- HANDLE_SBRDECODER self,
- HANDLE_SBR_HEADER_DATA hSbrHeader,
- SBR_HEADER_STATUS headerStatus,
- HANDLE_SBR_CHANNEL hSbrChannel[],
- const int numElementChannels
- )
-{
+static SBR_ERROR sbrDecoder_HeaderUpdate(HANDLE_SBRDECODER self,
+ HANDLE_SBR_HEADER_DATA hSbrHeader,
+ SBR_HEADER_STATUS headerStatus,
+ HANDLE_SBR_CHANNEL hSbrChannel[],
+ const int numElementChannels) {
SBR_ERROR errorStatus = SBRDEC_OK;
/*
@@ -622,8 +776,14 @@ SBR_ERROR sbrDecoder_HeaderUpdate(
errorStatus = resetFreqBandTables(hSbrHeader, self->flags);
if (errorStatus == SBRDEC_OK) {
- if (hSbrHeader->syncState == UPSAMPLING && headerStatus != HEADER_RESET)
- {
+ if (hSbrHeader->syncState == UPSAMPLING && headerStatus != HEADER_RESET) {
+#if (SBRDEC_MAX_HB_FADE_FRAMES > 0)
+ int ch;
+ for (ch = 0; ch < numElementChannels; ch += 1) {
+ hSbrChannel[ch]->SbrDec.highBandFadeCnt = SBRDEC_MAX_HB_FADE_FRAMES;
+ }
+
+#endif
/* As the default header would limit the frequency range,
lowSubband and highSubband must be patched. */
hSbrHeader->freqBandData.lowSubband = hSbrHeader->numberOfAnalysisBands;
@@ -637,155 +797,153 @@ SBR_ERROR sbrDecoder_HeaderUpdate(
return errorStatus;
}
-INT sbrDecoder_Header (
- HANDLE_SBRDECODER self,
- HANDLE_FDK_BITSTREAM hBs,
- const INT sampleRateIn,
- const INT sampleRateOut,
- const INT samplesPerFrame,
- const AUDIO_OBJECT_TYPE coreCodec,
- const MP4_ELEMENT_ID elementID,
- const INT elementIndex
- )
-{
+INT sbrDecoder_Header(HANDLE_SBRDECODER self, HANDLE_FDK_BITSTREAM hBs,
+ const INT sampleRateIn, const INT sampleRateOut,
+ const INT samplesPerFrame,
+ const AUDIO_OBJECT_TYPE coreCodec,
+ const MP4_ELEMENT_ID elementID, const INT elementIndex,
+ const UCHAR harmonicSBR, const UCHAR stereoConfigIndex,
+ const UCHAR configMode, UCHAR *configChanged,
+ const INT downscaleFactor) {
SBR_HEADER_STATUS headerStatus;
HANDLE_SBR_HEADER_DATA hSbrHeader;
SBR_ERROR sbrError = SBRDEC_OK;
int headerIndex;
+ UINT flagsSaved =
+ 0; /* flags should not be changed in AC_CM_DET_CFG_CHANGE - mode after
+ parsing */
- if ( self == NULL || elementIndex > (8) )
- {
+ if (self == NULL || elementIndex >= (8)) {
return SBRDEC_UNSUPPORTED_CONFIG;
}
- if (! sbrDecoder_isCoreCodecValid(coreCodec)) {
+ if (!sbrDecoder_isCoreCodecValid(coreCodec)) {
return SBRDEC_UNSUPPORTED_CONFIG;
}
+ if (configMode & AC_CM_DET_CFG_CHANGE) {
+ flagsSaved = self->flags; /* store */
+ }
+
sbrError = sbrDecoder_InitElement(
- self,
- sampleRateIn,
- sampleRateOut,
- samplesPerFrame,
- coreCodec,
- elementID,
- elementIndex
- );
+ self, sampleRateIn, sampleRateOut, samplesPerFrame, coreCodec, elementID,
+ elementIndex, harmonicSBR, stereoConfigIndex, configMode, configChanged,
+ downscaleFactor);
- if (sbrError != SBRDEC_OK) {
+ if ((sbrError != SBRDEC_OK) || (elementID == ID_LFE)) {
goto bail;
}
- headerIndex = getHeaderSlot(self->pSbrElement[elementIndex]->useFrameSlot,
- self->pSbrElement[elementIndex]->useHeaderSlot);
- hSbrHeader = &(self->sbrHeader[elementIndex][headerIndex]);
+ if (configMode & AC_CM_DET_CFG_CHANGE) {
+ hSbrHeader = NULL;
+ } else {
+ headerIndex = getHeaderSlot(self->pSbrElement[elementIndex]->useFrameSlot,
+ self->pSbrElement[elementIndex]->useHeaderSlot);
- headerStatus = sbrGetHeaderData ( hSbrHeader,
- hBs,
- self->flags,
- 0);
+ hSbrHeader = &(self->sbrHeader[elementIndex][headerIndex]);
+ }
+ headerStatus = sbrGetHeaderData(hSbrHeader, hBs, self->flags, 0, configMode);
- {
+ if (coreCodec == AOT_USAC) {
+ if (configMode & AC_CM_DET_CFG_CHANGE) {
+ self->flags = flagsSaved; /* restore */
+ }
+ return sbrError;
+ }
+
+ if (configMode & AC_CM_ALLOC_MEM) {
SBR_DECODER_ELEMENT *pSbrElement;
pSbrElement = self->pSbrElement[elementIndex];
/* Sanity check */
if (pSbrElement != NULL) {
- if ( (elementID == ID_CPE && pSbrElement->nChannels != 2)
- || (elementID != ID_CPE && pSbrElement->nChannels != 1) )
- {
+ if ((elementID == ID_CPE && pSbrElement->nChannels != 2) ||
+ (elementID != ID_CPE && pSbrElement->nChannels != 1)) {
return SBRDEC_UNSUPPORTED_CONFIG;
}
- if ( headerStatus == HEADER_RESET ) {
-
- sbrError = sbrDecoder_HeaderUpdate(
- self,
- hSbrHeader,
- headerStatus,
- pSbrElement->pSbrChannel,
- pSbrElement->nChannels
- );
+ if (headerStatus == HEADER_RESET) {
+ sbrError = sbrDecoder_HeaderUpdate(self, hSbrHeader, headerStatus,
+ pSbrElement->pSbrChannel,
+ pSbrElement->nChannels);
if (sbrError == SBRDEC_OK) {
hSbrHeader->syncState = SBR_HEADER;
- hSbrHeader->status |= SBRDEC_HDR_STAT_UPDATE;
+ hSbrHeader->status |= SBRDEC_HDR_STAT_UPDATE;
}
/* else {
- Since we already have overwritten the old SBR header the only way out is UPSAMPLING!
- This will be prepared in the next step.
+ Since we already have overwritten the old SBR header the only way out
+ is UPSAMPLING! This will be prepared in the next step.
} */
}
}
}
bail:
+ if (configMode & AC_CM_DET_CFG_CHANGE) {
+ self->flags = flagsSaved; /* restore */
+ }
return sbrError;
}
-
-SBR_ERROR sbrDecoder_SetParam (HANDLE_SBRDECODER self,
- const SBRDEC_PARAM param,
- const INT value )
-{
+SBR_ERROR sbrDecoder_SetParam(HANDLE_SBRDECODER self, const SBRDEC_PARAM param,
+ const INT value) {
SBR_ERROR errorStatus = SBRDEC_OK;
/* configure the subsystems */
- switch (param)
- {
- case SBR_SYSTEM_BITSTREAM_DELAY:
- if (value < 0 || value > (1)) {
- errorStatus = SBRDEC_SET_PARAM_FAIL;
- break;
- }
- if (self == NULL) {
- errorStatus = SBRDEC_NOT_INITIALIZED;
- } else {
- self->numDelayFrames = (UCHAR)value;
- }
- break;
- case SBR_QMF_MODE:
- if (self == NULL) {
- errorStatus = SBRDEC_NOT_INITIALIZED;
- } else {
- if (value == 1) {
- self->flags |= SBRDEC_LOW_POWER;
- } else {
- self->flags &= ~SBRDEC_LOW_POWER;
+ switch (param) {
+ case SBR_SYSTEM_BITSTREAM_DELAY:
+ if (value < 0 || value > (1)) {
+ errorStatus = SBRDEC_SET_PARAM_FAIL;
+ break;
}
- }
- break;
- case SBR_LD_QMF_TIME_ALIGN:
- if (self == NULL) {
- errorStatus = SBRDEC_NOT_INITIALIZED;
- } else {
- if (value == 1) {
- self->flags |= SBRDEC_LD_MPS_QMF;
+ if (self == NULL) {
+ errorStatus = SBRDEC_NOT_INITIALIZED;
} else {
- self->flags &= ~SBRDEC_LD_MPS_QMF;
+ self->numDelayFrames = (UCHAR)value;
}
- }
- break;
- case SBR_FLUSH_DATA:
- if (value != 0) {
+ break;
+ case SBR_QMF_MODE:
if (self == NULL) {
errorStatus = SBRDEC_NOT_INITIALIZED;
} else {
- self->flags |= SBRDEC_FLUSH;
+ if (value == 1) {
+ self->flags |= SBRDEC_LOW_POWER;
+ } else {
+ self->flags &= ~SBRDEC_LOW_POWER;
+ }
}
- }
- break;
- case SBR_CLEAR_HISTORY:
- if (value != 0) {
+ break;
+ case SBR_LD_QMF_TIME_ALIGN:
if (self == NULL) {
errorStatus = SBRDEC_NOT_INITIALIZED;
} else {
- self->flags |= SBRDEC_FORCE_RESET;
+ if (value == 1) {
+ self->flags |= SBRDEC_LD_MPS_QMF;
+ } else {
+ self->flags &= ~SBRDEC_LD_MPS_QMF;
+ }
}
- }
- break;
- case SBR_BS_INTERRUPTION:
- {
+ break;
+ case SBR_FLUSH_DATA:
+ if (value != 0) {
+ if (self == NULL) {
+ errorStatus = SBRDEC_NOT_INITIALIZED;
+ } else {
+ self->flags |= SBRDEC_FLUSH;
+ }
+ }
+ break;
+ case SBR_CLEAR_HISTORY:
+ if (value != 0) {
+ if (self == NULL) {
+ errorStatus = SBRDEC_NOT_INITIALIZED;
+ } else {
+ self->flags |= SBRDEC_FORCE_RESET;
+ }
+ }
+ break;
+ case SBR_BS_INTERRUPTION: {
int elementIndex;
if (self == NULL) {
@@ -794,38 +952,55 @@ SBR_ERROR sbrDecoder_SetParam (HANDLE_SBRDECODER self,
}
/* Loop over SBR elements */
- for (elementIndex = 0; elementIndex < self->numSbrElements; elementIndex++) {
- if (self->pSbrElement[elementIndex] != NULL)
- {
- HANDLE_SBR_HEADER_DATA hSbrHeader;
- int headerIndex = getHeaderSlot(self->pSbrElement[elementIndex]->useFrameSlot,
- self->pSbrElement[elementIndex]->useHeaderSlot);
-
- hSbrHeader = &(self->sbrHeader[elementIndex][headerIndex]);
+ for (elementIndex = 0; elementIndex < self->numSbrElements;
+ elementIndex++) {
+ if (self->pSbrElement[elementIndex] != NULL) {
+ HANDLE_SBR_HEADER_DATA hSbrHeader;
+ int headerIndex =
+ getHeaderSlot(self->pSbrElement[elementIndex]->useFrameSlot,
+ self->pSbrElement[elementIndex]->useHeaderSlot);
+
+ hSbrHeader = &(self->sbrHeader[elementIndex][headerIndex]);
+
+ /* Set sync state UPSAMPLING for the corresponding slot.
+ This switches off bitstream parsing until a new header arrives. */
+ hSbrHeader->syncState = UPSAMPLING;
+ hSbrHeader->status |= SBRDEC_HDR_STAT_UPDATE;
+ }
+ }
+ } break;
- /* Set sync state UPSAMPLING for the corresponding slot.
- This switches off bitstream parsing until a new header arrives. */
- hSbrHeader->syncState = UPSAMPLING;
- hSbrHeader->status |= SBRDEC_HDR_STAT_UPDATE;
- } }
- }
- break;
- default:
- errorStatus = SBRDEC_SET_PARAM_FAIL;
- break;
- } /* switch(param) */
+ case SBR_SKIP_QMF:
+ if (self == NULL) {
+ errorStatus = SBRDEC_NOT_INITIALIZED;
+ } else {
+ if (value == 1) {
+ self->flags |= SBRDEC_SKIP_QMF_ANA;
+ } else {
+ self->flags &= ~SBRDEC_SKIP_QMF_ANA;
+ }
+ if (value == 2) {
+ self->flags |= SBRDEC_SKIP_QMF_SYN;
+ } else {
+ self->flags &= ~SBRDEC_SKIP_QMF_SYN;
+ }
+ }
+ break;
+ default:
+ errorStatus = SBRDEC_SET_PARAM_FAIL;
+ break;
+ } /* switch(param) */
return (errorStatus);
}
-static
-SBRDEC_DRC_CHANNEL * sbrDecoder_drcGetChannel( const HANDLE_SBRDECODER self, const INT channel )
-{
+static SBRDEC_DRC_CHANNEL *sbrDecoder_drcGetChannel(
+ const HANDLE_SBRDECODER self, const INT channel) {
SBRDEC_DRC_CHANNEL *pSbrDrcChannelData = NULL;
- int elementIndex, elChanIdx=0, numCh=0;
+ int elementIndex, elChanIdx = 0, numCh = 0;
- for (elementIndex = 0; (elementIndex < (8)) && (numCh <= channel); elementIndex++)
- {
+ for (elementIndex = 0; (elementIndex < (8)) && (numCh <= channel);
+ elementIndex++) {
SBR_DECODER_ELEMENT *pSbrElement = self->pSbrElement[elementIndex];
int c, elChannels;
@@ -834,18 +1009,21 @@ SBRDEC_DRC_CHANNEL * sbrDecoder_drcGetChannel( const HANDLE_SBRDECODER self, con
/* Determine amount of channels for this element */
switch (pSbrElement->elementID) {
- case ID_CPE: elChannels = 2;
+ case ID_CPE:
+ elChannels = 2;
break;
case ID_LFE:
- case ID_SCE: elChannels = 1;
+ case ID_SCE:
+ elChannels = 1;
break;
case ID_NONE:
- default: elChannels = 0;
+ default:
+ elChannels = 0;
break;
}
/* Limit with actual allocated element channels */
- elChannels = FDKmin(elChannels, pSbrElement->nChannels);
+ elChannels = fMin(elChannels, pSbrElement->nChannels);
for (c = 0; (c < elChannels) && (numCh <= channel); c++) {
if (pSbrElement->pSbrChannel[elChanIdx] != NULL) {
@@ -861,25 +1039,22 @@ SBRDEC_DRC_CHANNEL * sbrDecoder_drcGetChannel( const HANDLE_SBRDECODER self, con
return NULL;
}
- if ( self->pSbrElement[elementIndex] != NULL ) {
- if ( self->pSbrElement[elementIndex]->pSbrChannel[elChanIdx] != NULL )
- {
- pSbrDrcChannelData = &self->pSbrElement[elementIndex]->pSbrChannel[elChanIdx]->SbrDec.sbrDrcChannel;
+ if (self->pSbrElement[elementIndex] != NULL) {
+ if (self->pSbrElement[elementIndex]->pSbrChannel[elChanIdx] != NULL) {
+ pSbrDrcChannelData = &self->pSbrElement[elementIndex]
+ ->pSbrChannel[elChanIdx]
+ ->SbrDec.sbrDrcChannel;
}
}
return (pSbrDrcChannelData);
}
-SBR_ERROR sbrDecoder_drcFeedChannel ( HANDLE_SBRDECODER self,
- INT ch,
- UINT numBands,
- FIXP_DBL *pNextFact_mag,
- INT nextFact_exp,
- SHORT drcInterpolationScheme,
- UCHAR winSequence,
- USHORT *pBandTop )
-{
+SBR_ERROR sbrDecoder_drcFeedChannel(HANDLE_SBRDECODER self, INT ch,
+ UINT numBands, FIXP_DBL *pNextFact_mag,
+ INT nextFact_exp,
+ SHORT drcInterpolationScheme,
+ UCHAR winSequence, USHORT *pBandTop) {
SBRDEC_DRC_CHANNEL *pSbrDrcChannelData = NULL;
int band, isValidData = 0;
@@ -891,138 +1066,136 @@ SBR_ERROR sbrDecoder_drcFeedChannel ( HANDLE_SBRDECODER self,
}
/* Search for gain values different to 1.0f */
- for (band = 0; band < numBands; band += 1) {
- if ( !((pNextFact_mag[band] == FL2FXCONST_DBL(0.5)) && (nextFact_exp == 1))
- && !((pNextFact_mag[band] == (FIXP_DBL)MAXVAL_DBL) && (nextFact_exp == 0)) ) {
+ for (band = 0; band < (int)numBands; band += 1) {
+ if (!((pNextFact_mag[band] == FL2FXCONST_DBL(0.5)) &&
+ (nextFact_exp == 1)) &&
+ !((pNextFact_mag[band] == (FIXP_DBL)MAXVAL_DBL) &&
+ (nextFact_exp == 0))) {
isValidData = 1;
break;
}
}
/* Find the right SBR channel */
- pSbrDrcChannelData = sbrDecoder_drcGetChannel( self, ch );
+ pSbrDrcChannelData = sbrDecoder_drcGetChannel(self, ch);
- if ( pSbrDrcChannelData != NULL ) {
- if ( pSbrDrcChannelData->enable || isValidData )
- { /* Activate processing only with real and valid data */
- int i;
+ if (pSbrDrcChannelData != NULL) {
+ if (pSbrDrcChannelData->enable ||
+ isValidData) { /* Activate processing only with real and valid data */
+ int i;
- pSbrDrcChannelData->enable = 1;
- pSbrDrcChannelData->numBandsNext = numBands;
+ pSbrDrcChannelData->enable = 1;
+ pSbrDrcChannelData->numBandsNext = numBands;
- pSbrDrcChannelData->winSequenceNext = winSequence;
- pSbrDrcChannelData->drcInterpolationSchemeNext = drcInterpolationScheme;
- pSbrDrcChannelData->nextFact_exp = nextFact_exp;
+ pSbrDrcChannelData->winSequenceNext = winSequence;
+ pSbrDrcChannelData->drcInterpolationSchemeNext = drcInterpolationScheme;
+ pSbrDrcChannelData->nextFact_exp = nextFact_exp;
- for (i = 0; i < (int)numBands; i++) {
- pSbrDrcChannelData->bandTopNext[i] = pBandTop[i];
- pSbrDrcChannelData->nextFact_mag[i] = pNextFact_mag[i];
+ for (i = 0; i < (int)numBands; i++) {
+ pSbrDrcChannelData->bandTopNext[i] = pBandTop[i];
+ pSbrDrcChannelData->nextFact_mag[i] = pNextFact_mag[i];
+ }
}
}
- }
return SBRDEC_OK;
}
-
-void sbrDecoder_drcDisable ( HANDLE_SBRDECODER self,
- INT ch )
-{
+void sbrDecoder_drcDisable(HANDLE_SBRDECODER self, INT ch) {
SBRDEC_DRC_CHANNEL *pSbrDrcChannelData = NULL;
- if ( (self == NULL)
- || (ch > (8))
- || (self->numSbrElements == 0)
- || (self->numSbrChannels == 0) ) {
+ if ((self == NULL) || (ch > (8)) || (self->numSbrElements == 0) ||
+ (self->numSbrChannels == 0)) {
return;
}
/* Find the right SBR channel */
- pSbrDrcChannelData = sbrDecoder_drcGetChannel( self, ch );
+ pSbrDrcChannelData = sbrDecoder_drcGetChannel(self, ch);
- if ( pSbrDrcChannelData != NULL ) {
- sbrDecoder_drcInitChannel( pSbrDrcChannelData );
+ if (pSbrDrcChannelData != NULL) {
+ sbrDecoder_drcInitChannel(pSbrDrcChannelData);
}
}
-
-
-SBR_ERROR sbrDecoder_Parse(
- HANDLE_SBRDECODER self,
- HANDLE_FDK_BITSTREAM hBs,
- int *count,
- int bsPayLen,
- int crcFlag,
- MP4_ELEMENT_ID prevElement,
- int elementIndex,
- int fGlobalIndependencyFlag
- )
-{
- SBR_DECODER_ELEMENT *hSbrElement;
+SBR_ERROR sbrDecoder_Parse(HANDLE_SBRDECODER self, HANDLE_FDK_BITSTREAM hBs,
+ UCHAR *pDrmBsBuffer, USHORT drmBsBufferSize,
+ int *count, int bsPayLen, int crcFlag,
+ MP4_ELEMENT_ID prevElement, int elementIndex,
+ UINT acFlags, UINT acElFlags[]) {
+ SBR_DECODER_ELEMENT *hSbrElement = NULL;
HANDLE_SBR_HEADER_DATA hSbrHeader = NULL;
- HANDLE_SBR_CHANNEL *pSbrChannel;
+ HANDLE_SBR_CHANNEL *pSbrChannel;
- SBR_FRAME_DATA *hFrameDataLeft;
- SBR_FRAME_DATA *hFrameDataRight;
+ SBR_FRAME_DATA *hFrameDataLeft = NULL;
+ SBR_FRAME_DATA *hFrameDataRight = NULL;
+ SBR_FRAME_DATA frameDataLeftCopy;
+ SBR_FRAME_DATA frameDataRightCopy;
SBR_ERROR errorStatus = SBRDEC_OK;
SBR_HEADER_STATUS headerStatus = HEADER_NOT_PRESENT;
- INT startPos;
- INT CRCLen = 0;
+ INT startPos = FDKgetValidBits(hBs);
+ INT CRCLen = 0;
HANDLE_FDK_BITSTREAM hBsOriginal = hBs;
- FDK_CRCINFO crcInfo; /* shall be used for all other CRCs in the future (TBD) */
- INT crcReg = 0;
- USHORT drmSbrCrc = 0;
+ FDK_BITSTREAM bsBwd;
- int stereo;
- int fDoDecodeSbrData = 1;
+ FDK_CRCINFO crcInfo;
+ INT crcReg = 0;
+ USHORT drmSbrCrc = 0;
+ const int fGlobalIndependencyFlag = acFlags & AC_INDEP;
+ const int bs_pvc = acElFlags[elementIndex] & AC_EL_USAC_PVC;
+ const int bs_interTes = acElFlags[elementIndex] & AC_EL_USAC_ITES;
+ int stereo;
+ int fDoDecodeSbrData = 1;
- int lastSlot, lastHdrSlot = 0, thisHdrSlot;
+ int lastSlot, lastHdrSlot = 0, thisHdrSlot = 0;
+
+ /* SBR sanity checks */
+ if (self == NULL) {
+ errorStatus = SBRDEC_NOT_INITIALIZED;
+ goto bail;
+ }
/* Reverse bits of DRM SBR payload */
- if ( (self->flags & SBRDEC_SYNTAX_DRM) && *count > 0 )
- {
- UCHAR *bsBufferDrm = (UCHAR*)self->workBuffer1;
- HANDLE_FDK_BITSTREAM hBsBwd = (HANDLE_FDK_BITSTREAM) (bsBufferDrm + (512));
+ if ((self->flags & SBRDEC_SYNTAX_DRM) && *count > 0) {
int dataBytes, dataBits;
+ FDK_ASSERT(drmBsBufferSize >= (512));
dataBits = *count;
- if (dataBits > ((512)*8)) {
+ if (dataBits > ((512) * 8)) {
/* do not flip more data than needed */
- dataBits = (512)*8;
+ dataBits = (512) * 8;
}
- dataBytes = (dataBits+7)>>3;
+ dataBytes = (dataBits + 7) >> 3;
int j;
if ((j = (int)FDKgetValidBits(hBs)) != 8) {
- FDKpushBiDirectional(hBs, (j-8));
+ FDKpushBiDirectional(hBs, (j - 8));
}
j = 0;
- for ( ; dataBytes > 0; dataBytes--)
- {
+ for (; dataBytes > 0; dataBytes--) {
int i;
UCHAR tmpByte;
UCHAR buffer = 0x00;
- tmpByte = (UCHAR) FDKreadBits(hBs, 8);
+ tmpByte = (UCHAR)FDKreadBits(hBs, 8);
for (i = 0; i < 4; i++) {
int shift = 2 * i + 1;
- buffer |= (tmpByte & (0x08>>i)) << shift;
- buffer |= (tmpByte & (0x10<<i)) >> shift;
+ buffer |= (tmpByte & (0x08 >> i)) << shift;
+ buffer |= (tmpByte & (0x10 << i)) >> shift;
}
- bsBufferDrm[j++] = buffer;
+ pDrmBsBuffer[j++] = buffer;
FDKpushBack(hBs, 16);
}
- FDKinitBitStream(hBsBwd, bsBufferDrm, (512), dataBits, BS_READER);
+ FDKinitBitStream(&bsBwd, pDrmBsBuffer, (512), dataBits, BS_READER);
/* Use reversed data */
- hBs = hBsBwd;
+ hBs = &bsBwd;
bsPayLen = *count;
}
@@ -1030,16 +1203,19 @@ SBR_ERROR sbrDecoder_Parse(
startPos = FDKgetValidBits(hBs);
/* SBR sanity checks */
- if ( self == NULL || self->pSbrElement[elementIndex] == NULL ) {
+ if (self->pSbrElement[elementIndex] == NULL) {
errorStatus = SBRDEC_NOT_INITIALIZED;
goto bail;
- }
-
+ }
hSbrElement = self->pSbrElement[elementIndex];
- lastSlot = (hSbrElement->useFrameSlot > 0) ? hSbrElement->useFrameSlot-1 : self->numDelayFrames;
- lastHdrSlot = hSbrElement->useHeaderSlot[lastSlot];
- thisHdrSlot = getHeaderSlot( hSbrElement->useFrameSlot, hSbrElement->useHeaderSlot ); /* Get a free header slot not used by frames not processed yet. */
+ lastSlot = (hSbrElement->useFrameSlot > 0) ? hSbrElement->useFrameSlot - 1
+ : self->numDelayFrames;
+ lastHdrSlot = hSbrElement->useHeaderSlot[lastSlot];
+ thisHdrSlot = getHeaderSlot(
+ hSbrElement->useFrameSlot,
+ hSbrElement->useHeaderSlot); /* Get a free header slot not used by
+ frames not processed yet. */
/* Assign the free slot to store a new header if there is one. */
hSbrHeader = &self->sbrHeader[elementIndex][thisHdrSlot];
@@ -1047,9 +1223,20 @@ SBR_ERROR sbrDecoder_Parse(
pSbrChannel = hSbrElement->pSbrChannel;
stereo = (hSbrElement->elementID == ID_CPE) ? 1 : 0;
- hFrameDataLeft = &self->pSbrElement[elementIndex]->pSbrChannel[0]->frameData[hSbrElement->useFrameSlot];
- hFrameDataRight = &self->pSbrElement[elementIndex]->pSbrChannel[1]->frameData[hSbrElement->useFrameSlot];
+ hFrameDataLeft = &self->pSbrElement[elementIndex]
+ ->pSbrChannel[0]
+ ->frameData[hSbrElement->useFrameSlot];
+ if (stereo) {
+ hFrameDataRight = &self->pSbrElement[elementIndex]
+ ->pSbrChannel[1]
+ ->frameData[hSbrElement->useFrameSlot];
+ }
+ /* store frameData; new parsed frameData possibly corrupted */
+ FDKmemcpy(&frameDataLeftCopy, hFrameDataLeft, sizeof(SBR_FRAME_DATA));
+ if (stereo) {
+ FDKmemcpy(&frameDataRightCopy, hFrameDataRight, sizeof(SBR_FRAME_DATA));
+ }
/* reset PS flag; will be set after PS was found */
self->flags &= ~SBRDEC_PS_DECODED;
@@ -1058,23 +1245,23 @@ SBR_ERROR sbrDecoder_Parse(
/* Got a new header from extern (e.g. from an ASC) */
headerStatus = HEADER_OK;
hSbrHeader->status &= ~SBRDEC_HDR_STAT_UPDATE;
- }
- else if (thisHdrSlot != lastHdrSlot) {
+ } else if (thisHdrSlot != lastHdrSlot) {
/* Copy the last header into this slot otherwise the
header compare will trigger more HEADER_RESETs than needed. */
- copySbrHeader( hSbrHeader, &self->sbrHeader[elementIndex][lastHdrSlot] );
+ copySbrHeader(hSbrHeader, &self->sbrHeader[elementIndex][lastHdrSlot]);
}
/*
Check if bit stream data is valid and matches the element context
*/
- if ( ((prevElement != ID_SCE) && (prevElement != ID_CPE)) || prevElement != hSbrElement->elementID) {
- /* In case of LFE we also land here, since there is no LFE SBR element (do upsampling only) */
+ if (((prevElement != ID_SCE) && (prevElement != ID_CPE)) ||
+ prevElement != hSbrElement->elementID) {
+ /* In case of LFE we also land here, since there is no LFE SBR element (do
+ * upsampling only) */
fDoDecodeSbrData = 0;
}
- if (fDoDecodeSbrData)
- {
+ if (fDoDecodeSbrData) {
if ((INT)FDKgetValidBits(hBs) <= 0) {
fDoDecodeSbrData = 0;
}
@@ -1083,29 +1270,29 @@ SBR_ERROR sbrDecoder_Parse(
/*
SBR CRC-check
*/
- if (fDoDecodeSbrData)
- {
+ if (fDoDecodeSbrData) {
if (crcFlag) {
switch (self->coreCodec) {
- case AOT_ER_AAC_ELD:
- FDKpushFor (hBs, 10);
- /* check sbrcrc later: we don't know the payload length now */
- break;
- case AOT_DRM_AAC:
- drmSbrCrc = (USHORT)FDKreadBits(hBs, 8);
- /* Setup CRC decoder */
- FDKcrcInit(&crcInfo, 0x001d, 0xFFFF, 8);
- /* Start CRC region */
- crcReg = FDKcrcStartReg(&crcInfo, hBs, 0);
- break;
- default:
- CRCLen = bsPayLen - 10; /* change: 0 => i */
- if (CRCLen < 0) {
- fDoDecodeSbrData = 0;
- } else {
- fDoDecodeSbrData = SbrCrcCheck (hBs, CRCLen);
- }
- break;
+ case AOT_ER_AAC_ELD:
+ FDKpushFor(hBs, 10);
+ /* check sbrcrc later: we don't know the payload length now */
+ break;
+ case AOT_DRM_AAC:
+ case AOT_DRM_SURROUND:
+ drmSbrCrc = (USHORT)FDKreadBits(hBs, 8);
+ /* Setup CRC decoder */
+ FDKcrcInit(&crcInfo, 0x001d, 0xFFFF, 8);
+ /* Start CRC region */
+ crcReg = FDKcrcStartReg(&crcInfo, hBs, 0);
+ break;
+ default:
+ CRCLen = bsPayLen - 10; /* change: 0 => i */
+ if (CRCLen < 0) {
+ fDoDecodeSbrData = 0;
+ } else {
+ fDoDecodeSbrData = SbrCrcCheck(hBs, CRCLen);
+ }
+ break;
}
}
} /* if (fDoDecodeSbrData) */
@@ -1113,30 +1300,106 @@ SBR_ERROR sbrDecoder_Parse(
/*
Read in the header data and issue a reset if change occured
*/
- if (fDoDecodeSbrData)
- {
+ if (fDoDecodeSbrData) {
int sbrHeaderPresent;
- {
+ if (self->flags & (SBRDEC_SYNTAX_RSVD50 | SBRDEC_SYNTAX_USAC)) {
+ SBR_HEADER_DATA_BS_INFO newSbrInfo;
+ int sbrInfoPresent;
+
+ if (bs_interTes) {
+ self->flags |= SBRDEC_USAC_ITES;
+ } else {
+ self->flags &= ~SBRDEC_USAC_ITES;
+ }
+
+ if (fGlobalIndependencyFlag) {
+ self->flags |= SBRDEC_USAC_INDEP;
+ sbrInfoPresent = 1;
+ sbrHeaderPresent = 1;
+ } else {
+ self->flags &= ~SBRDEC_USAC_INDEP;
+ sbrInfoPresent = FDKreadBit(hBs);
+ if (sbrInfoPresent) {
+ sbrHeaderPresent = FDKreadBit(hBs);
+ } else {
+ sbrHeaderPresent = 0;
+ }
+ }
+
+ if (sbrInfoPresent) {
+ newSbrInfo.ampResolution = FDKreadBit(hBs);
+ newSbrInfo.xover_band = FDKreadBits(hBs, 4);
+ newSbrInfo.sbr_preprocessing = FDKreadBit(hBs);
+ if (bs_pvc) {
+ newSbrInfo.pvc_mode = FDKreadBits(hBs, 2);
+ /* bs_pvc_mode: 0 -> no PVC, 1 -> PVC mode 1, 2 -> PVC mode 2, 3 ->
+ * reserved */
+ if (newSbrInfo.pvc_mode > 2) {
+ headerStatus = HEADER_ERROR;
+ }
+ if (stereo && newSbrInfo.pvc_mode > 0) {
+ /* bs_pvc is always transmitted but pvc_mode is set to zero in case
+ * of stereo SBR. The config might be wrong but we cannot tell for
+ * sure. */
+ newSbrInfo.pvc_mode = 0;
+ }
+ } else {
+ newSbrInfo.pvc_mode = 0;
+ }
+ if (headerStatus != HEADER_ERROR) {
+ if (FDKmemcmp(&hSbrHeader->bs_info, &newSbrInfo,
+ sizeof(SBR_HEADER_DATA_BS_INFO))) {
+ /* in case of ampResolution and preprocessing change no full reset
+ * required */
+ /* HEADER reset would trigger HBE transposer reset which breaks
+ * eSbr_3_Eaa.mp4 */
+ if ((hSbrHeader->bs_info.pvc_mode != newSbrInfo.pvc_mode) ||
+ (hSbrHeader->bs_info.xover_band != newSbrInfo.xover_band)) {
+ headerStatus = HEADER_RESET;
+ } else {
+ headerStatus = HEADER_OK;
+ }
+
+ hSbrHeader->bs_info = newSbrInfo;
+ } else {
+ headerStatus = HEADER_OK;
+ }
+ }
+ }
+ if (headerStatus == HEADER_ERROR) {
+ /* Corrupt SBR info data, do not decode and switch to UPSAMPLING */
+ hSbrHeader->syncState = UPSAMPLING;
+ fDoDecodeSbrData = 0;
+ sbrHeaderPresent = 0;
+ }
+
+ if (sbrHeaderPresent && fDoDecodeSbrData) {
+ int useDfltHeader;
+
+ useDfltHeader = FDKreadBit(hBs);
+
+ if (useDfltHeader) {
+ sbrHeaderPresent = 0;
+ if (FDKmemcmp(&hSbrHeader->bs_data, &hSbrHeader->bs_dflt,
+ sizeof(SBR_HEADER_DATA_BS)) ||
+ hSbrHeader->syncState != SBR_ACTIVE) {
+ hSbrHeader->bs_data = hSbrHeader->bs_dflt;
+ headerStatus = HEADER_RESET;
+ }
+ }
+ }
+ } else {
sbrHeaderPresent = FDKreadBit(hBs);
}
- if ( sbrHeaderPresent ) {
- headerStatus = sbrGetHeaderData (hSbrHeader,
- hBs,
- self->flags,
- 1);
+ if (sbrHeaderPresent) {
+ headerStatus = sbrGetHeaderData(hSbrHeader, hBs, self->flags, 1, 0);
}
- if (headerStatus == HEADER_RESET)
- {
+ if (headerStatus == HEADER_RESET) {
errorStatus = sbrDecoder_HeaderUpdate(
- self,
- hSbrHeader,
- headerStatus,
- pSbrChannel,
- hSbrElement->nChannels
- );
+ self, hSbrHeader, headerStatus, pSbrChannel, hSbrElement->nChannels);
if (errorStatus == SBRDEC_OK) {
hSbrHeader->syncState = SBR_HEADER;
@@ -1159,31 +1422,22 @@ SBR_ERROR sbrDecoder_Parse(
if ((hSbrHeader->syncState >= SBR_HEADER) && fDoDecodeSbrData) {
int sbrFrameOk;
/* read the SBR element data */
- if (stereo) {
- sbrFrameOk = sbrGetChannelPairElement(hSbrHeader,
- hFrameDataLeft,
- hFrameDataRight,
- hBs,
- self->flags,
- self->pSbrElement[elementIndex]->transposerSettings.overlap);
- }
- else {
- if (self->hParametricStereoDec != NULL) {
- /* update slot index for PS bitstream parsing */
- self->hParametricStereoDec->bsLastSlot = self->hParametricStereoDec->bsReadSlot;
- self->hParametricStereoDec->bsReadSlot = hSbrElement->useFrameSlot;
- }
- sbrFrameOk = sbrGetSingleChannelElement(hSbrHeader,
- hFrameDataLeft,
- hBs,
- self->hParametricStereoDec,
- self->flags,
- self->pSbrElement[elementIndex]->transposerSettings.overlap);
+ if (!stereo && (self->hParametricStereoDec != NULL)) {
+ /* update slot index for PS bitstream parsing */
+ self->hParametricStereoDec->bsLastSlot =
+ self->hParametricStereoDec->bsReadSlot;
+ self->hParametricStereoDec->bsReadSlot = hSbrElement->useFrameSlot;
}
+ sbrFrameOk = sbrGetChannelElement(
+ hSbrHeader, hFrameDataLeft, (stereo) ? hFrameDataRight : NULL,
+ &pSbrChannel[0]->prevFrameData,
+ pSbrChannel[0]->SbrDec.PvcStaticData.pvc_mode_last, hBs,
+ (stereo) ? NULL : self->hParametricStereoDec, self->flags,
+ self->pSbrElement[elementIndex]->transposerSettings.overlap);
+
if (!sbrFrameOk) {
fDoDecodeSbrData = 0;
- }
- else {
+ } else {
INT valBits;
if (bsPayLen > 0) {
@@ -1192,28 +1446,32 @@ SBR_ERROR sbrDecoder_Parse(
valBits = (INT)FDKgetValidBits(hBs);
}
- if ( crcFlag ) {
+ if (crcFlag) {
switch (self->coreCodec) {
- case AOT_ER_AAC_ELD:
- {
+ case AOT_ER_AAC_ELD: {
/* late crc check for eld */
- INT payloadbits = (INT)startPos - (INT)FDKgetValidBits(hBs) - startPos;
- INT crcLen = payloadbits - 10;
+ INT payloadbits =
+ (INT)startPos - (INT)FDKgetValidBits(hBs) - startPos;
+ INT crcLen = payloadbits - 10;
FDKpushBack(hBs, payloadbits);
- fDoDecodeSbrData = SbrCrcCheck (hBs, crcLen);
+ fDoDecodeSbrData = SbrCrcCheck(hBs, crcLen);
FDKpushFor(hBs, crcLen);
- }
- break;
- case AOT_DRM_AAC:
- /* End CRC region */
- FDKcrcEndReg(&crcInfo, hBs, crcReg);
- /* Check CRC */
- if ((FDKcrcGetCRC(&crcInfo)^0xFF) != drmSbrCrc) {
- fDoDecodeSbrData = 0;
- }
- break;
- default:
- break;
+ } break;
+ case AOT_DRM_AAC:
+ case AOT_DRM_SURROUND:
+ /* End CRC region */
+ FDKcrcEndReg(&crcInfo, hBs, crcReg);
+ /* Check CRC */
+ if ((FDKcrcGetCRC(&crcInfo) ^ 0xFF) != drmSbrCrc) {
+ fDoDecodeSbrData = 0;
+ if (headerStatus != HEADER_NOT_PRESENT) {
+ headerStatus = HEADER_ERROR;
+ hSbrHeader->syncState = SBR_NOT_INITIALIZED;
+ }
+ }
+ break;
+ default:
+ break;
}
}
@@ -1222,37 +1480,42 @@ SBR_ERROR sbrDecoder_Parse(
fDoDecodeSbrData = 0;
} else {
switch (self->coreCodec) {
- case AOT_SBR:
- case AOT_PS:
- case AOT_AAC_LC:
- {
- /* This sanity check is only meaningful with General Audio bitstreams */
+ case AOT_SBR:
+ case AOT_PS:
+ case AOT_AAC_LC: {
+ /* This sanity check is only meaningful with General Audio
+ * bitstreams */
int alignBits = valBits & 0x7;
if (valBits > alignBits) {
fDoDecodeSbrData = 0;
}
- }
- break;
- default:
- /* No sanity check available */
- break;
+ } break;
+ default:
+ /* No sanity check available */
+ break;
}
}
}
} else {
- /* The returned bit count will not be the actual payload size since we did not
- parse the frame data. Return an error so that the caller can react respectively. */
+ /* The returned bit count will not be the actual payload size since we did
+ not parse the frame data. Return an error so that the caller can react
+ respectively. */
errorStatus = SBRDEC_PARSE_ERROR;
}
if (!fDoDecodeSbrData) {
/* Set error flag for this slot to trigger concealment */
- self->pSbrElement[elementIndex]->frameErrorFlag[hSbrElement->useFrameSlot] = 1;
+ setFrameErrorFlag(self->pSbrElement[elementIndex], FRAME_ERROR);
+ /* restore old frameData for concealment */
+ FDKmemcpy(hFrameDataLeft, &frameDataLeftCopy, sizeof(SBR_FRAME_DATA));
+ if (stereo) {
+ FDKmemcpy(hFrameDataRight, &frameDataRightCopy, sizeof(SBR_FRAME_DATA));
+ }
errorStatus = SBRDEC_PARSE_ERROR;
} else {
/* Everything seems to be ok so clear the error flag */
- self->pSbrElement[elementIndex]->frameErrorFlag[hSbrElement->useFrameSlot] = 0;
+ setFrameErrorFlag(self->pSbrElement[elementIndex], FRAME_OK);
}
if (!stereo) {
@@ -1263,116 +1526,138 @@ SBR_ERROR sbrDecoder_Parse(
bail:
- if ( self->flags & SBRDEC_SYNTAX_DRM )
- {
- hBs = hBsOriginal;
- }
+ if (self != NULL) {
+ if (self->flags & SBRDEC_SYNTAX_DRM) {
+ hBs = hBsOriginal;
+ }
- if ( (errorStatus == SBRDEC_OK)
- || ( (errorStatus == SBRDEC_PARSE_ERROR)
- && (headerStatus != HEADER_ERROR) ) )
- {
- int useOldHdr = ( (headerStatus == HEADER_NOT_PRESENT)
- || (headerStatus == HEADER_ERROR) ) ? 1 : 0;
+ if (errorStatus != SBRDEC_NOT_INITIALIZED) {
+ int useOldHdr =
+ ((headerStatus == HEADER_NOT_PRESENT) ||
+ (headerStatus == HEADER_ERROR) ||
+ (headerStatus == HEADER_RESET && errorStatus == SBRDEC_PARSE_ERROR))
+ ? 1
+ : 0;
+
+ if (!useOldHdr && (thisHdrSlot != lastHdrSlot) && (hSbrHeader != NULL)) {
+ useOldHdr |=
+ (compareSbrHeader(hSbrHeader,
+ &self->sbrHeader[elementIndex][lastHdrSlot]) == 0)
+ ? 1
+ : 0;
+ }
- if (!useOldHdr && (thisHdrSlot != lastHdrSlot)) {
- useOldHdr |= ( compareSbrHeader( hSbrHeader,
- &self->sbrHeader[elementIndex][lastHdrSlot] ) == 0 ) ? 1 : 0;
- }
+ if (hSbrElement != NULL) {
+ if (useOldHdr != 0) {
+ /* Use the old header for this frame */
+ hSbrElement->useHeaderSlot[hSbrElement->useFrameSlot] = lastHdrSlot;
+ } else {
+ /* Use the new header for this frame */
+ hSbrElement->useHeaderSlot[hSbrElement->useFrameSlot] = thisHdrSlot;
+ }
- if (useOldHdr != 0) {
- /* Use the old header for this frame */
- hSbrElement->useHeaderSlot[hSbrElement->useFrameSlot] = lastHdrSlot;
- } else {
- /* Use the new header for this frame */
- hSbrElement->useHeaderSlot[hSbrElement->useFrameSlot] = thisHdrSlot;
+ /* Move frame pointer to the next slot which is up to be decoded/applied
+ * next */
+ hSbrElement->useFrameSlot =
+ (hSbrElement->useFrameSlot + 1) % (self->numDelayFrames + 1);
+ }
}
-
- /* Move frame pointer to the next slot which is up to be decoded/applied next */
- hSbrElement->useFrameSlot = (hSbrElement->useFrameSlot+1) % (self->numDelayFrames+1);
}
- *count -= startPos - FDKgetValidBits(hBs);
+ *count -= startPos - (INT)FDKgetValidBits(hBs);
return errorStatus;
}
-
/**
* \brief Render one SBR element into time domain signal.
* \param self SBR decoder handle
* \param timeData pointer to output buffer
- * \param interleaved flag indicating interleaved channel output
- * \param channelMapping pointer to UCHAR array where next 2 channel offsets are stored.
+ * \param channelMapping pointer to UCHAR array where next 2 channel offsets are
+ * stored.
* \param elementIndex enumerating index of the SBR element to render.
- * \param numInChannels number of channels from core coder (reading stride).
- * \param numOutChannels pointer to a location to return number of output channels.
+ * \param numInChannels number of channels from core coder.
+ * \param numOutChannels pointer to a location to return number of output
+ * channels.
* \param psPossible flag indicating if PS is possible or not.
* \return SBRDEC_OK if successfull, else error code
*/
-static SBR_ERROR
-sbrDecoder_DecodeElement (
- HANDLE_SBRDECODER self,
- INT_PCM *timeData,
- const int interleaved,
- const UCHAR *channelMapping,
- const int elementIndex,
- const int numInChannels,
- int *numOutChannels,
- const int psPossible
- )
-{
+static SBR_ERROR sbrDecoder_DecodeElement(
+ HANDLE_SBRDECODER self, QDOM_PCM *input, INT_PCM *timeData,
+ const int timeDataSize, const FDK_channelMapDescr *const mapDescr,
+ const int mapIdx, int channelIndex, const int elementIndex,
+ const int numInChannels, int *numOutChannels, const int psPossible) {
SBR_DECODER_ELEMENT *hSbrElement = self->pSbrElement[elementIndex];
- HANDLE_SBR_CHANNEL *pSbrChannel = self->pSbrElement[elementIndex]->pSbrChannel;
- HANDLE_SBR_HEADER_DATA hSbrHeader = &self->sbrHeader[elementIndex][hSbrElement->useHeaderSlot[hSbrElement->useFrameSlot]];
+ HANDLE_SBR_CHANNEL *pSbrChannel =
+ self->pSbrElement[elementIndex]->pSbrChannel;
+ HANDLE_SBR_HEADER_DATA hSbrHeader =
+ &self->sbrHeader[elementIndex]
+ [hSbrElement->useHeaderSlot[hSbrElement->useFrameSlot]];
HANDLE_PS_DEC h_ps_d = self->hParametricStereoDec;
/* get memory for frame data from scratch */
- SBR_FRAME_DATA *hFrameDataLeft = &hSbrElement->pSbrChannel[0]->frameData[hSbrElement->useFrameSlot];
- SBR_FRAME_DATA *hFrameDataRight = &hSbrElement->pSbrChannel[1]->frameData[hSbrElement->useFrameSlot];
+ SBR_FRAME_DATA *hFrameDataLeft = NULL;
+ SBR_FRAME_DATA *hFrameDataRight = NULL;
SBR_ERROR errorStatus = SBRDEC_OK;
+ INT strideOut, offset0 = 255, offset0_block = 0, offset1 = 255,
+ offset1_block = 0;
+ INT codecFrameSize = self->codecFrameSize;
- INT strideIn, strideOut, offset0, offset1;
- INT codecFrameSize = self->codecFrameSize;
+ int stereo = (hSbrElement->elementID == ID_CPE) ? 1 : 0;
+ int numElementChannels =
+ hSbrElement
+ ->nChannels; /* Number of channels of the current SBR element */
- int stereo = (hSbrElement->elementID == ID_CPE) ? 1 : 0;
- int numElementChannels = hSbrElement->nChannels; /* Number of channels of the current SBR element */
+ hFrameDataLeft =
+ &hSbrElement->pSbrChannel[0]->frameData[hSbrElement->useFrameSlot];
+ if (stereo) {
+ hFrameDataRight =
+ &hSbrElement->pSbrChannel[1]->frameData[hSbrElement->useFrameSlot];
+ }
if (self->flags & SBRDEC_FLUSH) {
- if ( self->numFlushedFrames > self->numDelayFrames ) {
+ if (self->numFlushedFrames > self->numDelayFrames) {
int hdrIdx;
- /* No valid SBR payload available, hence switch to upsampling (in all headers) */
- for (hdrIdx = 0; hdrIdx < ((1)+1); hdrIdx += 1) {
+ /* No valid SBR payload available, hence switch to upsampling (in all
+ * headers) */
+ for (hdrIdx = 0; hdrIdx < ((1) + 1); hdrIdx += 1) {
self->sbrHeader[elementIndex][hdrIdx].syncState = UPSAMPLING;
}
- }
- else {
- /* Move frame pointer to the next slot which is up to be decoded/applied next */
- hSbrElement->useFrameSlot = (hSbrElement->useFrameSlot+1) % (self->numDelayFrames+1);
- /* Update header and frame data pointer because they have already been set */
- hSbrHeader = &self->sbrHeader[elementIndex][hSbrElement->useHeaderSlot[hSbrElement->useFrameSlot]];
- hFrameDataLeft = &hSbrElement->pSbrChannel[0]->frameData[hSbrElement->useFrameSlot];
- hFrameDataRight = &hSbrElement->pSbrChannel[1]->frameData[hSbrElement->useFrameSlot];
+ } else {
+ /* Move frame pointer to the next slot which is up to be decoded/applied
+ * next */
+ hSbrElement->useFrameSlot =
+ (hSbrElement->useFrameSlot + 1) % (self->numDelayFrames + 1);
+ /* Update header and frame data pointer because they have already been set
+ */
+ hSbrHeader =
+ &self->sbrHeader[elementIndex]
+ [hSbrElement
+ ->useHeaderSlot[hSbrElement->useFrameSlot]];
+ hFrameDataLeft =
+ &hSbrElement->pSbrChannel[0]->frameData[hSbrElement->useFrameSlot];
+ if (stereo) {
+ hFrameDataRight =
+ &hSbrElement->pSbrChannel[1]->frameData[hSbrElement->useFrameSlot];
+ }
}
}
/* Update the header error flag */
- hSbrHeader->frameErrorFlag = hSbrElement->frameErrorFlag[hSbrElement->useFrameSlot];
+ hSbrHeader->frameErrorFlag =
+ hSbrElement->frameErrorFlag[hSbrElement->useFrameSlot];
/*
Prepare filterbank for upsampling if no valid bit stream data is available.
*/
- if ( hSbrHeader->syncState == SBR_NOT_INITIALIZED )
- {
- errorStatus = initHeaderData(
- hSbrHeader,
- self->sampleRateIn,
- self->sampleRateOut,
- codecFrameSize,
- self->flags
- );
+ if (hSbrHeader->syncState == SBR_NOT_INITIALIZED) {
+ errorStatus =
+ initHeaderData(hSbrHeader, self->sampleRateIn, self->sampleRateOut,
+ self->downscaleFactor, codecFrameSize, self->flags,
+ 1 /* SET_DEFAULT_HDR */
+ );
if (errorStatus != SBRDEC_OK) {
return errorStatus;
@@ -1380,13 +1665,8 @@ sbrDecoder_DecodeElement (
hSbrHeader->syncState = UPSAMPLING;
- errorStatus = sbrDecoder_HeaderUpdate(
- self,
- hSbrHeader,
- HEADER_NOT_PRESENT,
- pSbrChannel,
- hSbrElement->nChannels
- );
+ errorStatus = sbrDecoder_HeaderUpdate(self, hSbrHeader, HEADER_NOT_PRESENT,
+ pSbrChannel, hSbrElement->nChannels);
if (errorStatus != SBRDEC_OK) {
hSbrHeader->syncState = SBR_NOT_INITIALIZED;
@@ -1397,170 +1677,163 @@ sbrDecoder_DecodeElement (
/* reset */
if (hSbrHeader->status & SBRDEC_HDR_STAT_RESET) {
int ch;
- for (ch = 0 ; ch < numElementChannels; ch++) {
+ for (ch = 0; ch < numElementChannels; ch++) {
SBR_ERROR errorStatusTmp = SBRDEC_OK;
- errorStatusTmp = resetSbrDec (
- &pSbrChannel[ch]->SbrDec,
- hSbrHeader,
- &pSbrChannel[ch]->prevFrameData,
- self->flags & SBRDEC_LOW_POWER,
- self->synDownsampleFac
- );
+ errorStatusTmp = resetSbrDec(
+ &pSbrChannel[ch]->SbrDec, hSbrHeader, &pSbrChannel[ch]->prevFrameData,
+ self->synDownsampleFac, self->flags, pSbrChannel[ch]->frameData);
if (errorStatusTmp != SBRDEC_OK) {
- errorStatus = errorStatusTmp;
+ hSbrHeader->syncState = UPSAMPLING;
}
}
hSbrHeader->status &= ~SBRDEC_HDR_STAT_RESET;
}
/* decoding */
- if ( (hSbrHeader->syncState == SBR_ACTIVE)
- || ((hSbrHeader->syncState == SBR_HEADER) && (hSbrHeader->frameErrorFlag == 0)) )
- {
+ if ((hSbrHeader->syncState == SBR_ACTIVE) ||
+ ((hSbrHeader->syncState == SBR_HEADER) &&
+ (hSbrHeader->frameErrorFlag == 0))) {
errorStatus = SBRDEC_OK;
- decodeSbrData (hSbrHeader,
- hFrameDataLeft,
- &pSbrChannel[0]->prevFrameData,
- (stereo) ? hFrameDataRight : NULL,
- (stereo) ? &pSbrChannel[1]->prevFrameData : NULL);
-
+ decodeSbrData(hSbrHeader, hFrameDataLeft, &pSbrChannel[0]->prevFrameData,
+ (stereo) ? hFrameDataRight : NULL,
+ (stereo) ? &pSbrChannel[1]->prevFrameData : NULL);
/* Now we have a full parameter set and can do parameter
based concealment instead of plain upsampling. */
hSbrHeader->syncState = SBR_ACTIVE;
}
- /* decode PS data if available */
- if (h_ps_d != NULL && psPossible) {
- int applyPs = 1;
+ if (timeDataSize <
+ hSbrHeader->numberTimeSlots * hSbrHeader->timeStep *
+ self->pQmfDomain->globalConf.nBandsSynthesis *
+ (psPossible ? fMax(2, numInChannels) : numInChannels)) {
+ return SBRDEC_OUTPUT_BUFFER_TOO_SMALL;
+ }
- /* define which frame delay line slot to process */
- h_ps_d->processSlot = hSbrElement->useFrameSlot;
+ {
+ self->flags &= ~SBRDEC_PS_DECODED;
+ C_ALLOC_SCRATCH_START(pPsScratch, struct PS_DEC_COEFFICIENTS, 1)
- applyPs = DecodePs(h_ps_d, hSbrHeader->frameErrorFlag);
- self->flags |= (applyPs) ? SBRDEC_PS_DECODED : 0;
- }
+ /* decode PS data if available */
+ if (h_ps_d != NULL && psPossible && (hSbrHeader->syncState == SBR_ACTIVE)) {
+ int applyPs = 1;
+
+ /* define which frame delay line slot to process */
+ h_ps_d->processSlot = hSbrElement->useFrameSlot;
+
+ applyPs = DecodePs(h_ps_d, hSbrHeader->frameErrorFlag, pPsScratch);
+ self->flags |= (applyPs) ? SBRDEC_PS_DECODED : 0;
+ }
- /* Set strides for reading and writing */
- if (interleaved) {
- strideIn = numInChannels;
- if ( psPossible )
+ offset0 = FDK_chMapDescr_getMapValue(mapDescr, channelIndex, mapIdx);
+ offset0_block = offset0 * codecFrameSize;
+ if (stereo || psPossible) {
+ /* the value of offset1 only matters if the condition is true, however if
+ it is not true channelIndex+1 may exceed the channel map resutling in an
+ error, though the value of offset1 is actually meaningless. This is
+ prevented here. */
+ offset1 = FDK_chMapDescr_getMapValue(mapDescr, channelIndex + 1, mapIdx);
+ offset1_block = offset1 * codecFrameSize;
+ }
+ /* Set strides for reading and writing */
+ if (psPossible)
strideOut = (numInChannels < 2) ? 2 : numInChannels;
else
strideOut = numInChannels;
- offset0 = channelMapping[0];
- offset1 = channelMapping[1];
- } else {
- strideIn = 1;
- strideOut = 1;
- offset0 = channelMapping[0]*2*codecFrameSize;
- offset1 = channelMapping[1]*2*codecFrameSize;
- }
-
- /* use same buffers for left and right channel and apply PS per timeslot */
- /* Process left channel */
-//FDKprintf("self->codecFrameSize %d\t%d\n",self->codecFrameSize,self->sampleRateIn);
- sbr_dec (&pSbrChannel[0]->SbrDec,
- timeData + offset0,
- timeData + offset0,
- &pSbrChannel[1]->SbrDec,
- timeData + offset1,
- strideIn,
- strideOut,
- hSbrHeader,
- hFrameDataLeft,
- &pSbrChannel[0]->prevFrameData,
- (hSbrHeader->syncState == SBR_ACTIVE),
- h_ps_d,
- self->flags,
- codecFrameSize
- );
- if (stereo) {
- /* Process right channel */
- sbr_dec (&pSbrChannel[1]->SbrDec,
- timeData + offset1,
- timeData + offset1,
- NULL,
- NULL,
- strideIn,
- strideOut,
- hSbrHeader,
- hFrameDataRight,
- &pSbrChannel[1]->prevFrameData,
- (hSbrHeader->syncState == SBR_ACTIVE),
- NULL,
- self->flags,
- codecFrameSize
- );
+ /* use same buffers for left and right channel and apply PS per timeslot */
+ /* Process left channel */
+ sbr_dec(&pSbrChannel[0]->SbrDec, input + offset0_block, timeData + offset0,
+ (self->flags & SBRDEC_PS_DECODED) ? &pSbrChannel[1]->SbrDec : NULL,
+ timeData + offset1, strideOut, hSbrHeader, hFrameDataLeft,
+ &pSbrChannel[0]->prevFrameData,
+ (hSbrHeader->syncState == SBR_ACTIVE), h_ps_d, self->flags,
+ codecFrameSize);
+
+ if (stereo) {
+ /* Process right channel */
+ sbr_dec(&pSbrChannel[1]->SbrDec, input + offset1_block,
+ timeData + offset1, NULL, NULL, strideOut, hSbrHeader,
+ hFrameDataRight, &pSbrChannel[1]->prevFrameData,
+ (hSbrHeader->syncState == SBR_ACTIVE), NULL, self->flags,
+ codecFrameSize);
+ }
+
+ C_ALLOC_SCRATCH_END(pPsScratch, struct PS_DEC_COEFFICIENTS, 1)
}
if (h_ps_d != NULL) {
/* save PS status for next run */
- h_ps_d->psDecodedPrv = (self->flags & SBRDEC_PS_DECODED) ? 1 : 0 ;
+ h_ps_d->psDecodedPrv = (self->flags & SBRDEC_PS_DECODED) ? 1 : 0;
}
- if ( psPossible
- )
- {
+ if (psPossible && !(self->flags & SBRDEC_SKIP_QMF_SYN)) {
FDK_ASSERT(strideOut > 1);
- if ( !(self->flags & SBRDEC_PS_DECODED) ) {
- /* A decoder which is able to decode PS has to produce a stereo output even if no PS data is availble. */
- /* So copy left channel to right channel. */
- int copyFrameSize = codecFrameSize * 2 / self->synDownsampleFac;
- if (interleaved) {
- INT_PCM *ptr;
- INT i;
- FDK_ASSERT(strideOut == 2);
-
- ptr = timeData;
- for (i = copyFrameSize>>1; i--; )
- {
- INT_PCM tmp; /* This temporal variable is required because some compilers can't do *ptr++ = *ptr++ correctly. */
- tmp = *ptr++; *ptr++ = tmp;
- tmp = *ptr++; *ptr++ = tmp;
- }
- } else {
- FDKmemcpy( timeData+copyFrameSize, timeData, copyFrameSize*sizeof(INT_PCM) );
+ if (!(self->flags & SBRDEC_PS_DECODED)) {
+ /* A decoder which is able to decode PS has to produce a stereo output
+ * even if no PS data is available. */
+ /* So copy left channel to right channel. */
+ int copyFrameSize =
+ codecFrameSize * self->pQmfDomain->QmfDomainOut->fb.no_channels;
+ copyFrameSize /= self->pQmfDomain->QmfDomainIn->fb.no_channels;
+ INT_PCM *ptr;
+ INT i;
+ FDK_ASSERT(strideOut == 2);
+
+ ptr = timeData;
+ for (i = copyFrameSize >> 1; i--;) {
+ INT_PCM tmp; /* This temporal variable is required because some
+ compilers can't do *ptr++ = *ptr++ correctly. */
+ tmp = *ptr++;
+ *ptr++ = tmp;
+ tmp = *ptr++;
+ *ptr++ = tmp;
}
}
- *numOutChannels = 2; /* Output minimum two channels when PS is enabled. */
+ *numOutChannels = 2; /* Output minimum two channels when PS is enabled. */
}
return errorStatus;
}
-
-SBR_ERROR sbrDecoder_Apply ( HANDLE_SBRDECODER self,
- INT_PCM *timeData,
- int *numChannels,
- int *sampleRate,
- const UCHAR channelMapping[(8)],
- const int interleaved,
- const int coreDecodedOk,
- UCHAR *psDecoded )
-{
+SBR_ERROR sbrDecoder_Apply(HANDLE_SBRDECODER self, INT_PCM *input,
+ INT_PCM *timeData, const int timeDataSize,
+ int *numChannels, int *sampleRate,
+ const FDK_channelMapDescr *const mapDescr,
+ const int mapIdx, const int coreDecodedOk,
+ UCHAR *psDecoded) {
SBR_ERROR errorStatus = SBRDEC_OK;
- int psPossible = 0;
- int sbrElementNum;
- int numCoreChannels = *numChannels;
- int numSbrChannels = 0;
+ int psPossible;
+ int sbrElementNum;
+ int numCoreChannels;
+ int numSbrChannels = 0;
+
+ if ((self == NULL) || (timeData == NULL) || (numChannels == NULL) ||
+ (sampleRate == NULL) || (psDecoded == NULL) ||
+ !FDK_chMapDescr_isValid(mapDescr)) {
+ return SBRDEC_INVALID_ARGUMENT;
+ }
psPossible = *psDecoded;
+ numCoreChannels = *numChannels;
+ if (numCoreChannels <= 0) {
+ return SBRDEC_INVALID_ARGUMENT;
+ }
if (self->numSbrElements < 1) {
/* exit immediately to avoid access violations */
- return SBRDEC_CREATE_ERROR;
+ return SBRDEC_NOT_INITIALIZED;
}
/* Sanity check of allocated SBR elements. */
- for (sbrElementNum=0; sbrElementNum<self->numSbrElements; sbrElementNum++) {
+ for (sbrElementNum = 0; sbrElementNum < self->numSbrElements;
+ sbrElementNum++) {
if (self->pSbrElement[sbrElementNum] == NULL) {
- return SBRDEC_CREATE_ERROR;
+ return SBRDEC_NOT_INITIALIZED;
}
}
@@ -1568,69 +1841,68 @@ SBR_ERROR sbrDecoder_Apply ( HANDLE_SBRDECODER self,
psPossible = 0;
}
+ /* Make sure that even if no SBR data was found/parsed *psDecoded is returned
+ * 1 if psPossible was 0. */
+ if (psPossible == 0) {
+ self->flags &= ~SBRDEC_PS_DECODED;
+ }
- /* In case of non-interleaved time domain data and upsampling, make room for bigger SBR output. */
- if (self->synDownsampleFac == 1 && interleaved == 0) {
- int c, outputFrameSize;
-
- outputFrameSize =
- self->pSbrElement[0]->pSbrChannel[0]->SbrDec.SynthesisQMF.no_channels
- * self->pSbrElement[0]->pSbrChannel[0]->SbrDec.SynthesisQMF.no_col;
-
- for (c=numCoreChannels-1; c>0; c--) {
- FDKmemmove(timeData + c*outputFrameSize, timeData + c*self->codecFrameSize , self->codecFrameSize*sizeof(INT_PCM));
+ /* replaces channel based reset inside sbr_dec() */
+ if (((self->flags & SBRDEC_LOW_POWER) ? 1 : 0) !=
+ ((self->pQmfDomain->globalConf.flags & QMF_FLAG_LP) ? 1 : 0)) {
+ if (self->flags & SBRDEC_LOW_POWER) {
+ self->pQmfDomain->globalConf.flags |= QMF_FLAG_LP;
+ self->pQmfDomain->globalConf.flags_requested |= QMF_FLAG_LP;
+ } else {
+ self->pQmfDomain->globalConf.flags &= ~QMF_FLAG_LP;
+ self->pQmfDomain->globalConf.flags_requested &= ~QMF_FLAG_LP;
+ }
+ if (FDK_QmfDomain_InitFilterBank(self->pQmfDomain, QMF_FLAG_KEEP_STATES)) {
+ return SBRDEC_UNSUPPORTED_CONFIG;
}
}
-
-
- /* Make sure that even if no SBR data was found/parsed *psDecoded is returned 1 if psPossible was 0. */
- if (psPossible == 0) {
- self->flags &= ~SBRDEC_PS_DECODED;
+ if (self->numSbrChannels > self->pQmfDomain->globalConf.nInputChannels) {
+ return SBRDEC_UNSUPPORTED_CONFIG;
}
- if ( self->flags & SBRDEC_FLUSH ) {
+ if (self->flags & SBRDEC_FLUSH) {
/* flushing is signalized, hence increment the flush frame counter */
self->numFlushedFrames++;
- }
- else {
+ } else {
/* no flushing is signalized, hence reset the flush frame counter */
self->numFlushedFrames = 0;
}
/* Loop over SBR elements */
- for (sbrElementNum = 0; sbrElementNum<self->numSbrElements; sbrElementNum++)
- {
+ for (sbrElementNum = 0; sbrElementNum < self->numSbrElements;
+ sbrElementNum++) {
int numElementChan;
- if (psPossible && self->pSbrElement[sbrElementNum]->pSbrChannel[1] == NULL) {
+ if (psPossible &&
+ self->pSbrElement[sbrElementNum]->pSbrChannel[1] == NULL) {
/* Disable PS and try decoding SBR mono. */
psPossible = 0;
}
- numElementChan = (self->pSbrElement[sbrElementNum]->elementID == ID_CPE) ? 2 : 1;
+ numElementChan =
+ (self->pSbrElement[sbrElementNum]->elementID == ID_CPE) ? 2 : 1;
/* If core signal is bad then force upsampling */
- if ( ! coreDecodedOk ) {
- self->pSbrElement[sbrElementNum]->frameErrorFlag[self->pSbrElement[sbrElementNum]->useFrameSlot] = 1;
+ if (!coreDecodedOk) {
+ setFrameErrorFlag(self->pSbrElement[sbrElementNum], FRAME_ERROR_ALLSLOTS);
}
- errorStatus = sbrDecoder_DecodeElement (
- self,
- timeData,
- interleaved,
- channelMapping,
- sbrElementNum,
- numCoreChannels,
- &numElementChan,
- psPossible
- );
+ errorStatus = sbrDecoder_DecodeElement(
+ self, input, timeData, timeDataSize, mapDescr, mapIdx, numSbrChannels,
+ sbrElementNum,
+ numCoreChannels, /* is correct even for USC SCI==2 case */
+ &numElementChan, psPossible);
if (errorStatus != SBRDEC_OK) {
goto bail;
}
numSbrChannels += numElementChan;
- channelMapping += numElementChan;
if (numSbrChannels >= numCoreChannels) {
break;
@@ -1638,13 +1910,16 @@ SBR_ERROR sbrDecoder_Apply ( HANDLE_SBRDECODER self,
}
/* Update numChannels and samplerate */
- *numChannels = numSbrChannels;
+ /* Do not mess with output channels in case of USAC. numSbrChannels !=
+ * numChannels for stereoConfigIndex == 2 */
+ if (!(self->flags & SBRDEC_SYNTAX_USAC)) {
+ *numChannels = numSbrChannels;
+ }
*sampleRate = self->sampleRateOut;
*psDecoded = (self->flags & SBRDEC_PS_DECODED) ? 1 : 0;
-
-
- /* Clear reset and flush flag because everything seems to be done successfully. */
+ /* Clear reset and flush flag because everything seems to be done
+ * successfully. */
self->flags &= ~SBRDEC_FORCE_RESET;
self->flags &= ~SBRDEC_FLUSH;
@@ -1653,27 +1928,17 @@ bail:
return errorStatus;
}
-
-SBR_ERROR sbrDecoder_Close ( HANDLE_SBRDECODER *pSelf )
-{
+SBR_ERROR sbrDecoder_Close(HANDLE_SBRDECODER *pSelf) {
HANDLE_SBRDECODER self = *pSelf;
int i;
- if (self != NULL)
- {
+ if (self != NULL) {
if (self->hParametricStereoDec != NULL) {
- DeletePsDec ( &self->hParametricStereoDec );
- }
-
- if (self->workBuffer1 != NULL) {
- FreeRam_SbrDecWorkBuffer1(&self->workBuffer1);
- }
- if (self->workBuffer2 != NULL) {
- FreeRam_SbrDecWorkBuffer2(&self->workBuffer2);
+ DeletePsDec(&self->hParametricStereoDec);
}
for (i = 0; i < (8); i++) {
- sbrDecoder_DestroyElement( self, i );
+ sbrDecoder_DestroyElement(self, i);
}
FreeRam_SbrDecoder(pSelf);
@@ -1682,9 +1947,7 @@ SBR_ERROR sbrDecoder_Close ( HANDLE_SBRDECODER *pSelf )
return SBRDEC_OK;
}
-
-INT sbrDecoder_GetLibInfo( LIB_INFO *info )
-{
+INT sbrDecoder_GetLibInfo(LIB_INFO *info) {
int i;
if (info == NULL) {
@@ -1693,62 +1956,55 @@ INT sbrDecoder_GetLibInfo( LIB_INFO *info )
/* search for next free tab */
for (i = 0; i < FDK_MODULE_LAST; i++) {
- if (info[i].module_id == FDK_NONE)
- break;
+ if (info[i].module_id == FDK_NONE) break;
}
- if (i == FDK_MODULE_LAST)
- return -1;
+ if (i == FDK_MODULE_LAST) return -1;
info += i;
info->module_id = FDK_SBRDEC;
- info->version = LIB_VERSION(SBRDECODER_LIB_VL0, SBRDECODER_LIB_VL1, SBRDECODER_LIB_VL2);
+ info->version =
+ LIB_VERSION(SBRDECODER_LIB_VL0, SBRDECODER_LIB_VL1, SBRDECODER_LIB_VL2);
LIB_VERSION_STRING(info);
- info->build_date = (char *)SBRDECODER_LIB_BUILD_DATE;
- info->build_time = (char *)SBRDECODER_LIB_BUILD_TIME;
- info->title = (char *)SBRDECODER_LIB_TITLE;
+ info->build_date = SBRDECODER_LIB_BUILD_DATE;
+ info->build_time = SBRDECODER_LIB_BUILD_TIME;
+ info->title = SBRDECODER_LIB_TITLE;
/* Set flags */
- info->flags = 0
- | CAPF_SBR_HQ
- | CAPF_SBR_LP
- | CAPF_SBR_PS_MPEG
- | CAPF_SBR_DRM_BS
- | CAPF_SBR_CONCEALMENT
- | CAPF_SBR_DRC
- ;
+ info->flags = 0 | CAPF_SBR_HQ | CAPF_SBR_LP | CAPF_SBR_PS_MPEG |
+ CAPF_SBR_DRM_BS | CAPF_SBR_CONCEALMENT | CAPF_SBR_DRC |
+ CAPF_SBR_ELD_DOWNSCALE | CAPF_SBR_HBEHQ;
/* End of flags */
return 0;
}
-
-UINT sbrDecoder_GetDelay( const HANDLE_SBRDECODER self )
-{
+UINT sbrDecoder_GetDelay(const HANDLE_SBRDECODER self) {
UINT outputDelay = 0;
- if ( self != NULL) {
+ if (self != NULL) {
UINT flags = self->flags;
/* See chapter 1.6.7.2 of ISO/IEC 14496-3 for the GA-SBR figures below. */
/* Are we initialized? */
- if ( (self->numSbrChannels > 0)
- && (self->numSbrElements > 0) )
- {
+ if ((self->numSbrChannels > 0) && (self->numSbrElements > 0)) {
/* Add QMF synthesis delay */
- if ( (flags & SBRDEC_ELD_GRID)
- && IS_LOWDELAY(self->coreCodec) ) {
+ if ((flags & SBRDEC_ELD_GRID) && IS_LOWDELAY(self->coreCodec)) {
/* Low delay SBR: */
- {
- outputDelay += (flags & SBRDEC_DOWNSAMPLE) ? 32 : 64; /* QMF synthesis */
+ if (!(flags & SBRDEC_SKIP_QMF_SYN)) {
+ outputDelay +=
+ (flags & SBRDEC_DOWNSAMPLE) ? 32 : 64; /* QMF synthesis */
if (flags & SBRDEC_LD_MPS_QMF) {
outputDelay += 32;
}
}
- }
- else if (!IS_USAC(self->coreCodec)) {
- /* By the method of elimination this is the GA (AAC-LC, HE-AAC, ...) branch: */
+ } else if (!IS_USAC(self->coreCodec)) {
+ /* By the method of elimination this is the GA (AAC-LC, HE-AAC, ...)
+ * branch: */
outputDelay += (flags & SBRDEC_DOWNSAMPLE) ? 481 : 962;
+ if (flags & SBRDEC_SKIP_QMF_SYN) {
+ outputDelay -= 257; /* QMF synthesis */
+ }
}
}
}