diff options
Diffstat (limited to 'libMpegTPDec')
-rw-r--r-- | libMpegTPDec/include/mpegFileRead.h | 194 | ||||
-rw-r--r-- | libMpegTPDec/include/tp_data.h | 487 | ||||
-rw-r--r-- | libMpegTPDec/include/tpdec_lib.h | 621 | ||||
-rw-r--r-- | libMpegTPDec/src/mpegFileFormat.h | 114 | ||||
-rw-r--r-- | libMpegTPDec/src/tp_version.h | 118 | ||||
-rw-r--r-- | libMpegTPDec/src/tpdec_adif.cpp | 163 | ||||
-rw-r--r-- | libMpegTPDec/src/tpdec_adif.h | 143 | ||||
-rw-r--r-- | libMpegTPDec/src/tpdec_adts.cpp | 352 | ||||
-rw-r--r-- | libMpegTPDec/src/tpdec_adts.h | 200 | ||||
-rw-r--r-- | libMpegTPDec/src/tpdec_asc.cpp | 2681 | ||||
-rw-r--r-- | libMpegTPDec/src/tpdec_drm.cpp | 154 | ||||
-rw-r--r-- | libMpegTPDec/src/tpdec_drm.h | 182 | ||||
-rw-r--r-- | libMpegTPDec/src/tpdec_latm.cpp | 693 | ||||
-rw-r--r-- | libMpegTPDec/src/tpdec_latm.h | 197 | ||||
-rw-r--r-- | libMpegTPDec/src/tpdec_lib.cpp | 1501 | ||||
-rw-r--r-- | libMpegTPDec/src/version | 13 |
16 files changed, 4809 insertions, 3004 deletions
diff --git a/libMpegTPDec/include/mpegFileRead.h b/libMpegTPDec/include/mpegFileRead.h deleted file mode 100644 index 1fbfb58..0000000 --- a/libMpegTPDec/include/mpegFileRead.h +++ /dev/null @@ -1,194 +0,0 @@ - -/* ----------------------------------------------------------------------------------------------------------- -Software License for The Fraunhofer FDK AAC Codec Library for Android - -© Copyright 1995 - 2013 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. - -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: - -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 -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. - -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." - -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. - -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. - -5. CONTACT INFORMATION - -Fraunhofer Institute for Integrated Circuits IIS -Attention: Audio and Multimedia Departments - FDK AAC LL -Am Wolfsmantel 33 -91058 Erlangen, Germany - -www.iis.fraunhofer.de/amm -amm-info@iis.fraunhofer.de ------------------------------------------------------------------------------------------------------------ */ - -/***************************** MPEG-4 AAC Decoder ************************** - - Author(s): Manuel Jander - Description: Bitstream data provider for MP4 decoders - -******************************************************************************/ - -#include "machine_type.h" -#include "FDK_audio.h" - -#define MPFREAD_MP4FF_DISABLE - -#ifndef MPFREAD_MP4FF_DISABLE - /*!< If MPFREAD_MP4FF_ENABLE is set, include support for MPEG ISO fileformat. - If not set, no .mp4, .m4a and .3gp files can be used for input. */ - #define MPFREAD_MP4FF_ENABLE -#endif - -/* maximum number of layers which can be read */ -/* shall equal max number of layers read by iisisoff */ -#define FILEREAD_MAX_LAYERS (2) - -typedef struct STRUCT_FILEREAD *HANDLE_FILEREAD; - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief Open an MPEG audio file and try to detect its format. - * \param filename String of the filename to be opened. - * \param fileFormat Skip file format detection and use given format if fileFormat != FF_UNKNOWN. - Else store detected format into *fileFmt. - * \param transportType Skip transport type detection and use given format if transportType != TT_UNKNOWN. - Else store detected format into *fileFmt. - * \param conf Pointer to unsigned char to hold the AudioSpecificConfig of the input file, if - any (MPEG 4 file format). In case of RAW LATM it holds the StreamMuxConfig. - * \param confSize Pointer to an integer, where the length of the ASC or SMC (in case of RAW LATM) - is stored to. - * \return MPEG file read handle. - */ -HANDLE_FILEREAD mpegFileRead_Open( const char *filename, - FILE_FORMAT fileFormat, - TRANSPORT_TYPE transportType, - UCHAR *conf[], - UINT confSize[], - INT *noOfLayers - ); - -/** - * \brief Get the file format of the input file. - * \param hDataSrc MPEG file read handle. - * \return File format of the input file. - */ -FILE_FORMAT mpegFileRead_GetFileFormat(HANDLE_FILEREAD hDataSrc); - -/** - * \brief Get the transport type of the input file. - * \param hDataSrc MPEG file read handle. - * \return Transport type of the input file. - */ -TRANSPORT_TYPE mpegFileRead_GetTransportType(HANDLE_FILEREAD hDataSrc); - -/** - * \brief Read data from MPEG file. In case of packet file, read one packet, in case - * of streaming file with embedded synchronisation layer (LOAS/ADTS...), just - * fill the buffer. - * - * \param hMpegFile MPEG file read handle. - * \param inBuffer Pointer to input buffer. - * \param bufferSize Size of input buffer. - * \param bytesValid Number of bytes that were read. - * \return 0 on success, -1 if unsupported file format or file read error. - */ -int mpegFileRead_Read( HANDLE_FILEREAD hMpegFile, - UCHAR *inBuffer[], - UINT bufferSize, - UINT *bytesValid - ); - -/** - * \brief Seek in file from origin by given offset in frames. - * \param hMpegFile MPEG file read handle. - * \param origin If 0, the origin is the file beginning (absolute seek). - * If 1, the origin is the current position (relative seek). - * \param offset The amount of frames to seek from the given origin. - * \return 0 on sucess, -1 if offset < 0 or file read error. - */ -int mpegFileRead_seek( HANDLE_FILEREAD hMpegFile, - INT origin, - INT offset - ); - -/** - * \brief Get file position in percent. - * \param hMpegFile MPEG file read handle. - * \return File position in percent. - */ -int mpegFileRead_getPercent(HANDLE_FILEREAD hMpegFile); - - -/** - * \brief Close MPEG audio file. - * \param hMpegFile Mpeg file read handle. - * \return 0 on sucess. - */ -int mpegFileRead_Close(HANDLE_FILEREAD *hMpegFile); - -#ifdef __cplusplus -} -#endif diff --git a/libMpegTPDec/include/tp_data.h b/libMpegTPDec/include/tp_data.h index c6e89b5..b4ab802 100644 --- a/libMpegTPDec/include/tp_data.h +++ b/libMpegTPDec/include/tp_data.h @@ -1,74 +1,85 @@ - -/* ----------------------------------------------------------------------------------------------------------- +/* ----------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 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,17 +90,18 @@ Am Wolfsmantel 33 www.iis.fraunhofer.de/amm amm-info@iis.fraunhofer.de ------------------------------------------------------------------------------------------------------------ */ +----------------------------------------------------------------------------- */ + +/******************* MPEG transport format decoder library ********************* -/***************************** MPEG-4 AAC Decoder ************************** + Author(s): Manuel Jander - Author(s): Manuel Jander Description: MPEG Transport data tables -******************************************************************************/ +*******************************************************************************/ -#ifndef __TP_DATA_H__ -#define __TP_DATA_H__ +#ifndef TP_DATA_H +#define TP_DATA_H #include "machine_type.h" #include "FDK_audio.h" @@ -98,17 +110,35 @@ amm-info@iis.fraunhofer.de /* * Configuration */ -#define TP_GA_ENABLE -/* #define TP_CELP_ENABLE */ -/* #define TP_HVXC_ENABLE */ -/* #define TP_SLS_ENABLE */ -#define TP_ELD_ENABLE -/* #define TP_USAC_ENABLE */ -/* #define TP_RSVD50_ENABLE */ - -#if defined(TP_GA_ENABLE) || defined(TP_SLS_ENABLE) -#define TP_PCE_ENABLE /**< Enable full PCE support */ -#endif + +#define TP_USAC_MAX_SPEAKERS (24) + +#define TP_USAC_MAX_EXT_ELEMENTS ((24)) + +#define TP_USAC_MAX_ELEMENTS ((24) + TP_USAC_MAX_EXT_ELEMENTS) + +#define TP_USAC_MAX_CONFIG_LEN \ + 512 /* next power of two of maximum of escapedValue(hBs, 4, 4, 8) in \ + AudioPreRoll() (285) */ + +#define TPDEC_USAC_NUM_CONFIG_CHANGE_FRAMES \ + (1) /* Number of frames for config change in USAC */ + +enum { + TPDEC_FLUSH_OFF = 0, + TPDEC_RSV60_CFG_CHANGE_ATSC_FLUSH_ON = 1, + TPDEC_RSV60_DASH_IPF_ATSC_FLUSH_ON = 2, + TPDEC_USAC_DASH_IPF_FLUSH_ON = 3 +}; + +enum { + TPDEC_BUILD_UP_OFF = 0, + TPDEC_RSV60_BUILD_UP_ON = 1, + TPDEC_RSV60_BUILD_UP_ON_IN_BAND = 2, + TPDEC_USAC_BUILD_UP_ON = 3, + TPDEC_RSV60_BUILD_UP_IDLE = 4, + TPDEC_RSV60_BUILD_UP_IDLE_IN_BAND = 5 +}; /** * ProgramConfig struct. @@ -116,13 +146,12 @@ amm-info@iis.fraunhofer.de /* ISO/IEC 14496-3 4.4.1.1 Table 4.2 Program config element */ #define PC_FSB_CHANNELS_MAX 16 /* Front/Side/Back channels */ #define PC_LFE_CHANNELS_MAX 4 -#define PC_ASSOCDATA_MAX 8 -#define PC_CCEL_MAX 16 /* CC elements */ -#define PC_COMMENTLENGTH 256 +#define PC_ASSOCDATA_MAX 8 +#define PC_CCEL_MAX 16 /* CC elements */ +#define PC_COMMENTLENGTH 256 +#define PC_NUM_HEIGHT_LAYER 3 -typedef struct -{ -#ifdef TP_PCE_ENABLE +typedef struct { /* PCE bitstream elements: */ UCHAR ElementInstanceTag; UCHAR Profile; @@ -165,54 +194,50 @@ typedef struct UCHAR CommentFieldBytes; UCHAR Comment[PC_COMMENTLENGTH]; -#endif /* TP_PCE_ENABLE */ /* Helper variables for administration: */ - UCHAR isValid; /*!< Flag showing if PCE has been read successfully. */ - UCHAR NumChannels; /*!< Amount of audio channels summing all channel elements including LFEs */ - UCHAR NumEffectiveChannels; /*!< Amount of audio channels summing only SCEs and CPEs */ + UCHAR isValid; /*!< Flag showing if PCE has been read successfully. */ + UCHAR + NumChannels; /*!< Amount of audio channels summing all channel elements + including LFEs */ + UCHAR NumEffectiveChannels; /*!< Amount of audio channels summing only SCEs + and CPEs */ UCHAR elCounter; } CProgramConfig; typedef enum { ASCEXT_UNKOWN = -1, - ASCEXT_SBR = 0x2b7, - ASCEXT_PS = 0x548, - ASCEXT_MPS = 0x76a, - ASCEXT_SAOC = 0x7cb, - ASCEXT_LDMPS = 0x7cc + ASCEXT_SBR = 0x2b7, + ASCEXT_PS = 0x548, + ASCEXT_MPS = 0x76a, + ASCEXT_SAOC = 0x7cb, + ASCEXT_LDMPS = 0x7cc } TP_ASC_EXTENSION_ID; -#ifdef TP_GA_ENABLE /** * GaSpecificConfig struct */ typedef struct { - UINT m_frameLengthFlag ; - UINT m_dependsOnCoreCoder ; - UINT m_coreCoderDelay ; + UINT m_frameLengthFlag; + UINT m_dependsOnCoreCoder; + UINT m_coreCoderDelay; - UINT m_extensionFlag ; - UINT m_extensionFlag3 ; + UINT m_extensionFlag; + UINT m_extensionFlag3; UINT m_layer; UINT m_numOfSubFrame; UINT m_layerLength; } CSGaSpecificConfig; -#endif /* TP_GA_ENABLE */ - - - - -#ifdef TP_ELD_ENABLE typedef enum { - ELDEXT_TERM = 0x0, /* Termination tag */ - ELDEXT_SAOC = 0x1, /* SAOC config */ - ELDEXT_LDSAC = 0x2 /* LD MPEG Surround config */ + ELDEXT_TERM = 0x0, /* Termination tag */ + ELDEXT_SAOC = 0x1, /* SAOC config */ + ELDEXT_LDSAC = 0x2, /* LD MPEG Surround config */ + ELDEXT_DOWNSCALEINFO = 0x3 /* ELD sample rate adaptation */ /* reserved */ } ASC_ELD_EXT_TYPE; @@ -220,103 +245,186 @@ typedef struct { UCHAR m_frameLengthFlag; UCHAR m_sbrPresentFlag; - UCHAR m_useLdQmfTimeAlign; /* Use LD-MPS QMF in SBR to achive time alignment */ + UCHAR + m_useLdQmfTimeAlign; /* Use LD-MPS QMF in SBR to achive time alignment */ UCHAR m_sbrSamplingRate; UCHAR m_sbrCrcFlag; + UINT m_downscaledSamplingFrequency; } CSEldSpecificConfig; -#endif /* TP_ELD_ENABLE */ +typedef struct { + USAC_EXT_ELEMENT_TYPE usacExtElementType; + USHORT usacExtElementConfigLength; + USHORT usacExtElementDefaultLength; + UCHAR usacExtElementPayloadFrag; + UCHAR usacExtElementHasAudioPreRoll; +} CSUsacExtElementConfig; +typedef struct { + MP4_ELEMENT_ID usacElementType; + UCHAR m_noiseFilling; + UCHAR m_harmonicSBR; + UCHAR m_interTes; + UCHAR m_pvc; + UCHAR m_stereoConfigIndex; + CSUsacExtElementConfig extElement; +} CSUsacElementConfig; +typedef struct { + UCHAR m_frameLengthFlag; + UCHAR m_coreSbrFrameLengthIndex; + UCHAR m_sbrRatioIndex; + UCHAR m_nUsacChannels; /* number of audio channels signaled in + UsacDecoderConfig() / rsv603daDecoderConfig() via + numElements and usacElementType */ + UCHAR m_channelConfigurationIndex; + UINT m_usacNumElements; + CSUsacElementConfig element[TP_USAC_MAX_ELEMENTS]; + + UCHAR numAudioChannels; + UCHAR m_usacConfigExtensionPresent; + UCHAR elementLengthPresent; + UCHAR UsacConfig[TP_USAC_MAX_CONFIG_LEN]; + USHORT UsacConfigBits; +} CSUsacConfig; /** * Audio configuration struct, suitable for encoder and decoder configuration. */ typedef struct { - /* XYZ Specific Data */ union { -#ifdef TP_GA_ENABLE - CSGaSpecificConfig m_gaSpecificConfig; /**< General audio specific configuration. */ -#endif /* TP_GA_ENABLE */ -#ifdef TP_ELD_ENABLE - CSEldSpecificConfig m_eldSpecificConfig; /**< ELD specific configuration. */ -#endif /* TP_ELD_ENABLE */ + CSGaSpecificConfig + m_gaSpecificConfig; /**< General audio specific configuration. */ + CSEldSpecificConfig m_eldSpecificConfig; /**< ELD specific configuration. */ + CSUsacConfig m_usacConfig; /**< USAC specific configuration */ } m_sc; - - /* Common ASC parameters */ -#ifdef TP_PCE_ENABLE - CProgramConfig m_progrConfigElement; /**< Program configuration. */ -#endif /* TP_PCE_ENABLE */ - - AUDIO_OBJECT_TYPE m_aot; /**< Audio Object Type. */ - UINT m_samplingFrequency; /**< Samplerate. */ - UINT m_samplesPerFrame; /**< Amount of samples per frame. */ - UINT m_directMapping; /**< Document this please !! */ - - AUDIO_OBJECT_TYPE m_extensionAudioObjectType; /**< Audio object type */ - UINT m_extensionSamplingFrequency; /**< Samplerate */ - SCHAR m_channelConfiguration; /**< Channel configuration index */ - - SCHAR m_epConfig; /**< Error protection index */ - SCHAR m_vcb11Flag; /**< aacSectionDataResilienceFlag */ - SCHAR m_rvlcFlag; /**< aacScalefactorDataResilienceFlag */ - SCHAR m_hcrFlag; /**< aacSpectralDataResilienceFlag */ - - SCHAR m_sbrPresentFlag; /**< Flag indicating the presence of SBR data in the bitstream */ - SCHAR m_psPresentFlag; /**< Flag indicating the presence of parametric stereo data in the bitstream */ - UCHAR m_samplingFrequencyIndex; /**< Samplerate index */ - UCHAR m_extensionSamplingFrequencyIndex; /**< Samplerate index */ - SCHAR m_extensionChannelConfiguration; /**< Channel configuration index */ + /* Common ASC parameters */ + CProgramConfig m_progrConfigElement; /**< Program configuration. */ + + AUDIO_OBJECT_TYPE m_aot; /**< Audio Object Type. */ + UINT m_samplingFrequency; /**< Samplerate. */ + UINT m_samplesPerFrame; /**< Amount of samples per frame. */ + UINT m_directMapping; /**< Document this please !! */ + + AUDIO_OBJECT_TYPE m_extensionAudioObjectType; /**< Audio object type */ + UINT m_extensionSamplingFrequency; /**< Samplerate */ + + SCHAR m_channelConfiguration; /**< Channel configuration index */ + + SCHAR m_epConfig; /**< Error protection index */ + SCHAR m_vcb11Flag; /**< aacSectionDataResilienceFlag */ + SCHAR m_rvlcFlag; /**< aacScalefactorDataResilienceFlag */ + SCHAR m_hcrFlag; /**< aacSpectralDataResilienceFlag */ + + SCHAR m_sbrPresentFlag; /**< Flag indicating the presence of SBR data in the + bitstream */ + SCHAR + m_psPresentFlag; /**< Flag indicating the presence of parametric stereo + data in the bitstream */ + UCHAR m_samplingFrequencyIndex; /**< Samplerate index */ + UCHAR m_extensionSamplingFrequencyIndex; /**< Samplerate index */ + SCHAR m_extensionChannelConfiguration; /**< Channel configuration index */ + + UCHAR + configMode; /**< The flag indicates if the callback shall work in memory + allocation mode or in config change detection mode */ + UCHAR AacConfigChanged; /**< The flag will be set if at least one aac config + parameter has changed that requires a memory + reconfiguration, otherwise it will be cleared */ + UCHAR SbrConfigChanged; /**< The flag will be set if at least one sbr config + parameter has changed that requires a memory + reconfiguration, otherwise it will be cleared */ + UCHAR SacConfigChanged; /**< The flag will be set if at least one sac config + parameter has changed that requires a memory + reconfiguration, otherwise it will be cleared */ + + UCHAR + config[TP_USAC_MAX_CONFIG_LEN]; /**< Configuration stored as bitstream */ + UINT configBits; /**< Configuration length in bits */ } CSAudioSpecificConfig; -typedef INT (*cbUpdateConfig_t)(void*, const CSAudioSpecificConfig*); -typedef INT (*cbSsc_t)( - void*, HANDLE_FDK_BITSTREAM, - const AUDIO_OBJECT_TYPE coreCodec, - const INT samplingFrequency, - const INT muxMode, - const INT configBytes - ); -typedef INT (*cbSbr_t)( - void * self, - HANDLE_FDK_BITSTREAM hBs, - const INT sampleRateIn, - const INT sampleRateOut, - const INT samplesPerFrame, - const AUDIO_OBJECT_TYPE coreCodec, - const MP4_ELEMENT_ID elementID, - const INT elementIndex - ); - -typedef struct { - cbUpdateConfig_t cbUpdateConfig; /*!< Function pointer for Config change notify callback. */ - void *cbUpdateConfigData; /*!< User data pointer for Config change notify callback. */ - cbSsc_t cbSsc; /*!< Function pointer for SSC parser callback. */ - void *cbSscData; /*!< User data pointer for SSC parser callback. */ - cbSbr_t cbSbr; /*!< Function pointer for SBR header parser callback. */ - void *cbSbrData; /*!< User data pointer for SBR header parser callback. */ +typedef struct { + SCHAR flushCnt; /**< Flush frame counter */ + UCHAR flushStatus; /**< Flag indicates flush mode: on|off */ + SCHAR buildUpCnt; /**< Build up frame counter */ + UCHAR buildUpStatus; /**< Flag indicates build up mode: on|off */ + UCHAR cfgChanged; /**< Flag indicates that the config changed and the decoder + needs to be initialized again via callback. Make sure + that memory is freed before initialization. */ + UCHAR contentChanged; /**< Flag indicates that the content changed i.e. a + right truncation occured before */ + UCHAR forceCfgChange; /**< Flag indicates if config change has to be forced + even if new config is the same */ +} CCtrlCFGChange; + +typedef INT (*cbUpdateConfig_t)(void *, const CSAudioSpecificConfig *, + const UCHAR configMode, UCHAR *configChanged); +typedef INT (*cbFreeMem_t)(void *, const CSAudioSpecificConfig *); +typedef INT (*cbCtrlCFGChange_t)(void *, const CCtrlCFGChange *); +typedef INT (*cbSsc_t)(void *, HANDLE_FDK_BITSTREAM, + const AUDIO_OBJECT_TYPE coreCodec, + const INT samplingRate, const INT stereoConfigIndex, + const INT coreSbrFrameLengthIndex, const INT configBytes, + const UCHAR configMode, UCHAR *configChanged); + +typedef INT (*cbSbr_t)(void *self, HANDLE_FDK_BITSTREAM hBs, + const INT sampleRateIn, const INT sampleRateOut, + const INT samplesPerFrame, + const AUDIO_OBJECT_TYPE coreCodec, + const MP4_ELEMENT_ID elementID, const INT elementIndex, + const UCHAR harmonicSbr, const UCHAR stereoConfigIndex, + const UCHAR configMode, UCHAR *configChanged, + const INT downscaleFactor); + +typedef INT (*cbUsac_t)(void *self, HANDLE_FDK_BITSTREAM hBs); + +typedef INT (*cbUniDrc_t)(void *self, HANDLE_FDK_BITSTREAM hBs, + const INT fullPayloadLength, const INT payloadType, + const INT subStreamIndex, const INT payloadStart, + const AUDIO_OBJECT_TYPE); + +typedef struct { + cbUpdateConfig_t cbUpdateConfig; /*!< Function pointer for Config change + notify callback. */ + void *cbUpdateConfigData; /*!< User data pointer for Config change notify + callback. */ + cbFreeMem_t cbFreeMem; /*!< Function pointer for free memory callback. */ + void *cbFreeMemData; /*!< User data pointer for free memory callback. */ + cbCtrlCFGChange_t cbCtrlCFGChange; /*!< Function pointer for config change + control callback. */ + void *cbCtrlCFGChangeData; /*!< User data pointer for config change control + callback. */ + cbSsc_t cbSsc; /*!< Function pointer for SSC parser callback. */ + void *cbSscData; /*!< User data pointer for SSC parser callback. */ + cbSbr_t cbSbr; /*!< Function pointer for SBR header parser callback. */ + void *cbSbrData; /*!< User data pointer for SBR header parser callback. */ + cbUsac_t cbUsac; + void *cbUsacData; + cbUniDrc_t cbUniDrc; /*!< Function pointer for uniDrcConfig and + loudnessInfoSet parser callback. */ + void *cbUniDrcData; /*!< User data pointer for uniDrcConfig and + loudnessInfoSet parser callback. */ } CSTpCallBacks; -static const UINT SamplingRateTable[] = -{ 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 7350, 0, 0, - 0 -}; +static const UINT SamplingRateTable[] = { + 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, + 8000, 7350, 0, 0, 57600, 51200, 40000, 38400, 34150, 28800, 25600, + 20000, 19200, 17075, 14400, 12800, 9600, 0, 0, 0, 0}; -static inline -int getSamplingRateIndex( UINT samplingRate ) -{ - UINT sf_index, tableSize=sizeof(SamplingRateTable)/sizeof(UINT); +static inline int getSamplingRateIndex(UINT samplingRate, UINT nBits) { + UINT sf_index; + UINT tableSize = (1 << nBits) - 1; - for (sf_index=0; sf_index<tableSize; sf_index++) { - if( SamplingRateTable[sf_index] == samplingRate ) break; + for (sf_index = 0; sf_index < tableSize; sf_index++) { + if (SamplingRateTable[sf_index] == samplingRate) break; } - if (sf_index>tableSize-1) { - return tableSize-1; + if (sf_index > tableSize) { + return tableSize - 1; } return sf_index; @@ -325,26 +433,33 @@ int getSamplingRateIndex( UINT samplingRate ) /* * Get Channel count from channel configuration */ -static inline int getNumberOfTotalChannels(int channelConfig) -{ +static inline int getNumberOfTotalChannels(int channelConfig) { switch (channelConfig) { - case 1: case 2: case 3: - case 4: case 5: case 6: - return channelConfig; - case 7: case 12: case 14: - return 8; - case 11: - return 7; - default: - return 0; + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + return channelConfig; + case 7: + case 12: + case 14: + return 8; + case 11: + return 7; + case 13: + return 24; + default: + return 0; } } -static inline -int getNumberOfEffectiveChannels(const int channelConfig) -{ /* index: 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 */ - const int n[] = {0,1,2,3,4,5,5,7,0,0, 0, 6, 7, 0, 7, 0}; +static inline int getNumberOfEffectiveChannels( + const int + channelConfig) { /* index: 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 */ + const int n[] = {0, 1, 2, 3, 4, 5, 5, 7, 0, 0, 0, 6, 7, 22, 7, 0}; return n[channelConfig]; } -#endif /* __TP_DATA_H__ */ +#endif /* TP_DATA_H */ diff --git a/libMpegTPDec/include/tpdec_lib.h b/libMpegTPDec/include/tpdec_lib.h index 2ad397d..30e53c1 100644 --- a/libMpegTPDec/include/tpdec_lib.h +++ b/libMpegTPDec/include/tpdec_lib.h @@ -1,74 +1,85 @@ - -/* ----------------------------------------------------------------------------------------------------------- +/* ----------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 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,114 +90,115 @@ Am Wolfsmantel 33 www.iis.fraunhofer.de/amm amm-info@iis.fraunhofer.de ------------------------------------------------------------------------------------------------------------ */ +----------------------------------------------------------------------------- */ + +/******************* MPEG transport format decoder library ********************* -/************************** MPEG-4 Transport Decoder *********************** + Author(s): Manuel Jander - Author(s): Manuel Jander Description: MPEG Transport decoder -******************************************************************************/ +*******************************************************************************/ -#ifndef __TPDEC_LIB_H__ -#define __TPDEC_LIB_H__ +#ifndef TPDEC_LIB_H +#define TPDEC_LIB_H #include "tp_data.h" #include "FDK_bitstream.h" -#define TRANSPORTDEC_INBUF_SIZE ( 8192 ) /*!< Size is in bytes. - Set the transport input buffer size carefully and - assure that it fulfills the requirements of the - supported transport format(s). */ - typedef enum { - TRANSPORTDEC_OK = 0, /*!< All fine. */ + TRANSPORTDEC_OK = 0, /*!< All fine. */ /* Synchronization errors. Wait for new input data and try again. */ - tpdec_sync_error_start = 0x100, - TRANSPORTDEC_NOT_ENOUGH_BITS, /*!< Out of bits. Provide more bits and try again. */ - TRANSPORTDEC_SYNC_ERROR, /*!< No sync was found or sync got lost. Keep trying. */ + tpdec_sync_error_start = 0x100, + TRANSPORTDEC_NOT_ENOUGH_BITS, /*!< Out of bits. Provide more bits and try + again. */ + TRANSPORTDEC_SYNC_ERROR, /*!< No sync was found or sync got lost. Keep trying. + */ tpdec_sync_error_end, /* Decode errors. Mostly caused due to bit errors. */ tpdec_decode_error_start = 0x400, - TRANSPORTDEC_PARSE_ERROR, /*!< Bitstream data showed inconsistencies (wrong syntax). */ - TRANSPORTDEC_UNSUPPORTED_FORMAT, /*!< Unsupported format or feature found in the bitstream data. */ - TRANSPORTDEC_CRC_ERROR, /*!< CRC error encountered in bitstream data. */ + TRANSPORTDEC_PARSE_ERROR, /*!< Bitstream data showed inconsistencies (wrong + syntax). */ + TRANSPORTDEC_UNSUPPORTED_FORMAT, /*!< Unsupported format or feature found in + the bitstream data. */ + TRANSPORTDEC_CRC_ERROR, /*!< CRC error encountered in bitstream data. */ tpdec_decode_error_end, /* Fatal errors. Stop immediately on one of these errors! */ - tpdec_fatal_error_start = 0x200, - TRANSPORTDEC_UNKOWN_ERROR, /*!< An unknown error occured. */ - TRANSPORTDEC_INVALID_PARAMETER, /*!< An invalid parameter was passed to a function. */ - TRANSPORTDEC_NEED_TO_RESTART, /*!< The decoder needs to be restarted, since the requiered - configuration change cannot be performed. */ + tpdec_fatal_error_start = 0x200, + TRANSPORTDEC_UNKOWN_ERROR, /*!< An unknown error occured. */ + TRANSPORTDEC_INVALID_PARAMETER, /*!< An invalid parameter was passed to a + function. */ + TRANSPORTDEC_NEED_TO_RESTART, /*!< The decoder needs to be restarted, since + the requiered configuration change cannot + be performed. */ + TRANSPORTDEC_TOO_MANY_BITS, /*!< In case of packet based formats: Supplied + number of bits exceed the size of the + internal bit buffer. */ tpdec_fatal_error_end } TRANSPORTDEC_ERROR; - /** Macro to identify decode errors. */ -#define TPDEC_IS_DECODE_ERROR(err) ( ((err>=tpdec_decode_error_start) && (err<=tpdec_decode_error_end)) ? 1 : 0) +#define TPDEC_IS_DECODE_ERROR(err) \ + (((err >= tpdec_decode_error_start) && (err <= tpdec_decode_error_end)) ? 1 \ + : 0) /** Macro to identify fatal errors. */ -#define TPDEC_IS_FATAL_ERROR(err) ( ((err>=tpdec_fatal_error_start) && (err<=tpdec_fatal_error_end)) ? 1 : 0) - +#define TPDEC_IS_FATAL_ERROR(err) \ + (((err >= tpdec_fatal_error_start) && (err <= tpdec_fatal_error_end)) ? 1 : 0) /** * \brief Parameter identifiers for transportDec_SetParam() */ typedef enum { - TPDEC_PARAM_MINIMIZE_DELAY = 1, /** Delay minimization strategy. 0: none, 1: discard as many frames as possible. */ - TPDEC_PARAM_EARLY_CONFIG, /** Enable early config discovery. */ - TPDEC_PARAM_IGNORE_BUFFERFULLNESS, /** Ignore buffer fullness. */ - TPDEC_PARAM_SET_BITRATE, /** Set average bit rate for bit stream interruption frame misses estimation. */ - TPDEC_PARAM_RESET, /** Reset transport decoder instance status. */ - TPDEC_PARAM_BURST_PERIOD /** Set data reception burst period in mili seconds. */ + TPDEC_PARAM_MINIMIZE_DELAY = 1, /** Delay minimization strategy. 0: none, 1: + discard as many frames as possible. */ + TPDEC_PARAM_EARLY_CONFIG, /** Enable early config discovery. */ + TPDEC_PARAM_IGNORE_BUFFERFULLNESS, /** Ignore buffer fullness. */ + TPDEC_PARAM_SET_BITRATE, /** Set average bit rate for bit stream interruption + frame misses estimation. */ + TPDEC_PARAM_RESET, /** Reset transport decoder instance status. */ + TPDEC_PARAM_BURST_PERIOD, /** Set data reception burst period in mili seconds. + */ + TPDEC_PARAM_TARGETLAYOUT, /** Set CICP target layout */ + TPDEC_PARAM_FORCE_CONFIG_CHANGE, /** Force config change for next received + config */ + TPDEC_PARAM_USE_ELEM_SKIPPING } TPDEC_PARAM; -/* ISO/IEC 14496-3 4.4.1.1 Table 4.2 Program config element */ -#define PC_FSB_CHANNELS_MAX 16 /* Front/Side/Back channels */ -#define PC_LFE_CHANNELS_MAX 4 -#define PC_ASSOCDATA_MAX 8 -#define PC_CCEL_MAX 16 /* CC elements */ -#define PC_COMMENTLENGTH 256 -#define PC_NUM_HEIGHT_LAYER 3 - - /*! \brief Reset Program Config Element. \param pPce Program Config Element structure. \return void */ -void CProgramConfig_Reset ( CProgramConfig *pPce ); +void CProgramConfig_Reset(CProgramConfig *pPce); /*! \brief Initialize Program Config Element. \param pPce Program Config Element structure. \return void */ -void CProgramConfig_Init ( CProgramConfig *pPce ); +void CProgramConfig_Init(CProgramConfig *pPce); /*! - \brief Inquire state of present Program Config Element structure. - \param pPce Program Config Element structure. - \return 1 if the PCE structure is filled correct, - 0 if no valid PCE present. + \brief Inquire state of present Program Config Element + structure. \param pPce Program Config Element structure. \return + 1 if the PCE structure is filled correct, 0 if no valid PCE present. */ -int CProgramConfig_IsValid ( const CProgramConfig *pPce ); +int CProgramConfig_IsValid(const CProgramConfig *pPce); -#ifdef TP_PCE_ENABLE /*! \brief Read Program Config Element. \param pPce Program Config Element structure. \param bs Bitstream buffer to read from. - \param alignAnchor Align bitstream to alignAnchor bits after all read operations. - \return void + \param alignAnchor Align bitstream to alignAnchor bits after all read + operations. \return void */ -void CProgramConfig_Read ( CProgramConfig *pPce, - HANDLE_FDK_BITSTREAM bs, - UINT alignAnchor ); +void CProgramConfig_Read(CProgramConfig *pPce, HANDLE_FDK_BITSTREAM bs, + UINT alignAnchor); /*! \brief Compare two Program Config Elements. @@ -194,50 +206,57 @@ void CProgramConfig_Read ( CProgramConfig *pPce, \param pPce2 Pointer to second Program Config Element structure. \return -1 if PCEs are completely different, 0 if PCEs are completely equal, - 1 if PCEs are different but have the same channel config, - 2 if PCEs have different channel config but same number of channels. + 1 if PCEs are different but have the same channel + config, 2 if PCEs have different channel config but same number of channels. */ -int CProgramConfig_Compare ( const CProgramConfig * const pPce1, - const CProgramConfig * const pPce2 ); +int CProgramConfig_Compare(const CProgramConfig *const pPce1, + const CProgramConfig *const pPce2); /*! - \brief Get a Program Config Element that matches the predefined MPEG-4 channel configurations 1-14. - \param pPce Program Config Element structure. - \param channelConfig MPEG-4 channel configuration. - \return void + \brief Get a Program Config Element that matches the predefined + MPEG-4 channel configurations 1-14. \param pPce Program Config + Element structure. \param channelConfig MPEG-4 channel configuration. \return + void */ -void CProgramConfig_GetDefault ( CProgramConfig *pPce, - const UINT channelConfig ); -#endif /* TP_PCE_ENABLE */ +void CProgramConfig_GetDefault(CProgramConfig *pPce, const UINT channelConfig); /** * \brief Lookup and verify a given element. The decoder calls this * method with every new element ID found in the bitstream. * * \param pPce A valid Program config structure. + * \param chConfig MPEG-4 channel configuration. * \param tag Tag of the current element to be looked up. * \param channelIdx The current channel count of the decoder parser. * \param chMapping Array to store the canonical channel mapping indexes. * \param chType Array to store the audio channel type. * \param chIndex Array to store the individual audio channel type index. + * \param chDescrLen Length of the output channel description array. * \param elMapping Pointer where the canonical element index is stored. * \param elType The element id of the current element to be looked up. * - * \return Non-zero if the element belongs to the current program, zero - * if it does not. - */ -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 - ); + * \return Non-zero if the element belongs to the current program, + * zero if it does not. + */ +int CProgramConfig_LookupElement(CProgramConfig *pPce, UINT chConfig, + 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); + +/** + * \brief Get table of channel indices in the order of their + * appearance in by the program config field. + * \param pPce A valid program config structure. + * \param pceChMap Array to store the channel mapping indices like they + * appear in the PCE. + * \param pceChMapLen Lenght of the channel mapping index array (pceChMap). + * + * \return Non-zero if any error occured otherwise zero. + */ +int CProgramConfig_GetPceChMap(const CProgramConfig *pPce, UCHAR pceChMap[], + const UINT pceChMapLen); /** * \brief Get table of elements in canonical order from a @@ -250,10 +269,22 @@ int CProgramConfig_LookupElement( * PCE. If none can be found it receives the value 0. * \return Total element count including all SCE, CPE and LFE. */ -int CProgramConfig_GetElementTable( const CProgramConfig *pPce, - MP4_ELEMENT_ID table[], - const INT elListSize, - UCHAR *pChMapIdx ); +int CProgramConfig_GetElementTable(const CProgramConfig *pPce, + MP4_ELEMENT_ID table[], const INT elListSize, + UCHAR *pChMapIdx); + +/** + * \brief Get channel description (type and index) for implicit + configurations (chConfig > 0) in MPEG canonical order. + * \param chConfig MPEG-4 channel configuration. + * \param chType Array to store the audio channel type. + * \param chIndex Array to store the individual audio channel type index. + * \return void + */ +void CProgramConfig_GetChannelDescription(const UINT chConfig, + const CProgramConfig *pPce, + AUDIO_CHANNEL_TYPE chType[], + UCHAR chIndex[]); /** * \brief Initialize a given AudioSpecificConfig structure. @@ -265,45 +296,50 @@ void AudioSpecificConfig_Init(CSAudioSpecificConfig *pAsc); /** * \brief Parse a AudioSpecificConfig from a given bitstream handle. * - * \param pAsc A pointer to an allocated CSAudioSpecificConfig struct. + * \param pAsc A pointer to an allocated + * CSAudioSpecificConfig struct. * \param hBs Bitstream handle. - * \param fExplicitBackwardCompatible Do explicit backward compatibility parsing if set (flag). + * \param fExplicitBackwardCompatible Do explicit backward compatibility + * parsing if set (flag). * \param cb pointer to structure holding callback information + * \param configMode Config modes: memory allocation mode or config change + * detection mode. + * \param configChanged Indicates a config change. + * \param m_aot in case of unequal AOT_NULL_OBJECT only the specific config is + * parsed. * * \return Total element count including all SCE, CPE and LFE. */ TRANSPORTDEC_ERROR AudioSpecificConfig_Parse( - CSAudioSpecificConfig *pAsc, - HANDLE_FDK_BITSTREAM hBs, - int fExplicitBackwardCompatible, - CSTpCallBacks *cb - ); + CSAudioSpecificConfig *pAsc, HANDLE_FDK_BITSTREAM hBs, + int fExplicitBackwardCompatible, CSTpCallBacks *cb, UCHAR configMode, + UCHAR configChanged, AUDIO_OBJECT_TYPE m_aot); /* CELP stuff */ -enum { - MPE = 0, - RPE = 1, - fs8KHz = 0, - fs16KHz = 1 -}; +enum { MPE = 0, RPE = 1, fs8KHz = 0, fs16KHz = 1 }; /* Defintion of flags that can be passed to transportDecOpen() */ #define TP_FLAG_MPEG4 1 /* Capability flags */ -#define CAPF_TPDEC_ADIF 0x00001000 /**< Flag indicating support for ADIF transport format. */ -#define CAPF_TPDEC_ADTS 0x00002000 /**< Flag indicating support for ADTS transport format. */ -#define CAPF_TPDEC_LOAS 0x00004000 /**< Flag indicating support for LOAS transport format. */ -#define CAPF_TPDEC_LATM 0x00008000 /**< Flag indicating support for LATM transport format. */ -#define CAPF_TPDEC_RAWPACKETS 0x00010000 /**< Flag indicating support for raw packets transport format. */ +#define CAPF_TPDEC_ADIF \ + 0x00001000 /**< Flag indicating support for ADIF transport format. */ +#define CAPF_TPDEC_ADTS \ + 0x00002000 /**< Flag indicating support for ADTS transport format. */ +#define CAPF_TPDEC_LOAS \ + 0x00004000 /**< Flag indicating support for LOAS transport format. */ +#define CAPF_TPDEC_LATM \ + 0x00008000 /**< Flag indicating support for LATM transport format. */ +#define CAPF_TPDEC_RAWPACKETS \ + 0x00010000 /**< Flag indicating support for raw packets transport format. */ typedef struct TRANSPORTDEC *HANDLE_TRANSPORTDEC; - /** - * \brief Configure Transport Decoder via a binary coded AudioSpecificConfig or StreamMuxConfig. - * The previously requested configuration callback will be called as well. The buffer conf - * must containt a SMC in case of LOAS/LATM transport format, and an ASC elseways. + * \brief Configure Transport Decoder via a binary coded AudioSpecificConfig or + * StreamMuxConfig. The previously requested configuration callback will be + * called as well. The buffer conf must containt a SMC in case of + * LOAS/LATM transport format, and an ASC elseways. * * \param hTp Handle of a transport decoder. * \param conf UCHAR buffer of the binary coded config (ASC or SMC). @@ -311,96 +347,174 @@ typedef struct TRANSPORTDEC *HANDLE_TRANSPORTDEC; * * \return Error code. */ -TRANSPORTDEC_ERROR transportDec_OutOfBandConfig( const HANDLE_TRANSPORTDEC hTp, - UCHAR *conf, - const UINT length, - const UINT layer ); +TRANSPORTDEC_ERROR transportDec_OutOfBandConfig(const HANDLE_TRANSPORTDEC hTp, + UCHAR *conf, const UINT length, + const UINT layer); + +/** + * \brief Configure Transport Decoder via a binary coded USAC/RSV603DA Config. + * The buffer newConfig contains a binary coded USAC/RSV603DA config of + * length newConfigLength bytes. If the new config and the previous config are + * different configChanged is set to 1 otherwise it is set to 0. + * + * \param hTp Handle of a transport decoder. + * \param newConfig buffer of the binary coded config. + * \param newConfigLength Length of new config in bytes. + * \param buildUpStatus Indicates build up status: off|on|idle. + * \param configChanged Indicates if config changed. + * \param layer Instance layer. + * + * \return Error code. + */ +TRANSPORTDEC_ERROR transportDec_InBandConfig( + const HANDLE_TRANSPORTDEC hTp, UCHAR *newConfig, const UINT newConfigLength, + const UCHAR buildUpStatus, UCHAR *configChanged, const UINT layer, + UCHAR *implicitExplicitCfgDiff); /** * \brief Open Transport medium for reading. * * \param transportDecFmt Format of the transport decoder medium to be accessed. - * \param flags Transport decoder flags. Currently only TP_FLAG_MPEG4, which signals a - * MPEG4 capable decoder (relevant for ADTS only). + * \param flags Transport decoder flags. Currently only TP_FLAG_MPEG4, + * which signals a MPEG4 capable decoder (relevant for ADTS only). * - * \return A pointer to a valid and allocated HANDLE_TRANSPORTDEC or a null pointer on failure. + * \return A pointer to a valid and allocated HANDLE_TRANSPORTDEC or a null + * pointer on failure. */ -HANDLE_TRANSPORTDEC transportDec_Open( TRANSPORT_TYPE transportDecFmt, - const UINT flags ); +HANDLE_TRANSPORTDEC transportDec_Open(TRANSPORT_TYPE transportDecFmt, + const UINT flags, const UINT nrOfLayer); /** * \brief Register configuration change callback. * \param hTp Handle of transport decoder. - * \param cbUpdateConfig Pointer to a callback function to handle audio config changes. - * \param user_data void pointer for user data passed to the callback as first parameter. + * \param cbUpdateConfig Pointer to a callback function to handle audio config + * changes. + * \param user_data void pointer for user data passed to the callback as + * first parameter. * \return 0 on success. */ -int transportDec_RegisterAscCallback ( - HANDLE_TRANSPORTDEC hTp, - const cbUpdateConfig_t cbUpdateConfig, - void* user_data ); +int transportDec_RegisterAscCallback(HANDLE_TRANSPORTDEC hTp, + const cbUpdateConfig_t cbUpdateConfig, + void *user_data); + +/** + * \brief Register free memory callback. + * \param hTp Handle of transport decoder. + * \param cbFreeMem Pointer to a callback function to free config dependent + * memory. + * \param user_data void pointer for user data passed to the callback as + * first parameter. + * \return 0 on success. + */ +int transportDec_RegisterFreeMemCallback(HANDLE_TRANSPORTDEC hTp, + const cbFreeMem_t cbFreeMem, + void *user_data); + +/** + * \brief Register config change control callback. + * \param hTp Handle of transport decoder. + * \param cbCtrlCFGChange Pointer to a callback function for config change + * control. + * \param user_data void pointer for user data passed to the callback as + * first parameter. + * \return 0 on success. + */ +int transportDec_RegisterCtrlCFGChangeCallback( + HANDLE_TRANSPORTDEC hTp, const cbCtrlCFGChange_t cbCtrlCFGChange, + void *user_data); /** * \brief Register SSC parser callback. * \param hTp Handle of transport decoder. * \param cbUpdateConfig Pointer to a callback function to handle SSC parsing. - * \param user_data void pointer for user data passed to the callback as first parameter. + * \param user_data void pointer for user data passed to the callback as + * first parameter. * \return 0 on success. */ -int transportDec_RegisterSscCallback ( - HANDLE_TRANSPORTDEC hTp, - const cbSsc_t cbSscParse, - void* user_data ); +int transportDec_RegisterSscCallback(HANDLE_TRANSPORTDEC hTp, + const cbSsc_t cbSscParse, void *user_data); /** * \brief Register SBR header parser callback. * \param hTp Handle of transport decoder. - * \param cbUpdateConfig Pointer to a callback function to handle SBR header parsing. - * \param user_data void pointer for user data passed to the callback as first parameter. - * \return 0 on success. + * \param cbUpdateConfig Pointer to a callback function to handle SBR header + * parsing. + * \param user_data void pointer for user data passed to the callback as + * first parameter. + * \return 0 on success. + */ +int transportDec_RegisterSbrCallback(HANDLE_TRANSPORTDEC hTpDec, + const cbSbr_t cbSbr, void *user_data); + +/** + * \brief Register USAC SC parser callback. + * \param hTp Handle of transport decoder. + * \param cbUpdateConfig Pointer to a callback function to handle USAC SC + * parsing. + * \param user_data void pointer for user data passed to the callback as + * first parameter. + * \return 0 on success. + */ +int transportDec_RegisterUsacCallback(HANDLE_TRANSPORTDEC hTpDec, + const cbUsac_t cbUsac, void *user_data); + +/** + * \brief Register uniDrcConfig and loudnessInfoSet parser + * callback. + * \param hTp Handle of transport decoder. + * \param cbUpdateConfig Pointer to a callback function to handle uniDrcConfig + * and loudnessInfoSet parsing. + * \param user_data void pointer for user data passed to the callback as + * first parameter. + * \return 0 on success. */ -int transportDec_RegisterSbrCallback( HANDLE_TRANSPORTDEC hTpDec, const cbSbr_t cbSbr, void* user_data); +int transportDec_RegisterUniDrcConfigCallback(HANDLE_TRANSPORTDEC hTpDec, + const cbUniDrc_t cbUniDrc, + void *user_data, + UINT *pLoudnessInfoSetPosition); /** - * \brief Fill internal input buffer with bitstream data from the external input buffer. - * The function only copies such data as long as the decoder-internal input buffer is not full. - * So it grabs whatever it can from pBuffer and returns information (bytesValid) so that at a - * subsequent call of %transportDec_FillData(), the right position in pBuffer can be determined to + * \brief Fill internal input buffer with bitstream data from the external input + * buffer. The function only copies such data as long as the decoder-internal + * input buffer is not full. So it grabs whatever it can from pBuffer and + * returns information (bytesValid) so that at a subsequent call of + * %transportDec_FillData(), the right position in pBuffer can be determined to * grab the next data. * * \param hTp Handle of transportDec. * \param pBuffer Pointer to external input buffer. - * \param bufferSize Size of external input buffer. This argument is required because decoder-internally - * we need the information to calculate the offset to pBuffer, where the next - * available data is, which is then fed into the decoder-internal buffer (as much - * as possible). Our example framework implementation fills the buffer at pBuffer - * again, once it contains no available valid bytes anymore (meaning bytesValid equal 0). - * \param bytesValid Number of bitstream bytes in the external bitstream buffer that have not yet been - * copied into the decoder's internal bitstream buffer by calling this function. - * The value is updated according to the amount of newly copied bytes. + * \param bufferSize Size of external input buffer. This argument is required + * because decoder-internally we need the information to calculate the offset to + * pBuffer, where the next available data is, which is then + * fed into the decoder-internal buffer (as much as + * possible). Our example framework implementation fills the + * buffer at pBuffer again, once it contains no available valid bytes anymore + * (meaning bytesValid equal 0). + * \param bytesValid Number of bitstream bytes in the external bitstream buffer + * that have not yet been copied into the decoder's internal bitstream buffer by + * calling this function. The value is updated according to + * the amount of newly copied bytes. * \param layer The layer the bitstream belongs to. * \return Error code. */ -TRANSPORTDEC_ERROR transportDec_FillData( - const HANDLE_TRANSPORTDEC hTp, - UCHAR *pBuffer, - const UINT bufferSize, - UINT *pBytesValid, - const INT layer ); +TRANSPORTDEC_ERROR transportDec_FillData(const HANDLE_TRANSPORTDEC hTp, + UCHAR *pBuffer, const UINT bufferSize, + UINT *pBytesValid, const INT layer); /** * \brief Get transportDec bitstream handle. * \param hTp Pointer to a transport decoder handle. * \return HANDLE_FDK_BITSTREAM bitstream handle. */ -HANDLE_FDK_BITSTREAM transportDec_GetBitstream ( const HANDLE_TRANSPORTDEC hTp, const UINT layer ); +HANDLE_FDK_BITSTREAM transportDec_GetBitstream(const HANDLE_TRANSPORTDEC hTp, + const UINT layer); /** * \brief Get transport format. * \param hTp Pointer to a transport decoder handle. * \return The transport format. */ -TRANSPORT_TYPE transportDec_GetFormat ( const HANDLE_TRANSPORTDEC hTp ); +TRANSPORT_TYPE transportDec_GetFormat(const HANDLE_TRANSPORTDEC hTp); /** * \brief Get the current buffer fullness value. @@ -409,60 +523,76 @@ TRANSPORT_TYPE transportDec_GetFormat ( const HANDLE_TRANSPORTDEC hTp ); * * \return Buffer fullness */ -INT transportDec_GetBufferFullness( const HANDLE_TRANSPORTDEC hTp ); +INT transportDec_GetBufferFullness(const HANDLE_TRANSPORTDEC hTp); /** * \brief Close and deallocate transportDec. * \param phTp Pointer to a previously allocated transport decoder handle. * \return void */ -void transportDec_Close ( HANDLE_TRANSPORTDEC *phTp ); +void transportDec_Close(HANDLE_TRANSPORTDEC *phTp); /** * \brief Read one access unit from the transportDec medium. * \param hTp Handle of transportDec. - * \param length On return, this value is overwritten with the actual access unit length in bits. - * Set to -1 if length is unknown. + * \param length On return, this value is overwritten with the actual access + * unit length in bits. Set to -1 if length is unknown. * \return Error code. */ -TRANSPORTDEC_ERROR transportDec_ReadAccessUnit ( const HANDLE_TRANSPORTDEC hTp, const UINT layer ); +TRANSPORTDEC_ERROR transportDec_ReadAccessUnit(const HANDLE_TRANSPORTDEC hTp, + const UINT layer); /** - * \brief Get the remaining amount of bits of the current access unit. The result - * can be below zero, meaning that too many bits have been read. + * \brief Get AudioSpecificConfig. + * \param hTp Handle of transportDec. + * \param layer Transport layer. + * \param asc Pointer to AudioSpecificConfig. + * \return Error code. + */ +TRANSPORTDEC_ERROR transportDec_GetAsc(const HANDLE_TRANSPORTDEC hTp, + const UINT layer, + CSAudioSpecificConfig *asc); + +/** + * \brief Get the remaining amount of bits of the current access unit. The + * result can be below zero, meaning that too many bits have been read. * \param hTp Handle of transportDec. * \return amount of remaining bits. */ -INT transportDec_GetAuBitsRemaining( const HANDLE_TRANSPORTDEC hTp, const UINT layer ); +INT transportDec_GetAuBitsRemaining(const HANDLE_TRANSPORTDEC hTp, + const UINT layer); /** * \brief Get the total amount of bits of the current access unit. * \param hTp Handle of transportDec. * \return amount of total bits. */ -INT transportDec_GetAuBitsTotal( const HANDLE_TRANSPORTDEC hTp, const UINT layer ); +INT transportDec_GetAuBitsTotal(const HANDLE_TRANSPORTDEC hTp, + const UINT layer); /** - * \brief This function is required to be called when the decoder has finished parsing - * one Access Unit for bitstream housekeeping. + * \brief This function is required to be called when the decoder has + * finished parsing one Access Unit for bitstream housekeeping. * \param hTp Transport Handle. * \return Error code. */ -TRANSPORTDEC_ERROR transportDec_EndAccessUnit ( const HANDLE_TRANSPORTDEC hTp ); +TRANSPORTDEC_ERROR transportDec_EndAccessUnit(const HANDLE_TRANSPORTDEC hTp); /** - * \brief Obtain the amount of missing access units if applicable in case of - * a bit stream synchronization error. Each time transportDec_ReadAccessUnit() - * returns TRANSPORTDEC_SYNC_ERROR this function can be called to retrieve an estimate - * of the amount of missing access units. This works only in case of constant average - * bit rate (has to be known) and if the parameter TPDEC_PARAM_SET_BITRATE has been set - * accordingly. + * \brief Obtain the amount of missing access units if applicable in case + * of a bit stream synchronization error. Each time + * transportDec_ReadAccessUnit() returns TRANSPORTDEC_SYNC_ERROR + * this function can be called to retrieve an estimate of the amount + * of missing access units. This works only in case of constant + * average bit rate (has to be known) and if the parameter + * TPDEC_PARAM_SET_BITRATE has been set accordingly. * \param hTp Transport Handle. - * \param pNAccessUnits pointer to a memory location where the estimated lost frame count will be stored into. + * \param pNAccessUnits pointer to a memory location where the estimated lost + * frame count will be stored into. * \return Error code. */ -TRANSPORTDEC_ERROR transportDec_GetMissingAccessUnitCount ( INT *pNAccessUnits, HANDLE_TRANSPORTDEC hTp ); - +TRANSPORTDEC_ERROR transportDec_GetMissingAccessUnitCount( + INT *pNAccessUnits, HANDLE_TRANSPORTDEC hTp); /** * \brief Set a given setting. @@ -471,35 +601,36 @@ TRANSPORTDEC_ERROR transportDec_GetMissingAccessUnitCount ( INT *pNAccessUnits, * \param value Value for the parameter to be changed. * \return Error code. */ -TRANSPORTDEC_ERROR transportDec_SetParam ( const HANDLE_TRANSPORTDEC hTp, - const TPDEC_PARAM param, - const INT value ); +TRANSPORTDEC_ERROR transportDec_SetParam(const HANDLE_TRANSPORTDEC hTp, + const TPDEC_PARAM param, + const INT value); /** * \brief Get number of subframes (for LATM or ADTS) * \param hTp Transport Handle. - * \return Number of ADTS/LATM subframes (return 1 for all other transport types). + * \return Number of ADTS/LATM subframes (return 1 for all other transport + * types). */ UINT transportDec_GetNrOfSubFrames(HANDLE_TRANSPORTDEC hTp); - /** * \brief Get info structure of transport decoder library. * \param info A pointer to an allocated LIB_INFO struct. * \return Error code. */ -TRANSPORTDEC_ERROR transportDec_GetLibInfo( LIB_INFO *info ); +TRANSPORTDEC_ERROR transportDec_GetLibInfo(LIB_INFO *info); /* ADTS CRC support */ /** * \brief Set current bitstream position as start of a new data region. * \param hTp Transport handle. - * \param mBits Size in bits of the data region. Set to 0 if it should not be of a fixed size. - * \return Data region ID, which should be used when calling transportDec_CrcEndReg(). + * \param mBits Size in bits of the data region. Set to 0 if it should not be + * of a fixed size. + * \return Data region ID, which should be used when calling + * transportDec_CrcEndReg(). */ -int transportDec_CrcStartReg ( const HANDLE_TRANSPORTDEC hTp, - const INT mBits ); +int transportDec_CrcStartReg(const HANDLE_TRANSPORTDEC hTp, const INT mBits); /** * \brief Set end of data region. @@ -507,15 +638,27 @@ int transportDec_CrcStartReg ( const HANDLE_TRANSPORTDEC hTp, * \param reg Data region ID, opbtained from transportDec_CrcStartReg(). * \return void */ -void transportDec_CrcEndReg ( const HANDLE_TRANSPORTDEC hTp, - const INT reg ); +void transportDec_CrcEndReg(const HANDLE_TRANSPORTDEC hTp, const INT reg); /** - * \brief Calculate ADTS crc and check if it is correct. The ADTS checksum is held internally. + * \brief Calculate ADTS crc and check if it is correct. The ADTS checksum + * is held internally. * \param hTp Transport handle. - * \return Return TRANSPORTDEC_OK if the CRC is ok, or error if CRC is not correct. + * \return Return TRANSPORTDEC_OK if the CRC is ok, or error if CRC is not + * correct. */ -TRANSPORTDEC_ERROR transportDec_CrcCheck ( const HANDLE_TRANSPORTDEC hTp ); +TRANSPORTDEC_ERROR transportDec_CrcCheck(const HANDLE_TRANSPORTDEC hTp); +/** + * \brief Only check whether a given config seems to be valid without modifying + * internal states. + * + * \param conf UCHAR buffer of the binary coded config (SDC type 9). + * \param length The length in bytes of the conf buffer. + * + * \return Error code. + */ +TRANSPORTDEC_ERROR transportDec_DrmRawSdcAudioConfig_Check(UCHAR *conf, + const UINT length); -#endif /* #ifndef __TPDEC_LIB_H__ */ +#endif /* #ifndef TPDEC_LIB_H */ diff --git a/libMpegTPDec/src/mpegFileFormat.h b/libMpegTPDec/src/mpegFileFormat.h deleted file mode 100644 index b0cfe9e..0000000 --- a/libMpegTPDec/src/mpegFileFormat.h +++ /dev/null @@ -1,114 +0,0 @@ - -/* ----------------------------------------------------------------------------------------------------------- -Software License for The Fraunhofer FDK AAC Codec Library for Android - -© Copyright 1995 - 2013 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. - -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: - -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 -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. - -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." - -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. - -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. - -5. CONTACT INFORMATION - -Fraunhofer Institute for Integrated Circuits IIS -Attention: Audio and Multimedia Departments - FDK AAC LL -Am Wolfsmantel 33 -91058 Erlangen, Germany - -www.iis.fraunhofer.de/amm -amm-info@iis.fraunhofer.de ------------------------------------------------------------------------------------------------------------ */ - -/*************************** Fraunhofer IIS FDK Tools *********************** - - Author(s): Oliver Moser - Description: bitstream format detection routines - -******************************************************************************/ - -#if !defined(__BITSTREAM_FORMAT_H__) -#define __BITSTREAM_FORMAT_H__ - -#include "machine_type.h" -#include "FDK_audio.h" - -/** - * \brief Try to find out the format of a file, given the few first bytes. - * \param fileData pointer to a buffer holding the first bytes of a file. - * \param pAu pointer to UCHAR*, returns the address of the first AU found or NULL. - * \param length pointer to the length of the buffer fileData. Return length of first AU. - * \return the detected file format, or FF_UNKNOWN in case of failure. - */ -FILE_FORMAT GetFileFormat(UCHAR *fileData, UCHAR **pAu, UINT *length); - -/** - * \brief Try to find out the transport type contained in a given file. - * \param filename name of the file to be analysed. - * \param fileFormat pointer to a variable where the detected file format is stored into. - * \return the detected transport type or TT_UNKNOWN in case of failure. - */ -TRANSPORT_TYPE GetTransportType(const char* filename, FILE_FORMAT *fileFormat); - -#endif diff --git a/libMpegTPDec/src/tp_version.h b/libMpegTPDec/src/tp_version.h new file mode 100644 index 0000000..4faed8c --- /dev/null +++ b/libMpegTPDec/src/tp_version.h @@ -0,0 +1,118 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© 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. + +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: + +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 +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. + +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." + +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. + +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. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* MPEG transport format decoder library ********************* + + Author(s): + + Description: + +*******************************************************************************/ + +#if !defined(TP_VERSION_H) +#define TP_VERSION_H + +/* library info */ +#define TP_LIB_VL0 3 +#define TP_LIB_VL1 0 +#define TP_LIB_VL2 0 +#define TP_LIB_TITLE "MPEG Transport" +#ifdef __ANDROID__ +#define TP_LIB_BUILD_DATE "" +#define TP_LIB_BUILD_TIME "" +#else +#define TP_LIB_BUILD_DATE __DATE__ +#define TP_LIB_BUILD_TIME __TIME__ +#endif +#endif /* !defined(TP_VERSION_H) */ diff --git a/libMpegTPDec/src/tpdec_adif.cpp b/libMpegTPDec/src/tpdec_adif.cpp index 237e881..ec20b9b 100644 --- a/libMpegTPDec/src/tpdec_adif.cpp +++ b/libMpegTPDec/src/tpdec_adif.cpp @@ -1,74 +1,85 @@ - -/* ----------------------------------------------------------------------------------------------------------- +/* ----------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 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,27 +90,24 @@ Am Wolfsmantel 33 www.iis.fraunhofer.de/amm amm-info@iis.fraunhofer.de ------------------------------------------------------------------------------------------------------------ */ +----------------------------------------------------------------------------- */ -/***************************** MPEG-4 AAC Decoder ************************** +/******************* MPEG transport format decoder library ********************* Author(s): Josef Hoepfl + Description: ADIF reader -******************************************************************************/ +*******************************************************************************/ #include "tpdec_adif.h" - #include "FDK_bitstream.h" #include "genericStds.h" -TRANSPORTDEC_ERROR adifRead_DecodeHeader( - CAdifHeader *pAdifHeader, - CProgramConfig *pPce, - HANDLE_FDK_BITSTREAM bs - ) -{ +TRANSPORTDEC_ERROR adifRead_DecodeHeader(CAdifHeader *pAdifHeader, + CProgramConfig *pPce, + HANDLE_FDK_BITSTREAM bs) { int i; TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK; UINT startAnchor = FDKgetValidBits(bs); @@ -108,41 +116,39 @@ TRANSPORTDEC_ERROR adifRead_DecodeHeader( return (TRANSPORTDEC_NOT_ENOUGH_BITS); } - if (FDKreadBits(bs,8) != 'A') { + if (FDKreadBits(bs, 8) != 'A') { return (TRANSPORTDEC_SYNC_ERROR); } - if (FDKreadBits(bs,8) != 'D') { + if (FDKreadBits(bs, 8) != 'D') { return (TRANSPORTDEC_SYNC_ERROR); } - if (FDKreadBits(bs,8) != 'I') { + if (FDKreadBits(bs, 8) != 'I') { return (TRANSPORTDEC_SYNC_ERROR); } - if (FDKreadBits(bs,8) != 'F') { + if (FDKreadBits(bs, 8) != 'F') { return (TRANSPORTDEC_SYNC_ERROR); } - if ( (pAdifHeader->CopyrightIdPresent = FDKreadBits(bs,1)) != 0 ) - FDKpushBiDirectional(bs,72); /* CopyrightId */ - + if ((pAdifHeader->CopyrightIdPresent = FDKreadBits(bs, 1)) != 0) + FDKpushBiDirectional(bs, 72); /* CopyrightId */ - pAdifHeader->OriginalCopy = FDKreadBits(bs,1); - pAdifHeader->Home = FDKreadBits(bs,1); - pAdifHeader->BitstreamType = FDKreadBits(bs,1); + pAdifHeader->OriginalCopy = FDKreadBits(bs, 1); + pAdifHeader->Home = FDKreadBits(bs, 1); + pAdifHeader->BitstreamType = FDKreadBits(bs, 1); /* pAdifHeader->BitRate = FDKreadBits(bs, 23); */ - pAdifHeader->BitRate = FDKreadBits(bs,16); + pAdifHeader->BitRate = FDKreadBits(bs, 16); pAdifHeader->BitRate <<= 7; - pAdifHeader->BitRate |= FDKreadBits(bs,7); + pAdifHeader->BitRate |= FDKreadBits(bs, 7); - pAdifHeader->NumProgramConfigElements = FDKreadBits(bs,4) + 1; + pAdifHeader->NumProgramConfigElements = FDKreadBits(bs, 4) + 1; if (pAdifHeader->BitstreamType == 0) { - FDKpushBiDirectional(bs,20); /* adif_buffer_fullness */ + FDKpushBiDirectional(bs, 20); /* adif_buffer_fullness */ } /* Parse all PCEs but keep only one */ - for (i=0; i < pAdifHeader->NumProgramConfigElements; i++) - { + for (i = 0; i < pAdifHeader->NumProgramConfigElements; i++) { CProgramConfig_Read(pPce, bs, startAnchor); } @@ -150,6 +156,3 @@ TRANSPORTDEC_ERROR adifRead_DecodeHeader( return (ErrorStatus); } - - - diff --git a/libMpegTPDec/src/tpdec_adif.h b/libMpegTPDec/src/tpdec_adif.h index d6780a7..72ccc6a 100644 --- a/libMpegTPDec/src/tpdec_adif.h +++ b/libMpegTPDec/src/tpdec_adif.h @@ -1,74 +1,85 @@ - -/* ----------------------------------------------------------------------------------------------------------- +/* ----------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 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,24 +90,24 @@ Am Wolfsmantel 33 www.iis.fraunhofer.de/amm amm-info@iis.fraunhofer.de ------------------------------------------------------------------------------------------------------------ */ +----------------------------------------------------------------------------- */ -/***************************** MPEG-4 AAC Decoder ************************** +/******************* MPEG transport format decoder library ********************* Author(s): Josef Hoepfl + Description: ADIF reader -******************************************************************************/ +*******************************************************************************/ #ifndef TPDEC_ADIF_H #define TPDEC_ADIF_H #include "tpdec_lib.h" -#define MIN_ADIF_HEADERLENGTH 63 /* in bits */ +#define MIN_ADIF_HEADERLENGTH 63 /* in bits */ -typedef struct -{ +typedef struct { INT NumProgramConfigElements; UINT BitRate; UCHAR CopyrightIdPresent; @@ -106,18 +117,18 @@ typedef struct } CAdifHeader; /** - * \brief Parse a ADIF header at the given bitstream and store the parsed data into a given CAdifHeader - * and CProgramConfig struct + * \brief Parse a ADIF header at the given bitstream and store the parsed data + * into a given CAdifHeader and CProgramConfig struct * - * \param pAdifHeader pointer to a CAdifHeader structure to hold the parsed ADIF header data. - * \param pPce pointer to a CProgramConfig structure where the last PCE will remain. + * \param pAdifHeader pointer to a CAdifHeader structure to hold the parsed ADIF + * header data. + * \param pPce pointer to a CProgramConfig structure where the last PCE will + * remain. * * \return TRANSPORTDEC_ERROR error code */ -TRANSPORTDEC_ERROR adifRead_DecodeHeader( - CAdifHeader *pAdifHeader, - CProgramConfig *pPce, - HANDLE_FDK_BITSTREAM bs - ); +TRANSPORTDEC_ERROR adifRead_DecodeHeader(CAdifHeader *pAdifHeader, + CProgramConfig *pPce, + HANDLE_FDK_BITSTREAM bs); #endif /* TPDEC_ADIF_H */ diff --git a/libMpegTPDec/src/tpdec_adts.cpp b/libMpegTPDec/src/tpdec_adts.cpp index c455681..6dc0275 100644 --- a/libMpegTPDec/src/tpdec_adts.cpp +++ b/libMpegTPDec/src/tpdec_adts.cpp @@ -1,74 +1,85 @@ - -/* ----------------------------------------------------------------------------------------------------------- +/* ----------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 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,96 +90,83 @@ Am Wolfsmantel 33 www.iis.fraunhofer.de/amm amm-info@iis.fraunhofer.de ------------------------------------------------------------------------------------------------------------ */ +----------------------------------------------------------------------------- */ -/***************************** MPEG-4 AAC Decoder ************************** +/******************* MPEG transport format decoder library ********************* Author(s): Josef Hoepfl + Description: ADTS interface -******************************************************************************/ +*******************************************************************************/ #include "tpdec_adts.h" - #include "FDK_bitstream.h" - - -void adtsRead_CrcInit(HANDLE_ADTS pAdts) /*!< pointer to adts crc info stucture */ +void adtsRead_CrcInit( + HANDLE_ADTS pAdts) /*!< pointer to adts crc info stucture */ { FDKcrcInit(&pAdts->crcInfo, 0x8005, 0xFFFF, 16); } int adtsRead_CrcStartReg( - HANDLE_ADTS pAdts, /*!< pointer to adts stucture */ - HANDLE_FDK_BITSTREAM hBs, /*!< handle to current bit buffer structure */ - int mBits /*!< number of bits in crc region */ - ) -{ + HANDLE_ADTS pAdts, /*!< pointer to adts stucture */ + HANDLE_FDK_BITSTREAM hBs, /*!< handle to current bit buffer structure */ + int mBits /*!< number of bits in crc region */ +) { if (pAdts->bs.protection_absent) { return 0; } - return ( FDKcrcStartReg(&pAdts->crcInfo, hBs, mBits) ); - + return (FDKcrcStartReg(&pAdts->crcInfo, hBs, mBits)); } void adtsRead_CrcEndReg( - HANDLE_ADTS pAdts, /*!< pointer to adts crc info stucture */ - HANDLE_FDK_BITSTREAM hBs, /*!< handle to current bit buffer structure */ - int reg /*!< crc region */ - ) -{ - if (pAdts->bs.protection_absent == 0) - { + HANDLE_ADTS pAdts, /*!< pointer to adts crc info stucture */ + HANDLE_FDK_BITSTREAM hBs, /*!< handle to current bit buffer structure */ + int reg /*!< crc region */ +) { + if (pAdts->bs.protection_absent == 0) { FDKcrcEndReg(&pAdts->crcInfo, hBs, reg); } } -TRANSPORTDEC_ERROR adtsRead_CrcCheck( HANDLE_ADTS pAdts ) -{ +TRANSPORTDEC_ERROR adtsRead_CrcCheck(HANDLE_ADTS pAdts) { TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK; USHORT crc; - if (pAdts->bs.protection_absent) - return TRANSPORTDEC_OK; + if (pAdts->bs.protection_absent) return TRANSPORTDEC_OK; crc = FDKcrcGetCRC(&pAdts->crcInfo); - if (crc != pAdts->crcReadValue) - { + if (crc != pAdts->crcReadValue) { return (TRANSPORTDEC_CRC_ERROR); } return (ErrorStatus); } - - -#define Adts_Length_SyncWord 12 -#define Adts_Length_Id 1 -#define Adts_Length_Layer 2 -#define Adts_Length_ProtectionAbsent 1 -#define Adts_Length_Profile 2 -#define Adts_Length_SamplingFrequencyIndex 4 -#define Adts_Length_PrivateBit 1 -#define Adts_Length_ChannelConfiguration 3 -#define Adts_Length_OriginalCopy 1 -#define Adts_Length_Home 1 -#define Adts_Length_CopyrightIdentificationBit 1 -#define Adts_Length_CopyrightIdentificationStart 1 -#define Adts_Length_FrameLength 13 -#define Adts_Length_BufferFullness 11 -#define Adts_Length_NumberOfRawDataBlocksInFrame 2 -#define Adts_Length_CrcCheck 16 - -TRANSPORTDEC_ERROR adtsRead_DecodeHeader( - HANDLE_ADTS pAdts, - CSAudioSpecificConfig *pAsc, - HANDLE_FDK_BITSTREAM hBs, - const INT ignoreBufferFullness - ) -{ +#define Adts_Length_SyncWord 12 +#define Adts_Length_Id 1 +#define Adts_Length_Layer 2 +#define Adts_Length_ProtectionAbsent 1 +#define Adts_Length_Profile 2 +#define Adts_Length_SamplingFrequencyIndex 4 +#define Adts_Length_PrivateBit 1 +#define Adts_Length_ChannelConfiguration 3 +#define Adts_Length_OriginalCopy 1 +#define Adts_Length_Home 1 +#define Adts_Length_CopyrightIdentificationBit 1 +#define Adts_Length_CopyrightIdentificationStart 1 +#define Adts_Length_FrameLength 13 +#define Adts_Length_BufferFullness 11 +#define Adts_Length_NumberOfRawDataBlocksInFrame 2 +#define Adts_Length_CrcCheck 16 + +TRANSPORTDEC_ERROR adtsRead_DecodeHeader(HANDLE_ADTS pAdts, + CSAudioSpecificConfig *pAsc, + HANDLE_FDK_BITSTREAM hBs, + const INT ignoreBufferFullness) { INT crcReg; INT valBits; @@ -177,58 +175,58 @@ TRANSPORTDEC_ERROR adtsRead_DecodeHeader( STRUCT_ADTS_BS bs; -#ifdef TP_PCE_ENABLE CProgramConfig oldPce; /* Store the old PCE temporarily. Maybe we'll need it later if we have channelConfig=0 and no PCE in this frame. */ FDKmemcpy(&oldPce, &pAsc->m_progrConfigElement, sizeof(CProgramConfig)); -#endif valBits = FDKgetValidBits(hBs); /* adts_fixed_header */ - bs.mpeg_id = FDKreadBits(hBs, Adts_Length_Id); - bs.layer = FDKreadBits(hBs, Adts_Length_Layer); + bs.mpeg_id = FDKreadBits(hBs, Adts_Length_Id); + bs.layer = FDKreadBits(hBs, Adts_Length_Layer); bs.protection_absent = FDKreadBits(hBs, Adts_Length_ProtectionAbsent); - bs.profile = FDKreadBits(hBs, Adts_Length_Profile); + bs.profile = FDKreadBits(hBs, Adts_Length_Profile); bs.sample_freq_index = FDKreadBits(hBs, Adts_Length_SamplingFrequencyIndex); - bs.private_bit = FDKreadBits(hBs, Adts_Length_PrivateBit); - bs.channel_config = FDKreadBits(hBs, Adts_Length_ChannelConfiguration); - bs.original = FDKreadBits(hBs, Adts_Length_OriginalCopy); - bs.home = FDKreadBits(hBs, Adts_Length_Home); + bs.private_bit = FDKreadBits(hBs, Adts_Length_PrivateBit); + bs.channel_config = FDKreadBits(hBs, Adts_Length_ChannelConfiguration); + bs.original = FDKreadBits(hBs, Adts_Length_OriginalCopy); + bs.home = FDKreadBits(hBs, Adts_Length_Home); /* adts_variable_header */ - bs.copyright_id = FDKreadBits(hBs, Adts_Length_CopyrightIdentificationBit); - bs.copyright_start = FDKreadBits(hBs, Adts_Length_CopyrightIdentificationStart); - bs.frame_length = FDKreadBits(hBs, Adts_Length_FrameLength); - bs.adts_fullness = FDKreadBits(hBs, Adts_Length_BufferFullness); - bs.num_raw_blocks = FDKreadBits(hBs, Adts_Length_NumberOfRawDataBlocksInFrame); - bs.num_pce_bits = 0; + bs.copyright_id = FDKreadBits(hBs, Adts_Length_CopyrightIdentificationBit); + bs.copyright_start = + FDKreadBits(hBs, Adts_Length_CopyrightIdentificationStart); + bs.frame_length = FDKreadBits(hBs, Adts_Length_FrameLength); + bs.adts_fullness = FDKreadBits(hBs, Adts_Length_BufferFullness); + bs.num_raw_blocks = + FDKreadBits(hBs, Adts_Length_NumberOfRawDataBlocksInFrame); + bs.num_pce_bits = 0; adtsHeaderLength = ADTS_HEADERLENGTH; if (!bs.protection_absent) { FDKcrcReset(&pAdts->crcInfo); - FDKpushBack(hBs, 56); /* complete fixed and variable header! */ + FDKpushBack(hBs, 56); /* complete fixed and variable header! */ crcReg = FDKcrcStartReg(&pAdts->crcInfo, hBs, 0); FDKpushFor(hBs, 56); } - if (! bs.protection_absent && bs.num_raw_blocks>0) { - for (i=0; i<bs.num_raw_blocks; i++) { + if (!bs.protection_absent && bs.num_raw_blocks > 0) { + for (i = 0; i < bs.num_raw_blocks; i++) { pAdts->rawDataBlockDist[i] = (USHORT)FDKreadBits(hBs, 16); adtsHeaderLength += 16; } /* Change raw data blocks to delta values */ - pAdts->rawDataBlockDist[bs.num_raw_blocks] = bs.frame_length - 7 - bs.num_raw_blocks*2 - 2 ; - for (i=bs.num_raw_blocks; i>0; i--) { - pAdts->rawDataBlockDist[i] -= pAdts->rawDataBlockDist[i-1]; + pAdts->rawDataBlockDist[bs.num_raw_blocks] = + bs.frame_length - 7 - bs.num_raw_blocks * 2 - 2; + for (i = bs.num_raw_blocks; i > 0; i--) { + pAdts->rawDataBlockDist[i] -= pAdts->rawDataBlockDist[i - 1]; } } /* adts_error_check */ - if (!bs.protection_absent) - { + if (!bs.protection_absent) { USHORT crc_check; FDKcrcEndReg(&pAdts->crcInfo, hBs, crcReg); @@ -246,75 +244,63 @@ TRANSPORTDEC_ERROR adtsRead_DecodeHeader( } } - /* check if valid header */ - if ( - (bs.layer != 0) || // we only support MPEG ADTS - (bs.sample_freq_index >= 13) // we only support 96kHz - 7350kHz - ) { - FDKpushFor(hBs, bs.frame_length * 8); // try again one frame later + if ((bs.layer != 0) || // we only support MPEG ADTS + (bs.sample_freq_index >= 13) // we only support 96kHz - 7350kHz + ) { + FDKpushFor(hBs, bs.frame_length * 8); // try again one frame later return TRANSPORTDEC_UNSUPPORTED_FORMAT; } /* special treatment of id-bit */ - if ( (bs.mpeg_id == 0) && (pAdts->decoderCanDoMpeg4 == 0) ) - { + if ((bs.mpeg_id == 0) && (pAdts->decoderCanDoMpeg4 == 0)) { /* MPEG-2 decoder cannot play MPEG-4 bitstreams */ - FDKpushFor(hBs, bs.frame_length * 8); // try again one frame later return TRANSPORTDEC_UNSUPPORTED_FORMAT; } - if (!ignoreBufferFullness) - { - cmp_buffer_fullness = bs.frame_length*8 + bs.adts_fullness*32*getNumberOfEffectiveChannels(bs.channel_config); - + if (!ignoreBufferFullness) { + cmp_buffer_fullness = + bs.frame_length * 8 + + bs.adts_fullness * 32 * getNumberOfEffectiveChannels(bs.channel_config); /* Evaluate buffer fullness */ - if (bs.adts_fullness != 0x7FF) - { - if (pAdts->BufferFullnesStartFlag) - { - if ( valBits < cmp_buffer_fullness ) - { + if (bs.adts_fullness != 0x7FF) { + if (pAdts->BufferFullnesStartFlag) { + if (valBits < cmp_buffer_fullness) { /* Condition for start of decoding is not fulfilled */ /* The current frame will not be decoded */ FDKpushBack(hBs, adtsHeaderLength); - if ( (cmp_buffer_fullness+adtsHeaderLength) > ((TRANSPORTDEC_INBUF_SIZE<<3)-7) ) { + if ((cmp_buffer_fullness + adtsHeaderLength) > + (((8192 * 4) << 3) - 7)) { return TRANSPORTDEC_SYNC_ERROR; } else { return TRANSPORTDEC_NOT_ENOUGH_BITS; } - } - else - { + } else { pAdts->BufferFullnesStartFlag = 0; } } } } - /* Get info from ADTS header */ AudioSpecificConfig_Init(pAsc); - pAsc->m_aot = (AUDIO_OBJECT_TYPE)(bs.profile + 1); + pAsc->m_aot = (AUDIO_OBJECT_TYPE)(bs.profile + 1); pAsc->m_samplingFrequencyIndex = bs.sample_freq_index; - pAsc->m_samplingFrequency = SamplingRateTable[bs.sample_freq_index]; - pAsc->m_channelConfiguration = bs.channel_config; - pAsc->m_samplesPerFrame = 1024; + pAsc->m_samplingFrequency = SamplingRateTable[bs.sample_freq_index]; + pAsc->m_channelConfiguration = bs.channel_config; + pAsc->m_samplesPerFrame = 1024; -#ifdef TP_PCE_ENABLE - if (bs.channel_config == 0) - { + if (bs.channel_config == 0) { int pceBits = 0; UINT alignAnchor = FDKgetValidBits(hBs); - - if (FDKreadBits(hBs,3) == ID_PCE) { + + if (FDKreadBits(hBs, 3) == ID_PCE) { /* Got luck! Parse the PCE */ - int crcReg; crcReg = adtsRead_CrcStartReg(pAdts, hBs, 0); CProgramConfig_Read(&pAsc->m_progrConfigElement, hBs, alignAnchor); @@ -323,25 +309,26 @@ TRANSPORTDEC_ERROR adtsRead_DecodeHeader( pceBits = alignAnchor - FDKgetValidBits(hBs); /* store the number of PCE bits */ bs.num_pce_bits = pceBits; - } - else { + } else { /* No PCE in this frame! Push back the ID tag bits. */ - FDKpushBack(hBs,3); + FDKpushBack(hBs, 3); /* Encoders do not have to write a PCE in each frame. So if we already have a valid PCE we have to use it. */ - if ( oldPce.isValid - && (bs.sample_freq_index == pAdts->bs.sample_freq_index) /* we could compare the complete fixed header (bytes) here! */ - && (bs.channel_config == pAdts->bs.channel_config) /* == 0 */ - && (bs.mpeg_id == pAdts->bs.mpeg_id) ) - { /* Restore previous PCE which is still valid */ + if (oldPce.isValid && + (bs.sample_freq_index == + pAdts->bs.sample_freq_index) /* we could compare the complete fixed + header (bytes) here! */ + && (bs.channel_config == pAdts->bs.channel_config) /* == 0 */ + && + (bs.mpeg_id == + pAdts->bs.mpeg_id)) { /* Restore previous PCE which is still valid */ FDKmemcpy(&pAsc->m_progrConfigElement, &oldPce, sizeof(CProgramConfig)); - } - else if (bs.mpeg_id == 0) { + } else if (bs.mpeg_id == 0) { /* If not it seems that we have a implicit channel configuration. This mode is not allowed in the context of ISO/IEC 14496-3. Skip this frame and try the next one. */ - FDKpushFor(hBs, (bs.frame_length<<3) - adtsHeaderLength - 3); + FDKpushFor(hBs, (bs.frame_length << 3) - adtsHeaderLength - 3); return TRANSPORTDEC_UNSUPPORTED_FORMAT; } /* else { @@ -350,33 +337,32 @@ TRANSPORTDEC_ERROR adtsRead_DecodeHeader( } */ } } -#endif /* TP_PCE_ENABLE */ - /* Copy bit stream data struct to persistent memory now, once we passed all sanity checks above. */ + /* Copy bit stream data struct to persistent memory now, once we passed all + * sanity checks above. */ FDKmemcpy(&pAdts->bs, &bs, sizeof(STRUCT_ADTS_BS)); return TRANSPORTDEC_OK; } -int adtsRead_GetRawDataBlockLength( - HANDLE_ADTS pAdts, - INT blockNum - ) -{ +int adtsRead_GetRawDataBlockLength(HANDLE_ADTS pAdts, INT blockNum) { int length; if (pAdts->bs.num_raw_blocks == 0) { - length = (pAdts->bs.frame_length - 7) << 3; /* aac_frame_length subtracted by the header size (7 bytes). */ + length = + (pAdts->bs.frame_length - 7) + << 3; /* aac_frame_length subtracted by the header size (7 bytes). */ if (pAdts->bs.protection_absent == 0) - length -= 16; /* substract 16 bit CRC */ + length -= 16; /* substract 16 bit CRC */ } else { if (pAdts->bs.protection_absent) { length = -1; /* raw data block length is unknown */ } else { if (blockNum < 0 || blockNum > 3) { length = -1; + } else { + length = (pAdts->rawDataBlockDist[blockNum] << 3) - 16; } - length = (pAdts->rawDataBlockDist[blockNum] << 3) - 16; } } if (blockNum == 0 && length > 0) { @@ -384,5 +370,3 @@ int adtsRead_GetRawDataBlockLength( } return length; } - - diff --git a/libMpegTPDec/src/tpdec_adts.h b/libMpegTPDec/src/tpdec_adts.h index a3b83a5..68f3f63 100644 --- a/libMpegTPDec/src/tpdec_adts.h +++ b/libMpegTPDec/src/tpdec_adts.h @@ -1,74 +1,85 @@ - -/* ----------------------------------------------------------------------------------------------------------- +/* ----------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 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,31 +90,31 @@ Am Wolfsmantel 33 www.iis.fraunhofer.de/amm amm-info@iis.fraunhofer.de ------------------------------------------------------------------------------------------------------------ */ +----------------------------------------------------------------------------- */ -/***************************** MPEG-4 AAC Decoder ************************** +/******************* MPEG transport format decoder library ********************* Author(s): Josef Hoepfl + Description: ADTS interface -******************************************************************************/ +*******************************************************************************/ #ifndef TPDEC_ADTS_H #define TPDEC_ADTS_H #include "tpdec_lib.h" - -#define ADTS_SYNCWORD ( 0xfff ) -#define ADTS_SYNCLENGTH ( 12 ) /* in bits */ -#define ADTS_HEADERLENGTH ( 56 ) /* minimum header size in bits */ -#define ADTS_FIXED_HEADERLENGTH ( 28 ) /* in bits */ -#define ADTS_VARIABLE_HEADERLENGTH ( ADTS_HEADERLENGTH - ADTS_FIXED_HEADERLENGTH ) +#define ADTS_SYNCWORD (0xfff) +#define ADTS_SYNCLENGTH (12) /* in bits */ +#define ADTS_HEADERLENGTH (56) /* minimum header size in bits */ +#define ADTS_FIXED_HEADERLENGTH (28) /* in bits */ +#define ADTS_VARIABLE_HEADERLENGTH (ADTS_HEADERLENGTH - ADTS_FIXED_HEADERLENGTH) #ifdef CHECK_TWO_SYNCS - #define ADTS_MIN_TP_BUF_SIZE ( 8191 + 2 ) +#define ADTS_MIN_TP_BUF_SIZE (8191 + 2) #else - #define ADTS_MIN_TP_BUF_SIZE ( 8191 ) +#define ADTS_MIN_TP_BUF_SIZE (8191) #endif #include "FDK_crc.h" @@ -128,16 +139,16 @@ typedef struct { } STRUCT_ADTS_BS; struct STRUCT_ADTS { - STRUCT_ADTS_BS bs; UCHAR decoderCanDoMpeg4; UCHAR BufferFullnesStartFlag; - FDK_CRCINFO crcInfo; /* CRC state info */ - USHORT crcReadValue; /* CRC value read from bitstream data */ - USHORT rawDataBlockDist[4]; /* distance between each raw data block. Not the same as found in the bitstream */ -} ; + FDK_CRCINFO crcInfo; /* CRC state info */ + USHORT crcReadValue; /* CRC value read from bitstream data */ + USHORT rawDataBlockDist[4]; /* distance between each raw data block. Not the + same as found in the bitstream */ +}; typedef struct STRUCT_ADTS *HANDLE_ADTS; @@ -148,15 +159,14 @@ typedef struct STRUCT_ADTS *HANDLE_ADTS; \return none */ -void adtsRead_CrcInit( HANDLE_ADTS pAdts ); +void adtsRead_CrcInit(HANDLE_ADTS pAdts); /** * \brief Starts CRC region with a maximum number of bits - * If mBits is positive zero padding will be used for CRC calculation, if there - * are less than mBits bits available. - * If mBits is negative no zero padding is done. - * If mBits is zero the memory for the buffer is allocated dynamically, the - * number of bits is not limited. + * If mBits is positive zero padding will be used for CRC calculation, if + * there are less than mBits bits available. If mBits is negative no zero + * padding is done. If mBits is zero the memory for the buffer is + * allocated dynamically, the number of bits is not limited. * * \param pAdts ADTS data handle * \param hBs bitstream handle, on which the CRC region referes to @@ -164,11 +174,8 @@ void adtsRead_CrcInit( HANDLE_ADTS pAdts ); * * \return ID for the created region, -1 in case of an error */ -int adtsRead_CrcStartReg( - HANDLE_ADTS pAdts, - HANDLE_FDK_BITSTREAM hBs, - int mBits - ); +int adtsRead_CrcStartReg(HANDLE_ADTS pAdts, HANDLE_FDK_BITSTREAM hBs, + int mBits); /** * \brief Ends CRC region identified by reg @@ -179,58 +186,49 @@ int adtsRead_CrcStartReg( * * \return none */ -void adtsRead_CrcEndReg( - HANDLE_ADTS pAdts, - HANDLE_FDK_BITSTREAM hBs, - int reg - ); +void adtsRead_CrcEndReg(HANDLE_ADTS pAdts, HANDLE_FDK_BITSTREAM hBs, int reg); /** * \brief Check CRC * - * Checks if the currently calculated CRC matches the CRC field read from the bitstream - * Deletes all CRC regions. + * Checks if the currently calculated CRC matches the CRC field read from the + * bitstream Deletes all CRC regions. * * \param pAdts ADTS data handle * * \return Returns 0 if they are identical otherwise 1 */ -TRANSPORTDEC_ERROR adtsRead_CrcCheck( HANDLE_ADTS pAdts ); - +TRANSPORTDEC_ERROR adtsRead_CrcCheck(HANDLE_ADTS pAdts); /** * \brief Check if we have a valid ADTS frame at the current bitbuffer position * * This function assumes enough bits in buffer for the current frame. * It reads out the header bits to prepare the bitbuffer for the decode loop. - * In case the header bits show an invalid bitstream/frame, the whole frame is skipped. + * In case the header bits show an invalid bitstream/frame, the whole frame is + * skipped. * * \param pAdts ADTS data handle which is filled with parsed ADTS header data * \param bs handle of bitstream from whom the ADTS header is read * * \return error status */ -TRANSPORTDEC_ERROR adtsRead_DecodeHeader( - HANDLE_ADTS pAdts, - CSAudioSpecificConfig *pAsc, - HANDLE_FDK_BITSTREAM bs, - const INT ignoreBufferFullness - ); +TRANSPORTDEC_ERROR adtsRead_DecodeHeader(HANDLE_ADTS pAdts, + CSAudioSpecificConfig *pAsc, + HANDLE_FDK_BITSTREAM bs, + const INT ignoreBufferFullness); /** * \brief Get the raw data block length of the given block number. * * \param pAdts ADTS data handle * \param blockNum current raw data block index - * \param pLength pointer to an INT where the length of the given raw data block is stored into - * the returned value might be -1, in which case the raw data block length is unknown. + * \param pLength pointer to an INT where the length of the given raw data block + * is stored into the returned value might be -1, in which case the raw data + * block length is unknown. * * \return error status */ -int adtsRead_GetRawDataBlockLength( - HANDLE_ADTS pAdts, - INT blockNum - ); - +int adtsRead_GetRawDataBlockLength(HANDLE_ADTS pAdts, INT blockNum); #endif /* TPDEC_ADTS_H */ 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); } - diff --git a/libMpegTPDec/src/tpdec_drm.cpp b/libMpegTPDec/src/tpdec_drm.cpp index df319e5..27c1c1d 100644 --- a/libMpegTPDec/src/tpdec_drm.cpp +++ b/libMpegTPDec/src/tpdec_drm.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,23 +90,21 @@ Am Wolfsmantel 33 www.iis.fraunhofer.de/amm amm-info@iis.fraunhofer.de ------------------------------------------------------------------------------------------------------------ */ +----------------------------------------------------------------------------- */ -/***************************** MPEG-4 AAC Decoder ************************** +/******************* MPEG transport format decoder library ********************* Author(s): Christian Griebel + Description: DRM transport stuff -******************************************************************************/ +*******************************************************************************/ #include "tpdec_drm.h" - #include "FDK_bitstream.h" - - -void drmRead_CrcInit(HANDLE_DRM pDrm) /*!< pointer to drm crc info stucture */ +void drmRead_CrcInit(HANDLE_DRM pDrm) /*!< pointer to drm crc info stucture */ { FDK_ASSERT(pDrm != NULL); @@ -103,44 +112,37 @@ void drmRead_CrcInit(HANDLE_DRM pDrm) /*!< pointer to drm crc info stucture } int drmRead_CrcStartReg( - HANDLE_DRM pDrm, /*!< pointer to drm stucture */ - HANDLE_FDK_BITSTREAM hBs, /*!< handle to current bit buffer structure */ - int mBits /*!< number of bits in crc region */ - ) -{ + HANDLE_DRM pDrm, /*!< pointer to drm stucture */ + HANDLE_FDK_BITSTREAM hBs, /*!< handle to current bit buffer structure */ + int mBits /*!< number of bits in crc region */ +) { FDK_ASSERT(pDrm != NULL); FDKcrcReset(&pDrm->crcInfo); pDrm->crcReadValue = FDKreadBits(hBs, 8); - return ( FDKcrcStartReg(&pDrm->crcInfo, hBs, mBits) ); - + return (FDKcrcStartReg(&pDrm->crcInfo, hBs, mBits)); } void drmRead_CrcEndReg( - HANDLE_DRM pDrm, /*!< pointer to drm crc info stucture */ - HANDLE_FDK_BITSTREAM hBs, /*!< handle to current bit buffer structure */ - int reg /*!< crc region */ - ) -{ + HANDLE_DRM pDrm, /*!< pointer to drm crc info stucture */ + HANDLE_FDK_BITSTREAM hBs, /*!< handle to current bit buffer structure */ + int reg /*!< crc region */ +) { FDK_ASSERT(pDrm != NULL); FDKcrcEndReg(&pDrm->crcInfo, hBs, reg); } -TRANSPORTDEC_ERROR drmRead_CrcCheck( HANDLE_DRM pDrm ) -{ +TRANSPORTDEC_ERROR drmRead_CrcCheck(HANDLE_DRM pDrm) { TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK; USHORT crc; crc = FDKcrcGetCRC(&pDrm->crcInfo) ^ 0xFF; - if (crc != pDrm->crcReadValue) - { + if (crc != pDrm->crcReadValue) { return (TRANSPORTDEC_CRC_ERROR); } return (ErrorStatus); } - - diff --git a/libMpegTPDec/src/tpdec_drm.h b/libMpegTPDec/src/tpdec_drm.h index 2161b4c..09822dc 100644 --- a/libMpegTPDec/src/tpdec_drm.h +++ b/libMpegTPDec/src/tpdec_drm.h @@ -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,27 +90,26 @@ Am Wolfsmantel 33 www.iis.fraunhofer.de/amm amm-info@iis.fraunhofer.de ------------------------------------------------------------------------------------------------------------ */ +----------------------------------------------------------------------------- */ -/***************************** MPEG-4 AAC Decoder ************************** +/******************* MPEG transport format decoder library ********************* Author(s): Josef Hoepfl + Description: DRM interface -******************************************************************************/ +*******************************************************************************/ #ifndef TPDEC_DRM_H #define TPDEC_DRM_H #include "tpdec_lib.h" - #include "FDK_crc.h" typedef struct { - - FDK_CRCINFO crcInfo; /* CRC state info */ - USHORT crcReadValue; /* CRC value read from bitstream data */ + FDK_CRCINFO crcInfo; /* CRC state info */ + USHORT crcReadValue; /* CRC value read from bitstream data */ } STRUCT_DRM; @@ -112,15 +122,14 @@ typedef STRUCT_DRM *HANDLE_DRM; \return none */ -void drmRead_CrcInit( HANDLE_DRM pDrm ); +void drmRead_CrcInit(HANDLE_DRM pDrm); /** * \brief Starts CRC region with a maximum number of bits - * If mBits is positive zero padding will be used for CRC calculation, if there - * are less than mBits bits available. - * If mBits is negative no zero padding is done. - * If mBits is zero the memory for the buffer is allocated dynamically, the - * number of bits is not limited. + * If mBits is positive zero padding will be used for CRC calculation, if + * there are less than mBits bits available. If mBits is negative no zero + * padding is done. If mBits is zero the memory for the buffer is + * allocated dynamically, the number of bits is not limited. * * \param pDrm DRM data handle * \param hBs bitstream handle, on which the CRC region referes to @@ -128,11 +137,7 @@ void drmRead_CrcInit( HANDLE_DRM pDrm ); * * \return ID for the created region, -1 in case of an error */ -int drmRead_CrcStartReg( - HANDLE_DRM pDrm, - HANDLE_FDK_BITSTREAM hBs, - int mBits - ); +int drmRead_CrcStartReg(HANDLE_DRM pDrm, HANDLE_FDK_BITSTREAM hBs, int mBits); /** * \brief Ends CRC region identified by reg @@ -143,52 +148,55 @@ int drmRead_CrcStartReg( * * \return none */ -void drmRead_CrcEndReg( - HANDLE_DRM pDrm, - HANDLE_FDK_BITSTREAM hBs, - int reg - ); +void drmRead_CrcEndReg(HANDLE_DRM pDrm, HANDLE_FDK_BITSTREAM hBs, int reg); /** * \brief Check CRC * - * Checks if the currently calculated CRC matches the CRC field read from the bitstream - * Deletes all CRC regions. + * Checks if the currently calculated CRC matches the CRC field read from the + * bitstream Deletes all CRC regions. * * \param pDrm DRM data handle * * \return Returns 0 if they are identical otherwise 1 */ -TRANSPORTDEC_ERROR drmRead_CrcCheck( HANDLE_DRM pDrm ); +TRANSPORTDEC_ERROR drmRead_CrcCheck(HANDLE_DRM pDrm); /** * \brief Check if we have a valid DRM frame at the current bitbuffer position * * This function assumes enough bits in buffer for the current frame. * It reads out the header bits to prepare the bitbuffer for the decode loop. - * In case the header bits show an invalid bitstream/frame, the whole frame is skipped. + * In case the header bits show an invalid bitstream/frame, the whole frame is + * skipped. * * \param pDrm DRM data handle which is filled with parsed DRM header data * \param bs handle of bitstream from whom the DRM header is read * * \return error status */ -TRANSPORTDEC_ERROR drmRead_DecodeHeader( - HANDLE_DRM pDrm, - HANDLE_FDK_BITSTREAM bs - ); +TRANSPORTDEC_ERROR drmRead_DecodeHeader(HANDLE_DRM pDrm, + HANDLE_FDK_BITSTREAM bs); /** * \brief Parse a Drm specific SDC audio config from a given bitstream handle. * - * \param pAsc A pointer to an allocated CSAudioSpecificConfig struct. + * \param pAsc A pointer to an allocated + * CSAudioSpecificConfig struct. * \param hBs Bitstream handle. + * \param cb A pointer to structure holding callback + * information Note: A NULL pointer for cb can be used to signal a "Check Config + * only functionality" + * \param configMode Config modes: memory allocation mode or + * config change detection mode + * \param configChanged Indicates a config change * * \return Total element count including all SCE, CPE and LFE. */ -TRANSPORTDEC_ERROR DrmRawSdcAudioConfig_Parse( CSAudioSpecificConfig *pAsc, - HANDLE_FDK_BITSTREAM hBs ); - - +TRANSPORTDEC_ERROR DrmRawSdcAudioConfig_Parse(CSAudioSpecificConfig *pAsc, + HANDLE_FDK_BITSTREAM hBs, + CSTpCallBacks *cb, + const UCHAR configMode, + const UCHAR configChanged); #endif /* TPDEC_DRM_H */ diff --git a/libMpegTPDec/src/tpdec_latm.cpp b/libMpegTPDec/src/tpdec_latm.cpp index 5710d77..b4f7372 100644 --- a/libMpegTPDec/src/tpdec_latm.cpp +++ b/libMpegTPDec/src/tpdec_latm.cpp @@ -1,74 +1,85 @@ - -/* ----------------------------------------------------------------------------------------------------------- +/* ----------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 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,91 +90,151 @@ 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_latm.h" - #include "FDK_bitstream.h" +#define TPDEC_TRACKINDEX(p, l) (1 * (p) + (l)) -#define TPDEC_TRACKINDEX(p,l) (2*(p) + (l)) - -static -UINT CLatmDemux_GetValue(HANDLE_FDK_BITSTREAM bs) -{ +static UINT CLatmDemux_GetValue(HANDLE_FDK_BITSTREAM bs) { UCHAR bytesForValue = 0, tmp = 0; int value = 0; - bytesForValue = (UCHAR) FDKreadBits(bs,2); + bytesForValue = (UCHAR)FDKreadBits(bs, 2); - for (UINT i=0; i<=bytesForValue; i++) { + for (UINT i = 0; i <= bytesForValue; i++) { value <<= 8; - tmp = (UCHAR) FDKreadBits(bs,8); + tmp = (UCHAR)FDKreadBits(bs, 8); value += tmp; } return value; } - -static -TRANSPORTDEC_ERROR CLatmDemux_ReadAudioMuxElement( - HANDLE_FDK_BITSTREAM bs, - CLatmDemux *pLatmDemux, - int m_muxConfigPresent, - CSTpCallBacks *pTpDecCallbacks, - CSAudioSpecificConfig *pAsc, - int *pfConfigFound - ) -{ +static TRANSPORTDEC_ERROR CLatmDemux_ReadAudioMuxElement( + HANDLE_FDK_BITSTREAM bs, CLatmDemux *pLatmDemux, int m_muxConfigPresent, + CSTpCallBacks *pTpDecCallbacks, CSAudioSpecificConfig *pAsc, + int *pfConfigFound) { TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK; + UCHAR applyAsc = pLatmDemux->applyAsc; if (m_muxConfigPresent) { - pLatmDemux->m_useSameStreamMux = FDKreadBits(bs,1); + pLatmDemux->m_useSameStreamMux = FDKreadBits(bs, 1); if (!pLatmDemux->m_useSameStreamMux) { - if ((ErrorStatus = CLatmDemux_ReadStreamMuxConfig(bs, pLatmDemux, pTpDecCallbacks, pAsc, pfConfigFound))) { - return (ErrorStatus); + int i; + UCHAR configChanged = 0; + UCHAR configMode = 0; + + FDK_BITSTREAM bsAnchor; + + FDK_BITSTREAM bsAnchorDummyParse; + + if (!pLatmDemux->applyAsc) { + bsAnchorDummyParse = *bs; + pLatmDemux->newCfgHasAudioPreRoll = 0; + /* do dummy-parsing of ASC to determine if there is an audioPreRoll */ + configMode |= AC_CM_DET_CFG_CHANGE; + if (TRANSPORTDEC_OK != + (ErrorStatus = CLatmDemux_ReadStreamMuxConfig( + bs, pLatmDemux, pTpDecCallbacks, pAsc, pfConfigFound, + configMode, configChanged))) { + goto bail; + } + + if (pLatmDemux->newCfgHasAudioPreRoll) { + pLatmDemux->newCfgHasAudioPreRoll = 0; + /* with audioPreRoll we must flush before applying new cfg */ + pLatmDemux->applyAsc = 0; + } else { + *bs = bsAnchorDummyParse; + pLatmDemux->applyAsc = 1; /* apply new config immediate */ + } + } + + if (pLatmDemux->applyAsc) { + for (i = 0; i < 2; i++) { + configMode = 0; + + if (i == 0) { + configMode |= AC_CM_DET_CFG_CHANGE; + bsAnchor = *bs; + } else { + configMode |= AC_CM_ALLOC_MEM; + *bs = bsAnchor; + } + + if (TRANSPORTDEC_OK != + (ErrorStatus = CLatmDemux_ReadStreamMuxConfig( + bs, pLatmDemux, pTpDecCallbacks, pAsc, pfConfigFound, + configMode, configChanged))) { + goto bail; + } + + if (ErrorStatus == TRANSPORTDEC_OK) { + if ((i == 0) && (pAsc->AacConfigChanged || pAsc->SbrConfigChanged || + pAsc->SacConfigChanged)) { + int errC; + + configChanged = 1; + errC = pTpDecCallbacks->cbFreeMem(pTpDecCallbacks->cbFreeMemData, + pAsc); + if (errC != 0) { + ErrorStatus = TRANSPORTDEC_PARSE_ERROR; + goto bail; + } + } + } + } } } } - /* If there was no configuration read, its not possible to parse PayloadLengthInfo below. */ - if (! *pfConfigFound) { - return TRANSPORTDEC_SYNC_ERROR; + /* If there was no configuration read, its not possible to parse + * PayloadLengthInfo below. */ + if (!*pfConfigFound) { + ErrorStatus = TRANSPORTDEC_SYNC_ERROR; + goto bail; } if (pLatmDemux->m_AudioMuxVersionA == 0) { /* Do only once per call, because parsing and decoding is done in-line. */ - if ((ErrorStatus = CLatmDemux_ReadPayloadLengthInfo(bs,pLatmDemux))) { - return (ErrorStatus); + if (TRANSPORTDEC_OK != + (ErrorStatus = CLatmDemux_ReadPayloadLengthInfo(bs, pLatmDemux))) { + *pfConfigFound = 0; + goto bail; } } else { /* audioMuxVersionA > 0 is reserved for future extensions */ ErrorStatus = TRANSPORTDEC_UNSUPPORTED_FORMAT; + *pfConfigFound = 0; + goto bail; + } + +bail: + if (ErrorStatus != TRANSPORTDEC_OK) { + pLatmDemux->applyAsc = applyAsc; } return (ErrorStatus); } -TRANSPORTDEC_ERROR CLatmDemux_Read( - HANDLE_FDK_BITSTREAM bs, - CLatmDemux *pLatmDemux, - TRANSPORT_TYPE tt, - CSTpCallBacks *pTpDecCallbacks, - CSAudioSpecificConfig *pAsc, - int *pfConfigFound, - const INT ignoreBufferFullness - ) -{ +TRANSPORTDEC_ERROR CLatmDemux_Read(HANDLE_FDK_BITSTREAM bs, + CLatmDemux *pLatmDemux, TRANSPORT_TYPE tt, + CSTpCallBacks *pTpDecCallbacks, + CSAudioSpecificConfig *pAsc, + int *pfConfigFound, + const INT ignoreBufferFullness) { UINT cntBits; UINT cmpBufferFullness; UINT audioMuxLengthBytesLast = 0; @@ -175,29 +246,27 @@ TRANSPORTDEC_ERROR CLatmDemux_Read( return TRANSPORTDEC_NOT_ENOUGH_BITS; } - if ((ErrorStatus = CLatmDemux_ReadAudioMuxElement(bs, pLatmDemux, (tt != TT_MP4_LATM_MCP0), pTpDecCallbacks, pAsc, pfConfigFound))) + if (TRANSPORTDEC_OK != (ErrorStatus = CLatmDemux_ReadAudioMuxElement( + bs, pLatmDemux, (tt != TT_MP4_LATM_MCP0), + pTpDecCallbacks, pAsc, pfConfigFound))) return (ErrorStatus); - if (!ignoreBufferFullness) - { - cmpBufferFullness = 24+audioMuxLengthBytesLast*8 - + pLatmDemux->m_linfo[0][0].m_bufferFullness* pAsc[TPDEC_TRACKINDEX(0,0)].m_channelConfiguration*32; + if (!ignoreBufferFullness) { + cmpBufferFullness = + 24 + audioMuxLengthBytesLast * 8 + + pLatmDemux->m_linfo[0][0].m_bufferFullness * + pAsc[TPDEC_TRACKINDEX(0, 0)].m_channelConfiguration * 32; /* evaluate buffer fullness */ - if (pLatmDemux->m_linfo[0][0].m_bufferFullness != 0xFF) - { - if (!pLatmDemux->BufferFullnessAchieved) - { - if (cntBits < cmpBufferFullness) - { + if (pLatmDemux->m_linfo[0][0].m_bufferFullness != 0xFF) { + if (!pLatmDemux->BufferFullnessAchieved) { + if (cntBits < cmpBufferFullness) { /* condition for start of decoding is not fulfilled */ /* the current frame will not be decoded */ return TRANSPORTDEC_NOT_ENOUGH_BITS; - } - else - { + } else { pLatmDemux->BufferFullnessAchieved = 1; } } @@ -207,227 +276,397 @@ TRANSPORTDEC_ERROR CLatmDemux_Read( return (ErrorStatus); } - TRANSPORTDEC_ERROR CLatmDemux_ReadStreamMuxConfig( - HANDLE_FDK_BITSTREAM bs, - CLatmDemux *pLatmDemux, - CSTpCallBacks *pTpDecCallbacks, - CSAudioSpecificConfig *pAsc, - int * pfConfigFound - ) -{ + HANDLE_FDK_BITSTREAM bs, CLatmDemux *pLatmDemux, + CSTpCallBacks *pTpDecCallbacks, CSAudioSpecificConfig *pAsc, + int *pfConfigFound, UCHAR configMode, UCHAR configChanged) { + CSAudioSpecificConfig ascDummy; /* the actual config is needed for flushing, + after that new config can be parsed */ + CSAudioSpecificConfig *pAscDummy; + pAscDummy = &ascDummy; + pLatmDemux->usacExplicitCfgChanged = 0; LATM_LAYER_INFO *p_linfo = NULL; TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK; + UCHAR updateConfig[1 * 1] = {0}; - pLatmDemux->m_AudioMuxVersion = FDKreadBits(bs,1); + pLatmDemux->m_AudioMuxVersion = FDKreadBits(bs, 1); if (pLatmDemux->m_AudioMuxVersion == 0) { pLatmDemux->m_AudioMuxVersionA = 0; } else { - pLatmDemux->m_AudioMuxVersionA = FDKreadBits(bs,1); + pLatmDemux->m_AudioMuxVersionA = FDKreadBits(bs, 1); } if (pLatmDemux->m_AudioMuxVersionA == 0) { if (pLatmDemux->m_AudioMuxVersion == 1) { pLatmDemux->m_taraBufferFullness = CLatmDemux_GetValue(bs); } - pLatmDemux->m_allStreamsSameTimeFraming = FDKreadBits(bs,1); - pLatmDemux->m_noSubFrames = FDKreadBits(bs,6) + 1; - pLatmDemux->m_numProgram = FDKreadBits(bs,4) + 1; + pLatmDemux->m_allStreamsSameTimeFraming = FDKreadBits(bs, 1); + pLatmDemux->m_noSubFrames = FDKreadBits(bs, 6) + 1; + pLatmDemux->m_numProgram = FDKreadBits(bs, 4) + 1; - if (pLatmDemux->m_numProgram > 1) { - return TRANSPORTDEC_UNSUPPORTED_FORMAT; + if (pLatmDemux->m_numProgram > LATM_MAX_PROG) { + ErrorStatus = TRANSPORTDEC_UNSUPPORTED_FORMAT; + goto bail; } int idCnt = 0; for (UINT prog = 0; prog < pLatmDemux->m_numProgram; prog++) { - pLatmDemux->m_numLayer = FDKreadBits(bs,3) + 1; - if (pLatmDemux->m_numLayer > 2) { - return TRANSPORTDEC_UNSUPPORTED_FORMAT; + pLatmDemux->m_numLayer[prog] = FDKreadBits(bs, 3) + 1; + if (pLatmDemux->m_numLayer[prog] > LATM_MAX_LAYER) { + ErrorStatus = TRANSPORTDEC_UNSUPPORTED_FORMAT; + goto bail; } - for (UINT lay = 0; lay < pLatmDemux->m_numLayer; lay++) { + for (UINT lay = 0; lay < pLatmDemux->m_numLayer[prog]; lay++) { + int useSameConfig; p_linfo = &pLatmDemux->m_linfo[prog][lay]; p_linfo->m_streamID = idCnt++; p_linfo->m_frameLengthInBits = 0; - if( (prog == 0) && (lay == 0) ) { - pLatmDemux->m_useSameConfig = 0; + if ((prog == 0) && (lay == 0)) { + useSameConfig = 0; } else { - pLatmDemux->m_useSameConfig = FDKreadBits(bs,1); + useSameConfig = FDKreadBits(bs, 1); } - if (pLatmDemux->m_useSameConfig) { - if (lay > 1) { - FDKmemcpy(&pAsc[TPDEC_TRACKINDEX(prog,lay)], &pAsc[TPDEC_TRACKINDEX(prog,lay-1)], sizeof(CSAudioSpecificConfig)); + if (useSameConfig) { + if (lay > 0) { + FDKmemcpy(&pAsc[TPDEC_TRACKINDEX(prog, lay)], + &pAsc[TPDEC_TRACKINDEX(prog, lay - 1)], + sizeof(CSAudioSpecificConfig)); } else { - return TRANSPORTDEC_PARSE_ERROR; + ErrorStatus = TRANSPORTDEC_PARSE_ERROR; + goto bail; } } else { - if (pLatmDemux->m_AudioMuxVersion == 1) - { + UINT usacConfigLengthPrev = 0; + UCHAR usacConfigPrev[TP_USAC_MAX_CONFIG_LEN]; + + if (!(pLatmDemux->applyAsc) && + (pAsc[TPDEC_TRACKINDEX(prog, lay)].m_aot == AOT_USAC)) { + usacConfigLengthPrev = + (UINT)(pAsc[TPDEC_TRACKINDEX(prog, lay)] + .m_sc.m_usacConfig.UsacConfigBits + + 7) >> + 3; /* store previous USAC config length */ + if (usacConfigLengthPrev > TP_USAC_MAX_CONFIG_LEN) { + ErrorStatus = TRANSPORTDEC_PARSE_ERROR; + goto bail; + } + FDKmemclear(usacConfigPrev, TP_USAC_MAX_CONFIG_LEN); + FDKmemcpy( + usacConfigPrev, + &pAsc[TPDEC_TRACKINDEX(prog, lay)].m_sc.m_usacConfig.UsacConfig, + usacConfigLengthPrev); /* store previous USAC config */ + } + if (pLatmDemux->m_AudioMuxVersion == 1) { FDK_BITSTREAM tmpBs; - UINT ascStartPos, ascLen=0; - + UINT ascLen = 0; ascLen = CLatmDemux_GetValue(bs); - ascStartPos = FDKgetValidBits(bs); + /* The ascLen could be wrong, so check if validBits<=bufBits*/ + if (ascLen > FDKgetValidBits(bs)) { + ErrorStatus = TRANSPORTDEC_PARSE_ERROR; + goto bail; + } + FDKsyncCache(bs); tmpBs = *bs; - FDKsyncCache(&tmpBs); tmpBs.hBitBuf.ValidBits = ascLen; - + /* Read ASC */ - if ((ErrorStatus = AudioSpecificConfig_Parse(&pAsc[TPDEC_TRACKINDEX(prog,lay)], &tmpBs, 1, pTpDecCallbacks))) { - return (ErrorStatus); + if (pLatmDemux->applyAsc) { + if (TRANSPORTDEC_OK != + (ErrorStatus = AudioSpecificConfig_Parse( + &pAsc[TPDEC_TRACKINDEX(prog, lay)], &tmpBs, 1, + pTpDecCallbacks, configMode, configChanged, + AOT_NULL_OBJECT))) + goto bail; + } else { + if (TRANSPORTDEC_OK != + (ErrorStatus = AudioSpecificConfig_Parse( + pAscDummy, &tmpBs, 1, pTpDecCallbacks, configMode, + configChanged, AOT_NULL_OBJECT))) + goto bail; } - *pfConfigFound = 1; /* The field p_linfo->m_ascLen could be wrong, so check if */ - if ( 0 > (INT)FDKgetValidBits(&tmpBs)) { - return TRANSPORTDEC_PARSE_ERROR; + if (0 > (INT)FDKgetValidBits(&tmpBs)) { + ErrorStatus = TRANSPORTDEC_PARSE_ERROR; + goto bail; } FDKpushFor(bs, ascLen); /* position bitstream after ASC */ - } - else { + } else { /* Read ASC */ - if ((ErrorStatus = AudioSpecificConfig_Parse(&pAsc[TPDEC_TRACKINDEX(prog,lay)], bs, 0, pTpDecCallbacks))) { - return (ErrorStatus); + if (pLatmDemux->applyAsc) { + if (TRANSPORTDEC_OK != (ErrorStatus = AudioSpecificConfig_Parse( + &pAsc[TPDEC_TRACKINDEX(prog, lay)], + bs, 0, pTpDecCallbacks, configMode, + configChanged, AOT_NULL_OBJECT))) + goto bail; + } else { + if (TRANSPORTDEC_OK != + (ErrorStatus = AudioSpecificConfig_Parse( + pAscDummy, bs, 0, pTpDecCallbacks, configMode, + configChanged, AOT_NULL_OBJECT))) + goto bail; } } - { - int cbError; + if (!pLatmDemux->applyAsc) { + updateConfig[TPDEC_TRACKINDEX(prog, lay)] = 0; + } else { + updateConfig[TPDEC_TRACKINDEX(prog, lay)] = 1; + } - cbError = pTpDecCallbacks->cbUpdateConfig(pTpDecCallbacks->cbUpdateConfigData, &pAsc[TPDEC_TRACKINDEX(prog,lay)]); - if (cbError != 0) { - return TRANSPORTDEC_UNKOWN_ERROR; + if (!pLatmDemux->applyAsc) { + if (pAscDummy[TPDEC_TRACKINDEX(prog, lay)].m_aot == + AOT_USAC) { /* flush in case SMC has changed */ + const UINT usacConfigLength = + (UINT)(pAscDummy->m_sc.m_usacConfig.UsacConfigBits + 7) >> 3; + if (usacConfigLength > TP_USAC_MAX_CONFIG_LEN) { + ErrorStatus = TRANSPORTDEC_PARSE_ERROR; + goto bail; + } + if (usacConfigLength != usacConfigLengthPrev) { + FDKmemclear(&pAsc[TPDEC_TRACKINDEX(prog, lay)] + .m_sc.m_usacConfig.UsacConfig, + TP_USAC_MAX_CONFIG_LEN); + FDKmemcpy(&pAsc[TPDEC_TRACKINDEX(prog, lay)] + .m_sc.m_usacConfig.UsacConfig, + &pAscDummy->m_sc.m_usacConfig.UsacConfig, + usacConfigLength); /* store new USAC config */ + pAsc[TPDEC_TRACKINDEX(prog, lay)] + .m_sc.m_usacConfig.UsacConfigBits = + pAscDummy->m_sc.m_usacConfig.UsacConfigBits; + pLatmDemux->usacExplicitCfgChanged = 1; + } else { + if (FDKmemcmp(usacConfigPrev, + pAscDummy->m_sc.m_usacConfig.UsacConfig, + usacConfigLengthPrev)) { + FDKmemclear(&pAsc[TPDEC_TRACKINDEX(prog, lay)] + .m_sc.m_usacConfig.UsacConfig, + TP_USAC_MAX_CONFIG_LEN); + FDKmemcpy(&pAsc[TPDEC_TRACKINDEX(prog, lay)] + .m_sc.m_usacConfig.UsacConfig, + &pAscDummy->m_sc.m_usacConfig.UsacConfig, + usacConfigLength); /* store new USAC config */ + pAsc[TPDEC_TRACKINDEX(prog, lay)] + .m_sc.m_usacConfig.UsacConfigBits = + pAscDummy->m_sc.m_usacConfig.UsacConfigBits; + pLatmDemux->usacExplicitCfgChanged = 1; + } + } + + if (pAscDummy[TPDEC_TRACKINDEX(prog, lay)] + .m_sc.m_usacConfig.m_usacNumElements) { + if (pAscDummy[TPDEC_TRACKINDEX(prog, lay)] + .m_sc.m_usacConfig.element[0] + .extElement.usacExtElementHasAudioPreRoll) { + pLatmDemux->newCfgHasAudioPreRoll = + 1; /* if dummy parsed cfg has audioPreRoll we first flush + before applying new cfg */ + } + } } - *pfConfigFound = 1; } } - p_linfo->m_frameLengthType = FDKreadBits(bs,3); - switch( p_linfo->m_frameLengthType ) { - case 0: - p_linfo->m_bufferFullness = FDKreadBits(bs,8); - - if (!pLatmDemux->m_allStreamsSameTimeFraming) { - if ((lay > 0) && (pAsc[TPDEC_TRACKINDEX(prog,lay)].m_aot == AOT_AAC_SCAL || pAsc[TPDEC_TRACKINDEX(prog,lay)].m_aot == AOT_ER_AAC_SCAL)) { - return TRANSPORTDEC_UNSUPPORTED_FORMAT; + p_linfo->m_frameLengthType = FDKreadBits(bs, 3); + switch (p_linfo->m_frameLengthType) { + case 0: + p_linfo->m_bufferFullness = FDKreadBits(bs, 8); + + if (!pLatmDemux->m_allStreamsSameTimeFraming) { + if ((lay > 0) && + (pAsc[TPDEC_TRACKINDEX(prog, lay)].m_aot == AOT_AAC_SCAL || + pAsc[TPDEC_TRACKINDEX(prog, lay)].m_aot == + AOT_ER_AAC_SCAL) && + (pAsc[TPDEC_TRACKINDEX(prog, lay - 1)].m_aot == AOT_CELP || + pAsc[TPDEC_TRACKINDEX(prog, lay - 1)].m_aot == + AOT_ER_CELP)) { /* The layer maybe + ignored later so + read it anyway: */ + /* coreFrameOffset = */ FDKreadBits(bs, 6); + } } - } - break; - case 1: - /* frameLength = FDKreadBits(bs,9); */ - case 3: - case 4: - case 5: - /* CELP */ - case 6: - case 7: - /* HVXC */ - default: - return TRANSPORTDEC_PARSE_ERROR; //_LATM_INVALIDFRAMELENGTHTYPE; - - } /* switch framelengthtype*/ - - } /* layer loop */ - } /* prog loop */ - - pLatmDemux->m_otherDataPresent = FDKreadBits(bs,1); - pLatmDemux->m_otherDataLength = 0; + break; + case 1: + p_linfo->m_frameLengthInBits = FDKreadBits(bs, 9); + break; + case 3: + case 4: + case 5: + /* CELP */ + case 6: + case 7: + /* HVXC */ + default: + ErrorStatus = TRANSPORTDEC_PARSE_ERROR; + goto bail; + } /* switch framelengthtype*/ + + } /* layer loop */ + } /* prog loop */ + + pLatmDemux->m_otherDataPresent = FDKreadBits(bs, 1); + pLatmDemux->m_otherDataLength = 0; if (pLatmDemux->m_otherDataPresent) { - int otherDataLenEsc = 0; - do { - pLatmDemux->m_otherDataLength <<= 8; // *= 256 - otherDataLenEsc = FDKreadBits(bs,1); - pLatmDemux->m_otherDataLength += FDKreadBits(bs,8); - } while (otherDataLenEsc); + if (pLatmDemux->m_AudioMuxVersion == 1) { + pLatmDemux->m_otherDataLength = CLatmDemux_GetValue(bs); + } else { + int otherDataLenEsc = 0; + do { + pLatmDemux->m_otherDataLength <<= 8; // *= 256 + otherDataLenEsc = FDKreadBits(bs, 1); + pLatmDemux->m_otherDataLength += FDKreadBits(bs, 8); + } while (otherDataLenEsc); + } + if (pLatmDemux->m_audioMuxLengthBytes < + (pLatmDemux->m_otherDataLength >> 3)) { + ErrorStatus = TRANSPORTDEC_PARSE_ERROR; + goto bail; + } } - pLatmDemux->m_crcCheckPresent = FDKreadBits(bs,1); - pLatmDemux->m_crcCheckSum = 0; + pLatmDemux->m_crcCheckPresent = FDKreadBits(bs, 1); if (pLatmDemux->m_crcCheckPresent) { - pLatmDemux->m_crcCheckSum = FDKreadBits(bs,8); + FDKreadBits(bs, 8); } - } - else { + } else { /* audioMuxVersionA > 0 is reserved for future extensions */ ErrorStatus = TRANSPORTDEC_UNSUPPORTED_FORMAT; } + + /* Configure source decoder: */ + if (ErrorStatus == TRANSPORTDEC_OK) { + UINT prog; + for (prog = 0; prog < pLatmDemux->m_numProgram; prog++) { + UINT lay; + for (lay = 0; lay < pLatmDemux->m_numLayer[prog]; lay++) { + if (updateConfig[TPDEC_TRACKINDEX(prog, lay)] != 0) { + int cbError; + cbError = pTpDecCallbacks->cbUpdateConfig( + pTpDecCallbacks->cbUpdateConfigData, + &pAsc[TPDEC_TRACKINDEX(prog, lay)], + pAsc[TPDEC_TRACKINDEX(prog, lay)].configMode, + &pAsc[TPDEC_TRACKINDEX(prog, lay)].AacConfigChanged); + if (cbError == TRANSPORTDEC_NEED_TO_RESTART) { + *pfConfigFound = 0; + ErrorStatus = TRANSPORTDEC_NEED_TO_RESTART; + goto bail; + } + if (cbError != 0) { + *pfConfigFound = 0; + if (lay == 0) { + ErrorStatus = TRANSPORTDEC_SYNC_ERROR; + goto bail; + } + } else { + *pfConfigFound = 1; + } + } else { + *pfConfigFound = 1; + } + } + } + } + +bail: + if (ErrorStatus != TRANSPORTDEC_OK) { + UCHAR applyAsc = pLatmDemux->applyAsc; + FDKmemclear(pLatmDemux, sizeof(CLatmDemux)); /* reset structure */ + pLatmDemux->applyAsc = applyAsc; + } else { + /* no error and config parsing is finished */ + if (configMode == AC_CM_ALLOC_MEM) pLatmDemux->applyAsc = 0; + } + return (ErrorStatus); } -TRANSPORTDEC_ERROR CLatmDemux_ReadPayloadLengthInfo(HANDLE_FDK_BITSTREAM bs, CLatmDemux *pLatmDemux) -{ +TRANSPORTDEC_ERROR CLatmDemux_ReadPayloadLengthInfo(HANDLE_FDK_BITSTREAM bs, + CLatmDemux *pLatmDemux) { TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK; int totalPayloadBits = 0; - if( pLatmDemux->m_allStreamsSameTimeFraming == 1 ) { - for (UINT prog=0; prog<pLatmDemux->m_numProgram; prog++ ) { - for (UINT lay=0; lay<pLatmDemux->m_numLayer; lay++ ) { + if (pLatmDemux->m_allStreamsSameTimeFraming == 1) { + FDK_ASSERT(pLatmDemux->m_numProgram <= LATM_MAX_PROG); + for (UINT prog = 0; prog < pLatmDemux->m_numProgram; prog++) { + FDK_ASSERT(pLatmDemux->m_numLayer[prog] <= LATM_MAX_LAYER); + for (UINT lay = 0; lay < pLatmDemux->m_numLayer[prog]; lay++) { LATM_LAYER_INFO *p_linfo = &pLatmDemux->m_linfo[prog][lay]; - switch (p_linfo->m_frameLengthType ) { - case 0: - p_linfo->m_frameLengthInBits = CLatmDemux_ReadAuChunkLengthInfo(bs); - totalPayloadBits += p_linfo->m_frameLengthInBits; - break; - case 3: - case 5: - case 7: - default: - return TRANSPORTDEC_PARSE_ERROR; //AAC_DEC_LATM_INVALIDFRAMELENGTHTYPE; + switch (p_linfo->m_frameLengthType) { + case 0: + p_linfo->m_frameLengthInBits = CLatmDemux_ReadAuChunkLengthInfo(bs); + totalPayloadBits += p_linfo->m_frameLengthInBits; + break; + case 3: + case 5: + case 7: + default: + return TRANSPORTDEC_PARSE_ERROR; // AAC_DEC_LATM_INVALIDFRAMELENGTHTYPE; } } } + } else { + ErrorStatus = TRANSPORTDEC_PARSE_ERROR; // AAC_DEC_LATM_TIMEFRAMING; } - else { - ErrorStatus = TRANSPORTDEC_PARSE_ERROR; //AAC_DEC_LATM_TIMEFRAMING; - } - if (pLatmDemux->m_audioMuxLengthBytes > (UINT)0 && totalPayloadBits > (int)pLatmDemux->m_audioMuxLengthBytes*8) { + if (pLatmDemux->m_audioMuxLengthBytes > (UINT)0 && + totalPayloadBits > (int)pLatmDemux->m_audioMuxLengthBytes * 8) { return TRANSPORTDEC_PARSE_ERROR; } + return (ErrorStatus); } -int CLatmDemux_ReadAuChunkLengthInfo(HANDLE_FDK_BITSTREAM bs) -{ +int CLatmDemux_ReadAuChunkLengthInfo(HANDLE_FDK_BITSTREAM bs) { UCHAR endFlag; int len = 0; do { - UCHAR tmp = (UCHAR) FDKreadBits(bs,8); + UCHAR tmp = (UCHAR)FDKreadBits(bs, 8); endFlag = (tmp < 255); len += tmp; - } while( endFlag == 0 ); + } while (endFlag == 0); - len <<= 3; /* convert from bytes to bits */ + len <<= 3; /* convert from bytes to bits */ return len; } -int CLatmDemux_GetFrameLengthInBits(CLatmDemux *pLatmDemux) -{ - return pLatmDemux->m_linfo[0][0].m_frameLengthInBits; +UINT CLatmDemux_GetFrameLengthInBits(CLatmDemux *pLatmDemux, const UINT prog, + const UINT layer) { + UINT nFrameLenBits = 0; + if (prog < pLatmDemux->m_numProgram) { + if (layer < pLatmDemux->m_numLayer[prog]) { + nFrameLenBits = pLatmDemux->m_linfo[prog][layer].m_frameLengthInBits; + } + } + return nFrameLenBits; } -int CLatmDemux_GetOtherDataPresentFlag(CLatmDemux *pLatmDemux) -{ +UINT CLatmDemux_GetOtherDataPresentFlag(CLatmDemux *pLatmDemux) { return pLatmDemux->m_otherDataPresent ? 1 : 0; } -int CLatmDemux_GetOtherDataLength(CLatmDemux *pLatmDemux) -{ +UINT CLatmDemux_GetOtherDataLength(CLatmDemux *pLatmDemux) { return pLatmDemux->m_otherDataLength; } -UINT CLatmDemux_GetNrOfSubFrames(CLatmDemux *pLatmDemux) -{ +UINT CLatmDemux_GetNrOfSubFrames(CLatmDemux *pLatmDemux) { return pLatmDemux->m_noSubFrames; } +UINT CLatmDemux_GetNrOfLayers(CLatmDemux *pLatmDemux, const UINT prog) { + UINT numLayer = 0; + if (prog < pLatmDemux->m_numProgram) { + numLayer = pLatmDemux->m_numLayer[prog]; + } + return numLayer; +} diff --git a/libMpegTPDec/src/tpdec_latm.h b/libMpegTPDec/src/tpdec_latm.h index 6dc13e8..6af553d 100644 --- a/libMpegTPDec/src/tpdec_latm.h +++ b/libMpegTPDec/src/tpdec_latm.h @@ -1,74 +1,85 @@ - -/* ----------------------------------------------------------------------------------------------------------- +/* ----------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 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,32 +90,32 @@ 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: -******************************************************************************/ +*******************************************************************************/ -#ifndef LATM_DEMUX_H -#define LATM_DEMUX_H +#ifndef TPDEC_LATM_H +#define TPDEC_LATM_H #include "tpdec_lib.h" - #include "FDK_bitstream.h" -#define MIN_LATM_HEADERLENGTH 9 -#define MIN_LOAS_HEADERLENGTH MIN_LATM_HEADERLENGTH + 24 /* both in bits */ - #define MIN_TP_BUF_SIZE_LOAS ( 8194 ) +#define MIN_LATM_HEADERLENGTH 9 +#define MIN_LOAS_HEADERLENGTH MIN_LATM_HEADERLENGTH + 24 /* both in bits */ +#define MIN_TP_BUF_SIZE_LOAS (8194) enum { LATM_MAX_PROG = 1, - LATM_MAX_LAYER = 2, - LATM_MAX_VAR_CHUNKS=16, - LATM_MAX_ID=16 + LATM_MAX_LAYER = 1, + LATM_MAX_VAR_CHUNKS = 16, + LATM_MAX_ID = 16 }; typedef struct { @@ -118,7 +129,7 @@ typedef struct { LATM_LAYER_INFO m_linfo[LATM_MAX_PROG][LATM_MAX_LAYER]; UINT m_taraBufferFullness; UINT m_otherDataLength; - UINT m_audioMuxLengthBytes; /* Length of LOAS payload */ + UINT m_audioMuxLengthBytes; /* Length of LOAS payload */ UCHAR m_useSameStreamMux; UCHAR m_AudioMuxVersion; @@ -126,27 +137,28 @@ typedef struct { UCHAR m_allStreamsSameTimeFraming; UCHAR m_noSubFrames; UCHAR m_numProgram; - UCHAR m_numLayer; - UCHAR m_useSameConfig; + UCHAR m_numLayer[LATM_MAX_PROG]; UCHAR m_otherDataPresent; UCHAR m_crcCheckPresent; - UCHAR m_crcCheckSum; SCHAR BufferFullnessAchieved; + UCHAR + usacExplicitCfgChanged; /* explicit config in case of USAC and LOAS/LATM + must be compared to IPF cfg */ + UCHAR applyAsc; /* apply ASC immediate without flushing */ + UCHAR newCfgHasAudioPreRoll; /* the new (dummy parsed) config has an + AudioPreRoll */ } CLatmDemux; int CLatmDemux_ReadAuChunkLengthInfo(HANDLE_FDK_BITSTREAM bs); -TRANSPORTDEC_ERROR CLatmDemux_Read( - HANDLE_FDK_BITSTREAM bs, - CLatmDemux *pLatmDemux, - TRANSPORT_TYPE tt, - CSTpCallBacks *pTpDecCallbacks, - CSAudioSpecificConfig *pAsc, - int *pfConfigFound, - const INT ignoreBufferFullness - ); +TRANSPORTDEC_ERROR CLatmDemux_Read(HANDLE_FDK_BITSTREAM bs, + CLatmDemux *pLatmDemux, TRANSPORT_TYPE tt, + CSTpCallBacks *pTpDecCallbacks, + CSAudioSpecificConfig *pAsc, + int *pfConfigFound, + const INT ignoreBufferFullness); /** * \brief Read StreamMuxConfig @@ -154,23 +166,26 @@ TRANSPORTDEC_ERROR CLatmDemux_Read( * \param pLatmDemux pointer to CLatmDemux struct of current LATM context * \param pTpDecCallbacks Call back structure for configuration callbacks * \param pAsc pointer to a ASC for configuration storage - * \param pfConfigFound pointer to a flag which is set to 1 if a configuration was found and processed successfully + * \param pfConfigFound pointer to a flag which is set to 1 if a configuration + * was found and processed successfully + * \param configMode Config modes: memory allocation mode or config change + * detection mode + * \param configChanged Indicates a config change * \return error code */ TRANSPORTDEC_ERROR CLatmDemux_ReadStreamMuxConfig( - HANDLE_FDK_BITSTREAM bs, - CLatmDemux *pLatmDemux, - CSTpCallBacks *pTpDecCallbacks, - CSAudioSpecificConfig *pAsc, - int * pfConfigFound - ); - -TRANSPORTDEC_ERROR CLatmDemux_ReadPayloadLengthInfo(HANDLE_FDK_BITSTREAM bs, CLatmDemux *pLatmDemux); - -int CLatmDemux_GetFrameLengthInBits(CLatmDemux *pLatmDemux); -int CLatmDemux_GetOtherDataPresentFlag(CLatmDemux *pLatmDemux); -int CLatmDemux_GetOtherDataLength(CLatmDemux *pLatmDemux); -UINT CLatmDemux_GetNrOfSubFrames(CLatmDemux *pLatmDemux); + HANDLE_FDK_BITSTREAM bs, CLatmDemux *pLatmDemux, + CSTpCallBacks *pTpDecCallbacks, CSAudioSpecificConfig *pAsc, + int *pfConfigFound, UCHAR configMode, UCHAR configChanged); + +TRANSPORTDEC_ERROR CLatmDemux_ReadPayloadLengthInfo(HANDLE_FDK_BITSTREAM bs, + CLatmDemux *pLatmDemux); +UINT CLatmDemux_GetFrameLengthInBits(CLatmDemux *pLatmDemux, const UINT prog, + const UINT layer); +UINT CLatmDemux_GetOtherDataPresentFlag(CLatmDemux *pLatmDemux); +UINT CLatmDemux_GetOtherDataLength(CLatmDemux *pLatmDemux); +UINT CLatmDemux_GetNrOfSubFrames(CLatmDemux *pLatmDemux); +UINT CLatmDemux_GetNrOfLayers(CLatmDemux *pLatmDemux, const UINT program); -#endif /* LATM_DEMUX_H */ +#endif /* TPDEC_LATM_H */ diff --git a/libMpegTPDec/src/tpdec_lib.cpp b/libMpegTPDec/src/tpdec_lib.cpp index 24f755b..10e3352 100644 --- a/libMpegTPDec/src/tpdec_lib.cpp +++ b/libMpegTPDec/src/tpdec_lib.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,20 +90,20 @@ Am Wolfsmantel 33 www.iis.fraunhofer.de/amm amm-info@iis.fraunhofer.de ------------------------------------------------------------------------------------------------------------ */ +----------------------------------------------------------------------------- */ + +/******************* MPEG transport format decoder library ********************* -/************************** MPEG-4 Transport Decoder ************************ + Author(s): Manuel Jander - Author(s): Manuel Jander Description: MPEG Transport decoder -******************************************************************************/ +*******************************************************************************/ #include "tpdec_lib.h" /* library version */ -#include "version" - +#include "tp_version.h" #include "tp_data.h" @@ -104,6 +115,7 @@ amm-info@iis.fraunhofer.de #include "tpdec_drm.h" +#include "FDK_crc.h" #define MODULE_NAME "transportDec" @@ -118,51 +130,70 @@ typedef union { } transportdec_parser_t; -struct TRANSPORTDEC -{ - TRANSPORT_TYPE transportFmt; /*!< MPEG4 transportDec type. */ - - CSTpCallBacks callbacks; /*!< Struct holding callback and its data */ - - FDK_BITSTREAM bitStream[2]; /* Bitstream reader */ - UCHAR *bsBuffer; /* Internal bitstreamd data buffer (unallocated in case of TT_MP4_RAWPACKETS) */ - - transportdec_parser_t parser; /* Format specific parser structs. */ - - CSAudioSpecificConfig asc[(1*2)]; /* Audio specific config from the last config found. */ - UINT globalFramePos; /* Global transport frame reference bit position. */ - UINT accessUnitAnchor[2]; /* Current access unit start bit position. */ - INT auLength[2]; /* Length of current access unit. */ - INT numberOfRawDataBlocks; /* Current number of raw data blocks contained remaining from the current transport frame. */ - UINT avgBitRate; /* Average bit rate used for frame loss estimation. */ - UINT lastValidBufferFullness; /* Last valid buffer fullness value for frame loss estimation */ - INT remainder; /* Reminder in division during lost access unit estimation. */ - INT missingAccessUnits; /* Estimated missing access units. */ - UINT burstPeriod; /* Data burst period in mili seconds. */ - UINT holdOffFrames; /* Amount of frames that were already hold off due to buffer fullness condition not being met. */ - UINT flags; /* Flags. */ +#define MHAS_CONFIG_PRESENT 0x001 +#define MHAS_UI_PRESENT 0x002 + +struct TRANSPORTDEC { + TRANSPORT_TYPE transportFmt; /*!< MPEG4 transportDec type. */ + + CSTpCallBacks callbacks; /*!< Struct holding callback and its data */ + + FDK_BITSTREAM bitStream[1]; /* Bitstream reader */ + UCHAR *bsBuffer; /* Internal bitstreamd data buffer */ + + transportdec_parser_t parser; /* Format specific parser structs. */ + + CSAudioSpecificConfig asc[(1 * 1) + 1]; /* Audio specific config from the last + config found. One additional + CSAudioSpecificConfig is used + temporarily for parsing. */ + CCtrlCFGChange ctrlCFGChange[(1 * 1)]; /* Controls config change */ + + UINT globalFramePos; /* Global transport frame reference bit position. */ + UINT accessUnitAnchor[1]; /* Current access unit start bit position. */ + INT auLength[1]; /* Length of current access unit. */ + INT numberOfRawDataBlocks; /* Current number of raw data blocks contained + remaining from the current transport frame. */ + UINT avgBitRate; /* Average bit rate used for frame loss estimation. */ + UINT lastValidBufferFullness; /* Last valid buffer fullness value for frame + loss estimation */ + INT remainder; /* Reminder in division during lost access unit estimation. */ + INT missingAccessUnits; /* Estimated missing access units. */ + UINT burstPeriod; /* Data burst period in mili seconds. */ + UINT holdOffFrames; /* Amount of frames that were already hold off due to + buffer fullness condition not being met. */ + UINT flags; /* Flags. */ + INT targetLayout; /* CICP target layout. */ + UINT *pLoudnessInfoSetPosition; /* Reference and start position (bits) and + length (bytes) of loudnessInfoSet within + rsv603daConfig. */ }; /* Flag bitmasks for "flags" member of struct TRANSPORTDEC */ -#define TPDEC_SYNCOK 1 -#define TPDEC_MINIMIZE_DELAY 2 +#define TPDEC_SYNCOK 1 +#define TPDEC_MINIMIZE_DELAY 2 #define TPDEC_IGNORE_BUFFERFULLNESS 4 -#define TPDEC_EARLY_CONFIG 8 -#define TPDEC_LOST_FRAMES_PENDING 16 -#define TPDEC_CONFIG_FOUND 32 +#define TPDEC_EARLY_CONFIG 8 +#define TPDEC_LOST_FRAMES_PENDING 16 +#define TPDEC_CONFIG_FOUND 32 +#define TPDEC_USE_ELEM_SKIPPING 64 -C_ALLOC_MEM(Ram_TransportDecoder, TRANSPORTDEC, 1) -C_ALLOC_MEM(Ram_TransportDecoderBuffer, UCHAR, TRANSPORTDEC_INBUF_SIZE) +/* force config/content change */ +#define TPDEC_FORCE_CONFIG_CHANGE 1 +#define TPDEC_FORCE_CONTENT_CHANGE 2 +/* skip packet */ +#define TPDEC_SKIP_PACKET 1 +C_ALLOC_MEM(Ram_TransportDecoder, struct TRANSPORTDEC, 1) +C_ALLOC_MEM(Ram_TransportDecoderBuffer, UCHAR, (8192 * 4)) - -HANDLE_TRANSPORTDEC transportDec_Open( const TRANSPORT_TYPE transportFmt, const UINT flags) -{ +HANDLE_TRANSPORTDEC transportDec_Open(const TRANSPORT_TYPE transportFmt, + const UINT flags, const UINT nrOfLayers) { HANDLE_TRANSPORTDEC hInput; hInput = GetRam_TransportDecoder(0); - if ( hInput == NULL ) { + if (hInput == NULL) { return NULL; } @@ -170,106 +201,355 @@ HANDLE_TRANSPORTDEC transportDec_Open( const TRANSPORT_TYPE transportFmt, const hInput->transportFmt = transportFmt; switch (transportFmt) { + case TT_MP4_ADIF: + break; + + case TT_MP4_ADTS: + if (flags & TP_FLAG_MPEG4) + hInput->parser.adts.decoderCanDoMpeg4 = 1; + else + hInput->parser.adts.decoderCanDoMpeg4 = 0; + adtsRead_CrcInit(&hInput->parser.adts); + hInput->parser.adts.BufferFullnesStartFlag = 1; + hInput->numberOfRawDataBlocks = 0; + break; + + case TT_DRM: + drmRead_CrcInit(&hInput->parser.drm); + break; + + case TT_MP4_LATM_MCP0: + case TT_MP4_LATM_MCP1: + hInput->parser.latm.usacExplicitCfgChanged = 0; + hInput->parser.latm.applyAsc = 1; + break; + case TT_MP4_LOAS: + hInput->parser.latm.usacExplicitCfgChanged = 0; + hInput->parser.latm.applyAsc = 1; + break; + case TT_MP4_RAW: + break; - case TT_MP4_ADIF: - break; - - case TT_MP4_ADTS: - if (flags & TP_FLAG_MPEG4) - hInput->parser.adts.decoderCanDoMpeg4 = 1; - else - hInput->parser.adts.decoderCanDoMpeg4 = 0; - adtsRead_CrcInit(&hInput->parser.adts); - hInput->parser.adts.BufferFullnesStartFlag = 1; - hInput->numberOfRawDataBlocks = 0; - break; - - case TT_DRM: - drmRead_CrcInit(&hInput->parser.drm); - break; - - case TT_MP4_LATM_MCP0: - case TT_MP4_LATM_MCP1: - case TT_MP4_LOAS: - case TT_MP4_RAW: - break; - - default: - FreeRam_TransportDecoder(&hInput); - hInput = NULL; - break; + default: + FreeRam_TransportDecoder(&hInput); + hInput = NULL; + break; } if (hInput != NULL) { /* Create bitstream */ - if ( TT_IS_PACKET(transportFmt) ) { - hInput->bsBuffer = NULL; - } else { + { hInput->bsBuffer = GetRam_TransportDecoderBuffer(0); if (hInput->bsBuffer == NULL) { - transportDec_Close( &hInput ); - return NULL; + transportDec_Close(&hInput); + return NULL; + } + if (nrOfLayers > 1) { + transportDec_Close(&hInput); + return NULL; + } + for (UINT i = 0; i < nrOfLayers; i++) { + FDKinitBitStream(&hInput->bitStream[i], hInput->bsBuffer, (8192 * 4), 0, + BS_READER); } - FDKinitBitStream(&hInput->bitStream[0], hInput->bsBuffer, TRANSPORTDEC_INBUF_SIZE, 0, BS_READER); } - hInput->burstPeriod = 0; } return hInput; } -TRANSPORTDEC_ERROR transportDec_OutOfBandConfig(HANDLE_TRANSPORTDEC hTp, UCHAR *conf, const UINT length, UINT layer ) -{ - TRANSPORTDEC_ERROR err = TRANSPORTDEC_OK; +TRANSPORTDEC_ERROR transportDec_OutOfBandConfig(HANDLE_TRANSPORTDEC hTp, + UCHAR *conf, const UINT length, + UINT layer) { + int i; - FDK_BITSTREAM bs; - HANDLE_FDK_BITSTREAM hBs = &bs; + TRANSPORTDEC_ERROR err = TRANSPORTDEC_OK; - FDKinitBitStream(hBs, conf, 0x10000000, length<<3, BS_READER); + FDK_BITSTREAM bs; + HANDLE_FDK_BITSTREAM hBs = &bs; int fConfigFound = 0; - /* config transport decoder */ - switch (hTp->transportFmt) { - case TT_MP4_LATM_MCP0: - case TT_MP4_LATM_MCP1: - case TT_MP4_LOAS: - { + UCHAR configChanged = 0; + UCHAR configMode = AC_CM_DET_CFG_CHANGE; + + UCHAR tmpConf[1024]; + if (length > 1024) { + return TRANSPORTDEC_UNSUPPORTED_FORMAT; + } + FDKmemcpy(tmpConf, conf, length); + FDKinitBitStream(hBs, tmpConf, 1024, length << 3, BS_READER); + + for (i = 0; i < 2; i++) { + if (i > 0) { + FDKpushBack(hBs, length * 8 - FDKgetValidBits(hBs)); + configMode = AC_CM_ALLOC_MEM; + } + + /* config transport decoder */ + switch (hTp->transportFmt) { + case TT_MP4_LATM_MCP0: + case TT_MP4_LATM_MCP1: + case TT_MP4_LOAS: { if (layer != 0) { return TRANSPORTDEC_INVALID_PARAMETER; } CLatmDemux *pLatmDemux = &hTp->parser.latm; - err = CLatmDemux_ReadStreamMuxConfig(hBs, pLatmDemux, &hTp->callbacks, hTp->asc, &fConfigFound); + err = CLatmDemux_ReadStreamMuxConfig(hBs, pLatmDemux, &hTp->callbacks, + hTp->asc, &fConfigFound, + configMode, configChanged); if (err != TRANSPORTDEC_OK) { return err; } - } - break; - default: - fConfigFound = 1; - err = AudioSpecificConfig_Parse(&hTp->asc[layer], hBs, 1, &hTp->callbacks); - if (err == TRANSPORTDEC_OK) { + } break; + default: + fConfigFound = 1; + err = AudioSpecificConfig_Parse(&hTp->asc[(1 * 1)], hBs, 1, + &hTp->callbacks, configMode, + configChanged, AOT_NULL_OBJECT); + if (err == TRANSPORTDEC_OK) { + int errC; + + hTp->asc[layer] = hTp->asc[(1 * 1)]; + errC = hTp->callbacks.cbUpdateConfig( + hTp->callbacks.cbUpdateConfigData, &hTp->asc[layer], + hTp->asc[layer].configMode, &hTp->asc[layer].AacConfigChanged); + if (errC != 0) { + err = TRANSPORTDEC_PARSE_ERROR; + } + } + break; + case TT_DRM: + fConfigFound = 1; + err = DrmRawSdcAudioConfig_Parse(&hTp->asc[layer], hBs, &hTp->callbacks, + configMode, configChanged); + if (err == TRANSPORTDEC_OK) { + int errC; + + errC = hTp->callbacks.cbUpdateConfig( + hTp->callbacks.cbUpdateConfigData, &hTp->asc[layer], + hTp->asc[layer].configMode, &hTp->asc[layer].AacConfigChanged); + if (errC != 0) { + err = TRANSPORTDEC_PARSE_ERROR; + } + } + break; + } + + if (err == TRANSPORTDEC_OK) { + if ((i == 0) && (hTp->asc[layer].AacConfigChanged || + hTp->asc[layer].SbrConfigChanged || + hTp->asc[layer].SacConfigChanged)) { int errC; - errC = hTp->callbacks.cbUpdateConfig(hTp->callbacks.cbUpdateConfigData, &hTp->asc[layer]); + configChanged = 1; + errC = hTp->callbacks.cbFreeMem(hTp->callbacks.cbFreeMemData, + &hTp->asc[layer]); if (errC != 0) { err = TRANSPORTDEC_PARSE_ERROR; } } - break; - case TT_DRM: + } + } + + if (err == TRANSPORTDEC_OK && fConfigFound) { + hTp->flags |= TPDEC_CONFIG_FOUND; + } + + return err; +} + +TRANSPORTDEC_ERROR transportDec_InBandConfig(HANDLE_TRANSPORTDEC hTp, + UCHAR *newConfig, + const UINT newConfigLength, + const UCHAR buildUpStatus, + UCHAR *configChanged, UINT layer, + UCHAR *implicitExplicitCfgDiff) { + int errC; + FDK_BITSTREAM bs; + HANDLE_FDK_BITSTREAM hBs = &bs; + TRANSPORTDEC_ERROR err = TRANSPORTDEC_OK; + int fConfigFound = 0; + UCHAR configMode = AC_CM_ALLOC_MEM; + *implicitExplicitCfgDiff = 0; + + FDK_ASSERT(hTp->asc->m_aot == AOT_USAC); + + FDKinitBitStream(hBs, newConfig, TP_USAC_MAX_CONFIG_LEN, newConfigLength << 3, + BS_READER); + + if ((hTp->ctrlCFGChange[layer].flushStatus == TPDEC_FLUSH_OFF) && + (hTp->ctrlCFGChange[layer].buildUpStatus != + TPDEC_RSV60_BUILD_UP_IDLE_IN_BAND)) { + if (hTp->asc->m_aot == AOT_USAC) { + if ((UINT)(hTp->asc->m_sc.m_usacConfig.UsacConfigBits + 7) >> 3 == + newConfigLength) { + if (0 == FDKmemcmp(newConfig, hTp->asc->m_sc.m_usacConfig.UsacConfig, + newConfigLength)) { + if (hTp->parser.latm.usacExplicitCfgChanged) { /* configChange from + LOAS/LATM parser */ + hTp->parser.latm.usacExplicitCfgChanged = 0; + hTp->ctrlCFGChange[layer].flushCnt = 0; + hTp->ctrlCFGChange[layer].flushStatus = + TPDEC_USAC_DASH_IPF_FLUSH_ON; + hTp->ctrlCFGChange[layer].buildUpCnt = 0; + hTp->ctrlCFGChange[layer].buildUpStatus = TPDEC_BUILD_UP_OFF; + } else { + *configChanged = 0; + return err; + } + } else { + *implicitExplicitCfgDiff = 1; + } + } else { + *implicitExplicitCfgDiff = 1; + } + /* ISO/IEC 23003-3:2012/FDAM 3:2016(E) Annex F.2: explicit and implicit + * config shall be identical. */ + if (*implicitExplicitCfgDiff) { + switch (hTp->transportFmt) { + case TT_MP4_LATM_MCP0: + case TT_MP4_LATM_MCP1: + case TT_MP4_LOAS: + /* reset decoder to initial state to achieve definite behavior after + * error in config */ + hTp->callbacks.cbFreeMem(hTp->callbacks.cbFreeMemData, + &hTp->asc[layer]); + hTp->parser.latm.usacExplicitCfgChanged = 0; + hTp->parser.latm.applyAsc = 1; + err = TRANSPORTDEC_PARSE_ERROR; + goto bail; + default: + break; + } + } + } + } + + { + if ((hTp->ctrlCFGChange[layer].flushStatus == TPDEC_FLUSH_OFF) && + (hTp->ctrlCFGChange[layer].buildUpStatus != + TPDEC_RSV60_BUILD_UP_IDLE_IN_BAND)) { + hTp->ctrlCFGChange[layer].flushCnt = 0; + hTp->ctrlCFGChange[layer].buildUpCnt = 0; + hTp->ctrlCFGChange[layer].buildUpStatus = TPDEC_BUILD_UP_OFF; + if (hTp->asc->m_aot == AOT_USAC) { + hTp->ctrlCFGChange[layer].flushStatus = TPDEC_USAC_DASH_IPF_FLUSH_ON; + } + } + + if ((hTp->ctrlCFGChange[layer].flushStatus == + TPDEC_RSV60_DASH_IPF_ATSC_FLUSH_ON) || + (hTp->ctrlCFGChange[layer].flushStatus == + TPDEC_USAC_DASH_IPF_FLUSH_ON)) { + SCHAR counter = 0; + if (hTp->asc->m_aot == AOT_USAC) { + counter = TPDEC_USAC_NUM_CONFIG_CHANGE_FRAMES; + } + if (hTp->ctrlCFGChange[layer].flushCnt >= counter) { + hTp->ctrlCFGChange[layer].flushCnt = 0; + hTp->ctrlCFGChange[layer].flushStatus = TPDEC_FLUSH_OFF; + hTp->ctrlCFGChange[layer].forceCfgChange = 0; + if (hTp->asc->m_aot == AOT_USAC) { + hTp->ctrlCFGChange[layer].buildUpCnt = + TPDEC_USAC_NUM_CONFIG_CHANGE_FRAMES - 1; + hTp->ctrlCFGChange[layer].buildUpStatus = TPDEC_USAC_BUILD_UP_ON; + } + } + + /* Activate flush mode. After that continue with build up mode in core */ + if (hTp->callbacks.cbCtrlCFGChange(hTp->callbacks.cbCtrlCFGChangeData, + &hTp->ctrlCFGChange[layer]) != 0) { + err = TRANSPORTDEC_PARSE_ERROR; + } + + if ((hTp->ctrlCFGChange[layer].flushStatus == + TPDEC_RSV60_DASH_IPF_ATSC_FLUSH_ON) || + (hTp->ctrlCFGChange[layer].flushStatus == + TPDEC_USAC_DASH_IPF_FLUSH_ON)) { + hTp->ctrlCFGChange[layer].flushCnt++; + return err; + } + } + + if (hTp->asc->m_aot == AOT_USAC) { fConfigFound = 1; - err = DrmRawSdcAudioConfig_Parse(&hTp->asc[layer], hBs); + if (err == TRANSPORTDEC_OK) { - int errC; + *configChanged = 0; + configMode = AC_CM_DET_CFG_CHANGE; - errC = hTp->callbacks.cbUpdateConfig(hTp->callbacks.cbUpdateConfigData, &hTp->asc[layer]); - if (errC != 0) { - err = TRANSPORTDEC_PARSE_ERROR; + for (int i = 0; i < 2; i++) { + if (i > 0) { + FDKpushBack(hBs, newConfigLength * 8 - FDKgetValidBits(hBs)); + configMode = AC_CM_ALLOC_MEM; + } + /* config transport decoder */ + err = AudioSpecificConfig_Parse( + &hTp->asc[(1 * 1)], hBs, 0, &hTp->callbacks, configMode, + *configChanged, hTp->asc[layer].m_aot); + if (err == TRANSPORTDEC_OK) { + hTp->asc[layer] = hTp->asc[(1 * 1)]; + errC = hTp->callbacks.cbUpdateConfig( + hTp->callbacks.cbUpdateConfigData, &hTp->asc[layer], + hTp->asc[layer].configMode, &hTp->asc[layer].AacConfigChanged); + if (errC != 0) { + err = TRANSPORTDEC_PARSE_ERROR; + } + } + + if (err == TRANSPORTDEC_OK) { + if ((i == 0) && (hTp->asc[layer].AacConfigChanged || + hTp->asc[layer].SbrConfigChanged || + hTp->asc[layer].SacConfigChanged)) { + *configChanged = 1; + errC = hTp->callbacks.cbFreeMem(hTp->callbacks.cbFreeMemData, + &hTp->asc[layer]); + if (errC != 0) { + err = TRANSPORTDEC_PARSE_ERROR; + } + } + } + + /* if an error is detected terminate config parsing to avoid that an + * invalid config is accepted in the second pass */ + if (err != TRANSPORTDEC_OK) { + break; + } } } - break; + } + + bail: + /* save new config */ + if (err == TRANSPORTDEC_OK) { + if (hTp->asc->m_aot == AOT_USAC) { + hTp->asc->m_sc.m_usacConfig.UsacConfigBits = newConfigLength << 3; + FDKmemcpy(hTp->asc->m_sc.m_usacConfig.UsacConfig, newConfig, + newConfigLength); + /* in case of USAC reset transportDecoder variables here because + * otherwise without IPF they are not reset */ + hTp->ctrlCFGChange[layer].flushCnt = 0; + hTp->ctrlCFGChange[layer].flushStatus = TPDEC_FLUSH_OFF; + hTp->ctrlCFGChange[layer].buildUpCnt = 0; + hTp->ctrlCFGChange[layer].buildUpStatus = TPDEC_BUILD_UP_OFF; + } + } else { + hTp->numberOfRawDataBlocks = 0; + + /* If parsing error while config found, clear ctrlCFGChange-struct */ + hTp->ctrlCFGChange[layer].flushCnt = 0; + hTp->ctrlCFGChange[layer].flushStatus = TPDEC_FLUSH_OFF; + hTp->ctrlCFGChange[layer].buildUpCnt = 0; + hTp->ctrlCFGChange[layer].buildUpStatus = TPDEC_BUILD_UP_OFF; + hTp->ctrlCFGChange[layer].cfgChanged = 0; + hTp->ctrlCFGChange[layer].contentChanged = 0; + hTp->ctrlCFGChange[layer].forceCfgChange = 0; + + hTp->callbacks.cbCtrlCFGChange(hTp->callbacks.cbCtrlCFGChangeData, + &hTp->ctrlCFGChange[layer]); + } } if (err == TRANSPORTDEC_OK && fConfigFound) { @@ -279,8 +559,9 @@ TRANSPORTDEC_ERROR transportDec_OutOfBandConfig(HANDLE_TRANSPORTDEC hTp, UCHAR * return err; } -int transportDec_RegisterAscCallback( HANDLE_TRANSPORTDEC hTpDec, const cbUpdateConfig_t cbUpdateConfig, void* user_data) -{ +int transportDec_RegisterAscCallback(HANDLE_TRANSPORTDEC hTpDec, + const cbUpdateConfig_t cbUpdateConfig, + void *user_data) { if (hTpDec == NULL) { return -1; } @@ -289,8 +570,30 @@ int transportDec_RegisterAscCallback( HANDLE_TRANSPORTDEC hTpDec, const cbUpdate return 0; } -int transportDec_RegisterSscCallback( HANDLE_TRANSPORTDEC hTpDec, const cbSsc_t cbSsc, void* user_data) -{ +int transportDec_RegisterFreeMemCallback(HANDLE_TRANSPORTDEC hTpDec, + const cbFreeMem_t cbFreeMem, + void *user_data) { + if (hTpDec == NULL) { + return -1; + } + hTpDec->callbacks.cbFreeMem = cbFreeMem; + hTpDec->callbacks.cbFreeMemData = user_data; + return 0; +} + +int transportDec_RegisterCtrlCFGChangeCallback( + HANDLE_TRANSPORTDEC hTpDec, const cbCtrlCFGChange_t cbCtrlCFGChange, + void *user_data) { + if (hTpDec == NULL) { + return -1; + } + hTpDec->callbacks.cbCtrlCFGChange = cbCtrlCFGChange; + hTpDec->callbacks.cbCtrlCFGChangeData = user_data; + return 0; +} + +int transportDec_RegisterSscCallback(HANDLE_TRANSPORTDEC hTpDec, + const cbSsc_t cbSsc, void *user_data) { if (hTpDec == NULL) { return -1; } @@ -299,8 +602,8 @@ int transportDec_RegisterSscCallback( HANDLE_TRANSPORTDEC hTpDec, const cbSsc_t return 0; } -int transportDec_RegisterSbrCallback( HANDLE_TRANSPORTDEC hTpDec, const cbSbr_t cbSbr, void* user_data) -{ +int transportDec_RegisterSbrCallback(HANDLE_TRANSPORTDEC hTpDec, + const cbSbr_t cbSbr, void *user_data) { if (hTpDec == NULL) { return -1; } @@ -309,65 +612,86 @@ int transportDec_RegisterSbrCallback( HANDLE_TRANSPORTDEC hTpDec, const cbSbr_t return 0; } -TRANSPORTDEC_ERROR transportDec_FillData( - const HANDLE_TRANSPORTDEC hTp, - UCHAR *pBuffer, - const UINT bufferSize, - UINT *pBytesValid, - const INT layer ) -{ - HANDLE_FDK_BITSTREAM hBs; +int transportDec_RegisterUsacCallback(HANDLE_TRANSPORTDEC hTpDec, + const cbUsac_t cbUsac, void *user_data) { + if (hTpDec == NULL) { + return -1; + } + hTpDec->callbacks.cbUsac = cbUsac; + hTpDec->callbacks.cbUsacData = user_data; + return 0; +} - if ( (hTp == NULL) - || (layer >= 2) ) { - return TRANSPORTDEC_INVALID_PARAMETER; +int transportDec_RegisterUniDrcConfigCallback(HANDLE_TRANSPORTDEC hTpDec, + const cbUniDrc_t cbUniDrc, + void *user_data, + UINT *pLoudnessInfoSetPosition) { + if (hTpDec == NULL) { + return -1; } - if (*pBytesValid == 0) { - /* nothing to do */ - return TRANSPORTDEC_OK; + hTpDec->callbacks.cbUniDrc = cbUniDrc; + hTpDec->callbacks.cbUniDrcData = user_data; + + hTpDec->pLoudnessInfoSetPosition = pLoudnessInfoSetPosition; + return 0; +} + +TRANSPORTDEC_ERROR transportDec_FillData(const HANDLE_TRANSPORTDEC hTp, + UCHAR *pBuffer, const UINT bufferSize, + UINT *pBytesValid, const INT layer) { + HANDLE_FDK_BITSTREAM hBs; + + if ((hTp == NULL) || (layer >= 1)) { + return TRANSPORTDEC_INVALID_PARAMETER; } /* set bitbuffer shortcut */ hBs = &hTp->bitStream[layer]; - if ( TT_IS_PACKET(hTp->transportFmt) ) { + if (TT_IS_PACKET(hTp->transportFmt)) { if (hTp->numberOfRawDataBlocks == 0) { - /* For packet based transport, pass input buffer to bitbuffer without copying the data. - Unfortunately we do not know the actual buffer size. And the FDK bit buffer implementation - needs a number 2^x. So we assume the maximum of 48 channels with 6144 bits per channel - and round it up to the next power of 2 => 65536 bytes */ - FDKinitBitStream(hBs, pBuffer, 0x10000, (*pBytesValid)<<3, BS_READER); - *pBytesValid = 0; + FDKresetBitbuffer(hBs); + FDKfeedBuffer(hBs, pBuffer, bufferSize, pBytesValid); + if (*pBytesValid != 0) { + return TRANSPORTDEC_TOO_MANY_BITS; + } } } else { /* ... else feed bitbuffer with new stream data (append). */ + + if (*pBytesValid == 0) { + /* nothing to do */ + return TRANSPORTDEC_OK; + } + if (hTp->numberOfRawDataBlocks <= 0) { - FDKfeedBuffer (hBs, pBuffer, bufferSize, pBytesValid) ; + FDKfeedBuffer(hBs, pBuffer, bufferSize, pBytesValid); } } return TRANSPORTDEC_OK; } -HANDLE_FDK_BITSTREAM transportDec_GetBitstream( const HANDLE_TRANSPORTDEC hTp, const UINT layer ) -{ +HANDLE_FDK_BITSTREAM transportDec_GetBitstream(const HANDLE_TRANSPORTDEC hTp, + const UINT layer) { return &hTp->bitStream[layer]; } -TRANSPORT_TYPE transportDec_GetFormat( const HANDLE_TRANSPORTDEC hTp ) -{ +TRANSPORT_TYPE transportDec_GetFormat(const HANDLE_TRANSPORTDEC hTp) { return hTp->transportFmt; } -INT transportDec_GetBufferFullness( const HANDLE_TRANSPORTDEC hTp ) -{ +INT transportDec_GetBufferFullness(const HANDLE_TRANSPORTDEC hTp) { INT bufferFullness = -1; switch (hTp->transportFmt) { case TT_MP4_ADTS: if (hTp->parser.adts.bs.adts_fullness != 0x7ff) { - bufferFullness = hTp->parser.adts.bs.frame_length*8 + hTp->parser.adts.bs.adts_fullness * 32 * getNumberOfEffectiveChannels(hTp->parser.adts.bs.channel_config); + bufferFullness = hTp->parser.adts.bs.frame_length * 8 + + hTp->parser.adts.bs.adts_fullness * 32 * + getNumberOfEffectiveChannels( + hTp->parser.adts.bs.channel_config); } break; case TT_MP4_LOAS: @@ -389,31 +713,37 @@ INT transportDec_GetBufferFullness( const HANDLE_TRANSPORTDEC hTp ) * \param hTp transport decoder handle. * \return error code. */ -static -TRANSPORTDEC_ERROR transportDec_AdjustEndOfAccessUnit(HANDLE_TRANSPORTDEC hTp) -{ +static TRANSPORTDEC_ERROR transportDec_AdjustEndOfAccessUnit( + HANDLE_TRANSPORTDEC hTp) { HANDLE_FDK_BITSTREAM hBs = &hTp->bitStream[0]; TRANSPORTDEC_ERROR err = TRANSPORTDEC_OK; switch (hTp->transportFmt) { + case TT_MP4_ADIF: + /* Do byte align at the end of raw_data_block() because UsacFrame() is not + * byte aligned. */ + FDKbyteAlign(hBs, hTp->accessUnitAnchor[0]); + break; case TT_MP4_LOAS: case TT_MP4_LATM_MCP0: case TT_MP4_LATM_MCP1: - if ( hTp->numberOfRawDataBlocks == 0 ) - { + if (hTp->numberOfRawDataBlocks == 0) { /* Do byte align at the end of AudioMuxElement. */ FDKbyteAlign(hBs, hTp->globalFramePos); /* Check global frame length */ - if (hTp->transportFmt == TT_MP4_LOAS && hTp->parser.latm.m_audioMuxLengthBytes > 0) - { + if (hTp->transportFmt == TT_MP4_LOAS && + hTp->parser.latm.m_audioMuxLengthBytes > 0) { int loasOffset; - loasOffset = (hTp->parser.latm.m_audioMuxLengthBytes*8 + FDKgetValidBits(hBs)) - hTp->globalFramePos; + loasOffset = (hTp->parser.latm.m_audioMuxLengthBytes * 8 + + FDKgetValidBits(hBs)) - + hTp->globalFramePos; if (loasOffset != 0) { FDKpushBiDirectional(hBs, loasOffset); - /* For ELD and other payloads there is an unknown amount of padding, so ignore unread bits, but - throw an error only if too many bits where read. */ + /* For ELD and other payloads there is an unknown amount of padding, + so ignore unread bits, but throw an error only if too many bits + where read. */ if (loasOffset < 0) { err = TRANSPORTDEC_PARSE_ERROR; } @@ -423,28 +753,34 @@ TRANSPORTDEC_ERROR transportDec_AdjustEndOfAccessUnit(HANDLE_TRANSPORTDEC hTp) break; case TT_MP4_ADTS: - if (hTp->parser.adts.bs.protection_absent == 0) - { + if (hTp->parser.adts.bs.protection_absent == 0) { int offset; /* Calculate offset to end of AU */ - offset = hTp->parser.adts.rawDataBlockDist[hTp->parser.adts.bs.num_raw_blocks-hTp->numberOfRawDataBlocks]<<3; - /* CAUTION: The PCE (if available) is declared to be a part of the header! */ - offset -= hTp->accessUnitAnchor[0] - FDKgetValidBits(hBs) + 16 + hTp->parser.adts.bs.num_pce_bits; + offset = hTp->parser.adts + .rawDataBlockDist[hTp->parser.adts.bs.num_raw_blocks - + hTp->numberOfRawDataBlocks] + << 3; + /* CAUTION: The PCE (if available) is declared to be a part of the + * header! */ + offset -= (INT)hTp->accessUnitAnchor[0] - (INT)FDKgetValidBits(hBs) + + 16 + hTp->parser.adts.bs.num_pce_bits; FDKpushBiDirectional(hBs, offset); } - if (hTp->parser.adts.bs.num_raw_blocks > 0 && hTp->parser.adts.bs.protection_absent == 0) { - /* Note this CRC read currently happens twice because of transportDec_CrcCheck() */ + if (hTp->parser.adts.bs.num_raw_blocks > 0 && + hTp->parser.adts.bs.protection_absent == 0) { + /* Note this CRC read currently happens twice because of + * transportDec_CrcCheck() */ hTp->parser.adts.crcReadValue = FDKreadBits(hBs, 16); } - if ( hTp->numberOfRawDataBlocks == 0 ) - { + if (hTp->numberOfRawDataBlocks == 0) { /* Check global frame length */ - if (hTp->parser.adts.bs.protection_absent == 0) - { + if (hTp->parser.adts.bs.protection_absent == 0) { int offset; - offset = (hTp->parser.adts.bs.frame_length*8 - ADTS_SYNCLENGTH + FDKgetValidBits(hBs)) - hTp->globalFramePos; + offset = (hTp->parser.adts.bs.frame_length * 8 - ADTS_SYNCLENGTH + + (INT)FDKgetValidBits(hBs)) - + (INT)hTp->globalFramePos; if (offset != 0) { FDKpushBiDirectional(hBs, offset); } @@ -459,41 +795,39 @@ TRANSPORTDEC_ERROR transportDec_AdjustEndOfAccessUnit(HANDLE_TRANSPORTDEC hTp) return err; } - /** - * \brief Determine additional buffer fullness contraint due to burst data reception. - * The parameter TPDEC_PARAM_BURSTPERIOD must have been set as a precondition. + * \brief Determine additional buffer fullness contraint due to burst data + * reception. The parameter TPDEC_PARAM_BURSTPERIOD must have been set as a + * precondition. * \param hTp transport decoder handle. - * \param bufferFullness the buffer fullness value of the first frame to be decoded. - * \param bitsAvail the amount of available bits at the end of the first frame to be decoded. + * \param bufferFullness the buffer fullness value of the first frame to be + * decoded. + * \param bitsAvail the amount of available bits at the end of the first frame + * to be decoded. * \return error code */ -static -TRANSPORTDEC_ERROR additionalHoldOffNeeded( - HANDLE_TRANSPORTDEC hTp, - INT bufferFullness, - INT bitsAvail - ) -{ +static TRANSPORTDEC_ERROR additionalHoldOffNeeded(HANDLE_TRANSPORTDEC hTp, + INT bufferFullness, + INT bitsAvail) { INT checkLengthBits, avgBitsPerFrame; INT maxAU; /* maximum number of frames per Master Frame */ INT samplesPerFrame = hTp->asc->m_samplesPerFrame; INT samplingFrequency = (INT)hTp->asc->m_samplingFrequency; - if ( (hTp->avgBitRate == 0) || (hTp->burstPeriod == 0) ) { + if ((hTp->avgBitRate == 0) || (hTp->burstPeriod == 0)) { return TRANSPORTDEC_OK; } - if ( (samplesPerFrame == 0 ) || (samplingFrequency == 0) ) { + if ((samplesPerFrame == 0) || (samplingFrequency == 0)) { return TRANSPORTDEC_NOT_ENOUGH_BITS; } /* One Master Frame is sent every hTp->burstPeriod ms */ - maxAU = hTp->burstPeriod * samplingFrequency + (samplesPerFrame*1000 - 1); - maxAU = maxAU / (samplesPerFrame*1000); + maxAU = hTp->burstPeriod * samplingFrequency + (samplesPerFrame * 1000 - 1); + maxAU = maxAU / (samplesPerFrame * 1000); /* Subtract number of frames which were already held off. */ maxAU -= hTp->holdOffFrames; - avgBitsPerFrame = hTp->avgBitRate * samplesPerFrame + (samplingFrequency-1); + avgBitsPerFrame = hTp->avgBitRate * samplesPerFrame + (samplingFrequency - 1); avgBitsPerFrame = avgBitsPerFrame / samplingFrequency; /* Consider worst case of bufferFullness quantization. */ @@ -505,41 +839,35 @@ TRANSPORTDEC_ERROR additionalHoldOffNeeded( case TT_MP4_LATM_MCP1: bufferFullness += 31; break; - default: - break; + default: /* added to avoid compiler warning */ + break; /* added to avoid compiler warning */ } - checkLengthBits = bufferFullness + (maxAU-1)*avgBitsPerFrame; + checkLengthBits = bufferFullness + (maxAU - 1) * avgBitsPerFrame; /* Check if buffer is big enough to fullfill buffer fullness condition */ - if ( (checkLengthBits /*+headerBits*/) > ((TRANSPORTDEC_INBUF_SIZE<<3)-7) ) { + if ((checkLengthBits /*+headerBits*/) > (((8192 * 4) << 3) - 7)) { return TRANSPORTDEC_SYNC_ERROR; } - if ( bitsAvail < checkLengthBits ) { + if (bitsAvail < checkLengthBits) { return TRANSPORTDEC_NOT_ENOUGH_BITS; - } - else { + } else { return TRANSPORTDEC_OK; } } static TRANSPORTDEC_ERROR transportDec_readHeader( - HANDLE_TRANSPORTDEC hTp, - HANDLE_FDK_BITSTREAM hBs, - int syncLength, - int ignoreBufferFullness, - int *pRawDataBlockLength, - int *pfTraverseMoreFrames, - int *pSyncLayerFrameBits, - int *pfConfigFound, - int *pHeaderBits - ) -{ + HANDLE_TRANSPORTDEC hTp, HANDLE_FDK_BITSTREAM hBs, int syncLength, + int ignoreBufferFullness, int *pRawDataBlockLength, + int *pfTraverseMoreFrames, int *pSyncLayerFrameBits, int *pfConfigFound, + int *pHeaderBits) { TRANSPORTDEC_ERROR err = TRANSPORTDEC_OK; int rawDataBlockLength = *pRawDataBlockLength; - int fTraverseMoreFrames = (pfTraverseMoreFrames != NULL) ? *pfTraverseMoreFrames : 0; - int syncLayerFrameBits = (pSyncLayerFrameBits != NULL) ? *pSyncLayerFrameBits : 0; + int fTraverseMoreFrames = + (pfTraverseMoreFrames != NULL) ? *pfTraverseMoreFrames : 0; + int syncLayerFrameBits = + (pSyncLayerFrameBits != NULL) ? *pSyncLayerFrameBits : 0; int fConfigFound = (pfConfigFound != NULL) ? *pfConfigFound : 0; int startPos; @@ -547,46 +875,74 @@ static TRANSPORTDEC_ERROR transportDec_readHeader( switch (hTp->transportFmt) { case TT_MP4_ADTS: - if (hTp->numberOfRawDataBlocks <= 0) - { - int errC; + if (hTp->numberOfRawDataBlocks <= 0) { + int i, errC; hTp->globalFramePos = FDKgetValidBits(hBs); - /* Parse ADTS header */ - err = adtsRead_DecodeHeader( &hTp->parser.adts, &hTp->asc[0], hBs, ignoreBufferFullness ); - if (err != TRANSPORTDEC_OK) { - if (err != TRANSPORTDEC_NOT_ENOUGH_BITS) { - err = TRANSPORTDEC_SYNC_ERROR; + UCHAR configChanged = 0; + UCHAR configMode = AC_CM_DET_CFG_CHANGE; + + for (i = 0; i < 2; i++) { + if (i > 0) { + FDKpushBack(hBs, + (INT)hTp->globalFramePos - (INT)FDKgetValidBits(hBs)); + configMode = AC_CM_ALLOC_MEM; } - } else { - errC = hTp->callbacks.cbUpdateConfig(hTp->callbacks.cbUpdateConfigData, &hTp->asc[0]); - if (errC != 0) { - if (errC == TRANSPORTDEC_NEED_TO_RESTART) { - err = TRANSPORTDEC_NEED_TO_RESTART; - goto bail; - } else { + + /* Parse ADTS header */ + err = adtsRead_DecodeHeader(&hTp->parser.adts, &hTp->asc[0], hBs, + ignoreBufferFullness); + if (err != TRANSPORTDEC_OK) { + if (err != TRANSPORTDEC_NOT_ENOUGH_BITS) { err = TRANSPORTDEC_SYNC_ERROR; } } else { - fConfigFound = 1; - hTp->numberOfRawDataBlocks = hTp->parser.adts.bs.num_raw_blocks+1; + errC = hTp->callbacks.cbUpdateConfig( + hTp->callbacks.cbUpdateConfigData, &hTp->asc[0], configMode, + &configChanged); + if (errC != 0) { + if (errC == TRANSPORTDEC_NEED_TO_RESTART) { + err = TRANSPORTDEC_NEED_TO_RESTART; + goto bail; + } else { + err = TRANSPORTDEC_SYNC_ERROR; + } + } else { + fConfigFound = 1; + hTp->numberOfRawDataBlocks = + hTp->parser.adts.bs.num_raw_blocks + 1; + } + } + + if (err == TRANSPORTDEC_OK) { + if ((i == 0) && configChanged) { + errC = hTp->callbacks.cbFreeMem(hTp->callbacks.cbFreeMemData, + &hTp->asc[0]); + if (errC != 0) { + err = TRANSPORTDEC_PARSE_ERROR; + } + } } } - } - else { - /* Reset CRC because the next bits are the beginning of a raw_data_block() */ + } else { + /* Reset CRC because the next bits are the beginning of a + * raw_data_block() */ FDKcrcReset(&hTp->parser.adts.crcInfo); hTp->parser.adts.bs.num_pce_bits = 0; } if (err == TRANSPORTDEC_OK) { hTp->numberOfRawDataBlocks--; - rawDataBlockLength = adtsRead_GetRawDataBlockLength(&hTp->parser.adts, (hTp->parser.adts.bs.num_raw_blocks-hTp->numberOfRawDataBlocks)); + rawDataBlockLength = adtsRead_GetRawDataBlockLength( + &hTp->parser.adts, + (hTp->parser.adts.bs.num_raw_blocks - hTp->numberOfRawDataBlocks)); if (rawDataBlockLength <= 0) { /* No further frame traversal possible. */ fTraverseMoreFrames = 0; } - syncLayerFrameBits = (hTp->parser.adts.bs.frame_length<<3) - (startPos - FDKgetValidBits(hBs)) - syncLength; + syncLayerFrameBits = (hTp->parser.adts.bs.frame_length << 3) - + ((INT)startPos - (INT)FDKgetValidBits(hBs)) - + syncLength; if (syncLayerFrameBits <= 0) { err = TRANSPORTDEC_SYNC_ERROR; } @@ -595,35 +951,30 @@ static TRANSPORTDEC_ERROR transportDec_readHeader( } break; case TT_MP4_LOAS: - if (hTp->numberOfRawDataBlocks <= 0) - { + if (hTp->numberOfRawDataBlocks <= 0) { syncLayerFrameBits = FDKreadBits(hBs, 13); hTp->parser.latm.m_audioMuxLengthBytes = syncLayerFrameBits; syncLayerFrameBits <<= 3; } case TT_MP4_LATM_MCP1: case TT_MP4_LATM_MCP0: - if (hTp->numberOfRawDataBlocks <= 0) - { + if (hTp->numberOfRawDataBlocks <= 0) { hTp->globalFramePos = FDKgetValidBits(hBs); - err = CLatmDemux_Read( - hBs, - &hTp->parser.latm, - hTp->transportFmt, - &hTp->callbacks, - hTp->asc, - &fConfigFound, - ignoreBufferFullness); + err = CLatmDemux_Read(hBs, &hTp->parser.latm, hTp->transportFmt, + &hTp->callbacks, hTp->asc, &fConfigFound, + ignoreBufferFullness); if (err != TRANSPORTDEC_OK) { - if (err != TRANSPORTDEC_NOT_ENOUGH_BITS) { + if ((err != TRANSPORTDEC_NOT_ENOUGH_BITS) && + !TPDEC_IS_FATAL_ERROR(err)) { err = TRANSPORTDEC_SYNC_ERROR; } } else { - hTp->numberOfRawDataBlocks = CLatmDemux_GetNrOfSubFrames(&hTp->parser.latm); + hTp->numberOfRawDataBlocks = + CLatmDemux_GetNrOfSubFrames(&hTp->parser.latm); if (hTp->transportFmt == TT_MP4_LOAS) { - syncLayerFrameBits -= startPos - FDKgetValidBits(hBs) - (13); + syncLayerFrameBits -= startPos - FDKgetValidBits(hBs) - (13); } } } else { @@ -633,17 +984,20 @@ static TRANSPORTDEC_ERROR transportDec_readHeader( } } if (err == TRANSPORTDEC_OK) { - rawDataBlockLength = CLatmDemux_GetFrameLengthInBits(&hTp->parser.latm); + int layer; + rawDataBlockLength = 0; + for (layer = 0; + layer < (int)CLatmDemux_GetNrOfLayers(&hTp->parser.latm, 0); + layer += 1) { + rawDataBlockLength += + CLatmDemux_GetFrameLengthInBits(&hTp->parser.latm, 0, layer); + } hTp->numberOfRawDataBlocks--; } else { hTp->numberOfRawDataBlocks = 0; } break; - default: - { - syncLayerFrameBits = 0; - } - break; + default: { syncLayerFrameBits = 0; } break; } bail: @@ -653,6 +1007,24 @@ bail: if (pHeaderBits != NULL) { *pHeaderBits += startPos - (INT)FDKgetValidBits(hBs); } + + for (int i = 0; i < (1 * 1); i++) { + /* If parsing error while config found, clear ctrlCFGChange-struct */ + if (hTp->ctrlCFGChange[i].cfgChanged && err != TRANSPORTDEC_OK) { + hTp->numberOfRawDataBlocks = 0; + hTp->ctrlCFGChange[i].flushCnt = 0; + hTp->ctrlCFGChange[i].flushStatus = TPDEC_FLUSH_OFF; + hTp->ctrlCFGChange[i].buildUpCnt = 0; + hTp->ctrlCFGChange[i].buildUpStatus = TPDEC_BUILD_UP_OFF; + hTp->ctrlCFGChange[i].cfgChanged = 0; + hTp->ctrlCFGChange[i].contentChanged = 0; + hTp->ctrlCFGChange[i].forceCfgChange = 0; + + hTp->callbacks.cbCtrlCFGChange(hTp->callbacks.cbCtrlCFGChangeData, + &hTp->ctrlCFGChange[i]); + } + } + if (pfConfigFound != NULL) { *pfConfigFound = fConfigFound; } @@ -660,12 +1032,9 @@ bail: if (pfTraverseMoreFrames != NULL) { *pfTraverseMoreFrames = fTraverseMoreFrames; } - if (pSyncLayerFrameBits != NULL) { + if (pSyncLayerFrameBits != NULL) { *pSyncLayerFrameBits = syncLayerFrameBits; } - if (pfConfigFound != NULL) { - *pfConfigFound = fConfigFound; - } return err; } @@ -673,12 +1042,8 @@ bail: /* How many bits to advance for synchronization search. */ #define TPDEC_SYNCSKIP 8 -static -TRANSPORTDEC_ERROR synchronization( - HANDLE_TRANSPORTDEC hTp, - INT *pHeaderBits - ) -{ +static TRANSPORTDEC_ERROR synchronization(HANDLE_TRANSPORTDEC hTp, + INT *pHeaderBits) { TRANSPORTDEC_ERROR err = TRANSPORTDEC_OK, errFirstFrame = TRANSPORTDEC_OK; HANDLE_FDK_BITSTREAM hBs = &hTp->bitStream[0]; @@ -686,14 +1051,20 @@ TRANSPORTDEC_ERROR synchronization( INT rawDataBlockLength = 0, rawDataBlockLengthPrevious; INT totalBits; INT headerBits = 0, headerBitsFirstFrame = 0, headerBitsPrevious; - INT numFramesTraversed = 0, fTraverseMoreFrames, fConfigFound = (hTp->flags & TPDEC_CONFIG_FOUND), startPosFirstFrame = -1; - INT numRawDataBlocksFirstFrame = 0, numRawDataBlocksPrevious, globalFramePosFirstFrame = 0, rawDataBlockLengthFirstFrame = 0; - INT ignoreBufferFullness = hTp->flags & (TPDEC_LOST_FRAMES_PENDING|TPDEC_IGNORE_BUFFERFULLNESS|TPDEC_SYNCOK); + INT numFramesTraversed = 0, fTraverseMoreFrames, + fConfigFound = (hTp->flags & TPDEC_CONFIG_FOUND), startPosFirstFrame = -1; + INT numRawDataBlocksFirstFrame = 0, numRawDataBlocksPrevious, + globalFramePosFirstFrame = 0, rawDataBlockLengthFirstFrame = 0; + INT ignoreBufferFullness = + hTp->flags & + (TPDEC_LOST_FRAMES_PENDING | TPDEC_IGNORE_BUFFERFULLNESS | TPDEC_SYNCOK); + UINT endTpFrameBitsPrevious = 0; /* Synch parameters */ - INT syncLength; /* Length of sync word in bits */ - UINT syncWord; /* Sync word to be found */ - UINT syncMask; /* Mask for sync word (for adding one bit, so comprising one bit less) */ + INT syncLength; /* Length of sync word in bits */ + UINT syncWord; /* Sync word to be found */ + UINT syncMask; /* Mask for sync word (for adding one bit, so comprising one + bit less) */ C_ALLOC_SCRATCH_START(contextFirstFrame, transportdec_parser_t, 1); totalBits = (INT)FDKgetValidBits(hBs); @@ -703,7 +1074,9 @@ TRANSPORTDEC_ERROR synchronization( goto bail; } - fTraverseMoreFrames = (hTp->flags & (TPDEC_MINIMIZE_DELAY|TPDEC_EARLY_CONFIG)) && ! (hTp->flags & TPDEC_SYNCOK); + fTraverseMoreFrames = + (hTp->flags & (TPDEC_MINIMIZE_DELAY | TPDEC_EARLY_CONFIG)) && + !(hTp->flags & TPDEC_SYNCOK); /* Set transport specific sync parameters */ switch (hTp->transportFmt) { @@ -721,12 +1094,13 @@ TRANSPORTDEC_ERROR synchronization( break; } - syncMask = (1<<syncLength)-1; + syncMask = (1 << syncLength) - 1; do { - INT bitsAvail = 0; /* Bits available in bitstream buffer */ - INT checkLengthBits; /* Helper to check remaining bits and buffer boundaries */ - UINT synch; /* Current sync word read from bitstream */ + INT bitsAvail = 0; /* Bits available in bitstream buffer */ + INT checkLengthBits; /* Helper to check remaining bits and buffer boundaries + */ + UINT synch; /* Current sync word read from bitstream */ headerBitsPrevious = headerBits; @@ -735,21 +1109,22 @@ TRANSPORTDEC_ERROR synchronization( if (hTp->numberOfRawDataBlocks == 0) { /* search synchword */ - FDK_ASSERT( (bitsAvail % TPDEC_SYNCSKIP) == 0); + FDK_ASSERT((bitsAvail % TPDEC_SYNCSKIP) == 0); - if ((bitsAvail-syncLength) < TPDEC_SYNCSKIP) { + if ((bitsAvail - syncLength) < TPDEC_SYNCSKIP) { err = TRANSPORTDEC_NOT_ENOUGH_BITS; headerBits = 0; } else { - synch = FDKreadBits(hBs, syncLength); - if ( !(hTp->flags & TPDEC_SYNCOK) ) { - for (; (bitsAvail-syncLength) >= TPDEC_SYNCSKIP; bitsAvail-=TPDEC_SYNCSKIP) { + if (!(hTp->flags & TPDEC_SYNCOK)) { + for (; (bitsAvail - syncLength) >= TPDEC_SYNCSKIP; + bitsAvail -= TPDEC_SYNCSKIP) { if (synch == syncWord) { break; } - synch = ((synch << TPDEC_SYNCSKIP) & syncMask) | FDKreadBits(hBs, TPDEC_SYNCSKIP); + synch = ((synch << TPDEC_SYNCSKIP) & syncMask) | + FDKreadBits(hBs, TPDEC_SYNCSKIP); } } if (synch != syncWord) { @@ -770,44 +1145,40 @@ TRANSPORTDEC_ERROR synchronization( /* Parse transport header (raw data block granularity) */ - if (err == TRANSPORTDEC_OK ) - { - err = transportDec_readHeader( - hTp, - hBs, - syncLength, - ignoreBufferFullness, - &rawDataBlockLength, - &fTraverseMoreFrames, - &syncLayerFrameBits, - &fConfigFound, - &headerBits - ); + if (err == TRANSPORTDEC_OK) { + err = transportDec_readHeader(hTp, hBs, syncLength, ignoreBufferFullness, + &rawDataBlockLength, &fTraverseMoreFrames, + &syncLayerFrameBits, &fConfigFound, + &headerBits); + if (TPDEC_IS_FATAL_ERROR(err)) { + goto bail; + } } bitsAvail -= headerBits; - checkLengthBits = syncLayerFrameBits; + checkLengthBits = syncLayerFrameBits; /* Check if the whole frame would fit the bitstream buffer */ if (err == TRANSPORTDEC_OK) { - if ( (checkLengthBits+headerBits) > ((TRANSPORTDEC_INBUF_SIZE<<3)-7) ) { + if ((checkLengthBits + headerBits) > (((8192 * 4) << 3) - 7)) { /* We assume that the size of the transport bit buffer has been chosen to meet all system requirements, thus this condition is considered a synchronisation error. */ err = TRANSPORTDEC_SYNC_ERROR; } else { - if ( bitsAvail < checkLengthBits ) { + if (bitsAvail < checkLengthBits) { err = TRANSPORTDEC_NOT_ENOUGH_BITS; } } } if (err == TRANSPORTDEC_NOT_ENOUGH_BITS) { + /* Enforce reading of new data */ + hTp->numberOfRawDataBlocks = 0; break; } - if (err == TRANSPORTDEC_SYNC_ERROR) { int bits; @@ -816,38 +1187,39 @@ TRANSPORTDEC_ERROR synchronization( /* Ensure that the bit amount lands at a multiple of TPDEC_SYNCSKIP */ bits = (bitsAvail + headerBits) % TPDEC_SYNCSKIP; - /* Rewind - TPDEC_SYNCSKIP, in order to look for a synch one bit ahead next time. */ + /* Rewind - TPDEC_SYNCSKIP, in order to look for a synch one bit ahead + * next time. */ FDKpushBiDirectional(hBs, -(headerBits - TPDEC_SYNCSKIP) + bits); - bitsAvail += headerBits - TPDEC_SYNCSKIP - bits; headerBits = 0; } /* Frame traversal */ - if ( fTraverseMoreFrames ) - { + if (fTraverseMoreFrames) { /* Save parser context for early config discovery "rewind all frames" */ - if ( (hTp->flags & TPDEC_EARLY_CONFIG) && !(hTp->flags & TPDEC_MINIMIZE_DELAY)) - { - /* ignore buffer fullness if just traversing additional frames for ECD */ + if ((hTp->flags & TPDEC_EARLY_CONFIG) && + !(hTp->flags & TPDEC_MINIMIZE_DELAY)) { + /* ignore buffer fullness if just traversing additional frames for ECD + */ ignoreBufferFullness = 1; /* Save context in order to return later */ - if ( err == TRANSPORTDEC_OK && startPosFirstFrame == -1 ) { + if (err == TRANSPORTDEC_OK && startPosFirstFrame == -1) { startPosFirstFrame = FDKgetValidBits(hBs); numRawDataBlocksFirstFrame = hTp->numberOfRawDataBlocks; globalFramePosFirstFrame = hTp->globalFramePos; rawDataBlockLengthFirstFrame = rawDataBlockLength; headerBitsFirstFrame = headerBits; errFirstFrame = err; - FDKmemcpy(contextFirstFrame, &hTp->parser, sizeof(transportdec_parser_t)); + FDKmemcpy(contextFirstFrame, &hTp->parser, + sizeof(transportdec_parser_t)); } - /* Break when config was found or it is not possible anymore to find a config */ - if (startPosFirstFrame != -1 && (fConfigFound || err != TRANSPORTDEC_OK)) - { + /* Break when config was found or it is not possible anymore to find a + * config */ + if (startPosFirstFrame != -1 && + (fConfigFound || err != TRANSPORTDEC_OK)) { /* In case of ECD and sync error, do not rewind anywhere. */ - if (err == TRANSPORTDEC_SYNC_ERROR) - { + if (err == TRANSPORTDEC_SYNC_ERROR) { startPosFirstFrame = -1; fConfigFound = 0; numFramesTraversed = 0; @@ -858,16 +1230,18 @@ TRANSPORTDEC_ERROR synchronization( if (err == TRANSPORTDEC_OK) { FDKpushFor(hBs, rawDataBlockLength); - bitsAvail -= rawDataBlockLength; numFramesTraversed++; + endTpFrameBitsPrevious = (INT)FDKgetValidBits(hBs); /* Ignore error here itentionally. */ transportDec_AdjustEndOfAccessUnit(hTp); + endTpFrameBitsPrevious -= FDKgetValidBits(hBs); } } - } while ( fTraverseMoreFrames || (err == TRANSPORTDEC_SYNC_ERROR && !(hTp->flags & TPDEC_SYNCOK))); + } while (fTraverseMoreFrames || + (err == TRANSPORTDEC_SYNC_ERROR && !(hTp->flags & TPDEC_SYNCOK))); /* Restore context in case of ECD frame traversal */ - if ( startPosFirstFrame != -1 && (fConfigFound || err != TRANSPORTDEC_OK) ) { + if (startPosFirstFrame != -1 && (fConfigFound || err != TRANSPORTDEC_OK)) { FDKpushBiDirectional(hBs, FDKgetValidBits(hBs) - startPosFirstFrame); FDKmemcpy(&hTp->parser, contextFirstFrame, sizeof(transportdec_parser_t)); hTp->numberOfRawDataBlocks = numRawDataBlocksFirstFrame; @@ -876,32 +1250,35 @@ TRANSPORTDEC_ERROR synchronization( headerBits = headerBitsFirstFrame; err = errFirstFrame; numFramesTraversed = 0; - } + } /* Additional burst data mode buffer fullness check. */ - if ( !(hTp->flags & (TPDEC_LOST_FRAMES_PENDING|TPDEC_IGNORE_BUFFERFULLNESS|TPDEC_SYNCOK)) && err == TRANSPORTDEC_OK) { - err = additionalHoldOffNeeded(hTp, transportDec_GetBufferFullness(hTp), FDKgetValidBits(hBs) - syncLayerFrameBits); + if (!(hTp->flags & (TPDEC_LOST_FRAMES_PENDING | TPDEC_IGNORE_BUFFERFULLNESS | + TPDEC_SYNCOK)) && + err == TRANSPORTDEC_OK) { + err = additionalHoldOffNeeded(hTp, transportDec_GetBufferFullness(hTp), + FDKgetValidBits(hBs) - syncLayerFrameBits); if (err == TRANSPORTDEC_NOT_ENOUGH_BITS) { hTp->holdOffFrames++; } } - + /* Rewind for retry because of not enough bits */ if (err == TRANSPORTDEC_NOT_ENOUGH_BITS) { FDKpushBack(hBs, headerBits); headerBits = 0; - } - else { + } else { /* reset hold off frame counter */ hTp->holdOffFrames = 0; } /* Return to last good frame in case of frame traversal but not ECD. */ if (numFramesTraversed > 0) { - FDKpushBack(hBs, rawDataBlockLengthPrevious); + FDKpushBack(hBs, rawDataBlockLengthPrevious + endTpFrameBitsPrevious); if (err != TRANSPORTDEC_OK) { hTp->numberOfRawDataBlocks = numRawDataBlocksPrevious; headerBits = headerBitsPrevious; + rawDataBlockLength = rawDataBlockLengthPrevious; } err = TRANSPORTDEC_OK; } @@ -909,10 +1286,13 @@ TRANSPORTDEC_ERROR synchronization( bail: hTp->auLength[0] = rawDataBlockLength; - /* Detect pointless TRANSPORTDEC_NOT_ENOUGH_BITS error case, were the bit buffer is already full, - or no new burst packet fits. Recover by advancing the bit buffer. */ - if ( (TRANSPORTDEC_NOT_ENOUGH_BITS == err) && (FDKgetValidBits(hBs) >= ((TRANSPORTDEC_INBUF_SIZE*8 - ((hTp->avgBitRate*hTp->burstPeriod)/1000)) - 7)) ) - { + /* Detect pointless TRANSPORTDEC_NOT_ENOUGH_BITS error case, where the bit + buffer is already full, or no new burst packet fits. Recover by advancing + the bit buffer. */ + if ((totalBits > 0) && (TRANSPORTDEC_NOT_ENOUGH_BITS == err) && + (FDKgetValidBits(hBs) >= + (((8192 * 4) * 8 - ((hTp->avgBitRate * hTp->burstPeriod) / 1000)) - + 7))) { FDKpushFor(hBs, TPDEC_SYNCSKIP); err = TRANSPORTDEC_SYNC_ERROR; } @@ -939,16 +1319,14 @@ bail: } /** - * \brief Synchronize to stream and estimate the amount of missing access units due - * to a current synchronization error in case of constant average bit rate. + * \brief Synchronize to stream and estimate the amount of missing access units + * due to a current synchronization error in case of constant average bit rate. */ -static -TRANSPORTDEC_ERROR transportDec_readStream ( HANDLE_TRANSPORTDEC hTp, const UINT layer ) -{ - +static TRANSPORTDEC_ERROR transportDec_readStream(HANDLE_TRANSPORTDEC hTp, + const UINT layer) { TRANSPORTDEC_ERROR error = TRANSPORTDEC_OK; HANDLE_FDK_BITSTREAM hBs = &hTp->bitStream[layer]; - INT nAU = -1; + INT headerBits; INT bitDistance, bfDelta; @@ -957,16 +1335,16 @@ TRANSPORTDEC_ERROR transportDec_readStream ( HANDLE_TRANSPORTDEC hTp, const UINT error = synchronization(hTp, &headerBits); bitDistance -= FDKgetValidBits(hBs); - FDK_ASSERT(bitDistance >= 0); - if (error == TRANSPORTDEC_SYNC_ERROR || (hTp->flags & TPDEC_LOST_FRAMES_PENDING)) - { + INT nAU = -1; + + if (error == TRANSPORTDEC_SYNC_ERROR || + (hTp->flags & TPDEC_LOST_FRAMES_PENDING)) { /* Check if estimating lost access units is feasible. */ - if (hTp->avgBitRate > 0 && hTp->asc[0].m_samplesPerFrame > 0 && hTp->asc[0].m_samplingFrequency > 0) - { - if (error == TRANSPORTDEC_OK) - { + if (hTp->avgBitRate > 0 && hTp->asc[0].m_samplesPerFrame > 0 && + hTp->asc[0].m_samplingFrequency > 0) { + if (error == TRANSPORTDEC_OK) { int aj; aj = transportDec_GetBufferFullness(hTp); @@ -978,15 +1356,15 @@ TRANSPORTDEC_ERROR transportDec_readStream ( HANDLE_TRANSPORTDEC hTp, const UINT /* sync was ok: last of a series of bad access units. */ hTp->flags &= ~TPDEC_LOST_FRAMES_PENDING; /* Add up bitDistance until end of the current frame. Later we substract - this frame from the grand total, since this current successfully synchronized - frame should not be skipped of course; but it must be accounted into the - bufferfulness math. */ + this frame from the grand total, since this current successfully + synchronized frame should not be skipped of course; but it must be + accounted into the bufferfulness math. */ bitDistance += hTp->auLength[0]; } else { - if ( !(hTp->flags & TPDEC_LOST_FRAMES_PENDING) ) { + if (!(hTp->flags & TPDEC_LOST_FRAMES_PENDING)) { /* sync not ok: one of many bad access units. */ hTp->flags |= TPDEC_LOST_FRAMES_PENDING; - bfDelta = - (INT)hTp->lastValidBufferFullness; + bfDelta = -(INT)hTp->lastValidBufferFullness; } else { bfDelta = 0; } @@ -996,7 +1374,8 @@ TRANSPORTDEC_ERROR transportDec_readStream ( HANDLE_TRANSPORTDEC hTp, const UINT int num, denom; /* Obtain estimate of number of lost frames */ - num = hTp->asc[0].m_samplingFrequency * (bfDelta + bitDistance) + hTp->remainder; + num = hTp->asc[0].m_samplingFrequency * (bfDelta + bitDistance) + + hTp->remainder; denom = hTp->avgBitRate * hTp->asc[0].m_samplesPerFrame; if (num > 0) { nAU = num / denom; @@ -1005,23 +1384,20 @@ TRANSPORTDEC_ERROR transportDec_readStream ( HANDLE_TRANSPORTDEC hTp, const UINT hTp->remainder = num; } - if (error == TRANSPORTDEC_OK) - { - /* Final adjustment of remainder, taken -1 into account because current - frame should not be skipped, thus substract -1 or do nothing instead - of +1-1 accordingly. */ - if ( (denom - hTp->remainder) >= hTp->remainder ) { + if (error == TRANSPORTDEC_OK) { + /* Final adjustment of remainder, taken -1 into account because + current frame should not be skipped, thus substract -1 or do + nothing instead of +1-1 accordingly. */ + if ((denom - hTp->remainder) >= hTp->remainder) { nAU--; } - + if (nAU < 0) { - /* There was one frame too much concealed, so unfortunately we will have to skip one good frame. */ + /* There was one frame too much concealed, so unfortunately we will + * have to skip one good frame. */ transportDec_EndAccessUnit(hTp); - error = synchronization(hTp, &headerBits); + error = synchronization(hTp, &headerBits); nAU = -1; -#ifdef DEBUG - FDKprintf("ERROR: Bufferfullness accounting failed. remainder=%d, nAU=%d\n", hTp->remainder, nAU); -#endif } hTp->remainder = 0; /* Enforce last missed frames to be concealed. */ @@ -1033,9 +1409,10 @@ TRANSPORTDEC_ERROR transportDec_readStream ( HANDLE_TRANSPORTDEC hTp, const UINT } } - /* Be sure that lost frames are handled correctly. This is necessary due to some - sync error sequences where later it turns out that there is not enough data, but - the bits upto the sync word are discarded, thus causing a value of nAU > 0 */ + /* Be sure that lost frames are handled correctly. This is necessary due to + some sync error sequences where later it turns out that there is not enough + data, but the bits upto the sync word are discarded, thus causing a value + of nAU > 0 */ if (nAU > 0) { error = TRANSPORTDEC_SYNC_ERROR; } @@ -1046,8 +1423,8 @@ TRANSPORTDEC_ERROR transportDec_readStream ( HANDLE_TRANSPORTDEC hTp, const UINT } /* returns error code */ -TRANSPORTDEC_ERROR transportDec_ReadAccessUnit( const HANDLE_TRANSPORTDEC hTp, const UINT layer ) -{ +TRANSPORTDEC_ERROR transportDec_ReadAccessUnit(const HANDLE_TRANSPORTDEC hTp, + const UINT layer) { TRANSPORTDEC_ERROR err = TRANSPORTDEC_OK; HANDLE_FDK_BITSTREAM hBs; @@ -1058,41 +1435,66 @@ TRANSPORTDEC_ERROR transportDec_ReadAccessUnit( const HANDLE_TRANSPORTDEC hTp, c hBs = &hTp->bitStream[layer]; if ((INT)FDKgetValidBits(hBs) <= 0) { + /* This is only relevant for RAW and ADIF cases. + * For streaming formats err will get overwritten. */ err = TRANSPORTDEC_NOT_ENOUGH_BITS; + hTp->numberOfRawDataBlocks = 0; } switch (hTp->transportFmt) { - case TT_MP4_ADIF: /* Read header if not already done */ - if (!(hTp->flags & TPDEC_CONFIG_FOUND)) - { + if (!(hTp->flags & TPDEC_CONFIG_FOUND)) { + int i; CProgramConfig *pce; + INT bsStart = FDKgetValidBits(hBs); + UCHAR configChanged = 0; + UCHAR configMode = AC_CM_DET_CFG_CHANGE; + + for (i = 0; i < 2; i++) { + if (i > 0) { + FDKpushBack(hBs, bsStart - FDKgetValidBits(hBs)); + configMode = AC_CM_ALLOC_MEM; + } - AudioSpecificConfig_Init(&hTp->asc[0]); - pce = &hTp->asc[0].m_progrConfigElement; - err = adifRead_DecodeHeader(&hTp->parser.adif, pce, hBs); - if (err) - goto bail; - - /* Map adif header to ASC */ - hTp->asc[0].m_aot = (AUDIO_OBJECT_TYPE)(pce->Profile + 1); - hTp->asc[0].m_samplingFrequencyIndex = pce->SamplingFrequencyIndex; - hTp->asc[0].m_samplingFrequency = SamplingRateTable[pce->SamplingFrequencyIndex]; - hTp->asc[0].m_channelConfiguration = 0; - hTp->asc[0].m_samplesPerFrame = 1024; - hTp->avgBitRate = hTp->parser.adif.BitRate; - - /* Call callback to decoder. */ - { - int errC; + AudioSpecificConfig_Init(&hTp->asc[0]); + pce = &hTp->asc[0].m_progrConfigElement; + err = adifRead_DecodeHeader(&hTp->parser.adif, pce, hBs); + if (err) goto bail; + + /* Map adif header to ASC */ + hTp->asc[0].m_aot = (AUDIO_OBJECT_TYPE)(pce->Profile + 1); + hTp->asc[0].m_samplingFrequencyIndex = pce->SamplingFrequencyIndex; + hTp->asc[0].m_samplingFrequency = + SamplingRateTable[pce->SamplingFrequencyIndex]; + hTp->asc[0].m_channelConfiguration = 0; + hTp->asc[0].m_samplesPerFrame = 1024; + hTp->avgBitRate = hTp->parser.adif.BitRate; + + /* Call callback to decoder. */ + { + int errC; - errC = hTp->callbacks.cbUpdateConfig(hTp->callbacks.cbUpdateConfigData, &hTp->asc[0]); - if (errC == 0) { - hTp->flags |= TPDEC_CONFIG_FOUND; - } else { - err = TRANSPORTDEC_PARSE_ERROR; - goto bail; + errC = hTp->callbacks.cbUpdateConfig( + hTp->callbacks.cbUpdateConfigData, &hTp->asc[0], configMode, + &configChanged); + if (errC == 0) { + hTp->flags |= TPDEC_CONFIG_FOUND; + } else { + err = TRANSPORTDEC_PARSE_ERROR; + goto bail; + } + } + + if (err == TRANSPORTDEC_OK) { + if ((i == 0) && configChanged) { + int errC; + errC = hTp->callbacks.cbFreeMem(hTp->callbacks.cbFreeMemData, + &hTp->asc[0]); + if (errC != 0) { + err = TRANSPORTDEC_PARSE_ERROR; + } + } } } } @@ -1109,9 +1511,10 @@ TRANSPORTDEC_ERROR transportDec_ReadAccessUnit( const HANDLE_TRANSPORTDEC hTp, c case TT_MP4_LATM_MCP0: case TT_MP4_LATM_MCP1: - { + if (err == TRANSPORTDEC_OK) { int fConfigFound = hTp->flags & TPDEC_CONFIG_FOUND; - err = transportDec_readHeader(hTp, hBs, 0, 1, &hTp->auLength[layer], NULL, NULL, &fConfigFound, NULL); + err = transportDec_readHeader(hTp, hBs, 0, 1, &hTp->auLength[layer], + NULL, NULL, &fConfigFound, NULL); if (fConfigFound) { hTp->flags |= TPDEC_CONFIG_FOUND; } @@ -1138,12 +1541,29 @@ bail: return err; } -INT transportDec_GetAuBitsRemaining( const HANDLE_TRANSPORTDEC hTp, const UINT layer ) -{ +TRANSPORTDEC_ERROR transportDec_GetAsc(const HANDLE_TRANSPORTDEC hTp, + const UINT layer, + CSAudioSpecificConfig *asc) { + TRANSPORTDEC_ERROR err = TRANSPORTDEC_OK; + + if (hTp != NULL) { + *asc = hTp->asc[layer]; + err = TRANSPORTDEC_OK; + } else { + err = TRANSPORTDEC_INVALID_PARAMETER; + } + return err; +} + +INT transportDec_GetAuBitsRemaining(const HANDLE_TRANSPORTDEC hTp, + const UINT layer) { INT bits; if (hTp->accessUnitAnchor[layer] > 0 && hTp->auLength[layer] > 0) { - bits = hTp->auLength[layer] - (hTp->accessUnitAnchor[layer] - FDKgetValidBits(&hTp->bitStream[layer])); + bits = (INT)FDKgetValidBits(&hTp->bitStream[layer]); + if (bits >= 0) { + bits = hTp->auLength[layer] - ((INT)hTp->accessUnitAnchor[layer] - bits); + } } else { bits = FDKgetValidBits(&hTp->bitStream[layer]); } @@ -1151,23 +1571,55 @@ INT transportDec_GetAuBitsRemaining( const HANDLE_TRANSPORTDEC hTp, const UINT l return bits; } -INT transportDec_GetAuBitsTotal( const HANDLE_TRANSPORTDEC hTp, const UINT layer ) -{ +INT transportDec_GetAuBitsTotal(const HANDLE_TRANSPORTDEC hTp, + const UINT layer) { return hTp->auLength[layer]; } -TRANSPORTDEC_ERROR transportDec_GetMissingAccessUnitCount ( INT *pNAccessUnits, HANDLE_TRANSPORTDEC hTp ) -{ +TRANSPORTDEC_ERROR transportDec_GetMissingAccessUnitCount( + INT *pNAccessUnits, HANDLE_TRANSPORTDEC hTp) { *pNAccessUnits = hTp->missingAccessUnits; return TRANSPORTDEC_OK; } /* Inform the transportDec layer that reading of access unit has finished. */ -TRANSPORTDEC_ERROR transportDec_EndAccessUnit(HANDLE_TRANSPORTDEC hTp) -{ +TRANSPORTDEC_ERROR transportDec_EndAccessUnit(HANDLE_TRANSPORTDEC hTp) { TRANSPORTDEC_ERROR err = TRANSPORTDEC_OK; + switch (hTp->transportFmt) { + case TT_MP4_LOAS: + case TT_MP4_LATM_MCP0: + case TT_MP4_LATM_MCP1: { + HANDLE_FDK_BITSTREAM hBs = &hTp->bitStream[0]; + if (hTp->numberOfRawDataBlocks == 0) { + /* Read other data if available. */ + if (CLatmDemux_GetOtherDataPresentFlag(&hTp->parser.latm)) { + int otherDataLen = CLatmDemux_GetOtherDataLength(&hTp->parser.latm); + + if ((INT)FDKgetValidBits(hBs) >= otherDataLen) { + FDKpushFor(hBs, otherDataLen); + } else { + /* Do byte align at the end of AudioMuxElement. */ + if (hTp->numberOfRawDataBlocks == 0) { + FDKbyteAlign(hBs, hTp->globalFramePos); + } + return TRANSPORTDEC_NOT_ENOUGH_BITS; + } + } + } else { + /* If bit buffer has not more bits but hTp->numberOfRawDataBlocks > 0 + then too many bits were read and obviously no more RawDataBlocks can + be read. Set numberOfRawDataBlocks to zero to attempt a new sync + attempt. */ + if ((INT)FDKgetValidBits(hBs) <= 0) { + hTp->numberOfRawDataBlocks = 0; + } + } + } break; + default: + break; + } err = transportDec_AdjustEndOfAccessUnit(hTp); @@ -1179,12 +1631,15 @@ TRANSPORTDEC_ERROR transportDec_EndAccessUnit(HANDLE_TRANSPORTDEC hTp) return err; } -TRANSPORTDEC_ERROR transportDec_SetParam ( const HANDLE_TRANSPORTDEC hTp, - const TPDEC_PARAM param, - const INT value) -{ +TRANSPORTDEC_ERROR transportDec_SetParam(const HANDLE_TRANSPORTDEC hTp, + const TPDEC_PARAM param, + const INT value) { TRANSPORTDEC_ERROR error = TRANSPORTDEC_OK; + if (hTp == NULL) { + return TRANSPORTDEC_INVALID_PARAMETER; + } + switch (param) { case TPDEC_PARAM_MINIMIZE_DELAY: if (value) { @@ -1213,25 +1668,36 @@ TRANSPORTDEC_ERROR transportDec_SetParam ( const HANDLE_TRANSPORTDEC hTp, case TPDEC_PARAM_BURST_PERIOD: hTp->burstPeriod = value; break; - case TPDEC_PARAM_RESET: - { - int i; + case TPDEC_PARAM_RESET: { + int i; - for (i=0; i<(1*2); i++) { - FDKresetBitbuffer(&hTp->bitStream[i]); - hTp->auLength[i] = 0; - hTp->accessUnitAnchor[i] = 0; - } - hTp->flags &= ~(TPDEC_SYNCOK|TPDEC_LOST_FRAMES_PENDING); - if (hTp->transportFmt != TT_MP4_ADIF) { - hTp->flags &= ~TPDEC_CONFIG_FOUND; - } - hTp->remainder = 0; - hTp->avgBitRate = 0; - hTp->missingAccessUnits = 0; - hTp->numberOfRawDataBlocks = 0; - hTp->globalFramePos = 0; - hTp->holdOffFrames = 0; + for (i = 0; i < (1 * 1); i++) { + FDKresetBitbuffer(&hTp->bitStream[i]); + hTp->auLength[i] = 0; + hTp->accessUnitAnchor[i] = 0; + } + hTp->flags &= ~(TPDEC_SYNCOK | TPDEC_LOST_FRAMES_PENDING); + if (hTp->transportFmt != TT_MP4_ADIF) { + hTp->flags &= ~TPDEC_CONFIG_FOUND; + } + hTp->remainder = 0; + hTp->avgBitRate = 0; + hTp->missingAccessUnits = 0; + hTp->numberOfRawDataBlocks = 0; + hTp->globalFramePos = 0; + hTp->holdOffFrames = 0; + } break; + case TPDEC_PARAM_TARGETLAYOUT: + hTp->targetLayout = value; + break; + case TPDEC_PARAM_FORCE_CONFIG_CHANGE: + hTp->ctrlCFGChange[value].forceCfgChange = TPDEC_FORCE_CONFIG_CHANGE; + break; + case TPDEC_PARAM_USE_ELEM_SKIPPING: + if (value) { + hTp->flags |= TPDEC_USE_ELEM_SKIPPING; + } else { + hTp->flags &= ~TPDEC_USE_ELEM_SKIPPING; } break; } @@ -1239,38 +1705,30 @@ TRANSPORTDEC_ERROR transportDec_SetParam ( const HANDLE_TRANSPORTDEC hTp, return error; } -UINT transportDec_GetNrOfSubFrames(HANDLE_TRANSPORTDEC hTp) -{ +UINT transportDec_GetNrOfSubFrames(HANDLE_TRANSPORTDEC hTp) { UINT nSubFrames = 0; - if (hTp == NULL) - return 0; + if (hTp == NULL) return 0; - if (hTp->transportFmt==TT_MP4_LATM_MCP1 || hTp->transportFmt==TT_MP4_LATM_MCP0 || hTp->transportFmt==TT_MP4_LOAS) + if (hTp->transportFmt == TT_MP4_LATM_MCP1 || + hTp->transportFmt == TT_MP4_LATM_MCP0 || hTp->transportFmt == TT_MP4_LOAS) nSubFrames = CLatmDemux_GetNrOfSubFrames(&hTp->parser.latm); - else if (hTp->transportFmt==TT_MP4_ADTS) + else if (hTp->transportFmt == TT_MP4_ADTS) nSubFrames = hTp->parser.adts.bs.num_raw_blocks; return nSubFrames; } -void transportDec_Close(HANDLE_TRANSPORTDEC *phTp) -{ - if (phTp != NULL) - { +void transportDec_Close(HANDLE_TRANSPORTDEC *phTp) { + if (phTp != NULL) { if (*phTp != NULL) { - if ( ! TT_IS_PACKET((*phTp)->transportFmt) ) { - FreeRam_TransportDecoderBuffer(&(*phTp)->bsBuffer); - } - if (*phTp != NULL) { - FreeRam_TransportDecoder(phTp); - } + FreeRam_TransportDecoderBuffer(&(*phTp)->bsBuffer); + FreeRam_TransportDecoder(phTp); } } } -TRANSPORTDEC_ERROR transportDec_GetLibInfo( LIB_INFO *info ) -{ +TRANSPORTDEC_ERROR transportDec_GetLibInfo(LIB_INFO *info) { int i; if (info == NULL) { @@ -1284,7 +1742,7 @@ TRANSPORTDEC_ERROR transportDec_GetLibInfo( LIB_INFO *info ) if (i == FDK_MODULE_LAST) return TRANSPORTDEC_UNKOWN_ERROR; info += i; - info->module_id = FDK_TPDEC; + info->module_id = FDK_TPDEC; #ifdef __ANDROID__ info->build_date = ""; info->build_time = ""; @@ -1292,63 +1750,64 @@ TRANSPORTDEC_ERROR transportDec_GetLibInfo( LIB_INFO *info ) info->build_date = __DATE__; info->build_time = __TIME__; #endif - info->title = TP_LIB_TITLE; - info->version = LIB_VERSION(TP_LIB_VL0, TP_LIB_VL1, TP_LIB_VL2); + info->title = TP_LIB_TITLE; + info->version = LIB_VERSION(TP_LIB_VL0, TP_LIB_VL1, TP_LIB_VL2); LIB_VERSION_STRING(info); - info->flags = 0 - | CAPF_ADIF - | CAPF_ADTS - | CAPF_LATM - | CAPF_LOAS - | CAPF_RAWPACKETS - | CAPF_DRM - ; + info->flags = 0 | CAPF_ADIF | CAPF_ADTS | CAPF_LATM | CAPF_LOAS | + CAPF_RAWPACKETS | CAPF_DRM; return TRANSPORTDEC_OK; /* FDKERR_NOERROR; */ } - -int transportDec_CrcStartReg(HANDLE_TRANSPORTDEC pTp, INT mBits) -{ +int transportDec_CrcStartReg(HANDLE_TRANSPORTDEC pTp, INT mBits) { switch (pTp->transportFmt) { - case TT_MP4_ADTS: - return adtsRead_CrcStartReg(&pTp->parser.adts, &pTp->bitStream[0], mBits); - case TT_DRM: - return drmRead_CrcStartReg(&pTp->parser.drm, &pTp->bitStream[0], mBits); - default: - return 0; + case TT_MP4_ADTS: + return adtsRead_CrcStartReg(&pTp->parser.adts, &pTp->bitStream[0], mBits); + case TT_DRM: + return drmRead_CrcStartReg(&pTp->parser.drm, &pTp->bitStream[0], mBits); + default: + return -1; } } -void transportDec_CrcEndReg(HANDLE_TRANSPORTDEC pTp, INT reg) -{ +void transportDec_CrcEndReg(HANDLE_TRANSPORTDEC pTp, INT reg) { switch (pTp->transportFmt) { - case TT_MP4_ADTS: - adtsRead_CrcEndReg(&pTp->parser.adts, &pTp->bitStream[0], reg); - break; - case TT_DRM: - drmRead_CrcEndReg(&pTp->parser.drm, &pTp->bitStream[0], reg); - break; - default: - break; + case TT_MP4_ADTS: + adtsRead_CrcEndReg(&pTp->parser.adts, &pTp->bitStream[0], reg); + break; + case TT_DRM: + drmRead_CrcEndReg(&pTp->parser.drm, &pTp->bitStream[0], reg); + break; + default: + break; } } -TRANSPORTDEC_ERROR transportDec_CrcCheck(HANDLE_TRANSPORTDEC pTp) -{ +TRANSPORTDEC_ERROR transportDec_CrcCheck(HANDLE_TRANSPORTDEC pTp) { switch (pTp->transportFmt) { - case TT_MP4_ADTS: - if ( (pTp->parser.adts.bs.num_raw_blocks > 0) && (pTp->parser.adts.bs.protection_absent == 0) ) - { - HANDLE_FDK_BITSTREAM hBs = &pTp->bitStream[0]; - - transportDec_AdjustEndOfAccessUnit(pTp); - } - return adtsRead_CrcCheck(&pTp->parser.adts); - case TT_DRM: - return drmRead_CrcCheck(&pTp->parser.drm); - break; - default: - return TRANSPORTDEC_OK; + case TT_MP4_ADTS: + if ((pTp->parser.adts.bs.num_raw_blocks > 0) && + (pTp->parser.adts.bs.protection_absent == 0)) { + transportDec_AdjustEndOfAccessUnit(pTp); + } + return adtsRead_CrcCheck(&pTp->parser.adts); + case TT_DRM: + return drmRead_CrcCheck(&pTp->parser.drm); + default: + return TRANSPORTDEC_OK; } } + +TRANSPORTDEC_ERROR transportDec_DrmRawSdcAudioConfig_Check(UCHAR *conf, + const UINT length) { + CSAudioSpecificConfig asc; + FDK_BITSTREAM bs; + HANDLE_FDK_BITSTREAM hBs = &bs; + + FDKinitBitStream(hBs, conf, BUFSIZE_DUMMY_VALUE, length << 3, BS_READER); + + TRANSPORTDEC_ERROR err = + DrmRawSdcAudioConfig_Parse(&asc, hBs, NULL, (UCHAR)AC_CM_ALLOC_MEM, 0); + + return err; +} diff --git a/libMpegTPDec/src/version b/libMpegTPDec/src/version deleted file mode 100644 index 75e22c9..0000000 --- a/libMpegTPDec/src/version +++ /dev/null @@ -1,13 +0,0 @@ - -/* library info */ -#define TP_LIB_VL0 2 -#define TP_LIB_VL1 3 -#define TP_LIB_VL2 7 -#define TP_LIB_TITLE "MPEG Transport" -#ifdef __ANDROID__ -#define TP_LIB_BUILD_DATE "" -#define TP_LIB_BUILD_TIME "" -#else -#define TP_LIB_BUILD_DATE __DATE__ -#define TP_LIB_BUILD_TIME __TIME__ -#endif |