diff options
Diffstat (limited to 'libMpegTPDec/src/tpdec_asc.cpp')
-rw-r--r-- | libMpegTPDec/src/tpdec_asc.cpp | 2681 |
1 files changed, 1856 insertions, 825 deletions
diff --git a/libMpegTPDec/src/tpdec_asc.cpp b/libMpegTPDec/src/tpdec_asc.cpp index e80d0e5..abe66e5 100644 --- a/libMpegTPDec/src/tpdec_asc.cpp +++ b/libMpegTPDec/src/tpdec_asc.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,42 +90,109 @@ Am Wolfsmantel 33 www.iis.fraunhofer.de/amm amm-info@iis.fraunhofer.de ------------------------------------------------------------------------------------------------------------ */ +----------------------------------------------------------------------------- */ -/***************************** MPEG-4 AAC Decoder ************************** +/******************* MPEG transport format decoder library ********************* Author(s): Daniel Homm + Description: -******************************************************************************/ +*******************************************************************************/ #include "tpdec_lib.h" #include "tp_data.h" -#ifdef TP_PCE_ENABLE -#include "FDK_crc.h" -#endif +#include "FDK_crc.h" -void CProgramConfig_Reset(CProgramConfig *pPce) -{ - pPce->elCounter = 0; -} +#include "common_fix.h" -void CProgramConfig_Init(CProgramConfig *pPce) -{ +/** + * The following arrays provide the IDs of the consecutive elements for each + * channel configuration. Every channel_configuration has to be finalized with + * ID_NONE. + */ +static const MP4_ELEMENT_ID channel_configuration_0[] = {ID_NONE}; +static const MP4_ELEMENT_ID channel_configuration_1[] = {ID_SCE, ID_NONE}; +static const MP4_ELEMENT_ID channel_configuration_2[] = {ID_CPE, ID_NONE}; +static const MP4_ELEMENT_ID channel_configuration_3[] = {ID_SCE, ID_CPE, + ID_NONE}; +static const MP4_ELEMENT_ID channel_configuration_4[] = {ID_SCE, ID_CPE, ID_SCE, + ID_NONE}; +static const MP4_ELEMENT_ID channel_configuration_5[] = {ID_SCE, ID_CPE, ID_CPE, + ID_NONE}; +static const MP4_ELEMENT_ID channel_configuration_6[] = {ID_SCE, ID_CPE, ID_CPE, + ID_LFE, ID_NONE}; +static const MP4_ELEMENT_ID channel_configuration_7[] = { + ID_SCE, ID_CPE, ID_CPE, ID_CPE, ID_LFE, ID_NONE}; +static const MP4_ELEMENT_ID channel_configuration_8[] = { + ID_NONE}; /* reserved */ +static const MP4_ELEMENT_ID channel_configuration_9[] = { + ID_NONE}; /* reserved */ +static const MP4_ELEMENT_ID channel_configuration_10[] = { + ID_NONE}; /* reserved */ +static const MP4_ELEMENT_ID channel_configuration_11[] = { + ID_SCE, ID_CPE, ID_CPE, ID_SCE, ID_LFE, ID_NONE}; +static const MP4_ELEMENT_ID channel_configuration_12[] = { + ID_SCE, ID_CPE, ID_CPE, ID_CPE, ID_LFE, ID_NONE}; +static const MP4_ELEMENT_ID channel_configuration_13[] = { + ID_SCE, ID_CPE, ID_CPE, ID_CPE, ID_CPE, ID_SCE, ID_LFE, ID_LFE, ID_SCE, + ID_CPE, ID_CPE, ID_SCE, ID_CPE, ID_SCE, ID_SCE, ID_CPE, ID_NONE}; +static const MP4_ELEMENT_ID channel_configuration_14[] = { + ID_SCE, ID_CPE, ID_CPE, ID_LAST, ID_CPE, ID_NONE}; + +static const MP4_ELEMENT_ID *channel_configuration_array[] = { + channel_configuration_0, channel_configuration_1, + channel_configuration_2, channel_configuration_3, + channel_configuration_4, channel_configuration_5, + channel_configuration_6, channel_configuration_7, + channel_configuration_8, channel_configuration_9, + channel_configuration_10, channel_configuration_11, + channel_configuration_12, channel_configuration_13, + channel_configuration_14}; + +#define TP_USAC_MAX_CHANNEL_CONFIGURATION_INDEX (13) +#define SC_CHANNEL_CONFIG_TAB_SIZE (TP_USAC_MAX_CHANNEL_CONFIGURATION_INDEX + 1) + +/* channel config structure used for sanity check */ +typedef struct { + SCHAR nCh; /* number of channels */ + SCHAR nSCE; /* number of SCE's */ + SCHAR nCPE; /* number of CPE's */ + SCHAR nLFE; /* number of LFE's */ +} SC_CHANNEL_CONFIG; + +static const SC_CHANNEL_CONFIG sc_chan_config_tab[SC_CHANNEL_CONFIG_TAB_SIZE] = + { + /* nCh, nSCE, nCPE, nLFE, cci */ + {0, 0, 0, 0}, /* 0 */ + {1, 1, 0, 0}, /* 1 */ + {2, 0, 1, 0}, /* 2 */ + {3, 1, 1, 0}, /* 3 */ + {4, 2, 1, 0}, /* 4 */ + {5, 1, 2, 0}, /* 5 */ + {6, 1, 2, 1}, /* 6 */ + {8, 1, 3, 1}, /* 7 */ + {2, 2, 0, 0}, /* 8 */ + {3, 1, 1, 0}, /* 9 */ + {4, 0, 2, 0}, /* 10 */ + {7, 2, 2, 1}, /* 11 */ + {8, 1, 3, 1}, /* 12 */ + {24, 6, 8, 2} /* 13 */ +}; + +void CProgramConfig_Reset(CProgramConfig *pPce) { pPce->elCounter = 0; } + +void CProgramConfig_Init(CProgramConfig *pPce) { FDKmemclear(pPce, sizeof(CProgramConfig)); -#ifdef TP_PCE_ENABLE pPce->SamplingFrequencyIndex = 0xf; -#endif } -int CProgramConfig_IsValid ( const CProgramConfig *pPce ) -{ - return ( (pPce->isValid) ? 1 : 0); +int CProgramConfig_IsValid(const CProgramConfig *pPce) { + return ((pPce->isValid) ? 1 : 0); } -#ifdef TP_PCE_ENABLE -#define PCE_HEIGHT_EXT_SYNC ( 0xAC ) +#define PCE_HEIGHT_EXT_SYNC (0xAC) /* * Read the extension for height info. @@ -122,16 +200,12 @@ int CProgramConfig_IsValid ( const CProgramConfig *pPce ) * -1 if the CRC failed, * -2 if invalid HeightInfo. */ -static -int CProgramConfig_ReadHeightExt( - CProgramConfig *pPce, - HANDLE_FDK_BITSTREAM bs, - int * const bytesAvailable, - const UINT alignmentAnchor - ) -{ +static int CProgramConfig_ReadHeightExt(CProgramConfig *pPce, + HANDLE_FDK_BITSTREAM bs, + int *const bytesAvailable, + const UINT alignmentAnchor) { int err = 0; - FDK_CRCINFO crcInfo; /* CRC state info */ + FDK_CRCINFO crcInfo; /* CRC state info */ INT crcReg; FDKcrcInit(&crcInfo, 0x07, 0xFF, 8); crcReg = FDKcrcStartReg(&crcInfo, bs, 0); @@ -141,45 +215,47 @@ int CProgramConfig_ReadHeightExt( FDK_ASSERT(bs != NULL); FDK_ASSERT(bytesAvailable != NULL); - if ( (startAnchor >= 24) && (*bytesAvailable >= 3) - && (FDKreadBits(bs,8) == PCE_HEIGHT_EXT_SYNC) ) - { + if ((startAnchor >= 24) && (*bytesAvailable >= 3) && + (FDKreadBits(bs, 8) == PCE_HEIGHT_EXT_SYNC)) { int i; - for (i=0; i < pPce->NumFrontChannelElements; i++) - { - if ((pPce->FrontElementHeightInfo[i] = (UCHAR) FDKreadBits(bs,2)) >= PC_NUM_HEIGHT_LAYER) { + for (i = 0; i < pPce->NumFrontChannelElements; i++) { + if ((pPce->FrontElementHeightInfo[i] = (UCHAR)FDKreadBits(bs, 2)) >= + PC_NUM_HEIGHT_LAYER) { err = -2; /* height information is out of the valid range */ } } - for (i=0; i < pPce->NumSideChannelElements; i++) - { - if ((pPce->SideElementHeightInfo[i] = (UCHAR) FDKreadBits(bs,2)) >= PC_NUM_HEIGHT_LAYER) { + for (i = 0; i < pPce->NumSideChannelElements; i++) { + if ((pPce->SideElementHeightInfo[i] = (UCHAR)FDKreadBits(bs, 2)) >= + PC_NUM_HEIGHT_LAYER) { err = -2; /* height information is out of the valid range */ } } - for (i=0; i < pPce->NumBackChannelElements; i++) - { - if ((pPce->BackElementHeightInfo[i] = (UCHAR) FDKreadBits(bs,2)) >= PC_NUM_HEIGHT_LAYER) { + for (i = 0; i < pPce->NumBackChannelElements; i++) { + if ((pPce->BackElementHeightInfo[i] = (UCHAR)FDKreadBits(bs, 2)) >= + PC_NUM_HEIGHT_LAYER) { err = -2; /* height information is out of the valid range */ } } FDKbyteAlign(bs, alignmentAnchor); FDKcrcEndReg(&crcInfo, bs, crcReg); - if ((USHORT)FDKreadBits(bs,8) != FDKcrcGetCRC(&crcInfo)) { + if ((USHORT)FDKreadBits(bs, 8) != FDKcrcGetCRC(&crcInfo)) { /* CRC failed */ err = -1; } - if (err!=0) { - /* Reset whole height information in case an error occured during parsing. The return - value ensures that pPce->isValid is set to 0 and implicit channel mapping is used. */ - FDKmemclear(pPce->FrontElementHeightInfo, sizeof(pPce->FrontElementHeightInfo)); - FDKmemclear(pPce->SideElementHeightInfo, sizeof(pPce->SideElementHeightInfo)); - FDKmemclear(pPce->BackElementHeightInfo, sizeof(pPce->BackElementHeightInfo)); + if (err != 0) { + /* Reset whole height information in case an error occured during parsing. + The return value ensures that pPce->isValid is set to 0 and implicit + channel mapping is used. */ + FDKmemclear(pPce->FrontElementHeightInfo, + sizeof(pPce->FrontElementHeightInfo)); + FDKmemclear(pPce->SideElementHeightInfo, + sizeof(pPce->SideElementHeightInfo)); + FDKmemclear(pPce->BackElementHeightInfo, + sizeof(pPce->BackElementHeightInfo)); } - } - else { + } else { /* No valid extension data found -> restore the initial bitbuffer state */ FDKpushBack(bs, startAnchor - FDKgetValidBits(bs)); } @@ -190,99 +266,84 @@ int CProgramConfig_ReadHeightExt( return (err); } -void CProgramConfig_Read( - CProgramConfig *pPce, - HANDLE_FDK_BITSTREAM bs, - UINT alignmentAnchor - ) -{ +void CProgramConfig_Read(CProgramConfig *pPce, HANDLE_FDK_BITSTREAM bs, + UINT alignmentAnchor) { int i, err = 0; int commentBytes; pPce->NumEffectiveChannels = 0; pPce->NumChannels = 0; - pPce->ElementInstanceTag = (UCHAR) FDKreadBits(bs,4); - pPce->Profile = (UCHAR) FDKreadBits(bs,2); - pPce->SamplingFrequencyIndex = (UCHAR) FDKreadBits(bs,4); - pPce->NumFrontChannelElements = (UCHAR) FDKreadBits(bs,4); - pPce->NumSideChannelElements = (UCHAR) FDKreadBits(bs,4); - pPce->NumBackChannelElements = (UCHAR) FDKreadBits(bs,4); - pPce->NumLfeChannelElements = (UCHAR) FDKreadBits(bs,2); - pPce->NumAssocDataElements = (UCHAR) FDKreadBits(bs,3); - pPce->NumValidCcElements = (UCHAR) FDKreadBits(bs,4); - - if ((pPce->MonoMixdownPresent = (UCHAR) FDKreadBits(bs,1)) != 0) - { - pPce->MonoMixdownElementNumber = (UCHAR) FDKreadBits(bs,4); + pPce->ElementInstanceTag = (UCHAR)FDKreadBits(bs, 4); + pPce->Profile = (UCHAR)FDKreadBits(bs, 2); + pPce->SamplingFrequencyIndex = (UCHAR)FDKreadBits(bs, 4); + pPce->NumFrontChannelElements = (UCHAR)FDKreadBits(bs, 4); + pPce->NumSideChannelElements = (UCHAR)FDKreadBits(bs, 4); + pPce->NumBackChannelElements = (UCHAR)FDKreadBits(bs, 4); + pPce->NumLfeChannelElements = (UCHAR)FDKreadBits(bs, 2); + pPce->NumAssocDataElements = (UCHAR)FDKreadBits(bs, 3); + pPce->NumValidCcElements = (UCHAR)FDKreadBits(bs, 4); + + if ((pPce->MonoMixdownPresent = (UCHAR)FDKreadBits(bs, 1)) != 0) { + pPce->MonoMixdownElementNumber = (UCHAR)FDKreadBits(bs, 4); } - if ((pPce->StereoMixdownPresent = (UCHAR) FDKreadBits(bs,1)) != 0) - { - pPce->StereoMixdownElementNumber = (UCHAR) FDKreadBits(bs,4); + if ((pPce->StereoMixdownPresent = (UCHAR)FDKreadBits(bs, 1)) != 0) { + pPce->StereoMixdownElementNumber = (UCHAR)FDKreadBits(bs, 4); } - if ((pPce->MatrixMixdownIndexPresent = (UCHAR) FDKreadBits(bs,1)) != 0) - { - pPce->MatrixMixdownIndex = (UCHAR) FDKreadBits(bs,2); - pPce->PseudoSurroundEnable = (UCHAR) FDKreadBits(bs,1); + if ((pPce->MatrixMixdownIndexPresent = (UCHAR)FDKreadBits(bs, 1)) != 0) { + pPce->MatrixMixdownIndex = (UCHAR)FDKreadBits(bs, 2); + pPce->PseudoSurroundEnable = (UCHAR)FDKreadBits(bs, 1); } - for (i=0; i < pPce->NumFrontChannelElements; i++) - { - pPce->FrontElementIsCpe[i] = (UCHAR) FDKreadBits(bs,1); - pPce->FrontElementTagSelect[i] = (UCHAR) FDKreadBits(bs,4); + for (i = 0; i < pPce->NumFrontChannelElements; i++) { + pPce->FrontElementIsCpe[i] = (UCHAR)FDKreadBits(bs, 1); + pPce->FrontElementTagSelect[i] = (UCHAR)FDKreadBits(bs, 4); pPce->NumChannels += pPce->FrontElementIsCpe[i] ? 2 : 1; } - for (i=0; i < pPce->NumSideChannelElements; i++) - { - pPce->SideElementIsCpe[i] = (UCHAR) FDKreadBits(bs,1); - pPce->SideElementTagSelect[i] = (UCHAR) FDKreadBits(bs,4); + for (i = 0; i < pPce->NumSideChannelElements; i++) { + pPce->SideElementIsCpe[i] = (UCHAR)FDKreadBits(bs, 1); + pPce->SideElementTagSelect[i] = (UCHAR)FDKreadBits(bs, 4); pPce->NumChannels += pPce->SideElementIsCpe[i] ? 2 : 1; } - for (i=0; i < pPce->NumBackChannelElements; i++) - { - pPce->BackElementIsCpe[i] = (UCHAR) FDKreadBits(bs,1); - pPce->BackElementTagSelect[i] = (UCHAR) FDKreadBits(bs,4); + for (i = 0; i < pPce->NumBackChannelElements; i++) { + pPce->BackElementIsCpe[i] = (UCHAR)FDKreadBits(bs, 1); + pPce->BackElementTagSelect[i] = (UCHAR)FDKreadBits(bs, 4); pPce->NumChannels += pPce->BackElementIsCpe[i] ? 2 : 1; } pPce->NumEffectiveChannels = pPce->NumChannels; - for (i=0; i < pPce->NumLfeChannelElements; i++) - { - pPce->LfeElementTagSelect[i] = (UCHAR) FDKreadBits(bs,4); + for (i = 0; i < pPce->NumLfeChannelElements; i++) { + pPce->LfeElementTagSelect[i] = (UCHAR)FDKreadBits(bs, 4); pPce->NumChannels += 1; } - for (i=0; i < pPce->NumAssocDataElements; i++) - { - pPce->AssocDataElementTagSelect[i] = (UCHAR) FDKreadBits(bs,4); + for (i = 0; i < pPce->NumAssocDataElements; i++) { + pPce->AssocDataElementTagSelect[i] = (UCHAR)FDKreadBits(bs, 4); } - for (i=0; i < pPce->NumValidCcElements; i++) - { - pPce->CcElementIsIndSw[i] = (UCHAR) FDKreadBits(bs,1); - pPce->ValidCcElementTagSelect[i] = (UCHAR) FDKreadBits(bs,4); + for (i = 0; i < pPce->NumValidCcElements; i++) { + pPce->CcElementIsIndSw[i] = (UCHAR)FDKreadBits(bs, 1); + pPce->ValidCcElementTagSelect[i] = (UCHAR)FDKreadBits(bs, 4); } FDKbyteAlign(bs, alignmentAnchor); - pPce->CommentFieldBytes = (UCHAR) FDKreadBits(bs,8); + pPce->CommentFieldBytes = (UCHAR)FDKreadBits(bs, 8); commentBytes = pPce->CommentFieldBytes; /* Search for height info extension and read it if available */ - err = CProgramConfig_ReadHeightExt( pPce, bs, &commentBytes, alignmentAnchor ); + err = CProgramConfig_ReadHeightExt(pPce, bs, &commentBytes, alignmentAnchor); - for (i=0; i < commentBytes; i++) - { + for (i = 0; i < commentBytes; i++) { UCHAR text; - text = (UCHAR)FDKreadBits(bs,8); + text = (UCHAR)FDKreadBits(bs, 8); - if (i < PC_COMMENTLENGTH) - { + if (i < PC_COMMENTLENGTH) { pPce->Comment[i] = text; } } @@ -298,28 +359,29 @@ void CProgramConfig_Read( * 1 - different but same channel configuration * 2 - different channel configuration but same number of channels */ -int CProgramConfig_Compare ( const CProgramConfig * const pPce1, - const CProgramConfig * const pPce2 ) -{ - int result = 0; /* Innocent until proven false. */ - - if (FDKmemcmp(pPce1, pPce2, sizeof(CProgramConfig)) != 0) - { /* Configurations are not completely different. - So look into details and analyse the channel configurations: */ +int CProgramConfig_Compare(const CProgramConfig *const pPce1, + const CProgramConfig *const pPce2) { + int result = 0; /* Innocent until proven false. */ + + if (FDKmemcmp(pPce1, pPce2, sizeof(CProgramConfig)) != + 0) { /* Configurations are not completely equal. + So look into details and analyse the channel configurations: */ result = -1; - if (pPce1->NumChannels == pPce2->NumChannels) - { /* Now the logic changes. We first assume to have the same channel configuration - and then prove if this assumption is true. */ + if (pPce1->NumChannels == + pPce2->NumChannels) { /* Now the logic changes. We first assume to have + the same channel configuration and then prove + if this assumption is true. */ result = 1; /* Front channels */ if (pPce1->NumFrontChannelElements != pPce2->NumFrontChannelElements) { - result = 2; /* different number of front channel elements */ + result = 2; /* different number of front channel elements */ } else { int el, numCh1 = 0, numCh2 = 0; for (el = 0; el < pPce1->NumFrontChannelElements; el += 1) { - if (pPce1->FrontElementHeightInfo[el] != pPce2->FrontElementHeightInfo[el]) { + if (pPce1->FrontElementHeightInfo[el] != + pPce2->FrontElementHeightInfo[el]) { result = 2; /* different height info */ break; } @@ -327,16 +389,17 @@ int CProgramConfig_Compare ( const CProgramConfig * const pPce1, numCh2 += pPce2->FrontElementIsCpe[el] ? 2 : 1; } if (numCh1 != numCh2) { - result = 2; /* different number of front channels */ + result = 2; /* different number of front channels */ } } /* Side channels */ if (pPce1->NumSideChannelElements != pPce2->NumSideChannelElements) { - result = 2; /* different number of side channel elements */ + result = 2; /* different number of side channel elements */ } else { int el, numCh1 = 0, numCh2 = 0; for (el = 0; el < pPce1->NumSideChannelElements; el += 1) { - if (pPce1->SideElementHeightInfo[el] != pPce2->SideElementHeightInfo[el]) { + if (pPce1->SideElementHeightInfo[el] != + pPce2->SideElementHeightInfo[el]) { result = 2; /* different height info */ break; } @@ -344,16 +407,17 @@ int CProgramConfig_Compare ( const CProgramConfig * const pPce1, numCh2 += pPce2->SideElementIsCpe[el] ? 2 : 1; } if (numCh1 != numCh2) { - result = 2; /* different number of side channels */ + result = 2; /* different number of side channels */ } } /* Back channels */ if (pPce1->NumBackChannelElements != pPce2->NumBackChannelElements) { - result = 2; /* different number of back channel elements */ + result = 2; /* different number of back channel elements */ } else { int el, numCh1 = 0, numCh2 = 0; for (el = 0; el < pPce1->NumBackChannelElements; el += 1) { - if (pPce1->BackElementHeightInfo[el] != pPce2->BackElementHeightInfo[el]) { + if (pPce1->BackElementHeightInfo[el] != + pPce2->BackElementHeightInfo[el]) { result = 2; /* different height info */ break; } @@ -361,12 +425,12 @@ int CProgramConfig_Compare ( const CProgramConfig * const pPce1, numCh2 += pPce2->BackElementIsCpe[el] ? 2 : 1; } if (numCh1 != numCh2) { - result = 2; /* different number of back channels */ + result = 2; /* different number of back channels */ } } /* LFE channels */ if (pPce1->NumLfeChannelElements != pPce2->NumLfeChannelElements) { - result = 2; /* different number of lfe channels */ + result = 2; /* different number of lfe channels */ } /* LFEs are always SCEs so we don't need to count the channels. */ } @@ -375,88 +439,87 @@ int CProgramConfig_Compare ( const CProgramConfig * const pPce1, return result; } -void CProgramConfig_GetDefault( CProgramConfig *pPce, - const UINT channelConfig ) -{ +void CProgramConfig_GetDefault(CProgramConfig *pPce, const UINT channelConfig) { FDK_ASSERT(pPce != NULL); /* Init PCE */ CProgramConfig_Init(pPce); - pPce->Profile = 1; /* Set AAC LC because it is the only supported object type. */ + pPce->Profile = + 1; /* Set AAC LC because it is the only supported object type. */ switch (channelConfig) { - /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - case 32: /* 7.1 side channel configuration as defined in FDK_audio.h */ - pPce->NumFrontChannelElements = 2; - pPce->FrontElementIsCpe[0] = 0; - pPce->FrontElementIsCpe[1] = 1; - pPce->NumSideChannelElements = 1; - pPce->SideElementIsCpe[0] = 1; - pPce->NumBackChannelElements = 1; - pPce->BackElementIsCpe[0] = 1; - pPce->NumLfeChannelElements = 1; - pPce->NumChannels = 8; - pPce->NumEffectiveChannels = 7; - pPce->isValid = 1; - break; - /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - case 12: /* 3/0/4.1ch surround back */ - pPce->BackElementIsCpe[1] = 1; - pPce->NumChannels += 1; - pPce->NumEffectiveChannels += 1; - case 11: /* 3/0/3.1ch */ - pPce->NumFrontChannelElements += 2; - pPce->FrontElementIsCpe[0] = 0; - pPce->FrontElementIsCpe[1] = 1; - pPce->NumBackChannelElements += 2; - pPce->BackElementIsCpe[0] = 1; - pPce->BackElementIsCpe[1] += 0; - pPce->NumLfeChannelElements += 1; - pPce->NumChannels += 7; - pPce->NumEffectiveChannels += 6; - pPce->isValid = 1; - break; - /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - case 14: /* 2/0/0-3/0/2-0.1ch front height */ - pPce->FrontElementHeightInfo[2] = 1; /* Top speaker */ - case 7: /* 5/0/2.1ch front */ - pPce->NumFrontChannelElements += 1; - pPce->FrontElementIsCpe[2] = 1; - pPce->NumChannels += 2; - pPce->NumEffectiveChannels += 2; - case 6: /* 3/0/2.1ch */ - pPce->NumLfeChannelElements += 1; - pPce->NumChannels += 1; - case 5: /* 3/0/2.0ch */ - case 4: /* 3/0/1.0ch */ - pPce->NumBackChannelElements += 1; - pPce->BackElementIsCpe[0] = (channelConfig>4) ? 1 : 0; - pPce->NumChannels += (channelConfig>4) ? 2 : 1; - pPce->NumEffectiveChannels += (channelConfig>4) ? 2 : 1; - case 3: /* 3/0/0.0ch */ - pPce->NumFrontChannelElements += 1; - pPce->FrontElementIsCpe[1] = 1; - pPce->NumChannels += 2; - pPce->NumEffectiveChannels += 2; - case 1: /* 1/0/0.0ch */ - pPce->NumFrontChannelElements += 1; - pPce->FrontElementIsCpe[0] = 0; - pPce->NumChannels += 1; - pPce->NumEffectiveChannels += 1; - pPce->isValid = 1; - break; - /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - case 2: /* 2/0/0.ch */ - pPce->NumFrontChannelElements = 1; - pPce->FrontElementIsCpe[0] = 1; - pPce->NumChannels += 2; - pPce->NumEffectiveChannels += 2; - pPce->isValid = 1; - break; - /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - default: - pPce->isValid = 0; /* To be explicit! */ - break; + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + case 32: /* 7.1 side channel configuration as defined in FDK_audio.h */ + pPce->NumFrontChannelElements = 2; + pPce->FrontElementIsCpe[0] = 0; + pPce->FrontElementIsCpe[1] = 1; + pPce->NumSideChannelElements = 1; + pPce->SideElementIsCpe[0] = 1; + pPce->NumBackChannelElements = 1; + pPce->BackElementIsCpe[0] = 1; + pPce->NumLfeChannelElements = 1; + pPce->NumChannels = 8; + pPce->NumEffectiveChannels = 7; + pPce->isValid = 1; + break; + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + case 12: /* 3/0/4.1ch surround back */ + pPce->BackElementIsCpe[1] = 1; + pPce->NumChannels += 1; + pPce->NumEffectiveChannels += 1; + case 11: /* 3/0/3.1ch */ + pPce->NumFrontChannelElements += 2; + pPce->FrontElementIsCpe[0] = 0; + pPce->FrontElementIsCpe[1] = 1; + pPce->NumBackChannelElements += 2; + pPce->BackElementIsCpe[0] = 1; + pPce->BackElementIsCpe[1] += 0; + pPce->NumLfeChannelElements += 1; + pPce->NumChannels += 7; + pPce->NumEffectiveChannels += 6; + pPce->isValid = 1; + break; + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + case 14: /* 2/0/0-3/0/2-0.1ch front height */ + pPce->FrontElementHeightInfo[2] = 1; /* Top speaker */ + case 7: /* 5/0/2.1ch front */ + pPce->NumFrontChannelElements += 1; + pPce->FrontElementIsCpe[2] = 1; + pPce->NumChannels += 2; + pPce->NumEffectiveChannels += 2; + case 6: /* 3/0/2.1ch */ + pPce->NumLfeChannelElements += 1; + pPce->NumChannels += 1; + case 5: /* 3/0/2.0ch */ + case 4: /* 3/0/1.0ch */ + pPce->NumBackChannelElements += 1; + pPce->BackElementIsCpe[0] = (channelConfig > 4) ? 1 : 0; + pPce->NumChannels += (channelConfig > 4) ? 2 : 1; + pPce->NumEffectiveChannels += (channelConfig > 4) ? 2 : 1; + case 3: /* 3/0/0.0ch */ + pPce->NumFrontChannelElements += 1; + pPce->FrontElementIsCpe[1] = 1; + pPce->NumChannels += 2; + pPce->NumEffectiveChannels += 2; + case 1: /* 1/0/0.0ch */ + pPce->NumFrontChannelElements += 1; + pPce->FrontElementIsCpe[0] = 0; + pPce->NumChannels += 1; + pPce->NumEffectiveChannels += 1; + pPce->isValid = 1; + break; + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + case 2: /* 2/0/0.ch */ + pPce->NumFrontChannelElements = 1; + pPce->FrontElementIsCpe[0] = 1; + pPce->NumChannels += 2; + pPce->NumEffectiveChannels += 2; + pPce->isValid = 1; + break; + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + default: + pPce->isValid = 0; /* To be explicit! */ + break; } if (pPce->isValid) { @@ -464,13 +527,16 @@ void CProgramConfig_GetDefault( CProgramConfig *pPce, int el, elTagSce = 0, elTagCpe = 0; for (el = 0; el < pPce->NumFrontChannelElements; el += 1) { - pPce->FrontElementTagSelect[el] = (pPce->FrontElementIsCpe[el]) ? elTagCpe++ : elTagSce++; + pPce->FrontElementTagSelect[el] = + (pPce->FrontElementIsCpe[el]) ? elTagCpe++ : elTagSce++; } for (el = 0; el < pPce->NumSideChannelElements; el += 1) { - pPce->SideElementTagSelect[el] = (pPce->SideElementIsCpe[el]) ? elTagCpe++ : elTagSce++; + pPce->SideElementTagSelect[el] = + (pPce->SideElementIsCpe[el]) ? elTagCpe++ : elTagSce++; } for (el = 0; el < pPce->NumBackChannelElements; el += 1) { - pPce->BackElementTagSelect[el] = (pPce->BackElementIsCpe[el]) ? elTagCpe++ : elTagSce++; + pPce->BackElementTagSelect[el] = + (pPce->BackElementIsCpe[el]) ? elTagCpe++ : elTagSce++; } elTagSce = 0; for (el = 0; el < pPce->NumLfeChannelElements; el += 1) { @@ -478,30 +544,26 @@ void CProgramConfig_GetDefault( CProgramConfig *pPce, } } } -#endif /* TP_PCE_ENABLE */ /** - * \brief get implicit audio channel type for given channelConfig and MPEG ordered channel index + * \brief get implicit audio channel type for given channelConfig and MPEG + * ordered channel index * \param channelConfig MPEG channelConfiguration from 1 upto 14 * \param index MPEG channel order index * \return audio channel type. */ -static -void getImplicitAudioChannelTypeAndIndex( - AUDIO_CHANNEL_TYPE *chType, - UCHAR *chIndex, - UINT channelConfig, - UINT index - ) -{ +static void getImplicitAudioChannelTypeAndIndex(AUDIO_CHANNEL_TYPE *chType, + UCHAR *chIndex, + UINT channelConfig, + UINT index) { if (index < 3) { *chType = ACT_FRONT; *chIndex = index; } else { switch (channelConfig) { - case 4: /* SCE, CPE, SCE */ - case 5: /* SCE, CPE, CPE */ - case 6: /* SCE, CPE, CPE, LFE */ + case 4: /* SCE, CPE, SCE */ + case 5: /* SCE, CPE, CPE */ + case 6: /* SCE, CPE, CPE, LFE */ switch (index) { case 3: case 4: @@ -514,7 +576,7 @@ void getImplicitAudioChannelTypeAndIndex( break; } break; - case 7: /* SCE,CPE,CPE,CPE,LFE */ + case 7: /* SCE,CPE,CPE,CPE,LFE */ switch (index) { case 3: case 4: @@ -532,7 +594,7 @@ void getImplicitAudioChannelTypeAndIndex( break; } break; - case 11: /* SCE,CPE,CPE,SCE,LFE */ + case 11: /* SCE,CPE,CPE,SCE,LFE */ if (index < 6) { *chType = ACT_BACK; *chIndex = index - 3; @@ -541,7 +603,7 @@ void getImplicitAudioChannelTypeAndIndex( *chIndex = 0; } break; - case 12: /* SCE,CPE,CPE,CPE,LFE */ + case 12: /* SCE,CPE,CPE,CPE,LFE */ if (index < 7) { *chType = ACT_BACK; *chIndex = index - 3; @@ -550,7 +612,7 @@ void getImplicitAudioChannelTypeAndIndex( *chIndex = 0; } break; - case 14: /* SCE,CPE,CPE,LFE,CPE */ + case 14: /* SCE,CPE,CPE,LFE,CPE */ switch (index) { case 3: case 4: @@ -564,7 +626,7 @@ void getImplicitAudioChannelTypeAndIndex( case 6: case 7: *chType = ACT_FRONT_TOP; - *chIndex = index - 6; /* handle the top layer independently */ + *chIndex = index - 6; /* handle the top layer independently */ break; } break; @@ -575,436 +637,574 @@ void getImplicitAudioChannelTypeAndIndex( } } -int CProgramConfig_LookupElement( - CProgramConfig *pPce, - UINT channelConfig, - const UINT tag, - const UINT channelIdx, - UCHAR chMapping[], - AUDIO_CHANNEL_TYPE chType[], - UCHAR chIndex[], - UCHAR *elMapping, - MP4_ELEMENT_ID elList[], - MP4_ELEMENT_ID elType - ) -{ - if (channelConfig > 0) - { +int CProgramConfig_LookupElement(CProgramConfig *pPce, UINT channelConfig, + const UINT tag, const UINT channelIdx, + UCHAR chMapping[], AUDIO_CHANNEL_TYPE chType[], + UCHAR chIndex[], const UINT chDescrLen, + UCHAR *elMapping, MP4_ELEMENT_ID elList[], + MP4_ELEMENT_ID elType) { + if (channelConfig > 0) { /* Constant channel mapping must have been set during initialization. */ - if ( elType == ID_SCE - || elType == ID_CPE - || elType == ID_LFE ) - { + if (IS_CHANNEL_ELEMENT(elType)) { *elMapping = pPce->elCounter; - if (elList[pPce->elCounter] != elType) { + if (elList[pPce->elCounter] != elType && + !IS_USAC_CHANNEL_ELEMENT(elType)) { /* Not in the list */ - if ( (channelConfig == 2) && (elType == ID_SCE) ) - { /* This scenario occurs with HE-AAC v2 streams of buggy encoders. - Due to other decoder implementations decoding of these kind of streams is desired. */ + if ((channelConfig == 2) && + (elType == ID_SCE)) { /* This scenario occurs with HE-AAC v2 streams + of buggy encoders. In other decoder + implementations decoding of this kind of + streams is desired. */ channelConfig = 1; + } else if ((elList[pPce->elCounter] == ID_LFE) && + (elType == + ID_SCE)) { /* Decode bitstreams which wrongly use ID_SCE + instead of ID_LFE element type. */ + ; } else { return 0; } } /* Assume all front channels */ - getImplicitAudioChannelTypeAndIndex(&chType[channelIdx], &chIndex[channelIdx], channelConfig, channelIdx); - if (elType == ID_CPE) { - chType[channelIdx+1] = chType[channelIdx]; - chIndex[channelIdx+1] = chIndex[channelIdx]+1; + getImplicitAudioChannelTypeAndIndex( + &chType[channelIdx], &chIndex[channelIdx], channelConfig, channelIdx); + if (elType == ID_CPE || elType == ID_USAC_CPE) { + chType[channelIdx + 1] = chType[channelIdx]; + chIndex[channelIdx + 1] = chIndex[channelIdx] + 1; } pPce->elCounter++; } /* Accept all non-channel elements, too. */ return 1; - } - else - { -#ifdef TP_PCE_ENABLE - if (!pPce->isValid) -#endif /* TP_PCE_ENABLE */ - { + } else { + if ((!pPce->isValid) || (pPce->NumChannels > chDescrLen)) { /* Implicit channel mapping. */ - if ( elType == ID_SCE - || elType == ID_CPE - || elType == ID_LFE ) - { + if (IS_USAC_CHANNEL_ELEMENT(elType)) { + *elMapping = pPce->elCounter++; + } else if (IS_MP4_CHANNEL_ELEMENT(elType)) { /* Store all channel element IDs */ elList[pPce->elCounter] = elType; *elMapping = pPce->elCounter++; } - } -#ifdef TP_PCE_ENABLE - else { + } else { /* Accept the additional channel(s), only if the tag is in the lists */ int isCpe = 0, i; /* Element counter */ int ec[PC_NUM_HEIGHT_LAYER] = {0}; /* Channel counters */ int cc[PC_NUM_HEIGHT_LAYER] = {0}; - int fc[PC_NUM_HEIGHT_LAYER] = {0}; - int sc[PC_NUM_HEIGHT_LAYER] = {0}; - int bc[PC_NUM_HEIGHT_LAYER] = {0}; - int lc = 0;; + int fc[PC_NUM_HEIGHT_LAYER] = {0}; /* front channel counter */ + int sc[PC_NUM_HEIGHT_LAYER] = {0}; /* side channel counter */ + int bc[PC_NUM_HEIGHT_LAYER] = {0}; /* back channel counter */ + int lc = 0; /* lfe channel counter */ /* General MPEG (PCE) composition rules: - Over all: - <normal height channels><top height channels><bottom height channels> + <normal height channels><top height channels><bottom height + channels> - Within each height layer: <front channels><side channels><back channels> - Exception: - The LFE channels have no height info and thus they are arranged at the very - end of the normal height layer channels. + The LFE channels have no height info and thus they are arranged at + the very end of the normal height layer channels. */ - switch (elType) - { - case ID_CPE: - isCpe = 1; - case ID_SCE: - /* search in front channels */ - for (i = 0; i < pPce->NumFrontChannelElements; i++) { - int heightLayer = pPce->FrontElementHeightInfo[i]; - if (isCpe == pPce->FrontElementIsCpe[i] && pPce->FrontElementTagSelect[i] == tag) { - int h, elIdx = ec[heightLayer], chIdx = cc[heightLayer]; - AUDIO_CHANNEL_TYPE aChType = (AUDIO_CHANNEL_TYPE)((heightLayer<<4) | ACT_FRONT); - for (h = heightLayer-1; h >= 0; h-=1) { - int el; - /* Count front channels/elements */ - for (el = 0; el < pPce->NumFrontChannelElements; el+=1) { - if (pPce->FrontElementHeightInfo[el] == h) { - elIdx += 1; - chIdx += (pPce->FrontElementIsCpe[el]) ? 2 : 1; + switch (elType) { + case ID_CPE: + isCpe = 1; + case ID_SCE: + /* search in front channels */ + for (i = 0; i < pPce->NumFrontChannelElements; i++) { + int heightLayer = pPce->FrontElementHeightInfo[i]; + if (isCpe == pPce->FrontElementIsCpe[i] && + pPce->FrontElementTagSelect[i] == tag) { + int h, elIdx = ec[heightLayer], chIdx = cc[heightLayer]; + AUDIO_CHANNEL_TYPE aChType = + (AUDIO_CHANNEL_TYPE)((heightLayer << 4) | ACT_FRONT); + for (h = heightLayer - 1; h >= 0; h -= 1) { + int el; + /* Count front channels/elements */ + for (el = 0; el < pPce->NumFrontChannelElements; el += 1) { + if (pPce->FrontElementHeightInfo[el] == h) { + elIdx += 1; + chIdx += (pPce->FrontElementIsCpe[el]) ? 2 : 1; + } } - } - /* Count side channels/elements */ - for (el = 0; el < pPce->NumSideChannelElements; el+=1) { - if (pPce->SideElementHeightInfo[el] == h) { - elIdx += 1; - chIdx += (pPce->SideElementIsCpe[el]) ? 2 : 1; + /* Count side channels/elements */ + for (el = 0; el < pPce->NumSideChannelElements; el += 1) { + if (pPce->SideElementHeightInfo[el] == h) { + elIdx += 1; + chIdx += (pPce->SideElementIsCpe[el]) ? 2 : 1; + } } - } - /* Count back channels/elements */ - for (el = 0; el < pPce->NumBackChannelElements; el+=1) { - if (pPce->BackElementHeightInfo[el] == h) { - elIdx += 1; - chIdx += (pPce->BackElementIsCpe[el]) ? 2 : 1; + /* Count back channels/elements */ + for (el = 0; el < pPce->NumBackChannelElements; el += 1) { + if (pPce->BackElementHeightInfo[el] == h) { + elIdx += 1; + chIdx += (pPce->BackElementIsCpe[el]) ? 2 : 1; + } + } + if (h == 0) { /* normal height */ + elIdx += pPce->NumLfeChannelElements; + chIdx += pPce->NumLfeChannelElements; } } - if (h == 0) { /* normal height */ - elIdx += pPce->NumLfeChannelElements; - chIdx += pPce->NumLfeChannelElements; + chMapping[chIdx] = channelIdx; + chType[chIdx] = aChType; + chIndex[chIdx] = fc[heightLayer]; + if (isCpe) { + chMapping[chIdx + 1] = channelIdx + 1; + chType[chIdx + 1] = aChType; + chIndex[chIdx + 1] = fc[heightLayer] + 1; } + *elMapping = elIdx; + return 1; } - chMapping[chIdx] = channelIdx; - chType[chIdx] = aChType; - chIndex[chIdx] = fc[heightLayer]; - if (isCpe) { - chMapping[chIdx+1] = channelIdx+1; - chType[chIdx+1] = aChType; - chIndex[chIdx+1] = fc[heightLayer]+1; + ec[heightLayer] += 1; + if (pPce->FrontElementIsCpe[i]) { + cc[heightLayer] += 2; + fc[heightLayer] += 2; + } else { + cc[heightLayer] += 1; + fc[heightLayer] += 1; } - *elMapping = elIdx; - return 1; - } - ec[heightLayer] += 1; - if (pPce->FrontElementIsCpe[i]) { - cc[heightLayer] += 2; - fc[heightLayer] += 2; - } else { - cc[heightLayer] += 1; - fc[heightLayer] += 1; } - } - /* search in side channels */ - for (i = 0; i < pPce->NumSideChannelElements; i++) { - int heightLayer = pPce->SideElementHeightInfo[i]; - if (isCpe == pPce->SideElementIsCpe[i] && pPce->SideElementTagSelect[i] == tag) { - int h, elIdx = ec[heightLayer], chIdx = cc[heightLayer]; - AUDIO_CHANNEL_TYPE aChType = (AUDIO_CHANNEL_TYPE)((heightLayer<<4) | ACT_SIDE); - for (h = heightLayer-1; h >= 0; h-=1) { - int el; - /* Count front channels/elements */ - for (el = 0; el < pPce->NumFrontChannelElements; el+=1) { - if (pPce->FrontElementHeightInfo[el] == h) { - elIdx += 1; - chIdx += (pPce->FrontElementIsCpe[el]) ? 2 : 1; + /* search in side channels */ + for (i = 0; i < pPce->NumSideChannelElements; i++) { + int heightLayer = pPce->SideElementHeightInfo[i]; + if (isCpe == pPce->SideElementIsCpe[i] && + pPce->SideElementTagSelect[i] == tag) { + int h, elIdx = ec[heightLayer], chIdx = cc[heightLayer]; + AUDIO_CHANNEL_TYPE aChType = + (AUDIO_CHANNEL_TYPE)((heightLayer << 4) | ACT_SIDE); + for (h = heightLayer - 1; h >= 0; h -= 1) { + int el; + /* Count front channels/elements */ + for (el = 0; el < pPce->NumFrontChannelElements; el += 1) { + if (pPce->FrontElementHeightInfo[el] == h) { + elIdx += 1; + chIdx += (pPce->FrontElementIsCpe[el]) ? 2 : 1; + } } - } - /* Count side channels/elements */ - for (el = 0; el < pPce->NumSideChannelElements; el+=1) { - if (pPce->SideElementHeightInfo[el] == h) { - elIdx += 1; - chIdx += (pPce->SideElementIsCpe[el]) ? 2 : 1; + /* Count side channels/elements */ + for (el = 0; el < pPce->NumSideChannelElements; el += 1) { + if (pPce->SideElementHeightInfo[el] == h) { + elIdx += 1; + chIdx += (pPce->SideElementIsCpe[el]) ? 2 : 1; + } } - } - /* Count back channels/elements */ - for (el = 0; el < pPce->NumBackChannelElements; el+=1) { - if (pPce->BackElementHeightInfo[el] == h) { - elIdx += 1; - chIdx += (pPce->BackElementIsCpe[el]) ? 2 : 1; + /* Count back channels/elements */ + for (el = 0; el < pPce->NumBackChannelElements; el += 1) { + if (pPce->BackElementHeightInfo[el] == h) { + elIdx += 1; + chIdx += (pPce->BackElementIsCpe[el]) ? 2 : 1; + } + } + if (h == + 0) { /* LFE channels belong to the normal height layer */ + elIdx += pPce->NumLfeChannelElements; + chIdx += pPce->NumLfeChannelElements; } } - if (h == 0) { /* LFE channels belong to the normal height layer */ - elIdx += pPce->NumLfeChannelElements; - chIdx += pPce->NumLfeChannelElements; + chMapping[chIdx] = channelIdx; + chType[chIdx] = aChType; + chIndex[chIdx] = sc[heightLayer]; + if (isCpe) { + chMapping[chIdx + 1] = channelIdx + 1; + chType[chIdx + 1] = aChType; + chIndex[chIdx + 1] = sc[heightLayer] + 1; } + *elMapping = elIdx; + return 1; } - chMapping[chIdx] = channelIdx; - chType[chIdx] = aChType; - chIndex[chIdx] = sc[heightLayer]; - if (isCpe) { - chMapping[chIdx+1] = channelIdx+1; - chType[chIdx+1] = aChType; - chIndex[chIdx+1] = sc[heightLayer]+1; + ec[heightLayer] += 1; + if (pPce->SideElementIsCpe[i]) { + cc[heightLayer] += 2; + sc[heightLayer] += 2; + } else { + cc[heightLayer] += 1; + sc[heightLayer] += 1; } - *elMapping = elIdx; - return 1; - } - ec[heightLayer] += 1; - if (pPce->SideElementIsCpe[i]) { - cc[heightLayer] += 2; - sc[heightLayer] += 2; - } else { - cc[heightLayer] += 1; - sc[heightLayer] += 1; } - } - /* search in back channels */ - for (i = 0; i < pPce->NumBackChannelElements; i++) { - int heightLayer = pPce->BackElementHeightInfo[i]; - if (isCpe == pPce->BackElementIsCpe[i] && pPce->BackElementTagSelect[i] == tag) { - int h, elIdx = ec[heightLayer], chIdx = cc[heightLayer]; - AUDIO_CHANNEL_TYPE aChType = (AUDIO_CHANNEL_TYPE)((heightLayer<<4) | ACT_BACK); - for (h = heightLayer-1; h >= 0; h-=1) { - int el; - /* Count front channels/elements */ - for (el = 0; el < pPce->NumFrontChannelElements; el+=1) { - if (pPce->FrontElementHeightInfo[el] == h) { - elIdx += 1; - chIdx += (pPce->FrontElementIsCpe[el]) ? 2 : 1; + /* search in back channels */ + for (i = 0; i < pPce->NumBackChannelElements; i++) { + int heightLayer = pPce->BackElementHeightInfo[i]; + if (isCpe == pPce->BackElementIsCpe[i] && + pPce->BackElementTagSelect[i] == tag) { + int h, elIdx = ec[heightLayer], chIdx = cc[heightLayer]; + AUDIO_CHANNEL_TYPE aChType = + (AUDIO_CHANNEL_TYPE)((heightLayer << 4) | ACT_BACK); + for (h = heightLayer - 1; h >= 0; h -= 1) { + int el; + /* Count front channels/elements */ + for (el = 0; el < pPce->NumFrontChannelElements; el += 1) { + if (pPce->FrontElementHeightInfo[el] == h) { + elIdx += 1; + chIdx += (pPce->FrontElementIsCpe[el]) ? 2 : 1; + } } - } - /* Count side channels/elements */ - for (el = 0; el < pPce->NumSideChannelElements; el+=1) { - if (pPce->SideElementHeightInfo[el] == h) { - elIdx += 1; - chIdx += (pPce->SideElementIsCpe[el]) ? 2 : 1; + /* Count side channels/elements */ + for (el = 0; el < pPce->NumSideChannelElements; el += 1) { + if (pPce->SideElementHeightInfo[el] == h) { + elIdx += 1; + chIdx += (pPce->SideElementIsCpe[el]) ? 2 : 1; + } } - } - /* Count back channels/elements */ - for (el = 0; el < pPce->NumBackChannelElements; el+=1) { - if (pPce->BackElementHeightInfo[el] == h) { - elIdx += 1; - chIdx += (pPce->BackElementIsCpe[el]) ? 2 : 1; + /* Count back channels/elements */ + for (el = 0; el < pPce->NumBackChannelElements; el += 1) { + if (pPce->BackElementHeightInfo[el] == h) { + elIdx += 1; + chIdx += (pPce->BackElementIsCpe[el]) ? 2 : 1; + } + } + if (h == 0) { /* normal height */ + elIdx += pPce->NumLfeChannelElements; + chIdx += pPce->NumLfeChannelElements; } } - if (h == 0) { /* normal height */ - elIdx += pPce->NumLfeChannelElements; - chIdx += pPce->NumLfeChannelElements; + chMapping[chIdx] = channelIdx; + chType[chIdx] = aChType; + chIndex[chIdx] = bc[heightLayer]; + if (isCpe) { + chMapping[chIdx + 1] = channelIdx + 1; + chType[chIdx + 1] = aChType; + chIndex[chIdx + 1] = bc[heightLayer] + 1; } + *elMapping = elIdx; + return 1; } - chMapping[chIdx] = channelIdx; - chType[chIdx] = aChType; - chIndex[chIdx] = bc[heightLayer]; - if (isCpe) { - chMapping[chIdx+1] = channelIdx+1; - chType[chIdx+1] = aChType; - chIndex[chIdx+1] = bc[heightLayer]+1; + ec[heightLayer] += 1; + if (pPce->BackElementIsCpe[i]) { + cc[heightLayer] += 2; + bc[heightLayer] += 2; + } else { + cc[heightLayer] += 1; + bc[heightLayer] += 1; } - *elMapping = elIdx; - return 1; } - ec[heightLayer] += 1; - if (pPce->BackElementIsCpe[i]) { - cc[heightLayer] += 2; - bc[heightLayer] += 2; - } else { - cc[heightLayer] += 1; - bc[heightLayer] += 1; + break; + + case ID_LFE: { /* Unfortunately we have to go through all normal height + layer elements to get the position of the LFE + channels. Start with counting the front + channels/elements at normal height */ + for (i = 0; i < pPce->NumFrontChannelElements; i += 1) { + int heightLayer = pPce->FrontElementHeightInfo[i]; + ec[heightLayer] += 1; + cc[heightLayer] += (pPce->FrontElementIsCpe[i]) ? 2 : 1; } - } - break; + /* Count side channels/elements at normal height */ + for (i = 0; i < pPce->NumSideChannelElements; i += 1) { + int heightLayer = pPce->SideElementHeightInfo[i]; + ec[heightLayer] += 1; + cc[heightLayer] += (pPce->SideElementIsCpe[i]) ? 2 : 1; + } + /* Count back channels/elements at normal height */ + for (i = 0; i < pPce->NumBackChannelElements; i += 1) { + int heightLayer = pPce->BackElementHeightInfo[i]; + ec[heightLayer] += 1; + cc[heightLayer] += (pPce->BackElementIsCpe[i]) ? 2 : 1; + } + + /* search in lfe channels */ + for (i = 0; i < pPce->NumLfeChannelElements; i++) { + int elIdx = + ec[0]; /* LFE channels belong to the normal height layer */ + int chIdx = cc[0]; + if (pPce->LfeElementTagSelect[i] == tag) { + chMapping[chIdx] = channelIdx; + *elMapping = elIdx; + chType[chIdx] = ACT_LFE; + chIndex[chIdx] = lc; + return 1; + } + ec[0] += 1; + cc[0] += 1; + lc += 1; + } + } break; + + /* Non audio elements */ + case ID_CCE: + /* search in cce channels */ + for (i = 0; i < pPce->NumValidCcElements; i++) { + if (pPce->ValidCcElementTagSelect[i] == tag) { + return 1; + } + } + break; + case ID_DSE: + /* search associated data elements */ + for (i = 0; i < pPce->NumAssocDataElements; i++) { + if (pPce->AssocDataElementTagSelect[i] == tag) { + return 1; + } + } + break; + default: + return 0; + } + return 0; /* not found in any list */ + } + } - case ID_LFE: - { /* Unfortunately we have to go through all normal height - layer elements to get the position of the LFE channels. - Start with counting the front channels/elements at normal height */ - for (i = 0; i < pPce->NumFrontChannelElements; i+=1) { - int heightLayer = pPce->FrontElementHeightInfo[i]; - ec[heightLayer] += 1; - cc[heightLayer] += (pPce->FrontElementIsCpe[i]) ? 2 : 1; + return 1; +} + +#define SPEAKER_PLANE_NORMAL 0 +#define SPEAKER_PLANE_TOP 1 +#define SPEAKER_PLANE_BOTTOM 2 + +void CProgramConfig_GetChannelDescription(const UINT chConfig, + const CProgramConfig *pPce, + AUDIO_CHANNEL_TYPE chType[], + UCHAR chIndex[]) { + FDK_ASSERT(chType != NULL); + FDK_ASSERT(chIndex != NULL); + + if ((chConfig == 0) && (pPce != NULL)) { + if (pPce->isValid) { + int spkPlane, chIdx = 0; + for (spkPlane = SPEAKER_PLANE_NORMAL; spkPlane <= SPEAKER_PLANE_BOTTOM; + spkPlane += 1) { + int elIdx, grpChIdx = 0; + for (elIdx = 0; elIdx < pPce->NumFrontChannelElements; elIdx += 1) { + if (pPce->FrontElementHeightInfo[elIdx] == spkPlane) { + chType[chIdx] = (AUDIO_CHANNEL_TYPE)((spkPlane << 4) | ACT_FRONT); + chIndex[chIdx++] = grpChIdx++; + if (pPce->FrontElementIsCpe[elIdx]) { + chType[chIdx] = (AUDIO_CHANNEL_TYPE)((spkPlane << 4) | ACT_FRONT); + chIndex[chIdx++] = grpChIdx++; + } + } } - /* Count side channels/elements at normal height */ - for (i = 0; i < pPce->NumSideChannelElements; i+=1) { - int heightLayer = pPce->SideElementHeightInfo[i]; - ec[heightLayer] += 1; - cc[heightLayer] += (pPce->SideElementIsCpe[i]) ? 2 : 1; + grpChIdx = 0; + for (elIdx = 0; elIdx < pPce->NumSideChannelElements; elIdx += 1) { + if (pPce->SideElementHeightInfo[elIdx] == spkPlane) { + chType[chIdx] = (AUDIO_CHANNEL_TYPE)((spkPlane << 4) | ACT_SIDE); + chIndex[chIdx++] = grpChIdx++; + if (pPce->SideElementIsCpe[elIdx]) { + chType[chIdx] = (AUDIO_CHANNEL_TYPE)((spkPlane << 4) | ACT_SIDE); + chIndex[chIdx++] = grpChIdx++; + } + } } - /* Count back channels/elements at normal height */ - for (i = 0; i < pPce->NumBackChannelElements; i+=1) { - int heightLayer = pPce->BackElementHeightInfo[i]; - ec[heightLayer] += 1; - cc[heightLayer] += (pPce->BackElementIsCpe[i]) ? 2 : 1; + grpChIdx = 0; + for (elIdx = 0; elIdx < pPce->NumBackChannelElements; elIdx += 1) { + if (pPce->BackElementHeightInfo[elIdx] == spkPlane) { + chType[chIdx] = (AUDIO_CHANNEL_TYPE)((spkPlane << 4) | ACT_BACK); + chIndex[chIdx++] = grpChIdx++; + if (pPce->BackElementIsCpe[elIdx]) { + chType[chIdx] = (AUDIO_CHANNEL_TYPE)((spkPlane << 4) | ACT_BACK); + chIndex[chIdx++] = grpChIdx++; + } + } } - - /* search in lfe channels */ - for (i = 0; i < pPce->NumLfeChannelElements; i++) { - int elIdx = ec[0]; /* LFE channels belong to the normal height layer */ - int chIdx = cc[0]; - if ( pPce->LfeElementTagSelect[i] == tag ) { - chMapping[chIdx] = channelIdx; - *elMapping = elIdx; + grpChIdx = 0; + if (spkPlane == SPEAKER_PLANE_NORMAL) { + for (elIdx = 0; elIdx < pPce->NumLfeChannelElements; elIdx += 1) { chType[chIdx] = ACT_LFE; - chIndex[chIdx] = lc; - return 1; + chIndex[chIdx++] = grpChIdx++; } - ec[0] += 1; - cc[0] += 1; - lc += 1; } - } break; + } + } + } else { + int chIdx; + for (chIdx = 0; chIdx < getNumberOfTotalChannels(chConfig); chIdx += 1) { + getImplicitAudioChannelTypeAndIndex(&chType[chIdx], &chIndex[chIdx], + chConfig, chIdx); + } + } +} - /* Non audio elements */ - case ID_CCE: - /* search in cce channels */ - for (i = 0; i < pPce->NumValidCcElements; i++) { - if (pPce->ValidCcElementTagSelect[i] == tag) { - return 1; - } - } - break; - case ID_DSE: - /* search associated data elements */ - for (i = 0; i < pPce->NumAssocDataElements; i++) { - if (pPce->AssocDataElementTagSelect[i] == tag) { - return 1; - } +int CProgramConfig_GetPceChMap(const CProgramConfig *pPce, UCHAR pceChMap[], + const UINT pceChMapLen) { + const UCHAR *nElements = &pPce->NumFrontChannelElements; + const UCHAR *elHeight[3], *elIsCpe[3]; + unsigned chIdx, plane, grp, offset, totCh[3], numCh[3][4]; + + FDK_ASSERT(pPce != NULL); + FDK_ASSERT(pceChMap != NULL); + + /* Init counter: */ + FDKmemclear(totCh, 3 * sizeof(unsigned)); + FDKmemclear(numCh, 3 * 4 * sizeof(unsigned)); + + /* Analyse PCE: */ + elHeight[0] = pPce->FrontElementHeightInfo; + elIsCpe[0] = pPce->FrontElementIsCpe; + elHeight[1] = pPce->SideElementHeightInfo; + elIsCpe[1] = pPce->SideElementIsCpe; + elHeight[2] = pPce->BackElementHeightInfo; + elIsCpe[2] = pPce->BackElementIsCpe; + + for (plane = 0; plane <= SPEAKER_PLANE_BOTTOM; plane += 1) { + for (grp = 0; grp < 3; grp += 1) { /* front, side, back */ + unsigned el; + for (el = 0; el < nElements[grp]; el += 1) { + if (elHeight[grp][el] == plane) { + unsigned elCh = elIsCpe[grp][el] ? 2 : 1; + numCh[plane][grp] += elCh; + totCh[plane] += elCh; } - break; - default: - return 0; } - return 0; /* not found in any list */ } -#endif /* TP_PCE_ENABLE */ + if (plane == SPEAKER_PLANE_NORMAL) { + unsigned elCh = pPce->NumLfeChannelElements; + numCh[plane][grp] += elCh; + totCh[plane] += elCh; + } + } + /* Sanity checks: */ + chIdx = totCh[SPEAKER_PLANE_NORMAL] + totCh[SPEAKER_PLANE_TOP] + + totCh[SPEAKER_PLANE_BOTTOM]; + if (chIdx > pceChMapLen) { + return -1; } - return 1; + /* Create map: */ + offset = grp = 0; + unsigned grpThresh = numCh[SPEAKER_PLANE_NORMAL][grp]; + for (chIdx = 0; chIdx < totCh[SPEAKER_PLANE_NORMAL]; chIdx += 1) { + while ((chIdx >= grpThresh) && (grp < 3)) { + offset += numCh[1][grp] + numCh[2][grp]; + grp += 1; + grpThresh += numCh[SPEAKER_PLANE_NORMAL][grp]; + } + pceChMap[chIdx] = chIdx + offset; + } + offset = 0; + for (grp = 0; grp < 4; grp += 1) { /* front, side, back and lfe */ + offset += numCh[SPEAKER_PLANE_NORMAL][grp]; + for (plane = SPEAKER_PLANE_TOP; plane <= SPEAKER_PLANE_BOTTOM; plane += 1) { + unsigned mapCh; + for (mapCh = 0; mapCh < numCh[plane][grp]; mapCh += 1) { + pceChMap[chIdx++] = offset; + offset += 1; + } + } + } + return 0; } -#ifdef TP_PCE_ENABLE -int CProgramConfig_GetElementTable( - const CProgramConfig *pPce, - MP4_ELEMENT_ID elList[], - const INT elListSize, - UCHAR *pChMapIdx - ) -{ +int CProgramConfig_GetElementTable(const CProgramConfig *pPce, + MP4_ELEMENT_ID elList[], + const INT elListSize, UCHAR *pChMapIdx) { int i, el = 0; FDK_ASSERT(elList != NULL); FDK_ASSERT(pChMapIdx != NULL); + FDK_ASSERT(pPce != NULL); *pChMapIdx = 0; - if ( elListSize - < pPce->NumFrontChannelElements + pPce->NumSideChannelElements + pPce->NumBackChannelElements + pPce->NumLfeChannelElements - ) - { + if ((elListSize < + pPce->NumFrontChannelElements + pPce->NumSideChannelElements + + pPce->NumBackChannelElements + pPce->NumLfeChannelElements) || + (pPce->NumChannels == 0)) { return 0; } - for (i=0; i < pPce->NumFrontChannelElements; i++) - { - elList[el++] = (pPce->FrontElementIsCpe[i]) ? ID_CPE : ID_SCE; + for (i = 0; i < pPce->NumFrontChannelElements; i += 1) { + elList[el++] = (pPce->FrontElementIsCpe[i]) ? ID_CPE : ID_SCE; } - for (i=0; i < pPce->NumSideChannelElements; i++) - { - elList[el++] = (pPce->SideElementIsCpe[i]) ? ID_CPE : ID_SCE; + for (i = 0; i < pPce->NumSideChannelElements; i += 1) { + elList[el++] = (pPce->SideElementIsCpe[i]) ? ID_CPE : ID_SCE; } - for (i=0; i < pPce->NumBackChannelElements; i++) - { - elList[el++] = (pPce->BackElementIsCpe[i]) ? ID_CPE : ID_SCE; + for (i = 0; i < pPce->NumBackChannelElements; i += 1) { + elList[el++] = (pPce->BackElementIsCpe[i]) ? ID_CPE : ID_SCE; } - for (i=0; i < pPce->NumLfeChannelElements; i++) - { + for (i = 0; i < pPce->NumLfeChannelElements; i += 1) { elList[el++] = ID_LFE; } - /* Find an corresponding channel configuration if possible */ switch (pPce->NumChannels) { - case 1: case 2: case 3: case 4: case 5: case 6: - /* One and two channels have no alternatives. The other ones are mapped directly to the - corresponding channel config. Because of legacy reasons or for lack of alternative mappings. */ - *pChMapIdx = pPce->NumChannels; - break; - case 7: - { + case 1: + case 2: + /* One and two channels have no alternatives. */ + *pChMapIdx = pPce->NumChannels; + break; + case 3: + case 4: + case 5: + case 6: { /* Test if the number of channels can be used as channel config: + */ + C_ALLOC_SCRATCH_START(tmpPce, CProgramConfig, 1); + /* Create a PCE for the config to test ... */ + CProgramConfig_GetDefault(tmpPce, pPce->NumChannels); + /* ... and compare it with the given one. */ + *pChMapIdx = (!(CProgramConfig_Compare(pPce, tmpPce) & 0xE)) + ? pPce->NumChannels + : 0; + /* If compare result is 0 or 1 we can be sure that it is channel + * config 11. */ + C_ALLOC_SCRATCH_END(tmpPce, CProgramConfig, 1); + } break; + case 7: { C_ALLOC_SCRATCH_START(tmpPce, CProgramConfig, 1); /* Create a PCE for the config to test ... */ CProgramConfig_GetDefault(tmpPce, 11); /* ... and compare it with the given one. */ - *pChMapIdx = (!(CProgramConfig_Compare(pPce, tmpPce)&0xE)) ? 11 : 0; - /* If compare result is 0 or 1 we can be sure that it is channel config 11. */ + *pChMapIdx = (!(CProgramConfig_Compare(pPce, tmpPce) & 0xE)) ? 11 : 0; + /* If compare result is 0 or 1 we can be sure that it is channel + * config 11. */ C_ALLOC_SCRATCH_END(tmpPce, CProgramConfig, 1); - } - break; - case 8: - { /* Try the four possible 7.1ch configurations. One after the other. */ - UCHAR testCfg[4] = { 32, 14, 12, 7}; + } break; + case 8: { /* Try the four possible 7.1ch configurations. One after the + other. */ + UCHAR testCfg[4] = {32, 14, 12, 7}; C_ALLOC_SCRATCH_START(tmpPce, CProgramConfig, 1); - for (i=0; i<4; i+=1) { + for (i = 0; i < 4; i += 1) { /* Create a PCE for the config to test ... */ CProgramConfig_GetDefault(tmpPce, testCfg[i]); /* ... and compare it with the given one. */ - if (!(CProgramConfig_Compare(pPce, tmpPce)&0xE)) { - /* If the compare result is 0 or 1 than the two channel configurations match. */ - /* Explicit mapping of 7.1 side channel configuration to 7.1 rear channel mapping. */ - *pChMapIdx = (testCfg[i]==32) ? 12 : testCfg[i]; + if (!(CProgramConfig_Compare(pPce, tmpPce) & 0xE)) { + /* If the compare result is 0 or 1 than the two channel configurations + * match. */ + /* Explicit mapping of 7.1 side channel configuration to 7.1 rear + * channel mapping. */ + *pChMapIdx = (testCfg[i] == 32) ? 12 : testCfg[i]; } } C_ALLOC_SCRATCH_END(tmpPce, CProgramConfig, 1); - } - break; - default: - /* The PCE does not match any predefined channel configuration. */ - *pChMapIdx = 0; - break; + } break; + default: + /* The PCE does not match any predefined channel configuration. */ + *pChMapIdx = 0; + break; } return el; } -#endif -static AUDIO_OBJECT_TYPE getAOT(HANDLE_FDK_BITSTREAM bs) -{ +static AUDIO_OBJECT_TYPE getAOT(HANDLE_FDK_BITSTREAM bs) { int tmp = 0; - tmp = FDKreadBits(bs,5); + tmp = FDKreadBits(bs, 5); if (tmp == AOT_ESCAPE) { - int tmp2 = FDKreadBits(bs,6); + int tmp2 = FDKreadBits(bs, 6); tmp = 32 + tmp2; } return (AUDIO_OBJECT_TYPE)tmp; } -static INT getSampleRate(HANDLE_FDK_BITSTREAM bs, UCHAR *index, int nBits) -{ +static INT getSampleRate(HANDLE_FDK_BITSTREAM bs, UCHAR *index, int nBits) { INT sampleRate; int idx; idx = FDKreadBits(bs, nBits); - if( idx == (1<<nBits)-1 ) { - if(FDKgetValidBits(bs) < 24) { + if (idx == (1 << nBits) - 1) { + if (FDKgetValidBits(bs) < 24) { return 0; } - sampleRate = FDKreadBits(bs,24); + sampleRate = FDKreadBits(bs, 24); } else { sampleRate = SamplingRateTable[idx]; } @@ -1014,132 +1214,164 @@ static INT getSampleRate(HANDLE_FDK_BITSTREAM bs, UCHAR *index, int nBits) return sampleRate; } -#ifdef TP_GA_ENABLE -static -TRANSPORTDEC_ERROR GaSpecificConfig_Parse( CSGaSpecificConfig *self, - CSAudioSpecificConfig *asc, - HANDLE_FDK_BITSTREAM bs, - UINT ascStartAnchor ) -{ +static TRANSPORTDEC_ERROR GaSpecificConfig_Parse(CSGaSpecificConfig *self, + CSAudioSpecificConfig *asc, + HANDLE_FDK_BITSTREAM bs, + UINT ascStartAnchor) { TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK; - self->m_frameLengthFlag = FDKreadBits(bs,1); + self->m_frameLengthFlag = FDKreadBits(bs, 1); - self->m_dependsOnCoreCoder = FDKreadBits(bs,1); + self->m_dependsOnCoreCoder = FDKreadBits(bs, 1); - if( self->m_dependsOnCoreCoder ) - self->m_coreCoderDelay = FDKreadBits(bs,14); + if (self->m_dependsOnCoreCoder) self->m_coreCoderDelay = FDKreadBits(bs, 14); - self->m_extensionFlag = FDKreadBits(bs,1); + self->m_extensionFlag = FDKreadBits(bs, 1); - if( asc->m_channelConfiguration == 0 ) { + if (asc->m_channelConfiguration == 0) { CProgramConfig_Read(&asc->m_progrConfigElement, bs, ascStartAnchor); } if ((asc->m_aot == AOT_AAC_SCAL) || (asc->m_aot == AOT_ER_AAC_SCAL)) { - self->m_layer = FDKreadBits(bs,3); + self->m_layer = FDKreadBits(bs, 3); } if (self->m_extensionFlag) { if (asc->m_aot == AOT_ER_BSAC) { - self->m_numOfSubFrame = FDKreadBits(bs,5); - self->m_layerLength = FDKreadBits(bs,11); + self->m_numOfSubFrame = FDKreadBits(bs, 5); + self->m_layerLength = FDKreadBits(bs, 11); } - if ((asc->m_aot == AOT_ER_AAC_LC) || (asc->m_aot == AOT_ER_AAC_LTP) || - (asc->m_aot == AOT_ER_AAC_SCAL) || (asc->m_aot == AOT_ER_AAC_LD)) - { - asc->m_vcb11Flag = FDKreadBits(bs,1); /* aacSectionDataResilienceFlag */ - asc->m_rvlcFlag = FDKreadBits(bs,1); /* aacScalefactorDataResilienceFlag */ - asc->m_hcrFlag = FDKreadBits(bs,1); /* aacSpectralDataResilienceFlag */ + if ((asc->m_aot == AOT_ER_AAC_LC) || (asc->m_aot == AOT_ER_AAC_LTP) || + (asc->m_aot == AOT_ER_AAC_SCAL) || (asc->m_aot == AOT_ER_AAC_LD)) { + asc->m_vcb11Flag = FDKreadBits(bs, 1); /* aacSectionDataResilienceFlag */ + asc->m_rvlcFlag = + FDKreadBits(bs, 1); /* aacScalefactorDataResilienceFlag */ + asc->m_hcrFlag = FDKreadBits(bs, 1); /* aacSpectralDataResilienceFlag */ } - self->m_extensionFlag3 = FDKreadBits(bs,1); - + self->m_extensionFlag3 = FDKreadBits(bs, 1); } return (ErrorStatus); } -#endif /* TP_GA_ENABLE */ - - +static INT skipSbrHeader(HANDLE_FDK_BITSTREAM hBs, int isUsac) { + /* Dummy parse SbrDfltHeader() */ + INT dflt_header_extra1, dflt_header_extra2, bitsToSkip = 0; + if (!isUsac) { + bitsToSkip = 6; + FDKpushFor(hBs, 6); /* amp res 1, xover freq 3, reserved 2 */ + } + bitsToSkip += 8; + FDKpushFor(hBs, 8); /* start / stop freq */ + bitsToSkip += 2; + dflt_header_extra1 = FDKreadBit(hBs); + dflt_header_extra2 = FDKreadBit(hBs); + bitsToSkip += 5 * dflt_header_extra1 + 6 * dflt_header_extra2; + FDKpushFor(hBs, 5 * dflt_header_extra1 + 6 * dflt_header_extra2); + + return bitsToSkip; +} -#ifdef TP_ELD_ENABLE - -static INT ld_sbr_header( const CSAudioSpecificConfig *asc, - HANDLE_FDK_BITSTREAM hBs, - CSTpCallBacks *cb ) -{ +static INT ld_sbr_header(CSAudioSpecificConfig *asc, const INT dsFactor, + HANDLE_FDK_BITSTREAM hBs, CSTpCallBacks *cb) { const int channelConfiguration = asc->m_channelConfiguration; - int i = 0; + int i = 0, j = 0; INT error = 0; - - if (channelConfiguration == 2) { - error = cb->cbSbr(cb->cbSbrData, hBs, asc->m_samplingFrequency, asc->m_extensionSamplingFrequency, asc->m_samplesPerFrame, AOT_ER_AAC_ELD, ID_CPE, i++); - } else { - error = cb->cbSbr(cb->cbSbrData, hBs, asc->m_samplingFrequency, asc->m_extensionSamplingFrequency, asc->m_samplesPerFrame, AOT_ER_AAC_ELD, ID_SCE, i++); + MP4_ELEMENT_ID element = ID_NONE; + + /* check whether the channelConfiguration is defined in + * channel_configuration_array */ + if (channelConfiguration < 0 || + channelConfiguration > (INT)(sizeof(channel_configuration_array) / + sizeof(MP4_ELEMENT_ID **) - + 1)) { + return TRANSPORTDEC_PARSE_ERROR; } - switch ( channelConfiguration ) { - case 14: - case 12: - case 7: - error |= cb->cbSbr(cb->cbSbrData, hBs, asc->m_samplingFrequency, asc->m_extensionSamplingFrequency, asc->m_samplesPerFrame, AOT_ER_AAC_ELD, ID_CPE, i++); - case 6: - case 5: - error |= cb->cbSbr(cb->cbSbrData, hBs, asc->m_samplingFrequency, asc->m_extensionSamplingFrequency, asc->m_samplesPerFrame, AOT_ER_AAC_ELD, ID_CPE, i++); - case 3: - error |= cb->cbSbr(cb->cbSbrData, hBs, asc->m_samplingFrequency, asc->m_extensionSamplingFrequency, asc->m_samplesPerFrame, AOT_ER_AAC_ELD, ID_CPE, i++); - break; - - case 11: - error |= cb->cbSbr(cb->cbSbrData, hBs, asc->m_samplingFrequency, asc->m_extensionSamplingFrequency, asc->m_samplesPerFrame, AOT_ER_AAC_ELD, ID_CPE, i++); - case 4: - error |= cb->cbSbr(cb->cbSbrData, hBs, asc->m_samplingFrequency, asc->m_extensionSamplingFrequency, asc->m_samplesPerFrame, AOT_ER_AAC_ELD, ID_CPE, i++); - error |= cb->cbSbr(cb->cbSbrData, hBs, asc->m_samplingFrequency, asc->m_extensionSamplingFrequency, asc->m_samplesPerFrame, AOT_ER_AAC_ELD, ID_SCE, i++); - break; + /* read elements of the passed channel_configuration until there is ID_NONE */ + while ((element = channel_configuration_array[channelConfiguration][j]) != + ID_NONE) { + if (element == ID_SCE || element == ID_CPE) { + error |= cb->cbSbr( + cb->cbSbrData, hBs, asc->m_samplingFrequency / dsFactor, + asc->m_extensionSamplingFrequency / dsFactor, + asc->m_samplesPerFrame / dsFactor, AOT_ER_AAC_ELD, element, i++, 0, 0, + asc->configMode, &asc->SbrConfigChanged, dsFactor); + if (error != TRANSPORTDEC_OK) { + goto bail; + } + } + j++; } - +bail: return error; } -static -TRANSPORTDEC_ERROR EldSpecificConfig_Parse( - CSAudioSpecificConfig *asc, - HANDLE_FDK_BITSTREAM hBs, - CSTpCallBacks *cb - ) -{ +static TRANSPORTDEC_ERROR EldSpecificConfig_Parse(CSAudioSpecificConfig *asc, + HANDLE_FDK_BITSTREAM hBs, + CSTpCallBacks *cb) { TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK; CSEldSpecificConfig *esc = &asc->m_sc.m_eldSpecificConfig; ASC_ELD_EXT_TYPE eldExtType; - int eldExtLen, len, cnt; + int eldExtLen, len, cnt, ldSbrLen = 0, eldExtLenSum, numSbrHeader = 0, + sbrIndex; + + unsigned char downscale_fill_nibble; FDKmemclear(esc, sizeof(CSEldSpecificConfig)); - esc->m_frameLengthFlag = FDKreadBits(hBs, 1 ); + esc->m_frameLengthFlag = FDKreadBits(hBs, 1); if (esc->m_frameLengthFlag) { asc->m_samplesPerFrame = 480; } else { asc->m_samplesPerFrame = 512; } - asc->m_vcb11Flag = FDKreadBits(hBs, 1 ); - asc->m_rvlcFlag = FDKreadBits(hBs, 1 ); - asc->m_hcrFlag = FDKreadBits(hBs, 1 ); + asc->m_vcb11Flag = FDKreadBits(hBs, 1); + asc->m_rvlcFlag = FDKreadBits(hBs, 1); + asc->m_hcrFlag = FDKreadBits(hBs, 1); - esc->m_sbrPresentFlag = FDKreadBits(hBs, 1 ); + esc->m_sbrPresentFlag = FDKreadBits(hBs, 1); if (esc->m_sbrPresentFlag == 1) { - esc->m_sbrSamplingRate = FDKreadBits(hBs, 1 ); /* 0: single rate, 1: dual rate */ - esc->m_sbrCrcFlag = FDKreadBits(hBs, 1 ); - - asc->m_extensionSamplingFrequency = asc->m_samplingFrequency << esc->m_sbrSamplingRate; - - if (cb->cbSbr != NULL){ - if ( 0 != ld_sbr_header(asc, hBs, cb) ) { - return TRANSPORTDEC_PARSE_ERROR; + esc->m_sbrSamplingRate = + FDKreadBits(hBs, 1); /* 0: single rate, 1: dual rate */ + esc->m_sbrCrcFlag = FDKreadBits(hBs, 1); + + asc->m_extensionSamplingFrequency = asc->m_samplingFrequency + << esc->m_sbrSamplingRate; + + if (cb->cbSbr != NULL) { + /* ELD reduced delay mode: LD-SBR initialization has to know the downscale + information. Postpone LD-SBR initialization and read ELD extension + information first. */ + switch (asc->m_channelConfiguration) { + case 1: + case 2: + numSbrHeader = 1; + break; + case 3: + numSbrHeader = 2; + break; + case 4: + case 5: + case 6: + numSbrHeader = 3; + break; + case 7: + case 11: + case 12: + case 14: + numSbrHeader = 4; + break; + default: + numSbrHeader = 0; + break; + } + for (sbrIndex = 0; sbrIndex < numSbrHeader; sbrIndex++) { + ldSbrLen += skipSbrHeader(hBs, 0); } } else { return TRANSPORTDEC_UNSUPPORTED_FORMAT; @@ -1148,85 +1380,686 @@ TRANSPORTDEC_ERROR EldSpecificConfig_Parse( esc->m_useLdQmfTimeAlign = 0; /* new ELD syntax */ + eldExtLenSum = FDKgetValidBits(hBs); + esc->m_downscaledSamplingFrequency = asc->m_samplingFrequency; /* parse ExtTypeConfigData */ - while ((eldExtType = (ASC_ELD_EXT_TYPE)FDKreadBits(hBs, 4 )) != ELDEXT_TERM) { - eldExtLen = len = FDKreadBits(hBs, 4 ); - if ( len == 0xf ) { - len = FDKreadBits(hBs, 8 ); + while ( + ((eldExtType = (ASC_ELD_EXT_TYPE)FDKreadBits(hBs, 4)) != ELDEXT_TERM) && + ((INT)FDKgetValidBits(hBs) >= 0)) { + eldExtLen = len = FDKreadBits(hBs, 4); + if (len == 0xf) { + len = FDKreadBits(hBs, 8); eldExtLen += len; - if ( len == 0xff ) { - len = FDKreadBits(hBs, 16 ); + if (len == 0xff) { + len = FDKreadBits(hBs, 16); eldExtLen += len; } } switch (eldExtType) { + case ELDEXT_LDSAC: + esc->m_useLdQmfTimeAlign = 1; + if (cb->cbSsc != NULL) { + ErrorStatus = (TRANSPORTDEC_ERROR)cb->cbSsc( + cb->cbSscData, hBs, asc->m_aot, asc->m_extensionSamplingFrequency, + 1, /* stereoConfigIndex */ + -1, /* nTimeSlots: read from bitstream */ + eldExtLen, asc->configMode, &asc->SacConfigChanged); + if (ErrorStatus != TRANSPORTDEC_OK) { + return TRANSPORTDEC_PARSE_ERROR; + } + break; + } + + /* fall-through */ default: - for(cnt=0; cnt<eldExtLen; cnt++) { - FDKreadBits(hBs, 8 ); + for (cnt = 0; cnt < eldExtLen; cnt++) { + FDKreadBits(hBs, 8); + } + break; + + case ELDEXT_DOWNSCALEINFO: + UCHAR tmpDownscaleFreqIdx; + esc->m_downscaledSamplingFrequency = + getSampleRate(hBs, &tmpDownscaleFreqIdx, 4); + if (esc->m_downscaledSamplingFrequency == 0) { + return TRANSPORTDEC_PARSE_ERROR; + } + downscale_fill_nibble = FDKreadBits(hBs, 4); + if (downscale_fill_nibble != 0x0) { + return TRANSPORTDEC_PARSE_ERROR; } break; - /* add future eld extension configs here */ } } -bail: + + if ((INT)FDKgetValidBits(hBs) < 0) { + return TRANSPORTDEC_PARSE_ERROR; + } + + if (esc->m_sbrPresentFlag == 1 && numSbrHeader != 0) { + INT dsFactor = 1; /* Downscale factor must be 1 or even for SBR */ + if (esc->m_downscaledSamplingFrequency != 0) { + if (asc->m_samplingFrequency % esc->m_downscaledSamplingFrequency != 0) { + return TRANSPORTDEC_UNSUPPORTED_FORMAT; + } + dsFactor = asc->m_samplingFrequency / esc->m_downscaledSamplingFrequency; + if (dsFactor != 1 && (dsFactor)&1) { + return TRANSPORTDEC_UNSUPPORTED_FORMAT; /* SBR needs an even downscale + factor */ + } + if (dsFactor != 1 && dsFactor != 2 && dsFactor != 4) { + dsFactor = 1; /* don't apply dsf for not yet supported even dsfs */ + } + if ((INT)asc->m_samplesPerFrame % dsFactor != 0) { + return TRANSPORTDEC_UNSUPPORTED_FORMAT; /* frameSize/dsf must be an + integer number */ + } + } + eldExtLenSum = eldExtLenSum - FDKgetValidBits(hBs); + FDKpushBack(hBs, eldExtLenSum + ldSbrLen); + if (0 != ld_sbr_header(asc, dsFactor, hBs, cb)) { + return TRANSPORTDEC_PARSE_ERROR; + } + FDKpushFor(hBs, eldExtLenSum); + } return (ErrorStatus); } -#endif /* TP_ELD_ENABLE */ +/* +Subroutine to store config in UCHAR buffer. Bit stream position does not change. +*/ +static UINT StoreConfigAsBitstream( + HANDLE_FDK_BITSTREAM hBs, const INT configSize_bits, /* If < 0 (> 0) config + to read is before + (after) current bit + stream position. */ + UCHAR *configTargetBuffer, const USHORT configTargetBufferSize_bytes) { + FDK_BITSTREAM usacConf; + UINT const nBits = fAbs(configSize_bits); + UINT j, tmp; + + if (nBits > 8 * (UINT)configTargetBufferSize_bytes) { + return 1; + } + FDKmemclear(configTargetBuffer, configTargetBufferSize_bytes); + + FDKinitBitStream(&usacConf, configTargetBuffer, configTargetBufferSize_bytes, + nBits, BS_WRITER); + if (configSize_bits < 0) { + FDKpushBack(hBs, nBits); + } + for (j = nBits; j > 31; j -= 32) { + tmp = FDKreadBits(hBs, 32); + FDKwriteBits(&usacConf, tmp, 32); + } + if (j > 0) { + tmp = FDKreadBits(hBs, j); + FDKwriteBits(&usacConf, tmp, j); + } + FDKsyncCache(&usacConf); + if (configSize_bits > 0) { + FDKpushBack(hBs, nBits); + } + + return 0; +} + +/* maps coreSbrFrameLengthIndex to coreCoderFrameLength */ +static const USHORT usacFrameLength[8] = {768, 1024, 2048, 2048, 4096, 0, 0, 0}; +/* maps coreSbrFrameLengthIndex to sbrRatioIndex */ +static const UCHAR sbrRatioIndex[8] = {0, 0, 2, 3, 1, 0, 0, 0}; + +/* + subroutine for parsing extension element configuration: + UsacExtElementConfig() q.v. ISO/IEC FDIS 23003-3:2011(E) Table 14 + rsv603daExtElementConfig() q.v. ISO/IEC DIS 23008-3 Table 13 +*/ +static TRANSPORTDEC_ERROR extElementConfig(CSUsacExtElementConfig *extElement, + HANDLE_FDK_BITSTREAM hBs, + const CSTpCallBacks *cb, + const UCHAR numSignalsInGroup, + const UINT coreFrameLength, + const int subStreamIndex, + const AUDIO_OBJECT_TYPE aot) { + TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK; + + USAC_EXT_ELEMENT_TYPE usacExtElementType = + (USAC_EXT_ELEMENT_TYPE)escapedValue(hBs, 4, 8, 16); + + /* recurve extension elements which are invalid for USAC */ + if (aot == AOT_USAC) { + switch (usacExtElementType) { + case ID_EXT_ELE_FILL: + case ID_EXT_ELE_MPEGS: + case ID_EXT_ELE_SAOC: + case ID_EXT_ELE_AUDIOPREROLL: + case ID_EXT_ELE_UNI_DRC: + break; + default: + usacExtElementType = ID_EXT_ELE_UNKNOWN; + break; + } + } + + extElement->usacExtElementType = usacExtElementType; + int usacExtElementConfigLength = escapedValue(hBs, 4, 8, 16); + extElement->usacExtElementConfigLength = (USHORT)usacExtElementConfigLength; + INT bsAnchor; -static -TRANSPORTDEC_ERROR AudioSpecificConfig_ExtensionParse(CSAudioSpecificConfig *self, HANDLE_FDK_BITSTREAM bs, CSTpCallBacks *cb) -{ - TP_ASC_EXTENSION_ID lastAscExt, ascExtId = ASCEXT_UNKOWN; - INT bitsAvailable = (INT)FDKgetValidBits(bs); + if (FDKreadBit(hBs)) /* usacExtElementDefaultLengthPresent */ + extElement->usacExtElementDefaultLength = escapedValue(hBs, 8, 16, 0) + 1; + else + extElement->usacExtElementDefaultLength = 0; + + extElement->usacExtElementPayloadFrag = FDKreadBit(hBs); - while (bitsAvailable >= 11) + bsAnchor = (INT)FDKgetValidBits(hBs); + + switch (usacExtElementType) { + case ID_EXT_ELE_UNKNOWN: + case ID_EXT_ELE_FILL: + break; + case ID_EXT_ELE_AUDIOPREROLL: + /* No configuration element */ + extElement->usacExtElementHasAudioPreRoll = 1; + break; + case ID_EXT_ELE_UNI_DRC: { + if (cb->cbUniDrc != NULL) { + ErrorStatus = (TRANSPORTDEC_ERROR)cb->cbUniDrc( + cb->cbUniDrcData, hBs, usacExtElementConfigLength, + 0, /* uniDrcConfig */ + subStreamIndex, 0, aot); + if (ErrorStatus != TRANSPORTDEC_OK) { + return ErrorStatus; + } + } + } break; + default: + break; + } + + /* Adjust bit stream position. This is required because of byte alignment and + * unhandled extensions. */ { - lastAscExt = ascExtId; - ascExtId = (TP_ASC_EXTENSION_ID)FDKreadBits(bs, 11); - bitsAvailable -= 11; + INT left_bits = (usacExtElementConfigLength << 3) - + (bsAnchor - (INT)FDKgetValidBits(hBs)); + if (left_bits >= 0) { + FDKpushFor(hBs, left_bits); + } else { + /* parsed too many bits */ + ErrorStatus = TRANSPORTDEC_PARSE_ERROR; + } + } - switch (ascExtId) { - case ASCEXT_SBR: /* 0x2b7 */ - if ( (self->m_extensionAudioObjectType != AOT_SBR) && (bitsAvailable >= 5) ) { - self->m_extensionAudioObjectType = getAOT(bs); - - if ( (self->m_extensionAudioObjectType == AOT_SBR) - || (self->m_extensionAudioObjectType == AOT_ER_BSAC) ) - { /* Get SBR extension configuration */ - self->m_sbrPresentFlag = FDKreadBits(bs, 1); - bitsAvailable -= 1; + return ErrorStatus; +} + +/* + subroutine for parsing the USAC / RSVD60 configuration extension: + UsacConfigExtension() q.v. ISO/IEC FDIS 23003-3:2011(E) Table 15 + rsv603daConfigExtension() q.v. ISO/IEC DIS 23008-3 Table 14 +*/ +static TRANSPORTDEC_ERROR configExtension(CSUsacConfig *usc, + HANDLE_FDK_BITSTREAM hBs, + const CSTpCallBacks *cb) { + TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK; + + int numConfigExtensions; + CONFIG_EXT_ID usacConfigExtType; + int usacConfigExtLength; + + numConfigExtensions = (int)escapedValue(hBs, 2, 4, 8) + 1; + for (int confExtIdx = 0; confExtIdx < numConfigExtensions; confExtIdx++) { + INT nbits; + int loudnessInfoSetConfigExtensionPosition = FDKgetValidBits(hBs); + usacConfigExtType = (CONFIG_EXT_ID)escapedValue(hBs, 4, 8, 16); + usacConfigExtLength = (int)escapedValue(hBs, 4, 8, 16); + + /* Start bit position of config extension */ + nbits = FDKgetValidBits(hBs); + + /* Return an error in case the bitbuffer fill level is too low. */ + if (nbits < usacConfigExtLength * 8) { + return TRANSPORTDEC_PARSE_ERROR; + } + + switch (usacConfigExtType) { + case ID_CONFIG_EXT_FILL: + for (int i = 0; i < usacConfigExtLength; i++) { + if (FDKreadBits(hBs, 8) != 0xa5) { + return TRANSPORTDEC_PARSE_ERROR; + } + } + break; + case ID_CONFIG_EXT_LOUDNESS_INFO: { + if (cb->cbUniDrc != NULL) { + ErrorStatus = (TRANSPORTDEC_ERROR)cb->cbUniDrc( + cb->cbUniDrcData, hBs, usacConfigExtLength, + 1, /* loudnessInfoSet */ + 0, loudnessInfoSetConfigExtensionPosition, AOT_USAC); + if (ErrorStatus != TRANSPORTDEC_OK) { + return ErrorStatus; + } + } + } break; + default: + break; + } + + /* Skip remaining bits. If too many bits were parsed, assume error. */ + usacConfigExtLength = + 8 * usacConfigExtLength - (nbits - FDKgetValidBits(hBs)); + if (usacConfigExtLength < 0) { + return TRANSPORTDEC_PARSE_ERROR; + } + FDKpushFor(hBs, usacConfigExtLength); + } + + return ErrorStatus; +} + +/* This function unifies decoder config parsing of USAC and RSV60: + rsv603daDecoderConfig() ISO/IEC DIS 23008-3 Table 8 + UsacDecoderConfig() ISO/IEC FDIS 23003-3 Table 6 + */ +static TRANSPORTDEC_ERROR UsacRsv60DecoderConfig_Parse( + CSAudioSpecificConfig *asc, HANDLE_FDK_BITSTREAM hBs, + const CSTpCallBacks *cb) { + TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK; + CSUsacConfig *usc = &asc->m_sc.m_usacConfig; + int i, numberOfElements; + int channelElementIdx = + 0; /* index for elements which contain audio channels (sce, cpe, lfe) */ + SC_CHANNEL_CONFIG sc_chan_config = {0, 0, 0, 0}; + + numberOfElements = (int)escapedValue(hBs, 4, 8, 16) + 1; + usc->m_usacNumElements = numberOfElements; + if (numberOfElements > TP_USAC_MAX_ELEMENTS) { + return TRANSPORTDEC_UNSUPPORTED_FORMAT; + } + usc->m_nUsacChannels = 0; + usc->m_channelConfigurationIndex = asc->m_channelConfiguration; + + if (asc->m_aot == AOT_USAC) { + sc_chan_config = sc_chan_config_tab[usc->m_channelConfigurationIndex]; + + if (sc_chan_config.nCh > (SCHAR)TP_USAC_MAX_SPEAKERS) { + return TRANSPORTDEC_PARSE_ERROR; + } + } - if ( self->m_sbrPresentFlag == 1 ) { - self->m_extensionSamplingFrequency = getSampleRate(bs, &self->m_extensionSamplingFrequencyIndex, 4); + for (i = 0; i < numberOfElements; i++) { + MP4_ELEMENT_ID usacElementType = (MP4_ELEMENT_ID)( + FDKreadBits(hBs, 2) | USAC_ID_BIT); /* set USAC_ID_BIT to map + usacElementType to + MP4_ELEMENT_ID enum */ + usc->element[i].usacElementType = usacElementType; + + /* sanity check: update element counter */ + if (asc->m_aot == AOT_USAC) { + switch (usacElementType) { + case ID_USAC_SCE: + sc_chan_config.nSCE--; + break; + case ID_USAC_CPE: + sc_chan_config.nCPE--; + break; + case ID_USAC_LFE: + sc_chan_config.nLFE--; + break; + default: + break; + } + if (usc->m_channelConfigurationIndex) { + /* sanity check: no element counter may be smaller zero */ + if (sc_chan_config.nCPE < 0 || sc_chan_config.nSCE < 0 || + sc_chan_config.nLFE < 0) { + return TRANSPORTDEC_PARSE_ERROR; + } + } + } - if ((INT)self->m_extensionSamplingFrequency <= 0) { + switch (usacElementType) { + case ID_USAC_SCE: + /* UsacCoreConfig() ISO/IEC FDIS 23003-3 Table 10 */ + if (FDKreadBit(hBs)) { /* tw_mdct */ + return TRANSPORTDEC_UNSUPPORTED_FORMAT; + } + usc->element[i].m_noiseFilling = FDKreadBits(hBs, 1); + /* end of UsacCoreConfig() */ + if (usc->m_sbrRatioIndex > 0) { + if (cb->cbSbr == NULL) { + return TRANSPORTDEC_UNKOWN_ERROR; + } + /* SbrConfig() ISO/IEC FDIS 23003-3 Table 11 */ + usc->element[i].m_harmonicSBR = FDKreadBit(hBs); + usc->element[i].m_interTes = FDKreadBit(hBs); + usc->element[i].m_pvc = FDKreadBit(hBs); + if (cb->cbSbr(cb->cbSbrData, hBs, asc->m_samplingFrequency, + asc->m_extensionSamplingFrequency, + asc->m_samplesPerFrame, asc->m_aot, ID_SCE, + channelElementIdx, usc->element[i].m_harmonicSBR, + usc->element[i].m_stereoConfigIndex, asc->configMode, + &asc->SbrConfigChanged, 1)) { + return TRANSPORTDEC_PARSE_ERROR; + } + /* end of SbrConfig() */ + } + usc->m_nUsacChannels += 1; + channelElementIdx++; + break; + + case ID_USAC_CPE: + /* UsacCoreConfig() ISO/IEC FDIS 23003-3 Table 10 */ + if (FDKreadBit(hBs)) { /* tw_mdct */ + return TRANSPORTDEC_UNSUPPORTED_FORMAT; + } + usc->element[i].m_noiseFilling = FDKreadBits(hBs, 1); + /* end of UsacCoreConfig() */ + if (usc->m_sbrRatioIndex > 0) { + if (cb->cbSbr == NULL) return TRANSPORTDEC_UNKOWN_ERROR; + /* SbrConfig() ISO/IEC FDIS 23003-3 */ + usc->element[i].m_harmonicSBR = FDKreadBit(hBs); + usc->element[i].m_interTes = FDKreadBit(hBs); + usc->element[i].m_pvc = FDKreadBit(hBs); + { + INT bitsToSkip = skipSbrHeader(hBs, 1); + /* read stereoConfigIndex */ + usc->element[i].m_stereoConfigIndex = FDKreadBits(hBs, 2); + /* rewind */ + FDKpushBack(hBs, bitsToSkip + 2); + } + { + MP4_ELEMENT_ID el_type = + (usc->element[i].m_stereoConfigIndex == 1 || + usc->element[i].m_stereoConfigIndex == 2) + ? ID_SCE + : ID_CPE; + if (cb->cbSbr(cb->cbSbrData, hBs, asc->m_samplingFrequency, + asc->m_extensionSamplingFrequency, + asc->m_samplesPerFrame, asc->m_aot, el_type, + channelElementIdx, usc->element[i].m_harmonicSBR, + usc->element[i].m_stereoConfigIndex, asc->configMode, + &asc->SbrConfigChanged, 1)) { return TRANSPORTDEC_PARSE_ERROR; } } - if ( self->m_extensionAudioObjectType == AOT_ER_BSAC ) { - self->m_extensionChannelConfiguration = FDKreadBits(bs, 4); - bitsAvailable -= 4; + /* end of SbrConfig() */ + + usc->element[i].m_stereoConfigIndex = + FDKreadBits(hBs, 2); /* Needed in RM5 syntax */ + + if (usc->element[i].m_stereoConfigIndex > 0) { + if (cb->cbSsc != NULL) { + /* Mps212Config() ISO/IEC FDIS 23003-3 */ + if (cb->cbSsc(cb->cbSscData, hBs, asc->m_aot, + asc->m_extensionSamplingFrequency, + usc->element[i].m_stereoConfigIndex, + usc->m_coreSbrFrameLengthIndex, + 0, /* don't know the length */ + asc->configMode, &asc->SacConfigChanged)) { + return TRANSPORTDEC_PARSE_ERROR; + } + /* end of Mps212Config() */ + } else { + return TRANSPORTDEC_UNKOWN_ERROR; + } } + } else { + usc->element[i].m_stereoConfigIndex = 0; } - /* Update counter because of variable length fields (AOT and sampling rate) */ - bitsAvailable = (INT)FDKgetValidBits(bs); + usc->m_nUsacChannels += 2; + + channelElementIdx++; + break; + + case ID_USAC_LFE: + usc->element[i].m_noiseFilling = 0; + usc->m_nUsacChannels += 1; + if (usc->m_sbrRatioIndex > 0) { + /* Use SBR for upsampling */ + if (cb->cbSbr == NULL) return ErrorStatus = TRANSPORTDEC_UNKOWN_ERROR; + usc->element[i].m_harmonicSBR = (UCHAR)0; + usc->element[i].m_interTes = (UCHAR)0; + usc->element[i].m_pvc = (UCHAR)0; + if (cb->cbSbr(cb->cbSbrData, hBs, asc->m_samplingFrequency, + asc->m_extensionSamplingFrequency, + asc->m_samplesPerFrame, asc->m_aot, ID_LFE, + channelElementIdx, usc->element[i].m_harmonicSBR, + usc->element[i].m_stereoConfigIndex, asc->configMode, + &asc->SbrConfigChanged, 1)) { + return ErrorStatus = TRANSPORTDEC_PARSE_ERROR; + } + } + channelElementIdx++; + break; + + case ID_USAC_EXT: + ErrorStatus = extElementConfig(&usc->element[i].extElement, hBs, cb, 0, + asc->m_samplesPerFrame, 0, asc->m_aot); + + if (ErrorStatus) { + return ErrorStatus; + } + break; + + default: + /* non USAC-element encountered */ + return TRANSPORTDEC_PARSE_ERROR; + } + } + + if (asc->m_aot == AOT_USAC) { + if (usc->m_channelConfigurationIndex) { + /* sanity check: all element counter must be zero */ + if (sc_chan_config.nCPE | sc_chan_config.nSCE | sc_chan_config.nLFE) { + return TRANSPORTDEC_PARSE_ERROR; } - break; - case ASCEXT_PS: /* 0x548 */ - if ( (lastAscExt == ASCEXT_SBR) - && (self->m_extensionAudioObjectType == AOT_SBR) - && (bitsAvailable > 0) ) - { /* Get PS extension configuration */ - self->m_psPresentFlag = FDKreadBits(bs, 1); - bitsAvailable -= 1; + } else { + /* sanity check: number of audio channels shall be equal to or smaller + * than the accumulated sum of all channels */ + if ((INT)(-2 * sc_chan_config.nCPE - sc_chan_config.nSCE - + sc_chan_config.nLFE) < (INT)usc->numAudioChannels) { + return TRANSPORTDEC_PARSE_ERROR; } - break; - default: - /* Just ignore anything. */ - return TRANSPORTDEC_OK; + } + } + + return ErrorStatus; +} + +/* Mapping of coreSbrFrameLengthIndex defined by Table 70 in ISO/IEC 23003-3 */ +static TRANSPORTDEC_ERROR UsacConfig_SetCoreSbrFrameLengthIndex( + CSAudioSpecificConfig *asc, int coreSbrFrameLengthIndex) { + int sbrRatioIndex_val; + + if (coreSbrFrameLengthIndex > 4) { + return TRANSPORTDEC_PARSE_ERROR; /* reserved values */ + } + asc->m_sc.m_usacConfig.m_coreSbrFrameLengthIndex = coreSbrFrameLengthIndex; + asc->m_samplesPerFrame = usacFrameLength[coreSbrFrameLengthIndex]; + sbrRatioIndex_val = sbrRatioIndex[coreSbrFrameLengthIndex]; + asc->m_sc.m_usacConfig.m_sbrRatioIndex = sbrRatioIndex_val; + + if (sbrRatioIndex_val > 0) { + asc->m_sbrPresentFlag = 1; + asc->m_extensionSamplingFrequency = asc->m_samplingFrequency; + asc->m_extensionSamplingFrequencyIndex = asc->m_samplingFrequencyIndex; + switch (sbrRatioIndex_val) { + case 1: /* sbrRatio = 4:1 */ + asc->m_samplingFrequency >>= 2; + asc->m_samplesPerFrame >>= 2; + break; + case 2: /* sbrRatio = 8:3 */ + asc->m_samplingFrequency = (asc->m_samplingFrequency * 3) / 8; + asc->m_samplesPerFrame = (asc->m_samplesPerFrame * 3) / 8; + break; + case 3: /* sbrRatio = 2:1 */ + asc->m_samplingFrequency >>= 1; + asc->m_samplesPerFrame >>= 1; + break; + default: + return TRANSPORTDEC_PARSE_ERROR; + } + asc->m_samplingFrequencyIndex = + getSamplingRateIndex(asc->m_samplingFrequency, 4); + } + + return TRANSPORTDEC_OK; +} + +static TRANSPORTDEC_ERROR UsacConfig_Parse(CSAudioSpecificConfig *asc, + HANDLE_FDK_BITSTREAM hBs, + CSTpCallBacks *cb) { + int usacSamplingFrequency, channelConfigurationIndex, coreSbrFrameLengthIndex; + TRANSPORTDEC_ERROR err = TRANSPORTDEC_OK; + + /* Start bit position of usacConfig */ + INT nbits = (INT)FDKgetValidBits(hBs); + + usacSamplingFrequency = getSampleRate(hBs, &asc->m_samplingFrequencyIndex, 5); + asc->m_samplingFrequency = (UINT)usacSamplingFrequency; + + coreSbrFrameLengthIndex = FDKreadBits(hBs, 3); + if (UsacConfig_SetCoreSbrFrameLengthIndex(asc, coreSbrFrameLengthIndex) != + TRANSPORTDEC_OK) { + return TRANSPORTDEC_PARSE_ERROR; + } + + channelConfigurationIndex = FDKreadBits(hBs, 5); + if (channelConfigurationIndex > 2) { + return TRANSPORTDEC_PARSE_ERROR; /* only channelConfigurationIndex = [1,2] + are supported */ + } + + if (channelConfigurationIndex == 0) { + return TRANSPORTDEC_PARSE_ERROR; /* only channelConfigurationIndex = [1,2] + are supported */ + } + asc->m_channelConfiguration = channelConfigurationIndex; + + err = UsacRsv60DecoderConfig_Parse(asc, hBs, cb); + if (err != TRANSPORTDEC_OK) { + return err; + } + + if (FDKreadBits(hBs, 1)) { /* usacConfigExtensionPresent */ + err = configExtension(&asc->m_sc.m_usacConfig, hBs, cb); + if (err != TRANSPORTDEC_OK) { + return err; + } + } + + /* sanity check whether number of channels signaled in UsacDecoderConfig() + matches the number of channels required by channelConfigurationIndex */ + if ((channelConfigurationIndex > 0) && + (sc_chan_config_tab[channelConfigurationIndex].nCh != + asc->m_sc.m_usacConfig.m_nUsacChannels)) { + return TRANSPORTDEC_PARSE_ERROR; + } + + /* Copy UsacConfig() to asc->m_sc.m_usacConfig.UsacConfig[] buffer. */ + INT configSize_bits = (INT)FDKgetValidBits(hBs) - nbits; + StoreConfigAsBitstream(hBs, configSize_bits, + asc->m_sc.m_usacConfig.UsacConfig, + TP_USAC_MAX_CONFIG_LEN); + asc->m_sc.m_usacConfig.UsacConfigBits = fAbs(configSize_bits); + + return err; +} + +static TRANSPORTDEC_ERROR AudioSpecificConfig_ExtensionParse( + CSAudioSpecificConfig *self, HANDLE_FDK_BITSTREAM bs, CSTpCallBacks *cb) { + TP_ASC_EXTENSION_ID lastAscExt, ascExtId = ASCEXT_UNKOWN; + INT bitsAvailable = (INT)FDKgetValidBits(bs); + + while (bitsAvailable >= 11) { + lastAscExt = ascExtId; + ascExtId = (TP_ASC_EXTENSION_ID)FDKreadBits(bs, 11); + bitsAvailable -= 11; + + switch (ascExtId) { + case ASCEXT_SBR: /* 0x2b7 */ + if ((self->m_extensionAudioObjectType != AOT_SBR) && + (bitsAvailable >= 5)) { + self->m_extensionAudioObjectType = getAOT(bs); + + if ((self->m_extensionAudioObjectType == AOT_SBR) || + (self->m_extensionAudioObjectType == + AOT_ER_BSAC)) { /* Get SBR extension configuration */ + self->m_sbrPresentFlag = FDKreadBits(bs, 1); + if (self->m_aot == AOT_USAC && self->m_sbrPresentFlag > 0 && + self->m_sc.m_usacConfig.m_sbrRatioIndex == 0) { + return TRANSPORTDEC_PARSE_ERROR; + } + + if (self->m_sbrPresentFlag == 1) { + self->m_extensionSamplingFrequency = getSampleRate( + bs, &self->m_extensionSamplingFrequencyIndex, 4); + + if ((INT)self->m_extensionSamplingFrequency <= 0) { + return TRANSPORTDEC_PARSE_ERROR; + } + } + if (self->m_extensionAudioObjectType == AOT_ER_BSAC) { + self->m_extensionChannelConfiguration = FDKreadBits(bs, 4); + } + } + /* Update counter because of variable length fields (AOT and sampling + * rate) */ + bitsAvailable = (INT)FDKgetValidBits(bs); + } + break; + case ASCEXT_PS: /* 0x548 */ + if ((lastAscExt == ASCEXT_SBR) && + (self->m_extensionAudioObjectType == AOT_SBR) && + (bitsAvailable > 0)) { /* Get PS extension configuration */ + self->m_psPresentFlag = FDKreadBits(bs, 1); + bitsAvailable -= 1; + } + break; + case ASCEXT_MPS: /* 0x76a */ + if (self->m_extensionAudioObjectType == AOT_MPEGS) break; + case ASCEXT_LDMPS: /* 0x7cc */ + if ((ascExtId == ASCEXT_LDMPS) && + (self->m_extensionAudioObjectType == AOT_LD_MPEGS)) + break; + if (bitsAvailable >= 1) { + bitsAvailable -= 1; + if (FDKreadBits(bs, 1)) { /* self->m_mpsPresentFlag */ + int sscLen = FDKreadBits(bs, 8); + bitsAvailable -= 8; + if (sscLen == 0xFF) { + sscLen += FDKreadBits(bs, 16); + bitsAvailable -= 16; + } + FDKpushFor(bs, sscLen); /* Skip SSC to be able to read the next + extension if there is one. */ + + bitsAvailable -= sscLen * 8; + } + } + break; + case ASCEXT_SAOC: + if ((ascExtId == ASCEXT_SAOC) && + (self->m_extensionAudioObjectType == AOT_SAOC)) + break; + if (FDKreadBits(bs, 1)) { /* saocPresent */ + int saocscLen = FDKreadBits(bs, 8); + bitsAvailable -= 8; + if (saocscLen == 0xFF) { + saocscLen += FDKreadBits(bs, 16); + bitsAvailable -= 16; + } + FDKpushFor(bs, saocscLen); + bitsAvailable -= saocscLen * 8; + } + break; + default: + /* Just ignore anything. */ + return TRANSPORTDEC_OK; } } @@ -1237,134 +2070,149 @@ TRANSPORTDEC_ERROR AudioSpecificConfig_ExtensionParse(CSAudioSpecificConfig *sel * API Functions */ -void AudioSpecificConfig_Init(CSAudioSpecificConfig *asc) -{ +void AudioSpecificConfig_Init(CSAudioSpecificConfig *asc) { FDKmemclear(asc, sizeof(CSAudioSpecificConfig)); /* Init all values that should not be zero. */ - asc->m_aot = AOT_NONE; + asc->m_aot = AOT_NONE; asc->m_samplingFrequencyIndex = 0xf; - asc->m_epConfig = -1; - asc->m_extensionAudioObjectType = AOT_NULL_OBJECT; -#ifdef TP_PCE_ENABLE + asc->m_epConfig = -1; + asc->m_extensionAudioObjectType = AOT_NULL_OBJECT; CProgramConfig_Init(&asc->m_progrConfigElement); -#endif } TRANSPORTDEC_ERROR AudioSpecificConfig_Parse( - CSAudioSpecificConfig *self, - HANDLE_FDK_BITSTREAM bs, - int fExplicitBackwardCompatible, - CSTpCallBacks *cb - ) -{ + CSAudioSpecificConfig *self, HANDLE_FDK_BITSTREAM bs, + int fExplicitBackwardCompatible, CSTpCallBacks *cb, UCHAR configMode, + UCHAR configChanged, AUDIO_OBJECT_TYPE m_aot) { TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK; UINT ascStartAnchor = FDKgetValidBits(bs); int frameLengthFlag = -1; AudioSpecificConfig_Init(self); - self->m_aot = getAOT(bs); - self->m_samplingFrequency = getSampleRate(bs, &self->m_samplingFrequencyIndex, 4); - if (self->m_samplingFrequency <= 0) { - return TRANSPORTDEC_PARSE_ERROR; - } + self->configMode = configMode; + self->AacConfigChanged = configChanged; + self->SbrConfigChanged = configChanged; + self->SacConfigChanged = configChanged; - self->m_channelConfiguration = FDKreadBits(bs,4); + if (m_aot != AOT_NULL_OBJECT) { + self->m_aot = m_aot; + } else { + self->m_aot = getAOT(bs); + self->m_samplingFrequency = + getSampleRate(bs, &self->m_samplingFrequencyIndex, 4); + if (self->m_samplingFrequency <= 0) { + return TRANSPORTDEC_PARSE_ERROR; + } - /* SBR extension ( explicit non-backwards compatible mode ) */ - self->m_sbrPresentFlag = 0; - self->m_psPresentFlag = 0; + self->m_channelConfiguration = FDKreadBits(bs, 4); - if ( self->m_aot == AOT_SBR || self->m_aot == AOT_PS ) { - self->m_extensionAudioObjectType = AOT_SBR; + /* SBR extension ( explicit non-backwards compatible mode ) */ + self->m_sbrPresentFlag = 0; + self->m_psPresentFlag = 0; - self->m_sbrPresentFlag = 1; - if ( self->m_aot == AOT_PS ) { - self->m_psPresentFlag = 1; - } + if (self->m_aot == AOT_SBR || self->m_aot == AOT_PS) { + self->m_extensionAudioObjectType = AOT_SBR; - self->m_extensionSamplingFrequency = getSampleRate(bs, &self->m_extensionSamplingFrequencyIndex, 4); - self->m_aot = getAOT(bs); + self->m_sbrPresentFlag = 1; + if (self->m_aot == AOT_PS) { + self->m_psPresentFlag = 1; + } - } else { - self->m_extensionAudioObjectType = AOT_NULL_OBJECT; + self->m_extensionSamplingFrequency = + getSampleRate(bs, &self->m_extensionSamplingFrequencyIndex, 4); + self->m_aot = getAOT(bs); + + switch (self->m_aot) { + case AOT_AAC_LC: + break; + case AOT_ER_BSAC: + break; + default: + return TRANSPORTDEC_UNSUPPORTED_FORMAT; + } + + if (self->m_aot == AOT_ER_BSAC) { + self->m_extensionChannelConfiguration = FDKreadBits(bs, 4); + } + } else { + self->m_extensionAudioObjectType = AOT_NULL_OBJECT; + } } /* Parse whatever specific configs */ - switch (self->m_aot) - { -#ifdef TP_GA_ENABLE + switch (self->m_aot) { case AOT_AAC_LC: + case AOT_AAC_SCAL: case AOT_ER_AAC_LC: case AOT_ER_AAC_LD: case AOT_ER_AAC_SCAL: case AOT_ER_BSAC: - if ((ErrorStatus = GaSpecificConfig_Parse(&self->m_sc.m_gaSpecificConfig, self, bs, ascStartAnchor)) != TRANSPORTDEC_OK ) { + if ((ErrorStatus = GaSpecificConfig_Parse(&self->m_sc.m_gaSpecificConfig, + self, bs, ascStartAnchor)) != + TRANSPORTDEC_OK) { return (ErrorStatus); } frameLengthFlag = self->m_sc.m_gaSpecificConfig.m_frameLengthFlag; break; -#endif /* TP_GA_ENABLE */ case AOT_MPEGS: if (cb->cbSsc != NULL) { - cb->cbSsc( - cb->cbSscData, - bs, - self->m_aot, - self->m_samplingFrequency, - 1, - 0 /* don't know the length */ - ); + if (cb->cbSsc(cb->cbSscData, bs, self->m_aot, self->m_samplingFrequency, + 1, -1, /* nTimeSlots: read from bitstream */ + 0, /* don't know the length */ + self->configMode, &self->SacConfigChanged)) { + return TRANSPORTDEC_UNSUPPORTED_FORMAT; + } } else { return TRANSPORTDEC_UNSUPPORTED_FORMAT; } break; -#ifdef TP_ELD_ENABLE case AOT_ER_AAC_ELD: - if ((ErrorStatus = EldSpecificConfig_Parse(self, bs, cb)) != TRANSPORTDEC_OK ) { + if ((ErrorStatus = EldSpecificConfig_Parse(self, bs, cb)) != + TRANSPORTDEC_OK) { return (ErrorStatus); } frameLengthFlag = self->m_sc.m_eldSpecificConfig.m_frameLengthFlag; self->m_sbrPresentFlag = self->m_sc.m_eldSpecificConfig.m_sbrPresentFlag; - self->m_extensionSamplingFrequency = (self->m_sc.m_eldSpecificConfig.m_sbrSamplingRate+1) * self->m_samplingFrequency; + self->m_extensionSamplingFrequency = + (self->m_sc.m_eldSpecificConfig.m_sbrSamplingRate + 1) * + self->m_samplingFrequency; + break; + case AOT_USAC: + if ((ErrorStatus = UsacConfig_Parse(self, bs, cb)) != TRANSPORTDEC_OK) { + return (ErrorStatus); + } break; -#endif /* TP_ELD_ENABLE */ default: return TRANSPORTDEC_UNSUPPORTED_FORMAT; - break; } /* Frame length */ - switch (self->m_aot) - { -#if defined(TP_GA_ENABLE) || defined(TP_USAC_ENABLE) + switch (self->m_aot) { case AOT_AAC_LC: + case AOT_AAC_SCAL: case AOT_ER_AAC_LC: case AOT_ER_AAC_SCAL: case AOT_ER_BSAC: - /*case AOT_USAC:*/ + /*case AOT_USAC:*/ if (!frameLengthFlag) self->m_samplesPerFrame = 1024; else self->m_samplesPerFrame = 960; break; -#endif /* TP_GA_ENABLE */ -#if defined(TP_GA_ENABLE) case AOT_ER_AAC_LD: if (!frameLengthFlag) self->m_samplesPerFrame = 512; else self->m_samplesPerFrame = 480; break; -#endif /* defined(TP_GA_ENABLE) */ default: break; } - switch (self->m_aot) - { + switch (self->m_aot) { case AOT_ER_AAC_LC: case AOT_ER_AAC_LD: case AOT_ER_AAC_ELD: @@ -1372,40 +2220,196 @@ TRANSPORTDEC_ERROR AudioSpecificConfig_Parse( case AOT_ER_CELP: case AOT_ER_HVXC: case AOT_ER_BSAC: - self->m_epConfig = FDKreadBits(bs,2); + self->m_epConfig = FDKreadBits(bs, 2); if (self->m_epConfig > 1) { - return TRANSPORTDEC_UNSUPPORTED_FORMAT; // EPCONFIG; + return TRANSPORTDEC_UNSUPPORTED_FORMAT; // EPCONFIG; } break; default: break; } - if (fExplicitBackwardCompatible) { + if (fExplicitBackwardCompatible && + (self->m_aot == AOT_AAC_LC || self->m_aot == AOT_ER_AAC_LD || + self->m_aot == AOT_ER_BSAC)) { ErrorStatus = AudioSpecificConfig_ExtensionParse(self, bs, cb); } + /* Copy config() to asc->config[] buffer. */ + if ((ErrorStatus == TRANSPORTDEC_OK) && (self->m_aot == AOT_USAC)) { + INT configSize_bits = (INT)FDKgetValidBits(bs) - (INT)ascStartAnchor; + StoreConfigAsBitstream(bs, configSize_bits, self->config, + TP_USAC_MAX_CONFIG_LEN); + self->configBits = fAbs(configSize_bits); + } + return (ErrorStatus); } +static TRANSPORTDEC_ERROR Drm_xHEAACDecoderConfig( + CSAudioSpecificConfig *asc, HANDLE_FDK_BITSTREAM hBs, int audioMode, + CSTpCallBacks *cb /* use cb == NULL to signal config check only mode */ +) { + TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK; + CSUsacConfig *usc = &asc->m_sc.m_usacConfig; + int elemIdx = 0; + + usc->element[elemIdx].m_stereoConfigIndex = 0; + + usc->m_usacNumElements = 1; /* Currently all extension elements are skipped + -> only one SCE or CPE. */ + + switch (audioMode) { + case 0: /* mono: ID_USAC_SCE */ + usc->element[elemIdx].usacElementType = ID_USAC_SCE; + usc->m_nUsacChannels = 1; + usc->element[elemIdx].m_noiseFilling = FDKreadBits(hBs, 1); + if (usc->m_sbrRatioIndex > 0) { + if (cb == NULL) { + return ErrorStatus; + } + if (cb->cbSbr != NULL) { + usc->element[elemIdx].m_harmonicSBR = FDKreadBit(hBs); + usc->element[elemIdx].m_interTes = FDKreadBit(hBs); + usc->element[elemIdx].m_pvc = FDKreadBit(hBs); + if (cb->cbSbr(cb->cbSbrData, hBs, asc->m_samplingFrequency, + asc->m_extensionSamplingFrequency, + asc->m_samplesPerFrame, asc->m_aot, ID_SCE, elemIdx, + usc->element[elemIdx].m_harmonicSBR, + usc->element[elemIdx].m_stereoConfigIndex, + asc->configMode, &asc->SbrConfigChanged, 1)) { + return ErrorStatus = TRANSPORTDEC_PARSE_ERROR; + } + } + } + break; + case 2: /* stereo: ID_USAC_CPE */ + usc->element[elemIdx].usacElementType = ID_USAC_CPE; + usc->m_nUsacChannels = 2; + usc->element[elemIdx].m_noiseFilling = FDKreadBits(hBs, 1); + if (usc->m_sbrRatioIndex > 0) { + usc->element[elemIdx].m_harmonicSBR = FDKreadBit(hBs); + usc->element[elemIdx].m_interTes = FDKreadBit(hBs); + usc->element[elemIdx].m_pvc = FDKreadBit(hBs); + { + INT bitsToSkip = skipSbrHeader(hBs, 1); + /* read stereoConfigIndex */ + usc->element[elemIdx].m_stereoConfigIndex = FDKreadBits(hBs, 2); + /* rewind */ + FDKpushBack(hBs, bitsToSkip + 2); + } + /* + The application of the following tools is mutually exclusive per audio + stream configuration (see clause 5.3.2, xHE-AAC codec configuration): + - MPS212 parametric stereo tool with residual coding + (stereoConfigIndex>1); and + - QMF based Harmonic Transposer (harmonicSBR==1). + */ + if ((usc->element[elemIdx].m_stereoConfigIndex > 1) && + usc->element[elemIdx].m_harmonicSBR) { + return ErrorStatus = TRANSPORTDEC_PARSE_ERROR; + } + /* + The 4:1 sbrRatio (sbrRatioIndex==1 in [11]) may only be employed: + - in mono operation; or + - in stereo operation if parametric stereo (MPS212) without residual + coding is applied, i.e. if stereoConfigIndex==1 (see clause 5.3.2, + xHE-AAC codec configuration). + */ + if ((usc->m_sbrRatioIndex == 1) && + (usc->element[elemIdx].m_stereoConfigIndex != 1)) { + return ErrorStatus = TRANSPORTDEC_PARSE_ERROR; + } + if (cb == NULL) { + return ErrorStatus; + } + { + MP4_ELEMENT_ID el_type = + (usc->element[elemIdx].m_stereoConfigIndex == 1 || + usc->element[elemIdx].m_stereoConfigIndex == 2) + ? ID_SCE + : ID_CPE; + if (cb->cbSbr == NULL) return ErrorStatus = TRANSPORTDEC_UNKOWN_ERROR; + if (cb->cbSbr(cb->cbSbrData, hBs, asc->m_samplingFrequency, + asc->m_extensionSamplingFrequency, + asc->m_samplesPerFrame, asc->m_aot, el_type, elemIdx, + usc->element[elemIdx].m_harmonicSBR, + usc->element[elemIdx].m_stereoConfigIndex, + asc->configMode, &asc->SbrConfigChanged, 1)) { + return ErrorStatus = TRANSPORTDEC_PARSE_ERROR; + } + } + /*usc->element[elemIdx].m_stereoConfigIndex =*/FDKreadBits(hBs, 2); + if (usc->element[elemIdx].m_stereoConfigIndex > 0) { + if (cb->cbSsc != NULL) { + ErrorStatus = (TRANSPORTDEC_ERROR)cb->cbSsc( + cb->cbSscData, hBs, + AOT_DRM_USAC, /* syntax differs from MPEG Mps212Config() */ + asc->m_extensionSamplingFrequency, + usc->element[elemIdx].m_stereoConfigIndex, + usc->m_coreSbrFrameLengthIndex, 0, /* don't know the length */ + asc->configMode, &asc->SacConfigChanged); + } else { + /* ErrorStatus = TRANSPORTDEC_UNSUPPORTED_FORMAT; */ + } + } + } + break; + default: + return TRANSPORTDEC_PARSE_ERROR; + } + + return ErrorStatus; +} + +TRANSPORTDEC_ERROR Drm_xHEAACStaticConfig( + CSAudioSpecificConfig *asc, HANDLE_FDK_BITSTREAM bs, int audioMode, + CSTpCallBacks *cb /* use cb == NULL to signal config check only mode */ +) { + int coreSbrFrameLengthIndexDrm = FDKreadBits(bs, 2); + if (UsacConfig_SetCoreSbrFrameLengthIndex( + asc, coreSbrFrameLengthIndexDrm + 1) != TRANSPORTDEC_OK) { + return TRANSPORTDEC_PARSE_ERROR; + } + + asc->m_channelConfiguration = (audioMode) ? 2 : 1; + + if (Drm_xHEAACDecoderConfig(asc, bs, audioMode, cb) != TRANSPORTDEC_OK) { + return TRANSPORTDEC_PARSE_ERROR; + } + + return TRANSPORTDEC_OK; +} + +/* Mapping of DRM audio sampling rate field to MPEG usacSamplingFrequencyIndex + */ +const UCHAR mapSr2MPEGIdx[8] = { + 0x1b, /* 9.6 kHz */ + 0x09, /* 12.0 kHz */ + 0x08, /* 16.0 kHz */ + 0x17, /* 19.2 kHz */ + 0x06, /* 24.0 kHz */ + 0x05, /* 32.0 kHz */ + 0x12, /* 38.4 kHz */ + 0x03 /* 48.0 kHz */ +}; + TRANSPORTDEC_ERROR DrmRawSdcAudioConfig_Parse( - CSAudioSpecificConfig *self, - HANDLE_FDK_BITSTREAM bs - ) -{ + CSAudioSpecificConfig *self, HANDLE_FDK_BITSTREAM bs, + CSTpCallBacks *cb, /* use cb == NULL to signal config check only mode */ + UCHAR configMode, UCHAR configChanged) { TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK; AudioSpecificConfig_Init(self); - if ((INT)FDKgetValidBits(bs) < 20) { + if ((INT)FDKgetValidBits(bs) < 16) { ErrorStatus = TRANSPORTDEC_PARSE_ERROR; goto bail; - } - else { + } else { /* DRM - Audio information data entity - type 9 - - Short Id 2 bits - - Stream Id 2 bits + - Short Id 2 bits (not part of the config buffer) + - Stream Id 2 bits (not part of the config buffer) - audio coding 2 bits - SBR flag 1 bit - audio mode 2 bits @@ -1417,54 +2421,64 @@ TRANSPORTDEC_ERROR DrmRawSdcAudioConfig_Parse( int audioCoding, audioMode, cSamplingFreq, coderField, sfIdx, sbrFlag; - /* Read the SDC field */ - FDKreadBits(bs,4); /* Short and Stream Id */ + self->configMode = configMode; + self->AacConfigChanged = configChanged; + self->SbrConfigChanged = configChanged; + self->SacConfigChanged = configChanged; - audioCoding = FDKreadBits(bs, 2); - sbrFlag = FDKreadBits(bs, 1); - audioMode = FDKreadBits(bs, 2); - cSamplingFreq = FDKreadBits(bs, 3); /* audio sampling rate */ + /* Read the SDC field */ + audioCoding = FDKreadBits(bs, 2); + sbrFlag = FDKreadBits(bs, 1); + audioMode = FDKreadBits(bs, 2); + cSamplingFreq = FDKreadBits(bs, 3); /* audio sampling rate */ - FDKreadBits(bs, 2); /* Text and enhancement flag */ - coderField = FDKreadBits(bs, 5); - FDKreadBits(bs, 1); /* rfa */ + FDKreadBits(bs, 2); /* Text and enhancement flag */ + coderField = FDKreadBits(bs, 5); + FDKreadBits(bs, 1); /* rfa */ /* Evaluate configuration and fill the ASC */ - switch (cSamplingFreq) { - case 0: /* 8 kHz */ - sfIdx = 11; - break; - case 1: /* 12 kHz */ - sfIdx = 9; - break; - case 2: /* 16 kHz */ - sfIdx = 8; - break; - case 3: /* 24 kHz */ - sfIdx = 6; - break; - case 5: /* 48 kHz */ - sfIdx = 3; - break; - case 4: /* reserved */ - case 6: /* reserved */ - case 7: /* reserved */ - default: - ErrorStatus = TRANSPORTDEC_PARSE_ERROR; - goto bail; + if (audioCoding == 3) { + sfIdx = (int)mapSr2MPEGIdx[cSamplingFreq]; + sbrFlag = 0; /* rfa */ + } else { + switch (cSamplingFreq) { + case 0: /* 8 kHz */ + sfIdx = 11; + break; + case 1: /* 12 kHz */ + sfIdx = 9; + break; + case 2: /* 16 kHz */ + sfIdx = 8; + break; + case 3: /* 24 kHz */ + sfIdx = 6; + break; + case 5: /* 48 kHz */ + sfIdx = 3; + break; + case 4: /* reserved */ + case 6: /* reserved */ + case 7: /* reserved */ + default: + ErrorStatus = TRANSPORTDEC_PARSE_ERROR; + goto bail; + } } self->m_samplingFrequencyIndex = sfIdx; self->m_samplingFrequency = SamplingRateTable[sfIdx]; - if ( sbrFlag ) { + if (sbrFlag) { UINT i; int tmp = -1; self->m_sbrPresentFlag = 1; self->m_extensionAudioObjectType = AOT_SBR; self->m_extensionSamplingFrequency = self->m_samplingFrequency << 1; - for (i=0; i<(sizeof(SamplingRateTable)/sizeof(SamplingRateTable[0])); i++){ - if (SamplingRateTable[i] == self->m_extensionSamplingFrequency){ + for (i = 0; + i < (sizeof(SamplingRateTable) / sizeof(SamplingRateTable[0])); + i++) { + if (SamplingRateTable[i] == self->m_extensionSamplingFrequency) { tmp = i; break; } @@ -1474,20 +2488,23 @@ TRANSPORTDEC_ERROR DrmRawSdcAudioConfig_Parse( switch (audioCoding) { case 0: /* AAC */ - self->m_aot = AOT_DRM_AAC ; /* Set pseudo AOT for Drm AAC */ - + if (coderField >> 2) { + self->m_aot = AOT_DRM_SURROUND; /* Set pseudo AOT for Drm Surround */ + } else { + self->m_aot = AOT_DRM_AAC; /* Set pseudo AOT for Drm AAC */ + } switch (audioMode) { - case 1: /* parametric stereo */ - self->m_psPresentFlag = 1; - case 0: /* mono */ - self->m_channelConfiguration = 1; - break; - case 2: /* stereo */ - self->m_channelConfiguration = 2; - break; - default: - ErrorStatus = TRANSPORTDEC_PARSE_ERROR; - goto bail; + case 1: /* parametric stereo */ + self->m_psPresentFlag = 1; + case 0: /* mono */ + self->m_channelConfiguration = 1; + break; + case 2: /* stereo */ + self->m_channelConfiguration = 2; + break; + default: + ErrorStatus = TRANSPORTDEC_PARSE_ERROR; + goto bail; } self->m_vcb11Flag = 1; self->m_hcrFlag = 1; @@ -1502,7 +2519,22 @@ TRANSPORTDEC_ERROR DrmRawSdcAudioConfig_Parse( self->m_aot = AOT_ER_HVXC; self->m_channelConfiguration = 1; break; - case 3: /* reserved */ + case 3: /* xHE-AAC */ + { + /* payload is MPEG conform -> no pseudo DRM AOT needed */ + self->m_aot = AOT_USAC; + } + switch (audioMode) { + case 0: /* mono */ + case 2: /* stereo */ + /* codec specific config 8n bits */ + ErrorStatus = Drm_xHEAACStaticConfig(self, bs, audioMode, cb); + break; + default: + ErrorStatus = TRANSPORTDEC_PARSE_ERROR; + goto bail; + } + break; default: ErrorStatus = TRANSPORTDEC_PARSE_ERROR; self->m_aot = AOT_NONE; @@ -1518,4 +2550,3 @@ TRANSPORTDEC_ERROR DrmRawSdcAudioConfig_Parse( bail: return (ErrorStatus); } - |