diff options
Diffstat (limited to 'libAACdec/src/aacdec_hcr.cpp')
-rw-r--r-- | libAACdec/src/aacdec_hcr.cpp | 1591 |
1 files changed, 1591 insertions, 0 deletions
diff --git a/libAACdec/src/aacdec_hcr.cpp b/libAACdec/src/aacdec_hcr.cpp new file mode 100644 index 0000000..5b86833 --- /dev/null +++ b/libAACdec/src/aacdec_hcr.cpp @@ -0,0 +1,1591 @@ + +/* ----------------------------------------------------------------------------------------------------------- +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): Robert Weidner (DSP Solutions) + Description: HCR Decoder: HCR initialization, preprocess HCR sideinfo, + decode priority codewords (PCWs) + +*******************************************************************************/ + +#include "aacdec_hcr.h" + + + +#include "aacdec_hcr_types.h" +#include "aacdec_hcr_bit.h" +#include "aacdec_hcrs.h" +#include "aac_ram.h" +#include "aac_rom.h" +#include "channel.h" +#include "block.h" + +#include "aacdecoder.h" /* for ID_CPE, ID_SCE ... */ +#include "FDK_bitstream.h" + +extern int mlFileChCurr; + +static void errDetectorInHcrSideinfoShrt(SCHAR cb, + SHORT numLine, + UINT *errorWord); + +static void errDetectorInHcrLengths(SCHAR lengthOfLongestCodeword, + SHORT lengthOfReorderedSpectralData, + UINT *errorWord); + +static void HcrCalcNumCodeword (H_HCR_INFO pHcr); +static void HcrSortCodebookAndNumCodewordInSection(H_HCR_INFO pHcr); +static void HcrPrepareSegmentationGrid (H_HCR_INFO pHcr); +static void HcrExtendedSectionInfo (H_HCR_INFO pHcr); + +static void DeriveNumberOfExtendedSortedSectionsInSets(UINT numSegment, + USHORT *pNumExtendedSortedCodewordInSection, + int numExtendedSortedCodewordInSectionIdx, + USHORT *pNumExtendedSortedSectionsInSets, + int numExtendedSortedSectionsInSetsIdx); + +static INT DecodeEscapeSequence(HANDLE_FDK_BITSTREAM bs, + INT quantSpecCoef, + USHORT *pLeftStartOfSegment, + SCHAR *pRemainingBitsInSegment, + int *pNumDecodedBits + ); + +static int DecodePCW_Sign(HANDLE_FDK_BITSTREAM bs, + UINT codebookDim, + const SCHAR *pQuantVal, + FIXP_DBL *pQuantSpecCoef, + int *quantSpecCoefIdx, + USHORT *pLeftStartOfSegment, + SCHAR *pRemainingBitsInSegment, + int *pNumDecodedBits + ); + +static const SCHAR *DecodePCW_Body(HANDLE_FDK_BITSTREAM bs, + const UINT *pCurrentTree, + const SCHAR *pQuantValBase, + USHORT *pLeftStartOfSegment, + SCHAR *pRemainingBitsInSegment, + int *pNumDecodedBits + ); + +static void DecodePCWs(HANDLE_FDK_BITSTREAM bs, H_HCR_INFO pHcr); + +static void HcrReorderQuantizedSpectralCoefficients( + H_HCR_INFO pHcr, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + const SamplingRateInfo *pSamplingRateInfo + ); + + +#if CHECK_SEGMENTATION_IMMEDIATELY +static UCHAR errDetectPcwSegmentation(SCHAR remainingBitsInSegment, + H_HCR_INFO pHcr, + PCW_TYPE kind, + FIXP_DBL *qsc_base_of_cw, + UCHAR dimension); +#endif + +#if CHECK_SEGMENTATION_FINAL +static void errDetectWithinSegmentationFinal(H_HCR_INFO pHcr); +#endif + +/*--------------------------------------------------------------------------------------------- + description: Check if codebook and numSect are within allowed range (short only) +-------------------------------------------------------------------------------------------- */ +static void errDetectorInHcrSideinfoShrt(SCHAR cb, SHORT numLine,UINT* errorWord) +{ + + + + if ( cb < ZERO_HCB || cb >= MAX_CB_CHECK || cb == BOOKSCL ) { + *errorWord |= CB_OUT_OF_RANGE_SHORT_BLOCK; + } + if ( numLine < 0 || numLine > 1024 ) { + *errorWord |= LINE_IN_SECT_OUT_OF_RANGE_SHORT_BLOCK; + } +} + +/*--------------------------------------------------------------------------------------------- + description: Check both HCR lengths +-------------------------------------------------------------------------------------------- */ +static void errDetectorInHcrLengths(SCHAR lengthOfLongestCodeword, + SHORT lengthOfReorderedSpectralData, + UINT *errorWord) +{ + if ( lengthOfReorderedSpectralData < lengthOfLongestCodeword ) { + *errorWord |= HCR_SI_LENGTHS_FAILURE; + } +} + +/*--------------------------------------------------------------------------------------------- + description: Decode (and adapt if necessary) the two HCR sideinfo components: + 'reordered_spectral_data_length' and 'longest_codeword_length' +-------------------------------------------------------------------------------------------- */ + +void CHcr_Read(HANDLE_FDK_BITSTREAM bs, + CAacDecoderChannelInfo *pAacDecoderChannelInfo) +{ + INT globalHcrType = getHcrType(&pAacDecoderChannelInfo->pComData->overlay.aac.erHcrInfo); + SHORT lengOfReorderedSpectralData; + SCHAR lengOfLongestCodeword; + + pAacDecoderChannelInfo->pDynData->specificTo.aac.lenOfReorderedSpectralData = 0; + pAacDecoderChannelInfo->pDynData->specificTo.aac.lenOfLongestCodeword = 0; + + + + /* ------- SI-Value No 1 ------- */ + lengOfReorderedSpectralData = FDKreadBits(bs,14) + ERROR_LORSD; + if ( globalHcrType == ID_CPE ) { + if ((lengOfReorderedSpectralData >= 0) && (lengOfReorderedSpectralData <= CPE_TOP_LENGTH)) { + pAacDecoderChannelInfo->pDynData->specificTo.aac.lenOfReorderedSpectralData = lengOfReorderedSpectralData; /* the decoded value is within range */ + } + else { + if (lengOfReorderedSpectralData > CPE_TOP_LENGTH) { + pAacDecoderChannelInfo->pDynData->specificTo.aac.lenOfReorderedSpectralData = CPE_TOP_LENGTH; /* use valid maximum */ + } + } + } + else if (globalHcrType == ID_SCE || globalHcrType == ID_LFE || globalHcrType == ID_CCE ) { + if ((lengOfReorderedSpectralData >= 0) && (lengOfReorderedSpectralData <= SCE_TOP_LENGTH)) { + pAacDecoderChannelInfo->pDynData->specificTo.aac.lenOfReorderedSpectralData = lengOfReorderedSpectralData; /* the decoded value is within range */ + } + else { + if (lengOfReorderedSpectralData > SCE_TOP_LENGTH) { + pAacDecoderChannelInfo->pDynData->specificTo.aac.lenOfReorderedSpectralData = SCE_TOP_LENGTH; /* use valid maximum */ + } + } + } + + /* ------- SI-Value No 2 ------- */ + lengOfLongestCodeword = FDKreadBits(bs,6) + ERROR_LOLC; + if ((lengOfLongestCodeword >= 0) && (lengOfLongestCodeword <= LEN_OF_LONGEST_CW_TOP_LENGTH)) { + pAacDecoderChannelInfo->pDynData->specificTo.aac.lenOfLongestCodeword = lengOfLongestCodeword; /* the decoded value is within range */ + } + else { + if (lengOfLongestCodeword > LEN_OF_LONGEST_CW_TOP_LENGTH) { + pAacDecoderChannelInfo->pDynData->specificTo.aac.lenOfLongestCodeword = LEN_OF_LONGEST_CW_TOP_LENGTH; /* use valid maximum */ + } + } +} + + +/*--------------------------------------------------------------------------------------------- + description: Sets up HCR ROM-Tables +-------------------------------------------------------------------------------------------- */ + +void HcrInitRom(H_HCR_INFO pHcr) +{ + pHcr->cbPairs.pMinOfCbPair = aMinOfCbPair; + pHcr->cbPairs.pMaxOfCbPair = aMaxOfCbPair; + + pHcr->tableInfo.pMaxCwLength = aMaxCwLen; + pHcr->tableInfo.pCbDimension = aDimCb; + pHcr->tableInfo.pCbDimShift = aDimCbShift; + pHcr->tableInfo.pCbSign = aSignCb; + pHcr->tableInfo.pCbPriority = aCbPriority; + pHcr->tableInfo.pLargestAbsVal = aLargestAbsoluteValue; +} + +/*--------------------------------------------------------------------------------------------- + description: Set up HCR - must be called before every call to HcrDecoder(). + For short block a sorting algorithm is applied to get the SI in the order + that HCR could assemble the qsc's as if it is a long block. +----------------------------------------------------------------------------------------------- + return: error log +-------------------------------------------------------------------------------------------- */ + +UINT HcrInit(H_HCR_INFO pHcr, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + const SamplingRateInfo *pSamplingRateInfo, + HANDLE_FDK_BITSTREAM bs) +{ + CIcsInfo *pIcsInfo = &pAacDecoderChannelInfo->icsInfo; + SHORT *pNumLinesInSec; + UCHAR *pCodeBk; + SHORT numSection; + SCHAR cb; + int numLine; + int i; + + pHcr->decInOut.lengthOfReorderedSpectralData = pAacDecoderChannelInfo->pDynData->specificTo.aac.lenOfReorderedSpectralData; + pHcr->decInOut.lengthOfLongestCodeword = pAacDecoderChannelInfo->pDynData->specificTo.aac.lenOfLongestCodeword; + pHcr->decInOut.pQuantizedSpectralCoefficientsBase = pAacDecoderChannelInfo->pSpectralCoefficient; + pHcr->decInOut.quantizedSpectralCoefficientsIdx = 0; + pHcr->decInOut.pCodebook = pAacDecoderChannelInfo->pDynData->specificTo.aac.aCodeBooks4Hcr; + pHcr->decInOut.pNumLineInSect = pAacDecoderChannelInfo->pDynData->specificTo.aac.aNumLineInSec4Hcr; + pHcr->decInOut.numSection = pAacDecoderChannelInfo->pDynData->specificTo.aac.numberSection; + pHcr->decInOut.errorLog = 0; + pHcr->nonPcwSideinfo.pResultBase = SPEC_LONG(pAacDecoderChannelInfo->pSpectralCoefficient); + + FDKsyncCache(bs); + pHcr->decInOut.bitstreamIndex = FDKgetBitCnt(bs); + + if (!IsLongBlock(&pAacDecoderChannelInfo->icsInfo)) /* short block */ + { + SHORT band; + SHORT maxBand; + SCHAR group; + SCHAR winGroupLen; + SCHAR window; + SCHAR numUnitInBand; + SCHAR cntUnitInBand; + SCHAR groupWin; + SCHAR cb_prev; + + UCHAR *pCodeBook; + const SHORT *BandOffsets; + SCHAR numOfGroups; + + + pCodeBook = pAacDecoderChannelInfo->pDynData->aCodeBook; /* in */ + pNumLinesInSec = pHcr->decInOut.pNumLineInSect; /* out */ + pCodeBk = pHcr->decInOut.pCodebook; /* out */ + BandOffsets = GetScaleFactorBandOffsets(pIcsInfo, pSamplingRateInfo); /* aux */ + numOfGroups = GetWindowGroups(pIcsInfo); + + numLine = 0; + numSection = 0; + cb = pCodeBook[0]; + cb_prev = pCodeBook[0]; + + /* convert HCR-sideinfo into a unitwise manner: When the cb changes, a new section starts */ + + *pCodeBk++ = cb_prev; + + maxBand = GetScaleFactorBandsTransmitted(&pAacDecoderChannelInfo->icsInfo); + for (band = 0; band < maxBand; band++) { /* from low to high sfbs i.e. from low to high frequencies */ + numUnitInBand = ((BandOffsets[band+1] - BandOffsets[band]) >> FOUR_LOG_DIV_TWO_LOG); /* get the number of units in current sfb */ + for (cntUnitInBand = numUnitInBand; cntUnitInBand != 0; cntUnitInBand-- ) { /* for every unit in the band */ + for (window = 0, group = 0; group < numOfGroups; group++) { + winGroupLen = GetWindowGroupLength(&pAacDecoderChannelInfo->icsInfo,group); + for (groupWin = winGroupLen; groupWin != 0; groupWin--, window++) { + cb = pCodeBook[group * 16 + band]; + if (cb != cb_prev) { +#if CHECK_VALID_HCR_INPUT /* short-block 1 of 2 */ + errDetectorInHcrSideinfoShrt(cb,numLine,&pHcr->decInOut.errorLog ); + if (pHcr->decInOut.errorLog != 0 ) { + return ( pHcr->decInOut.errorLog ); + } +#endif + *pCodeBk++ = cb; + *pNumLinesInSec++ = numLine; + numSection++; + + cb_prev = cb; + numLine = LINES_PER_UNIT; + } + else { + numLine += LINES_PER_UNIT; + } + } + } + } + } + + numSection++; + +#if CHECK_VALID_HCR_INPUT /* short-block 2 of 2 */ + errDetectorInHcrSideinfoShrt(cb,numLine,&pHcr->decInOut.errorLog ); + if ( numSection <= 0 || numSection > 1024/2 ) { + pHcr->decInOut.errorLog |= NUM_SECT_OUT_OF_RANGE_SHORT_BLOCK; + } + errDetectorInHcrLengths(pHcr->decInOut.lengthOfLongestCodeword, + pHcr->decInOut.lengthOfReorderedSpectralData, + &pHcr->decInOut.errorLog); + if (pHcr->decInOut.errorLog != 0 ) { + return ( pHcr->decInOut.errorLog ); + } +#endif + + *pCodeBk = cb; + *pNumLinesInSec = numLine; + pHcr->decInOut.numSection = numSection; + + } else /* end short block prepare SI */ + { /* long block */ +#if CHECK_VALID_HCR_INPUT /* long-block 1 of 1 */ + errDetectorInHcrLengths(pHcr->decInOut.lengthOfLongestCodeword, + pHcr->decInOut.lengthOfReorderedSpectralData, + &pHcr->decInOut.errorLog); + numSection = pHcr->decInOut.numSection; + pNumLinesInSec = pHcr->decInOut.pNumLineInSect; + pCodeBk = pHcr->decInOut.pCodebook; + if ( numSection <= 0 || numSection > 64 ) { + pHcr->decInOut.errorLog |= NUM_SECT_OUT_OF_RANGE_LONG_BLOCK; + numSection = 0; + } + + for ( i = numSection; i != 0; i-- ) + { + cb = *pCodeBk++; + + if ( cb < ZERO_HCB || cb >= MAX_CB_CHECK || cb == BOOKSCL ) { + pHcr->decInOut.errorLog |= CB_OUT_OF_RANGE_LONG_BLOCK; + } + + numLine = *pNumLinesInSec++; + /* FDK_ASSERT(numLine > 0); */ + + if ( (numLine <= 0) || (numLine > 1024) ) { + pHcr->decInOut.errorLog |= LINE_IN_SECT_OUT_OF_RANGE_LONG_BLOCK; + } + } + if (pHcr->decInOut.errorLog != 0 ) { + return ( pHcr->decInOut.errorLog ); + } +#endif /* CHECK_VALID_HCR_INPUT */ + } + + pCodeBk = pHcr->decInOut.pCodebook; + for ( i = 0; i < numSection; i++ ) { + if ( + (*pCodeBk == NOISE_HCB) || + (*pCodeBk == INTENSITY_HCB2) || + (*pCodeBk == INTENSITY_HCB)) + { + *pCodeBk = 0; + } + pCodeBk++; + } + + /* HCR-sideinfo-input is complete and seems to be valid */ + + + + return ( pHcr->decInOut.errorLog ); +} + + + + +#if USE_HCR_DUMMY + +/*--------------------------------------------------------------------------------------------- + + description: This HCR - dummy - function writes only a dirac-sequence in output buffer + +-------------------------------------------------------------------------------------------- */ +UINT HcrDecoder(H_HCR_INFO pHcr, + const CAacDecoderChannelInfo *pAacDecoderChannelInfo, + HANDLE_FDK_BITSTREAM bs) +{ + for (SHORT i=0; i < 1024; i++ ) { + pHcr->decInOut.pQuantizedSpectralCoefficients->Long[i] = FL2FXCONST_DBL(0.0f); + if ( i % 30 == 0) { + pHcr->decInOut.pQuantizedSpectralCoefficients->Long[i] = (FIXP_DBL)HCR_DIRAC; + } + } + return 0; +} + +#else /* USE_HCR_DUMMY */ + +/*--------------------------------------------------------------------------------------------- + description: This function decodes the codewords of the spectral coefficients from the + bitstream according to the HCR algorithm and stores the quantized spectral + coefficients in correct order in the output buffer. +-------------------------------------------------------------------------------------------- */ + +UINT HcrDecoder(H_HCR_INFO pHcr, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + const SamplingRateInfo *pSamplingRateInfo, + HANDLE_FDK_BITSTREAM bs) +{ + int pTmp1, pTmp2, pTmp3, pTmp4; +#if DETECT_TOO_LONG_CW_READS + int pTmp5; +#endif + + INT bitCntOffst; + UINT saveBitCnt = FDKgetBitCnt(bs); /* save bitstream position */ + + HcrCalcNumCodeword(pHcr); + + HcrSortCodebookAndNumCodewordInSection(pHcr); + + HcrPrepareSegmentationGrid(pHcr); + + HcrExtendedSectionInfo(pHcr); + + if (( pHcr->decInOut.errorLog & HCR_FATAL_PCW_ERROR_MASK ) != 0 ) { + return ( pHcr->decInOut.errorLog ); /* sideinfo is massively corrupt, return from HCR without having decoded anything */ + } + + DeriveNumberOfExtendedSortedSectionsInSets(pHcr->segmentInfo.numSegment, + pHcr->sectionInfo.pNumExtendedSortedCodewordInSection, + pHcr->sectionInfo.numExtendedSortedCodewordInSectionIdx, + pHcr->sectionInfo.pNumExtendedSortedSectionsInSets, + pHcr->sectionInfo.numExtendedSortedSectionsInSetsIdx); + + /* store */ + pTmp1 = pHcr->sectionInfo.numExtendedSortedCodewordInSectionIdx; + pTmp2 = pHcr->sectionInfo.extendedSortedCodebookIdx; + pTmp3 = pHcr->sectionInfo.numExtendedSortedSectionsInSetsIdx; + pTmp4 = pHcr->decInOut.quantizedSpectralCoefficientsIdx; +#if DETECT_TOO_LONG_CW_READS + pTmp5 = pHcr->sectionInfo.maxLenOfCbInExtSrtSecIdx; +#endif + + /* ------- decode meaningful PCWs ------ */ + DecodePCWs(bs, pHcr); + + if (( pHcr->decInOut.errorLog & HCR_FATAL_PCW_ERROR_MASK ) == 0 ) { + /* ------ decode the non-PCWs -------- */ + DecodeNonPCWs(bs, pHcr); + } + + +#if CHECK_SEGMENTATION_FINAL + errDetectWithinSegmentationFinal(pHcr); +#endif + + /* restore */ + pHcr->sectionInfo.numExtendedSortedCodewordInSectionIdx = pTmp1; + pHcr->sectionInfo.extendedSortedCodebookIdx = pTmp2; + pHcr->sectionInfo.numExtendedSortedSectionsInSetsIdx = pTmp3; + pHcr->decInOut.quantizedSpectralCoefficientsIdx = pTmp4; +#if DETECT_TOO_LONG_CW_READS + pHcr->sectionInfo.maxLenOfCbInExtSrtSecIdx = pTmp5; +#endif + + HcrReorderQuantizedSpectralCoefficients(pHcr, pAacDecoderChannelInfo, pSamplingRateInfo); + + /* restore bitstream position */ + bitCntOffst = saveBitCnt - FDKgetBitCnt(bs); + if( bitCntOffst ) { + FDKpushBiDirectional(bs, bitCntOffst); + } + + return ( pHcr->decInOut.errorLog ); +} + + +#endif /* USE_HCR_DUMMY */ + + + + +/*--------------------------------------------------------------------------------------------- + description: This function reorders the quantized spectral coefficients sectionwise for + long- and short-blocks and compares to the LAV (Largest Absolute Value of + the current codebook) -- a counter is incremented if there is an error + detected. + Additional for short-blocks a unit-based-deinterleaving is applied. + Moreover (for short blocks) the scaling is derived (compare plain huffman + decoder). +-------------------------------------------------------------------------------------------- */ + +static void HcrReorderQuantizedSpectralCoefficients( + H_HCR_INFO pHcr, CAacDecoderChannelInfo *pAacDecoderChannelInfo, + const SamplingRateInfo *pSamplingRateInfo + ) +{ + INT qsc; + UINT abs_qsc; + UINT i,j; + USHORT numSpectralValuesInSection; + FIXP_DBL *pTeVa; + USHORT lavErrorCnt = 0; + + UINT numSection = pHcr->decInOut.numSection; + SPECTRAL_PTR pQuantizedSpectralCoefficientsBase = pHcr->decInOut.pQuantizedSpectralCoefficientsBase; + FIXP_DBL *pQuantizedSpectralCoefficients = SPEC_LONG(pHcr->decInOut.pQuantizedSpectralCoefficientsBase); + const UCHAR *pCbDimShift = pHcr->tableInfo.pCbDimShift; + const USHORT *pLargestAbsVal = pHcr->tableInfo.pLargestAbsVal; + UCHAR *pSortedCodebook = pHcr->sectionInfo.pSortedCodebook; + USHORT *pNumSortedCodewordInSection = pHcr->sectionInfo.pNumSortedCodewordInSection; + USHORT *pReorderOffset = pHcr->sectionInfo.pReorderOffset; + FIXP_DBL *pTempValues = pHcr->segmentInfo.pTempValues; + FIXP_DBL *pBak = pHcr->segmentInfo.pTempValues; + + FDKmemclear(pTempValues,1024*sizeof(FIXP_DBL)); + + /* long and short: check if decoded huffman-values (quantized spectral coefficients) are within range */ + for ( i=numSection; i != 0; i-- ) { + numSpectralValuesInSection = *pNumSortedCodewordInSection++ << pCbDimShift[*pSortedCodebook]; + pTeVa = &pTempValues[*pReorderOffset++]; + for( j = numSpectralValuesInSection; j != 0; j-- ) { + qsc = *pQuantizedSpectralCoefficients++; + abs_qsc = FDKabs(qsc); +#if VALID_LAV_ERROR_TRIGGER + if ( abs_qsc <= pLargestAbsVal[*pSortedCodebook] ) { + *pTeVa++ = (FIXP_DBL)qsc; /* the qsc value is within range */ + } + else { /* line is too high .. */ + if ( abs_qsc == Q_VALUE_INVALID ) { /* .. because of previous marking --> dont set LAV flag (would be confusing), just copy out the already marked value */ + *pTeVa++ = (FIXP_DBL) qsc; + } + else { /* .. because a too high value was decoded for this cb --> set LAV flag */ + *pTeVa++ = (FIXP_DBL) Q_VALUE_INVALID; + lavErrorCnt += 1; + } + } +#else + if ( abs_qsc <= pLargestAbsVal[*pSortedCodebook] ) { + *pTeVa++ = qsc; + } + else { + *pTeVa++ = Q_VALUE_INVALID; + lavErrorCnt += 1; + } +#endif + } + pSortedCodebook++; + } + + if (!IsLongBlock(&pAacDecoderChannelInfo->icsInfo)) + { + FIXP_DBL *pOut; + FIXP_DBL locMax; + FIXP_DBL tmp; + SCHAR groupoffset; + SCHAR group; + SCHAR band; + SCHAR groupwin; + SCHAR window; + SCHAR numWinGroup; + SHORT interm; + SCHAR numSfbTransm; + SCHAR winGroupLen; + SHORT index; + INT msb; + INT lsb; + + SHORT *pScaleFacHcr = pAacDecoderChannelInfo->pDynData->aScaleFactor; + SHORT *pSfbSclHcr = pAacDecoderChannelInfo->pDynData->aSfbScale; + const SHORT *BandOffsets = GetScaleFactorBandOffsets(&pAacDecoderChannelInfo->icsInfo, pSamplingRateInfo); + + pBak = pHcr->segmentInfo.pTempValues; + /* deinterleave unitwise for short blocks */ + for ( window = 0; window < (8); window++ ) { + pOut = SPEC(pQuantizedSpectralCoefficientsBase, window, pAacDecoderChannelInfo->granuleLength); + for ( i=0; i < (LINES_PER_UNIT_GROUP); i++ ) { + pTeVa = pBak + (window << FOUR_LOG_DIV_TWO_LOG) + i * 32; /* distance of lines between unit groups has to be constant for every framelength (32)! */ + for ( j=(LINES_PER_UNIT); j != 0; j-- ) { + *pOut++ = *pTeVa++; + } + } + } + + /* short blocks only */ + /* derive global scaling-value for every sfb and every window (as it is done in plain-huffman-decoder at short blocks) */ + groupoffset = 0; + + numWinGroup = GetWindowGroups(&pAacDecoderChannelInfo->icsInfo); + numSfbTransm = GetScaleFactorBandsTransmitted(&pAacDecoderChannelInfo->icsInfo); + + for (group = 0; group < numWinGroup; group++) { + winGroupLen = GetWindowGroupLength(&pAacDecoderChannelInfo->icsInfo,group); + for (band = 0; band < numSfbTransm; band++) { + interm = group * 16 + band; + msb = pScaleFacHcr[interm] >> 2; + lsb = pScaleFacHcr[interm] & 3; + for (groupwin = 0; groupwin < winGroupLen; groupwin++) { + window = groupoffset + groupwin; + pBak = SPEC(pQuantizedSpectralCoefficientsBase, window, pAacDecoderChannelInfo->granuleLength); + locMax = FL2FXCONST_DBL(0.0f); + for (index = BandOffsets[band]; index < BandOffsets[band+1]; index += LINES_PER_UNIT) { + pTeVa = &pBak[index]; + for ( i = LINES_PER_UNIT; i != 0; i --) { + tmp = (*pTeVa < FL2FXCONST_DBL(0.0f))? -*pTeVa++ : *pTeVa++; + locMax = fixMax(tmp,locMax); + } + } + if ( fixp_abs(locMax) > (FIXP_DBL)MAX_QUANTIZED_VALUE ) { + locMax = (FIXP_DBL)MAX_QUANTIZED_VALUE; + } + pSfbSclHcr[window*16+band] = msb - GetScaleFromValue(locMax, lsb); /* save global scale maxima in this sfb */ + } + } + groupoffset += GetWindowGroupLength(&pAacDecoderChannelInfo->icsInfo,group); + } + } else + { + /* copy straight for long-blocks */ + pQuantizedSpectralCoefficients = SPEC_LONG(pQuantizedSpectralCoefficientsBase); + for ( i = 1024; i != 0; i-- ) { + *pQuantizedSpectralCoefficients++ = *pBak++; + } + } + + if ( lavErrorCnt != 0 ) { + pHcr->decInOut.errorLog |= LAV_VIOLATION; + } +} + + +/*--------------------------------------------------------------------------------------------- + description: This function calculates the number of codewords + for each section (numCodewordInSection) and the number of codewords + for all sections (numCodeword). + For zero and intensity codebooks a entry is also done in the variable + numCodewordInSection. It is assumed that the codebook is a two tuples + codebook. This is needed later for the calculation of the base addresses + for the reordering of the quantize spectral coefficients at the end of the + hcr tool. + The variable numCodeword contain the number of codewords which are really + in the bitstream. Zero or intensity codebooks does not increase the + variable numCodewords. +----------------------------------------------------------------------------------------------- + return: - +-------------------------------------------------------------------------------------------- */ + +static void HcrCalcNumCodeword(H_HCR_INFO pHcr) +{ + int hcrSection; + UINT numCodeword; + + UINT numSection = pHcr->decInOut.numSection; + UCHAR *pCodebook = pHcr->decInOut.pCodebook; + SHORT *pNumLineInSection = pHcr->decInOut.pNumLineInSect; + const UCHAR *pCbDimShift = pHcr->tableInfo.pCbDimShift; + USHORT *pNumCodewordInSection = pHcr->sectionInfo.pNumCodewordInSection; + + numCodeword = 0; + for ( hcrSection = numSection; hcrSection != 0; hcrSection-- ) { + *pNumCodewordInSection = *pNumLineInSection++ >> pCbDimShift[*pCodebook]; + if ( *pCodebook != 0 ) { + numCodeword += *pNumCodewordInSection; + } + pNumCodewordInSection++; + pCodebook++; + } + pHcr->sectionInfo.numCodeword = numCodeword; +} + + +/*--------------------------------------------------------------------------------------------- + description: This function calculates the number + of sorted codebooks and sorts the codebooks and the numCodewordInSection + according to the priority. +-------------------------------------------------------------------------------------------- */ + +static void HcrSortCodebookAndNumCodewordInSection(H_HCR_INFO pHcr) +{ + + UINT i,j,k; + UCHAR temp; + UINT counter; + UINT startOffset; + UINT numZeroSection; + UCHAR *pDest; + UINT numSectionDec; + + UINT numSection = pHcr->decInOut.numSection; + UCHAR *pCodebook = pHcr->decInOut.pCodebook; + UCHAR *pSortedCodebook = pHcr->sectionInfo.pSortedCodebook; + USHORT *pNumCodewordInSection = pHcr->sectionInfo.pNumCodewordInSection; + USHORT *pNumSortedCodewordInSection = pHcr->sectionInfo.pNumSortedCodewordInSection; + UCHAR *pCodebookSwitch = pHcr->sectionInfo.pCodebookSwitch; + USHORT *pReorderOffset = pHcr->sectionInfo.pReorderOffset; + const UCHAR *pCbPriority = pHcr->tableInfo.pCbPriority; + const UCHAR *pMinOfCbPair = pHcr->cbPairs.pMinOfCbPair; + const UCHAR *pMaxOfCbPair = pHcr->cbPairs.pMaxOfCbPair; + const UCHAR *pCbDimShift = pHcr->tableInfo.pCbDimShift; + + UINT searchStart = 0; + + /* calculate *pNumSortedSection and store the priorities in array pSortedCdebook */ + pDest = pSortedCodebook; + numZeroSection = 0; + for ( i=numSection; i != 0; i-- ) { + if ( pCbPriority[*pCodebook] == 0 ) { + numZeroSection += 1; + } + *pDest++ = pCbPriority[*pCodebook++]; + } + pHcr->sectionInfo.numSortedSection = numSection - numZeroSection; /* numSortedSection contains no zero or intensity section */ + pCodebook = pHcr->decInOut.pCodebook; + + /* sort priorities of the codebooks in array pSortedCdebook[] */ + numSectionDec = numSection - 1; + if ( numSectionDec > 0 ) { + counter = numSectionDec; + for ( j=numSectionDec; j != 0; j-- ) { + for ( i=0; i < counter; i++ ) { + /* swap priorities */ + if ( pSortedCodebook[i+1] > pSortedCodebook[i] ) { + temp = pSortedCodebook[i]; + pSortedCodebook[i] = pSortedCodebook[i+1]; + pSortedCodebook[i+1] = temp; + } + } + counter -= 1; + } + } + + /* clear codebookSwitch array */ + for ( i = numSection; i != 0; i--) { + *pCodebookSwitch++ = 0; + } + pCodebookSwitch = pHcr->sectionInfo.pCodebookSwitch; + + /* sort sectionCodebooks and numCodwordsInSection and calculate pReorderOffst[j] */ + for ( j = 0; j < numSection; j++ ) { + for ( i = searchStart; i < numSection; i++ ) { + if ( pCodebookSwitch[i] == 0 && ( pMinOfCbPair[pSortedCodebook[j]] == pCodebook[i] || pMaxOfCbPair[pSortedCodebook[j]] == pCodebook[i] )) { + pCodebookSwitch[i] = 1; + pSortedCodebook[j] = pCodebook[i]; /* sort codebook */ + pNumSortedCodewordInSection[j] = pNumCodewordInSection[i]; /* sort NumCodewordInSection */ + + startOffset = 0; + for ( k = 0; k < i; k++ ) { /* make entry in pReorderOffst */ + startOffset += pNumCodewordInSection[k] << pCbDimShift[pCodebook[k]]; + } + pReorderOffset[j] = startOffset; /* offset for reordering the codewords */ + + if(i == searchStart) { + UINT k = i; + while(pCodebookSwitch[k++] == 1) searchStart++; + } + break; + } + } + } +} + + +/*--------------------------------------------------------------------------------------------- + description: This function calculates the segmentation, which includes numSegment, + leftStartOfSegment, rightStartOfSegment and remainingBitsInSegment. + The segmentation could be visualized a as kind of 'overlay-grid' for the + bitstream-block holding the HCR-encoded quantized-spectral-coefficients. +-------------------------------------------------------------------------------------------- */ + +static void HcrPrepareSegmentationGrid(H_HCR_INFO pHcr) +{ + USHORT i,j; + USHORT numSegment = 0; + USHORT segmentStart = 0; + UCHAR segmentWidth; + UCHAR lastSegmentWidth; + UCHAR sortedCodebook; + UCHAR endFlag = 0; + USHORT intermediateResult; + + SCHAR lengthOfLongestCodeword = pHcr->decInOut.lengthOfLongestCodeword; + SHORT lengthOfReorderedSpectralData = pHcr->decInOut.lengthOfReorderedSpectralData; + UINT numSortedSection = pHcr->sectionInfo.numSortedSection; + UCHAR *pSortedCodebook = pHcr->sectionInfo.pSortedCodebook; + USHORT *pNumSortedCodewordInSection = pHcr->sectionInfo.pNumSortedCodewordInSection; + USHORT *pLeftStartOfSegment = pHcr->segmentInfo.pLeftStartOfSegment; + USHORT *pRightStartOfSegment = pHcr->segmentInfo.pRightStartOfSegment; + SCHAR *pRemainingBitsInSegment = pHcr->segmentInfo.pRemainingBitsInSegment; + USHORT bitstreamIndex = pHcr->decInOut.bitstreamIndex; + const UCHAR *pMaxCwLength = pHcr->tableInfo.pMaxCwLength; + + for ( i=numSortedSection; i != 0; i-- ) { + sortedCodebook = *pSortedCodebook++; + segmentWidth = FDKmin(pMaxCwLength[sortedCodebook],lengthOfLongestCodeword); + + for ( j = *pNumSortedCodewordInSection; j != 0 ; j-- ) { + /* width allows a new segment */ + intermediateResult = bitstreamIndex + segmentStart; + if ( (segmentStart + segmentWidth) <= lengthOfReorderedSpectralData ) { + /* store segment start, segment length and increment the number of segments */ + *pLeftStartOfSegment++ = intermediateResult; + *pRightStartOfSegment++ = intermediateResult + segmentWidth - 1; + *pRemainingBitsInSegment++ = segmentWidth; + segmentStart += segmentWidth; + numSegment += 1; + } + /* width does not allow a new segment */ + else { + /* correct the last segment length */ + pLeftStartOfSegment--; + pRightStartOfSegment--; + pRemainingBitsInSegment--; + segmentStart = *pLeftStartOfSegment - bitstreamIndex; + + lastSegmentWidth = lengthOfReorderedSpectralData - segmentStart; + *pRemainingBitsInSegment = lastSegmentWidth; + *pRightStartOfSegment = bitstreamIndex + segmentStart + lastSegmentWidth - 1; + endFlag = 1; + break; + } + } + pNumSortedCodewordInSection++; + if (endFlag != 0) { + break; + } + } + pHcr->segmentInfo.numSegment = numSegment; + +} + + +/*--------------------------------------------------------------------------------------------- + description: This function adapts the sorted section boundaries to the boundaries of + segmentation. If the section lengths does not fit completely into the + current segment, the section is spitted into two so called 'extended + sections'. The extended-section-info (pNumExtendedSortedCodewordInSectin + and pExtendedSortedCodebook) is updated in this case. + +-------------------------------------------------------------------------------------------- */ + +static void HcrExtendedSectionInfo(H_HCR_INFO pHcr) +{ + UINT srtSecCnt = 0; /* counter for sorted sections */ + UINT xSrtScCnt = 0; /* counter for extended sorted sections */ + UINT remainNumCwInSortSec; + UINT inSegmentRemainNumCW; + + UINT numSortedSection = pHcr->sectionInfo.numSortedSection; + UCHAR *pSortedCodebook = pHcr->sectionInfo.pSortedCodebook; + USHORT *pNumSortedCodewordInSection = pHcr->sectionInfo.pNumSortedCodewordInSection; + UCHAR *pExtendedSortedCoBo = pHcr->sectionInfo.pExtendedSortedCodebook; + USHORT *pNumExtSortCwInSect = pHcr->sectionInfo.pNumExtendedSortedCodewordInSection; + UINT numSegment = pHcr->segmentInfo.numSegment; +#if DETECT_TOO_LONG_CW_READS + UCHAR *pMaxLenOfCbInExtSrtSec = pHcr->sectionInfo.pMaxLenOfCbInExtSrtSec; + SCHAR lengthOfLongestCodeword = pHcr->decInOut.lengthOfLongestCodeword; + const UCHAR *pMaxCwLength = pHcr->tableInfo.pMaxCwLength; +#endif + + remainNumCwInSortSec = pNumSortedCodewordInSection[srtSecCnt]; + inSegmentRemainNumCW = numSegment; + + while (srtSecCnt < numSortedSection) { + if (inSegmentRemainNumCW < remainNumCwInSortSec) { + + pNumExtSortCwInSect[xSrtScCnt] = inSegmentRemainNumCW; + pExtendedSortedCoBo[xSrtScCnt] = pSortedCodebook[srtSecCnt]; + + remainNumCwInSortSec -= inSegmentRemainNumCW; + inSegmentRemainNumCW = numSegment; + /* data of a sorted section was not integrated in extended sorted section */ + } + else if (inSegmentRemainNumCW == remainNumCwInSortSec) { + pNumExtSortCwInSect[xSrtScCnt] = inSegmentRemainNumCW; + pExtendedSortedCoBo[xSrtScCnt] = pSortedCodebook[srtSecCnt]; + + srtSecCnt++; + remainNumCwInSortSec = pNumSortedCodewordInSection[srtSecCnt]; + inSegmentRemainNumCW = numSegment; + /* data of a sorted section was integrated in extended sorted section */ + } + else { /* inSegmentRemainNumCW > remainNumCwInSortSec */ + pNumExtSortCwInSect[xSrtScCnt] = remainNumCwInSortSec; + pExtendedSortedCoBo[xSrtScCnt] = pSortedCodebook[srtSecCnt]; + + + inSegmentRemainNumCW -= remainNumCwInSortSec; + srtSecCnt++; + remainNumCwInSortSec = pNumSortedCodewordInSection[srtSecCnt]; + /* data of a sorted section was integrated in extended sorted section */ + } +#if DETECT_TOO_LONG_CW_READS + pMaxLenOfCbInExtSrtSec[xSrtScCnt] = FDKmin(pMaxCwLength[pExtendedSortedCoBo[xSrtScCnt]],lengthOfLongestCodeword); +#endif + + + + xSrtScCnt += 1; + + if ( xSrtScCnt >= (MAX_SFB_HCR + MAX_HCR_SETS) ) { + pHcr->decInOut.errorLog |= EXTENDED_SORTED_COUNTER_OVERFLOW; + return; + } + + } + pNumExtSortCwInSect[xSrtScCnt] = 0; + +} + + +/*--------------------------------------------------------------------------------------------- + description: This function calculates the number of extended sorted sections which + belong to the sets. Each set from set 0 (one and only set for the PCWs) + till to the last set gets a entry in the array to which + 'pNumExtendedSortedSectinsInSets' points to. + + Calculation: The entrys in pNumExtendedSortedCodewordInSectin are added + untill the value numSegment is reached. Then the sum_variable is cleared + and the calculation starts from the beginning. As much extended sorted + Sections are summed up to reach the value numSegment, as much is the + current entry in *pNumExtendedSortedCodewordInSectin. +-------------------------------------------------------------------------------------------- */ +static void DeriveNumberOfExtendedSortedSectionsInSets(UINT numSegment, + USHORT *pNumExtendedSortedCodewordInSection, + int numExtendedSortedCodewordInSectionIdx, + USHORT *pNumExtendedSortedSectionsInSets, + int numExtendedSortedSectionsInSetsIdx) +{ + USHORT counter = 0; + UINT cwSum = 0; + USHORT *pNumExSortCwInSec = pNumExtendedSortedCodewordInSection; + USHORT *pNumExSortSecInSets = pNumExtendedSortedSectionsInSets; + + while (pNumExSortCwInSec[numExtendedSortedCodewordInSectionIdx] != 0) + { + cwSum += pNumExSortCwInSec[numExtendedSortedCodewordInSectionIdx]; + numExtendedSortedCodewordInSectionIdx++; + if (numExtendedSortedCodewordInSectionIdx >= (MAX_SFB_HCR+MAX_HCR_SETS)) { + return; + } + if (cwSum > numSegment) { + return; + } + counter++; + if (counter > 1024/4) { + return; + } + if ( cwSum == numSegment ) { + pNumExSortSecInSets[numExtendedSortedSectionsInSetsIdx] = counter; + numExtendedSortedSectionsInSetsIdx++; + if (numExtendedSortedSectionsInSetsIdx >= MAX_HCR_SETS) { + return; + } + counter = 0; + cwSum = 0; + } + } + pNumExSortSecInSets[numExtendedSortedSectionsInSetsIdx] = counter; /* save last entry for the last - probably shorter - set */ +} + + +/*--------------------------------------------------------------------------------------------- + description: This function decodes all priority codewords (PCWs) in a spectrum (within + set 0). The calculation of the PCWs is managed in two loops. The + loopcounter of the outer loop is set to the first value pointer + pNumExtendedSortedSectionsInSets points to. This value represents the + number of extended sorted sections within set 0. + The loopcounter of the inner loop is set to the first value pointer + pNumExtendedSortedCodewordInSectin points to. The value represents the + number of extended sorted codewords in sections (the original sections have + been splitted to go along with the borders of the sets). + Each time the number of the extended sorted codewords in sections are de- + coded, the pointer 'pNumExtendedSortedCodewordInSectin' is incremented by + one. +-------------------------------------------------------------------------------------------- */ +static void DecodePCWs(HANDLE_FDK_BITSTREAM bs, H_HCR_INFO pHcr) +{ + UINT i; + USHORT extSortSec; + USHORT curExtSortCwInSec; + UCHAR codebook; + UCHAR dimension; + const UINT *pCurrentTree; + const SCHAR *pQuantValBase; + const SCHAR *pQuantVal; + + USHORT *pNumExtendedSortedCodewordInSection = pHcr->sectionInfo.pNumExtendedSortedCodewordInSection; + int numExtendedSortedCodewordInSectionIdx = pHcr->sectionInfo.numExtendedSortedCodewordInSectionIdx; + UCHAR *pExtendedSortedCodebook = pHcr->sectionInfo.pExtendedSortedCodebook; + int extendedSortedCodebookIdx = pHcr->sectionInfo.extendedSortedCodebookIdx; + USHORT *pNumExtendedSortedSectionsInSets = pHcr->sectionInfo.pNumExtendedSortedSectionsInSets; + int numExtendedSortedSectionsInSetsIdx = pHcr->sectionInfo.numExtendedSortedSectionsInSetsIdx; + FIXP_DBL *pQuantizedSpectralCoefficients = SPEC_LONG(pHcr->decInOut.pQuantizedSpectralCoefficientsBase); + int quantizedSpectralCoefficientsIdx = pHcr->decInOut.quantizedSpectralCoefficientsIdx; + USHORT *pLeftStartOfSegment = pHcr->segmentInfo.pLeftStartOfSegment; + SCHAR *pRemainingBitsInSegment = pHcr->segmentInfo.pRemainingBitsInSegment; +#if DETECT_TOO_LONG_CW_READS + UCHAR *pMaxLenOfCbInExtSrtSec = pHcr->sectionInfo.pMaxLenOfCbInExtSrtSec; + int maxLenOfCbInExtSrtSecIdx = pHcr->sectionInfo.maxLenOfCbInExtSrtSecIdx; + UCHAR maxAllowedCwLen; + int numDecodedBits; +#endif + const UCHAR *pCbDimension = pHcr->tableInfo.pCbDimension; + const UCHAR *pCbSign = pHcr->tableInfo.pCbSign; + + /* clear result array */ + //pQSC = &pQuantizedSpectralCoefficients[quantizedSpectralCoefficientsIdx]; + //pQSC = *pQuantizedSpectralCoefficients; + + FDKmemclear(pQuantizedSpectralCoefficients+quantizedSpectralCoefficientsIdx,1024*sizeof(FIXP_DBL)); + + /* decode all PCWs in the extended sorted section(s) belonging to set 0 */ + for ( extSortSec = pNumExtendedSortedSectionsInSets[numExtendedSortedSectionsInSetsIdx]; extSortSec != 0; extSortSec-- ) { + + codebook = pExtendedSortedCodebook[extendedSortedCodebookIdx]; /* get codebook for this extended sorted section and increment ptr to cb of next ext. sort sec */ + extendedSortedCodebookIdx++; + if (extendedSortedCodebookIdx >= (MAX_SFB_HCR+MAX_HCR_SETS)) { + return; + } + dimension = pCbDimension[codebook]; /* get dimension of codebook of this extended sort. sec. */ + pCurrentTree = aHuffTable [codebook]; /* convert codebook to pointer to QSCs */ + pQuantValBase = aQuantTable [codebook]; /* convert codebook to index to table of QSCs */ +#if DETECT_TOO_LONG_CW_READS + maxAllowedCwLen = pMaxLenOfCbInExtSrtSec[maxLenOfCbInExtSrtSecIdx]; + maxLenOfCbInExtSrtSecIdx++; + if (maxLenOfCbInExtSrtSecIdx >= (MAX_SFB_HCR+MAX_HCR_SETS)) { + return; + } +#endif + + /* switch for decoding with different codebooks: */ + if ( pCbSign[codebook] == 0 ) { /* no sign bits follow after the codeword-body */ + /* PCW_BodyONLY */ + /*==============*/ + + for ( curExtSortCwInSec = pNumExtendedSortedCodewordInSection[numExtendedSortedCodewordInSectionIdx] ; curExtSortCwInSec != 0; curExtSortCwInSec--) { + numDecodedBits = 0; + + /* decode PCW_BODY */ + pQuantVal = DecodePCW_Body(bs, + pCurrentTree, + pQuantValBase, + pLeftStartOfSegment, + pRemainingBitsInSegment, + &numDecodedBits + ); + + /* result is written out here because NO sign bits follow the body */ + for( i=dimension; i != 0 ; i-- ) { + pQuantizedSpectralCoefficients[quantizedSpectralCoefficientsIdx] = (FIXP_DBL) *pQuantVal++; /* write quant. spec. coef. into spectrum; sign is already valid */ + quantizedSpectralCoefficientsIdx++; + if (quantizedSpectralCoefficientsIdx >= 1024) { + return; + } + } + + /* one more PCW should be decoded */ + +#if DETECT_TOO_LONG_CW_READS + if ( maxAllowedCwLen < (numDecodedBits + ERROR_PCW_BODY_ONLY_TOO_LONG) ) { + pHcr->decInOut.errorLog |= TOO_MANY_PCW_BODY_BITS_DECODED; + } +#endif + +#if CHECK_SEGMENTATION_IMMEDIATELY + if (1 == errDetectPcwSegmentation(*pRemainingBitsInSegment-ERROR_PCW_BODY,pHcr,PCW_BODY,pQuantizedSpectralCoefficients+quantizedSpectralCoefficientsIdx-dimension,dimension)) { + return; + } +#endif + pLeftStartOfSegment++; /* update pointer for decoding the next PCW */ + pRemainingBitsInSegment++; /* update pointer for decoding the next PCW */ + } + } + else if (( pCbSign[codebook] == 1 ) && ( codebook < 11 )) { /* possibly there follow 1,2,3 or 4 sign bits after the codeword-body */ + /* PCW_Body and PCW_Sign */ + /*=======================*/ + + for ( curExtSortCwInSec = pNumExtendedSortedCodewordInSection[numExtendedSortedCodewordInSectionIdx] ; curExtSortCwInSec != 0; curExtSortCwInSec--) + { + int err; + numDecodedBits = 0; + + pQuantVal = DecodePCW_Body(bs, + pCurrentTree, + pQuantValBase, + pLeftStartOfSegment, + pRemainingBitsInSegment, + &numDecodedBits + ); + + err = DecodePCW_Sign( bs, + dimension, + pQuantVal, + pQuantizedSpectralCoefficients, + &quantizedSpectralCoefficientsIdx, + pLeftStartOfSegment, + pRemainingBitsInSegment, + &numDecodedBits + ); + if (err != 0) { + return; + } + /* one more PCW should be decoded */ + +#if DETECT_TOO_LONG_CW_READS + if ( maxAllowedCwLen < (numDecodedBits + ERROR_PCW_BODY_SIGN_TOO_LONG) ) { + pHcr->decInOut.errorLog |= TOO_MANY_PCW_BODY_SIGN_BITS_DECODED; + } +#endif + +#if CHECK_SEGMENTATION_IMMEDIATELY + if (1 == errDetectPcwSegmentation(*pRemainingBitsInSegment-ERROR_PCW_BODY_SIGN,pHcr,PCW_BODY_SIGN, pQuantizedSpectralCoefficients+quantizedSpectralCoefficientsIdx-dimension,dimension)) { + return; + } +#endif + pLeftStartOfSegment++; + pRemainingBitsInSegment++; + } + } + else if (( pCbSign[codebook] == 1 ) && ( codebook >= 11 )) { /* possibly there follow some sign bits and maybe one or two escape sequences after the cw-body */ + /* PCW_Body, PCW_Sign and maybe PCW_Escape */ + /*=========================================*/ + + for ( curExtSortCwInSec = pNumExtendedSortedCodewordInSection[numExtendedSortedCodewordInSectionIdx] ; curExtSortCwInSec != 0; curExtSortCwInSec--) + { + int err; + numDecodedBits = 0; + + /* decode PCW_BODY */ + pQuantVal = DecodePCW_Body(bs, + pCurrentTree, + pQuantValBase, + pLeftStartOfSegment, + pRemainingBitsInSegment, + &numDecodedBits + ); + + err = DecodePCW_Sign( bs, + dimension, + pQuantVal, + pQuantizedSpectralCoefficients, + &quantizedSpectralCoefficientsIdx, + pLeftStartOfSegment, + pRemainingBitsInSegment, + &numDecodedBits + ); + if (err != 0) { + return; + } + + /* decode PCW_ESCAPE if present */ + quantizedSpectralCoefficientsIdx -= DIMENSION_OF_ESCAPE_CODEBOOK; + + if ( fixp_abs(pQuantizedSpectralCoefficients[quantizedSpectralCoefficientsIdx]) == (FIXP_DBL)ESCAPE_VALUE ) { + pQuantizedSpectralCoefficients[quantizedSpectralCoefficientsIdx] = (FIXP_DBL) DecodeEscapeSequence( bs, + pQuantizedSpectralCoefficients[quantizedSpectralCoefficientsIdx], + pLeftStartOfSegment, + pRemainingBitsInSegment, + &numDecodedBits + ); + } + quantizedSpectralCoefficientsIdx++; + if (quantizedSpectralCoefficientsIdx >= 1024) { + return; + } + + if ( fixp_abs(pQuantizedSpectralCoefficients[quantizedSpectralCoefficientsIdx]) == (FIXP_DBL)ESCAPE_VALUE ) { + pQuantizedSpectralCoefficients[quantizedSpectralCoefficientsIdx] = (FIXP_DBL) DecodeEscapeSequence( bs, + pQuantizedSpectralCoefficients[quantizedSpectralCoefficientsIdx], + pLeftStartOfSegment, + pRemainingBitsInSegment, + &numDecodedBits + ); + } + quantizedSpectralCoefficientsIdx++; + if (quantizedSpectralCoefficientsIdx >= 1024) { + return; + } + + /* one more PCW should be decoded */ + +#if DETECT_TOO_LONG_CW_READS + if ( maxAllowedCwLen < (numDecodedBits + ERROR_PCW_BODY_SIGN_ESC_TOO_LONG) ) { + pHcr->decInOut.errorLog |= TOO_MANY_PCW_BODY_SIGN_ESC_BITS_DECODED; + } +#endif + +#if CHECK_SEGMENTATION_IMMEDIATELY + if (1 == errDetectPcwSegmentation(*pRemainingBitsInSegment-ERROR_PCW_BODY_SIGN_ESC,pHcr,PCW_BODY_SIGN_ESC,pQuantizedSpectralCoefficients+quantizedSpectralCoefficientsIdx-DIMENSION_OF_ESCAPE_CODEBOOK,DIMENSION_OF_ESCAPE_CODEBOOK)) { + return; + } +#endif + pLeftStartOfSegment++; + pRemainingBitsInSegment++; + } + } + + /* all PCWs belonging to this extended section should be decoded */ + numExtendedSortedCodewordInSectionIdx++; + if (numExtendedSortedCodewordInSectionIdx >= MAX_SFB_HCR+MAX_HCR_SETS) { + return; + } + } + /* all PCWs should be decoded */ + + numExtendedSortedSectionsInSetsIdx++; + if (numExtendedSortedSectionsInSetsIdx >= MAX_HCR_SETS) { + return; + } + + /* Write back indexes into structure */ + pHcr->sectionInfo.numExtendedSortedCodewordInSectionIdx = numExtendedSortedCodewordInSectionIdx; + pHcr->sectionInfo.extendedSortedCodebookIdx = extendedSortedCodebookIdx; + pHcr->sectionInfo.numExtendedSortedSectionsInSetsIdx = numExtendedSortedSectionsInSetsIdx; + pHcr->decInOut.quantizedSpectralCoefficientsIdx = quantizedSpectralCoefficientsIdx; + pHcr->sectionInfo.maxLenOfCbInExtSrtSecIdx = maxLenOfCbInExtSrtSecIdx; +} + +#if CHECK_SEGMENTATION_IMMEDIATELY +/*--------------------------------------------------------------------------------------------- + description: This function checks immediately after every decoded PCW, whether out of + the current segment too many bits have been read or not. If an error occurrs, + probably the sideinfo or the HCR-bitstream block holding the huffman + encoded quantized spectral coefficients is distorted. In this case the two + or four quantized spectral coefficients belonging to the current codeword + are marked (for being detected by concealment later). +-------------------------------------------------------------------------------------------- */ +static UCHAR errDetectPcwSegmentation(SCHAR remainingBitsInSegment, + H_HCR_INFO pHcr, + PCW_TYPE kind, + FIXP_DBL *qsc_base_of_cw, + UCHAR dimension) +{ + SCHAR i; + if ( remainingBitsInSegment < 0 ) { + /* log the error */ + switch (kind) { + case PCW_BODY: + pHcr->decInOut.errorLog |= SEGMENT_OVERRIDE_ERR_PCW_BODY; + break; + case PCW_BODY_SIGN: + pHcr->decInOut.errorLog |= SEGMENT_OVERRIDE_ERR_PCW_BODY_SIGN; + break; + case PCW_BODY_SIGN_ESC: + pHcr->decInOut.errorLog |= SEGMENT_OVERRIDE_ERR_PCW_BODY_SIGN_ESC; + break; + } + /* mark the erred lines */ + for ( i = dimension; i != 0; i-- ) { + *qsc_base_of_cw++ = (FIXP_DBL) Q_VALUE_INVALID; + } + return 1; + } + return 0; +} +#endif + +#if CHECK_SEGMENTATION_FINAL +/*--------------------------------------------------------------------------------------------- + description: This function checks if all segments are empty after decoding. There + are _no lines markded_ as invalid because it could not be traced back + where from the remaining bits are. +-------------------------------------------------------------------------------------------- */ +static void errDetectWithinSegmentationFinal(H_HCR_INFO pHcr) +{ + UCHAR segmentationErrorFlag = 0; + USHORT i; + SCHAR *pRemainingBitsInSegment = pHcr->segmentInfo.pRemainingBitsInSegment; + UINT numSegment = pHcr->segmentInfo.numSegment; + + for ( i=numSegment; i != 0 ; i--) { + if (*pRemainingBitsInSegment++ != 0) { + segmentationErrorFlag = 1; + } + } + if (segmentationErrorFlag == 1) { + pHcr->decInOut.errorLog |= BIT_IN_SEGMENTATION_ERROR; + } +} +#endif + +/*--------------------------------------------------------------------------------------------- + description: This function walks one step within the decoding tree. Which branch is + taken depends on the decoded carryBit input parameter. +-------------------------------------------------------------------------------------------- */ +void CarryBitToBranchValue(UCHAR carryBit, + UINT treeNode, + UINT *branchValue, + UINT *branchNode) +{ + if (carryBit == 0) { + *branchNode = (treeNode & MASK_LEFT) >> LEFT_OFFSET; /* MASK_LEFT: 00FFF000 */ + } + else { + *branchNode = treeNode & MASK_RIGHT; /* MASK_RIGHT: 00000FFF */ + } + + *branchValue = *branchNode & CLR_BIT_10; /* clear bit 10 (if set) */ +} + + +/*--------------------------------------------------------------------------------------------- + description: Decodes the body of a priority codeword (PCW) +----------------------------------------------------------------------------------------------- + return: - return value is pointer to first of two or four quantized spectral + coefficients +-------------------------------------------------------------------------------------------- */ +static const SCHAR *DecodePCW_Body(HANDLE_FDK_BITSTREAM bs, + const UINT *pCurrentTree, + const SCHAR *pQuantValBase, + USHORT *pLeftStartOfSegment, + SCHAR *pRemainingBitsInSegment, + int *pNumDecodedBits + ) +{ + UCHAR carryBit; + UINT branchNode; + UINT treeNode; + UINT branchValue; + const SCHAR *pQuantVal; + + /* decode PCW_BODY */ + treeNode = *pCurrentTree; /* get first node of current tree belonging to current codebook */ + + /* decode whole PCW-codeword-body */ + while (1) { + + carryBit = HcrGetABitFromBitstream(bs, + pLeftStartOfSegment, + pLeftStartOfSegment, /* dummy */ + FROM_LEFT_TO_RIGHT); + *pRemainingBitsInSegment -= 1; + *pNumDecodedBits += 1; + + CarryBitToBranchValue(carryBit, + treeNode, + &branchValue, + &branchNode); + + if ((branchNode & TEST_BIT_10) == TEST_BIT_10) { /* test bit 10 ; if set --> codeword-body is complete */ + break; /* end of branch in tree reached i.e. a whole PCW-Body is decoded */ + } + else { + treeNode = *(pCurrentTree + branchValue); /* update treeNode for further step in decoding tree */ + } + + } + + pQuantVal = pQuantValBase + branchValue; /* update pointer to valid first of 2 or 4 quantized values */ + + return pQuantVal; +} + + +/*--------------------------------------------------------------------------------------------- + description: This function decodes one escape sequence. In case of a escape codebook + and in case of the absolute value of the quantized spectral value == 16, + a escapeSequence is decoded in two steps: + 1. escape prefix + 2. escape word +-------------------------------------------------------------------------------------------- */ + +static INT DecodeEscapeSequence(HANDLE_FDK_BITSTREAM bs, + INT quantSpecCoef, + USHORT *pLeftStartOfSegment, + SCHAR *pRemainingBitsInSegment, + int *pNumDecodedBits + ) +{ + UINT i; + INT sign; + UINT escapeOnesCounter = 0; + UINT carryBit; + INT escape_word = 0; + + /* decode escape prefix */ + while (1) { + carryBit = HcrGetABitFromBitstream(bs, + pLeftStartOfSegment, + pLeftStartOfSegment, /* dummy */ + FROM_LEFT_TO_RIGHT); + *pRemainingBitsInSegment -= 1; + *pNumDecodedBits += 1; + + if (carryBit != 0) { + escapeOnesCounter += 1; + } + else { + escapeOnesCounter += 4; + break; + } + } + + /* decode escape word */ + for( i=escapeOnesCounter; i != 0 ; i-- ) { + carryBit = HcrGetABitFromBitstream(bs, + pLeftStartOfSegment, + pLeftStartOfSegment, /* dummy */ + FROM_LEFT_TO_RIGHT); + *pRemainingBitsInSegment -= 1; + *pNumDecodedBits += 1; + + escape_word <<= 1; + escape_word = escape_word | carryBit; + } + + sign = (quantSpecCoef >= 0) ? 1 : -1; + + quantSpecCoef = sign * (((INT ) 1 << escapeOnesCounter) + escape_word); + + return quantSpecCoef; +} + + +/*--------------------------------------------------------------------------------------------- + description: Decodes the Signbits of a priority codeword (PCW) and writes out the + resulting quantized spectral values into unsorted sections +----------------------------------------------------------------------------------------------- + output: - two or four lines at position in corresponding section (which are not + located at the desired position, i.e. they must be reordered in the last + of eight function of HCR) +----------------------------------------------------------------------------------------------- + return: - updated pQuantSpecCoef pointer (to next empty storage for a line) +-------------------------------------------------------------------------------------------- */ +static int DecodePCW_Sign(HANDLE_FDK_BITSTREAM bs, + UINT codebookDim, + const SCHAR *pQuantVal, + FIXP_DBL *pQuantSpecCoef, + int *quantSpecCoefIdx, + USHORT *pLeftStartOfSegment, + SCHAR *pRemainingBitsInSegment, + int *pNumDecodedBits + ) +{ + UINT i; + UINT carryBit; + INT quantSpecCoef; + + for( i=codebookDim; i != 0 ; i-- ) { + quantSpecCoef = *pQuantVal++; + if (quantSpecCoef != 0) { + carryBit = HcrGetABitFromBitstream(bs, + pLeftStartOfSegment, + pLeftStartOfSegment, /* dummy */ + FROM_LEFT_TO_RIGHT); + *pRemainingBitsInSegment -= 1; + *pNumDecodedBits += 1; + if (*pRemainingBitsInSegment < 0 || *pNumDecodedBits >= (1024>>1)) { + return -1; + } + + /* adapt sign of values according to the decoded sign bit */ + if (carryBit != 0) { + pQuantSpecCoef[*quantSpecCoefIdx] = -(FIXP_DBL)quantSpecCoef; + } + else { + pQuantSpecCoef[*quantSpecCoefIdx] = (FIXP_DBL)quantSpecCoef; + } + } + else { + pQuantSpecCoef[*quantSpecCoefIdx] = FL2FXCONST_DBL(0.0f); + } + *quantSpecCoefIdx += 1 ; + if (*quantSpecCoefIdx >= 1024) { + return -1; + } + } + return 0; +} + + +/*--------------------------------------------------------------------------------------------- + description: Mutes spectral lines which have been marked as erroneous (Q_VALUE_INVALID) +-------------------------------------------------------------------------------------------- */ +void HcrMuteErroneousLines(H_HCR_INFO hHcr) +{ + int c; + FIXP_DBL *RESTRICT pLong = SPEC_LONG(hHcr->decInOut.pQuantizedSpectralCoefficientsBase); + + /* if there is a line with value Q_VALUE_INVALID mute it */ + for (c = 0; c < 1024; c++) { + if (pLong[c] == (FIXP_DBL)Q_VALUE_INVALID) { +#if HCR_LISTEN_TO_MUTED_LINES + pLong[c] = (FIXP_DBL)HCR_DIRAC; /* marking */ +#else + pLong[c] = FL2FXCONST_DBL(0.0f); /* muting */ +#endif + } + } +} + + +/*--------------------------------------------------------------------------------------------- + description: Sets global HCR type +-------------------------------------------------------------------------------------------- */ +void setHcrType(H_HCR_INFO hHcr, MP4_ELEMENT_ID type) +{ + switch (type) { + case ID_SCE: + hHcr->globalHcrType = 0; + break; + case ID_CPE: + hHcr->globalHcrType = 1; + break; + default: + break; + } +} + + +/*--------------------------------------------------------------------------------------------- + description: Gets HCR type from the HCR data structure +----------------------------------------------------------------------------------------------- + return: - global HCR type +-------------------------------------------------------------------------------------------- */ +INT getHcrType(H_HCR_INFO hHcr) +{ + return hHcr->globalHcrType; +} + + + + |