From 0e5af65c467b2423a0b857ae3ad98c91acc1e190 Mon Sep 17 00:00:00 2001 From: "Matthias P. Braendli" Date: Mon, 11 Nov 2019 11:38:02 +0100 Subject: Include patched FDK-AAC in the repository The initial idea was to get the DAB+ patch into upstream, but since that follows the android source releases, there is no place for a custom DAB+ patch there. So instead of having to maintain a patched fdk-aac that has to have the same .so version as the distribution package on which it is installed, we prefer having a separate fdk-aac-dab library to avoid collision. At that point, there's no reason to keep fdk-aac in a separate repository, as odr-audioenc is the only tool that needs DAB+ encoding support. Including it here simplifies installation, and makes it consistent with toolame-dab, also shipped in this repository. DAB+ decoding support (needed by ODR-SourceCompanion, dablin, etisnoop, welle.io and others) can be done using upstream FDK-AAC. --- fdk-aac/libAACdec/src/aacdec_hcrs.cpp | 1551 +++++++++++++++++++++++++++++++++ 1 file changed, 1551 insertions(+) create mode 100644 fdk-aac/libAACdec/src/aacdec_hcrs.cpp (limited to 'fdk-aac/libAACdec/src/aacdec_hcrs.cpp') diff --git a/fdk-aac/libAACdec/src/aacdec_hcrs.cpp b/fdk-aac/libAACdec/src/aacdec_hcrs.cpp new file mode 100644 index 0000000..d2bc867 --- /dev/null +++ b/fdk-aac/libAACdec/src/aacdec_hcrs.cpp @@ -0,0 +1,1551 @@ +/* ----------------------------------------------------------------------------- +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): Robert Weidner (DSP Solutions) + + Description: HCR Decoder: Prepare decoding of non-PCWs, segmentation- and + bitfield-handling, HCR-Statemachine + +*******************************************************************************/ + +#include "aacdec_hcrs.h" + +#include "aacdec_hcr.h" + +#include "aacdec_hcr_bit.h" +#include "aac_rom.h" +#include "aac_ram.h" + +static UINT InitSegmentBitfield(UINT *pNumSegment, + SCHAR *pRemainingBitsInSegment, + UINT *pSegmentBitfield, + UCHAR *pNumWordForBitfield, + USHORT *pNumBitValidInLastWord); + +static void InitNonPCWSideInformationForCurrentSet(H_HCR_INFO pHcr); + +static INT ModuloValue(INT input, INT bufferlength); + +static void ClearBitFromBitfield(STATEFUNC *ptrState, UINT offset, + UINT *pBitfield); + +/*--------------------------------------------------------------------------------------------- + description: This function decodes all non-priority codewords (non-PCWs) by +using a state-machine. +-------------------------------------------------------------------------------------------- +*/ +void DecodeNonPCWs(HANDLE_FDK_BITSTREAM bs, H_HCR_INFO pHcr) { + UINT numValidSegment; + INT segmentOffset; + INT codewordOffsetBase; + INT codewordOffset; + UINT trial; + + UINT *pNumSegment; + SCHAR *pRemainingBitsInSegment; + UINT *pSegmentBitfield; + UCHAR *pNumWordForBitfield; + USHORT *pNumBitValidInLastWord; + UINT *pCodewordBitfield; + INT bitfieldWord; + INT bitInWord; + UINT tempWord; + UINT interMediateWord; + INT tempBit; + INT carry; + + UINT numCodeword; + UCHAR numSet; + UCHAR currentSet; + UINT codewordInSet; + UINT remainingCodewordsInSet; + SCHAR *pSta; + UINT ret; + + pNumSegment = &(pHcr->segmentInfo.numSegment); + pRemainingBitsInSegment = pHcr->segmentInfo.pRemainingBitsInSegment; + pSegmentBitfield = pHcr->segmentInfo.pSegmentBitfield; + pNumWordForBitfield = &(pHcr->segmentInfo.numWordForBitfield); + pNumBitValidInLastWord = &(pHcr->segmentInfo.pNumBitValidInLastWord); + pSta = pHcr->nonPcwSideinfo.pSta; + + numValidSegment = InitSegmentBitfield(pNumSegment, pRemainingBitsInSegment, + pSegmentBitfield, pNumWordForBitfield, + pNumBitValidInLastWord); + + if (numValidSegment != 0) { + numCodeword = pHcr->sectionInfo.numCodeword; + numSet = ((numCodeword - 1) / *pNumSegment) + 1; + + pHcr->segmentInfo.readDirection = FROM_RIGHT_TO_LEFT; + + /* Process sets subsequently */ + for (currentSet = 1; currentSet < numSet; currentSet++) { + /* step 1 */ + numCodeword -= + *pNumSegment; /* number of remaining non PCWs [for all sets] */ + if (numCodeword < *pNumSegment) { + codewordInSet = numCodeword; /* for last set */ + } else { + codewordInSet = *pNumSegment; /* for all sets except last set */ + } + + /* step 2 */ + /* prepare array 'CodewordBitfield'; as much ones are written from left in + * all words, as much decodedCodewordInSetCounter nonPCWs exist in this + * set */ + tempWord = 0xFFFFFFFF; + pCodewordBitfield = pHcr->segmentInfo.pCodewordBitfield; + + for (bitfieldWord = *pNumWordForBitfield; bitfieldWord != 0; + bitfieldWord--) { /* loop over all used words */ + if (codewordInSet > NUMBER_OF_BIT_IN_WORD) { /* more codewords than + number of bits => fill + ones */ + /* fill a whole word with ones */ + *pCodewordBitfield++ = tempWord; + codewordInSet -= NUMBER_OF_BIT_IN_WORD; /* subtract number of bits */ + } else { + /* prepare last tempWord */ + for (remainingCodewordsInSet = codewordInSet; + remainingCodewordsInSet < NUMBER_OF_BIT_IN_WORD; + remainingCodewordsInSet++) { + tempWord = + tempWord & + ~(1 + << (NUMBER_OF_BIT_IN_WORD - 1 - + remainingCodewordsInSet)); /* set a zero at bit number + (NUMBER_OF_BIT_IN_WORD-1-i) + in tempWord */ + } + *pCodewordBitfield++ = tempWord; + tempWord = 0x00000000; + } + } + pCodewordBitfield = pHcr->segmentInfo.pCodewordBitfield; + + /* step 3 */ + /* build non-PCW sideinfo for each non-PCW of the current set */ + InitNonPCWSideInformationForCurrentSet(pHcr); + + /* step 4 */ + /* decode all non-PCWs belonging to this set */ + + /* loop over trials */ + codewordOffsetBase = 0; + for (trial = *pNumSegment; trial > 0; trial--) { + /* loop over number of words in bitfields */ + segmentOffset = 0; /* start at zero in every segment */ + pHcr->segmentInfo.segmentOffset = + segmentOffset; /* store in structure for states */ + codewordOffset = codewordOffsetBase; + pHcr->nonPcwSideinfo.codewordOffset = + codewordOffset; /* store in structure for states */ + + for (bitfieldWord = 0; bitfieldWord < *pNumWordForBitfield; + bitfieldWord++) { + /* derive tempWord with bitwise and */ + tempWord = + pSegmentBitfield[bitfieldWord] & pCodewordBitfield[bitfieldWord]; + + /* if tempWord is not zero, decode something */ + if (tempWord != 0) { + /* loop over all bits in tempWord; start state machine if & is true + */ + for (bitInWord = NUMBER_OF_BIT_IN_WORD; bitInWord > 0; + bitInWord--) { + interMediateWord = ((UINT)1 << (bitInWord - 1)); + if ((tempWord & interMediateWord) == interMediateWord) { + /* get state and start state machine */ + pHcr->nonPcwSideinfo.pState = + aStateConstant2State[pSta[codewordOffset]]; + + while (pHcr->nonPcwSideinfo.pState) { + ret = ((STATEFUNC)pHcr->nonPcwSideinfo.pState)(bs, pHcr); + if (ret != 0) { + return; + } + } + } + + /* update both offsets */ + segmentOffset += 1; /* add NUMBER_OF_BIT_IN_WORD times one */ + pHcr->segmentInfo.segmentOffset = segmentOffset; + codewordOffset += 1; /* add NUMBER_OF_BIT_IN_WORD times one */ + codewordOffset = + ModuloValue(codewordOffset, + *pNumSegment); /* index of the current codeword + lies within modulo range */ + pHcr->nonPcwSideinfo.codewordOffset = codewordOffset; + } + } else { + segmentOffset += + NUMBER_OF_BIT_IN_WORD; /* add NUMBER_OF_BIT_IN_WORD at once */ + pHcr->segmentInfo.segmentOffset = segmentOffset; + codewordOffset += + NUMBER_OF_BIT_IN_WORD; /* add NUMBER_OF_BIT_IN_WORD at once */ + codewordOffset = ModuloValue( + codewordOffset, + *pNumSegment); /* index of the current codeword lies within + modulo range */ + pHcr->nonPcwSideinfo.codewordOffset = codewordOffset; + } + } /* end of bitfield word loop */ + + /* decrement codeword - pointer */ + codewordOffsetBase -= 1; + codewordOffsetBase = + ModuloValue(codewordOffsetBase, *pNumSegment); /* index of the + current codeword + base lies within + modulo range */ + + /* rotate numSegment bits in codewordBitfield */ + /* rotation of *numSegment bits in bitfield of codewords + * (circle-rotation) */ + /* get last valid bit */ + tempBit = pCodewordBitfield[*pNumWordForBitfield - 1] & + (1 << (NUMBER_OF_BIT_IN_WORD - *pNumBitValidInLastWord)); + tempBit = tempBit >> (NUMBER_OF_BIT_IN_WORD - *pNumBitValidInLastWord); + + /* write zero into place where tempBit was fetched from */ + pCodewordBitfield[*pNumWordForBitfield - 1] = + pCodewordBitfield[*pNumWordForBitfield - 1] & + ~(1 << (NUMBER_OF_BIT_IN_WORD - *pNumBitValidInLastWord)); + + /* rotate last valid word */ + pCodewordBitfield[*pNumWordForBitfield - 1] = + pCodewordBitfield[*pNumWordForBitfield - 1] >> 1; + + /* transfare carry bit 0 from current word into bitposition 31 from next + * word and rotate current word */ + for (bitfieldWord = *pNumWordForBitfield - 2; bitfieldWord > -1; + bitfieldWord--) { + /* get carry (=bit at position 0) from current word */ + carry = pCodewordBitfield[bitfieldWord] & 1; + + /* put the carry bit at position 31 into word right from current word + */ + pCodewordBitfield[bitfieldWord + 1] = + pCodewordBitfield[bitfieldWord + 1] | + (carry << (NUMBER_OF_BIT_IN_WORD - 1)); + + /* shift current word */ + pCodewordBitfield[bitfieldWord] = + pCodewordBitfield[bitfieldWord] >> 1; + } + + /* put tempBit into free bit-position 31 from first word */ + pCodewordBitfield[0] = + pCodewordBitfield[0] | (tempBit << (NUMBER_OF_BIT_IN_WORD - 1)); + + } /* end of trial loop */ + + /* toggle read direction */ + pHcr->segmentInfo.readDirection = + ToggleReadDirection(pHcr->segmentInfo.readDirection); + } + /* end of set loop */ + + /* all non-PCWs of this spectrum are decoded */ + } + + /* all PCWs and all non PCWs are decoded. They are unbacksorted in output + * buffer. Here is the Interface with comparing QSCs to asm decoding */ +} + +/*--------------------------------------------------------------------------------------------- + description: This function prepares the bitfield used for the + segments. The list is set up once to be used in all +following sets. If a segment is decoded empty, the according bit from the +Bitfield is removed. +----------------------------------------------------------------------------------------------- + return: numValidSegment = the number of valid segments +-------------------------------------------------------------------------------------------- +*/ +static UINT InitSegmentBitfield(UINT *pNumSegment, + SCHAR *pRemainingBitsInSegment, + UINT *pSegmentBitfield, + UCHAR *pNumWordForBitfield, + USHORT *pNumBitValidInLastWord) { + SHORT i; + USHORT r; + UCHAR bitfieldWord; + UINT tempWord; + USHORT numValidSegment; + + *pNumWordForBitfield = + (*pNumSegment == 0) + ? 0 + : ((*pNumSegment - 1) >> THIRTYTWO_LOG_DIV_TWO_LOG) + 1; + + /* loop over all words, which are completely used or only partial */ + /* bit in pSegmentBitfield is zero if segment is empty; bit in + * pSegmentBitfield is one if segment is not empty */ + numValidSegment = 0; + *pNumBitValidInLastWord = *pNumSegment; + + /* loop over words */ + for (bitfieldWord = 0; bitfieldWord < *pNumWordForBitfield - 1; + bitfieldWord++) { + tempWord = 0xFFFFFFFF; /* set ones */ + r = bitfieldWord << THIRTYTWO_LOG_DIV_TWO_LOG; + for (i = 0; i < NUMBER_OF_BIT_IN_WORD; i++) { + if (pRemainingBitsInSegment[r + i] == 0) { + tempWord = tempWord & ~(1 << (NUMBER_OF_BIT_IN_WORD - 1 - + i)); /* set a zero at bit number + (NUMBER_OF_BIT_IN_WORD-1-i) in + tempWord */ + } else { + numValidSegment += 1; /* count segments which are not empty */ + } + } + pSegmentBitfield[bitfieldWord] = tempWord; /* store result */ + *pNumBitValidInLastWord -= NUMBER_OF_BIT_IN_WORD; /* calculate number of + zeros on LSB side in + the last word */ + } + + /* calculate last word: prepare special tempWord */ + tempWord = 0xFFFFFFFF; + for (i = 0; i < (NUMBER_OF_BIT_IN_WORD - *pNumBitValidInLastWord); i++) { + tempWord = tempWord & ~(1 << i); /* clear bit i in tempWord */ + } + + /* calculate last word */ + r = bitfieldWord << THIRTYTWO_LOG_DIV_TWO_LOG; + for (i = 0; i < *pNumBitValidInLastWord; i++) { + if (pRemainingBitsInSegment[r + i] == 0) { + tempWord = tempWord & ~(1 << (NUMBER_OF_BIT_IN_WORD - 1 - + i)); /* set a zero at bit number + (NUMBER_OF_BIT_IN_WORD-1-i) in + tempWord */ + } else { + numValidSegment += 1; /* count segments which are not empty */ + } + } + pSegmentBitfield[bitfieldWord] = tempWord; /* store result */ + + return numValidSegment; +} + +/*--------------------------------------------------------------------------------------------- + description: This function sets up sideinfo for the non-PCW decoder (for the +current set). +---------------------------------------------------------------------------------------------*/ +static void InitNonPCWSideInformationForCurrentSet(H_HCR_INFO pHcr) { + USHORT i, k; + UCHAR codebookDim; + UINT startNode; + + UCHAR *pCodebook = pHcr->nonPcwSideinfo.pCodebook; + UINT *iNode = pHcr->nonPcwSideinfo.iNode; + UCHAR *pCntSign = pHcr->nonPcwSideinfo.pCntSign; + USHORT *iResultPointer = pHcr->nonPcwSideinfo.iResultPointer; + UINT *pEscapeSequenceInfo = pHcr->nonPcwSideinfo.pEscapeSequenceInfo; + SCHAR *pSta = pHcr->nonPcwSideinfo.pSta; + 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; + int quantizedSpectralCoefficientsIdx = + pHcr->decInOut.quantizedSpectralCoefficientsIdx; + const UCHAR *pCbDimension = aDimCb; + int iterationCounter = 0; + + /* loop over number of extended sorted sections in the current set so all + * codewords sideinfo variables within this set can be prepared for decoding + */ + for (i = pNumExtendedSortedSectionsInSets[numExtendedSortedSectionsInSetsIdx]; + i != 0; i--) { + codebookDim = + pCbDimension[pExtendedSortedCodebook[extendedSortedCodebookIdx]]; + startNode = *aHuffTable[pExtendedSortedCodebook[extendedSortedCodebookIdx]]; + + for (k = pNumExtendedSortedCodewordInSection + [numExtendedSortedCodewordInSectionIdx]; + k != 0; k--) { + iterationCounter++; + if (iterationCounter > (1024 >> 2)) { + return; + } + *pSta++ = aCodebook2StartInt + [pExtendedSortedCodebook[extendedSortedCodebookIdx]]; + *pCodebook++ = pExtendedSortedCodebook[extendedSortedCodebookIdx]; + *iNode++ = startNode; + *pCntSign++ = 0; + *iResultPointer++ = quantizedSpectralCoefficientsIdx; + *pEscapeSequenceInfo++ = 0; + quantizedSpectralCoefficientsIdx += + codebookDim; /* update pointer by codebookDim --> point to next + starting value for writing out */ + if (quantizedSpectralCoefficientsIdx >= 1024) { + return; + } + } + numExtendedSortedCodewordInSectionIdx++; /* inc ptr for next ext sort sec in + current set */ + extendedSortedCodebookIdx++; /* inc ptr for next ext sort sec in current set + */ + if (numExtendedSortedCodewordInSectionIdx >= (MAX_SFB_HCR + MAX_HCR_SETS) || + extendedSortedCodebookIdx >= (MAX_SFB_HCR + MAX_HCR_SETS)) { + return; + } + } + numExtendedSortedSectionsInSetsIdx++; /* inc ptr for next set of non-PCWs */ + if (numExtendedSortedCodewordInSectionIdx >= (MAX_SFB_HCR + MAX_HCR_SETS)) { + return; + } + + /* Write back indexes */ + pHcr->sectionInfo.numExtendedSortedCodewordInSectionIdx = + numExtendedSortedCodewordInSectionIdx; + pHcr->sectionInfo.extendedSortedCodebookIdx = extendedSortedCodebookIdx; + pHcr->sectionInfo.numExtendedSortedSectionsInSetsIdx = + numExtendedSortedSectionsInSetsIdx; + pHcr->sectionInfo.numExtendedSortedCodewordInSectionIdx = + numExtendedSortedCodewordInSectionIdx; + pHcr->decInOut.quantizedSpectralCoefficientsIdx = + quantizedSpectralCoefficientsIdx; +} + +/*--------------------------------------------------------------------------------------------- + description: This function returns the input value if the value is in the + range of bufferlength. If is smaller, one bufferlength +is added, if is bigger one bufferlength is subtracted. +----------------------------------------------------------------------------------------------- + return: modulo result +-------------------------------------------------------------------------------------------- +*/ +static INT ModuloValue(INT input, INT bufferlength) { + if (input > (bufferlength - 1)) { + return (input - bufferlength); + } + if (input < 0) { + return (input + bufferlength); + } + return input; +} + +/*--------------------------------------------------------------------------------------------- + description: This function clears a bit from current bitfield and + switches off the statemachine. + + A bit is cleared in two cases: + a) a codeword is decoded, then a bit is cleared in codeword +bitfield b) a segment is decoded empty, then a bit is cleared in segment +bitfield +-------------------------------------------------------------------------------------------- +*/ +static void ClearBitFromBitfield(STATEFUNC *ptrState, UINT offset, + UINT *pBitfield) { + UINT numBitfieldWord; + UINT numBitfieldBit; + + /* get both values needed for clearing the bit */ + numBitfieldWord = offset >> THIRTYTWO_LOG_DIV_TWO_LOG; /* int = wordNr */ + numBitfieldBit = offset - (numBitfieldWord + << THIRTYTWO_LOG_DIV_TWO_LOG); /* fract = bitNr */ + + /* clear a bit in bitfield */ + pBitfield[numBitfieldWord] = + pBitfield[numBitfieldWord] & + ~(1 << (NUMBER_OF_BIT_IN_WORD - 1 - numBitfieldBit)); + + /* switch off state machine because codeword is decoded and/or because segment + * is empty */ + *ptrState = NULL; +} + +/* ========================================================================================= + the states of the statemachine + ========================================================================================= + */ + +/*--------------------------------------------------------------------------------------------- + description: Decodes the body of a codeword. This State is used for +codebooks 1,2,5 and 6. No sign bits are decoded, because the table of the +quantized spectral values has got a valid sign at the quantized spectral lines. +----------------------------------------------------------------------------------------------- + output: Two or four quantizes spectral values written at position +where pResultPointr points to +----------------------------------------------------------------------------------------------- + return: 0 +-------------------------------------------------------------------------------------------- +*/ +UINT Hcr_State_BODY_ONLY(HANDLE_FDK_BITSTREAM bs, void *ptr) { + H_HCR_INFO pHcr = (H_HCR_INFO)ptr; + UINT *pSegmentBitfield; + UINT *pCodewordBitfield; + UINT segmentOffset; + FIXP_DBL *pResultBase; + UINT *iNode; + USHORT *iResultPointer; + UINT codewordOffset; + UINT branchNode; + UINT branchValue; + UINT iQSC; + UINT treeNode; + UCHAR carryBit; + INT *pLeftStartOfSegment; + INT *pRightStartOfSegment; + SCHAR *pRemainingBitsInSegment; + UCHAR readDirection; + UCHAR *pCodebook; + UCHAR dimCntr; + const UINT *pCurrentTree; + const UCHAR *pCbDimension; + const SCHAR *pQuantVal; + const SCHAR *pQuantValBase; + + pRemainingBitsInSegment = pHcr->segmentInfo.pRemainingBitsInSegment; + pLeftStartOfSegment = pHcr->segmentInfo.pLeftStartOfSegment; + pRightStartOfSegment = pHcr->segmentInfo.pRightStartOfSegment; + readDirection = pHcr->segmentInfo.readDirection; + pSegmentBitfield = pHcr->segmentInfo.pSegmentBitfield; + pCodewordBitfield = pHcr->segmentInfo.pCodewordBitfield; + segmentOffset = pHcr->segmentInfo.segmentOffset; + + pCodebook = pHcr->nonPcwSideinfo.pCodebook; + iNode = pHcr->nonPcwSideinfo.iNode; + pResultBase = pHcr->nonPcwSideinfo.pResultBase; + iResultPointer = pHcr->nonPcwSideinfo.iResultPointer; + codewordOffset = pHcr->nonPcwSideinfo.codewordOffset; + + pCbDimension = aDimCb; + + treeNode = iNode[codewordOffset]; + pCurrentTree = aHuffTable[pCodebook[codewordOffset]]; + + for (; pRemainingBitsInSegment[segmentOffset] > 0; + pRemainingBitsInSegment[segmentOffset] -= 1) { + carryBit = HcrGetABitFromBitstream( + bs, pHcr->decInOut.bitstreamAnchor, &pLeftStartOfSegment[segmentOffset], + &pRightStartOfSegment[segmentOffset], readDirection); + + CarryBitToBranchValue(carryBit, /* make a step in decoding tree */ + treeNode, &branchValue, &branchNode); + + /* if end of branch reached write out lines and count bits needed for sign, + * otherwise store node in codeword sideinfo */ + if ((branchNode & TEST_BIT_10) == + TEST_BIT_10) { /* test bit 10 ; ==> body is complete */ + pQuantValBase = aQuantTable[pCodebook[codewordOffset]]; /* get base + address of + quantized + values + belonging to + current + codebook */ + pQuantVal = pQuantValBase + branchValue; /* set pointer to first valid + line [of 2 or 4 quantized + values] */ + + iQSC = iResultPointer[codewordOffset]; /* get position of first line for + writing out result */ + + for (dimCntr = pCbDimension[pCodebook[codewordOffset]]; dimCntr != 0; + dimCntr--) { + pResultBase[iQSC++] = + (FIXP_DBL)*pQuantVal++; /* write out 2 or 4 lines into + spectrum; no Sign bits + available in this state */ + } + + ClearBitFromBitfield(&(pHcr->nonPcwSideinfo.pState), segmentOffset, + pCodewordBitfield); /* clear a bit in bitfield and + switch off statemachine */ + pRemainingBitsInSegment[segmentOffset] -= 1; /* last reinitialzation of + for loop counter (see + above) is done here */ + break; /* end of branch in tree reached i.e. a whole nonPCW-Body is + decoded */ + } else { /* body is not decoded completely: */ + treeNode = *( + pCurrentTree + + branchValue); /* update treeNode for further step in decoding tree */ + } + } + iNode[codewordOffset] = treeNode; /* store updated treeNode because maybe + decoding of codeword body not finished + yet */ + + if (pRemainingBitsInSegment[segmentOffset] <= 0) { + ClearBitFromBitfield(&(pHcr->nonPcwSideinfo.pState), segmentOffset, + pSegmentBitfield); /* clear a bit in bitfield and + switch off statemachine */ + + if (pRemainingBitsInSegment[segmentOffset] < 0) { + pHcr->decInOut.errorLog |= STATE_ERROR_BODY_ONLY; + return BODY_ONLY; + } + } + + return STOP_THIS_STATE; +} + +/*--------------------------------------------------------------------------------------------- + description: Decodes the codeword body, writes out result and counts the +number of quantized spectral values, which are different form zero. For those +values sign bits are needed. + + If sign bit counter cntSign is different from zero, switch to +next state to decode sign Bits there. If sign bit counter cntSign is zero, no +sign bits are needed and codeword is decoded. +----------------------------------------------------------------------------------------------- + output: Two or four written quantizes spectral values written at +position where pResultPointr points to. The signs of those lines may be wrong. +If the signs [on just one signle sign] is wrong, the next state will correct it. +----------------------------------------------------------------------------------------------- + return: 0 +-------------------------------------------------------------------------------------------- +*/ +UINT Hcr_State_BODY_SIGN__BODY(HANDLE_FDK_BITSTREAM bs, void *ptr) { + H_HCR_INFO pHcr = (H_HCR_INFO)ptr; + SCHAR *pRemainingBitsInSegment; + INT *pLeftStartOfSegment; + INT *pRightStartOfSegment; + UCHAR readDirection; + UINT *pSegmentBitfield; + UINT *pCodewordBitfield; + UINT segmentOffset; + + UCHAR *pCodebook; + UINT *iNode; + UCHAR *pCntSign; + FIXP_DBL *pResultBase; + USHORT *iResultPointer; + UINT codewordOffset; + + UINT iQSC; + UINT cntSign; + UCHAR dimCntr; + UCHAR carryBit; + SCHAR *pSta; + UINT treeNode; + UINT branchValue; + UINT branchNode; + const UCHAR *pCbDimension; + const UINT *pCurrentTree; + const SCHAR *pQuantValBase; + const SCHAR *pQuantVal; + + pRemainingBitsInSegment = pHcr->segmentInfo.pRemainingBitsInSegment; + pLeftStartOfSegment = pHcr->segmentInfo.pLeftStartOfSegment; + pRightStartOfSegment = pHcr->segmentInfo.pRightStartOfSegment; + readDirection = pHcr->segmentInfo.readDirection; + pSegmentBitfield = pHcr->segmentInfo.pSegmentBitfield; + pCodewordBitfield = pHcr->segmentInfo.pCodewordBitfield; + segmentOffset = pHcr->segmentInfo.segmentOffset; + + pCodebook = pHcr->nonPcwSideinfo.pCodebook; + iNode = pHcr->nonPcwSideinfo.iNode; + pCntSign = pHcr->nonPcwSideinfo.pCntSign; + pResultBase = pHcr->nonPcwSideinfo.pResultBase; + iResultPointer = pHcr->nonPcwSideinfo.iResultPointer; + codewordOffset = pHcr->nonPcwSideinfo.codewordOffset; + pSta = pHcr->nonPcwSideinfo.pSta; + + pCbDimension = aDimCb; + + treeNode = iNode[codewordOffset]; + pCurrentTree = aHuffTable[pCodebook[codewordOffset]]; + + for (; pRemainingBitsInSegment[segmentOffset] > 0; + pRemainingBitsInSegment[segmentOffset] -= 1) { + carryBit = HcrGetABitFromBitstream( + bs, pHcr->decInOut.bitstreamAnchor, &pLeftStartOfSegment[segmentOffset], + &pRightStartOfSegment[segmentOffset], readDirection); + + CarryBitToBranchValue(carryBit, /* make a step in decoding tree */ + treeNode, &branchValue, &branchNode); + + /* if end of branch reached write out lines and count bits needed for sign, + * otherwise store node in codeword sideinfo */ + if ((branchNode & TEST_BIT_10) == + TEST_BIT_10) { /* test bit 10 ; if set body complete */ + /* body completely decoded; branchValue is valid, set pQuantVal to first + * (of two or four) quantized spectral coefficients */ + pQuantValBase = aQuantTable[pCodebook[codewordOffset]]; /* get base + address of + quantized + values + belonging to + current + codebook */ + pQuantVal = pQuantValBase + branchValue; /* set pointer to first valid + line [of 2 or 4 quantized + values] */ + + iQSC = iResultPointer[codewordOffset]; /* get position of first line for + writing result */ + + /* codeword decoding result is written out here: Write out 2 or 4 + * quantized spectral values with probably */ + /* wrong sign and count number of values which are different from zero for + * sign bit decoding [which happens in next state] */ + cntSign = 0; + for (dimCntr = pCbDimension[pCodebook[codewordOffset]]; dimCntr != 0; + dimCntr--) { + pResultBase[iQSC++] = + (FIXP_DBL)*pQuantVal; /* write quant. spec. coef. into spectrum */ + if (*pQuantVal++ != 0) { + cntSign += 1; + } + } + + if (cntSign == 0) { + ClearBitFromBitfield( + &(pHcr->nonPcwSideinfo.pState), segmentOffset, + pCodewordBitfield); /* clear a bit in bitfield and switch off + statemachine */ + } else { + pCntSign[codewordOffset] = cntSign; /* write sign count result into + codewordsideinfo of current + codeword */ + pSta[codewordOffset] = BODY_SIGN__SIGN; /* change state */ + pHcr->nonPcwSideinfo.pState = + aStateConstant2State[pSta[codewordOffset]]; /* get state from + separate array of + cw-sideinfo */ + } + pRemainingBitsInSegment[segmentOffset] -= 1; /* last reinitialzation of + for loop counter (see + above) is done here */ + break; /* end of branch in tree reached i.e. a whole nonPCW-Body is + decoded */ + } else { /* body is not decoded completely: */ + treeNode = *( + pCurrentTree + + branchValue); /* update treeNode for further step in decoding tree */ + } + } + iNode[codewordOffset] = treeNode; /* store updated treeNode because maybe + decoding of codeword body not finished + yet */ + + if (pRemainingBitsInSegment[segmentOffset] <= 0) { + ClearBitFromBitfield(&(pHcr->nonPcwSideinfo.pState), segmentOffset, + pSegmentBitfield); /* clear a bit in bitfield and + switch off statemachine */ + + if (pRemainingBitsInSegment[segmentOffset] < 0) { + pHcr->decInOut.errorLog |= STATE_ERROR_BODY_SIGN__BODY; + return BODY_SIGN__BODY; + } + } + + return STOP_THIS_STATE; +} + +/*--------------------------------------------------------------------------------------------- + description: This state decodes the sign bits belonging to a codeword. The +state is called as often in different "trials" until pCntSgn[codewordOffset] is +zero. +----------------------------------------------------------------------------------------------- + output: The two or four quantizes spectral values (written in previous +state) have now the correct sign. +----------------------------------------------------------------------------------------------- + return: 0 +-------------------------------------------------------------------------------------------- +*/ +UINT Hcr_State_BODY_SIGN__SIGN(HANDLE_FDK_BITSTREAM bs, void *ptr) { + H_HCR_INFO pHcr = (H_HCR_INFO)ptr; + SCHAR *pRemainingBitsInSegment; + INT *pLeftStartOfSegment; + INT *pRightStartOfSegment; + UCHAR readDirection; + UINT *pSegmentBitfield; + UINT *pCodewordBitfield; + UINT segmentOffset; + + UCHAR *pCntSign; + FIXP_DBL *pResultBase; + USHORT *iResultPointer; + UINT codewordOffset; + + UCHAR carryBit; + UINT iQSC; + UCHAR cntSign; + + pRemainingBitsInSegment = pHcr->segmentInfo.pRemainingBitsInSegment; + pLeftStartOfSegment = pHcr->segmentInfo.pLeftStartOfSegment; + pRightStartOfSegment = pHcr->segmentInfo.pRightStartOfSegment; + readDirection = pHcr->segmentInfo.readDirection; + pSegmentBitfield = pHcr->segmentInfo.pSegmentBitfield; + pCodewordBitfield = pHcr->segmentInfo.pCodewordBitfield; + segmentOffset = pHcr->segmentInfo.segmentOffset; + + /*pCodebook = */ + pCntSign = pHcr->nonPcwSideinfo.pCntSign; + pResultBase = pHcr->nonPcwSideinfo.pResultBase; + iResultPointer = pHcr->nonPcwSideinfo.iResultPointer; + codewordOffset = pHcr->nonPcwSideinfo.codewordOffset; + + iQSC = iResultPointer[codewordOffset]; + cntSign = pCntSign[codewordOffset]; + + /* loop for sign bit decoding */ + for (; pRemainingBitsInSegment[segmentOffset] > 0; + pRemainingBitsInSegment[segmentOffset] -= 1) { + carryBit = HcrGetABitFromBitstream( + bs, pHcr->decInOut.bitstreamAnchor, &pLeftStartOfSegment[segmentOffset], + &pRightStartOfSegment[segmentOffset], readDirection); + cntSign -= + 1; /* decrement sign counter because one sign bit has been read */ + + /* search for a line (which was decoded in previous state) which is not + * zero. [This value will get a sign] */ + while (pResultBase[iQSC] == (FIXP_DBL)0) { + if (++iQSC >= 1024) { /* points to current value different from zero */ + return BODY_SIGN__SIGN; + } + } + + /* put sign together with line; if carryBit is zero, the sign is ok already; + * no write operation necessary in this case */ + if (carryBit != 0) { + pResultBase[iQSC] = -pResultBase[iQSC]; /* carryBit = 1 --> minus */ + } + + iQSC++; /* update pointer to next (maybe valid) value */ + + if (cntSign == 0) { /* if (cntSign==0) ==> set state CODEWORD_DECODED */ + ClearBitFromBitfield(&(pHcr->nonPcwSideinfo.pState), segmentOffset, + pCodewordBitfield); /* clear a bit in bitfield and + switch off statemachine */ + pRemainingBitsInSegment[segmentOffset] -= 1; /* last reinitialzation of + for loop counter (see + above) is done here */ + break; /* whole nonPCW-Body and according sign bits are decoded */ + } + } + pCntSign[codewordOffset] = cntSign; + iResultPointer[codewordOffset] = iQSC; /* store updated pResultPointer */ + + if (pRemainingBitsInSegment[segmentOffset] <= 0) { + ClearBitFromBitfield(&(pHcr->nonPcwSideinfo.pState), segmentOffset, + pSegmentBitfield); /* clear a bit in bitfield and + switch off statemachine */ + + if (pRemainingBitsInSegment[segmentOffset] < 0) { + pHcr->decInOut.errorLog |= STATE_ERROR_BODY_SIGN__SIGN; + return BODY_SIGN__SIGN; + } + } + + return STOP_THIS_STATE; +} + +/*--------------------------------------------------------------------------------------------- + description: Decodes the codeword body in case of codebook is 11. Writes +out resulting two or four lines [with probably wrong sign] and counts the number +of lines, which are different form zero. This information is needed in next + state where sign bits will be decoded, if necessary. + If sign bit counter cntSign is zero, no sign bits are needed +and codeword is decoded completely. +----------------------------------------------------------------------------------------------- + output: Two lines (quantizes spectral coefficients) which are probably +wrong. The sign may be wrong and if one or two values is/are 16, the following +states will decode the escape sequence to correct the values which are wirtten +here. +----------------------------------------------------------------------------------------------- + return: 0 +-------------------------------------------------------------------------------------------- +*/ +UINT Hcr_State_BODY_SIGN_ESC__BODY(HANDLE_FDK_BITSTREAM bs, void *ptr) { + H_HCR_INFO pHcr = (H_HCR_INFO)ptr; + SCHAR *pRemainingBitsInSegment; + INT *pLeftStartOfSegment; + INT *pRightStartOfSegment; + UCHAR readDirection; + UINT *pSegmentBitfield; + UINT *pCodewordBitfield; + UINT segmentOffset; + + UINT *iNode; + UCHAR *pCntSign; + FIXP_DBL *pResultBase; + USHORT *iResultPointer; + UINT codewordOffset; + + UCHAR carryBit; + UINT iQSC; + UINT cntSign; + UINT dimCntr; + UINT treeNode; + SCHAR *pSta; + UINT branchNode; + UINT branchValue; + const UINT *pCurrentTree; + const SCHAR *pQuantValBase; + const SCHAR *pQuantVal; + + pRemainingBitsInSegment = pHcr->segmentInfo.pRemainingBitsInSegment; + pLeftStartOfSegment = pHcr->segmentInfo.pLeftStartOfSegment; + pRightStartOfSegment = pHcr->segmentInfo.pRightStartOfSegment; + readDirection = pHcr->segmentInfo.readDirection; + pSegmentBitfield = pHcr->segmentInfo.pSegmentBitfield; + pCodewordBitfield = pHcr->segmentInfo.pCodewordBitfield; + segmentOffset = pHcr->segmentInfo.segmentOffset; + + iNode = pHcr->nonPcwSideinfo.iNode; + pCntSign = pHcr->nonPcwSideinfo.pCntSign; + pResultBase = pHcr->nonPcwSideinfo.pResultBase; + iResultPointer = pHcr->nonPcwSideinfo.iResultPointer; + codewordOffset = pHcr->nonPcwSideinfo.codewordOffset; + pSta = pHcr->nonPcwSideinfo.pSta; + + treeNode = iNode[codewordOffset]; + pCurrentTree = aHuffTable[ESCAPE_CODEBOOK]; + + for (; pRemainingBitsInSegment[segmentOffset] > 0; + pRemainingBitsInSegment[segmentOffset] -= 1) { + carryBit = HcrGetABitFromBitstream( + bs, pHcr->decInOut.bitstreamAnchor, &pLeftStartOfSegment[segmentOffset], + &pRightStartOfSegment[segmentOffset], readDirection); + + /* make a step in tree */ + CarryBitToBranchValue(carryBit, treeNode, &branchValue, &branchNode); + + /* if end of branch reached write out lines and count bits needed for sign, + * otherwise store node in codeword sideinfo */ + if ((branchNode & TEST_BIT_10) == + TEST_BIT_10) { /* test bit 10 ; if set body complete */ + + /* body completely decoded; branchValue is valid */ + /* set pQuantVol to first (of two or four) quantized spectral coefficients + */ + pQuantValBase = aQuantTable[ESCAPE_CODEBOOK]; /* get base address of + quantized values + belonging to current + codebook */ + pQuantVal = pQuantValBase + branchValue; /* set pointer to first valid + line [of 2 or 4 quantized + values] */ + + /* make backup from original resultPointer in node storage for state + * BODY_SIGN_ESC__SIGN */ + iNode[codewordOffset] = iResultPointer[codewordOffset]; + + /* get position of first line for writing result */ + iQSC = iResultPointer[codewordOffset]; + + /* codeword decoding result is written out here: Write out 2 or 4 + * quantized spectral values with probably */ + /* wrong sign and count number of values which are different from zero for + * sign bit decoding [which happens in next state] */ + cntSign = 0; + + for (dimCntr = DIMENSION_OF_ESCAPE_CODEBOOK; dimCntr != 0; dimCntr--) { + pResultBase[iQSC++] = + (FIXP_DBL)*pQuantVal; /* write quant. spec. coef. into spectrum */ + if (*pQuantVal++ != 0) { + cntSign += 1; + } + } + + if (cntSign == 0) { + ClearBitFromBitfield( + &(pHcr->nonPcwSideinfo.pState), segmentOffset, + pCodewordBitfield); /* clear a bit in bitfield and switch off + statemachine */ + /* codeword decoded */ + } else { + /* write sign count result into codewordsideinfo of current codeword */ + pCntSign[codewordOffset] = cntSign; + pSta[codewordOffset] = BODY_SIGN_ESC__SIGN; /* change state */ + pHcr->nonPcwSideinfo.pState = + aStateConstant2State[pSta[codewordOffset]]; /* get state from + separate array of + cw-sideinfo */ + } + pRemainingBitsInSegment[segmentOffset] -= 1; /* the last reinitialzation + of for loop counter (see + above) is done here */ + break; /* end of branch in tree reached i.e. a whole nonPCW-Body is + decoded */ + } else { /* body is not decoded completely: */ + /* update treeNode for further step in decoding tree and store updated + * treeNode because maybe no more bits left in segment */ + treeNode = *(pCurrentTree + branchValue); + iNode[codewordOffset] = treeNode; + } + } + + if (pRemainingBitsInSegment[segmentOffset] <= 0) { + ClearBitFromBitfield(&(pHcr->nonPcwSideinfo.pState), segmentOffset, + pSegmentBitfield); /* clear a bit in bitfield and + switch off statemachine */ + + if (pRemainingBitsInSegment[segmentOffset] < 0) { + pHcr->decInOut.errorLog |= STATE_ERROR_BODY_SIGN_ESC__BODY; + return BODY_SIGN_ESC__BODY; + } + } + + return STOP_THIS_STATE; +} + +/*--------------------------------------------------------------------------------------------- + description: This state decodes the sign bits, if a codeword of codebook 11 +needs some. A flag named 'flagB' in codeword sideinfo is set, if the second line +of quantized spectral values is 16. The 'flagB' is used in case of decoding of a +escape sequence is necessary as far as the second line is concerned. + + If only the first line needs an escape sequence, the flagB is +cleared. If only the second line needs an escape sequence, the flagB is not +used. + + For storing sideinfo in case of escape sequence decoding one +single word can be used for both escape sequences because they are decoded not +at the same time: + + + bit 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 +4 3 2 1 0 + ===== == == =========== =========== +=================================== ^ ^ ^ ^ ^ +^ | | | | | | res. flagA flagB +escapePrefixUp escapePrefixDown escapeWord + +----------------------------------------------------------------------------------------------- + output: Two lines with correct sign. If one or two values is/are 16, +the lines are not valid, otherwise they are. +----------------------------------------------------------------------------------------------- + return: 0 +-------------------------------------------------------------------------------------------- +*/ +UINT Hcr_State_BODY_SIGN_ESC__SIGN(HANDLE_FDK_BITSTREAM bs, void *ptr) { + H_HCR_INFO pHcr = (H_HCR_INFO)ptr; + SCHAR *pRemainingBitsInSegment; + INT *pLeftStartOfSegment; + INT *pRightStartOfSegment; + UCHAR readDirection; + UINT *pSegmentBitfield; + UINT *pCodewordBitfield; + UINT segmentOffset; + + UINT *iNode; + UCHAR *pCntSign; + FIXP_DBL *pResultBase; + USHORT *iResultPointer; + UINT *pEscapeSequenceInfo; + UINT codewordOffset; + + UINT iQSC; + UCHAR cntSign; + UINT flagA; + UINT flagB; + UINT flags; + UCHAR carryBit; + SCHAR *pSta; + + pRemainingBitsInSegment = pHcr->segmentInfo.pRemainingBitsInSegment; + pLeftStartOfSegment = pHcr->segmentInfo.pLeftStartOfSegment; + pRightStartOfSegment = pHcr->segmentInfo.pRightStartOfSegment; + readDirection = pHcr->segmentInfo.readDirection; + pSegmentBitfield = pHcr->segmentInfo.pSegmentBitfield; + pCodewordBitfield = pHcr->segmentInfo.pCodewordBitfield; + segmentOffset = pHcr->segmentInfo.segmentOffset; + + iNode = pHcr->nonPcwSideinfo.iNode; + pCntSign = pHcr->nonPcwSideinfo.pCntSign; + pResultBase = pHcr->nonPcwSideinfo.pResultBase; + iResultPointer = pHcr->nonPcwSideinfo.iResultPointer; + pEscapeSequenceInfo = pHcr->nonPcwSideinfo.pEscapeSequenceInfo; + codewordOffset = pHcr->nonPcwSideinfo.codewordOffset; + pSta = pHcr->nonPcwSideinfo.pSta; + + iQSC = iResultPointer[codewordOffset]; + cntSign = pCntSign[codewordOffset]; + + /* loop for sign bit decoding */ + for (; pRemainingBitsInSegment[segmentOffset] > 0; + pRemainingBitsInSegment[segmentOffset] -= 1) { + carryBit = HcrGetABitFromBitstream( + bs, pHcr->decInOut.bitstreamAnchor, &pLeftStartOfSegment[segmentOffset], + &pRightStartOfSegment[segmentOffset], readDirection); + + /* decrement sign counter because one sign bit has been read */ + cntSign -= 1; + pCntSign[codewordOffset] = cntSign; + + /* get a quantized spectral value (which was decoded in previous state) + * which is not zero. [This value will get a sign] */ + while (pResultBase[iQSC] == (FIXP_DBL)0) { + if (++iQSC >= 1024) { + return BODY_SIGN_ESC__SIGN; + } + } + iResultPointer[codewordOffset] = iQSC; + + /* put negative sign together with quantized spectral value; if carryBit is + * zero, the sign is ok already; no write operation necessary in this case + */ + if (carryBit != 0) { + pResultBase[iQSC] = -pResultBase[iQSC]; /* carryBit = 1 --> minus */ + } + iQSC++; /* update index to next (maybe valid) value */ + iResultPointer[codewordOffset] = iQSC; + + if (cntSign == 0) { + /* all sign bits are decoded now */ + pRemainingBitsInSegment[segmentOffset] -= 1; /* last reinitialzation of + for loop counter (see + above) is done here */ + + /* check decoded values if codeword is decoded: Check if one or two escape + * sequences 16 follow */ + + /* step 0 */ + /* restore pointer to first decoded quantized value [ = original + * pResultPointr] from index iNode prepared in State_BODY_SIGN_ESC__BODY + */ + iQSC = iNode[codewordOffset]; + + /* step 1 */ + /* test first value if escape sequence follows */ + flagA = 0; /* for first possible escape sequence */ + if (fixp_abs(pResultBase[iQSC++]) == (FIXP_DBL)ESCAPE_VALUE) { + flagA = 1; + } + + /* step 2 */ + /* test second value if escape sequence follows */ + flagB = 0; /* for second possible escape sequence */ + if (fixp_abs(pResultBase[iQSC]) == (FIXP_DBL)ESCAPE_VALUE) { + flagB = 1; + } + + /* step 3 */ + /* evaluate flag result and go on if necessary */ + if (!flagA && !flagB) { + ClearBitFromBitfield( + &(pHcr->nonPcwSideinfo.pState), segmentOffset, + pCodewordBitfield); /* clear a bit in bitfield and switch off + statemachine */ + } else { + /* at least one of two lines is 16 */ + /* store both flags at correct positions in non PCW codeword sideinfo + * pEscapeSequenceInfo[codewordOffset] */ + flags = flagA << POSITION_OF_FLAG_A; + flags |= (flagB << POSITION_OF_FLAG_B); + pEscapeSequenceInfo[codewordOffset] = flags; + + /* set next state */ + pSta[codewordOffset] = BODY_SIGN_ESC__ESC_PREFIX; + pHcr->nonPcwSideinfo.pState = + aStateConstant2State[pSta[codewordOffset]]; /* get state from + separate array of + cw-sideinfo */ + + /* set result pointer to the first line of the two decoded lines */ + iResultPointer[codewordOffset] = iNode[codewordOffset]; + + if (!flagA && flagB) { + /* update pResultPointr ==> state Stat_BODY_SIGN_ESC__ESC_WORD writes + * to correct position. Second value is the one and only escape value + */ + iQSC = iResultPointer[codewordOffset]; + iQSC++; + iResultPointer[codewordOffset] = iQSC; + } + + } /* at least one of two lines is 16 */ + break; /* nonPCW-Body at cb 11 and according sign bits are decoded */ + + } /* if ( cntSign == 0 ) */ + } /* loop over remaining Bits in segment */ + + if (pRemainingBitsInSegment[segmentOffset] <= 0) { + ClearBitFromBitfield(&(pHcr->nonPcwSideinfo.pState), segmentOffset, + pSegmentBitfield); /* clear a bit in bitfield and + switch off statemachine */ + + if (pRemainingBitsInSegment[segmentOffset] < 0) { + pHcr->decInOut.errorLog |= STATE_ERROR_BODY_SIGN_ESC__SIGN; + return BODY_SIGN_ESC__SIGN; + } + } + return STOP_THIS_STATE; +} + +/*--------------------------------------------------------------------------------------------- + description: Decode escape prefix of first or second escape sequence. The +escape prefix consists of ones. The following zero is also decoded here. +----------------------------------------------------------------------------------------------- + output: If the single separator-zero which follows the +escape-prefix-ones is not yet decoded: The value 'escapePrefixUp' in word +pEscapeSequenceInfo[codewordOffset] is updated. + + If the single separator-zero which follows the +escape-prefix-ones is decoded: Two updated values 'escapePrefixUp' and +'escapePrefixDown' in word pEscapeSequenceInfo[codewordOffset]. This State is +finished. Switch to next state. +----------------------------------------------------------------------------------------------- + return: 0 +-------------------------------------------------------------------------------------------- +*/ +UINT Hcr_State_BODY_SIGN_ESC__ESC_PREFIX(HANDLE_FDK_BITSTREAM bs, void *ptr) { + H_HCR_INFO pHcr = (H_HCR_INFO)ptr; + SCHAR *pRemainingBitsInSegment; + INT *pLeftStartOfSegment; + INT *pRightStartOfSegment; + UCHAR readDirection; + UINT *pSegmentBitfield; + UINT segmentOffset; + UINT *pEscapeSequenceInfo; + UINT codewordOffset; + UCHAR carryBit; + UINT escapePrefixUp; + SCHAR *pSta; + + pRemainingBitsInSegment = pHcr->segmentInfo.pRemainingBitsInSegment; + pLeftStartOfSegment = pHcr->segmentInfo.pLeftStartOfSegment; + pRightStartOfSegment = pHcr->segmentInfo.pRightStartOfSegment; + readDirection = pHcr->segmentInfo.readDirection; + pSegmentBitfield = pHcr->segmentInfo.pSegmentBitfield; + segmentOffset = pHcr->segmentInfo.segmentOffset; + pEscapeSequenceInfo = pHcr->nonPcwSideinfo.pEscapeSequenceInfo; + codewordOffset = pHcr->nonPcwSideinfo.codewordOffset; + pSta = pHcr->nonPcwSideinfo.pSta; + + escapePrefixUp = + (pEscapeSequenceInfo[codewordOffset] & MASK_ESCAPE_PREFIX_UP) >> + LSB_ESCAPE_PREFIX_UP; + + /* decode escape prefix */ + for (; pRemainingBitsInSegment[segmentOffset] > 0; + pRemainingBitsInSegment[segmentOffset] -= 1) { + carryBit = HcrGetABitFromBitstream( + bs, pHcr->decInOut.bitstreamAnchor, &pLeftStartOfSegment[segmentOffset], + &pRightStartOfSegment[segmentOffset], readDirection); + + /* count ones and store sum in escapePrefixUp */ + if (carryBit == 1) { + escapePrefixUp += 1; /* update conter for ones */ + + /* store updated counter in sideinfo of current codeword */ + pEscapeSequenceInfo[codewordOffset] &= + ~MASK_ESCAPE_PREFIX_UP; /* delete old escapePrefixUp */ + escapePrefixUp <<= LSB_ESCAPE_PREFIX_UP; /* shift to correct position */ + pEscapeSequenceInfo[codewordOffset] |= + escapePrefixUp; /* insert new escapePrefixUp */ + escapePrefixUp >>= LSB_ESCAPE_PREFIX_UP; /* shift back down */ + } else { /* separator [zero] reached */ + pRemainingBitsInSegment[segmentOffset] -= 1; /* last reinitialzation of + for loop counter (see + above) is done here */ + escapePrefixUp += + 4; /* if escape_separator '0' appears, add 4 and ==> break */ + + /* store escapePrefixUp in pEscapeSequenceInfo[codewordOffset] at bit + * position escapePrefixUp */ + pEscapeSequenceInfo[codewordOffset] &= + ~MASK_ESCAPE_PREFIX_UP; /* delete old escapePrefixUp */ + escapePrefixUp <<= LSB_ESCAPE_PREFIX_UP; /* shift to correct position */ + pEscapeSequenceInfo[codewordOffset] |= + escapePrefixUp; /* insert new escapePrefixUp */ + escapePrefixUp >>= LSB_ESCAPE_PREFIX_UP; /* shift back down */ + + /* store escapePrefixUp in pEscapeSequenceInfo[codewordOffset] at bit + * position escapePrefixDown */ + pEscapeSequenceInfo[codewordOffset] &= + ~MASK_ESCAPE_PREFIX_DOWN; /* delete old escapePrefixDown */ + escapePrefixUp <<= LSB_ESCAPE_PREFIX_DOWN; /* shift to correct position */ + pEscapeSequenceInfo[codewordOffset] |= + escapePrefixUp; /* insert new escapePrefixDown */ + + pSta[codewordOffset] = BODY_SIGN_ESC__ESC_WORD; /* set next state */ + pHcr->nonPcwSideinfo.pState = + aStateConstant2State[pSta[codewordOffset]]; /* get state from separate + array of cw-sideinfo */ + break; + } + } + + if (pRemainingBitsInSegment[segmentOffset] <= 0) { + ClearBitFromBitfield(&(pHcr->nonPcwSideinfo.pState), segmentOffset, + pSegmentBitfield); /* clear a bit in bitfield and + switch off statemachine */ + + if (pRemainingBitsInSegment[segmentOffset] < 0) { + pHcr->decInOut.errorLog |= STATE_ERROR_BODY_SIGN_ESC__ESC_PREFIX; + return BODY_SIGN_ESC__ESC_PREFIX; + } + } + + return STOP_THIS_STATE; +} + +/*--------------------------------------------------------------------------------------------- + description: Decode escapeWord of escape sequence. If the escape sequence +is decoded completely, assemble quantized-spectral-escape-coefficient and +replace the previous decoded 16 by the new value. Test flagB. If flagB is set, +the second escape sequence must be decoded. If flagB is not set, the codeword is +decoded and the state machine is switched off. +----------------------------------------------------------------------------------------------- + output: Two lines with valid sign. At least one of both lines has got +the correct value. +----------------------------------------------------------------------------------------------- + return: 0 +-------------------------------------------------------------------------------------------- +*/ +UINT Hcr_State_BODY_SIGN_ESC__ESC_WORD(HANDLE_FDK_BITSTREAM bs, void *ptr) { + H_HCR_INFO pHcr = (H_HCR_INFO)ptr; + SCHAR *pRemainingBitsInSegment; + INT *pLeftStartOfSegment; + INT *pRightStartOfSegment; + UCHAR readDirection; + UINT *pSegmentBitfield; + UINT *pCodewordBitfield; + UINT segmentOffset; + + FIXP_DBL *pResultBase; + USHORT *iResultPointer; + UINT *pEscapeSequenceInfo; + UINT codewordOffset; + + UINT escapeWord; + UINT escapePrefixDown; + UINT escapePrefixUp; + UCHAR carryBit; + UINT iQSC; + INT sign; + UINT flagA; + UINT flagB; + SCHAR *pSta; + + pRemainingBitsInSegment = pHcr->segmentInfo.pRemainingBitsInSegment; + pLeftStartOfSegment = pHcr->segmentInfo.pLeftStartOfSegment; + pRightStartOfSegment = pHcr->segmentInfo.pRightStartOfSegment; + readDirection = pHcr->segmentInfo.readDirection; + pSegmentBitfield = pHcr->segmentInfo.pSegmentBitfield; + pCodewordBitfield = pHcr->segmentInfo.pCodewordBitfield; + segmentOffset = pHcr->segmentInfo.segmentOffset; + + pResultBase = pHcr->nonPcwSideinfo.pResultBase; + iResultPointer = pHcr->nonPcwSideinfo.iResultPointer; + pEscapeSequenceInfo = pHcr->nonPcwSideinfo.pEscapeSequenceInfo; + codewordOffset = pHcr->nonPcwSideinfo.codewordOffset; + pSta = pHcr->nonPcwSideinfo.pSta; + + escapeWord = pEscapeSequenceInfo[codewordOffset] & MASK_ESCAPE_WORD; + escapePrefixDown = + (pEscapeSequenceInfo[codewordOffset] & MASK_ESCAPE_PREFIX_DOWN) >> + LSB_ESCAPE_PREFIX_DOWN; + + /* decode escape word */ + for (; pRemainingBitsInSegment[segmentOffset] > 0; + pRemainingBitsInSegment[segmentOffset] -= 1) { + carryBit = HcrGetABitFromBitstream( + bs, pHcr->decInOut.bitstreamAnchor, &pLeftStartOfSegment[segmentOffset], + &pRightStartOfSegment[segmentOffset], readDirection); + + /* build escape word */ + escapeWord <<= + 1; /* left shift previous decoded part of escapeWord by on bit */ + escapeWord = escapeWord | carryBit; /* assemble escape word by bitwise or */ + + /* decrement counter for length of escape word because one more bit was + * decoded */ + escapePrefixDown -= 1; + + /* store updated escapePrefixDown */ + pEscapeSequenceInfo[codewordOffset] &= + ~MASK_ESCAPE_PREFIX_DOWN; /* delete old escapePrefixDown */ + escapePrefixDown <<= LSB_ESCAPE_PREFIX_DOWN; /* shift to correct position */ + pEscapeSequenceInfo[codewordOffset] |= + escapePrefixDown; /* insert new escapePrefixDown */ + escapePrefixDown >>= LSB_ESCAPE_PREFIX_DOWN; /* shift back */ + + /* store updated escapeWord */ + pEscapeSequenceInfo[codewordOffset] &= + ~MASK_ESCAPE_WORD; /* delete old escapeWord */ + pEscapeSequenceInfo[codewordOffset] |= + escapeWord; /* insert new escapeWord */ + + if (escapePrefixDown == 0) { + pRemainingBitsInSegment[segmentOffset] -= 1; /* last reinitialzation of + for loop counter (see + above) is done here */ + + /* escape sequence decoded. Assemble escape-line and replace original line + */ + + /* step 0 */ + /* derive sign */ + iQSC = iResultPointer[codewordOffset]; + sign = (pResultBase[iQSC] >= (FIXP_DBL)0) + ? 1 + : -1; /* get sign of escape value 16 */ + + /* step 1 */ + /* get escapePrefixUp */ + escapePrefixUp = + (pEscapeSequenceInfo[codewordOffset] & MASK_ESCAPE_PREFIX_UP) >> + LSB_ESCAPE_PREFIX_UP; + + /* step 2 */ + /* calculate escape value */ + pResultBase[iQSC] = + (FIXP_DBL)(sign * (((INT)1 << escapePrefixUp) + (INT)escapeWord)); + + /* get both flags from sideinfo (flags are not shifted to the + * lsb-position) */ + flagA = pEscapeSequenceInfo[codewordOffset] & MASK_FLAG_A; + flagB = pEscapeSequenceInfo[codewordOffset] & MASK_FLAG_B; + + /* step 3 */ + /* clear the whole escape sideinfo word */ + pEscapeSequenceInfo[codewordOffset] = 0; + + /* change state in dependence of flag flagB */ + if (flagA != 0) { + /* first escape sequence decoded; previous decoded 16 has been replaced + * by valid line */ + + /* clear flagA in sideinfo word because this escape sequence has already + * beed decoded */ + pEscapeSequenceInfo[codewordOffset] &= ~MASK_FLAG_A; + + if (flagB == 0) { + ClearBitFromBitfield(&(pHcr->nonPcwSideinfo.pState), segmentOffset, + pCodewordBitfield); /* clear a bit in bitfield + and switch off + statemachine */ + } else { + /* updated pointer to next and last 16 */ + iQSC++; + iResultPointer[codewordOffset] = iQSC; + + /* change state */ + pSta[codewordOffset] = BODY_SIGN_ESC__ESC_PREFIX; + pHcr->nonPcwSideinfo.pState = + aStateConstant2State[pSta[codewordOffset]]; /* get state from + separate array of + cw-sideinfo */ + } + } else { + ClearBitFromBitfield( + &(pHcr->nonPcwSideinfo.pState), segmentOffset, + pCodewordBitfield); /* clear a bit in bitfield and switch off + statemachine */ + } + break; + } + } + + if (pRemainingBitsInSegment[segmentOffset] <= 0) { + ClearBitFromBitfield(&(pHcr->nonPcwSideinfo.pState), segmentOffset, + pSegmentBitfield); /* clear a bit in bitfield and + switch off statemachine */ + + if (pRemainingBitsInSegment[segmentOffset] < 0) { + pHcr->decInOut.errorLog |= STATE_ERROR_BODY_SIGN_ESC__ESC_WORD; + return BODY_SIGN_ESC__ESC_WORD; + } + } + + return STOP_THIS_STATE; +} -- cgit v1.2.3