diff options
Diffstat (limited to 'libSBRdec/src/sbrdecoder.cpp')
-rw-r--r-- | libSBRdec/src/sbrdecoder.cpp | 1968 |
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 */ + } } } } |