Commit 5016eb7f authored by Jean-Michel Trivi's avatar Jean-Michel Trivi

Decoder stability, sanity checks improvements

* AAC-Decoder

   - Improved PCE handling for saver (re-)configuration and metadata processing.
     Modified file(s):
        libAACdec/src/aacdecoder.cpp
        libAACdec/src/aacdecoder_lib.cpp

   - Transport layer changes (config found) -> to be evaluated.
     Modified file(s):
        libMpegTPDec/include/tpdec_lib.h
        libMpegTPDec/src/tpdec_latm.h
        libMpegTPDec/src/version
        libMpegTPDec/src/tpdec_asc.cpp
        libMpegTPDec/src/tpdec_lib.cpp
        libMpegTPDec/src/tpdec_adts.cpp
        libMpegTPDec/src/tpdec_latm.cpp
        libSYS/include/FDK_audio.h
        libSYS/src/genericStds.cpp

   - Enable concealment state machine to skip states if the corresponding
     parameter is set to zero.
     Modified file(s):
        libAACdec/src/conceal.cpp

   - Add some more sanity checks to avoid segmentation faults especially when
     setting dynamic API params.
     Modified file(s):
        libAACdec/src/aacdecoder_lib.cpp

   - Fix to do a fail-safe initialization of IMDCT for all channels even with
     corrupt streams.
     Modified file(s):
        libAACdec/src/aacdecoder.cpp

   - HCR decoder fix (remove warnings).
     Modified file(s):
        libAACdec/src/block.cpp

   - Fix border calculation in SBR decoder's LPP transposer patch determination.
     Modified file(s):
        libSBRdec/src/env_dec.cpp
        libSBRdec/src/sbrdecoder.cpp
        libSBRdec/src/lpp_tran.cpp

Bug 9428126

