diff options
author | Xin Li <delphij@google.com> | 2018-06-08 11:06:57 -0700 |
---|---|---|
committer | Xin Li <delphij@google.com> | 2018-06-08 11:06:57 -0700 |
commit | 6a79fb47e4fe92cc4fd0c63f68db8a4d19b9c835 (patch) | |
tree | 41c65cebd836ff3f949f1134512985e4a1288593 /libMpegTPDec/src/tpdec_lib.cpp | |
parent | b9fc83e0e9412548830f07e60c53d8072adb60de (diff) | |
parent | 1f93990cfc1bb76aa538634512938e39565f471a (diff) | |
download | fdk-aac-6a79fb47e4fe92cc4fd0c63f68db8a4d19b9c835.tar.gz fdk-aac-6a79fb47e4fe92cc4fd0c63f68db8a4d19b9c835.tar.bz2 fdk-aac-6a79fb47e4fe92cc4fd0c63f68db8a4d19b9c835.zip |
Merge pi-dev-plus-aosp-without-vendor into stage-aosp-master
Bug: 79597307
Change-Id: Ia98e005208999b395595ef647902768a1199eaa4
Diffstat (limited to 'libMpegTPDec/src/tpdec_lib.cpp')
-rw-r--r-- | libMpegTPDec/src/tpdec_lib.cpp | 1511 |
1 files changed, 988 insertions, 523 deletions
diff --git a/libMpegTPDec/src/tpdec_lib.cpp b/libMpegTPDec/src/tpdec_lib.cpp index 24f755b..1d8b7b3 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, (INT)length * 8 - (INT)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,46 @@ 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)) { + /* Rewind - TPDEC_SYNCSKIP, in order to look for a synch one bit ahead + * next time. Ensure that the bit amount lands at a multiple of + * TPDEC_SYNCSKIP. */ + FDKpushBiDirectional( + hBs, -headerBits + TPDEC_SYNCSKIP + (bitsAvail % TPDEC_SYNCSKIP)); + + 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 +1193,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 +1236,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 +1256,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 +1292,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,34 +1325,32 @@ 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; /* Obtain distance to next synch word */ - bitDistance = FDKgetValidBits(hBs); + bitDistance = (INT)FDKgetValidBits(hBs); error = synchronization(hTp, &headerBits); - bitDistance -= FDKgetValidBits(hBs); - + bitDistance -= (INT)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 +1362,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 +1380,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 = (INT)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 +1390,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 +1415,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 +1429,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 +1441,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 +1517,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 +1547,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 +1577,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 +1637,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 +1674,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 +1711,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 +1748,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 +1756,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; +} |