aboutsummaryrefslogtreecommitdiffstats
path: root/libAACdec/src
diff options
context:
space:
mode:
Diffstat (limited to 'libAACdec/src')
-rw-r--r--libAACdec/src/aac_ram.cpp8
-rw-r--r--libAACdec/src/aac_rom.cpp50
-rw-r--r--libAACdec/src/aac_rom.h9
-rw-r--r--libAACdec/src/aacdec_drc.cpp104
-rw-r--r--libAACdec/src/aacdec_drc.h17
-rw-r--r--libAACdec/src/aacdec_drc_types.h4
-rw-r--r--libAACdec/src/aacdecoder.cpp188
-rw-r--r--libAACdec/src/aacdecoder.h29
-rw-r--r--libAACdec/src/aacdecoder_lib.cpp165
-rw-r--r--libAACdec/src/conceal.cpp15
10 files changed, 454 insertions, 135 deletions
diff --git a/libAACdec/src/aac_ram.cpp b/libAACdec/src/aac_ram.cpp
index a38f57c..1ff289b 100644
--- a/libAACdec/src/aac_ram.cpp
+++ b/libAACdec/src/aac_ram.cpp
@@ -108,15 +108,15 @@ C_ALLOC_MEM(AacDecoder, AAC_DECODER_INSTANCE, 1)
/*! The structure CAacDecoderStaticChannelInfo contains the static sideinfo which is needed
for the decoding of one aac channel. <br>
Dimension: #AacDecoderChannels */
-C_ALLOC_MEM2(AacDecoderStaticChannelInfo, CAacDecoderStaticChannelInfo, 1, (6))
+C_ALLOC_MEM2(AacDecoderStaticChannelInfo, CAacDecoderStaticChannelInfo, 1, (8))
/*! The structure CAacDecoderChannelInfo contains the dynamic sideinfo which is needed
for the decoding of one aac channel. <br>
Dimension: #AacDecoderChannels */
-C_ALLOC_MEM2(AacDecoderChannelInfo, CAacDecoderChannelInfo, 1, (6))
+C_AALLOC_MEM2(AacDecoderChannelInfo, CAacDecoderChannelInfo, 1, (8))
/*! Overlap buffer */
-C_ALLOC_MEM2(OverlapBuffer, FIXP_DBL, OverlapBufferSize, (6))
+C_ALLOC_MEM2(OverlapBuffer, FIXP_DBL, OverlapBufferSize, (8))
C_ALLOC_MEM(DrcInfo, CDrcInfo, 1)
@@ -128,7 +128,7 @@ C_ALLOC_MEM(DrcInfo, CDrcInfo, 1)
Dynamic memory areas, might be reused in other algorithm sections,
e.g. the sbr decoder
*/
-C_ALLOC_MEM_OVERLAY(WorkBufferCore2, FIXP_DBL, ((6)*1024), SECT_DATA_L2, WORKBUFFER2_TAG)
+C_ALLOC_MEM_OVERLAY(WorkBufferCore2, FIXP_DBL, ((8)*1024), SECT_DATA_L2, WORKBUFFER2_TAG)
C_ALLOC_MEM_OVERLAY(WorkBufferCore1, CWorkBufferCore1, 1, SECT_DATA_L1, WORKBUFFER1_TAG)
diff --git a/libAACdec/src/aac_rom.cpp b/libAACdec/src/aac_rom.cpp
index fa04c42..607cb3b 100644
--- a/libAACdec/src/aac_rom.cpp
+++ b/libAACdec/src/aac_rom.cpp
@@ -1777,42 +1777,62 @@ const FIXP_TCC FDKaacDec_tnsCoeff4 [16] =
};
/* MPEG like mapping (no change). */
-const UCHAR channelMappingTablePassthrough[8][8] =
+const UCHAR channelMappingTablePassthrough[15][8] =
{
+ { 0, 1, 2, 3, 4, 5, 6, 7}, /* fallback */
{ 0, 1,255,255,255,255,255,255}, /* mono / PS */
{ 0, 1,255,255,255,255,255,255}, /* stereo */
{ 0, 1, 2,255,255,255,255,255}, /* 3ch */
{ 0, 1, 2, 3,255,255,255,255}, /* 4ch */
{ 0, 1, 2, 3, 4,255,255,255}, /* 5ch */
{ 0, 1, 2, 3, 4, 5,255,255}, /* 5.1ch */
- { 0, 1, 2, 3, 4, 5, 6, 7}, /* 7ch */
- { 0, 1, 2, 3, 4, 5, 6, 7} /* 7.1ch */
+ { 0, 1, 2, 3, 4, 5, 6, 7}, /* 7.1 front */
+ { 0, 1, 2, 3, 4, 5, 6, 7}, /* reserved */
+ { 0, 1, 2, 3, 4, 5, 6, 7}, /* reserved */
+ { 0, 1, 2, 3, 4, 5, 6, 7}, /* reserved */
+ { 0, 1, 2, 3, 4, 5, 6,255}, /* 6.1ch */
+ { 0, 1, 2, 3, 4, 5, 6, 7}, /* 7.1 rear */
+ { 0, 1, 2, 3, 4, 5, 6, 7}, /* reserved */
+ { 0, 1, 2, 3, 4, 5, 6, 7} /* 7.1 top */
};
/* WAV file like mapping (from MPEG mapping). */
-const UCHAR channelMappingTableWAV[8][8] =
+const UCHAR channelMappingTableWAV[15][8] =
{
+ { 0, 1, 2, 3, 4, 5, 6, 7}, /* fallback */
{ 0, 1,255,255,255,255,255,255}, /* mono / PS */
{ 0, 1,255,255,255,255,255,255}, /* stereo */
{ 2, 0, 1,255,255,255,255,255}, /* 3ch */
{ 2, 0, 1, 3,255,255,255,255}, /* 4ch */
{ 2, 0, 1, 3, 4,255,255,255}, /* 5ch */
{ 2, 0, 1, 4, 5, 3,255,255}, /* 5.1ch */
- { 0, 1, 2, 3, 4, 5, 6, 7}, /* 7ch */
- { 2, 0, 1, 6, 7, 4, 5, 3} /* 7.1ch */
+ { 2, 6, 7, 0, 1, 4, 5, 3}, /* 7.1 front */
+ { 0, 1, 2, 3, 4, 5, 6, 7}, /* reserved */
+ { 0, 1, 2, 3, 4, 5, 6, 7}, /* reserved */
+ { 0, 1, 2, 3, 4, 5, 6, 7}, /* reserved */
+ { 2, 0, 1, 4, 5, 6, 3,255}, /* 6.1ch */
+ { 2, 0, 1, 6, 7, 4, 5, 3}, /* 7.1 rear */
+ { 0, 1, 2, 3, 4, 5, 6, 7}, /* reserved */
+ { 2, 0, 1, 4, 5, 3, 6, 7} /* 7.1 top */
};
/* Lookup tables for elements in ER bitstream */
-const MP4_ELEMENT_ID elementsTab[8][7] =
+const MP4_ELEMENT_ID elementsTab[15][7] =
{
- {ID_SCE, ID_EXT, ID_END, ID_NONE, ID_NONE,ID_NONE,ID_NONE }, /* 1 channel */
- {ID_CPE, ID_EXT, ID_END, ID_NONE, ID_NONE,ID_NONE,ID_NONE } /* 2 channels */
- ,
- {ID_SCE, ID_CPE, ID_EXT, ID_END, ID_NONE,ID_NONE,ID_NONE }, /* 3 channels */
- {ID_SCE, ID_CPE, ID_SCE, ID_EXT, ID_END, ID_NONE,ID_NONE }, /* 4 channels */
- {ID_SCE, ID_CPE, ID_CPE, ID_EXT, ID_END, ID_NONE,ID_NONE }, /* 5 channels */
- {ID_SCE, ID_CPE, ID_CPE, ID_LFE, ID_EXT, ID_END, ID_NONE }, /* 6 channels */
- {ID_SCE, ID_CPE, ID_CPE, ID_CPE, ID_LFE, ID_EXT, ID_END} /* 8 channels */
+ /* 1 */ { ID_SCE, ID_EXT, ID_END, ID_NONE, ID_NONE, ID_NONE, ID_NONE }, /* 1 channel */
+ /* 2 */ { ID_CPE, ID_EXT, ID_END, ID_NONE, ID_NONE, ID_NONE, ID_NONE } /* 2 channels */
+ /* 3 */ ,{ ID_SCE, ID_CPE, ID_EXT, ID_END, ID_NONE, ID_NONE, ID_NONE }, /* 3 channels */
+ /* 4 */ { ID_SCE, ID_CPE, ID_SCE, ID_EXT, ID_END, ID_NONE, ID_NONE }, /* 4 channels */
+ /* 5 */ { ID_SCE, ID_CPE, ID_CPE, ID_EXT, ID_END, ID_NONE, ID_NONE }, /* 5 channels */
+ /* 6 */ { ID_SCE, ID_CPE, ID_CPE, ID_LFE, ID_EXT, ID_END, ID_NONE } /* 6 channels */
+ /* 7 */ ,{ ID_SCE, ID_CPE, ID_CPE, ID_CPE, ID_LFE, ID_EXT, ID_END }, /* 8 channels */
+ /* 8 */ { ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE }, /* reserved */
+ /* 9 */ { ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE }, /* reserved */
+ /* 10 */ { ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE }, /* reserved */
+ /* 11 */ { ID_SCE, ID_CPE, ID_CPE, ID_SCE, ID_LFE, ID_EXT, ID_END }, /* 7 channels */
+ /* 12 */ { ID_SCE, ID_CPE, ID_CPE, ID_CPE, ID_LFE, ID_EXT, ID_END }, /* 8 channels */
+ /* 13 */ { ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE }, /* reserved */
+ /* 14 */ { ID_SCE, ID_CPE, ID_CPE, ID_LFE, ID_CPE, ID_EXT, ID_END } /* 8 channels */
};
/*! Random sign bit used for concealment
diff --git a/libAACdec/src/aac_rom.h b/libAACdec/src/aac_rom.h
index 536d184..f314a2d 100644
--- a/libAACdec/src/aac_rom.h
+++ b/libAACdec/src/aac_rom.h
@@ -177,11 +177,12 @@ extern const USHORT randomSign[AAC_NF_NO_RANDOM_VAL/16];
extern const FIXP_DBL pow2_div24minus1[47];
extern const int offsetTab[2][16];
-/* Channel mapping indices for time domain I/O. First dimension is channel count-1. */
-extern const UCHAR channelMappingTablePassthrough[8][8];
-extern const UCHAR channelMappingTableWAV[8][8];
+/* Channel mapping indices for time domain I/O.
+ The first dimension is the channel configuration index. */
+extern const UCHAR channelMappingTablePassthrough[15][8];
+extern const UCHAR channelMappingTableWAV[15][8];
/* Lookup tables for elements in ER bitstream */
-extern const MP4_ELEMENT_ID elementsTab[8][7];
+extern const MP4_ELEMENT_ID elementsTab[15][7];
#endif /* #ifndef AAC_ROM_H */
diff --git a/libAACdec/src/aacdec_drc.cpp b/libAACdec/src/aacdec_drc.cpp
index 2666454..0c33a2b 100644
--- a/libAACdec/src/aacdec_drc.cpp
+++ b/libAACdec/src/aacdec_drc.cpp
@@ -130,7 +130,6 @@ void aacDecoder_drcInit (
/* init control fields */
self->enable = 0;
self->numThreads = 0;
- self->digitalNorm = 0;
/* init params */
pParams = &self->params;
@@ -139,12 +138,15 @@ void aacDecoder_drcInit (
pParams->usrCut = FL2FXCONST_DBL(0.0f);
pParams->boost = FL2FXCONST_DBL(0.0f);
pParams->usrBoost = FL2FXCONST_DBL(0.0f);
- pParams->targetRefLevel = AACDEC_DRC_DEFAULT_REF_LEVEL;
+ pParams->targetRefLevel = -1;
pParams->expiryFrame = AACDEC_DRC_DFLT_EXPIRY_FRAMES;
+ pParams->applyDigitalNorm = 0;
pParams->applyHeavyCompression = 0;
/* initial program ref level = target ref level */
self->progRefLevel = pParams->targetRefLevel;
+ self->progRefLevelPresent = 0;
+ self->presMode = -1;
}
@@ -222,11 +224,12 @@ AAC_DECODER_ERROR aacDecoder_drcSetParam (
return AAC_DEC_INVALID_HANDLE;
}
if (value < 0) {
- self->digitalNorm = 0;
+ self->params.applyDigitalNorm = 0;
+ self->params.targetRefLevel = -1;
}
else {
/* ref_level must be between 0 and MAX_REFERENCE_LEVEL, inclusive */
- self->digitalNorm = 1;
+ self->params.applyDigitalNorm = 1;
if (self->params.targetRefLevel != (SCHAR)value) {
self->params.targetRefLevel = (SCHAR)value;
self->progRefLevel = (SCHAR)value; /* Always set the program reference level equal to the
@@ -234,6 +237,16 @@ AAC_DECODER_ERROR aacDecoder_drcSetParam (
}
}
break;
+ case APPLY_NORMALIZATION:
+ if (value < 0 || value > 1) {
+ return AAC_DEC_SET_PARAM_FAIL;
+ }
+ if (self == NULL) {
+ return AAC_DEC_INVALID_HANDLE;
+ }
+ /* Store new parameter value */
+ self->params.applyDigitalNorm = (UCHAR)value;
+ break;
case APPLY_HEAVY_COMPRESSION:
if (value < 0 || value > 1) {
return AAC_DEC_SET_PARAM_FAIL;
@@ -278,7 +291,7 @@ AAC_DECODER_ERROR aacDecoder_drcSetParam (
self->enable = ( (self->params.boost > (FIXP_DBL)0)
|| (self->params.cut > (FIXP_DBL)0)
|| (self->params.applyHeavyCompression != 0)
- || (self->digitalNorm == 1) );
+ || (self->params.targetRefLevel >= 0) );
return ErrorStatus;
@@ -539,7 +552,7 @@ static int aacDecoder_drcReadCompression (
UINT payloadPosition )
{
int bitCnt = 0;
- int dmxLevelsPresent, compressionPresent;
+ int dmxLevelsPresent, extensionPresent, compressionPresent;
int coarseGrainTcPresent, fineGrainTcPresent;
/* Move to the beginning of the DRC payload field */
@@ -561,8 +574,9 @@ static int aacDecoder_drcReadCompression (
return 0;
}
FDKreadBits(bs, 2); /* dolby_surround_mode */
- FDKreadBits(bs, 2); /* presentation_mode */
- if (FDKreadBits(bs, 2) != 0) { /* reserved, set to 0 */
+ pDrcBs->presMode = FDKreadBits(bs, 2); /* presentation_mode */
+ FDKreadBits(bs, 1); /* stereo_downmix_mode */
+ if (FDKreadBits(bs, 1) != 0) { /* reserved, set to 0 */
return 0;
}
@@ -571,9 +585,7 @@ static int aacDecoder_drcReadCompression (
return 0;
}
dmxLevelsPresent = FDKreadBits(bs, 1); /* downmixing_levels_MPEG4_status */
- if (FDKreadBits(bs, 1) != 0) { /* reserved, set to 0 */
- return 0;
- }
+ extensionPresent = FDKreadBits(bs, 1); /* ancillary_data_extension_status; */
compressionPresent = FDKreadBits(bs, 1); /* audio_coding_mode_and_compression status */
coarseGrainTcPresent = FDKreadBits(bs, 1); /* coarse_grain_timecode_status */
fineGrainTcPresent = FDKreadBits(bs, 1); /* fine_grain_timecode_status */
@@ -631,6 +643,19 @@ static int aacDecoder_drcReadCompression (
bitCnt += 16;
}
+ /* Read extension just to get the right amount of bits. */
+ if (extensionPresent) {
+ int extBits = 8;
+
+ FDKreadBits(bs, 1); /* reserved, set to 0 */
+ if (FDKreadBits(bs, 1)) extBits += 8; /* ext_downmixing_levels_status */
+ if (FDKreadBits(bs, 1)) extBits += 16; /* ext_downmixing_global_gains_status */
+ if (FDKreadBits(bs, 1)) extBits += 8; /* ext_downmixing_lfe_level_status */
+
+ FDKpushFor(bs, extBits - 4); /* skip the extension payload remainder. */
+ bitCnt += extBits;
+ }
+
return (bitCnt);
}
@@ -780,9 +805,15 @@ static int aacDecoder_drcExtractAndMap (
*/
if (pThreadBs->progRefLevel >= 0) {
self->progRefLevel = pThreadBs->progRefLevel;
+ self->progRefLevelPresent = 1;
self->prlExpiryCount = 0; /* Got a new value -> Reset counter */
}
+ if (drcPayloadType == DVB_DRC_ANC_DATA) {
+ /* Announce the presentation mode of this valid thread. */
+ self->presMode = pThreadBs->presMode;
+ }
+
/* SCE, CPE and LFE */
for (ch = 0; ch < validChannels; ch++) {
int mapedChannel = channelMapping[ch];
@@ -802,6 +833,7 @@ static int aacDecoder_drcExtractAndMap (
if ( (pParams->expiryFrame > 0)
&& (self->prlExpiryCount++ > pParams->expiryFrame) )
{ /* The program reference level is too old, so set it back to the target level. */
+ self->progRefLevelPresent = 0;
self->progRefLevel = pParams->targetRefLevel;
self->prlExpiryCount = 0;
}
@@ -815,6 +847,7 @@ void aacDecoder_drcApply (
void *pSbrDec,
CAacDecoderChannelInfo *pAacDecoderChannelInfo,
CDrcChannelData *pDrcChData,
+ FIXP_DBL *extGain,
int ch, /* needed only for SBR */
int aacFrameSize,
int bSbrPresent )
@@ -826,8 +859,8 @@ void aacDecoder_drcApply (
FIXP_DBL max_mantissa;
INT max_exponent;
- FIXP_DBL norm_mantissa = FL2FXCONST_DBL(0.0f);
- INT norm_exponent = 0;
+ FIXP_DBL norm_mantissa = FL2FXCONST_DBL(0.5f);
+ INT norm_exponent = 1;
FIXP_DBL fact_mantissa[MAX_DRC_BANDS];
INT fact_exponent[MAX_DRC_BANDS];
@@ -849,6 +882,15 @@ void aacDecoder_drcApply (
if (!self->enable) {
sbrDecoder_drcDisable( (HANDLE_SBRDECODER)pSbrDec, ch );
+ if (extGain != NULL) {
+ INT gainScale = (INT)*extGain;
+ /* The gain scaling must be passed to the function in the buffer pointed on by extGain. */
+ if (gainScale >= 0 && gainScale <= DFRACT_BITS) {
+ *extGain = scaleValue(norm_mantissa, norm_exponent-gainScale);
+ } else {
+ FDK_ASSERT(0);
+ }
+ }
return;
}
@@ -864,7 +906,7 @@ void aacDecoder_drcApply (
reduced DAC SNR (if signal is attenuated) or clipping (if signal is
boosted) */
- if (self->digitalNorm == 1)
+ if (pParams->targetRefLevel >= 0)
{
/* 0.5^((targetRefLevel - progRefLevel)/24) */
norm_mantissa = fLdPow(
@@ -874,7 +916,18 @@ void aacDecoder_drcApply (
3,
&norm_exponent );
}
- else {
+ /* Always export the normalization gain (if possible). */
+ if (extGain != NULL) {
+ INT gainScale = (INT)*extGain;
+ /* The gain scaling must be passed to the function in the buffer pointed on by extGain. */
+ if (gainScale >= 0 && gainScale <= DFRACT_BITS) {
+ *extGain = scaleValue(norm_mantissa, norm_exponent-gainScale);
+ } else {
+ FDK_ASSERT(0);
+ }
+ }
+ if (self->params.applyDigitalNorm == 0) {
+ /* Reset normalization gain since this module must not apply it */
norm_mantissa = FL2FXCONST_DBL(0.5f);
norm_exponent = 1;
}
@@ -1112,3 +1165,24 @@ int aacDecoder_drcEpilog (
return err;
}
+/*
+ * Export relevant metadata info from bitstream payload.
+ */
+void aacDecoder_drcGetInfo (
+ HANDLE_AAC_DRC self,
+ SCHAR *pPresMode,
+ SCHAR *pProgRefLevel )
+{
+ if (self != NULL) {
+ if (pPresMode != NULL) {
+ *pPresMode = self->presMode;
+ }
+ if (pProgRefLevel != NULL) {
+ if (self->progRefLevelPresent) {
+ *pProgRefLevel = self->progRefLevel;
+ } else {
+ *pProgRefLevel = -1;
+ }
+ }
+ }
+}
diff --git a/libAACdec/src/aacdec_drc.h b/libAACdec/src/aacdec_drc.h
index 2ebae2c..c850aa5 100644
--- a/libAACdec/src/aacdec_drc.h
+++ b/libAACdec/src/aacdec_drc.h
@@ -98,7 +98,6 @@ amm-info@iis.fraunhofer.de
#include "channel.h"
#include "FDK_bitstream.h"
-#define AACDEC_DRC_DEFAULT_REF_LEVEL ( 108 ) /* -27 dB below full scale (typical for movies) */
#define AACDEC_DRC_DFLT_EXPIRY_FRAMES ( 50 ) /* Default DRC data expiry time in AAC frames */
/**
@@ -111,6 +110,7 @@ typedef enum
TARGET_REF_LEVEL,
DRC_BS_DELAY,
DRC_DATA_EXPIRY_FRAME,
+ APPLY_NORMALIZATION,
APPLY_HEAVY_COMPRESSION
} AACDEC_DRC_PARAM;
@@ -149,6 +149,8 @@ int aacDecoder_drcProlog (
* \param pSbrDec pointer to SBR decoder instance
* \param pAacDecoderChannelInfo AAC decoder channel instance to be processed
* \param pDrcDat DRC channel data
+ * \param extGain Pointer to a FIXP_DBL where a externally applyable gain will be stored into (independently on whether it will be apply internally or not).
+ * At function call the buffer must hold the scale (0 >= scale < DFRACT_BITS) to be applied on the gain value.
* \param ch channel index
* \param aacFrameSize AAC frame size
* \param bSbrPresent flag indicating that SBR is present, in which case DRC is handed over to the SBR instance pSbrDec
@@ -158,6 +160,7 @@ void aacDecoder_drcApply (
void *pSbrDec,
CAacDecoderChannelInfo *pAacDecoderChannelInfo,
CDrcChannelData *pDrcDat,
+ FIXP_DBL *extGain,
int ch,
int aacFrameSize,
int bSbrPresent );
@@ -170,5 +173,17 @@ int aacDecoder_drcEpilog (
UCHAR channelMapping[],
int validChannels );
+/**
+ * \brief Get metadata information found in bitstream.
+ * \param self DRC module instance handle.
+ * \param pPresMode Pointer to field where the presentation mode will be written to.
+ * \param pProgRefLevel Pointer to field where the program reference level will be written to.
+ * \return Nothing.
+ */
+void aacDecoder_drcGetInfo (
+ HANDLE_AAC_DRC self,
+ SCHAR *pPresMode,
+ SCHAR *pProgRefLevel );
+
#endif /* AACDEC_DRC_H */
diff --git a/libAACdec/src/aacdec_drc_types.h b/libAACdec/src/aacdec_drc_types.h
index 1b5cd76..4c6d163 100644
--- a/libAACdec/src/aacdec_drc_types.h
+++ b/libAACdec/src/aacdec_drc_types.h
@@ -124,6 +124,7 @@ typedef struct
{
UINT excludedChnsMask;
SCHAR progRefLevel;
+ SCHAR presMode; /* Presentation mode: 0 (not indicated), 1, 2, and 3 (reserved). */
SCHAR pceInstanceTag;
CDrcChannelData channelData;
@@ -140,6 +141,7 @@ typedef struct
UINT expiryFrame;
SCHAR targetRefLevel;
UCHAR bsDelayEnable;
+ UCHAR applyDigitalNorm;
UCHAR applyHeavyCompression;
} CDrcParams;
@@ -155,9 +157,11 @@ typedef struct
USHORT numPayloads; /* The number of DRC data payload elements found within frame */
USHORT numThreads; /* The number of DRC data threads extracted from the found payload elements */
SCHAR progRefLevel; /* Program reference level for all channels */
+ UCHAR progRefLevelPresent; /* Program reference level found in bitstream */
UINT prlExpiryCount; /* Counter that can be used to monitor the life time of the program reference level. */
+ SCHAR presMode; /* Presentation mode as defined in ETSI TS 101 154 */
UCHAR dvbAncDataAvailable; /* Flag that indicates whether DVB ancillary data is present or not */
UINT dvbAncDataPosition; /* Used to store the DVB ancillary data payload position in the bitstream (only one per frame) */
UINT drcPayloadPosition[MAX_DRC_THREADS]; /* Used to store the DRC payload positions in the bitstream */
diff --git a/libAACdec/src/aacdecoder.cpp b/libAACdec/src/aacdecoder.cpp
index 3a2a561..e19c501 100644
--- a/libAACdec/src/aacdecoder.cpp
+++ b/libAACdec/src/aacdecoder.cpp
@@ -338,17 +338,22 @@ AAC_DECODER_ERROR CAacDecoder_AncDataParse (
\return Error code
*/
static AAC_DECODER_ERROR CDataStreamElement_Read (
+ HANDLE_AACDECODER self,
HANDLE_FDK_BITSTREAM bs,
- CAncData *ancData,
- HANDLE_AAC_DRC hDrcInfo,
- HANDLE_TRANSPORTDEC pTp,
UCHAR *elementInstanceTag,
UINT alignmentAnchor )
{
+ HANDLE_TRANSPORTDEC pTp;
+ CAncData *ancData;
AAC_DECODER_ERROR error = AAC_DEC_OK;
- UINT dataStart;
+ UINT dataStart, dseBits;
int dataByteAlignFlag, count;
+ FDK_ASSERT(self != NULL);
+
+ ancData = &self->ancData;
+ pTp = self->hInput;
+
int crcReg = transportDec_CrcStartReg(pTp, 0);
/* Element Instance Tag */
@@ -361,6 +366,7 @@ static AAC_DECODER_ERROR CDataStreamElement_Read (
if (count == 255) {
count += FDKreadBits(bs,8); /* EscCount */
}
+ dseBits = count*8;
if (dataByteAlignFlag) {
FDKbyteAlign(bs, alignmentAnchor);
@@ -372,19 +378,29 @@ static AAC_DECODER_ERROR CDataStreamElement_Read (
transportDec_CrcEndReg(pTp, crcReg);
{
- INT readBits, dataBits = count<<3;
-
/* Move to the beginning of the data junk */
FDKpushBack(bs, dataStart-FDKgetValidBits(bs));
/* Read Anc data if available */
- readBits = aacDecoder_drcMarkPayload( hDrcInfo, bs, DVB_DRC_ANC_DATA );
+ aacDecoder_drcMarkPayload( self->hDrcInfo, bs, DVB_DRC_ANC_DATA );
+ }
+
+ {
+ PCMDMX_ERROR dmxErr = PCMDMX_OK;
+
+ /* Move to the beginning of the data junk */
+ FDKpushBack(bs, dataStart-FDKgetValidBits(bs));
- if (readBits != dataBits) {
- /* Move to the end again. */
- FDKpushBiDirectional(bs, FDKgetValidBits(bs)-dataStart+dataBits);
+ /* Read DMX meta-data */
+ dmxErr = pcmDmx_Parse (
+ self->hPcmUtils,
+ bs,
+ dseBits,
+ 0 /* not mpeg2 */ );
}
- }
+
+ /* Move to the very end of the element. */
+ FDKpushBiDirectional(bs, FDKgetValidBits(bs)-dataStart+dseBits);
return error;
}
@@ -701,6 +717,12 @@ void CStreamInfoInit(CStreamInfo *pStreamInfo)
pStreamInfo->numChannels = 0;
pStreamInfo->sampleRate = 0;
pStreamInfo->frameSize = 0;
+
+ pStreamInfo->outputDelay = 0;
+
+ /* DRC */
+ pStreamInfo->drcProgRefLev = -1; /* set program reference level to not indicated */
+ pStreamInfo->drcPresMode = -1; /* default: presentation mode not indicated */
}
/*!
@@ -774,7 +796,7 @@ LINKSPEC_CPP void CAacDecoder_Close(HANDLE_AACDECODER self)
if (self == NULL)
return;
- for (ch=0; ch<(6); ch++) {
+ for (ch=0; ch<(8); ch++) {
if (self->pAacDecoderStaticChannelInfo[ch] != NULL) {
if (self->pAacDecoderStaticChannelInfo[ch]->pOverlapBuffer != NULL) {
FreeOverlapBuffer (&self->pAacDecoderStaticChannelInfo[ch]->pOverlapBuffer);
@@ -851,18 +873,19 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_Init(HANDLE_AACDECODER self, const CS
/* valid number of channels -> copy program config element (PCE) from ASC */
FDKmemcpy(&self->pce, &asc->m_progrConfigElement, sizeof(CProgramConfig));
/* Built element table */
- el = CProgramConfig_GetElementTable(&asc->m_progrConfigElement, self->elements, 7);
- for (; el<7; el++) {
+ el = CProgramConfig_GetElementTable(&asc->m_progrConfigElement, self->elements, (8), &self->chMapIndex);
+ for (; el<(8); el++) {
self->elements[el] = ID_NONE;
}
} else {
return AAC_DEC_UNSUPPORTED_CHANNELCONFIG;
}
} else {
+ self->chMapIndex = 0;
if (transportDec_GetFormat(self->hInput) == TT_MP4_ADTS) {
/* set default max_channels for memory allocation because in implicit channel mapping mode
we don't know the actual number of channels until we processed at least one raw_data_block(). */
- ascChannels = (6);
+ ascChannels = (8);
} else {
return AAC_DEC_UNSUPPORTED_CHANNELCONFIG;
}
@@ -874,26 +897,34 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_Init(HANDLE_AACDECODER self, const CS
case 1: case 2: case 3: case 4: case 5: case 6:
ascChannels = asc->m_channelConfiguration;
break;
- case 7:
+ case 11:
+ ascChannels = 7;
+ break;
+ case 7: case 12: case 14:
ascChannels = 8;
break;
default:
return AAC_DEC_UNSUPPORTED_CHANNELCONFIG;
}
+ if (ascChannels > (8)) {
+ return AAC_DEC_UNSUPPORTED_CHANNELCONFIG;
+ }
+
/* Initialize constant mappings for channel config 1-7 */
if (asc->m_channelConfiguration > 0) {
int el;
- FDKmemcpy(self->elements, elementsTab[asc->m_channelConfiguration-1], sizeof(MP4_ELEMENT_ID)*FDKmin(7,7));
- for (el=7; el<7; el++) {
+ FDKmemcpy(self->elements, elementsTab[asc->m_channelConfiguration-1], sizeof(MP4_ELEMENT_ID)*FDKmin(7,(8)));
+ for (el=7; el<(8); el++) {
self->elements[el] = ID_NONE;
}
for (ch=0; ch<ascChannels; ch++) {
self->chMapping[ch] = ch;
}
- for (; ch<(6); ch++) {
+ for (; ch<(8); ch++) {
self->chMapping[ch] = 255;
}
+ self->chMapIndex = asc->m_channelConfiguration;
}
#ifdef TP_PCE_ENABLE
else {
@@ -909,9 +940,6 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_Init(HANDLE_AACDECODER self, const CS
self->streamInfo.channelConfig = asc->m_channelConfiguration;
- if (ascChannels > (6)) {
- return AAC_DEC_UNSUPPORTED_CHANNELCONFIG;
- }
if (self->streamInfo.aot != asc->m_aot) {
self->streamInfo.aot = asc->m_aot;
ascChanged = 1;
@@ -1096,6 +1124,7 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
MP4_ELEMENT_ID type = ID_NONE; /* Current element type */
INT aacChannels=0; /* Channel counter for channels found in the bitstream */
+ int chOutMapIdx; /* Output channel mapping index (see comment below) */
INT auStartAnchor = (INT)FDKgetValidBits(bs); /* AU start bit buffer position for AU byte alignment */
@@ -1119,12 +1148,12 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
if (self->streamInfo.channelConfig == 0) {
/* Init Channel/Element mapping table */
- for (ch=0; ch<(6); ch++) {
+ for (ch=0; ch<(8); ch++) {
self->chMapping[ch] = 255;
}
if (!CProgramConfig_IsValid(pce)) {
int el;
- for (el=0; el<7; el++) {
+ for (el=0; el<(8); el++) {
self->elements[el] = ID_NONE;
}
}
@@ -1161,11 +1190,8 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
CConcealment_InitChannelData(&self->pAacDecoderStaticChannelInfo[ch]->concealmentInfo,
&self->concealCommonData,
self->streamInfo.aacSamplesPerFrame );
- /* Clear concealment buffers to get rid of the complete history */
- FDKmemclear(self->pAacDecoderStaticChannelInfo[ch]->concealmentInfo.spectralCoefficient, 1024 * sizeof(FIXP_CNCL));
- FDKmemclear(self->pAacDecoderStaticChannelInfo[ch]->concealmentInfo.specScale, 8 * sizeof(SHORT));
/* Clear overlap-add buffers to avoid clicks. */
- FDKmemclear(self->pAacDecoderStaticChannelInfo[ch]->IMdct.overlap.freq, OverlapBufferSize*sizeof(FIXP_DBL));
+ FDKmemclear(self->pAacDecoderStaticChannelInfo[ch]->pOverlapBuffer, OverlapBufferSize*sizeof(FIXP_DBL));
}
}
@@ -1378,10 +1404,8 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
{
UCHAR element_instance_tag;
- CDataStreamElement_Read( bs,
- &self->ancData,
- self->hDrcInfo,
- self->hInput,
+ CDataStreamElement_Read( self,
+ bs,
&element_instance_tag,
auStartAnchor );
@@ -1401,29 +1425,6 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
//self->frameOK = 0;
}
}
-
- {
- UCHAR *pDvbAncData = NULL;
- AAC_DECODER_ERROR ancErr;
- int ancIndex;
- int dvbAncDataSize = 0;
-
- /* Ask how many anc data elements are in buffer */
- ancIndex = self->ancData.nrElements - 1;
- /* Get the last one (if available) */
- ancErr = CAacDecoder_AncDataGet( &self->ancData,
- ancIndex,
- &pDvbAncData,
- &dvbAncDataSize );
-
- if (ancErr == AAC_DEC_OK) {
- pcmDmx_ReadDvbAncData (
- self->hPcmUtils,
- pDvbAncData,
- dvbAncDataSize,
- 0 /* not mpeg2 */ );
- }
- }
break;
#ifdef TP_PCE_ENABLE
@@ -1442,9 +1443,9 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
}
else if ( result > 1 ) {
/* Built element table */
- int elIdx = CProgramConfig_GetElementTable(pce, self->elements, 7);
+ int elIdx = CProgramConfig_GetElementTable(pce, self->elements, (8), &self->chMapIndex);
/* Reset the remaining tabs */
- for ( ; elIdx<7; elIdx++) {
+ for ( ; elIdx<(8); elIdx++) {
self->elements[elIdx] = ID_NONE;
}
/* Make new number of channel persistant */
@@ -1510,10 +1511,19 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
break;
}
}
- if (err == SBRDEC_OK) {
+ switch (err) {
+ case SBRDEC_PARSE_ERROR:
+ /* Can not go on parsing because we do not
+ know the length of the SBR extension data. */
+ FDKpushFor(bs, bitCnt);
+ bitCnt = 0;
+ break;
+ case SBRDEC_OK:
self->sbrEnabled = 1;
- } else {
+ break;
+ default:
self->frameOK = 0;
+ break;
}
}
@@ -1603,13 +1613,17 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
self->frameOK=0;
}
- /* store or restore the number of channels */
+ /* store or restore the number of channels and the corresponding info */
if ( self->frameOK && !(flags &(AACDEC_CONCEAL|AACDEC_FLUSH)) ) {
- self->concealChannels = aacChannels; /* store */
+ self->aacChannelsPrev = aacChannels; /* store */
+ FDKmemcpy(self->channelTypePrev, self->channelType, (8)*sizeof(AUDIO_CHANNEL_TYPE)); /* store */
+ FDKmemcpy(self->channelIndicesPrev, self->channelIndices, (8)*sizeof(UCHAR)); /* store */
self->sbrEnabledPrev = self->sbrEnabled;
} else {
if (self->aacChannels > 0) {
- aacChannels = self->concealChannels; /* restore */
+ aacChannels = self->aacChannelsPrev; /* restore */
+ FDKmemcpy(self->channelType, self->channelTypePrev, (8)*sizeof(AUDIO_CHANNEL_TYPE)); /* restore */
+ FDKmemcpy(self->channelIndices, self->channelIndicesPrev, (8)*sizeof(UCHAR)); /* restore */
self->sbrEnabled = self->sbrEnabledPrev;
}
}
@@ -1632,12 +1646,31 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
return ErrorStatus;
}
+ /* Setup the output channel mapping. The table below shows the four possibilities:
+ * # | chCfg | PCE | cChCfg | chOutMapIdx
+ * ---+-------+-----+--------+------------------
+ * 1 | > 0 | no | - | chCfg
+ * 2 | 0 | yes | > 0 | cChCfg
+ * 3 | 0 | yes | 0 | aacChannels || 0
+ * 4 | 0 | no | - | aacChannels || 0
+ * ---+-------+-----+--------+------------------
+ * Where chCfg is the channel configuration index from ASC and cChCfg is a corresponding chCfg
+ * derived from a given PCE. The variable aacChannels represents the number of channel found
+ * during bitstream decoding. Due to the structure of the mapping table it can only be used for
+ * mapping if its value is smaller than 7. Otherwise we use the fallback (0) which is a simple
+ * pass-through. The possibility #4 should appear only with MPEG-2 (ADTS) streams. This is
+ * mode is called "implicit channel mapping".
+ */
+ chOutMapIdx = ((self->chMapIndex==0) && (aacChannels<7)) ? aacChannels : self->chMapIndex;
+
/*
Inverse transform
*/
{
int stride, offset, c;
+ /* Turn on/off DRC modules level normalization in digital domain depending on the limiter status. */
+ aacDecoder_drcSetParam( self->hDrcInfo, APPLY_NORMALIZATION, (self->limiterEnableCurr) ? 0 : 1 );
/* Extract DRC control data and map it to channels (without bitstream delay) */
aacDecoder_drcProlog (
self->hDrcInfo,
@@ -1663,13 +1696,18 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
/* Setup offset and stride for time buffer traversal. */
if (interleaved) {
stride = aacChannels;
- offset = self->channelOutputMapping[aacChannels-1][c];
+ offset = self->channelOutputMapping[chOutMapIdx][c];
} else {
stride = 1;
- offset = self->channelOutputMapping[aacChannels-1][c] * self->streamInfo.aacSamplesPerFrame;
+ offset = self->channelOutputMapping[chOutMapIdx][c] * self->streamInfo.aacSamplesPerFrame;
}
+ if ( flags&AACDEC_FLUSH ) {
+ /* Clear pAacDecoderChannelInfo->pSpectralCoefficient because with AACDEC_FLUSH set it contains undefined data. */
+ FDKmemclear(pAacDecoderChannelInfo->pSpectralCoefficient, sizeof(FIXP_DBL)*self->streamInfo.aacSamplesPerFrame);
+ }
+
/*
Conceal defective spectral data
*/
@@ -1688,12 +1726,15 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
/* Reset DRC control data for this channel */
aacDecoder_drcInitChannelData ( &self->pAacDecoderStaticChannelInfo[c]->drcData );
}
+ /* The DRC module demands to be called with the gain field holding the gain scale. */
+ self->extGain[0] = (FIXP_DBL)TDL_GAIN_SCALING;
/* DRC processing */
aacDecoder_drcApply (
self->hDrcInfo,
self->hSbrDecoder,
pAacDecoderChannelInfo,
&self->pAacDecoderStaticChannelInfo[c]->drcData,
+ self->extGain,
c,
self->streamInfo.aacSamplesPerFrame,
self->sbrEnabled
@@ -1711,6 +1752,7 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
(self->frameOK && !(flags&AACDEC_CONCEAL)),
self->aacCommonData.workBufferCore1->mdctOutTemp
);
+ self->extGainDelay = self->streamInfo.aacSamplesPerFrame;
break;
case AACDEC_RENDER_ELDFB:
CBlock_FrequencyToTimeLowDelay(
@@ -1720,6 +1762,7 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
self->streamInfo.aacSamplesPerFrame,
stride
);
+ self->extGainDelay = (self->streamInfo.aacSamplesPerFrame*2 - self->streamInfo.aacSamplesPerFrame/2 - 1)/2;
break;
default:
ErrorStatus = AAC_DEC_UNKNOWN;
@@ -1743,11 +1786,20 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
);
}
+ /* Add additional concealment delay */
+ self->streamInfo.outputDelay += CConcealment_GetDelay(&self->concealCommonData) * self->streamInfo.aacSamplesPerFrame;
+
+ /* Map DRC data to StreamInfo structure */
+ aacDecoder_drcGetInfo (
+ self->hDrcInfo,
+ &self->streamInfo.drcPresMode,
+ &self->streamInfo.drcProgRefLev
+ );
/* Reorder channel type information tables. */
{
- AUDIO_CHANNEL_TYPE types[(6)];
- UCHAR idx[(6)];
+ AUDIO_CHANNEL_TYPE types[(8)];
+ UCHAR idx[(8)];
int c;
FDK_ASSERT(sizeof(self->channelType) == sizeof(types));
@@ -1757,8 +1809,8 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
FDKmemcpy(idx, self->channelIndices, sizeof(idx));
for (c=0; c<aacChannels; c++) {
- self->channelType[self->channelOutputMapping[aacChannels-1][c]] = types[c];
- self->channelIndices[self->channelOutputMapping[aacChannels-1][c]] = idx[c];
+ self->channelType[self->channelOutputMapping[chOutMapIdx][c]] = types[c];
+ self->channelIndices[self->channelOutputMapping[chOutMapIdx][c]] = idx[c];
}
}
diff --git a/libAACdec/src/aacdecoder.h b/libAACdec/src/aacdecoder.h
index 16351e6..3541773 100644
--- a/libAACdec/src/aacdecoder.h
+++ b/libAACdec/src/aacdecoder.h
@@ -111,6 +111,7 @@ amm-info@iis.fraunhofer.de
#include "aacdec_drc.h"
#include "pcmutils_lib.h"
+ #include "limiter.h"
/* Capabilities flags */
@@ -176,27 +177,31 @@ struct AAC_DECODER_INSTANCE {
UINT flags; /*!< Flags for internal decoder use. DO NOT USE self::streaminfo::flags ! */
- MP4_ELEMENT_ID elements[7]; /*!< Table where the element Id's are listed */
- UCHAR elTags[7]; /*!< Table where the elements id Tags are listed */
- UCHAR chMapping[(6)]; /*!< Table of MPEG canonical order to bitstream channel order mapping. */
+ MP4_ELEMENT_ID elements[(8)]; /*!< Table where the element Id's are listed */
+ UCHAR elTags[(8)]; /*!< Table where the elements id Tags are listed */
+ UCHAR chMapping[(8)]; /*!< Table of MPEG canonical order to bitstream channel order mapping. */
- AUDIO_CHANNEL_TYPE channelType[(6)]; /*!< Audio channel type of each output audio channel (from 0 upto numChannels). */
- UCHAR channelIndices[(6)]; /*!< Audio channel index for each output audio channel (from 0 upto numChannels). */
+ AUDIO_CHANNEL_TYPE channelType[(8)]; /*!< Audio channel type of each output audio channel (from 0 upto numChannels). */
+ UCHAR channelIndices[(8)]; /*!< Audio channel index for each output audio channel (from 0 upto numChannels). */
/* See ISO/IEC 13818-7:2005(E), 8.5.3.2 Explicit channel mapping using a program_config_element() */
const UCHAR (*channelOutputMapping)[8]; /*!< Table for MPEG canonical order to output channel order mapping. */
-
+ UCHAR chMapIndex; /*!< Index to access one line of the channelOutputMapping table. This is required
+ because not all 8 channel configurations have the same output mapping. */
CProgramConfig pce;
CStreamInfo streamInfo; /*!< pointer to StreamInfo data (read from the bitstream) */
- CAacDecoderChannelInfo *pAacDecoderChannelInfo[(6)]; /*!< Temporal channel memory */
- CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[(6)]; /*!< Persistent channel memory */
+ CAacDecoderChannelInfo *pAacDecoderChannelInfo[(8)]; /*!< Temporal channel memory */
+ CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[(8)]; /*!< Persistent channel memory */
CAacDecoderCommonData aacCommonData; /*!< Temporal shared data for all channels hooked into pAacDecoderChannelInfo */
CConcealParams concealCommonData;
- INT concealChannels;
+
+ INT aacChannelsPrev; /*!< The amount of AAC core channels of the last successful decode call. */
+ AUDIO_CHANNEL_TYPE channelTypePrev[(8)]; /*!< Array holding the channelType values of the last successful decode call. */
+ UCHAR channelIndicesPrev[(8)]; /*!< Array holding the channelIndices values of the last successful decode call. */
HANDLE_SBRDECODER hSbrDecoder; /*!< SBR decoder handle. */
@@ -214,6 +219,12 @@ struct AAC_DECODER_INSTANCE {
CAncData ancData; /*!< structure to handle ancillary data */
HANDLE_PCM_DOWNMIX hPcmUtils; /*!< privat data for the PCM utils. */
+ TDLimiterPtr hLimiter; /*!< Handle of time domain limiter. */
+ UCHAR limiterEnableUser; /*!< The limiter configuration requested by the library user */
+ UCHAR limiterEnableCurr; /*!< The current limiter configuration. */
+
+ FIXP_DBL extGain[1]; /*!< Gain that must be applied to the output signal. */
+ UINT extGainDelay; /*!< Delay that must be accounted for extGain. */
};
diff --git a/libAACdec/src/aacdecoder_lib.cpp b/libAACdec/src/aacdecoder_lib.cpp
index ec8f41e..82f85ab 100644
--- a/libAACdec/src/aacdecoder_lib.cpp
+++ b/libAACdec/src/aacdecoder_lib.cpp
@@ -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 5
+#define AACDECODER_LIB_VL2 10
#define AACDECODER_LIB_TITLE "AAC Decoder Lib"
#define AACDECODER_LIB_BUILD_DATE __DATE__
#define AACDECODER_LIB_BUILD_TIME __TIME__
@@ -397,12 +397,14 @@ aacDecoder_SetParam ( const HANDLE_AACDECODER self, /*!< Handle of the decode
CConcealParams *pConcealData = NULL;
HANDLE_AAC_DRC hDrcInfo = NULL;
HANDLE_PCM_DOWNMIX hPcmDmx = NULL;
+ TDLimiterPtr hPcmTdl = NULL;
/* check decoder handle */
if (self != NULL) {
pConcealData = &self->concealCommonData;
hDrcInfo = self->hDrcInfo;
hPcmDmx = self->hPcmUtils;
+ hPcmTdl = self->hLimiter;
} else {
errorStatus = AAC_DEC_INVALID_HANDLE;
}
@@ -420,8 +422,8 @@ aacDecoder_SetParam ( const HANDLE_AACDECODER self, /*!< Handle of the decode
self->outputInterleaved = value;
break;
- case AAC_PCM_OUTPUT_CHANNELS:
- if (value < -1 || value > (6)) {
+ case AAC_PCM_MIN_OUTPUT_CHANNELS:
+ if (value < -1 || value > (8)) {
return AAC_DEC_SET_PARAM_FAIL;
}
{
@@ -429,7 +431,30 @@ aacDecoder_SetParam ( const HANDLE_AACDECODER self, /*!< Handle of the decode
err = pcmDmx_SetParam (
hPcmDmx,
- NUMBER_OF_OUTPUT_CHANNELS,
+ MIN_NUMBER_OF_OUTPUT_CHANNELS,
+ value );
+
+ switch (err) {
+ case PCMDMX_OK:
+ break;
+ case PCMDMX_INVALID_HANDLE:
+ return AAC_DEC_INVALID_HANDLE;
+ default:
+ return AAC_DEC_SET_PARAM_FAIL;
+ }
+ }
+ break;
+
+ case AAC_PCM_MAX_OUTPUT_CHANNELS:
+ if (value < -1 || value > (8)) {
+ return AAC_DEC_SET_PARAM_FAIL;
+ }
+ {
+ PCMDMX_ERROR err;
+
+ err = pcmDmx_SetParam (
+ hPcmDmx,
+ MAX_NUMBER_OF_OUTPUT_CHANNELS,
value );
switch (err) {
@@ -449,7 +474,7 @@ aacDecoder_SetParam ( const HANDLE_AACDECODER self, /*!< Handle of the decode
err = pcmDmx_SetParam (
hPcmDmx,
- DUAL_CHANNEL_DOWNMIX_MODE,
+ DMX_DUAL_CHANNEL_MODE,
value );
switch (err) {
@@ -463,6 +488,47 @@ aacDecoder_SetParam ( const HANDLE_AACDECODER self, /*!< Handle of the decode
}
break;
+
+ case AAC_PCM_LIMITER_ENABLE:
+ if (value < -1 || value > 1) {
+ return AAC_DEC_SET_PARAM_FAIL;
+ }
+ if (self == NULL) {
+ return AAC_DEC_INVALID_HANDLE;
+ }
+ self->limiterEnableUser = value;
+ break;
+
+ case AAC_PCM_LIMITER_ATTACK_TIME:
+ if (value <= 0) { /* module function converts value to unsigned */
+ return AAC_DEC_SET_PARAM_FAIL;
+ }
+ switch (setLimiterAttack(hPcmTdl, value)) {
+ case TDLIMIT_OK:
+ break;
+ case TDLIMIT_INVALID_HANDLE:
+ return AAC_DEC_INVALID_HANDLE;
+ case TDLIMIT_INVALID_PARAMETER:
+ default:
+ return AAC_DEC_SET_PARAM_FAIL;
+ }
+ break;
+
+ case AAC_PCM_LIMITER_RELEAS_TIME:
+ if (value <= 0) { /* module function converts value to unsigned */
+ return AAC_DEC_SET_PARAM_FAIL;
+ }
+ switch (setLimiterRelease(hPcmTdl, value)) {
+ case TDLIMIT_OK:
+ break;
+ case TDLIMIT_INVALID_HANDLE:
+ return AAC_DEC_INVALID_HANDLE;
+ case TDLIMIT_INVALID_PARAMETER:
+ default:
+ return AAC_DEC_SET_PARAM_FAIL;
+ }
+ break;
+
case AAC_PCM_OUTPUT_CHANNEL_MAPPING:
switch (value) {
case 0:
@@ -609,6 +675,14 @@ LINKSPEC_CPP HANDLE_AACDECODER aacDecoder_Open(TRANSPORT_TYPE transportFmt, UINT
goto bail;
}
+ aacDec->hLimiter = createLimiter(TDL_ATTACK_DEFAULT_MS, TDL_RELEASE_DEFAULT_MS, SAMPLE_MAX, (8), 96000);
+ if (NULL == aacDec->hLimiter) {
+ err = -1;
+ goto bail;
+ }
+ aacDec->limiterEnableUser = (UCHAR)-1;
+ aacDec->limiterEnableCurr = 0;
+
/* Assure that all modules have same delay */
@@ -768,6 +842,7 @@ LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_DecodeFrame(
/* Signal bit stream interruption to other modules if required. */
if ( fTpInterruption || (flags & (AACDEC_INTR|AACDEC_CLRHIST)) )
{
+ sbrDecoder_SetParam(self->hSbrDecoder, SBR_CLEAR_HISTORY, (flags&AACDEC_CLRHIST));
aacDecoder_SignalInterruption(self);
if ( ! (flags & AACDEC_INTR) ) {
ErrorStatus = AAC_DEC_TRANSPORT_SYNC_ERROR;
@@ -783,6 +858,19 @@ LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_DecodeFrame(
self->streamInfo.numBadBytes = 0;
self->streamInfo.numTotalBytes = 0;
}
+ /* Reset the output delay field. The modules will add their figures one after another. */
+ self->streamInfo.outputDelay = 0;
+
+ if (self->limiterEnableUser==(UCHAR)-1) {
+ /* Enbale limiter for all non-lowdelay AOT's. */
+ self->limiterEnableCurr = ( self->flags & (AC_LD|AC_ELD) ) ? 0 : 1;
+ }
+ else {
+ /* Use limiter configuration as requested. */
+ self->limiterEnableCurr = self->limiterEnableUser;
+ }
+ /* reset limiter gain on a per frame basis */
+ self->extGain[0] = FL2FXCONST_DBL(1.0f/(float)(1<<TDL_GAIN_SCALING));
ErrorStatus = CAacDecoder_DecodeFrame(self,
@@ -825,11 +913,15 @@ LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_DecodeFrame(
if (self->sbrEnabled)
{
SBR_ERROR sbrError = SBRDEC_OK;
+ int chOutMapIdx = ((self->chMapIndex==0) && (self->streamInfo.numChannels<7)) ? self->streamInfo.numChannels : self->chMapIndex;
/* set params */
sbrDecoder_SetParam ( self->hSbrDecoder,
SBR_SYSTEM_BITSTREAM_DELAY,
self->sbrParams.bsDelay);
+ sbrDecoder_SetParam ( self->hSbrDecoder,
+ SBR_FLUSH_DATA,
+ (flags & AACDEC_FLUSH) );
if ( self->streamInfo.aot == AOT_ER_AAC_ELD ) {
/* Configure QMF */
@@ -838,7 +930,16 @@ LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_DecodeFrame(
(self->flags & AC_LD_MPS) ? 1 : 0 );
}
+ {
+ PCMDMX_ERROR dmxErr;
+ INT maxOutCh = 0;
+ dmxErr = pcmDmx_GetParam(self->hPcmUtils, MAX_NUMBER_OF_OUTPUT_CHANNELS, &maxOutCh);
+ if ( (dmxErr == PCMDMX_OK) && (maxOutCh == 1) ) {
+ /* Disable PS processing if we have to create a mono output signal. */
+ self->psPossible = 0;
+ }
+ }
/* apply SBR processing */
@@ -846,23 +947,29 @@ LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_DecodeFrame(
pTimeData,
&self->streamInfo.numChannels,
&self->streamInfo.sampleRate,
- self->channelOutputMapping[self->streamInfo.numChannels-1],
+ self->channelOutputMapping[chOutMapIdx],
interleaved,
self->frameOK,
&self->psPossible);
if (sbrError == SBRDEC_OK) {
+ #define UPS_SCALE 2 /* Maximum upsampling factor is 4 (CELP+SBR) */
+ FIXP_DBL upsampleFactor = FL2FXCONST_DBL(1.0f/(1<<UPS_SCALE));
/* Update data in streaminfo structure. Assume that the SBR upsampling factor is either 1 or 2 */
self->flags |= AC_SBR_PRESENT;
if (self->streamInfo.aacSampleRate != self->streamInfo.sampleRate) {
if (self->streamInfo.frameSize == 768) {
- self->streamInfo.frameSize = (self->streamInfo.aacSamplesPerFrame * 8) / 3;
+ upsampleFactor = FL2FXCONST_DBL(8.0f/(3<<UPS_SCALE));
} else {
- self->streamInfo.frameSize = self->streamInfo.aacSamplesPerFrame << 1;
+ upsampleFactor = FL2FXCONST_DBL(2.0f/(1<<UPS_SCALE));
}
}
+ /* Apply upsampling factor to both the core frame length and the core delay */
+ self->streamInfo.frameSize = (INT)fMult((FIXP_DBL)self->streamInfo.aacSamplesPerFrame<<UPS_SCALE, upsampleFactor);
+ self->streamInfo.outputDelay = (UINT)(INT)fMult((FIXP_DBL)self->streamInfo.outputDelay<<UPS_SCALE, upsampleFactor);
+ self->streamInfo.outputDelay += sbrDecoder_GetDelay( self->hSbrDecoder );
if (self->psPossible) {
self->flags |= AC_PS_PRESENT;
@@ -870,19 +977,20 @@ LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_DecodeFrame(
self->channelType[1] = ACT_FRONT;
self->channelIndices[0] = 0;
self->channelIndices[1] = 1;
- } else {
- self->flags &= ~AC_PS_PRESENT;
}
}
}
+ {
+ INT pcmLimiterScale = 0;
+ PCMDMX_ERROR dmxErr = PCMDMX_OK;
if ( flags & (AACDEC_INTR | AACDEC_CLRHIST) ) {
/* delete data from the past (e.g. mixdown coeficients) */
pcmDmx_Reset( self->hPcmUtils, PCMDMX_RESET_BS_DATA );
}
/* do PCM post processing */
- pcmDmx_ApplyFrame (
+ dmxErr = pcmDmx_ApplyFrame (
self->hPcmUtils,
pTimeData,
self->streamInfo.frameSize,
@@ -890,9 +998,39 @@ LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_DecodeFrame(
interleaved,
self->channelType,
self->channelIndices,
- self->channelOutputMapping
+ self->channelOutputMapping,
+ (self->limiterEnableCurr) ? &pcmLimiterScale : NULL
);
+ if (dmxErr == PCMDMX_INVALID_MODE) {
+ /* Announce the framework that the current combination of channel configuration and downmix
+ * settings are not know to produce a predictable behavior and thus maybe produce strange output. */
+ ErrorStatus = AAC_DEC_DECODE_FRAME_ERROR;
+ }
+ if ( flags & AACDEC_CLRHIST ) {
+ /* Delete the delayed signal. */
+ resetLimiter(self->hLimiter);
+ }
+ if (self->limiterEnableCurr)
+ {
+ /* Set actual signal parameters */
+ setLimiterNChannels(self->hLimiter, self->streamInfo.numChannels);
+ setLimiterSampleRate(self->hLimiter, self->streamInfo.sampleRate);
+
+ applyLimiter(
+ self->hLimiter,
+ pTimeData,
+ self->extGain,
+ &pcmLimiterScale,
+ 1,
+ self->extGainDelay,
+ self->streamInfo.frameSize
+ );
+
+ /* Announce the additional limiter output delay */
+ self->streamInfo.outputDelay += getLimiterDelay(self->hLimiter);
+ }
+ }
/* Signal interruption to take effect in next frame. */
@@ -917,6 +1055,9 @@ LINKSPEC_CPP void aacDecoder_Close ( HANDLE_AACDECODER self )
return;
+ if (self->hLimiter != NULL) {
+ destroyLimiter(self->hLimiter);
+ }
if (self->hPcmUtils != NULL) {
pcmDmx_Close( &self->hPcmUtils );
diff --git a/libAACdec/src/conceal.cpp b/libAACdec/src/conceal.cpp
index c26051c..1c313ef 100644
--- a/libAACdec/src/conceal.cpp
+++ b/libAACdec/src/conceal.cpp
@@ -762,7 +762,6 @@ int
CConcealment_UpdateState( hConcealmentInfo,
frameOk );
- if ( !frameOk )
{
/* Create data for signal rendering according to the selected concealment method and decoder operating mode. */
@@ -775,11 +774,13 @@ int
{
default:
case ConcealMethodMute:
- /* Mute spectral data in case of errors */
- FDKmemclear(pAacDecoderChannelInfo->pSpectralCoefficient, samplesPerFrame * sizeof(FIXP_DBL));
- /* Set last window shape */
- pAacDecoderChannelInfo->icsInfo.WindowShape = hConcealmentInfo->windowShape;
- appliedProcessing = 1;
+ if (!frameOk) {
+ /* Mute spectral data in case of errors */
+ FDKmemclear(pAacDecoderChannelInfo->pSpectralCoefficient, samplesPerFrame * sizeof(FIXP_DBL));
+ /* Set last window shape */
+ pAacDecoderChannelInfo->icsInfo.WindowShape = hConcealmentInfo->windowShape;
+ appliedProcessing = 1;
+ }
break;
case ConcealMethodNoise:
@@ -801,7 +802,7 @@ int
pSamplingRateInfo,
samplesPerFrame,
0, /* don't use tonal improvement */
- 0);
+ frameOk);
break;
}