diff options
Diffstat (limited to 'fdk-aac/libAACdec/src/rvlc.cpp')
-rw-r--r-- | fdk-aac/libAACdec/src/rvlc.cpp | 1217 |
1 files changed, 1217 insertions, 0 deletions
diff --git a/fdk-aac/libAACdec/src/rvlc.cpp b/fdk-aac/libAACdec/src/rvlc.cpp new file mode 100644 index 0000000..b7a9be1 --- /dev/null +++ b/fdk-aac/libAACdec/src/rvlc.cpp @@ -0,0 +1,1217 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief RVLC Decoder + \author Robert Weidner +*/ + +#include "rvlc.h" + +#include "block.h" + +#include "aac_rom.h" +#include "rvlcbit.h" +#include "rvlcconceal.h" +#include "aacdec_hcr.h" + +/*--------------------------------------------------------------------------------------------- + function: rvlcInit + + description: init RVLC by data from channelinfo, which was decoded +previously and set up pointers +----------------------------------------------------------------------------------------------- + input: - pointer rvlc structure + - pointer channel info structure + - pointer bitstream structure +----------------------------------------------------------------------------------------------- + return: - +-------------------------------------------------------------------------------------------- +*/ + +static void rvlcInit(CErRvlcInfo *pRvlc, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + HANDLE_FDK_BITSTREAM bs) { + /* RVLC common initialization part 2 of 2 */ + SHORT *pScfEsc = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfEsc; + SHORT *pScfFwd = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd; + SHORT *pScfBwd = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd; + SHORT *pScaleFactor = pAacDecoderChannelInfo->pDynData->aScaleFactor; + int bnds; + + pAacDecoderChannelInfo->pDynData->specificTo.aac.rvlcIntensityUsed = 0; + + pRvlc->numDecodedEscapeWordsEsc = 0; + pRvlc->numDecodedEscapeWordsFwd = 0; + pRvlc->numDecodedEscapeWordsBwd = 0; + + pRvlc->intensity_used = 0; + pRvlc->errorLogRvlc = 0; + + pRvlc->conceal_max = CONCEAL_MAX_INIT; + pRvlc->conceal_min = CONCEAL_MIN_INIT; + + pRvlc->conceal_max_esc = CONCEAL_MAX_INIT; + pRvlc->conceal_min_esc = CONCEAL_MIN_INIT; + + pRvlc->pHuffTreeRvlcEscape = aHuffTreeRvlcEscape; + pRvlc->pHuffTreeRvlCodewds = aHuffTreeRvlCodewds; + + /* init scf arrays (for savety (in case of there are only zero codebooks)) */ + for (bnds = 0; bnds < RVLC_MAX_SFB; bnds++) { + pScfFwd[bnds] = 0; + pScfBwd[bnds] = 0; + pScfEsc[bnds] = 0; + pScaleFactor[bnds] = 0; + } + + /* set base bitstream ptr to the RVL-coded part (start of RVLC data (ESC 2)) + */ + FDKsyncCache(bs); + pRvlc->bsAnchor = (INT)FDKgetValidBits(bs); + + pRvlc->bitstreamIndexRvlFwd = + 0; /* first bit within RVL coded block as start address for forward + decoding */ + pRvlc->bitstreamIndexRvlBwd = + pRvlc->length_of_rvlc_sf - 1; /* last bit within RVL coded block as start + address for backward decoding */ + + /* skip RVLC-bitstream-part -- pointing now to escapes (if present) or to TNS + * data (if present) */ + FDKpushFor(bs, pRvlc->length_of_rvlc_sf); + + if (pRvlc->sf_escapes_present != 0) { + /* locate internal bitstream ptr at escapes (which is the second part) */ + FDKsyncCache(bs); + pRvlc->bitstreamIndexEsc = pRvlc->bsAnchor - (INT)FDKgetValidBits(bs); + + /* skip escapeRVLC-bitstream-part -- pointing to TNS data (if present) to + * make decoder continue */ + /* decoding of RVLC should work despite this second pushFor during + * initialization because */ + /* bitstream initialization is valid for both ESC2 data parts (RVL-coded + * values and ESC-coded values) */ + FDKpushFor(bs, pRvlc->length_of_rvlc_escapes); + } +} + +/*--------------------------------------------------------------------------------------------- + function: rvlcCheckIntensityCb + + description: Check if a intensity codebook is used in the current channel. +----------------------------------------------------------------------------------------------- + input: - pointer rvlc structure + - pointer channel info structure +----------------------------------------------------------------------------------------------- + output: - intensity_used: 0 no intensity codebook is used + 1 intensity codebook is used +----------------------------------------------------------------------------------------------- + return: - +-------------------------------------------------------------------------------------------- +*/ + +static void rvlcCheckIntensityCb( + CErRvlcInfo *pRvlc, CAacDecoderChannelInfo *pAacDecoderChannelInfo) { + int group, band, bnds; + + pRvlc->intensity_used = 0; + + for (group = 0; group < pRvlc->numWindowGroups; group++) { + for (band = 0; band < pRvlc->maxSfbTransmitted; band++) { + bnds = 16 * group + band; + if ((pAacDecoderChannelInfo->pDynData->aCodeBook[bnds] == + INTENSITY_HCB) || + (pAacDecoderChannelInfo->pDynData->aCodeBook[bnds] == + INTENSITY_HCB2)) { + pRvlc->intensity_used = 1; + break; + } + } + } +} + +/*--------------------------------------------------------------------------------------------- + function: rvlcDecodeEscapeWord + + description: Decode a huffman coded RVLC Escape-word. This value is part +of a DPCM coded scalefactor. +----------------------------------------------------------------------------------------------- + input: - pointer rvlc structure +----------------------------------------------------------------------------------------------- + return: - a single RVLC-Escape value which had to be applied to a +DPCM value (which has a absolute value of 7) +-------------------------------------------------------------------------------------------- +*/ + +static SCHAR rvlcDecodeEscapeWord(CErRvlcInfo *pRvlc, HANDLE_FDK_BITSTREAM bs) { + int i; + SCHAR value; + UCHAR carryBit; + UINT treeNode; + UINT branchValue; + UINT branchNode; + + INT *pBitstreamIndexEsc; + const UINT *pEscTree; + + pEscTree = pRvlc->pHuffTreeRvlcEscape; + pBitstreamIndexEsc = &(pRvlc->bitstreamIndexEsc); + treeNode = *pEscTree; /* init at starting node */ + + for (i = MAX_LEN_RVLC_ESCAPE_WORD - 1; i >= 0; i--) { + carryBit = + rvlcReadBitFromBitstream(bs, /* get next bit */ + pRvlc->bsAnchor, pBitstreamIndexEsc, FWD); + + CarryBitToBranchValue(carryBit, /* huffman decoding, do a single step in + huffman decoding tree */ + treeNode, &branchValue, &branchNode); + + if ((branchNode & TEST_BIT_10) == + TEST_BIT_10) { /* test bit 10 ; if set --> a RVLC-escape-word is + completely decoded */ + value = (SCHAR)branchNode & CLR_BIT_10; + pRvlc->length_of_rvlc_escapes -= (MAX_LEN_RVLC_ESCAPE_WORD - i); + + if (pRvlc->length_of_rvlc_escapes < 0) { + pRvlc->errorLogRvlc |= RVLC_ERROR_ALL_ESCAPE_WORDS_INVALID; + value = -1; + } + + return value; + } else { + treeNode = *( + pEscTree + + branchValue); /* update treeNode for further step in decoding tree */ + } + } + + pRvlc->errorLogRvlc |= RVLC_ERROR_ALL_ESCAPE_WORDS_INVALID; + + return -1; /* should not be reached */ +} + +/*--------------------------------------------------------------------------------------------- + function: rvlcDecodeEscapes + + description: Decodes all huffman coded RVLC Escape Words. + Here a difference to the pseudo-code-implementation from +standard can be found. A while loop (and not two nested for loops) is used for +two reasons: + + 1. The plain huffman encoded escapes are decoded before the +RVL-coded scalefactors. Therefore the escapes are present in the second step + when decoding the RVL-coded-scalefactor values in forward +and backward direction. + + When the RVL-coded scalefactors are decoded and there a +escape is needed, then it is just taken out of the array in ascending order. + + 2. It's faster. +----------------------------------------------------------------------------------------------- + input: - pointer rvlc structure + - handle to FDK bitstream +----------------------------------------------------------------------------------------------- + return: - 0 ok the decoded escapes seem to be valid + - 1 error there was a error detected during decoding escapes + --> all escapes are invalid +-------------------------------------------------------------------------------------------- +*/ + +static void rvlcDecodeEscapes(CErRvlcInfo *pRvlc, SHORT *pEsc, + HANDLE_FDK_BITSTREAM bs) { + SCHAR escWord; + SCHAR escCnt = 0; + SHORT *pEscBitCntSum; + + pEscBitCntSum = &(pRvlc->length_of_rvlc_escapes); + + /* Decode all RVLC-Escape words with a plain Huffman-Decoder */ + while (*pEscBitCntSum > 0) { + escWord = rvlcDecodeEscapeWord(pRvlc, bs); + + if (escWord >= 0) { + pEsc[escCnt] = escWord; + escCnt++; + } else { + pRvlc->errorLogRvlc |= RVLC_ERROR_ALL_ESCAPE_WORDS_INVALID; + pRvlc->numDecodedEscapeWordsEsc = escCnt; + + return; + } + } /* all RVLC escapes decoded */ + + pRvlc->numDecodedEscapeWordsEsc = escCnt; +} + +/*--------------------------------------------------------------------------------------------- + function: decodeRVLCodeword + + description: Decodes a RVL-coded dpcm-word (-part). +----------------------------------------------------------------------------------------------- + input: - FDK bitstream handle + - pointer rvlc structure +----------------------------------------------------------------------------------------------- + return: - a dpcm value which is within range [0,1,..,14] in case of +no errors. The offset of 7 must be subtracted to get a valid dpcm scalefactor +value. In case of errors a forbidden codeword is detected --> returning -1 +-------------------------------------------------------------------------------------------- +*/ + +SCHAR decodeRVLCodeword(HANDLE_FDK_BITSTREAM bs, CErRvlcInfo *pRvlc) { + int i; + SCHAR value; + UCHAR carryBit; + UINT branchValue; + UINT branchNode; + + const UINT *pRvlCodeTree = pRvlc->pHuffTreeRvlCodewds; + UCHAR direction = pRvlc->direction; + INT *pBitstrIndxRvl = pRvlc->pBitstrIndxRvl_RVL; + UINT treeNode = *pRvlCodeTree; + + for (i = MAX_LEN_RVLC_CODE_WORD - 1; i >= 0; i--) { + carryBit = + rvlcReadBitFromBitstream(bs, /* get next bit */ + pRvlc->bsAnchor, pBitstrIndxRvl, direction); + + CarryBitToBranchValue(carryBit, /* huffman decoding, do a single step in + huffman decoding tree */ + treeNode, &branchValue, &branchNode); + + if ((branchNode & TEST_BIT_10) == + TEST_BIT_10) { /* test bit 10 ; if set --> a + RVLC-codeword is completely decoded + */ + value = (SCHAR)(branchNode & CLR_BIT_10); + *pRvlc->pRvlBitCnt_RVL -= (MAX_LEN_RVLC_CODE_WORD - i); + + /* check available bits for decoding */ + if (*pRvlc->pRvlBitCnt_RVL < 0) { + if (direction == FWD) { + pRvlc->errorLogRvlc |= RVLC_ERROR_RVL_SUM_BIT_COUNTER_BELOW_ZERO_FWD; + } else { + pRvlc->errorLogRvlc |= RVLC_ERROR_RVL_SUM_BIT_COUNTER_BELOW_ZERO_BWD; + } + value = -1; /* signalize an error in return value, because too many bits + was decoded */ + } + + /* check max value of dpcm value */ + if (value > MAX_ALLOWED_DPCM_INDEX) { + if (direction == FWD) { + pRvlc->errorLogRvlc |= RVLC_ERROR_FORBIDDEN_CW_DETECTED_FWD; + } else { + pRvlc->errorLogRvlc |= RVLC_ERROR_FORBIDDEN_CW_DETECTED_BWD; + } + value = -1; /* signalize an error in return value, because a forbidden + cw was detected*/ + } + + return value; /* return a dpcm value with offset +7 or an error status */ + } else { + treeNode = *( + pRvlCodeTree + + branchValue); /* update treeNode for further step in decoding tree */ + } + } + + return -1; +} + +/*--------------------------------------------------------------------------------------------- + function: rvlcDecodeForward + + description: Decode RVL-coded codewords in forward direction. +----------------------------------------------------------------------------------------------- + input: - pointer rvlc structure + - pointer channel info structure + - handle to FDK bitstream +----------------------------------------------------------------------------------------------- + return: - +-------------------------------------------------------------------------------------------- +*/ + +static void rvlcDecodeForward(CErRvlcInfo *pRvlc, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + HANDLE_FDK_BITSTREAM bs) { + int band = 0; + int group = 0; + int bnds = 0; + + SHORT dpcm; + + SHORT factor = + pAacDecoderChannelInfo->pDynData->RawDataInfo.GlobalGain - SF_OFFSET; + SHORT position = -SF_OFFSET; + SHORT noisenrg = pAacDecoderChannelInfo->pDynData->RawDataInfo.GlobalGain - + SF_OFFSET - 90 - 256; + + SHORT *pScfFwd = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd; + SHORT *pScfEsc = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfEsc; + UCHAR *pEscFwdCnt = &(pRvlc->numDecodedEscapeWordsFwd); + + pRvlc->pRvlBitCnt_RVL = &(pRvlc->length_of_rvlc_sf_fwd); + pRvlc->pBitstrIndxRvl_RVL = &(pRvlc->bitstreamIndexRvlFwd); + + *pEscFwdCnt = 0; + pRvlc->direction = FWD; + pRvlc->noise_used = 0; + pRvlc->sf_used = 0; + pRvlc->lastScf = 0; + pRvlc->lastNrg = 0; + pRvlc->lastIs = 0; + + rvlcCheckIntensityCb(pRvlc, pAacDecoderChannelInfo); + + /* main loop fwd long */ + for (group = 0; group < pRvlc->numWindowGroups; group++) { + for (band = 0; band < pRvlc->maxSfbTransmitted; band++) { + bnds = 16 * group + band; + + switch (pAacDecoderChannelInfo->pDynData->aCodeBook[bnds]) { + case ZERO_HCB: + pScfFwd[bnds] = 0; + break; + + case INTENSITY_HCB2: + case INTENSITY_HCB: + /* store dpcm_is_position */ + dpcm = decodeRVLCodeword(bs, pRvlc); + if (dpcm < 0) { + pRvlc->conceal_max = bnds; + return; + } + dpcm -= TABLE_OFFSET; + if ((dpcm == MIN_RVL) || (dpcm == MAX_RVL)) { + if (pRvlc->length_of_rvlc_escapes) { + pRvlc->conceal_max = bnds; + return; + } else { + if (dpcm == MIN_RVL) { + dpcm -= *pScfEsc++; + } else { + dpcm += *pScfEsc++; + } + (*pEscFwdCnt)++; + if (pRvlc->conceal_max_esc == CONCEAL_MAX_INIT) { + pRvlc->conceal_max_esc = bnds; + } + } + } + position += dpcm; + pScfFwd[bnds] = position; + pRvlc->lastIs = position; + break; + + case NOISE_HCB: + if (pRvlc->noise_used == 0) { + pRvlc->noise_used = 1; + pRvlc->first_noise_band = bnds; + noisenrg += pRvlc->dpcm_noise_nrg; + pScfFwd[bnds] = 100 + noisenrg; + pRvlc->lastNrg = noisenrg; + } else { + dpcm = decodeRVLCodeword(bs, pRvlc); + if (dpcm < 0) { + pRvlc->conceal_max = bnds; + return; + } + dpcm -= TABLE_OFFSET; + if ((dpcm == MIN_RVL) || (dpcm == MAX_RVL)) { + if (pRvlc->length_of_rvlc_escapes) { + pRvlc->conceal_max = bnds; + return; + } else { + if (dpcm == MIN_RVL) { + dpcm -= *pScfEsc++; + } else { + dpcm += *pScfEsc++; + } + (*pEscFwdCnt)++; + if (pRvlc->conceal_max_esc == CONCEAL_MAX_INIT) { + pRvlc->conceal_max_esc = bnds; + } + } + } + noisenrg += dpcm; + pScfFwd[bnds] = 100 + noisenrg; + pRvlc->lastNrg = noisenrg; + } + pAacDecoderChannelInfo->data.aac.PnsData.pnsUsed[bnds] = 1; + break; + + default: + pRvlc->sf_used = 1; + dpcm = decodeRVLCodeword(bs, pRvlc); + if (dpcm < 0) { + pRvlc->conceal_max = bnds; + return; + } + dpcm -= TABLE_OFFSET; + if ((dpcm == MIN_RVL) || (dpcm == MAX_RVL)) { + if (pRvlc->length_of_rvlc_escapes) { + pRvlc->conceal_max = bnds; + return; + } else { + if (dpcm == MIN_RVL) { + dpcm -= *pScfEsc++; + } else { + dpcm += *pScfEsc++; + } + (*pEscFwdCnt)++; + if (pRvlc->conceal_max_esc == CONCEAL_MAX_INIT) { + pRvlc->conceal_max_esc = bnds; + } + } + } + factor += dpcm; + pScfFwd[bnds] = factor; + pRvlc->lastScf = factor; + break; + } + } + } + + /* postfetch fwd long */ + if (pRvlc->intensity_used) { + dpcm = decodeRVLCodeword(bs, pRvlc); /* dpcm_is_last_position */ + if (dpcm < 0) { + pRvlc->conceal_max = bnds; + return; + } + dpcm -= TABLE_OFFSET; + if ((dpcm == MIN_RVL) || (dpcm == MAX_RVL)) { + if (pRvlc->length_of_rvlc_escapes) { + pRvlc->conceal_max = bnds; + return; + } else { + if (dpcm == MIN_RVL) { + dpcm -= *pScfEsc++; + } else { + dpcm += *pScfEsc++; + } + (*pEscFwdCnt)++; + if (pRvlc->conceal_max_esc == CONCEAL_MAX_INIT) { + pRvlc->conceal_max_esc = bnds; + } + } + } + pRvlc->dpcm_is_last_position = dpcm; + } +} + +/*--------------------------------------------------------------------------------------------- + function: rvlcDecodeBackward + + description: Decode RVL-coded codewords in backward direction. +----------------------------------------------------------------------------------------------- + input: - pointer rvlc structure + - pointer channel info structure + - handle FDK bitstream +----------------------------------------------------------------------------------------------- + return: - +-------------------------------------------------------------------------------------------- +*/ + +static void rvlcDecodeBackward(CErRvlcInfo *pRvlc, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + HANDLE_FDK_BITSTREAM bs) { + SHORT band, group, dpcm, offset; + SHORT bnds = pRvlc->maxSfbTransmitted - 1; + + SHORT factor = pRvlc->rev_global_gain - SF_OFFSET; + SHORT position = pRvlc->dpcm_is_last_position - SF_OFFSET; + SHORT noisenrg = pRvlc->rev_global_gain + pRvlc->dpcm_noise_last_position - + SF_OFFSET - 90 - 256; + + SHORT *pScfBwd = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd; + SHORT *pScfEsc = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfEsc; + UCHAR *pEscEscCnt = &(pRvlc->numDecodedEscapeWordsEsc); + UCHAR *pEscBwdCnt = &(pRvlc->numDecodedEscapeWordsBwd); + + pRvlc->pRvlBitCnt_RVL = &(pRvlc->length_of_rvlc_sf_bwd); + pRvlc->pBitstrIndxRvl_RVL = &(pRvlc->bitstreamIndexRvlBwd); + + *pEscBwdCnt = 0; + pRvlc->direction = BWD; + pScfEsc += *pEscEscCnt - 1; /* set pScfEsc to last entry */ + pRvlc->firstScf = 0; + pRvlc->firstNrg = 0; + pRvlc->firstIs = 0; + + /* prefetch long BWD */ + if (pRvlc->intensity_used) { + dpcm = decodeRVLCodeword(bs, pRvlc); /* dpcm_is_last_position */ + if (dpcm < 0) { + pRvlc->dpcm_is_last_position = 0; + pRvlc->conceal_min = bnds; + return; + } + dpcm -= TABLE_OFFSET; + if ((dpcm == MIN_RVL) || (dpcm == MAX_RVL)) { + if (pRvlc->length_of_rvlc_escapes) { + pRvlc->conceal_min = bnds; + return; + } else { + if (dpcm == MIN_RVL) { + dpcm -= *pScfEsc--; + } else { + dpcm += *pScfEsc--; + } + (*pEscBwdCnt)++; + if (pRvlc->conceal_min_esc == CONCEAL_MIN_INIT) { + pRvlc->conceal_min_esc = bnds; + } + } + } + pRvlc->dpcm_is_last_position = dpcm; + } + + /* main loop long BWD */ + for (group = pRvlc->numWindowGroups - 1; group >= 0; group--) { + for (band = pRvlc->maxSfbTransmitted - 1; band >= 0; band--) { + bnds = 16 * group + band; + if ((band == 0) && (pRvlc->numWindowGroups != 1)) + offset = 16 - pRvlc->maxSfbTransmitted + 1; + else + offset = 1; + + switch (pAacDecoderChannelInfo->pDynData->aCodeBook[bnds]) { + case ZERO_HCB: + pScfBwd[bnds] = 0; + break; + + case INTENSITY_HCB2: + case INTENSITY_HCB: + /* store dpcm_is_position */ + dpcm = decodeRVLCodeword(bs, pRvlc); + if (dpcm < 0) { + pScfBwd[bnds] = position; + pRvlc->conceal_min = fMax(0, bnds - offset); + return; + } + dpcm -= TABLE_OFFSET; + if ((dpcm == MIN_RVL) || (dpcm == MAX_RVL)) { + if (pRvlc->length_of_rvlc_escapes) { + pScfBwd[bnds] = position; + pRvlc->conceal_min = fMax(0, bnds - offset); + return; + } else { + if (dpcm == MIN_RVL) { + dpcm -= *pScfEsc--; + } else { + dpcm += *pScfEsc--; + } + (*pEscBwdCnt)++; + if (pRvlc->conceal_min_esc == CONCEAL_MIN_INIT) { + pRvlc->conceal_min_esc = fMax(0, bnds - offset); + } + } + } + pScfBwd[bnds] = position; + position -= dpcm; + pRvlc->firstIs = position; + break; + + case NOISE_HCB: + if (bnds == pRvlc->first_noise_band) { + pScfBwd[bnds] = + pRvlc->dpcm_noise_nrg + + pAacDecoderChannelInfo->pDynData->RawDataInfo.GlobalGain - + SF_OFFSET - 90 - 256; + pRvlc->firstNrg = pScfBwd[bnds]; + } else { + dpcm = decodeRVLCodeword(bs, pRvlc); + if (dpcm < 0) { + pScfBwd[bnds] = noisenrg; + pRvlc->conceal_min = fMax(0, bnds - offset); + return; + } + dpcm -= TABLE_OFFSET; + if ((dpcm == MIN_RVL) || (dpcm == MAX_RVL)) { + if (pRvlc->length_of_rvlc_escapes) { + pScfBwd[bnds] = noisenrg; + pRvlc->conceal_min = fMax(0, bnds - offset); + return; + } else { + if (dpcm == MIN_RVL) { + dpcm -= *pScfEsc--; + } else { + dpcm += *pScfEsc--; + } + (*pEscBwdCnt)++; + if (pRvlc->conceal_min_esc == CONCEAL_MIN_INIT) { + pRvlc->conceal_min_esc = fMax(0, bnds - offset); + } + } + } + pScfBwd[bnds] = noisenrg; + noisenrg -= dpcm; + pRvlc->firstNrg = noisenrg; + } + break; + + default: + dpcm = decodeRVLCodeword(bs, pRvlc); + if (dpcm < 0) { + pScfBwd[bnds] = factor; + pRvlc->conceal_min = fMax(0, bnds - offset); + return; + } + dpcm -= TABLE_OFFSET; + if ((dpcm == MIN_RVL) || (dpcm == MAX_RVL)) { + if (pRvlc->length_of_rvlc_escapes) { + pScfBwd[bnds] = factor; + pRvlc->conceal_min = fMax(0, bnds - offset); + return; + } else { + if (dpcm == MIN_RVL) { + dpcm -= *pScfEsc--; + } else { + dpcm += *pScfEsc--; + } + (*pEscBwdCnt)++; + if (pRvlc->conceal_min_esc == CONCEAL_MIN_INIT) { + pRvlc->conceal_min_esc = fMax(0, bnds - offset); + } + } + } + pScfBwd[bnds] = factor; + factor -= dpcm; + pRvlc->firstScf = factor; + break; + } + } + } +} + +/*--------------------------------------------------------------------------------------------- + function: rvlcFinalErrorDetection + + description: Call RVLC concealment if error was detected in decoding +process +----------------------------------------------------------------------------------------------- + input: - pointer rvlc structure + - pointer channel info structure +----------------------------------------------------------------------------------------------- + return: - +-------------------------------------------------------------------------------------------- +*/ + +static void rvlcFinalErrorDetection( + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo) { + CErRvlcInfo *pRvlc = + &pAacDecoderChannelInfo->pComData->overlay.aac.erRvlcInfo; + UCHAR ErrorStatusComplete = 0; + UCHAR ErrorStatusLengthFwd = 0; + UCHAR ErrorStatusLengthBwd = 0; + UCHAR ErrorStatusLengthEscapes = 0; + UCHAR ErrorStatusFirstScf = 0; + UCHAR ErrorStatusLastScf = 0; + UCHAR ErrorStatusFirstNrg = 0; + UCHAR ErrorStatusLastNrg = 0; + UCHAR ErrorStatusFirstIs = 0; + UCHAR ErrorStatusLastIs = 0; + UCHAR ErrorStatusForbiddenCwFwd = 0; + UCHAR ErrorStatusForbiddenCwBwd = 0; + UCHAR ErrorStatusNumEscapesFwd = 0; + UCHAR ErrorStatusNumEscapesBwd = 0; + UCHAR ConcealStatus = 1; + UCHAR currentBlockType; /* short: 0, not short: 1*/ + + pAacDecoderChannelInfo->pDynData->specificTo.aac.rvlcCurrentScaleFactorOK = 1; + + /* invalid escape words, bit counter unequal zero, forbidden codeword detected + */ + if (pRvlc->errorLogRvlc & RVLC_ERROR_FORBIDDEN_CW_DETECTED_FWD) + ErrorStatusForbiddenCwFwd = 1; + + if (pRvlc->errorLogRvlc & RVLC_ERROR_FORBIDDEN_CW_DETECTED_BWD) + ErrorStatusForbiddenCwBwd = 1; + + /* bit counter forward unequal zero */ + if (pRvlc->length_of_rvlc_sf_fwd) ErrorStatusLengthFwd = 1; + + /* bit counter backward unequal zero */ + if (pRvlc->length_of_rvlc_sf_bwd) ErrorStatusLengthBwd = 1; + + /* bit counter escape sequences unequal zero */ + if (pRvlc->sf_escapes_present) + if (pRvlc->length_of_rvlc_escapes) ErrorStatusLengthEscapes = 1; + + if (pRvlc->sf_used) { + /* first decoded scf does not match to global gain in backward direction */ + if (pRvlc->firstScf != + (pAacDecoderChannelInfo->pDynData->RawDataInfo.GlobalGain - SF_OFFSET)) + ErrorStatusFirstScf = 1; + + /* last decoded scf does not match to rev global gain in forward direction + */ + if (pRvlc->lastScf != (pRvlc->rev_global_gain - SF_OFFSET)) + ErrorStatusLastScf = 1; + } + + if (pRvlc->noise_used) { + /* first decoded nrg does not match to dpcm_noise_nrg in backward direction + */ + if (pRvlc->firstNrg != + (pAacDecoderChannelInfo->pDynData->RawDataInfo.GlobalGain + + pRvlc->dpcm_noise_nrg - SF_OFFSET - 90 - 256)) + ErrorStatusFirstNrg = 1; + + /* last decoded nrg does not match to dpcm_noise_last_position in forward + * direction */ + if (pRvlc->lastNrg != + (pRvlc->rev_global_gain + pRvlc->dpcm_noise_last_position - SF_OFFSET - + 90 - 256)) + ErrorStatusLastNrg = 1; + } + + if (pRvlc->intensity_used) { + /* first decoded is position does not match in backward direction */ + if (pRvlc->firstIs != (-SF_OFFSET)) ErrorStatusFirstIs = 1; + + /* last decoded is position does not match in forward direction */ + if (pRvlc->lastIs != (pRvlc->dpcm_is_last_position - SF_OFFSET)) + ErrorStatusLastIs = 1; + } + + /* decoded escapes and used escapes in forward direction do not fit */ + if ((pRvlc->numDecodedEscapeWordsFwd != pRvlc->numDecodedEscapeWordsEsc) && + (pRvlc->conceal_max == CONCEAL_MAX_INIT)) { + ErrorStatusNumEscapesFwd = 1; + } + + /* decoded escapes and used escapes in backward direction do not fit */ + if ((pRvlc->numDecodedEscapeWordsBwd != pRvlc->numDecodedEscapeWordsEsc) && + (pRvlc->conceal_min == CONCEAL_MIN_INIT)) { + ErrorStatusNumEscapesBwd = 1; + } + + if (ErrorStatusLengthEscapes || + (((pRvlc->conceal_max == CONCEAL_MAX_INIT) && + (pRvlc->numDecodedEscapeWordsFwd != pRvlc->numDecodedEscapeWordsEsc) && + (ErrorStatusLastScf || ErrorStatusLastNrg || ErrorStatusLastIs)) + + && + + ((pRvlc->conceal_min == CONCEAL_MIN_INIT) && + (pRvlc->numDecodedEscapeWordsBwd != pRvlc->numDecodedEscapeWordsEsc) && + (ErrorStatusFirstScf || ErrorStatusFirstNrg || ErrorStatusFirstIs))) || + ((pRvlc->conceal_max == CONCEAL_MAX_INIT) && + ((pRvlc->rev_global_gain - SF_OFFSET - pRvlc->lastScf) < -15)) || + ((pRvlc->conceal_min == CONCEAL_MIN_INIT) && + ((pAacDecoderChannelInfo->pDynData->RawDataInfo.GlobalGain - SF_OFFSET - + pRvlc->firstScf) < -15))) { + if ((pRvlc->conceal_max == CONCEAL_MAX_INIT) || + (pRvlc->conceal_min == CONCEAL_MIN_INIT)) { + pRvlc->conceal_max = 0; + pRvlc->conceal_min = fMax( + 0, (pRvlc->numWindowGroups - 1) * 16 + pRvlc->maxSfbTransmitted - 1); + } else { + pRvlc->conceal_max = fMin(pRvlc->conceal_max, pRvlc->conceal_max_esc); + pRvlc->conceal_min = fMax(pRvlc->conceal_min, pRvlc->conceal_min_esc); + } + } + + ErrorStatusComplete = ErrorStatusLastScf || ErrorStatusFirstScf || + ErrorStatusLastNrg || ErrorStatusFirstNrg || + ErrorStatusLastIs || ErrorStatusFirstIs || + ErrorStatusForbiddenCwFwd || + ErrorStatusForbiddenCwBwd || ErrorStatusLengthFwd || + ErrorStatusLengthBwd || ErrorStatusLengthEscapes || + ErrorStatusNumEscapesFwd || ErrorStatusNumEscapesBwd; + + currentBlockType = + (GetWindowSequence(&pAacDecoderChannelInfo->icsInfo) == BLOCK_SHORT) ? 0 + : 1; + + if (!ErrorStatusComplete) { + int band; + int group; + int bnds; + int lastSfbIndex; + + lastSfbIndex = (pRvlc->numWindowGroups > 1) ? 16 : 64; + + for (group = 0; group < pRvlc->numWindowGroups; group++) { + for (band = 0; band < pRvlc->maxSfbTransmitted; band++) { + bnds = 16 * group + band; + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = + pAacDecoderStaticChannelInfo->concealmentInfo + .aRvlcPreviousScaleFactor[bnds] = + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds]; + } + } + + for (group = 0; group < pRvlc->numWindowGroups; group++) { + for (band = 0; band < pRvlc->maxSfbTransmitted; band++) { + bnds = 16 * group + band; + pAacDecoderStaticChannelInfo->concealmentInfo + .aRvlcPreviousCodebook[bnds] = + pAacDecoderChannelInfo->pDynData->aCodeBook[bnds]; + } + for (; band < lastSfbIndex; band++) { + bnds = 16 * group + band; + FDK_ASSERT(bnds >= 0 && bnds < RVLC_MAX_SFB); + pAacDecoderStaticChannelInfo->concealmentInfo + .aRvlcPreviousCodebook[bnds] = ZERO_HCB; + } + } + } else { + int band; + int group; + + /* A single bit error was detected in decoding of dpcm values. It also could + be an error with more bits in decoding of escapes and dpcm values whereby + an illegal codeword followed not directly after the corrupted bits but + just after decoding some more (wrong) scalefactors. Use the smaller + scalefactor from forward decoding, backward decoding and previous frame. + */ + if (((pRvlc->conceal_min != CONCEAL_MIN_INIT) || + (pRvlc->conceal_max != CONCEAL_MAX_INIT)) && + (pRvlc->conceal_min <= pRvlc->conceal_max) && + (pAacDecoderStaticChannelInfo->concealmentInfo.rvlcPreviousBlockType == + currentBlockType) && + pAacDecoderStaticChannelInfo->concealmentInfo + .rvlcPreviousScaleFactorOK && + pRvlc->sf_concealment && ConcealStatus) { + BidirectionalEstimation_UseScfOfPrevFrameAsReference( + pAacDecoderChannelInfo, pAacDecoderStaticChannelInfo); + ConcealStatus = 0; + } + + /* A single bit error was detected in decoding of dpcm values. It also could + be an error with more bits in decoding of escapes and dpcm values whereby + an illegal codeword followed not directly after the corrupted bits but + just after decoding some more (wrong) scalefactors. Use the smaller + scalefactor from forward and backward decoding. */ + if ((pRvlc->conceal_min <= pRvlc->conceal_max) && + ((pRvlc->conceal_min != CONCEAL_MIN_INIT) || + (pRvlc->conceal_max != CONCEAL_MAX_INIT)) && + !(pAacDecoderStaticChannelInfo->concealmentInfo + .rvlcPreviousScaleFactorOK && + pRvlc->sf_concealment && + (pAacDecoderStaticChannelInfo->concealmentInfo + .rvlcPreviousBlockType == currentBlockType)) && + ConcealStatus) { + BidirectionalEstimation_UseLowerScfOfCurrentFrame(pAacDecoderChannelInfo); + ConcealStatus = 0; + } + + /* No errors were detected in decoding of escapes and dpcm values however + the first and last value of a group (is,nrg,sf) is incorrect */ + if ((pRvlc->conceal_min <= pRvlc->conceal_max) && + ((ErrorStatusLastScf && ErrorStatusFirstScf) || + (ErrorStatusLastNrg && ErrorStatusFirstNrg) || + (ErrorStatusLastIs && ErrorStatusFirstIs)) && + !(ErrorStatusForbiddenCwFwd || ErrorStatusForbiddenCwBwd || + ErrorStatusLengthEscapes) && + ConcealStatus) { + StatisticalEstimation(pAacDecoderChannelInfo); + ConcealStatus = 0; + } + + /* A error with more bits in decoding of escapes and dpcm values was + detected. Use the smaller scalefactor from forward decoding, backward + decoding and previous frame. */ + if ((pRvlc->conceal_min <= pRvlc->conceal_max) && + pAacDecoderStaticChannelInfo->concealmentInfo + .rvlcPreviousScaleFactorOK && + pRvlc->sf_concealment && + (pAacDecoderStaticChannelInfo->concealmentInfo.rvlcPreviousBlockType == + currentBlockType) && + ConcealStatus) { + PredictiveInterpolation(pAacDecoderChannelInfo, + pAacDecoderStaticChannelInfo); + ConcealStatus = 0; + } + + /* Call frame concealment, because no better strategy was found. Setting the + scalefactors to zero is done for debugging purposes */ + if (ConcealStatus) { + for (group = 0; group < pRvlc->numWindowGroups; group++) { + for (band = 0; band < pRvlc->maxSfbTransmitted; band++) { + pAacDecoderChannelInfo->pDynData->aScaleFactor[16 * group + band] = 0; + } + } + pAacDecoderChannelInfo->pDynData->specificTo.aac + .rvlcCurrentScaleFactorOK = 0; + } + } +} + +/*--------------------------------------------------------------------------------------------- + function: CRvlc_Read + + description: Read RVLC ESC1 data (side info) from bitstream. +----------------------------------------------------------------------------------------------- + input: - pointer rvlc structure + - pointer channel info structure + - pointer bitstream structure +----------------------------------------------------------------------------------------------- + return: - +-------------------------------------------------------------------------------------------- +*/ + +void CRvlc_Read(CAacDecoderChannelInfo *pAacDecoderChannelInfo, + HANDLE_FDK_BITSTREAM bs) { + CErRvlcInfo *pRvlc = + &pAacDecoderChannelInfo->pComData->overlay.aac.erRvlcInfo; + + int group, band; + + /* RVLC long specific initialization Init part 1 of 2 */ + pRvlc->numWindowGroups = GetWindowGroups(&pAacDecoderChannelInfo->icsInfo); + pRvlc->maxSfbTransmitted = + GetScaleFactorBandsTransmitted(&pAacDecoderChannelInfo->icsInfo); + pRvlc->noise_used = 0; /* noise detection */ + pRvlc->dpcm_noise_nrg = 0; /* only for debugging */ + pRvlc->dpcm_noise_last_position = 0; /* only for debugging */ + pRvlc->length_of_rvlc_escapes = + -1; /* default value is used for error detection and concealment */ + + /* read only error sensitivity class 1 data (ESC 1 - data) */ + pRvlc->sf_concealment = FDKreadBits(bs, 1); /* #1 */ + pRvlc->rev_global_gain = FDKreadBits(bs, 8); /* #2 */ + + if (GetWindowSequence(&pAacDecoderChannelInfo->icsInfo) == BLOCK_SHORT) { + pRvlc->length_of_rvlc_sf = FDKreadBits(bs, 11); /* #3 */ + } else { + pRvlc->length_of_rvlc_sf = FDKreadBits(bs, 9); /* #3 */ + } + + /* check if noise codebook is used */ + for (group = 0; group < pRvlc->numWindowGroups; group++) { + for (band = 0; band < pRvlc->maxSfbTransmitted; band++) { + if (pAacDecoderChannelInfo->pDynData->aCodeBook[16 * group + band] == + NOISE_HCB) { + pRvlc->noise_used = 1; + break; + } + } + } + + if (pRvlc->noise_used) + pRvlc->dpcm_noise_nrg = FDKreadBits(bs, 9); /* #4 PNS */ + + pRvlc->sf_escapes_present = FDKreadBits(bs, 1); /* #5 */ + + if (pRvlc->sf_escapes_present) { + pRvlc->length_of_rvlc_escapes = FDKreadBits(bs, 8); /* #6 */ + } + + if (pRvlc->noise_used) { + pRvlc->dpcm_noise_last_position = FDKreadBits(bs, 9); /* #7 PNS */ + pRvlc->length_of_rvlc_sf -= 9; + } + + pRvlc->length_of_rvlc_sf_fwd = pRvlc->length_of_rvlc_sf; + pRvlc->length_of_rvlc_sf_bwd = pRvlc->length_of_rvlc_sf; +} + +/*--------------------------------------------------------------------------------------------- + function: CRvlc_Decode + + description: Decode rvlc data + The function reads both the escape sequences and the +scalefactors in forward and backward direction. If an error occured during +decoding process which can not be concealed with the rvlc concealment frame +concealment will be initiated. Then the element "rvlcCurrentScaleFactorOK" in +the decoder channel info is set to 0 otherwise it is set to 1. +----------------------------------------------------------------------------------------------- + input: - pointer rvlc structure + - pointer channel info structure + - pointer to persistent channel info structure + - pointer bitstream structure +----------------------------------------------------------------------------------------------- + return: ErrorStatus = AAC_DEC_OK +-------------------------------------------------------------------------------------------- +*/ + +void CRvlc_Decode(CAacDecoderChannelInfo *pAacDecoderChannelInfo, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, + HANDLE_FDK_BITSTREAM bs) { + CErRvlcInfo *pRvlc = + &pAacDecoderChannelInfo->pComData->overlay.aac.erRvlcInfo; + INT bitCntOffst; + INT saveBitCnt; + + rvlcInit(pRvlc, pAacDecoderChannelInfo, bs); + + /* save bitstream position */ + saveBitCnt = (INT)FDKgetValidBits(bs); + + if (pRvlc->sf_escapes_present) + rvlcDecodeEscapes( + pRvlc, pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfEsc, bs); + + rvlcDecodeForward(pRvlc, pAacDecoderChannelInfo, bs); + rvlcDecodeBackward(pRvlc, pAacDecoderChannelInfo, bs); + rvlcFinalErrorDetection(pAacDecoderChannelInfo, pAacDecoderStaticChannelInfo); + + pAacDecoderChannelInfo->pDynData->specificTo.aac.rvlcIntensityUsed = + pRvlc->intensity_used; + pAacDecoderChannelInfo->data.aac.PnsData.PnsActive = pRvlc->noise_used; + + /* restore bitstream position */ + bitCntOffst = (INT)FDKgetValidBits(bs) - saveBitCnt; + if (bitCntOffst) { + FDKpushBiDirectional(bs, bitCntOffst); + } +} + +void CRvlc_ElementCheck( + CAacDecoderChannelInfo *pAacDecoderChannelInfo[], + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[], + const UINT flags, const INT elChannels) { + int ch; + + /* Required for MPS residuals. */ + if (pAacDecoderStaticChannelInfo == NULL) { + return; + } + + /* RVLC specific sanity checks */ + if ((flags & AC_ER_RVLC) && (elChannels == 2)) { /* to be reviewed */ + if (((pAacDecoderChannelInfo[0] + ->pDynData->specificTo.aac.rvlcCurrentScaleFactorOK == 0) || + (pAacDecoderChannelInfo[1] + ->pDynData->specificTo.aac.rvlcCurrentScaleFactorOK == 0)) && + pAacDecoderChannelInfo[0]->pComData->jointStereoData.MsMaskPresent) { + pAacDecoderChannelInfo[0] + ->pDynData->specificTo.aac.rvlcCurrentScaleFactorOK = 0; + pAacDecoderChannelInfo[1] + ->pDynData->specificTo.aac.rvlcCurrentScaleFactorOK = 0; + } + + if ((pAacDecoderChannelInfo[0] + ->pDynData->specificTo.aac.rvlcCurrentScaleFactorOK == 0) && + (pAacDecoderChannelInfo[1] + ->pDynData->specificTo.aac.rvlcCurrentScaleFactorOK == 1) && + (pAacDecoderChannelInfo[1] + ->pDynData->specificTo.aac.rvlcIntensityUsed == 1)) { + pAacDecoderChannelInfo[1] + ->pDynData->specificTo.aac.rvlcCurrentScaleFactorOK = 0; + } + } + + for (ch = 0; ch < elChannels; ch++) { + pAacDecoderStaticChannelInfo[ch]->concealmentInfo.rvlcPreviousBlockType = + (GetWindowSequence(&pAacDecoderChannelInfo[ch]->icsInfo) == BLOCK_SHORT) + ? 0 + : 1; + if (flags & AC_ER_RVLC) { + pAacDecoderStaticChannelInfo[ch] + ->concealmentInfo.rvlcPreviousScaleFactorOK = + pAacDecoderChannelInfo[ch] + ->pDynData->specificTo.aac.rvlcCurrentScaleFactorOK; + } else { + pAacDecoderStaticChannelInfo[ch] + ->concealmentInfo.rvlcPreviousScaleFactorOK = 0; + } + } +} |