mirror of
https://github.com/mstorsjo/fdk-aac.git
synced 2025-02-18 20:20:35 +01:00
- Update disclaimer in all source files. - Increment library version in each FDK sub-module. Bug 9428126 Change-Id: I490b96d4ee472246b01483202b0bb4f1e9c2a5d7
1216 lines
47 KiB
C++
1216 lines
47 KiB
C++
|
|
/* -----------------------------------------------------------------------------------------------------------
|
|
Software License for The Fraunhofer FDK AAC Codec Library for Android
|
|
|
|
© Copyright 1995 - 2013 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
|
|
----------------------------------------------------------------------------------------------------------- */
|
|
|
|
/*!
|
|
\file
|
|
\brief RVLC Decoder
|
|
\author Robert Weidner
|
|
*/
|
|
|
|
#include "rvlc.h"
|
|
|
|
|
|
#include "block.h"
|
|
|
|
#include "aac_rom.h"
|
|
#include "rvlcbit.h"
|
|
#include "rvlcconceal.h"
|
|
#include "aacdec_hcr.h"
|
|
|
|
/*---------------------------------------------------------------------------------------------
|
|
function: rvlcInit
|
|
|
|
description: init RVLC by data from channelinfo, which was decoded previously and
|
|
set up pointers
|
|
-----------------------------------------------------------------------------------------------
|
|
input: - pointer rvlc structure
|
|
- pointer channel info structure
|
|
- pointer bitstream structure
|
|
-----------------------------------------------------------------------------------------------
|
|
return: -
|
|
-------------------------------------------------------------------------------------------- */
|
|
|
|
static
|
|
void rvlcInit (CErRvlcInfo *pRvlc,
|
|
CAacDecoderChannelInfo *pAacDecoderChannelInfo,
|
|
HANDLE_FDK_BITSTREAM bs)
|
|
{
|
|
/* RVLC common initialization part 2 of 2 */
|
|
SHORT *pScfEsc = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfEsc;
|
|
SHORT *pScfFwd = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd;
|
|
SHORT *pScfBwd = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd;
|
|
SHORT *pScaleFactor = pAacDecoderChannelInfo->pDynData->aScaleFactor;
|
|
int bnds;
|
|
|
|
pAacDecoderChannelInfo->pDynData->specificTo.aac.rvlcIntensityUsed = 0;
|
|
|
|
pRvlc->numDecodedEscapeWordsEsc = 0;
|
|
pRvlc->numDecodedEscapeWordsFwd = 0;
|
|
pRvlc->numDecodedEscapeWordsBwd = 0;
|
|
|
|
pRvlc->intensity_used = 0;
|
|
pRvlc->errorLogRvlc = 0;
|
|
|
|
pRvlc->conceal_max = CONCEAL_MAX_INIT;
|
|
pRvlc->conceal_min = CONCEAL_MIN_INIT;
|
|
|
|
pRvlc->conceal_max_esc = CONCEAL_MAX_INIT;
|
|
pRvlc->conceal_min_esc = CONCEAL_MIN_INIT;
|
|
|
|
pRvlc->pHuffTreeRvlcEscape = aHuffTreeRvlcEscape;
|
|
pRvlc->pHuffTreeRvlCodewds = aHuffTreeRvlCodewds;
|
|
|
|
/* init scf arrays (for savety (in case of there are only zero codebooks)) */
|
|
for (bnds = 0; bnds < RVLC_MAX_SFB; bnds++) {
|
|
pScfFwd[bnds] = 0;
|
|
pScfBwd[bnds] = 0;
|
|
pScfEsc[bnds] = 0;
|
|
pScaleFactor[bnds] = 0;
|
|
}
|
|
|
|
/* set base bitstream ptr to the RVL-coded part (start of RVLC data (ESC 2)) */
|
|
FDKsyncCache (bs);
|
|
|
|
pRvlc->bitstreamIndexRvlFwd = FDKgetBitCnt(bs); /* first bit within RVL coded block as start address for forward decoding */
|
|
pRvlc->bitstreamIndexRvlBwd = FDKgetBitCnt(bs) + pRvlc->length_of_rvlc_sf - 1; /* last bit within RVL coded block as start address for backward decoding */
|
|
|
|
/* skip RVLC-bitstream-part -- pointing now to escapes (if present) or to TNS data (if present) */
|
|
FDKpushFor (bs, pRvlc->length_of_rvlc_sf);
|
|
|
|
if ( pRvlc->sf_escapes_present != 0 ) {
|
|
|
|
/* locate internal bitstream ptr at escapes (which is the second part) */
|
|
FDKsyncCache (bs);
|
|
pRvlc->bitstreamIndexEsc = FDKgetBitCnt(bs);
|
|
|
|
/* skip escapeRVLC-bitstream-part -- pointing to TNS data (if present) to make decoder continue */
|
|
/* decoding of RVLC should work despite this second pushFor during initialization because */
|
|
/* bitstream initialization is valid for both ESC2 data parts (RVL-coded values and ESC-coded values) */
|
|
FDKpushFor (bs, pRvlc->length_of_rvlc_escapes);
|
|
}
|
|
|
|
#if VERBOSE_RVLC_INIT
|
|
DebugOutputInit(pRvlc,pAacDecoderChannelInfo);
|
|
#endif
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------------------------
|
|
function: rvlcCheckIntensityCb
|
|
|
|
description: Check if a intensity codebook is used in the current channel.
|
|
-----------------------------------------------------------------------------------------------
|
|
input: - pointer rvlc structure
|
|
- pointer channel info structure
|
|
-----------------------------------------------------------------------------------------------
|
|
output: - intensity_used: 0 no intensity codebook is used
|
|
1 intensity codebook is used
|
|
-----------------------------------------------------------------------------------------------
|
|
return: -
|
|
-------------------------------------------------------------------------------------------- */
|
|
|
|
static
|
|
void rvlcCheckIntensityCb (CErRvlcInfo *pRvlc,
|
|
CAacDecoderChannelInfo *pAacDecoderChannelInfo)
|
|
{
|
|
int group, band, bnds;
|
|
|
|
pRvlc->intensity_used = 0;
|
|
|
|
for (group=0; group < pRvlc->numWindowGroups; group++) {
|
|
for (band=0; band < pRvlc->maxSfbTransmitted; band++) {
|
|
bnds = 16*group+band;
|
|
if ( (pAacDecoderChannelInfo->pDynData->aCodeBook[bnds] == INTENSITY_HCB) || (pAacDecoderChannelInfo->pDynData->aCodeBook[bnds] == INTENSITY_HCB2) ) {
|
|
pRvlc->intensity_used = 1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------------------------
|
|
function: rvlcDecodeEscapeWord
|
|
|
|
description: Decode a huffman coded RVLC Escape-word. This value is part of a DPCM coded
|
|
scalefactor.
|
|
-----------------------------------------------------------------------------------------------
|
|
input: - pointer rvlc structure
|
|
-----------------------------------------------------------------------------------------------
|
|
return: - a single RVLC-Escape value which had to be applied to a DPCM value (which
|
|
has a absolute value of 7)
|
|
-------------------------------------------------------------------------------------------- */
|
|
|
|
static
|
|
SCHAR rvlcDecodeEscapeWord (CErRvlcInfo *pRvlc,
|
|
HANDLE_FDK_BITSTREAM bs)
|
|
{
|
|
int i;
|
|
SCHAR value;
|
|
UCHAR carryBit;
|
|
UINT treeNode;
|
|
UINT branchValue;
|
|
UINT branchNode;
|
|
|
|
USHORT* pBitstreamIndexEsc;
|
|
const UINT* pEscTree;
|
|
|
|
pEscTree = pRvlc->pHuffTreeRvlcEscape;
|
|
pBitstreamIndexEsc = &(pRvlc->bitstreamIndexEsc);
|
|
treeNode = *pEscTree; /* init at starting node */
|
|
|
|
for (i=MAX_LEN_RVLC_ESCAPE_WORD-1; i >= 0; i--) {
|
|
carryBit = rvlcReadBitFromBitstream(bs, /* get next bit */
|
|
pBitstreamIndexEsc,
|
|
FWD);
|
|
|
|
CarryBitToBranchValue(carryBit, /* huffman decoding, do a single step in huffman decoding tree */
|
|
treeNode,
|
|
&branchValue,
|
|
&branchNode);
|
|
|
|
if ((branchNode & TEST_BIT_10) == TEST_BIT_10) { /* test bit 10 ; if set --> a RVLC-escape-word is completely decoded */
|
|
value = (SCHAR) branchNode & CLR_BIT_10;
|
|
pRvlc->length_of_rvlc_escapes -= (MAX_LEN_RVLC_ESCAPE_WORD - i);
|
|
|
|
if (pRvlc->length_of_rvlc_escapes < 0) {
|
|
pRvlc->errorLogRvlc |= RVLC_ERROR_ALL_ESCAPE_WORDS_INVALID;
|
|
value = -1;
|
|
}
|
|
|
|
return value;
|
|
}
|
|
else {
|
|
treeNode = *(pEscTree + branchValue); /* update treeNode for further step in decoding tree */
|
|
}
|
|
}
|
|
|
|
pRvlc->errorLogRvlc |= RVLC_ERROR_ALL_ESCAPE_WORDS_INVALID;
|
|
|
|
return -1; /* should not be reached */
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------------------------
|
|
function: rvlcDecodeEscapes
|
|
|
|
description: Decodes all huffman coded RVLC Escape Words.
|
|
Here a difference to the pseudo-code-implementation from standard can be
|
|
found. A while loop (and not two nested for loops) is used for two reasons:
|
|
|
|
1. The plain huffman encoded escapes are decoded before the RVL-coded
|
|
scalefactors. Therefore the escapes are present in the second step
|
|
when decoding the RVL-coded-scalefactor values in forward and
|
|
backward direction.
|
|
|
|
When the RVL-coded scalefactors are decoded and there a escape is
|
|
needed, then it is just taken out of the array in ascending order.
|
|
|
|
2. It's faster.
|
|
-----------------------------------------------------------------------------------------------
|
|
input: - pointer rvlc structure
|
|
- handle to FDK bitstream
|
|
-----------------------------------------------------------------------------------------------
|
|
return: - 0 ok the decoded escapes seem to be valid
|
|
- 1 error there was a error detected during decoding escapes
|
|
--> all escapes are invalid
|
|
-------------------------------------------------------------------------------------------- */
|
|
|
|
static
|
|
void rvlcDecodeEscapes (CErRvlcInfo *pRvlc,
|
|
SHORT *pEsc,
|
|
HANDLE_FDK_BITSTREAM bs)
|
|
{
|
|
SCHAR escWord;
|
|
SCHAR escCnt=0;
|
|
SHORT* pEscBitCntSum;
|
|
|
|
pEscBitCntSum = &(pRvlc->length_of_rvlc_escapes);
|
|
|
|
/* Decode all RVLC-Escape words with a plain Huffman-Decoder */
|
|
while ( *pEscBitCntSum > 0 ) {
|
|
escWord = rvlcDecodeEscapeWord(pRvlc, bs);
|
|
|
|
if (escWord >= 0) {
|
|
|
|
pEsc[escCnt] = escWord;
|
|
escCnt++;
|
|
}
|
|
else {
|
|
pRvlc->errorLogRvlc |= RVLC_ERROR_ALL_ESCAPE_WORDS_INVALID;
|
|
pRvlc->numDecodedEscapeWordsEsc = escCnt;
|
|
|
|
return;
|
|
}
|
|
} /* all RVLC escapes decoded */
|
|
|
|
pRvlc->numDecodedEscapeWordsEsc = escCnt;
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------------------------
|
|
function: decodeRVLCodeword
|
|
|
|
description: Decodes a RVL-coded dpcm-word (-part).
|
|
-----------------------------------------------------------------------------------------------
|
|
input: - FDK bitstream handle
|
|
- pointer rvlc structure
|
|
-----------------------------------------------------------------------------------------------
|
|
return: - a dpcm value which is within range [0,1,..,14] in case of no errors.
|
|
The offset of 7 must be subtracted to get a valid dpcm scalefactor value.
|
|
In case of errors a forbidden codeword is detected --> returning -1
|
|
-------------------------------------------------------------------------------------------- */
|
|
|
|
SCHAR decodeRVLCodeword (HANDLE_FDK_BITSTREAM bs, CErRvlcInfo *pRvlc)
|
|
{
|
|
int i;
|
|
SCHAR value;
|
|
UCHAR carryBit;
|
|
UINT branchValue;
|
|
UINT branchNode;
|
|
|
|
const UINT *pRvlCodeTree = pRvlc->pHuffTreeRvlCodewds;
|
|
UCHAR direction = pRvlc->direction;
|
|
USHORT *pBitstrIndxRvl = pRvlc->pBitstrIndxRvl_RVL;
|
|
UINT treeNode = *pRvlCodeTree;
|
|
|
|
for (i=MAX_LEN_RVLC_CODE_WORD-1; i >= 0; i--) {
|
|
carryBit = rvlcReadBitFromBitstream(bs, /* get next bit */
|
|
pBitstrIndxRvl,
|
|
direction);
|
|
|
|
CarryBitToBranchValue(carryBit, /* huffman decoding, do a single step in huffman decoding tree */
|
|
treeNode,
|
|
&branchValue,
|
|
&branchNode);
|
|
|
|
if ((branchNode & TEST_BIT_10) == TEST_BIT_10) { /* test bit 10 ; if set --> a RVLC-codeword is completely decoded */
|
|
value = (SCHAR) (branchNode & CLR_BIT_10);
|
|
*pRvlc->pRvlBitCnt_RVL -= (MAX_LEN_RVLC_CODE_WORD - i);
|
|
|
|
/* check available bits for decoding */
|
|
if (*pRvlc->pRvlBitCnt_RVL < 0) {
|
|
if (direction == FWD) {
|
|
pRvlc->errorLogRvlc |= RVLC_ERROR_RVL_SUM_BIT_COUNTER_BELOW_ZERO_FWD; }
|
|
else {
|
|
pRvlc->errorLogRvlc |= RVLC_ERROR_RVL_SUM_BIT_COUNTER_BELOW_ZERO_BWD; }
|
|
value = -1; /* signalize an error in return value, because too many bits was decoded */
|
|
}
|
|
|
|
/* check max value of dpcm value */
|
|
if (value > MAX_ALLOWED_DPCM_INDEX) {
|
|
if (direction == FWD) {
|
|
pRvlc->errorLogRvlc |= RVLC_ERROR_FORBIDDEN_CW_DETECTED_FWD;
|
|
}
|
|
else {
|
|
pRvlc->errorLogRvlc |= RVLC_ERROR_FORBIDDEN_CW_DETECTED_BWD;
|
|
}
|
|
value = -1; /* signalize an error in return value, because a forbidden cw was detected*/
|
|
}
|
|
|
|
return value; /* return a dpcm value with offset +7 or an error status */
|
|
}
|
|
else {
|
|
treeNode = *(pRvlCodeTree + branchValue); /* update treeNode for further step in decoding tree */
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------------------------
|
|
function: rvlcDecodeForward
|
|
|
|
description: Decode RVL-coded codewords in forward direction.
|
|
-----------------------------------------------------------------------------------------------
|
|
input: - pointer rvlc structure
|
|
- pointer channel info structure
|
|
- handle to FDK bitstream
|
|
-----------------------------------------------------------------------------------------------
|
|
return: -
|
|
-------------------------------------------------------------------------------------------- */
|
|
|
|
static
|
|
void rvlcDecodeForward (CErRvlcInfo *pRvlc,
|
|
CAacDecoderChannelInfo *pAacDecoderChannelInfo,
|
|
HANDLE_FDK_BITSTREAM bs)
|
|
{
|
|
int band = 0;
|
|
int group = 0;
|
|
int bnds = 0;
|
|
|
|
SHORT dpcm;
|
|
|
|
SHORT factor = pAacDecoderChannelInfo->pDynData->RawDataInfo.GlobalGain - SF_OFFSET;
|
|
SHORT position = - SF_OFFSET;
|
|
SHORT noisenrg = pAacDecoderChannelInfo->pDynData->RawDataInfo.GlobalGain - SF_OFFSET - 90 - 256;
|
|
|
|
SHORT* pScfFwd = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd;
|
|
SHORT* pScfEsc = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfEsc;
|
|
UCHAR* pEscFwdCnt = &(pRvlc->numDecodedEscapeWordsFwd);
|
|
|
|
pRvlc->pRvlBitCnt_RVL = &(pRvlc->length_of_rvlc_sf_fwd);
|
|
pRvlc->pBitstrIndxRvl_RVL = &(pRvlc->bitstreamIndexRvlFwd);
|
|
|
|
*pEscFwdCnt = 0;
|
|
pRvlc->direction = FWD;
|
|
pRvlc->noise_used = 0;
|
|
pRvlc->sf_used = 0;
|
|
pRvlc->lastScf = 0;
|
|
pRvlc->lastNrg = 0;
|
|
pRvlc->lastIs = 0;
|
|
|
|
rvlcCheckIntensityCb(pRvlc,pAacDecoderChannelInfo);
|
|
|
|
/* main loop fwd long */
|
|
for (group=0; group < pRvlc->numWindowGroups; group++) {
|
|
for (band=0; band < pRvlc->maxSfbTransmitted; band++) {
|
|
bnds = 16*group+band;
|
|
|
|
switch (pAacDecoderChannelInfo->pDynData->aCodeBook[bnds]) {
|
|
|
|
case ZERO_HCB :
|
|
pScfFwd[bnds] = 0;
|
|
break;
|
|
|
|
case INTENSITY_HCB2 :
|
|
case INTENSITY_HCB :
|
|
/* store dpcm_is_position */
|
|
dpcm = decodeRVLCodeword(bs, pRvlc);
|
|
if ( dpcm < 0 ) {
|
|
pRvlc->conceal_max = bnds;
|
|
return;
|
|
}
|
|
dpcm -= TABLE_OFFSET;
|
|
if ((dpcm == MIN_RVL) || (dpcm == MAX_RVL)) {
|
|
if (pRvlc->length_of_rvlc_escapes) {
|
|
pRvlc->conceal_max = bnds;
|
|
return;
|
|
}
|
|
else {
|
|
if (dpcm == MIN_RVL) {
|
|
dpcm -= *pScfEsc++;
|
|
}
|
|
else {
|
|
dpcm += *pScfEsc++;
|
|
}
|
|
(*pEscFwdCnt)++;
|
|
if (pRvlc->conceal_max_esc == CONCEAL_MAX_INIT) {
|
|
pRvlc->conceal_max_esc = bnds;
|
|
}
|
|
}
|
|
}
|
|
position += dpcm;
|
|
pScfFwd[bnds] = position;
|
|
pRvlc->lastIs = position;
|
|
break;
|
|
|
|
case NOISE_HCB :
|
|
if (pRvlc->noise_used == 0) {
|
|
pRvlc->noise_used = 1;
|
|
pRvlc->first_noise_band = bnds;
|
|
noisenrg += pRvlc->dpcm_noise_nrg;
|
|
pScfFwd[bnds] = 100 + noisenrg;
|
|
pRvlc->lastNrg = noisenrg;
|
|
}
|
|
else {
|
|
dpcm = decodeRVLCodeword(bs, pRvlc);
|
|
if ( dpcm < 0 ) {
|
|
pRvlc->conceal_max = bnds;
|
|
return;
|
|
}
|
|
dpcm -= TABLE_OFFSET;
|
|
if ((dpcm == MIN_RVL) || (dpcm == MAX_RVL)) {
|
|
if (pRvlc->length_of_rvlc_escapes) {
|
|
pRvlc->conceal_max = bnds;
|
|
return;
|
|
}
|
|
else {
|
|
if (dpcm == MIN_RVL) {
|
|
dpcm -= *pScfEsc++;
|
|
}
|
|
else {
|
|
dpcm += *pScfEsc++;
|
|
}
|
|
(*pEscFwdCnt)++;
|
|
if (pRvlc->conceal_max_esc == CONCEAL_MAX_INIT) {
|
|
pRvlc->conceal_max_esc = bnds;
|
|
}
|
|
}
|
|
}
|
|
noisenrg += dpcm;
|
|
pScfFwd[bnds] = 100 + noisenrg;
|
|
pRvlc->lastNrg = noisenrg;
|
|
}
|
|
pAacDecoderChannelInfo->data.aac.PnsData.pnsUsed[bnds] = 1;
|
|
break ;
|
|
|
|
default :
|
|
pRvlc->sf_used = 1;
|
|
dpcm = decodeRVLCodeword(bs, pRvlc);
|
|
if ( dpcm < 0 ) {
|
|
pRvlc->conceal_max = bnds;
|
|
return;
|
|
}
|
|
dpcm -= TABLE_OFFSET;
|
|
if ((dpcm == MIN_RVL) || (dpcm == MAX_RVL)) {
|
|
if (pRvlc->length_of_rvlc_escapes) {
|
|
pRvlc->conceal_max = bnds;
|
|
return;
|
|
}
|
|
else {
|
|
if (dpcm == MIN_RVL) {
|
|
dpcm -= *pScfEsc++; }
|
|
else {
|
|
dpcm += *pScfEsc++;
|
|
}
|
|
(*pEscFwdCnt)++;
|
|
if (pRvlc->conceal_max_esc == CONCEAL_MAX_INIT) {
|
|
pRvlc->conceal_max_esc = bnds;
|
|
}
|
|
}
|
|
}
|
|
factor += dpcm;
|
|
pScfFwd[bnds] = factor;
|
|
pRvlc->lastScf = factor;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* postfetch fwd long */
|
|
if (pRvlc->intensity_used) {
|
|
dpcm = decodeRVLCodeword(bs, pRvlc); /* dpcm_is_last_position */
|
|
if ( dpcm < 0 ) {
|
|
pRvlc->conceal_max = bnds;
|
|
return;
|
|
}
|
|
dpcm -= TABLE_OFFSET;
|
|
if ((dpcm == MIN_RVL) || (dpcm == MAX_RVL)) {
|
|
if (pRvlc->length_of_rvlc_escapes) {
|
|
pRvlc->conceal_max = bnds;
|
|
return;
|
|
}
|
|
else {
|
|
if (dpcm == MIN_RVL) {
|
|
dpcm -= *pScfEsc++;
|
|
}
|
|
else {
|
|
dpcm += *pScfEsc++;
|
|
}
|
|
(*pEscFwdCnt)++;
|
|
if (pRvlc->conceal_max_esc == CONCEAL_MAX_INIT) {
|
|
pRvlc->conceal_max_esc = bnds;
|
|
}
|
|
}
|
|
}
|
|
pRvlc->dpcm_is_last_position = dpcm;
|
|
}
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------------------------
|
|
function: rvlcDecodeBackward
|
|
|
|
description: Decode RVL-coded codewords in backward direction.
|
|
-----------------------------------------------------------------------------------------------
|
|
input: - pointer rvlc structure
|
|
- pointer channel info structure
|
|
- handle FDK bitstream
|
|
-----------------------------------------------------------------------------------------------
|
|
return: -
|
|
-------------------------------------------------------------------------------------------- */
|
|
|
|
static
|
|
void rvlcDecodeBackward (CErRvlcInfo *pRvlc,
|
|
CAacDecoderChannelInfo *pAacDecoderChannelInfo,
|
|
HANDLE_FDK_BITSTREAM bs)
|
|
{
|
|
SHORT band, group, dpcm, offset;
|
|
SHORT bnds = pRvlc->maxSfbTransmitted-1;
|
|
|
|
SHORT factor = pRvlc->rev_global_gain - SF_OFFSET;
|
|
SHORT position = pRvlc->dpcm_is_last_position - SF_OFFSET;
|
|
SHORT noisenrg = pRvlc->rev_global_gain + pRvlc->dpcm_noise_last_position - SF_OFFSET - 90 - 256;
|
|
|
|
SHORT *pScfBwd = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd;
|
|
SHORT *pScfEsc = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfEsc;
|
|
UCHAR *pEscEscCnt = &(pRvlc->numDecodedEscapeWordsEsc);
|
|
UCHAR *pEscBwdCnt = &(pRvlc->numDecodedEscapeWordsBwd);
|
|
|
|
pRvlc->pRvlBitCnt_RVL = &(pRvlc->length_of_rvlc_sf_bwd);
|
|
pRvlc->pBitstrIndxRvl_RVL = &(pRvlc->bitstreamIndexRvlBwd);
|
|
|
|
*pEscBwdCnt = 0;
|
|
pRvlc->direction = BWD;
|
|
pScfEsc += *pEscEscCnt - 1; /* set pScfEsc to last entry */
|
|
pRvlc->firstScf = 0;
|
|
pRvlc->firstNrg = 0;
|
|
pRvlc->firstIs = 0;
|
|
|
|
/* prefetch long BWD */
|
|
if (pRvlc->intensity_used) {
|
|
dpcm = decodeRVLCodeword(bs, pRvlc); /* dpcm_is_last_position */
|
|
if ( dpcm < 0 ) {
|
|
pRvlc->dpcm_is_last_position = 0;
|
|
pRvlc->conceal_min = bnds;
|
|
return;
|
|
}
|
|
dpcm -= TABLE_OFFSET;
|
|
if ((dpcm == MIN_RVL) || (dpcm == MAX_RVL)) {
|
|
if (pRvlc->length_of_rvlc_escapes) {
|
|
pRvlc->conceal_min = bnds;
|
|
return;
|
|
}
|
|
else {
|
|
if (dpcm == MIN_RVL) {
|
|
dpcm -= *pScfEsc--;
|
|
}
|
|
else {
|
|
dpcm += *pScfEsc--;
|
|
}
|
|
(*pEscBwdCnt)++;
|
|
if (pRvlc->conceal_min_esc == CONCEAL_MIN_INIT) {
|
|
pRvlc->conceal_min_esc = bnds;
|
|
}
|
|
}
|
|
}
|
|
pRvlc->dpcm_is_last_position = dpcm;
|
|
}
|
|
|
|
/* main loop long BWD */
|
|
for (group=pRvlc->numWindowGroups-1; group >= 0; group--) {
|
|
for (band=pRvlc->maxSfbTransmitted-1; band >= 0; band--) {
|
|
bnds = 16*group+band;
|
|
if ((band == 0) && (pRvlc->numWindowGroups != 1))
|
|
offset = 16 - pRvlc->maxSfbTransmitted + 1;
|
|
else
|
|
offset = 1;
|
|
|
|
switch (pAacDecoderChannelInfo->pDynData->aCodeBook[bnds]) {
|
|
|
|
case ZERO_HCB :
|
|
pScfBwd[bnds] = 0;
|
|
break;
|
|
|
|
case INTENSITY_HCB2 :
|
|
case INTENSITY_HCB :
|
|
/* store dpcm_is_position */
|
|
dpcm = decodeRVLCodeword(bs, pRvlc);
|
|
if ( dpcm < 0 ) {
|
|
pScfBwd[bnds] = position;
|
|
pRvlc->conceal_min = FDKmax(0,bnds-offset);
|
|
return;
|
|
}
|
|
dpcm -= TABLE_OFFSET;
|
|
if ((dpcm == MIN_RVL) || (dpcm == MAX_RVL)) {
|
|
if (pRvlc->length_of_rvlc_escapes) {
|
|
pScfBwd[bnds] = position;
|
|
pRvlc->conceal_min = FDKmax(0,bnds-offset);
|
|
return;
|
|
}
|
|
else {
|
|
if (dpcm == MIN_RVL) {
|
|
dpcm -= *pScfEsc--;
|
|
}
|
|
else {
|
|
dpcm += *pScfEsc--;
|
|
}
|
|
(*pEscBwdCnt)++;
|
|
if (pRvlc->conceal_min_esc == CONCEAL_MIN_INIT) {
|
|
pRvlc->conceal_min_esc = FDKmax(0,bnds-offset);
|
|
}
|
|
}
|
|
}
|
|
pScfBwd[bnds] = position;
|
|
position -= dpcm;
|
|
pRvlc->firstIs = position;
|
|
break;
|
|
|
|
case NOISE_HCB :
|
|
if ( bnds == pRvlc->first_noise_band ) {
|
|
pScfBwd[bnds] = pRvlc->dpcm_noise_nrg + pAacDecoderChannelInfo->pDynData->RawDataInfo.GlobalGain - SF_OFFSET - 90 - 256;
|
|
pRvlc->firstNrg = pScfBwd[bnds];
|
|
}
|
|
else {
|
|
dpcm = decodeRVLCodeword(bs, pRvlc);
|
|
if ( dpcm < 0 ) {
|
|
pScfBwd[bnds] = noisenrg;
|
|
pRvlc->conceal_min = FDKmax(0,bnds-offset);
|
|
return;
|
|
}
|
|
dpcm -= TABLE_OFFSET;
|
|
if ((dpcm == MIN_RVL) || (dpcm == MAX_RVL)) {
|
|
if (pRvlc->length_of_rvlc_escapes) {
|
|
pScfBwd[bnds] = noisenrg;
|
|
pRvlc->conceal_min = FDKmax(0,bnds-offset);
|
|
return;
|
|
}
|
|
else {
|
|
if (dpcm == MIN_RVL) {
|
|
dpcm -= *pScfEsc--;
|
|
}
|
|
else {
|
|
dpcm += *pScfEsc--;
|
|
}
|
|
(*pEscBwdCnt)++;
|
|
if (pRvlc->conceal_min_esc == CONCEAL_MIN_INIT) {
|
|
pRvlc->conceal_min_esc = FDKmax(0,bnds-offset);
|
|
}
|
|
}
|
|
}
|
|
pScfBwd[bnds] = noisenrg;
|
|
noisenrg -= dpcm;
|
|
pRvlc->firstNrg = noisenrg;
|
|
}
|
|
break ;
|
|
|
|
default :
|
|
dpcm = decodeRVLCodeword(bs, pRvlc);
|
|
if ( dpcm < 0 ) {
|
|
pScfBwd[bnds] = factor;
|
|
pRvlc->conceal_min = FDKmax(0,bnds-offset);
|
|
return;
|
|
}
|
|
dpcm -= TABLE_OFFSET;
|
|
if ((dpcm == MIN_RVL) || (dpcm == MAX_RVL)) {
|
|
if (pRvlc->length_of_rvlc_escapes) {
|
|
pScfBwd[bnds] = factor;
|
|
pRvlc->conceal_min = FDKmax(0,bnds-offset);
|
|
return;
|
|
}
|
|
else {
|
|
if (dpcm == MIN_RVL) {
|
|
dpcm -= *pScfEsc--;
|
|
}
|
|
else {
|
|
dpcm += *pScfEsc--;
|
|
}
|
|
(*pEscBwdCnt)++;
|
|
if (pRvlc->conceal_min_esc == CONCEAL_MIN_INIT) {
|
|
pRvlc->conceal_min_esc = FDKmax(0,bnds-offset);
|
|
}
|
|
}
|
|
}
|
|
pScfBwd[bnds] = factor;
|
|
factor -= dpcm;
|
|
pRvlc->firstScf = factor;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------------------------
|
|
function: rvlcFinalErrorDetection
|
|
|
|
description: Call RVLC concealment if error was detected in decoding process
|
|
-----------------------------------------------------------------------------------------------
|
|
input: - pointer rvlc structure
|
|
- pointer channel info structure
|
|
-----------------------------------------------------------------------------------------------
|
|
return: -
|
|
-------------------------------------------------------------------------------------------- */
|
|
|
|
static
|
|
void rvlcFinalErrorDetection (CAacDecoderChannelInfo *pAacDecoderChannelInfo,
|
|
CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo)
|
|
{
|
|
CErRvlcInfo *pRvlc = &pAacDecoderChannelInfo->pComData->overlay.aac.erRvlcInfo;
|
|
UCHAR ErrorStatusComplete = 0;
|
|
UCHAR ErrorStatusLengthFwd = 0;
|
|
UCHAR ErrorStatusLengthBwd = 0;
|
|
UCHAR ErrorStatusLengthEscapes = 0;
|
|
UCHAR ErrorStatusFirstScf = 0;
|
|
UCHAR ErrorStatusLastScf = 0;
|
|
UCHAR ErrorStatusFirstNrg = 0;
|
|
UCHAR ErrorStatusLastNrg = 0;
|
|
UCHAR ErrorStatusFirstIs = 0;
|
|
UCHAR ErrorStatusLastIs = 0;
|
|
UCHAR ErrorStatusForbiddenCwFwd = 0;
|
|
UCHAR ErrorStatusForbiddenCwBwd = 0;
|
|
UCHAR ErrorStatusNumEscapesFwd = 0;
|
|
UCHAR ErrorStatusNumEscapesBwd = 0;
|
|
UCHAR ConcealStatus = 1;
|
|
UCHAR currentBlockType; /* short: 0, not short: 1*/
|
|
|
|
#if VERBOSE_RVLC_OUTPUT
|
|
CHAR Strategy[60]="No";
|
|
SHORT conceal_max;
|
|
SHORT conceal_min;
|
|
#endif
|
|
|
|
pAacDecoderChannelInfo->pDynData->specificTo.aac.rvlcCurrentScaleFactorOK = 1;
|
|
|
|
/* invalid escape words, bit counter unequal zero, forbidden codeword detected */
|
|
if (pRvlc->errorLogRvlc & RVLC_ERROR_FORBIDDEN_CW_DETECTED_FWD)
|
|
ErrorStatusForbiddenCwFwd = 1;
|
|
|
|
if (pRvlc->errorLogRvlc & RVLC_ERROR_FORBIDDEN_CW_DETECTED_BWD)
|
|
ErrorStatusForbiddenCwBwd = 1;
|
|
|
|
/* bit counter forward unequal zero */
|
|
if (pRvlc->length_of_rvlc_sf_fwd)
|
|
ErrorStatusLengthFwd = 1;
|
|
|
|
/* bit counter backward unequal zero */
|
|
if (pRvlc->length_of_rvlc_sf_bwd)
|
|
ErrorStatusLengthBwd = 1;
|
|
|
|
/* bit counter escape sequences unequal zero */
|
|
if (pRvlc->sf_escapes_present)
|
|
if (pRvlc->length_of_rvlc_escapes)
|
|
ErrorStatusLengthEscapes = 1;
|
|
|
|
if (pRvlc->sf_used) {
|
|
/* first decoded scf does not match to global gain in backward direction */
|
|
if (pRvlc->firstScf != (pAacDecoderChannelInfo->pDynData->RawDataInfo.GlobalGain - SF_OFFSET) )
|
|
ErrorStatusFirstScf = 1;
|
|
|
|
/* last decoded scf does not match to rev global gain in forward direction */
|
|
if (pRvlc->lastScf != (pRvlc->rev_global_gain - SF_OFFSET) )
|
|
ErrorStatusLastScf = 1;
|
|
}
|
|
|
|
if (pRvlc->noise_used) {
|
|
/* first decoded nrg does not match to dpcm_noise_nrg in backward direction */
|
|
if (pRvlc->firstNrg != (pAacDecoderChannelInfo->pDynData->RawDataInfo.GlobalGain + pRvlc->dpcm_noise_nrg - SF_OFFSET -90 - 256) )
|
|
ErrorStatusFirstNrg = 1;
|
|
|
|
/* last decoded nrg does not match to dpcm_noise_last_position in forward direction */
|
|
if (pRvlc->lastNrg != (pRvlc->rev_global_gain + pRvlc->dpcm_noise_last_position - SF_OFFSET - 90 - 256) )
|
|
ErrorStatusLastNrg = 1;
|
|
}
|
|
|
|
if (pRvlc->intensity_used) {
|
|
/* first decoded is position does not match in backward direction */
|
|
if (pRvlc->firstIs != (-SF_OFFSET) )
|
|
ErrorStatusFirstIs = 1;
|
|
|
|
/* last decoded is position does not match in forward direction */
|
|
if (pRvlc->lastIs != (pRvlc->dpcm_is_last_position - SF_OFFSET) )
|
|
ErrorStatusLastIs = 1;
|
|
}
|
|
|
|
/* decoded escapes and used escapes in forward direction do not fit */
|
|
if ((pRvlc->numDecodedEscapeWordsFwd != pRvlc->numDecodedEscapeWordsEsc) && (pRvlc->conceal_max == CONCEAL_MAX_INIT)) {
|
|
ErrorStatusNumEscapesFwd = 1;
|
|
}
|
|
|
|
/* decoded escapes and used escapes in backward direction do not fit */
|
|
if ((pRvlc->numDecodedEscapeWordsBwd != pRvlc->numDecodedEscapeWordsEsc) && (pRvlc->conceal_min == CONCEAL_MIN_INIT)) {
|
|
ErrorStatusNumEscapesBwd = 1;
|
|
}
|
|
|
|
#if VERBOSE_RVLC_OUTPUT
|
|
conceal_max = pRvlc->conceal_max;
|
|
conceal_min = pRvlc->conceal_min;
|
|
#endif
|
|
|
|
if ( ErrorStatusLengthEscapes
|
|
|| (
|
|
( (pRvlc->conceal_max == CONCEAL_MAX_INIT)
|
|
&& (pRvlc->numDecodedEscapeWordsFwd != pRvlc->numDecodedEscapeWordsEsc)
|
|
&& (ErrorStatusLastScf || ErrorStatusLastNrg || ErrorStatusLastIs) )
|
|
|
|
&&
|
|
|
|
( (pRvlc->conceal_min == CONCEAL_MIN_INIT)
|
|
&& (pRvlc->numDecodedEscapeWordsBwd != pRvlc->numDecodedEscapeWordsEsc)
|
|
&& (ErrorStatusFirstScf || ErrorStatusFirstNrg || ErrorStatusFirstIs) )
|
|
)
|
|
|| ( (pRvlc->conceal_max == CONCEAL_MAX_INIT)
|
|
&& ((pRvlc->rev_global_gain - SF_OFFSET - pRvlc->lastScf) < -15)
|
|
)
|
|
|| ( (pRvlc->conceal_min == CONCEAL_MIN_INIT)
|
|
&& ((pAacDecoderChannelInfo->pDynData->RawDataInfo.GlobalGain - SF_OFFSET - pRvlc->firstScf) < -15)
|
|
)
|
|
) {
|
|
if ((pRvlc->conceal_max == CONCEAL_MAX_INIT) || (pRvlc->conceal_min == CONCEAL_MIN_INIT)) {
|
|
pRvlc->conceal_max = 0;
|
|
pRvlc->conceal_min = FDKmax(0, (pRvlc->numWindowGroups-1)*16+pRvlc->maxSfbTransmitted-1);
|
|
}
|
|
else {
|
|
pRvlc->conceal_max = FDKmin(pRvlc->conceal_max,pRvlc->conceal_max_esc);
|
|
pRvlc->conceal_min = FDKmax(pRvlc->conceal_min,pRvlc->conceal_min_esc);
|
|
}
|
|
}
|
|
|
|
ErrorStatusComplete = ErrorStatusLastScf || ErrorStatusFirstScf || ErrorStatusLastNrg || ErrorStatusFirstNrg
|
|
|| ErrorStatusLastIs || ErrorStatusFirstIs || ErrorStatusForbiddenCwFwd || ErrorStatusForbiddenCwBwd
|
|
|| ErrorStatusLengthFwd || ErrorStatusLengthBwd || ErrorStatusLengthEscapes || ErrorStatusNumEscapesFwd
|
|
|| ErrorStatusNumEscapesBwd;
|
|
|
|
currentBlockType = (GetWindowSequence(&pAacDecoderChannelInfo->icsInfo) == EightShortSequence) ? 0 : 1;
|
|
|
|
|
|
if (!ErrorStatusComplete) {
|
|
int band;
|
|
int group;
|
|
int bnds;
|
|
int lastSfbIndex;
|
|
|
|
lastSfbIndex = (pRvlc->numWindowGroups > 1) ? 16 : 64;
|
|
|
|
for (group=0; group < pRvlc->numWindowGroups; group++) {
|
|
for (band=0; band<pRvlc->maxSfbTransmitted; band++) {
|
|
bnds = 16*group+band;
|
|
pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousScaleFactor[bnds] = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds];
|
|
}
|
|
}
|
|
|
|
for (group=0; group < pRvlc->numWindowGroups; group++)
|
|
{
|
|
for (band=0; band<pRvlc->maxSfbTransmitted; band++) {
|
|
bnds = 16*group+band;
|
|
pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousCodebook[bnds] = pAacDecoderChannelInfo->pDynData->aCodeBook[bnds];
|
|
}
|
|
for (; band <lastSfbIndex; band++) {
|
|
bnds = 16*group+band;
|
|
FDK_ASSERT(bnds >= 0 && bnds < RVLC_MAX_SFB);
|
|
pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousCodebook[bnds] = ZERO_HCB;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
int band;
|
|
int group;
|
|
|
|
/* A single bit error was detected in decoding of dpcm values. It also could be an error with more bits in decoding
|
|
of escapes and dpcm values whereby an illegal codeword followed not directly after the corrupted bits but just
|
|
after decoding some more (wrong) scalefactors. Use the smaller scalefactor from forward decoding, backward decoding
|
|
and previous frame. */
|
|
if ( ((pRvlc->conceal_min != CONCEAL_MIN_INIT) || (pRvlc->conceal_max != CONCEAL_MAX_INIT)) && (pRvlc->conceal_min <= pRvlc->conceal_max)
|
|
&& (pAacDecoderStaticChannelInfo->concealmentInfo.rvlcPreviousBlockType == currentBlockType) && pAacDecoderStaticChannelInfo->concealmentInfo.rvlcPreviousScaleFactorOK
|
|
&& pRvlc->sf_concealment && ConcealStatus )
|
|
{
|
|
BidirectionalEstimation_UseScfOfPrevFrameAsReference (pAacDecoderChannelInfo, pAacDecoderStaticChannelInfo);
|
|
ConcealStatus=0;
|
|
#if VERBOSE_RVLC_OUTPUT
|
|
FDKstrcpy(Strategy,"Yes (BidirectionalEstimation_UseScfOfPrevFrameAsReference)");
|
|
#endif
|
|
}
|
|
|
|
/* A single bit error was detected in decoding of dpcm values. It also could be an error with more bits in decoding
|
|
of escapes and dpcm values whereby an illegal codeword followed not directly after the corrupted bits but just
|
|
after decoding some more (wrong) scalefactors. Use the smaller scalefactor from forward and backward decoding. */
|
|
if ( (pRvlc->conceal_min <= pRvlc->conceal_max) && ((pRvlc->conceal_min != CONCEAL_MIN_INIT) || (pRvlc->conceal_max != CONCEAL_MAX_INIT))
|
|
&& !(pAacDecoderStaticChannelInfo->concealmentInfo.rvlcPreviousScaleFactorOK && pRvlc->sf_concealment && (pAacDecoderStaticChannelInfo->concealmentInfo.rvlcPreviousBlockType == currentBlockType))
|
|
&& ConcealStatus )
|
|
{
|
|
BidirectionalEstimation_UseLowerScfOfCurrentFrame (pAacDecoderChannelInfo);
|
|
ConcealStatus=0;
|
|
#if VERBOSE_RVLC_OUTPUT
|
|
FDKstrcpy(Strategy,"Yes (BidirectionalEstimation_UseLowerScfOfCurrentFrame)");
|
|
#endif
|
|
}
|
|
|
|
/* No errors were detected in decoding of escapes and dpcm values however the first and last value
|
|
of a group (is,nrg,sf) is incorrect */
|
|
if ( (pRvlc->conceal_min <= pRvlc->conceal_max) && ((ErrorStatusLastScf && ErrorStatusFirstScf)
|
|
|| (ErrorStatusLastNrg && ErrorStatusFirstNrg) || (ErrorStatusLastIs && ErrorStatusFirstIs))
|
|
&& !(ErrorStatusForbiddenCwFwd || ErrorStatusForbiddenCwBwd || ErrorStatusLengthEscapes ) && ConcealStatus)
|
|
{
|
|
StatisticalEstimation (pAacDecoderChannelInfo);
|
|
ConcealStatus=0;
|
|
#if VERBOSE_RVLC_OUTPUT
|
|
FDKstrcpy(Strategy,"Yes (StatisticalEstimation)");
|
|
#endif
|
|
}
|
|
|
|
/* A error with more bits in decoding of escapes and dpcm values was detected. Use the smaller scalefactor from forward
|
|
decoding, backward decoding and previous frame. */
|
|
if ( (pRvlc->conceal_min <= pRvlc->conceal_max) && pAacDecoderStaticChannelInfo->concealmentInfo.rvlcPreviousScaleFactorOK && pRvlc->sf_concealment
|
|
&& (pAacDecoderStaticChannelInfo->concealmentInfo.rvlcPreviousBlockType == currentBlockType) && ConcealStatus )
|
|
{
|
|
PredictiveInterpolation(pAacDecoderChannelInfo, pAacDecoderStaticChannelInfo);
|
|
ConcealStatus=0;
|
|
#if VERBOSE_RVLC_OUTPUT
|
|
FDKstrcpy(Strategy,"Yes (PredictiveInterpolation)");
|
|
#endif
|
|
}
|
|
|
|
/* Call frame concealment, because no better strategy was found. Setting the scalefactors to zero is done for debugging
|
|
purposes */
|
|
if (ConcealStatus) {
|
|
for (group=0; group < pRvlc->numWindowGroups; group++) {
|
|
for (band=0; band<pRvlc->maxSfbTransmitted; band++) {
|
|
pAacDecoderChannelInfo->pDynData->aScaleFactor[16*group+band] = 0;
|
|
}
|
|
}
|
|
pAacDecoderChannelInfo->pDynData->specificTo.aac.rvlcCurrentScaleFactorOK = 0;
|
|
#if VERBOSE_RVLC_OUTPUT
|
|
FDKstrcpy(Strategy,"Yes (FrameConcealment)");
|
|
#endif
|
|
}
|
|
}
|
|
|
|
#if VERBOSE_RVLC_OUTPUT
|
|
DebugOutputDistortedBitstreams(pRvlc,pAacDecoderChannelInfo,ErrorStatusLengthFwd,ErrorStatusLengthBwd,
|
|
ErrorStatusLengthEscapes,ErrorStatusFirstScf,ErrorStatusLastScf,
|
|
ErrorStatusFirstNrg,ErrorStatusLastNrg,ErrorStatusFirstIs,ErrorStatusLastIs,
|
|
ErrorStatusForbiddenCwFwd,ErrorStatusForbiddenCwBwd,ErrorStatusNumEscapesFwd,
|
|
ErrorStatusNumEscapesBwd,conceal_max,conceal_min,Strategy);
|
|
#endif
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------------------------
|
|
function: CRvlc_Read
|
|
|
|
description: Read RVLC ESC1 data (side info) from bitstream.
|
|
-----------------------------------------------------------------------------------------------
|
|
input: - pointer rvlc structure
|
|
- pointer channel info structure
|
|
- pointer bitstream structure
|
|
-----------------------------------------------------------------------------------------------
|
|
return: -
|
|
-------------------------------------------------------------------------------------------- */
|
|
|
|
void CRvlc_Read (
|
|
CAacDecoderChannelInfo *pAacDecoderChannelInfo,
|
|
HANDLE_FDK_BITSTREAM bs)
|
|
{
|
|
CErRvlcInfo *pRvlc = &pAacDecoderChannelInfo->pComData->overlay.aac.erRvlcInfo;
|
|
|
|
int group,band;
|
|
|
|
/* RVLC long specific initialization Init part 1 of 2 */
|
|
pRvlc->numWindowGroups = GetWindowGroups(&pAacDecoderChannelInfo->icsInfo);
|
|
pRvlc->maxSfbTransmitted = GetScaleFactorBandsTransmitted(&pAacDecoderChannelInfo->icsInfo);
|
|
pRvlc->noise_used = 0; /* noise detection */
|
|
pRvlc->dpcm_noise_nrg = 0; /* only for debugging */
|
|
pRvlc->dpcm_noise_last_position = 0; /* only for debugging */
|
|
pRvlc->length_of_rvlc_escapes = -1; /* default value is used for error detection and concealment */
|
|
|
|
/* read only error sensitivity class 1 data (ESC 1 - data) */
|
|
pRvlc->sf_concealment = FDKreadBits(bs,1); /* #1 */
|
|
pRvlc->rev_global_gain = FDKreadBits(bs,8); /* #2 */
|
|
|
|
if (GetWindowSequence(&pAacDecoderChannelInfo->icsInfo) == EightShortSequence) {
|
|
pRvlc->length_of_rvlc_sf = FDKreadBits(bs,11); /* #3 */
|
|
}
|
|
else {
|
|
pRvlc->length_of_rvlc_sf = FDKreadBits(bs,9); /* #3 */
|
|
}
|
|
|
|
/* check if noise codebook is used */
|
|
for (group = 0; group < pRvlc->numWindowGroups; group++) {
|
|
for (band=0; band < pRvlc->maxSfbTransmitted; band++) {
|
|
if (pAacDecoderChannelInfo->pDynData->aCodeBook[16*group+band] == NOISE_HCB) {
|
|
pRvlc->noise_used = 1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (pRvlc->noise_used)
|
|
pRvlc->dpcm_noise_nrg = FDKreadBits(bs, 9); /* #4 PNS */
|
|
|
|
pRvlc->sf_escapes_present = FDKreadBits(bs, 1); /* #5 */
|
|
|
|
if ( pRvlc->sf_escapes_present) {
|
|
pRvlc->length_of_rvlc_escapes = FDKreadBits(bs, 8); /* #6 */
|
|
}
|
|
|
|
if (pRvlc->noise_used) {
|
|
pRvlc->dpcm_noise_last_position = FDKreadBits(bs, 9); /* #7 PNS */
|
|
pRvlc->length_of_rvlc_sf -= 9;
|
|
}
|
|
|
|
pRvlc->length_of_rvlc_sf_fwd = pRvlc->length_of_rvlc_sf;
|
|
pRvlc->length_of_rvlc_sf_bwd = pRvlc->length_of_rvlc_sf;
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------------------------
|
|
function: CRvlc_Decode
|
|
|
|
description: Decode rvlc data
|
|
The function reads both the escape sequences and the scalefactors in forward
|
|
and backward direction. If an error occured during decoding process which can
|
|
not be concealed with the rvlc concealment frame concealment will be initiated.
|
|
Then the element "rvlcCurrentScaleFactorOK" in the decoder channel info is set
|
|
to 0 otherwise it is set to 1.
|
|
-----------------------------------------------------------------------------------------------
|
|
input: - pointer rvlc structure
|
|
- pointer channel info structure
|
|
- pointer to persistent channel info structure
|
|
- pointer bitstream structure
|
|
-----------------------------------------------------------------------------------------------
|
|
return: ErrorStatus = AAC_DEC_OK
|
|
-------------------------------------------------------------------------------------------- */
|
|
|
|
void CRvlc_Decode (
|
|
CAacDecoderChannelInfo *pAacDecoderChannelInfo,
|
|
CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo,
|
|
HANDLE_FDK_BITSTREAM bs
|
|
)
|
|
{
|
|
CErRvlcInfo *pRvlc = &pAacDecoderChannelInfo->pComData->overlay.aac.erRvlcInfo;
|
|
INT bitCntOffst;
|
|
UINT saveBitCnt;
|
|
|
|
rvlcInit(pRvlc,pAacDecoderChannelInfo,bs);
|
|
|
|
/* save bitstream position */
|
|
saveBitCnt = FDKgetBitCnt(bs);
|
|
|
|
#if RVLC_ADVANCED_BITSTREAM_ERROR_GENERATOR_SF
|
|
GenerateSingleBitError(pRvlc,
|
|
&(pRvlc->bitstreamIndexRvlFwd),
|
|
pRvlc->length_of_rvlc_sf,
|
|
0);
|
|
#endif
|
|
|
|
#if RVLC_ADVANCED_BITSTREAM_ERROR_GENERATOR_ESC
|
|
if (pRvlc->sf_escapes_present)
|
|
GenerateSingleBitError(pRvlc,
|
|
&(pRvlc->bitstreamIndexEsc),
|
|
pRvlc->length_of_rvlc_escapes,
|
|
1);
|
|
#endif
|
|
|
|
if ( pRvlc->sf_escapes_present)
|
|
rvlcDecodeEscapes(pRvlc, pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfEsc, bs);
|
|
|
|
rvlcDecodeForward(pRvlc,pAacDecoderChannelInfo, bs);
|
|
rvlcDecodeBackward(pRvlc,pAacDecoderChannelInfo, bs);
|
|
rvlcFinalErrorDetection(pAacDecoderChannelInfo, pAacDecoderStaticChannelInfo);
|
|
|
|
pAacDecoderChannelInfo->pDynData->specificTo.aac.rvlcIntensityUsed = pRvlc->intensity_used;
|
|
pAacDecoderChannelInfo->data.aac.PnsData.PnsActive = pRvlc->noise_used;
|
|
|
|
/* restore bitstream position */
|
|
bitCntOffst = saveBitCnt - FDKgetBitCnt(bs);
|
|
if( bitCntOffst ) {
|
|
FDKpushBiDirectional(bs, bitCntOffst);
|
|
}
|
|
}
|
|
|
|
void CRvlc_ElementCheck (
|
|
CAacDecoderChannelInfo *pAacDecoderChannelInfo[],
|
|
CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[],
|
|
const UINT flags,
|
|
const INT elChannels
|
|
)
|
|
{
|
|
int ch;
|
|
|
|
/* Required for MPS residuals. */
|
|
if (pAacDecoderStaticChannelInfo == NULL) {
|
|
return;
|
|
}
|
|
|
|
/* RVLC specific sanity checks */
|
|
if ( (flags & AC_ER_RVLC) && (elChannels == 2)) { /* to be reviewed */
|
|
if ( ( (pAacDecoderChannelInfo[0]->pDynData->specificTo.aac.rvlcCurrentScaleFactorOK == 0) ||
|
|
(pAacDecoderChannelInfo[1]->pDynData->specificTo.aac.rvlcCurrentScaleFactorOK == 0) )
|
|
&& pAacDecoderChannelInfo[0]->pComData->jointStereoData.MsMaskPresent ) {
|
|
pAacDecoderChannelInfo[0]->pDynData->specificTo.aac.rvlcCurrentScaleFactorOK = 0;
|
|
pAacDecoderChannelInfo[1]->pDynData->specificTo.aac.rvlcCurrentScaleFactorOK = 0;
|
|
}
|
|
|
|
if ( (pAacDecoderChannelInfo[0]->pDynData->specificTo.aac.rvlcCurrentScaleFactorOK == 0)
|
|
&& (pAacDecoderChannelInfo[1]->pDynData->specificTo.aac.rvlcCurrentScaleFactorOK == 1)
|
|
&& (pAacDecoderChannelInfo[1]->pDynData->specificTo.aac.rvlcIntensityUsed == 1) ){
|
|
pAacDecoderChannelInfo[1]->pDynData->specificTo.aac.rvlcCurrentScaleFactorOK = 0;
|
|
}
|
|
}
|
|
|
|
for (ch = 0; ch < elChannels; ch ++)
|
|
{
|
|
pAacDecoderStaticChannelInfo[ch]->concealmentInfo.rvlcPreviousBlockType = (GetWindowSequence(&pAacDecoderChannelInfo[ch]->icsInfo) == EightShortSequence) ? 0 : 1;
|
|
if (flags & AC_ER_RVLC) {
|
|
pAacDecoderStaticChannelInfo[ch]->concealmentInfo.rvlcPreviousScaleFactorOK = pAacDecoderChannelInfo[ch]->pDynData->specificTo.aac.rvlcCurrentScaleFactorOK;
|
|
}
|
|
else {
|
|
pAacDecoderStaticChannelInfo[ch]->concealmentInfo.rvlcPreviousScaleFactorOK = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
|