diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2012-07-11 10:15:24 -0700 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2012-07-11 10:15:24 -0700 |
commit | 2228e360595641dd906bf1773307f43d304f5b2e (patch) | |
tree | 57f3d390ebb0782cc0de0fb984c8ea7e45b4f386 /libAACdec/src/aacdecoder_lib.cpp | |
download | fdk-aac-2228e360595641dd906bf1773307f43d304f5b2e.tar.gz fdk-aac-2228e360595641dd906bf1773307f43d304f5b2e.tar.bz2 fdk-aac-2228e360595641dd906bf1773307f43d304f5b2e.zip |
Snapshot 2bda038c163298531d47394bc2c09e1409c5d0db
Change-Id: If584e579464f28b97d50e51fc76ba654a5536c54
Diffstat (limited to 'libAACdec/src/aacdecoder_lib.cpp')
-rw-r--r-- | libAACdec/src/aacdecoder_lib.cpp | 989 |
1 files changed, 989 insertions, 0 deletions
diff --git a/libAACdec/src/aacdecoder_lib.cpp b/libAACdec/src/aacdecoder_lib.cpp new file mode 100644 index 0000000..451d659 --- /dev/null +++ b/libAACdec/src/aacdecoder_lib.cpp @@ -0,0 +1,989 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2012 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: + +******************************************************************************/ + +#include "aacdecoder_lib.h" + +#include "aac_ram.h" +#include "aacdecoder.h" +#include "tpdec_lib.h" +#include "FDK_core.h" /* FDK_tools version info */ + + + #include "sbrdecoder.h" + + + + +#include "conceal.h" + + #include "aacdec_drc.h" + + + +/* Decoder library info */ +#define AACDECODER_LIB_VL0 2 +#define AACDECODER_LIB_VL1 4 +#define AACDECODER_LIB_VL2 4 +#define AACDECODER_LIB_TITLE "AAC Decoder Lib" +#define AACDECODER_LIB_BUILD_DATE __DATE__ +#define AACDECODER_LIB_BUILD_TIME __TIME__ + +static AAC_DECODER_ERROR +setConcealMethod ( const HANDLE_AACDECODER self, + const INT method ); + + +LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_GetFreeBytes ( const HANDLE_AACDECODER self, UINT *pFreeBytes){ + + /* reset free bytes */ + *pFreeBytes = 0; + + /* check handle */ + if(!self) + return AAC_DEC_INVALID_HANDLE; + + /* return nr of free bytes */ + HANDLE_FDK_BITSTREAM hBs = transportDec_GetBitstream(self->hInput, 0); + *pFreeBytes = FDKgetFreeBits(hBs) >> 3; + + /* success */ + return AAC_DEC_OK; +} + +/** + * Config Decoder using a CSAudioSpecificConfig struct. + */ +static +LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_Config(HANDLE_AACDECODER self, const CSAudioSpecificConfig *pAscStruct) +{ + AAC_DECODER_ERROR err; + + /* Initialize AAC core decoder, and update self->streaminfo */ + err = CAacDecoder_Init(self, pAscStruct); + + return err; +} + +LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_ConfigRaw ( + HANDLE_AACDECODER self, + UCHAR *conf[], + const UINT length[] ) +{ + AAC_DECODER_ERROR err = AAC_DEC_OK; + TRANSPORTDEC_ERROR errTp; + UINT layer, nrOfLayers = self->nrOfLayers; + + for(layer = 0; layer < nrOfLayers; layer++){ + if(length[layer] > 0){ + errTp = transportDec_OutOfBandConfig(self->hInput, conf[layer], length[layer], layer); + if (errTp != TRANSPORTDEC_OK) { + switch (errTp) { + case TRANSPORTDEC_NEED_TO_RESTART: + err = AAC_DEC_NEED_TO_RESTART; + break; + case TRANSPORTDEC_UNSUPPORTED_FORMAT: + err = AAC_DEC_UNSUPPORTED_FORMAT; + break; + default: + err = AAC_DEC_UNKNOWN; + break; + } + /* if baselayer is OK we continue decoding */ + if(layer >= 1){ + self->nrOfLayers = layer; + } + break; + } + } + } + + return err; +} + + + +static INT aacDecoder_ConfigCallback(void *handle, const CSAudioSpecificConfig *pAscStruct) +{ + HANDLE_AACDECODER self = (HANDLE_AACDECODER)handle; + AAC_DECODER_ERROR err = AAC_DEC_OK; + TRANSPORTDEC_ERROR errTp; + + { + { + err = aacDecoder_Config(self, pAscStruct); + } + } + if (err == AAC_DEC_OK) { + if ( self->flags & (AC_USAC|AC_RSVD50|AC_LD|AC_ELD) + && CConcealment_GetDelay(&self->concealCommonData) > 0 ) + { + /* Revert to error concealment method Noise Substitution. + Because interpolation is not implemented for USAC/RSVD50 or + the additional delay is unwanted for low delay codecs. */ + setConcealMethod(self, 1); +#ifdef DEBUG + FDKprintf(" Concealment method was reverted to 1 !\n"); +#endif + } + errTp = TRANSPORTDEC_OK; + } else { + if (IS_INIT_ERROR(err)) { + errTp = TRANSPORTDEC_UNSUPPORTED_FORMAT; + } /* Fatal errors */ + else if (err == AAC_DEC_NEED_TO_RESTART) { + errTp = TRANSPORTDEC_NEED_TO_RESTART; + } else { + errTp = TRANSPORTDEC_UNKOWN_ERROR; + } + } + + return errTp; +} + + + +LINKSPEC_CPP AAC_DECODER_ERROR +aacDecoder_AncDataInit ( HANDLE_AACDECODER self, + UCHAR *buffer, + int size ) +{ + CAncData *ancData = &self->ancData; + + return CAacDecoder_AncDataInit(ancData, buffer, size); +} + + +LINKSPEC_CPP AAC_DECODER_ERROR +aacDecoder_AncDataGet ( HANDLE_AACDECODER self, + int index, + UCHAR **ptr, + int *size ) +{ + CAncData *ancData = &self->ancData; + + return CAacDecoder_AncDataGet(ancData, index, ptr, size); +} + + +static AAC_DECODER_ERROR +setConcealMethod ( const HANDLE_AACDECODER self, /*!< Handle of the decoder instance */ + const INT method ) +{ + AAC_DECODER_ERROR errorStatus = AAC_DEC_OK; + CConcealParams *pConcealData = NULL; + HANDLE_SBRDECODER hSbrDec = NULL; + HANDLE_AAC_DRC hDrcInfo = NULL; + HANDLE_PCM_DOWNMIX hPcmDmx = NULL; + CConcealmentMethod backupMethod; + int backupDelay = 0; + int bsDelay = 0; + + /* check decoder handle */ + if (self != NULL) { + pConcealData = &self->concealCommonData; + hSbrDec = self->hSbrDecoder; + hDrcInfo = self->hDrcInfo; + hPcmDmx = self->hPcmUtils; + } + + + /* Get current method/delay */ + backupMethod = CConcealment_GetMethod(pConcealData); + backupDelay = CConcealment_GetDelay(pConcealData); + + /* Be sure to set AAC and SBR concealment method simultaneously! */ + errorStatus = + CConcealment_SetParams( + pConcealData, + (int)method, // concealMethod + AACDEC_CONCEAL_PARAM_NOT_SPECIFIED, // concealFadeOutSlope + AACDEC_CONCEAL_PARAM_NOT_SPECIFIED, // concealFadeInSlope + AACDEC_CONCEAL_PARAM_NOT_SPECIFIED, // concealMuteRelease + AACDEC_CONCEAL_PARAM_NOT_SPECIFIED // concealComfNoiseLevel + ); + if ( (errorStatus != AAC_DEC_OK) + && (errorStatus != AAC_DEC_INVALID_HANDLE) ) { + goto bail; + } + + /* Get new delay */ + bsDelay = CConcealment_GetDelay(pConcealData); + + { + SBR_ERROR sbrErr = SBRDEC_OK; + + /* set SBR bitstream delay */ + sbrErr = sbrDecoder_SetParam ( + hSbrDec, + SBR_SYSTEM_BITSTREAM_DELAY, + bsDelay + ); + + switch (sbrErr) { + case SBRDEC_OK: + case SBRDEC_NOT_INITIALIZED: + if (self != NULL) { + /* save the param value and set later + (when SBR has been initialized) */ + self->sbrParams.bsDelay = bsDelay; + } + break; + default: + errorStatus = AAC_DEC_SET_PARAM_FAIL; + goto bail; + } + } + + errorStatus = + aacDecoder_drcSetParam ( + hDrcInfo, + DRC_BS_DELAY, + bsDelay + ); + if ( (errorStatus != AAC_DEC_OK) + && (errorStatus != AAC_DEC_INVALID_HANDLE) ) { + goto bail; + } + + if (errorStatus == AAC_DEC_OK) { + PCMDMX_ERROR err = + pcmDmx_SetParam ( + hPcmDmx, + DMX_BS_DATA_DELAY, + bsDelay + ); + switch (err) { + case PCMDMX_INVALID_HANDLE: + errorStatus = AAC_DEC_INVALID_HANDLE; + case PCMDMX_OK: + break; + default: + errorStatus = AAC_DEC_SET_PARAM_FAIL; + goto bail; + } + } + + +bail: + if ( (errorStatus != AAC_DEC_OK) + && (errorStatus != AAC_DEC_INVALID_HANDLE) ) + { + /* Revert to the initial state */ + CConcealment_SetParams ( + pConcealData, + (int)backupMethod, + AACDEC_CONCEAL_PARAM_NOT_SPECIFIED, + AACDEC_CONCEAL_PARAM_NOT_SPECIFIED, + AACDEC_CONCEAL_PARAM_NOT_SPECIFIED, + AACDEC_CONCEAL_PARAM_NOT_SPECIFIED + ); + /* Revert SBR bitstream delay */ + sbrDecoder_SetParam ( + hSbrDec, + SBR_SYSTEM_BITSTREAM_DELAY, + backupDelay + ); + /* Revert DRC bitstream delay */ + aacDecoder_drcSetParam ( + hDrcInfo, + DRC_BS_DELAY, + backupDelay + ); + /* Revert PCM mixdown bitstream delay */ + pcmDmx_SetParam ( + hPcmDmx, + DMX_BS_DATA_DELAY, + backupDelay + ); + } + + return errorStatus; +} + + +LINKSPEC_CPP AAC_DECODER_ERROR +aacDecoder_SetParam ( const HANDLE_AACDECODER self, /*!< Handle of the decoder instance */ + const AACDEC_PARAM param, /*!< Parameter to set */ + const INT value) /*!< Parameter valued */ +{ + AAC_DECODER_ERROR errorStatus = AAC_DEC_OK; + CConcealParams *pConcealData = NULL; + HANDLE_AAC_DRC hDrcInfo = NULL; + + /* check decoder handle */ + if (self != NULL) { + pConcealData = &self->concealCommonData; + hDrcInfo = self->hDrcInfo; + } + + /* configure the subsystems */ + switch (param) + { + case AAC_PCM_OUTPUT_INTERLEAVED: + if (value < 0 || value > 1) { + return AAC_DEC_SET_PARAM_FAIL; + } + if (self == NULL) { + return AAC_DEC_INVALID_HANDLE; + } + self->outputInterleaved = value; + break; + + case AAC_PCM_OUTPUT_CHANNELS: + { + PCMDMX_ERROR err; + + err = pcmDmx_SetParam ( + self->hPcmUtils, + NUMBER_OF_OUTPUT_CHANNELS, + value ); + + switch (err) { + case PCMDMX_OK: + break; + case PCMDMX_INVALID_HANDLE: + return AAC_DEC_INVALID_HANDLE; + default: + return AAC_DEC_SET_PARAM_FAIL; + } + } + break; + + case AAC_PCM_DUAL_CHANNEL_OUTPUT_MODE: + { + PCMDMX_ERROR err; + + err = pcmDmx_SetParam ( + self->hPcmUtils, + DUAL_CHANNEL_DOWNMIX_MODE, + value ); + + switch (err) { + case PCMDMX_OK: + break; + case PCMDMX_INVALID_HANDLE: + return AAC_DEC_INVALID_HANDLE; + default: + return AAC_DEC_SET_PARAM_FAIL; + } + } + break; + + case AAC_PCM_OUTPUT_CHANNEL_MAPPING: + switch (value) { + case 0: + self->channelOutputMapping = channelMappingTablePassthrough; + break; + case 1: + self->channelOutputMapping = channelMappingTableWAV; + break; + default: + errorStatus = AAC_DEC_SET_PARAM_FAIL; + break; + } + break; + + + case AAC_QMF_LOWPOWER: + if (self == NULL) { + return AAC_DEC_INVALID_HANDLE; + } + + /** + * Set QMF mode (might be overriden) + * 0:HQ (complex) + * 1:LP (partially complex) + */ + self->qmfModeUser = (QMF_MODE)value; + break; + + + case AAC_DRC_ATTENUATION_FACTOR: + /* DRC compression factor (where 0 is no and 127 is max compression) */ + errorStatus = + aacDecoder_drcSetParam ( + hDrcInfo, + DRC_CUT_SCALE, + value + ); + break; + + case AAC_DRC_BOOST_FACTOR: + /* DRC boost factor (where 0 is no and 127 is max boost) */ + errorStatus = + aacDecoder_drcSetParam ( + hDrcInfo, + DRC_BOOST_SCALE, + value + ); + break; + + case AAC_DRC_REFERENCE_LEVEL: + /* DRC reference level quantized in 0.25dB steps using values [0..127] it is '-' for analog scaling */ + errorStatus = + aacDecoder_drcSetParam ( + hDrcInfo, + TARGET_REF_LEVEL, + value + ); + break; + + case AAC_DRC_HEAVY_COMPRESSION: + /* Don't need to overwrite cut/boost values */ + errorStatus = + aacDecoder_drcSetParam ( + hDrcInfo, + APPLY_HEAVY_COMPRESSION, + value + ); + break; + + + case AAC_TPDEC_CLEAR_BUFFER: + transportDec_SetParam(self->hInput, TPDEC_PARAM_RESET, 1); + self->streamInfo.numLostAccessUnits = 0; + self->streamInfo.numBadBytes = 0; + self->streamInfo.numTotalBytes = 0; + /* aacDecoder_SignalInterruption(self); */ + break; + + case AAC_CONCEAL_METHOD: + /* Changing the concealment method can introduce additional bitstream delay. And + that in turn affects sub libraries and modules which makes the whole thing quite + complex. So the complete changing routine is packed into a helper function which + keeps all modules and libs in a consistent state even in the case an error occures. */ + errorStatus = setConcealMethod ( self, value ); + break; + + default: + return AAC_DEC_SET_PARAM_FAIL; + } /* switch(param) */ + + return (errorStatus); +} + + +LINKSPEC_CPP HANDLE_AACDECODER aacDecoder_Open(TRANSPORT_TYPE transportFmt, UINT nrOfLayers) +{ + AAC_DECODER_INSTANCE *aacDec = NULL; + HANDLE_TRANSPORTDEC pIn; + int err = 0; + + /* Allocate transport layer struct. */ + pIn = transportDec_Open(transportFmt, TP_FLAG_MPEG4); + if (pIn == NULL) { + return NULL; + } + + transportDec_SetParam(pIn, TPDEC_PARAM_IGNORE_BUFFERFULLNESS, 1); + + /* Allocate AAC decoder core struct. */ + aacDec = CAacDecoder_Open(transportFmt); + + if (aacDec == NULL) { + transportDec_Close(&pIn); + goto bail; + } + aacDec->hInput = pIn; + + aacDec->nrOfLayers = nrOfLayers; + + aacDec->channelOutputMapping = channelMappingTableWAV; + + /* Register Config Update callback. */ + transportDec_RegisterAscCallback(pIn, aacDecoder_ConfigCallback, (void*)aacDec); + + /* open SBR decoder */ + if ( SBRDEC_OK != sbrDecoder_Open ( &aacDec->hSbrDecoder )) { + err = -1; + goto bail; + } + aacDec->qmfModeUser = NOT_DEFINED; + transportDec_RegisterSbrCallback(aacDec->hInput, (cbSbr_t)sbrDecoder_Header, (void*)aacDec->hSbrDecoder); + + + pcmDmx_Open( &aacDec->hPcmUtils ); + if (aacDec->hPcmUtils == NULL) { + err = -1; + goto bail; + } + + + + /* Assure that all modules have same delay */ + if ( setConcealMethod(aacDec, CConcealment_GetMethod(&aacDec->concealCommonData)) ) { + err = -1; + goto bail; + } + +bail: + if (err == -1) { + aacDecoder_Close(aacDec); + aacDec = NULL; + } + return aacDec; +} + +LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_Fill( + HANDLE_AACDECODER self, + UCHAR *pBuffer[], + const UINT bufferSize[], + UINT *pBytesValid + ) +{ + TRANSPORTDEC_ERROR tpErr; + /* loop counter for layers; if not TT_MP4_RAWPACKETS used as index for only + available layer */ + INT layer = 0; + INT nrOfLayers = self->nrOfLayers; + + { + for (layer = 0; layer < nrOfLayers; layer++){ + { + tpErr = transportDec_FillData( self->hInput, pBuffer[layer], bufferSize[layer], &pBytesValid[layer], layer ); + if (tpErr != TRANSPORTDEC_OK) { + return AAC_DEC_UNKNOWN; /* Must be an internal error */ + } + } + } + } + + return AAC_DEC_OK; +} + + +static void aacDecoder_SignalInterruption(HANDLE_AACDECODER self) +{ + CAacDecoder_SignalInterruption(self); + + if ( self->hSbrDecoder != NULL ) { + sbrDecoder_SetParam(self->hSbrDecoder, SBR_BS_INTERRUPTION, 0); + } +} + +static void aacDecoder_UpdateBitStreamCounters(CStreamInfo *pSi, HANDLE_FDK_BITSTREAM hBs, int nBits, AAC_DECODER_ERROR ErrorStatus) +{ + /* calculate bit difference (amount of bits moved forward) */ + nBits = nBits - FDKgetValidBits(hBs); + + /* Note: The amount of bits consumed might become negative when parsing a + bit stream with several sub frames, and we find out at the last sub frame + that the total frame length does not match the sum of sub frame length. + If this happens, the transport decoder might want to rewind to the supposed + ending of the transport frame, and this position might be before the last + access unit beginning. */ + + /* Calc bitrate. */ + if (pSi->frameSize > 0) { + pSi->bitRate = (nBits * pSi->sampleRate)/pSi->frameSize; + } + + /* bit/byte counters */ + { + int nBytes; + + nBytes = nBits>>3; + pSi->numTotalBytes += nBytes; + if (IS_OUTPUT_VALID(ErrorStatus)) { + pSi->numTotalAccessUnits++; + } + if (IS_DECODE_ERROR(ErrorStatus)) { + pSi->numBadBytes += nBytes; + pSi->numBadAccessUnits++; + } + } +} + +static INT aacDecoder_EstimateNumberOfLostFrames(HANDLE_AACDECODER self) +{ + INT n; + + transportDec_GetMissingAccessUnitCount( &n, self->hInput); + + return n; +} + +LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_DecodeFrame( + HANDLE_AACDECODER self, + INT_PCM *pTimeData, + const INT timeDataSize, + const UINT flags) +{ + AAC_DECODER_ERROR ErrorStatus; + INT layer; + INT nBits; + INT interleaved = self->outputInterleaved; + HANDLE_FDK_BITSTREAM hBs; + int fTpInterruption = 0; /* Transport originated interruption detection. */ + int fTpConceal = 0; /* Transport originated concealment. */ + + + if (self == NULL) { + return AAC_DEC_INVALID_HANDLE; + } + + if (flags & AACDEC_INTR) { + self->streamInfo.numLostAccessUnits = 0; + } + + hBs = transportDec_GetBitstream(self->hInput, 0); + + /* Get current bits position for bitrate calculation. */ + nBits = FDKgetValidBits(hBs); + if (! (flags & (AACDEC_CONCEAL | AACDEC_FLUSH) ) ) + { + TRANSPORTDEC_ERROR err; + + for(layer = 0; layer < self->nrOfLayers; layer++) + { + err = transportDec_ReadAccessUnit(self->hInput, layer); + if (err != TRANSPORTDEC_OK) { + switch (err) { + case TRANSPORTDEC_NOT_ENOUGH_BITS: + ErrorStatus = AAC_DEC_NOT_ENOUGH_BITS; + goto bail; + case TRANSPORTDEC_SYNC_ERROR: + self->streamInfo.numLostAccessUnits = aacDecoder_EstimateNumberOfLostFrames(self); + fTpInterruption = 1; + break; + case TRANSPORTDEC_NEED_TO_RESTART: + ErrorStatus = AAC_DEC_NEED_TO_RESTART; + goto bail; + case TRANSPORTDEC_CRC_ERROR: + fTpConceal = 1; + break; + default: + ErrorStatus = AAC_DEC_UNKNOWN; + goto bail; + } + } + } + } else { + if (self->streamInfo.numLostAccessUnits > 0) { + self->streamInfo.numLostAccessUnits--; + } + } + + /* Signal bit stream interruption to other modules if required. */ + if ( fTpInterruption || (flags & (AACDEC_INTR|AACDEC_CLRHIST)) ) + { + aacDecoder_SignalInterruption(self); + if ( ! (flags & AACDEC_INTR) ) { + ErrorStatus = AAC_DEC_TRANSPORT_SYNC_ERROR; + goto bail; + } + } + + /* Empty bit buffer in case of flush request. */ + if (flags & AACDEC_FLUSH) + { + transportDec_SetParam(self->hInput, TPDEC_PARAM_RESET, 1); + self->streamInfo.numLostAccessUnits = 0; + self->streamInfo.numBadBytes = 0; + self->streamInfo.numTotalBytes = 0; + } + + + ErrorStatus = CAacDecoder_DecodeFrame(self, + flags | (fTpConceal ? AACDEC_CONCEAL : 0), + pTimeData, + timeDataSize, + interleaved); + + if (!(flags & (AACDEC_CONCEAL|AACDEC_FLUSH))) { + TRANSPORTDEC_ERROR tpErr; + tpErr = transportDec_EndAccessUnit(self->hInput); + if (tpErr != TRANSPORTDEC_OK) { + self->frameOK = 0; + } + } + + /* If the current pTimeData does not contain a valid signal, there nothing else we can do, so bail. */ + if ( ! IS_OUTPUT_VALID(ErrorStatus) ) { + goto bail; + } + + { + /* Export data into streaminfo structure */ + self->streamInfo.sampleRate = self->streamInfo.aacSampleRate; + self->streamInfo.frameSize = self->streamInfo.aacSamplesPerFrame; + self->streamInfo.numChannels = self->aacChannels; + } + + + + CAacDecoder_SyncQmfMode(self); + +/* sbr decoder */ + + if (ErrorStatus || (flags & AACDEC_CONCEAL) || self->pAacDecoderStaticChannelInfo[0]->concealmentInfo.concealState > ConcealState_FadeIn) + { + self->frameOK = 0; /* if an error has occured do concealment in the SBR decoder too */ + } + + if (self->sbrEnabled) + { + SBR_ERROR sbrError = SBRDEC_OK; + + /* set params */ + sbrDecoder_SetParam ( self->hSbrDecoder, + SBR_SYSTEM_BITSTREAM_DELAY, + self->sbrParams.bsDelay); + + if ( self->streamInfo.aot == AOT_ER_AAC_ELD ) { + /* Configure QMF */ + sbrDecoder_SetParam ( self->hSbrDecoder, + SBR_LD_QMF_TIME_ALIGN, + (self->flags & AC_LD_MPS) ? 1 : 0 ); + } + + + + + /* apply SBR processing */ + sbrError = sbrDecoder_Apply ( self->hSbrDecoder, + pTimeData, + &self->streamInfo.numChannels, + &self->streamInfo.sampleRate, + self->channelOutputMapping[self->aacChannels-1], + interleaved, + self->frameOK, + &self->psPossible); + + + if (sbrError == SBRDEC_OK) { + + /* Update data in streaminfo structure. Assume that the SBR upsampling factor is either 1 or 2 */ + self->flags |= AC_SBR_PRESENT; + if (self->streamInfo.aacSampleRate != self->streamInfo.sampleRate) { + if (self->streamInfo.frameSize == 768) { + self->streamInfo.frameSize = (self->streamInfo.aacSamplesPerFrame * 8) / 3; + } else { + self->streamInfo.frameSize = self->streamInfo.aacSamplesPerFrame << 1; + } + } + + if (self->psPossible) { + self->flags |= AC_PS_PRESENT; + self->channelType[0] = ACT_FRONT; + self->channelType[1] = ACT_FRONT; + self->channelIndices[0] = 0; + self->channelIndices[1] = 1; + } else { + self->flags &= ~AC_PS_PRESENT; + } + } + } + + + if ( flags & (AACDEC_INTR | AACDEC_CLRHIST) ) { + /* delete data from the past (e.g. mixdown coeficients) */ + pcmDmx_Reset( self->hPcmUtils, PCMDMX_RESET_BS_DATA ); + } + /* do PCM post processing */ + pcmDmx_ApplyFrame ( + self->hPcmUtils, + pTimeData, + self->streamInfo.frameSize, + &self->streamInfo.numChannels, + interleaved, + self->channelType, + self->channelIndices, + self->channelOutputMapping + ); + + + + /* Signal interruption to take effect in next frame. */ + if ( flags & AACDEC_FLUSH ) { + aacDecoder_SignalInterruption(self); + } + + /* Update externally visible copy of flags */ + self->streamInfo.flags = self->flags; + +bail: + + /* Update Statistics */ + aacDecoder_UpdateBitStreamCounters(&self->streamInfo, hBs, nBits, ErrorStatus); + + return ErrorStatus; +} + +LINKSPEC_CPP void aacDecoder_Close ( HANDLE_AACDECODER self ) +{ + if (self == NULL) + return; + + + + if (self->hPcmUtils != NULL) { + pcmDmx_Close( &self->hPcmUtils ); + } + + + + if (self->hSbrDecoder != NULL) { + sbrDecoder_Close(&self->hSbrDecoder); + } + + if (self->hInput != NULL) { + transportDec_Close(&self->hInput); + } + + CAacDecoder_Close(self); +} + + +LINKSPEC_CPP CStreamInfo* aacDecoder_GetStreamInfo ( HANDLE_AACDECODER self ) +{ + return CAacDecoder_GetStreamInfo(self); +} + +LINKSPEC_CPP INT aacDecoder_GetLibInfo ( LIB_INFO *info ) +{ + int i; + + if (info == NULL) { + return -1; + } + + sbrDecoder_GetLibInfo( info ); + transportDec_GetLibInfo( info ); + FDK_toolsGetLibInfo( info ); + pcmDmx_GetLibInfo( info ); + + /* search for next free tab */ + for (i = 0; i < FDK_MODULE_LAST; i++) { + if (info[i].module_id == FDK_NONE) break; + } + if (i == FDK_MODULE_LAST) { + return -1; + } + info += i; + + info->module_id = FDK_AACDEC; + /* build own library info */ + info->version = LIB_VERSION(AACDECODER_LIB_VL0, AACDECODER_LIB_VL1, AACDECODER_LIB_VL2); + LIB_VERSION_STRING(info); + info->build_date = AACDECODER_LIB_BUILD_DATE; + info->build_time = AACDECODER_LIB_BUILD_TIME; + info->title = AACDECODER_LIB_TITLE; + + /* Set flags */ + info->flags = 0 + | CAPF_AAC_LC + | CAPF_AAC_VCB11 + | CAPF_AAC_HCR + | CAPF_AAC_RVLC + | CAPF_ER_AAC_LD + | CAPF_ER_AAC_ELD + | CAPF_AAC_CONCEALMENT + | CAPF_AAC_DRC + + | CAPF_AAC_MPEG4 + + + | CAPF_AAC_1024 + | CAPF_AAC_960 + + | CAPF_AAC_512 + + | CAPF_AAC_480 + + ; + /* End of flags */ + + return 0; +} + + + + |