| /* ----------------------------------------------------------------------------- |
| 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; |
| } |
| } |
| } |