mirror of https://github.com/mstorsjo/fdk-aac.git
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
This commit is contained in:
parent
b9774f9065
commit
5016eb7f65
|
@ -394,18 +394,21 @@ 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 */
|
||||
|
@ -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
|
||||
|
@ -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,9 +776,13 @@ LINKSPEC_CPP void CAacDecoder_Close(HANDLE_AACDECODER self)
|
|||
|
||||
for (ch=0; ch<(6); ch++) {
|
||||
if (self->pAacDecoderStaticChannelInfo[ch] != NULL) {
|
||||
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);
|
||||
}
|
||||
|
||||
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,13 +1428,20 @@ 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 */
|
||||
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++) {
|
||||
|
@ -1413,7 +1454,8 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
|
|||
self->frameOK = 0;
|
||||
}
|
||||
}
|
||||
pceRead = 1;
|
||||
pceRead = (result>=0) ? 1 : 0;
|
||||
}
|
||||
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:
|
||||
if (self != NULL) {
|
||||
self->channelOutputMapping = channelMappingTablePassthrough;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
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);
|
||||
#else
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
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 {
|
||||
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))) {
|
||||
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) {
|
||||
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) {
|
||||
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 {
|
||||
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,17 +235,15 @@ 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;
|
||||
|
||||
|
@ -253,8 +252,10 @@ TRANSPORTDEC_ERROR transportDec_OutOfBandConfig(HANDLE_TRANSPORTDEC hTp, UCHAR *
|
|||
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_ADTS:
|
||||
if (hTp->numberOfRawDataBlocks <= 0)
|
||||
{
|
||||
int errC;
|
||||
|
||||
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:
|
||||
case TT_MP4_LATM_MCP0:
|
||||
if (hTp->numberOfRawDataBlocks <= 0)
|
||||
{
|
||||
syncLayerFrameBits = FDKreadBits(hBs, 13);
|
||||
hTp->parser.latm.m_audioMuxLengthBytes = syncLayerFrameBits;
|
||||
syncLayerFrameBits <<= 3;
|
||||
}
|
||||
case TT_MP4_LATM_MCP1:
|
||||
if ( hTp->numberOfRawDataBlocks == 0 )
|
||||
case TT_MP4_LATM_MCP0:
|
||||
if (hTp->numberOfRawDataBlocks <= 0)
|
||||
{
|
||||
/* Check global frame length */
|
||||
if (hTp->transportFmt == TT_MP4_LOAS && hTp->parser.latm.m_audioMuxLengthBytes > 0)
|
||||
{
|
||||
int loasOffset;
|
||||
hTp->globalFramePos = FDKgetValidBits(hBs);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
err = CLatmDemux_Read(
|
||||
hBs,
|
||||
&hTp->parser.latm,
|
||||
hTp->transportFmt,
|
||||
&hTp->callbacks,
|
||||
hTp->asc,
|
||||
&fConfigFound,
|
||||
ignoreBufferFullness);
|
||||
|
||||
/* Do global LOAS/LATM audioMuxElement byte alignment */
|
||||
FDKbyteAlign(hBs, hTp->globalFramePos);
|
||||
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(
|
||||
err = transportDec_readHeader(
|
||||
hTp,
|
||||
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;
|
||||
}
|
||||
syncLength,
|
||||
ignoreBufferFullness,
|
||||
&rawDataBlockLength,
|
||||
&fTraverseMoreFrames,
|
||||
&syncLayerFrameBits,
|
||||
&fConfigFound,
|
||||
&headerBits
|
||||
);
|
||||
}
|
||||
|
||||
headerBits += startPos - (INT)FDKgetValidBits(hBs);
|
||||
bitsAvail -= headerBits;
|
||||
|
||||
checkLengthBits = syncLayerFrameBits;
|
||||
|
@ -702,7 +797,7 @@ 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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -1084,6 +1206,9 @@ TRANSPORTDEC_ERROR transportDec_SetParam ( const HANDLE_TRANSPORTDEC hTp,
|
|||
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__
|
||||
|
|
Loading…
Reference in New Issue