Change-Id: Ib415b702b88a7ec8e9a55789d79cafb39296d26b
parent b9774f90
......@@ -373,7 +373,7 @@ static AAC_DECODER_ERROR CDataStreamElement_Read (
{
INT readBits, dataBits = count<<3;
/* Move to the beginning of the data junk */
FDKpushBack(bs, dataStart-FDKgetValidBits(bs));
......@@ -394,23 +394,26 @@ static AAC_DECODER_ERROR CDataStreamElement_Read (
\brief Read Program Config Element
\bs Bitstream Handle
\count Pointer to program config element.
\pTp Transport decoder handle for CRC handling
\pce Pointer to PCE buffer
\channelConfig Current channel configuration
\alignAnchor Anchor for byte alignment
\return Error code
\return PCE status (-1: fail, 0: no new PCE, 1: PCE updated, 2: PCE updated need re-config).
*/
static AAC_DECODER_ERROR CProgramConfigElement_Read (
static int CProgramConfigElement_Read (
HANDLE_FDK_BITSTREAM bs,
HANDLE_TRANSPORTDEC pTp,
CProgramConfig *pce,
UINT channelConfig,
UINT alignAnchor )
const UINT channelConfig,
const UINT alignAnchor )
{
AAC_DECODER_ERROR error = AAC_DEC_OK;
int pceStatus = 0;
int crcReg;
/* read PCE to temporal buffer first */
C_ALLOC_SCRATCH_START(tmpPce, CProgramConfig, 1);
CProgramConfig_Init(tmpPce);
CProgramConfig_Reset(tmpPce);
......@@ -421,22 +424,43 @@ static AAC_DECODER_ERROR CProgramConfigElement_Read (
transportDec_CrcEndReg(pTp, crcReg);
if ( CProgramConfig_IsValid(tmpPce)
&& ( (channelConfig == 6 && (tmpPce->NumChannels == 6))
|| (channelConfig == 5 && (tmpPce->NumChannels == 5))
|| (channelConfig == 0 && (tmpPce->NumChannels == pce->NumChannels)) )
&& (tmpPce->NumFrontChannelElements == 2)
&& (tmpPce->NumSideChannelElements == 0)
&& (tmpPce->NumBackChannelElements == 1)
&& (tmpPce->Profile == 1) )
{ /* Copy the complete PCE including metadata. */
FDKmemcpy(pce, tmpPce, sizeof(CProgramConfig));
{
if ( !pce->isValid && (channelConfig > 0) ) {
/* Create a standard channel config PCE to compare with */
CProgramConfig_GetDefault( pce, channelConfig );
}
if (pce->isValid) {
/* Compare the new and the old PCE (tags ignored) */
switch ( CProgramConfig_Compare( pce, tmpPce ) )
{
case 1: /* Channel configuration not changed. Just new metadata. */
FDKmemcpy(pce, tmpPce, sizeof(CProgramConfig)); /* Store the complete PCE */
pceStatus = 1; /* New PCE but no change of config */
break;
case 2: /* The number of channels are identical but not the config */
if (channelConfig == 0) {
FDKmemcpy(pce, tmpPce, sizeof(CProgramConfig)); /* Store the complete PCE */
pceStatus = 2; /* Decoder needs re-configuration */
}
break;
case -1: /* The channel configuration is completely different */
pceStatus = -1; /* Not supported! */
break;
case 0: /* Nothing to do because PCE matches the old one exactly. */
default:
/* pceStatus = 0; */
break;
}
}
}
C_ALLOC_SCRATCH_END(tmpPce, CProgramConfig, 1);
return error;
return pceStatus;
}
#endif
#endif /* TP_PCE_ENABLE */
/*!
\brief Parse Extension Payload
......@@ -591,7 +615,7 @@ AAC_DECODER_ERROR CAacDecoder_ExtPayloadParse (HANDLE_AACDECODER self,
{ /* ... created to circumvent the missing length in ER-Syntax. */
int bitCnt, len = FDKreadBits(hBs, 4);
*count -= 4;
if (len == 15) {
int add_len = FDKreadBits(hBs, 8);
*count -= 8;
......@@ -609,9 +633,7 @@ AAC_DECODER_ERROR CAacDecoder_ExtPayloadParse (HANDLE_AACDECODER self,
/* Check NOTE 2: The extension_payload() included here must
not have extension_type == EXT_DATA_LENGTH. */
error = AAC_DEC_PARSE_ERROR;
goto bail;
}
else {
} else {
/* rewind and call myself again. */
FDKpushBack(hBs, 4);
......@@ -622,7 +644,7 @@ AAC_DECODER_ERROR CAacDecoder_ExtPayloadParse (HANDLE_AACDECODER self,
&bitCnt,
previous_element,
elIndex,
1 ); /* Treat same as fill element */
0 );
*count -= len - bitCnt;
}
......@@ -754,8 +776,12 @@ LINKSPEC_CPP void CAacDecoder_Close(HANDLE_AACDECODER self)
for (ch=0; ch<(6); ch++) {
if (self->pAacDecoderStaticChannelInfo[ch] != NULL) {
FreeOverlapBuffer (&self->pAacDecoderStaticChannelInfo[ch]->pOverlapBuffer);
FreeAacDecoderStaticChannelInfo (&self->pAacDecoderStaticChannelInfo[ch]);
if (self->pAacDecoderStaticChannelInfo[ch]->pOverlapBuffer != NULL) {
FreeOverlapBuffer (&self->pAacDecoderStaticChannelInfo[ch]->pOverlapBuffer);
}
if (self->pAacDecoderStaticChannelInfo[ch] != NULL) {
FreeAacDecoderStaticChannelInfo (&self->pAacDecoderStaticChannelInfo[ch]);
}
}
if (self->pAacDecoderChannelInfo[ch] != NULL) {
FreeAacDecoderChannelInfo (&self->pAacDecoderChannelInfo[ch]);
......@@ -768,8 +794,12 @@ LINKSPEC_CPP void CAacDecoder_Close(HANDLE_AACDECODER self)
FreeDrcInfo(&self->hDrcInfo);
}
FreeWorkBufferCore1 (&self->aacCommonData.workBufferCore1);
FreeWorkBufferCore2 (&self->aacCommonData.workBufferCore2);
if (self->aacCommonData.workBufferCore1 != NULL) {
FreeWorkBufferCore1 (&self->aacCommonData.workBufferCore1);
}
if (self->aacCommonData.workBufferCore2 != NULL) {
FreeWorkBufferCore2 (&self->aacCommonData.workBufferCore2);
}
FreeAacDecoder ( &self);
}
......@@ -994,12 +1024,14 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_Init(HANDLE_AACDECODER self, const CS
CPns_InitPns(&self->pAacDecoderChannelInfo[ch]->data.aac.PnsData, &self->aacCommonData.pnsInterChannelData, &self->aacCommonData.pnsCurrentSeed, self->aacCommonData.pnsRandomSeed);
}
if (ascChannels > self->aacChannels)
{
/* Make allocated channel count persistent in decoder context. */
self->aacChannels = ascChannels;
}
HcrInitRom(&self->aacCommonData.overlay.aac.erHcrInfo);
setHcrType(&self->aacCommonData.overlay.aac.erHcrInfo, ID_SCE);
/* Make allocated channel count persistent in decoder context. */
self->aacChannels = ascChannels;
}
/* Make amount of signalled channels persistent in decoder context. */
......@@ -1009,8 +1041,10 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_Init(HANDLE_AACDECODER self, const CS
/* Update structures */
if (ascChanged) {
/* Things to be done for each channel, which do not involved allocating memory. */
for (ch = 0; ch < ascChannels; ch++) {
/* Things to be done for each channel, which do not involve allocating memory.
Doing these things only on the channels needed for the current configuration
(ascChannels) could lead to memory access violation later (error concealment). */
for (ch = 0; ch < self->aacChannels; ch++) {
switch (self->streamInfo.aot) {
case AOT_ER_AAC_ELD:
case AOT_ER_AAC_LD:
......@@ -1241,10 +1275,10 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
else {
self->frameOK = 0;
}
/* Create SBR element for SBR for upsampling. */
if ( (type == ID_LFE)
&& ( (self->flags & AC_SBR_PRESENT)
|| (self->sbrEnabled == 1) ) )
/* Create SBR element for SBR for upsampling for LFE elements,
and if SBR was explicitly signaled, because the first frame(s)
may not contain SBR payload (broken encoder, bit errors). */
if ( (self->flags & AC_SBR_PRESENT) || (self->sbrEnabled == 1) )
{
SBR_ERROR sbrError;
......@@ -1254,7 +1288,7 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
self->streamInfo.extSamplingRate,
self->streamInfo.aacSamplesPerFrame,
self->streamInfo.aot,
ID_LFE,
type,
previous_element_index
);
if (sbrError != SBRDEC_OK) {
......@@ -1394,26 +1428,34 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
#ifdef TP_PCE_ENABLE
case ID_PCE:
if ( CProgramConfigElement_Read( bs,
{
int result = CProgramConfigElement_Read(
bs,
self->hInput,
pce,
self->streamInfo.channelConfig,
auStartAnchor ) )
{ /* Built element table */
int elIdx = CProgramConfig_GetElementTable(pce, self->elements, 7);
/* Reset the remaining tabs */
for ( ; elIdx<7; elIdx++) {
self->elements[elIdx] = ID_NONE;
}
/* Make new number of channel persistant */
self->ascChannels = pce->NumChannels;
/* If PCE is not first element conceal this frame to avoid inconsistencies */
if ( element_count != 0 ) {
auStartAnchor );
if ( result < 0 ) {
/* Something went wrong */
ErrorStatus = AAC_DEC_PARSE_ERROR;
self->frameOK = 0;
}
else if ( result > 1 ) {
/* Built element table */
int elIdx = CProgramConfig_GetElementTable(pce, self->elements, 7);
/* Reset the remaining tabs */
for ( ; elIdx<7; elIdx++) {
self->elements[elIdx] = ID_NONE;
}
/* Make new number of channel persistant */
self->ascChannels = pce->NumChannels;
/* If PCE is not first element conceal this frame to avoid inconsistencies */
if ( element_count != 0 ) {
self->frameOK = 0;
}
}
pceRead = (result>=0) ? 1 : 0;
}
pceRead = 1;
break;
#endif /* TP_PCE_ENABLE */
......
......@@ -110,7 +110,7 @@ amm-info@iis.fraunhofer.de
/* Decoder library info */
#define AACDECODER_LIB_VL0 2
#define AACDECODER_LIB_VL1 5
#define AACDECODER_LIB_VL2 3
#define AACDECODER_LIB_VL2 4
#define AACDECODER_LIB_TITLE "AAC Decoder Lib"
#define AACDECODER_LIB_BUILD_DATE __DATE__
#define AACDECODER_LIB_BUILD_TIME __TIME__
......@@ -261,7 +261,7 @@ setConcealMethod ( const HANDLE_AACDECODER self, /*!< Handle of the decoder i
HANDLE_SBRDECODER hSbrDec = NULL;
HANDLE_AAC_DRC hDrcInfo = NULL;
HANDLE_PCM_DOWNMIX hPcmDmx = NULL;
CConcealmentMethod backupMethod;
CConcealmentMethod backupMethod = ConcealMethodNone;
int backupDelay = 0;
int bsDelay = 0;
......@@ -396,11 +396,15 @@ aacDecoder_SetParam ( const HANDLE_AACDECODER self, /*!< Handle of the decode
AAC_DECODER_ERROR errorStatus = AAC_DEC_OK;
CConcealParams *pConcealData = NULL;
HANDLE_AAC_DRC hDrcInfo = NULL;
HANDLE_PCM_DOWNMIX hPcmDmx = NULL;
/* check decoder handle */
if (self != NULL) {
pConcealData = &self->concealCommonData;
hDrcInfo = self->hDrcInfo;
hPcmDmx = self->hPcmUtils;
} else {
errorStatus = AAC_DEC_INVALID_HANDLE;
}
/* configure the subsystems */
......@@ -417,11 +421,14 @@ aacDecoder_SetParam ( const HANDLE_AACDECODER self, /*!< Handle of the decode
break;
case AAC_PCM_OUTPUT_CHANNELS:
if (value < -1 || value > (6)) {
return AAC_DEC_SET_PARAM_FAIL;
}
{
PCMDMX_ERROR err;
err = pcmDmx_SetParam (
self->hPcmUtils,
hPcmDmx,
NUMBER_OF_OUTPUT_CHANNELS,
value );
......@@ -441,7 +448,7 @@ aacDecoder_SetParam ( const HANDLE_AACDECODER self, /*!< Handle of the decode
PCMDMX_ERROR err;
err = pcmDmx_SetParam (
self->hPcmUtils,
hPcmDmx,
DUAL_CHANNEL_DOWNMIX_MODE,
value );
......@@ -459,10 +466,14 @@ aacDecoder_SetParam ( const HANDLE_AACDECODER self, /*!< Handle of the decode
case AAC_PCM_OUTPUT_CHANNEL_MAPPING:
switch (value) {
case 0:
self->channelOutputMapping = channelMappingTablePassthrough;
if (self != NULL) {
self->channelOutputMapping = channelMappingTablePassthrough;
}
break;
case 1:
self->channelOutputMapping = channelMappingTableWAV;
if (self != NULL) {
self->channelOutputMapping = channelMappingTableWAV;
}
break;
default:
errorStatus = AAC_DEC_SET_PARAM_FAIL;
......@@ -472,6 +483,9 @@ aacDecoder_SetParam ( const HANDLE_AACDECODER self, /*!< Handle of the decode
case AAC_QMF_LOWPOWER:
if (value < -1 || value > 1) {
return AAC_DEC_SET_PARAM_FAIL;
}
if (self == NULL) {
return AAC_DEC_INVALID_HANDLE;
}
......
......@@ -589,7 +589,6 @@ AAC_DECODER_ERROR CBlock_ReadSpectralData(HANDLE_FDK_BITSTREAM bs,
{
H_HCR_INFO hHcr = &pAacDecoderChannelInfo->pComData->overlay.aac.erHcrInfo;
int hcrStatus = 0;
int hcrConcealWholeFrame = 0;
/* advanced Huffman decoding starts here (HCR decoding :) */
if ( pAacDecoderChannelInfo->pDynData->specificTo.aac.lenOfReorderedSpectralData != 0 ) {
......@@ -598,24 +597,19 @@ AAC_DECODER_ERROR CBlock_ReadSpectralData(HANDLE_FDK_BITSTREAM bs,
hcrStatus = HcrInit(hHcr, pAacDecoderChannelInfo, pSamplingRateInfo, bs);
if (hcrStatus != 0) {
#if HCR_ERROR_CONCEALMENT
hcrConcealWholeFrame = 1;
return AAC_DEC_DECODE_FRAME_ERROR; /* concealment is muting in the first step, therefore return now */
// hcr decoding is not skipped because of returning above
#else
return AAC_DEC_DECODE_FRAME_ERROR;
#endif
}
/* HCR decoding short */
hcrStatus = HcrDecoder(hHcr, pAacDecoderChannelInfo, pSamplingRateInfo, bs);
if (hcrStatus != 0) {
#if HCR_ERROR_CONCEALMENT
HcrMuteErroneousLines(hHcr);
HcrMuteErroneousLines(hHcr);
#else
return AAC_DEC_DECODE_FRAME_ERROR;
return AAC_DEC_DECODE_FRAME_ERROR;
#endif /* HCR_ERROR_CONCEALMENT */
}
FDKpushFor (bs, pAacDecoderChannelInfo->pDynData->specificTo.aac.lenOfReorderedSpectralData);
}
......
......@@ -441,7 +441,7 @@ AAC_DECODER_ERROR
/* set confort noise level which will be inserted while in state 'muting' */
if (comfNoiseLevel != AACDEC_CONCEAL_PARAM_NOT_SPECIFIED) {
if ( (comfNoiseLevel < 0)
if ( (comfNoiseLevel < -1)
|| (comfNoiseLevel > 127) ) {
return AAC_DEC_SET_PARAM_FAIL;
}
......@@ -1527,8 +1527,13 @@ static void
{
case ConcealState_Ok:
if (!frameOk) {
/* change to state SINGLE-FRAME-LOSS */
pConcealmentInfo->concealState = ConcealState_Single;
if (pConcealCommonData->numFadeOutFrames > 0) {
/* change to state SINGLE-FRAME-LOSS */
pConcealmentInfo->concealState = ConcealState_Single;
} else {
/* change to state MUTE */
pConcealmentInfo->concealState = ConcealState_Mute;
}
pConcealmentInfo->cntFadeFrames = 0;
pConcealmentInfo->cntValidFrames = 0;
}
......@@ -1561,11 +1566,16 @@ static void
case ConcealState_FadeOut:
pConcealmentInfo->cntFadeFrames += 1; /* used to address the fade-out factors */
if (pConcealmentInfo->cntValidFrames > pConcealCommonData->numMuteReleaseFrames) {
/* change to state FADE-IN */
pConcealmentInfo->concealState = ConcealState_FadeIn;
pConcealmentInfo->cntFadeFrames = findEquiFadeFrame( pConcealCommonData,
pConcealmentInfo->cntFadeFrames-1,
0 /* FadeOut -> FadeIn */);
if (pConcealCommonData->numFadeInFrames > 0) {
/* change to state FADE-IN */
pConcealmentInfo->concealState = ConcealState_FadeIn;
pConcealmentInfo->cntFadeFrames = findEquiFadeFrame( pConcealCommonData,
pConcealmentInfo->cntFadeFrames-1,
0 /* FadeOut -> FadeIn */);
} else {
/* change to state OK */
pConcealmentInfo->concealState = ConcealState_Ok;
}
} else {
if (pConcealmentInfo->cntFadeFrames >= pConcealCommonData->numFadeOutFrames) {
/* change to state MUTE */
......@@ -1576,9 +1586,14 @@ static void
case ConcealState_Mute:
if (pConcealmentInfo->cntValidFrames > pConcealCommonData->numMuteReleaseFrames) {
/* change to state FADE-IN */
pConcealmentInfo->concealState = ConcealState_FadeIn;
pConcealmentInfo->cntFadeFrames = pConcealCommonData->numFadeInFrames - 1;
if (pConcealCommonData->numFadeInFrames > 0) {
/* change to state FADE-IN */
pConcealmentInfo->concealState = ConcealState_FadeIn;
pConcealmentInfo->cntFadeFrames = pConcealCommonData->numFadeInFrames - 1;
} else {
/* change to state OK */
pConcealmentInfo->concealState = ConcealState_Ok;
}
}
break;
......@@ -1590,11 +1605,16 @@ static void
pConcealmentInfo->concealState = ConcealState_Ok;
}
} else {
/* change to state FADE-OUT */
pConcealmentInfo->concealState = ConcealState_FadeOut;
pConcealmentInfo->cntFadeFrames = findEquiFadeFrame( pConcealCommonData,
pConcealmentInfo->cntFadeFrames+1,
1 /* FadeIn -> FadeOut */);
if (pConcealCommonData->numFadeOutFrames > 0) {
/* change to state FADE-OUT */
pConcealmentInfo->concealState = ConcealState_FadeOut;
pConcealmentInfo->cntFadeFrames = findEquiFadeFrame( pConcealCommonData,
pConcealmentInfo->cntFadeFrames+1,
1 /* FadeIn -> FadeOut */);
} else {
/* change to state MUTE */
pConcealmentInfo->concealState = ConcealState_Mute;
}
}
break;
......@@ -1625,8 +1645,13 @@ static void
case ConcealState_Ok:
if (!(pConcealmentInfo->prevFrameOk[1] ||
(pConcealmentInfo->prevFrameOk[0] && !pConcealmentInfo->prevFrameOk[1] && frameOk))) {
/* Fade out only if the energy interpolation algorithm can not be applied! */
pConcealmentInfo->concealState = ConcealState_FadeOut;
if (pConcealCommonData->numFadeOutFrames > 0) {
/* Fade out only if the energy interpolation algorithm can not be applied! */
pConcealmentInfo->concealState = ConcealState_FadeOut;
} else {
/* change to state MUTE */
pConcealmentInfo->concealState = ConcealState_Mute;
}
pConcealmentInfo->cntFadeFrames = 0;
pConcealmentInfo->cntValidFrames = 0;
}
......@@ -1640,11 +1665,16 @@ static void
pConcealmentInfo->cntFadeFrames += 1;
if (pConcealmentInfo->cntValidFrames > pConcealCommonData->numMuteReleaseFrames) {
/* change to state FADE-IN */
pConcealmentInfo->concealState = ConcealState_FadeIn;
pConcealmentInfo->cntFadeFrames = findEquiFadeFrame( pConcealCommonData,
pConcealmentInfo->cntFadeFrames-1,
0 /* FadeOut -> FadeIn */);
if (pConcealCommonData->numFadeInFrames > 0) {
/* change to state FADE-IN */
pConcealmentInfo->concealState = ConcealState_FadeIn;
pConcealmentInfo->cntFadeFrames = findEquiFadeFrame( pConcealCommonData,
pConcealmentInfo->cntFadeFrames-1,
0 /* FadeOut -> FadeIn */);
} else {
/* change to state OK */
pConcealmentInfo->concealState = ConcealState_Ok;
}
} else {
if (pConcealmentInfo->cntFadeFrames >= pConcealCommonData->numFadeOutFrames) {
/* change to state MUTE */
......@@ -1655,9 +1685,14 @@ static void
case ConcealState_Mute:
if (pConcealmentInfo->cntValidFrames > pConcealCommonData->numMuteReleaseFrames) {
/* change to state FADE-IN */
pConcealmentInfo->concealState = ConcealState_FadeIn;
pConcealmentInfo->cntFadeFrames = pConcealCommonData->numFadeInFrames - 1;
if (pConcealCommonData->numFadeInFrames > 0) {
/* change to state FADE-IN */
pConcealmentInfo->concealState = ConcealState_FadeIn;
pConcealmentInfo->cntFadeFrames = pConcealCommonData->numFadeInFrames - 1;
} else {
/* change to state OK */
pConcealmentInfo->concealState = ConcealState_Ok;
}
}
break;
......@@ -1670,11 +1705,16 @@ static void
pConcealmentInfo->concealState = ConcealState_Ok;
}
} else {
/* change to state FADE-OUT */
pConcealmentInfo->concealState = ConcealState_FadeOut;
pConcealmentInfo->cntFadeFrames = findEquiFadeFrame( pConcealCommonData,
pConcealmentInfo->cntFadeFrames+1,
1 /* FadeIn -> FadeOut */);
if (pConcealCommonData->numFadeOutFrames > 0) {
/* change to state FADE-OUT */
pConcealmentInfo->concealState = ConcealState_FadeOut;
pConcealmentInfo->cntFadeFrames = findEquiFadeFrame( pConcealCommonData,
pConcealmentInfo->cntFadeFrames+1,
1 /* FadeIn -> FadeOut */);
} else {
/* change to state MUTE */
pConcealmentInfo->concealState = ConcealState_Mute;
}
}
break;
} /* End switch(pConcealmentInfo->concealState) */
......
......@@ -186,6 +186,27 @@ int CProgramConfig_IsValid ( const CProgramConfig *pPce );
void CProgramConfig_Read ( CProgramConfig *pPce,
HANDLE_FDK_BITSTREAM bs,
UINT alignAnchor );
/*!
\brief Compare two Program Config Elements.
\param pPce1 Pointer to first Program Config Element structure.
\param pPce2 Pointer to second Program Config Element structure.
\return -1 if PCEs are completely different,
0 if PCEs are completely equal,
1 if PCEs are different but have the same channel config,
2 if PCEs have different channel config but same number of channels.
*/
int CProgramConfig_Compare ( const CProgramConfig * const pPce1,
const CProgramConfig * const pPce2 );
/*!
\brief Get a Program Config Element that matches the predefined MPEG-4 channel configurations 1-14.
\param pPce Program Config Element structure.
\param channelConfig MPEG-4 channel configuration.
\return void
*/
void CProgramConfig_GetDefault ( CProgramConfig *pPce,
const UINT channelConfig );
#endif /* TP_PCE_ENABLE */
/**
......
......@@ -374,12 +374,12 @@ int adtsRead_GetRawDataBlockLength(
length = -1; /* raw data block length is unknown */
} else {
if (blockNum < 0 || blockNum > 3) {
return TRANSPORTDEC_INVALID_PARAMETER;
length = -1;
}
length = (pAdts->rawDataBlockDist[blockNum] << 3) - 16;
}
}
if (blockNum == 0) {
if (blockNum == 0 && length > 0) {
length -= pAdts->bs.num_pce_bits;
}
return length;
......
......@@ -205,6 +205,145 @@ void CProgramConfig_Read(
pPce->isValid = 1;
}
/*
* Compare two program configurations.
* Returns the result of the comparison:
* -1 - completely different
* 0 - completely equal
* 1 - different but same channel configuration
* 2 - different channel configuration but same number of channels
*/
int CProgramConfig_Compare ( const CProgramConfig * const pPce1,
const CProgramConfig * const pPce2 )
{
int result = 0; /* Innocent until proven false. */
if (FDKmemcmp(pPce1, pPce2, sizeof(CProgramConfig)) != 0)
{ /* Configurations are not completely different.
So look into details and analyse the channel configurations: */
result = -1;
if (pPce1->NumChannels == pPce2->NumChannels)
{ /* Now the logic changes. We first assume to have the same channel configuration
and then prove if this assumption is true. */
result = 1;
/* Front channels */
if (pPce1->NumFrontChannelElements != pPce2->NumFrontChannelElements) {
result = 2; /* different number of front channel elements */
} else {
int el, numCh1 = 0, numCh2 = 0;
for (el = 0; el < pPce1->NumFrontChannelElements; el += 1) {
numCh1 += pPce1->FrontElementIsCpe[el] ? 2 : 1;
numCh2 += pPce2->FrontElementIsCpe[el] ? 2 : 1;
}
if (numCh1 != numCh2) {
result = 2; /* different number of front channels */
}
}
/* Side channels */
if (pPce1->NumSideChannelElements != pPce2->NumSideChannelElements) {
result = 2; /* different number of side channel elements */
} else {
int el, numCh1 = 0, numCh2 = 0;
for (el = 0; el < pPce1->NumSideChannelElements; el += 1) {
numCh1 += pPce1->SideElementIsCpe[el] ? 2 : 1;
numCh2 += pPce2->SideElementIsCpe[el] ? 2 : 1;
}
if (numCh1 != numCh2) {
result = 2; /* different number of side channels */
}
}
/* Back channels */
if (pPce1->NumBackChannelElements != pPce2->NumBackChannelElements) {
result = 2; /* different number of back channel elements */
} else {
int el, numCh1 = 0, numCh2 = 0;
for (el = 0; el < pPce1->NumBackChannelElements; el += 1) {
numCh1 += pPce1->BackElementIsCpe[el] ? 2 : 1;
numCh2 += pPce2->BackElementIsCpe[el] ? 2 : 1;
}
if (numCh1 != numCh2) {
result = 2; /* different number of back channels */
}
}
/* LFE channels */
if (pPce1->NumLfeChannelElements != pPce2->NumLfeChannelElements) {
result = 2; /* different number of lfe channels */
}
/* LFEs are always SCEs so we don't need to count the channels. */
}
}
return result;
}
void CProgramConfig_GetDefault( CProgramConfig *pPce,
const UINT channelConfig )
{
FDK_ASSERT(pPce != NULL);
/* Init PCE */
CProgramConfig_Init(pPce);
pPce->Profile = 1; /* Set AAC LC because it is the only supported object type. */
switch (channelConfig) {
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
case 6: /* 3/0/2.1ch */
pPce->NumLfeChannelElements += 1;
pPce->NumChannels += 1;
case 5: /* 3/0/2.0ch */
case 4: /* 3/0/1.0ch */
pPce->NumBackChannelElements += 1;
pPce->BackElementIsCpe[0] = (channelConfig>4) ? 1 : 0;
pPce->NumChannels += (channelConfig>4) ? 2 : 1;
pPce->NumEffectiveChannels += (channelConfig>4) ? 2 : 1;
case 3: /* 3/0/0.0ch */
pPce->NumFrontChannelElements += 1;
pPce->FrontElementIsCpe[1] = 1;
pPce->NumChannels += 2;
pPce->NumEffectiveChannels += 2;
case 1: /* 1/0/0.0ch */
pPce->NumFrontChannelElements += 1;
pPce->FrontElementIsCpe[0] = 0;
pPce->NumChannels += 1;
pPce->NumEffectiveChannels += 1;
pPce->isValid = 1;
break;
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
case 2: /* 2/0/0.ch */
pPce->NumFrontChannelElements = 1;
pPce->FrontElementIsCpe[0] = 1;
pPce->NumChannels += 2;
pPce->NumEffectiveChannels += 2;
pPce->isValid = 1;
break;
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
default:
pPce->isValid = 0; /* To be explicit! */
break;
}
if (pPce->isValid) {
/* Create valid element instance tags */
int el, elTagSce = 0, elTagCpe = 0;
for (el = 0; el < pPce->NumFrontChannelElements; el += 1) {
pPce->FrontElementTagSelect[el] = (pPce->FrontElementIsCpe) ? elTagCpe++ : elTagSce++;
}
for (el = 0; el < pPce->NumSideChannelElements; el += 1) {
pPce->SideElementTagSelect[el] = (pPce->SideElementIsCpe) ? elTagCpe++ : elTagSce++;
}
for (el = 0; el < pPce->NumBackChannelElements; el += 1) {
pPce->BackElementTagSelect[el] = (pPce->BackElementIsCpe) ? elTagCpe++ : elTagSce++;
}
elTagSce = 0;
for (el = 0; el < pPce->NumLfeChannelElements; el += 1) {
pPce->LfeElementTagSelect[el] = elTagSce++;
}
}
}
#endif /* TP_PCE_ENABLE */
/**
......@@ -589,18 +728,18 @@ static INT ld_sbr_header( const CSAudioSpecificConfig *asc,
}
switch ( channelConfiguration ) {
case 7:
error |= cb->cbSbr(cb->cbSbrData, hBs, asc->m_samplingFrequency, asc->m_extensionSamplingFrequency, asc->m_samplesPerFrame, AOT_ER_AAC_ELD, ID_CPE, i++);
case 6:
case 5:
error |= cb->cbSbr(cb->cbSbrData, hBs, asc->m_samplingFrequency, asc->m_extensionSamplingFrequency, asc->m_samplesPerFrame, AOT_ER_AAC_ELD, ID_CPE, i++);
case 3:
error |= cb->cbSbr(cb->cbSbrData, hBs, asc->m_samplingFrequency, asc->m_extensionSamplingFrequency, asc->m_samplesPerFrame, AOT_ER_AAC_ELD, ID_CPE, i++);
break;
case 7:
error |= cb->cbSbr(cb->cbSbrData, hBs, asc->m_samplingFrequency, asc->m_extensionSamplingFrequency, asc->m_samplesPerFrame, AOT_ER_AAC_ELD, ID_SCE, i++);
case 6:
error |= cb->cbSbr(cb->cbSbrData, hBs, asc->m_samplingFrequency, asc->m_extensionSamplingFrequency, asc->m_samplesPerFrame, AOT_ER_AAC_ELD, ID_CPE, i++);
case 4:
error |= cb->cbSbr(cb->cbSbrData, hBs, asc->m_samplingFrequency, asc->m_extensionSamplingFrequency, asc->m_samplesPerFrame, AOT_ER_AAC_ELD, ID_CPE, i++);
error |= cb->cbSbr(cb->cbSbrData, hBs, asc->m_samplingFrequency, asc->m_extensionSamplingFrequency, asc->m_samplesPerFrame, AOT_ER_AAC_ELD, ID_SCE, i++);
break;
}
......
......@@ -120,7 +120,8 @@ TRANSPORTDEC_ERROR CLatmDemux_ReadAudioMuxElement(
CLatmDemux *pLatmDemux,
int m_muxConfigPresent,
CSTpCallBacks *pTpDecCallbacks,
CSAudioSpecificConfig *pAsc
CSAudioSpecificConfig *pAsc,
int *pfConfigFound
)
{
TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK;
......@@ -129,12 +130,17 @@ TRANSPORTDEC_ERROR CLatmDemux_ReadAudioMuxElement(
pLatmDemux->m_useSameStreamMux = FDKreadBits(bs,1);
if (!pLatmDemux->m_useSameStreamMux) {
if ((ErrorStatus = CLatmDemux_ReadStreamMuxConfig(bs, pLatmDemux, pTpDecCallbacks, pAsc))) {
if ((ErrorStatus = CLatmDemux_ReadStreamMuxConfig(bs, pLatmDemux, pTpDecCallbacks, pAsc, pfConfigFound))) {
return (ErrorStatus);
}
}
}
/* If there was no configuration read, its not possible to parse PayloadLengthInfo below. */
if (! *pfConfigFound) {
return TRANSPORTDEC_SYNC_ERROR;
}
if (pLatmDemux->m_AudioMuxVersionA == 0) {
/* Do only once per call, because parsing and decoding is done in-line. */
if ((ErrorStatus = CLatmDemux_ReadPayloadLengthInfo(bs,pLatmDemux))) {
......@@ -154,6 +160,7 @@ TRANSPORTDEC_ERROR CLatmDemux_Read(
TRANSPORT_TYPE tt,
CSTpCallBacks *pTpDecCallbacks,
CSAudioSpecificConfig *pAsc,
int *pfConfigFound,
const INT ignoreBufferFullness
)
{
......@@ -168,7 +175,7 @@ TRANSPORTDEC_ERROR CLatmDemux_Read(
return TRANSPORTDEC_NOT_ENOUGH_BITS;
}
if ((ErrorStatus = CLatmDemux_ReadAudioMuxElement(bs, pLatmDemux, (tt != TT_MP4_LATM_MCP0), pTpDecCallbacks, pAsc)))
if ((ErrorStatus = CLatmDemux_ReadAudioMuxElement(bs, pLatmDemux, (tt != TT_MP4_LATM_MCP0), pTpDecCallbacks, pAsc, pfConfigFound)))
return (ErrorStatus);
if (!ignoreBufferFullness)
......@@ -205,7 +212,8 @@ TRANSPORTDEC_ERROR CLatmDemux_ReadStreamMuxConfig(
HANDLE_FDK_BITSTREAM bs,
CLatmDemux *pLatmDemux,
CSTpCallBacks *pTpDecCallbacks,
CSAudioSpecificConfig *pAsc
CSAudioSpecificConfig *pAsc,
int * pfConfigFound
)
{
LATM_LAYER_INFO *p_linfo = NULL;
......@@ -272,6 +280,7 @@ TRANSPORTDEC_ERROR CLatmDemux_ReadStreamMuxConfig(
if ((ErrorStatus = AudioSpecificConfig_Parse(&pAsc[TPDEC_TRACKINDEX(prog,lay)], &tmpBs, 1, pTpDecCallbacks))) {
return (ErrorStatus);
}
*pfConfigFound = 1;
/* The field p_linfo->m_ascLen could be wrong, so check if */
if ( 0 > (INT)FDKgetValidBits(&tmpBs)) {
......@@ -292,6 +301,7 @@ TRANSPORTDEC_ERROR CLatmDemux_ReadStreamMuxConfig(
if (cbError != 0) {
return TRANSPORTDEC_UNKOWN_ERROR;
}
*pfConfigFound = 1;
}
}
......@@ -377,7 +387,7 @@ TRANSPORTDEC_ERROR CLatmDemux_ReadPayloadLengthInfo(HANDLE_FDK_BITSTREAM bs, CLa
else {
ErrorStatus = TRANSPORTDEC_PARSE_ERROR; //AAC_DEC_LATM_TIMEFRAMING;
}
if (pLatmDemux->m_audioMuxLengthBytes > 0 && totalPayloadBits > pLatmDemux->m_audioMuxLengthBytes*8) {
if (pLatmDemux->m_audioMuxLengthBytes > (UINT)0 && totalPayloadBits > (int)pLatmDemux->m_audioMuxLengthBytes*8) {
return TRANSPORTDEC_PARSE_ERROR;
}
return (ErrorStatus);
......
......@@ -144,14 +144,25 @@ TRANSPORTDEC_ERROR CLatmDemux_Read(
TRANSPORT_TYPE tt,
CSTpCallBacks *pTpDecCallbacks,
CSAudioSpecificConfig *pAsc,
int *pfConfigFound,
const INT ignoreBufferFullness
);
/**
* \brief Read StreamMuxConfig
* \param bs bit stream handle as data source
* \param pLatmDemux pointer to CLatmDemux struct of current LATM context
* \param pTpDecCallbacks Call back structure for configuration callbacks
* \param pAsc pointer to a ASC for configuration storage
* \param pfConfigFound pointer to a flag which is set to 1 if a configuration was found and processed successfully
* \return error code
*/
TRANSPORTDEC_ERROR CLatmDemux_ReadStreamMuxConfig(
HANDLE_FDK_BITSTREAM bs,
CLatmDemux *pLatmDemux,
CSTpCallBacks *pTpDecCallbacks,
CSAudioSpecificConfig *pAsc
CSAudioSpecificConfig *pAsc,
int * pfConfigFound
);
TRANSPORTDEC_ERROR CLatmDemux_ReadPayloadLengthInfo(HANDLE_FDK_BITSTREAM bs, CLatmDemux *pLatmDemux);
......
......@@ -197,8 +197,7 @@ HANDLE_TRANSPORTDEC transportDec_Open( const TRANSPORT_TYPE transportFmt, const
if (hInput != NULL) {
/* Create bitstream */
if ( (transportFmt == TT_MP4_RAW)
|| (transportFmt == TT_DRM) ){
if ( TT_IS_PACKET(transportFmt) ) {
hInput->bsBuffer = NULL;
} else {
hInput->bsBuffer = GetRam_TransportDecoderBuffer(0);
......@@ -222,7 +221,9 @@ TRANSPORTDEC_ERROR transportDec_OutOfBandConfig(HANDLE_TRANSPORTDEC hTp, UCHAR *
FDK_BITSTREAM bs;
HANDLE_FDK_BITSTREAM hBs = &bs;
FDKinitBitStream(hBs, conf, 0x80000000, length<<3, BS_READER);
FDKinitBitStream(hBs, conf, 0x10000000, length<<3, BS_READER);
int fConfigFound = 0;
/* config transport decoder */
switch (hTp->transportFmt) {
......@@ -234,27 +235,27 @@ TRANSPORTDEC_ERROR transportDec_OutOfBandConfig(HANDLE_TRANSPORTDEC hTp, UCHAR *
return TRANSPORTDEC_INVALID_PARAMETER;
}
CLatmDemux *pLatmDemux = &hTp->parser.latm;
err = CLatmDemux_ReadStreamMuxConfig(hBs, pLatmDemux, &hTp->callbacks, hTp->asc);
err = CLatmDemux_ReadStreamMuxConfig(hBs, pLatmDemux, &hTp->callbacks, hTp->asc, &fConfigFound);
if (err != TRANSPORTDEC_OK) {
return err;
}
}
break;
default:
case TT_MP4_RAW:
fConfigFound = 1;
err = AudioSpecificConfig_Parse(&hTp->asc[layer], hBs, 1, &hTp->callbacks);
break;
}
if (err == TRANSPORTDEC_OK) {
int errC;
if (err == TRANSPORTDEC_OK) {
int errC;
errC = hTp->callbacks.cbUpdateConfig(hTp->callbacks.cbUpdateConfigData, &hTp->asc[layer]);
if (errC != 0) {
err = TRANSPORTDEC_PARSE_ERROR;
}
errC = hTp->callbacks.cbUpdateConfig(hTp->callbacks.cbUpdateConfigData, &hTp->asc[layer]);
if (errC != 0) {
err = TRANSPORTDEC_PARSE_ERROR;
}
}
break;
}
if (err == TRANSPORTDEC_OK) {
if (err == TRANSPORTDEC_OK && fConfigFound) {
hTp->flags |= TPDEC_CONFIG_FOUND;
}
......@@ -313,18 +314,16 @@ TRANSPORTDEC_ERROR transportDec_FillData(
/* set bitbuffer shortcut */
hBs = &hTp->bitStream[layer];
switch (hTp->transportFmt) {
case TT_MP4_RAW:
case TT_DRM:
if ( TT_IS_PACKET(hTp->transportFmt) ) {
if (hTp->numberOfRawDataBlocks == 0) {
/* For packet based transport, pass input buffer to bitbuffer without copying the data.
Unfortunately we do not know the actual buffer size. And the FDK bit buffer implementation
needs a number 2^x. So we assume the maximum of 48 channels with 6144 bits per channel
and round it up to the next power of 2 => 65536 bytes */
FDKinitBitStream(hBs, pBuffer, 0x10000, (*pBytesValid)<<3, BS_READER);
*pBytesValid = 0;
break;
default:
}
} else {
/* ... else feed bitbuffer with new stream data (append). */
if (hTp->numberOfRawDataBlocks <= 0) {
FDKfeedBuffer (hBs, pBuffer, bufferSize, pBytesValid) ;
......@@ -368,6 +367,82 @@ INT transportDec_GetBufferFullness( const HANDLE_TRANSPORTDEC hTp )
return bufferFullness;
}
/**
* \brief adjust bit stream position and the end of an access unit.
* \param hTp transport decoder handle.
* \return error code.
*/
static
TRANSPORTDEC_ERROR transportDec_AdjustEndOfAccessUnit(HANDLE_TRANSPORTDEC hTp)
{
HANDLE_FDK_BITSTREAM hBs = &hTp->bitStream[0];
TRANSPORTDEC_ERROR err = TRANSPORTDEC_OK;
switch (hTp->transportFmt) {
case TT_MP4_LOAS:
case TT_MP4_LATM_MCP0:
case TT_MP4_LATM_MCP1:
if ( hTp->numberOfRawDataBlocks == 0 )
{
/* Do byte align at the end of AudioMuxElement. */
FDKbyteAlign(hBs, hTp->globalFramePos);
/* Check global frame length */
if (hTp->transportFmt == TT_MP4_LOAS && hTp->parser.latm.m_audioMuxLengthBytes > 0)
{
int loasOffset;
loasOffset = (hTp->parser.latm.m_audioMuxLengthBytes*8 + FDKgetValidBits(hBs)) - hTp->globalFramePos;
if (loasOffset != 0) {
FDKpushBiDirectional(hBs, loasOffset);
/* For ELD and other payloads there is an unknown amount of padding, so ignore unread bits, but
throw an error only if too many bits where read. */
if (loasOffset < 0) {
err = TRANSPORTDEC_PARSE_ERROR;
}
}
}
}
break;
case TT_MP4_ADTS:
if (hTp->parser.adts.bs.protection_absent == 0)
{
int offset;
/* Calculate offset to end of AU */
offset = hTp->parser.adts.rawDataBlockDist[hTp->parser.adts.bs.num_raw_blocks-hTp->numberOfRawDataBlocks]<<3;
/* CAUTION: The PCE (if available) is declared to be a part of the header! */
offset -= hTp->accessUnitAnchor[0] - FDKgetValidBits(hBs) + 16 + hTp->parser.adts.bs.num_pce_bits;
FDKpushBiDirectional(hBs, offset);
}
if (hTp->parser.adts.bs.num_raw_blocks > 0 && hTp->parser.adts.bs.protection_absent == 0) {
/* Note this CRC read currently happens twice because of transportDec_CrcCheck() */
hTp->parser.adts.crcReadValue = FDKreadBits(hBs, 16);
}
if ( hTp->numberOfRawDataBlocks == 0 )
{
/* Check global frame length */
if (hTp->parser.adts.bs.protection_absent == 0)
{
int offset;
offset = (hTp->parser.adts.bs.frame_length*8 - ADTS_SYNCLENGTH + FDKgetValidBits(hBs)) - hTp->globalFramePos;
if (offset != 0) {
FDKpushBiDirectional(hBs, offset);
}
}
}
break;
default:
break;
}
return err;
}
/**
* \brief Determine additional buffer fullness contraint due to burst data reception.
* The parameter TPDEC_PARAM_BURSTPERIOD must have been set as a precondition.
......@@ -432,51 +507,152 @@ TRANSPORTDEC_ERROR additionalHoldOffNeeded(
}
}
/**
* \brief adjust bit stream position and the end of an access unit.
* \param hTp transport decoder handle.
* \return error code.
*/
static
TRANSPORTDEC_ERROR transportDec_AdjustEndOfAccessUnit(HANDLE_TRANSPORTDEC hTp)
static TRANSPORTDEC_ERROR transportDec_readHeader(
HANDLE_TRANSPORTDEC hTp,
HANDLE_FDK_BITSTREAM hBs,
int syncLength,
int ignoreBufferFullness,
int *pRawDataBlockLength,
int *pfTraverseMoreFrames,
int *pSyncLayerFrameBits,
int *pfConfigFound,
int *pHeaderBits
)
{
HANDLE_FDK_BITSTREAM hBs = &hTp->bitStream[0];
TRANSPORTDEC_ERROR err = TRANSPORTDEC_OK;
int rawDataBlockLength = *pRawDataBlockLength;
int fTraverseMoreFrames = (pfTraverseMoreFrames != NULL) ? *pfTraverseMoreFrames : 0;
int syncLayerFrameBits = (pSyncLayerFrameBits != NULL) ? *pSyncLayerFrameBits : 0;
int fConfigFound = (pfConfigFound != NULL) ? *pfConfigFound : 0;
int startPos;
startPos = FDKgetValidBits(hBs);
switch (hTp->transportFmt) {
case TT_MP4_LOAS:
case TT_MP4_LATM_MCP0:
case TT_MP4_LATM_MCP1:
if ( hTp->numberOfRawDataBlocks == 0 )
case TT_MP4_ADTS:
if (hTp->numberOfRawDataBlocks <= 0)
{
/* Check global frame length */
if (hTp->transportFmt == TT_MP4_LOAS && hTp->parser.latm.m_audioMuxLengthBytes > 0)
{
int loasOffset;
int errC;
loasOffset = (hTp->parser.latm.m_audioMuxLengthBytes*8 + FDKgetValidBits(hBs)) - hTp->globalFramePos;
if (loasOffset != 0) {
FDKpushBiDirectional(hBs, loasOffset);
/* For ELD and other payloads there is an unknown amount of padding, so ignore unread bits, but
throw an error only if too many bits where read. */
if (loasOffset < 0) {
err = TRANSPORTDEC_PARSE_ERROR;
hTp->globalFramePos = FDKgetValidBits(hBs);
/* Parse ADTS header */
err = adtsRead_DecodeHeader( &hTp->parser.adts, &hTp->asc[0], hBs, ignoreBufferFullness );
if (err != TRANSPORTDEC_OK) {
if (err != TRANSPORTDEC_NOT_ENOUGH_BITS) {
err = TRANSPORTDEC_SYNC_ERROR;
}
} else {
errC = hTp->callbacks.cbUpdateConfig(hTp->callbacks.cbUpdateConfigData, &hTp->asc[0]);
if (errC != 0) {
if (errC == TRANSPORTDEC_NEED_TO_RESTART) {
err = TRANSPORTDEC_NEED_TO_RESTART;
goto bail;
} else {
err = TRANSPORTDEC_SYNC_ERROR;
}
} else {
fConfigFound = 1;
hTp->numberOfRawDataBlocks = hTp->parser.adts.bs.num_raw_blocks+1;
}
}
}
else {
/* Reset CRC because the next bits are the beginning of a raw_data_block() */
FDKcrcReset(&hTp->parser.adts.crcInfo);
hTp->parser.adts.bs.num_pce_bits = 0;
}
if (err == TRANSPORTDEC_OK) {
hTp->numberOfRawDataBlocks--;
rawDataBlockLength = adtsRead_GetRawDataBlockLength(&hTp->parser.adts, (hTp->parser.adts.bs.num_raw_blocks-hTp->numberOfRawDataBlocks));
if (rawDataBlockLength <= 0) {
/* No further frame traversal possible. */
fTraverseMoreFrames = 0;
}
syncLayerFrameBits = (hTp->parser.adts.bs.frame_length<<3) - (startPos - FDKgetValidBits(hBs)) - syncLength;
if (syncLayerFrameBits <= 0) {
err = TRANSPORTDEC_SYNC_ERROR;
}
} else {
hTp->numberOfRawDataBlocks = 0;
}
break;
case TT_MP4_LOAS:
if (hTp->numberOfRawDataBlocks <= 0)
{
syncLayerFrameBits = FDKreadBits(hBs, 13);
hTp->parser.latm.m_audioMuxLengthBytes = syncLayerFrameBits;
syncLayerFrameBits <<= 3;
}
case TT_MP4_LATM_MCP1:
case TT_MP4_LATM_MCP0:
if (hTp->numberOfRawDataBlocks <= 0)
{
hTp->globalFramePos = FDKgetValidBits(hBs);
/* Do global LOAS/LATM audioMuxElement byte alignment */
FDKbyteAlign(hBs, hTp->globalFramePos);
err = CLatmDemux_Read(
hBs,
&hTp->parser.latm,
hTp->transportFmt,
&hTp->callbacks,
hTp->asc,
&fConfigFound,
ignoreBufferFullness);
if (err != TRANSPORTDEC_OK) {
if (err != TRANSPORTDEC_NOT_ENOUGH_BITS) {
err = TRANSPORTDEC_SYNC_ERROR;
}
} else {
hTp->numberOfRawDataBlocks = CLatmDemux_GetNrOfSubFrames(&hTp->parser.latm);
if (hTp->transportFmt == TT_MP4_LOAS) {
syncLayerFrameBits -= startPos - FDKgetValidBits(hBs) - (13);
}
}
} else {
err = CLatmDemux_ReadPayloadLengthInfo(hBs, &hTp->parser.latm);
if (err != TRANSPORTDEC_OK) {
err = TRANSPORTDEC_SYNC_ERROR;
}
}
if (err == TRANSPORTDEC_OK) {
rawDataBlockLength = CLatmDemux_GetFrameLengthInBits(&hTp->parser.latm);
hTp->numberOfRawDataBlocks--;
} else {
hTp->numberOfRawDataBlocks = 0;
}
break;
default:
{
syncLayerFrameBits = 0;
}
break;
}
bail:
*pRawDataBlockLength = rawDataBlockLength;
if (pHeaderBits != NULL) {
*pHeaderBits += startPos - (INT)FDKgetValidBits(hBs);
}
if (pfConfigFound != NULL) {
*pfConfigFound = fConfigFound;
}
if (pfTraverseMoreFrames != NULL) {
*pfTraverseMoreFrames = fTraverseMoreFrames;
}
if (pSyncLayerFrameBits != NULL) {
*pSyncLayerFrameBits = syncLayerFrameBits;
}
if (pfConfigFound != NULL) {
*pfConfigFound = fConfigFound;
}
return err;
}
/* How many bits to advance for synchronization search. */
#define TPDEC_SYNCSKIP 8
......@@ -493,9 +669,9 @@ TRANSPORTDEC_ERROR synchronization(
INT rawDataBlockLength = 0, rawDataBlockLengthPrevious;
INT totalBits;
INT headerBits = 0, headerBitsFirstFrame = 0, headerBitsPrevious;
INT numFramesTraversed = 0, fTraverseMoreFrames, fConfigFound = 0, startPos, startPosFirstFrame = -1;
INT numFramesTraversed = 0, fTraverseMoreFrames, fConfigFound = (hTp->flags & TPDEC_CONFIG_FOUND), startPosFirstFrame = -1;
INT numRawDataBlocksFirstFrame = 0, numRawDataBlocksPrevious, globalFramePosFirstFrame = 0, rawDataBlockLengthFirstFrame = 0;
INT ignoreBufferFullness = hTp->flags & (TPDEC_IGNORE_BUFFERFULLNESS|TPDEC_SYNCOK);
INT ignoreBufferFullness = hTp->flags & (TPDEC_LOST_FRAMES_PENDING|TPDEC_IGNORE_BUFFERFULLNESS|TPDEC_SYNCOK);
/* Synch parameters */
INT syncLength; /* Length of sync word in bits */
......@@ -506,10 +682,7 @@ TRANSPORTDEC_ERROR synchronization(
totalBits = (INT)FDKgetValidBits(hBs);
if (totalBits <= 0) {
/* Return sync error, because this happens only in case of severly damaged bit streams.
Returning TRANSPORTDEC_NOT_ENOUGH_BITS here is very dangerous. */
/* numberOfRawDataBlocks must be always reset in case of sync errors. */
hTp->numberOfRawDataBlocks = 0;
err = TRANSPORTDEC_NOT_ENOUGH_BITS;
goto bail;
}
......@@ -579,100 +752,22 @@ TRANSPORTDEC_ERROR synchronization(
numRawDataBlocksPrevious = hTp->numberOfRawDataBlocks;
/* Parse transport header (raw data block granularity) */
startPos = FDKgetValidBits(hBs);
if (err == TRANSPORTDEC_OK )
{
switch (hTp->transportFmt) {
case TT_MP4_ADTS:
if (hTp->numberOfRawDataBlocks <= 0)
{
int errC;
/* Parse ADTS header */
err = adtsRead_DecodeHeader( &hTp->parser.adts, &hTp->asc[0], hBs, ignoreBufferFullness );
if (err != TRANSPORTDEC_OK) {
if (err != TRANSPORTDEC_NOT_ENOUGH_BITS) {
err = TRANSPORTDEC_SYNC_ERROR;
}
} else {
errC = hTp->callbacks.cbUpdateConfig(hTp->callbacks.cbUpdateConfigData, &hTp->asc[0]);
if (errC != 0) {
err = TRANSPORTDEC_SYNC_ERROR;
} else {
hTp->numberOfRawDataBlocks = hTp->parser.adts.bs.num_raw_blocks+1;
/* CAUTION: The PCE (if available) is declared to be a part of the header! */
hTp->globalFramePos = FDKgetValidBits(hBs) + hTp->parser.adts.bs.num_pce_bits;
}
}
}
else {
/* Reset CRC because the next bits are the beginning of a raw_data_block() */
FDKcrcReset(&hTp->parser.adts.crcInfo);
hTp->globalFramePos = FDKgetValidBits(hBs);
}
if (err == TRANSPORTDEC_OK) {
hTp->numberOfRawDataBlocks--;
rawDataBlockLength = adtsRead_GetRawDataBlockLength(&hTp->parser.adts, (hTp->parser.adts.bs.num_raw_blocks-hTp->numberOfRawDataBlocks));
syncLayerFrameBits = (hTp->parser.adts.bs.frame_length<<3) - (startPos - FDKgetValidBits(hBs)) - syncLength;
if (syncLayerFrameBits <= 0) {
err = TRANSPORTDEC_SYNC_ERROR;
}
} else {
hTp->numberOfRawDataBlocks = 0;
}
break;
case TT_MP4_LOAS:
if (hTp->numberOfRawDataBlocks <= 0)
{
syncLayerFrameBits = FDKreadBits(hBs, 13);
hTp->parser.latm.m_audioMuxLengthBytes = syncLayerFrameBits;
syncLayerFrameBits <<= 3;
}
case TT_MP4_LATM_MCP1:
case TT_MP4_LATM_MCP0:
if (hTp->numberOfRawDataBlocks <= 0)
{
hTp->globalFramePos = FDKgetValidBits(hBs);
err = CLatmDemux_Read(
hBs,
&hTp->parser.latm,
hTp->transportFmt,
&hTp->callbacks,
hTp->asc,
ignoreBufferFullness);
if (err != TRANSPORTDEC_OK) {
if (err != TRANSPORTDEC_NOT_ENOUGH_BITS) {
err = TRANSPORTDEC_SYNC_ERROR;
}
} else {
hTp->numberOfRawDataBlocks = CLatmDemux_GetNrOfSubFrames(&hTp->parser.latm);
syncLayerFrameBits -= startPos - FDKgetValidBits(hBs) - (13);
}
} else {
err = CLatmDemux_ReadPayloadLengthInfo(hBs, &hTp->parser.latm);
if (err != TRANSPORTDEC_OK) {
err = TRANSPORTDEC_SYNC_ERROR;
}
}
if (err == TRANSPORTDEC_OK) {
rawDataBlockLength = CLatmDemux_GetFrameLengthInBits(&hTp->parser.latm);
hTp->numberOfRawDataBlocks--;
} else {
hTp->numberOfRawDataBlocks = 0;
}
break;
default:
{
syncLayerFrameBits = 0;
}
break;
}
err = transportDec_readHeader(
hTp,
hBs,
syncLength,
ignoreBufferFullness,
&rawDataBlockLength,
&fTraverseMoreFrames,
&syncLayerFrameBits,
&fConfigFound,
&headerBits
);
}
headerBits += startPos - (INT)FDKgetValidBits(hBs);
bitsAvail -= headerBits;
checkLengthBits = syncLayerFrameBits;
......@@ -702,12 +797,12 @@ TRANSPORTDEC_ERROR synchronization(
/* Enforce re-sync of transport headers. */
hTp->numberOfRawDataBlocks = 0;
/* Ensure that the bit amount lands and a multiple of TPDEC_SYNCSKIP */
/* Ensure that the bit amount lands at a multiple of TPDEC_SYNCSKIP */
bits = (bitsAvail + headerBits) % TPDEC_SYNCSKIP;
/* Rewind - TPDEC_SYNCSKIP, in order to look for a synch one bit ahead next time. */
FDKpushBiDirectional(hBs, -(headerBits - TPDEC_SYNCSKIP) + bits);
bitsAvail += headerBits - TPDEC_SYNCSKIP - bits;
headerBits = 0;
headerBits = 0;
}
/* Frame traversal */
......@@ -731,7 +826,15 @@ TRANSPORTDEC_ERROR synchronization(
}
/* Break when config was found or it is not possible anymore to find a config */
if (startPosFirstFrame != -1 && (fConfigFound || err != TRANSPORTDEC_OK)) {
if (startPosFirstFrame != -1 && (fConfigFound || err != TRANSPORTDEC_OK))
{
/* In case of ECD and sync error, do not rewind anywhere. */
if (err == TRANSPORTDEC_SYNC_ERROR)
{
startPosFirstFrame = -1;
fConfigFound = 0;
numFramesTraversed = 0;
}
break;
}
}
......@@ -759,7 +862,7 @@ TRANSPORTDEC_ERROR synchronization(
}
/* Additional burst data mode buffer fullness check. */
if ( !(hTp->flags & (TPDEC_IGNORE_BUFFERFULLNESS|TPDEC_SYNCOK)) && err == TRANSPORTDEC_OK) {
if ( !(hTp->flags & (TPDEC_LOST_FRAMES_PENDING|TPDEC_IGNORE_BUFFERFULLNESS|TPDEC_SYNCOK)) && err == TRANSPORTDEC_OK) {
err = additionalHoldOffNeeded(hTp, transportDec_GetBufferFullness(hTp), FDKgetValidBits(hBs) - syncLayerFrameBits);
if (err == TRANSPORTDEC_NOT_ENOUGH_BITS) {
hTp->holdOffFrames++;
......@@ -789,10 +892,22 @@ TRANSPORTDEC_ERROR synchronization(
bail:
hTp->auLength[0] = rawDataBlockLength;
/* Detect pointless TRANSPORTDEC_NOT_ENOUGH_BITS error case, were the bit buffer is already full,
or no new burst packet fits. Recover by advancing the bit buffer. */
if ( (TRANSPORTDEC_NOT_ENOUGH_BITS == err) && (FDKgetValidBits(hBs) >= ((TRANSPORTDEC_INBUF_SIZE*8 - ((hTp->avgBitRate*hTp->burstPeriod)/1000)) - 7)) )
{
FDKpushFor(hBs, TPDEC_SYNCSKIP);
err = TRANSPORTDEC_SYNC_ERROR;
}
if (err == TRANSPORTDEC_OK) {
hTp->flags |= TPDEC_SYNCOK;
}
if (fConfigFound) {
hTp->flags |= TPDEC_CONFIG_FOUND;
}
if (pHeaderBits != NULL) {
*pHeaderBits = headerBits;
}
......@@ -925,6 +1040,10 @@ TRANSPORTDEC_ERROR transportDec_ReadAccessUnit( const HANDLE_TRANSPORTDEC hTp, c
hBs = &hTp->bitStream[layer];
if ((INT)FDKgetValidBits(hBs) <= 0) {
err = TRANSPORTDEC_NOT_ENOUGH_BITS;
}
switch (hTp->transportFmt) {
case TT_MP4_ADIF:
......@@ -964,20 +1083,26 @@ TRANSPORTDEC_ERROR transportDec_ReadAccessUnit( const HANDLE_TRANSPORTDEC hTp, c
break;
case TT_MP4_RAW:
if ((INT)FDKgetValidBits(hBs) <= 0 && layer == 0) {
err = TRANSPORTDEC_NOT_ENOUGH_BITS;
}
/* One Access Unit was filled into buffer.
So get the length out of the buffer. */
hTp->auLength[layer] = FDKgetValidBits(hBs);
hTp->flags |= TPDEC_SYNCOK;
break;
case TT_MP4_LATM_MCP0:
case TT_MP4_LATM_MCP1:
{
int fConfigFound = hTp->flags & TPDEC_CONFIG_FOUND;
err = transportDec_readHeader(hTp, hBs, 0, 1, &hTp->auLength[layer], NULL, NULL, &fConfigFound, NULL);
if (fConfigFound) {
hTp->flags |= TPDEC_CONFIG_FOUND;
}
}
break;
case TT_RSVD50:
case TT_MP4_ADTS:
case TT_MP4_LOAS:
case TT_MP4_LATM_MCP0:
case TT_MP4_LATM_MCP1:
err = transportDec_readStream(hTp, layer);
break;
......@@ -1026,13 +1151,10 @@ TRANSPORTDEC_ERROR transportDec_EndAccessUnit(HANDLE_TRANSPORTDEC hTp)
{
TRANSPORTDEC_ERROR err = TRANSPORTDEC_OK;
err = transportDec_AdjustEndOfAccessUnit(hTp);
switch (hTp->transportFmt) {
case TT_MP4_LOAS:
case TT_MP4_LATM_MCP0:
case TT_MP4_LATM_MCP1:
break;
default:
break;
}
......@@ -1082,8 +1204,11 @@ TRANSPORTDEC_ERROR transportDec_SetParam ( const HANDLE_TRANSPORTDEC hTp,
FDKresetBitbuffer(&hTp->bitStream[i]);
hTp->auLength[i] = 0;
hTp->accessUnitAnchor[i] = 0;
}
}
hTp->flags &= ~(TPDEC_SYNCOK|TPDEC_LOST_FRAMES_PENDING);
if (hTp->transportFmt != TT_MP4_ADIF) {
hTp->flags &= ~TPDEC_CONFIG_FOUND;
}
hTp->remainder = 0;
hTp->avgBitRate = 0;
hTp->missingAccessUnits = 0;
......@@ -1117,7 +1242,7 @@ void transportDec_Close(HANDLE_TRANSPORTDEC *phTp)
if (phTp != NULL)
{
if (*phTp != NULL) {
if ((*phTp)->transportFmt != TT_MP4_RAW && (*phTp)->transportFmt != TT_DRM) {
if ( ! TT_IS_PACKET((*phTp)->transportFmt) ) {
FreeRam_TransportDecoderBuffer(&(*phTp)->bsBuffer);
}
if (*phTp != NULL) {
......@@ -1188,13 +1313,8 @@ TRANSPORTDEC_ERROR transportDec_CrcCheck(HANDLE_TRANSPORTDEC pTp)
if ( (pTp->parser.adts.bs.num_raw_blocks > 0) && (pTp->parser.adts.bs.protection_absent == 0) )
{
HANDLE_FDK_BITSTREAM hBs = &pTp->bitStream[0];
int bitDiff;
/* Calculate possible offset to CRC value. */
bitDiff = pTp->parser.adts.rawDataBlockDist[pTp->parser.adts.bs.num_raw_blocks-pTp->numberOfRawDataBlocks]<<3;
bitDiff -= pTp->globalFramePos - FDKgetValidBits(hBs) + 16;
FDKpushBiDirectional(hBs, bitDiff);
pTp->parser.adts.crcReadValue = FDKreadBits(hBs, 16);
transportDec_AdjustEndOfAccessUnit(pTp);
}
return adtsRead_CrcCheck(&pTp->parser.adts);
default:
......
......@@ -2,7 +2,7 @@
/* library info */
#define TP_LIB_VL0 2
#define TP_LIB_VL1 3
#define TP_LIB_VL2 1
#define TP_LIB_VL2 2
#define TP_LIB_TITLE "MPEG Transport"
#define TP_LIB_BUILD_DATE __DATE__
#define TP_LIB_BUILD_TIME __TIME__
......@@ -624,8 +624,8 @@ timeCompensateFirstEnvelope (HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static con
deltaExp = FDK_getNumOctavesDiv8(newLen, refLen);
/* Shift by -3 to rescale ld-table, 1-ampRes to enable coarser steps */
shift = (FRACT_BITS - 1 - ENV_EXP_FRACT + 1 - h_sbr_data->ampResolutionCurrentFrame - 3);
/* Shift by -3 to rescale ld-table, ampRes-1 to enable coarser steps */
shift = (FRACT_BITS - 1 - ENV_EXP_FRACT - 1 + h_sbr_data->ampResolutionCurrentFrame - 3);
deltaExp = deltaExp >> shift;
pFrameInfo->borders[0] = estimatedStartPos;
pFrameInfo->bordersNoise[0] = estimatedStartPos;
......
......@@ -875,22 +875,8 @@ resetLppTransposer (HANDLE_SBR_LPP_TRANS hLppTrans, /*!< Handle of lpp transpos
/*
* Initialize the patching parameter
*/
desiredBorder = 21;
if (fs < 92017) {
desiredBorder = 23;
}
if (fs < 75132) {
desiredBorder = 32;
}
if (fs < 55426) {
desiredBorder = 43;
}
if (fs < 46009) {
desiredBorder = 46;
}
if (fs < 35777) {
desiredBorder = 64;
}
/* ISO/IEC 14496-3 (Figure 4.48): goalSb = round( 2.048e6 / fs ) */
desiredBorder = (((2048000*2) / fs) + 1) >> 1;
desiredBorder = findClosestEntry(desiredBorder, v_k_master, numMaster, 1); /* Adapt region to master-table */
......
......@@ -137,7 +137,7 @@ amm-info@iis.fraunhofer.de
/* Decoder library info */
#define SBRDECODER_LIB_VL0 2
#define SBRDECODER_LIB_VL1 2
#define SBRDECODER_LIB_VL2 2
#define SBRDECODER_LIB_VL2 3
#define SBRDECODER_LIB_TITLE "SBR Decoder"
#define SBRDECODER_LIB_BUILD_DATE __DATE__
#define SBRDECODER_LIB_BUILD_TIME __TIME__
......@@ -552,7 +552,7 @@ bail:
sbrDecoder_DestroyElement( self, elementIndex );
} else if (self->pSbrElement[elementIndex] != NULL) {
/* Set error flag to trigger concealment */
self->pSbrElement[elementIndex]->frameErrorFlag[self->pSbrElement[elementIndex]->useFrameSlot] = 1;;
self->pSbrElement[elementIndex]->frameErrorFlag[self->pSbrElement[elementIndex]->useFrameSlot] = 1;
}
}
......@@ -731,6 +731,12 @@ SBR_ERROR sbrDecoder_SetParam (HANDLE_SBRDECODER self,
case SBR_BS_INTERRUPTION:
{
int elementIndex;
if (self == NULL) {
errorStatus = SBRDEC_NOT_INITIALIZED;
break;
}
/* Loop over SBR elements */
for (elementIndex = 0; elementIndex < self->numSbrElements; elementIndex++)
{
......
......@@ -144,6 +144,12 @@ typedef enum
} TRANSPORT_TYPE;
#define TT_IS_PACKET(x) \
( ((x) == TT_MP4_RAW) \
|| ((x) == TT_DRM) \
|| ((x) == TT_MP4_LATM_MCP0) \
|| ((x) == TT_MP4_LATM_MCP1) )
/**
* Audio Object Type definitions.
*/
......
......@@ -99,7 +99,7 @@ amm-info@iis.fraunhofer.de
/* library info */
#define SYS_LIB_VL0 1
#define SYS_LIB_VL1 3
#define SYS_LIB_VL2 1
#define SYS_LIB_VL2 2
#define SYS_LIB_TITLE "System Integration Library"
#define SYS_LIB_BUILD_DATE __DATE__
#define SYS_LIB_BUILD_TIME __TIME__
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment