aboutsummaryrefslogtreecommitdiffstats
path: root/fdk-aac/libAACdec/src/aacdecoder_lib.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'fdk-aac/libAACdec/src/aacdecoder_lib.cpp')
-rw-r--r--fdk-aac/libAACdec/src/aacdecoder_lib.cpp272
1 files changed, 168 insertions, 104 deletions
diff --git a/fdk-aac/libAACdec/src/aacdecoder_lib.cpp b/fdk-aac/libAACdec/src/aacdecoder_lib.cpp
index 8685a30..bcbd46c 100644
--- a/fdk-aac/libAACdec/src/aacdecoder_lib.cpp
+++ b/fdk-aac/libAACdec/src/aacdecoder_lib.cpp
@@ -119,10 +119,10 @@ amm-info@iis.fraunhofer.de
/* Decoder library info */
#define AACDECODER_LIB_VL0 3
-#define AACDECODER_LIB_VL1 1
-#define AACDECODER_LIB_VL2 2
+#define AACDECODER_LIB_VL1 2
+#define AACDECODER_LIB_VL2 0
#define AACDECODER_LIB_TITLE "AAC Decoder Lib"
-#ifdef __ANDROID__
+#ifdef SUPPRESS_BUILD_DATE_INFO
#define AACDECODER_LIB_BUILD_DATE ""
#define AACDECODER_LIB_BUILD_TIME ""
#else
@@ -1133,35 +1133,31 @@ static INT aacDecoder_EstimateNumberOfLostFrames(HANDLE_AACDECODER self) {
return n;
}
-LINKSPEC_CPP AAC_DECODER_ERROR
-aacDecoder_DecodeFrame(HANDLE_AACDECODER self, INT_PCM *pTimeData_extern,
- const INT timeDataSize_extern, const UINT flags) {
+LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_DecodeFrame(HANDLE_AACDECODER self,
+ INT_PCM *pTimeData,
+ const INT timeDataSize,
+ const UINT flags) {
AAC_DECODER_ERROR ErrorStatus;
INT layer;
INT nBits;
+ INT timeData2Size;
+ INT timeData3Size;
+ INT timeDataHeadroom;
HANDLE_FDK_BITSTREAM hBs;
int fTpInterruption = 0; /* Transport originated interruption detection. */
int fTpConceal = 0; /* Transport originated concealment. */
- INT_PCM *pTimeData = NULL;
- INT timeDataSize = 0;
UINT accessUnit = 0;
UINT numAccessUnits = 1;
UINT numPrerollAU = 0;
- int fEndAuNotAdjusted = 0; /* The end of the access unit was not adjusted */
- int applyCrossfade = 1; /* flag indicates if flushing was possible */
- FIXP_PCM *pTimeDataFixpPcm; /* Signal buffer for decoding process before PCM
- processing */
- INT timeDataFixpPcmSize;
- PCM_DEC *pTimeDataPcmPost; /* Signal buffer for PCM post-processing */
- INT timeDataPcmPostSize;
+ int fEndAuNotAdjusted = 0; /* The end of the access unit was not adjusted */
+ int applyCrossfade = 1; /* flag indicates if flushing was possible */
+ PCM_DEC *pTimeData2;
+ PCM_AAC *pTimeData3;
if (self == NULL) {
return AAC_DEC_INVALID_HANDLE;
}
- pTimeData = self->pcmOutputBuffer;
- timeDataSize = sizeof(self->pcmOutputBuffer) / sizeof(*self->pcmOutputBuffer);
-
if (flags & AACDEC_INTR) {
self->streamInfo.numLostAccessUnits = 0;
}
@@ -1271,9 +1267,9 @@ aacDecoder_DecodeFrame(HANDLE_AACDECODER self, INT_PCM *pTimeData_extern,
}
/* Signal bit stream interruption to other modules if required. */
- if (fTpInterruption || (flags & AACDEC_INTR)) {
+ if (fTpInterruption || ((flags & AACDEC_INTR) && (accessUnit == 0))) {
aacDecoder_SignalInterruption(self);
- if (!(flags & AACDEC_INTR)) {
+ if (!((flags & AACDEC_INTR) && (accessUnit == 0))) {
ErrorStatus = AAC_DEC_TRANSPORT_SYNC_ERROR;
goto bail;
}
@@ -1317,19 +1313,23 @@ aacDecoder_DecodeFrame(HANDLE_AACDECODER self, INT_PCM *pTimeData_extern,
/* 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));
- pTimeDataFixpPcm = pTimeData;
- timeDataFixpPcmSize = timeDataSize;
+ /* reset DRC level normalization gain on a per frame basis */
+ self->extGain[0] = AACDEC_DRC_GAIN_INIT_VALUE;
+
+ pTimeData2 = self->pTimeData2;
+ timeData2Size = self->timeData2Size / sizeof(PCM_DEC);
+ pTimeData3 = (PCM_AAC *)self->pTimeData2;
+ timeData3Size = self->timeData2Size / sizeof(PCM_AAC);
ErrorStatus = CAacDecoder_DecodeFrame(
self,
flags | (fTpConceal ? AACDEC_CONCEAL : 0) |
((self->flushStatus && !(flags & AACDEC_CONCEAL)) ? AACDEC_FLUSH
: 0),
- pTimeDataFixpPcm + 0, timeDataFixpPcmSize,
- self->streamInfo.aacSamplesPerFrame + 0);
+ pTimeData2 + 0, timeData2Size, self->streamInfo.aacSamplesPerFrame + 0);
+
+ timeDataHeadroom = self->aacOutDataHeadroom;
/* if flushing for USAC DASH IPF was not possible go on with decoding
* preroll */
@@ -1354,7 +1354,7 @@ aacDecoder_DecodeFrame(HANDLE_AACDECODER self, INT_PCM *pTimeData_extern,
}
}
- /* If the current pTimeDataFixpPcm does not contain a valid signal, there
+ /* If the current pTimeData2 does not contain a valid signal, there
* nothing else we can do, so bail. */
if (!IS_OUTPUT_VALID(ErrorStatus)) {
goto bail;
@@ -1368,10 +1368,10 @@ aacDecoder_DecodeFrame(HANDLE_AACDECODER self, INT_PCM *pTimeData_extern,
self->streamInfo.numChannels = self->streamInfo.aacNumChannels;
{
- FDK_Delay_Apply(&self->usacResidualDelay,
- pTimeDataFixpPcm +
- 1 * (self->streamInfo.aacSamplesPerFrame + 0) + 0,
- self->streamInfo.frameSize, 0);
+ FDK_Delay_Apply(
+ &self->usacResidualDelay,
+ pTimeData2 + 1 * (self->streamInfo.aacSamplesPerFrame + 0) + 0,
+ self->streamInfo.frameSize, 0);
}
/* Setting of internal MPS state; may be reset in CAacDecoder_SyncQmfMode
@@ -1418,8 +1418,6 @@ aacDecoder_DecodeFrame(HANDLE_AACDECODER self, INT_PCM *pTimeData_extern,
}
}
- self->qmfDomain.globalConf.TDinput = pTimeData;
-
switch (FDK_QmfDomain_Configure(&self->qmfDomain)) {
default:
case QMF_DOMAIN_INIT_ERROR:
@@ -1476,18 +1474,18 @@ aacDecoder_DecodeFrame(HANDLE_AACDECODER self, INT_PCM *pTimeData_extern,
sbrDecoder_SetParam(self->hSbrDecoder, SBR_SKIP_QMF,
(self->mpsEnableCurr) ? 2 : 0);
- INT_PCM *input;
- input = (INT_PCM *)self->workBufferCore2;
- FDKmemcpy(input, pTimeData,
- sizeof(INT_PCM) * (self->streamInfo.numChannels) *
+ PCM_AAC *input;
+ input = (PCM_AAC *)self->workBufferCore2;
+ FDKmemcpy(input, pTimeData3,
+ sizeof(PCM_AAC) * (self->streamInfo.numChannels) *
(self->streamInfo.frameSize));
/* apply SBR processing */
- sbrError = sbrDecoder_Apply(self->hSbrDecoder, input, pTimeData,
- timeDataSize, &self->streamInfo.numChannels,
- &self->streamInfo.sampleRate,
- &self->mapDescr, self->chMapIndex,
- self->frameOK, &self->psPossible);
+ sbrError = sbrDecoder_Apply(
+ self->hSbrDecoder, input, pTimeData3, timeData3Size,
+ &self->streamInfo.numChannels, &self->streamInfo.sampleRate,
+ &self->mapDescr, self->chMapIndex, self->frameOK, &self->psPossible,
+ self->aacOutDataHeadroom, &timeDataHeadroom);
if (sbrError == SBRDEC_OK) {
/* Update data in streaminfo structure. Assume that the SBR upsampling
@@ -1566,10 +1564,11 @@ aacDecoder_DecodeFrame(HANDLE_AACDECODER self, INT_PCM *pTimeData_extern,
if (err == 0) {
err = mpegSurroundDecoder_Apply(
(CMpegSurroundDecoder *)self->pMpegSurroundDecoder,
- (INT_PCM *)self->workBufferCore2, pTimeData, timeDataSize,
+ (PCM_AAC *)self->workBufferCore2, pTimeData3, timeData3Size,
self->streamInfo.aacSamplesPerFrame, &nChannels, &frameSize,
self->streamInfo.sampleRate, self->streamInfo.aot,
- self->channelType, self->channelIndices, &self->mapDescr);
+ self->channelType, self->channelIndices, &self->mapDescr,
+ self->aacOutDataHeadroom, &timeDataHeadroom);
}
if (err == MPS_OUTPUT_BUFFER_TOO_SMALL) {
@@ -1592,8 +1591,8 @@ aacDecoder_DecodeFrame(HANDLE_AACDECODER self, INT_PCM *pTimeData_extern,
self->streamInfo.frameSize = self->mpsFrameSizeLast;
/* ... and clear output buffer so that potentially corrupted data does
* not reach the framework. */
- FDKmemclear(pTimeData, self->mpsOutChannelsLast *
- self->mpsFrameSizeLast * sizeof(INT_PCM));
+ FDKmemclear(pTimeData3, self->mpsOutChannelsLast *
+ self->mpsFrameSizeLast * sizeof(PCM_AAC));
/* Additionally proclaim that this frame had errors during decoding.
*/
ErrorStatus = AAC_DEC_DECODE_FRAME_ERROR;
@@ -1614,11 +1613,11 @@ aacDecoder_DecodeFrame(HANDLE_AACDECODER self, INT_PCM *pTimeData_extern,
sbrDecoder_SetParam(self->hSbrDecoder, SBR_SKIP_QMF, 1);
/* apply SBR processing */
- sbrError = sbrDecoder_Apply(self->hSbrDecoder, pTimeData, pTimeData,
- timeDataSize, &self->streamInfo.numChannels,
- &self->streamInfo.sampleRate,
- &self->mapDescr, self->chMapIndex,
- self->frameOK, &self->psPossible);
+ sbrError = sbrDecoder_Apply(
+ self->hSbrDecoder, pTimeData3, pTimeData3, timeData3Size,
+ &self->streamInfo.numChannels, &self->streamInfo.sampleRate,
+ &self->mapDescr, self->chMapIndex, self->frameOK, &self->psPossible,
+ self->aacOutDataHeadroom, &timeDataHeadroom);
if (sbrError == SBRDEC_OK) {
/* Update data in streaminfo structure. Assume that the SBR upsampling
@@ -1646,17 +1645,15 @@ aacDecoder_DecodeFrame(HANDLE_AACDECODER self, INT_PCM *pTimeData_extern,
}
}
- /* Use dedicated memory for PCM postprocessing */
- pTimeDataPcmPost = self->pTimeData2;
- timeDataPcmPostSize = self->timeData2Size;
-
{
- const int size =
- self->streamInfo.frameSize * self->streamInfo.numChannels;
- FDK_ASSERT(timeDataPcmPostSize >= size);
- for (int i = 0; i < size; i++) {
- pTimeDataPcmPost[i] =
- (PCM_DEC)FX_PCM2PCM_DEC(pTimeData[i]) >> PCM_OUT_HEADROOM;
+ if ((INT)PCM_OUT_HEADROOM != timeDataHeadroom) {
+ for (int i = ((self->streamInfo.frameSize *
+ self->streamInfo.numChannels) -
+ 1);
+ i >= 0; i--) {
+ pTimeData2[i] =
+ (PCM_DEC)pTimeData3[i] >> (PCM_OUT_HEADROOM - timeDataHeadroom);
+ }
}
}
@@ -1711,22 +1708,21 @@ aacDecoder_DecodeFrame(HANDLE_AACDECODER self, INT_PCM *pTimeData_extern,
if ((self->streamInfo.numChannels > 1) &&
(0 || (self->sbrEnabled) || (self->mpsEnableCurr))) {
/* interleaving/deinterleaving is performed on upper part of
- * pTimeDataPcmPost. Check if this buffer is large enough. */
- if (timeDataPcmPostSize <
- (INT)(2 * self->streamInfo.numChannels *
- self->streamInfo.frameSize * sizeof(PCM_DEC))) {
+ * pTimeData2. Check if this buffer is large enough. */
+ if (timeData2Size < (INT)(2 * self->streamInfo.numChannels *
+ self->streamInfo.frameSize)) {
ErrorStatus = AAC_DEC_UNKNOWN;
goto bail;
}
needsDeinterleaving = 1;
drcWorkBuffer =
- (FIXP_DBL *)pTimeDataPcmPost +
+ (FIXP_DBL *)pTimeData2 +
self->streamInfo.numChannels * self->streamInfo.frameSize;
FDK_deinterleave(
- pTimeDataPcmPost, drcWorkBuffer, self->streamInfo.numChannels,
+ pTimeData2, drcWorkBuffer, self->streamInfo.numChannels,
self->streamInfo.frameSize, self->streamInfo.frameSize);
} else {
- drcWorkBuffer = (FIXP_DBL *)pTimeDataPcmPost;
+ drcWorkBuffer = pTimeData2;
}
/* prepare Loudness Normalisation gain */
@@ -1761,16 +1757,51 @@ aacDecoder_DecodeFrame(HANDLE_AACDECODER self, INT_PCM *pTimeData_extern,
if (needsDeinterleaving) {
FDK_interleave(
- drcWorkBuffer, pTimeDataPcmPost, self->streamInfo.numChannels,
+ drcWorkBuffer, pTimeData2, self->streamInfo.numChannels,
self->streamInfo.frameSize, self->streamInfo.frameSize);
}
}
}
+ if (FDK_drcDec_GetParam(self->hUniDrcDecoder, DRC_DEC_IS_ACTIVE)) {
+ /* return output loudness information for MPEG-D DRC */
+ LONG outputLoudness =
+ FDK_drcDec_GetParam(self->hUniDrcDecoder, DRC_DEC_OUTPUT_LOUDNESS);
+ if (outputLoudness == DRC_DEC_LOUDNESS_NOT_PRESENT) {
+ /* no valid MPEG-D DRC loudness value contained */
+ self->streamInfo.outputLoudness = -1;
+ } else {
+ if (outputLoudness > 0) {
+ /* positive output loudness values (very unusual) are limited to 0
+ * dB */
+ self->streamInfo.outputLoudness = 0;
+ } else {
+ self->streamInfo.outputLoudness =
+ -(INT)outputLoudness >>
+ 22; /* negate and scale from e = 7 to e = (31-2) */
+ }
+ }
+ } else {
+ /* return output loudness information for MPEG-4 DRC */
+ if (self->streamInfo.drcProgRefLev <
+ 0) { /* no MPEG-4 DRC loudness metadata contained */
+ self->streamInfo.outputLoudness = -1;
+ } else {
+ if (self->defaultTargetLoudness <
+ 0) { /* loudness normalization is off */
+ self->streamInfo.outputLoudness = self->streamInfo.drcProgRefLev;
+ } else {
+ self->streamInfo.outputLoudness = self->defaultTargetLoudness;
+ }
+ }
+ }
if (self->streamInfo.extAot != AOT_AAC_SLS) {
INT pcmLimiterScale = 0;
+ INT interleaved = 0;
+ interleaved |= (self->sbrEnabled) ? 1 : 0;
+ interleaved |= (self->mpsEnableCurr) ? 1 : 0;
PCMDMX_ERROR dmxErr = PCMDMX_OK;
- if (flags & (AACDEC_INTR)) {
+ if ((flags & AACDEC_INTR) && (accessUnit == 0)) {
/* delete data from the past (e.g. mixdown coeficients) */
pcmDmx_Reset(self->hPcmUtils, PCMDMX_RESET_BS_DATA);
}
@@ -1781,17 +1812,12 @@ aacDecoder_DecodeFrame(HANDLE_AACDECODER self, INT_PCM *pTimeData_extern,
}
}
- INT interleaved = 0;
- interleaved |= (self->sbrEnabled) ? 1 : 0;
- interleaved |= (self->mpsEnableCurr) ? 1 : 0;
-
/* do PCM post processing */
- dmxErr = pcmDmx_ApplyFrame(
- self->hPcmUtils, pTimeDataPcmPost, timeDataFixpPcmSize,
- self->streamInfo.frameSize, &self->streamInfo.numChannels,
- interleaved, self->channelType, self->channelIndices,
- &self->mapDescr,
- (self->limiterEnableCurr) ? &pcmLimiterScale : NULL);
+ dmxErr = pcmDmx_ApplyFrame(self->hPcmUtils, pTimeData2, timeData2Size,
+ self->streamInfo.frameSize,
+ &self->streamInfo.numChannels, interleaved,
+ self->channelType, self->channelIndices,
+ &self->mapDescr, &pcmLimiterScale);
if (dmxErr == PCMDMX_OUTPUT_BUFFER_TOO_SMALL) {
ErrorStatus = AAC_DEC_OUTPUT_BUFFER_TOO_SMALL;
goto bail;
@@ -1803,13 +1829,35 @@ aacDecoder_DecodeFrame(HANDLE_AACDECODER self, INT_PCM *pTimeData_extern,
ErrorStatus = AAC_DEC_DECODE_FRAME_ERROR;
}
+ pcmLimiterScale += PCM_OUT_HEADROOM;
+
if (flags & AACDEC_CLRHIST) {
if (!(self->flags[0] & AC_USAC)) {
+ /* Reset DRC data */
+ aacDecoder_drcReset(self->hDrcInfo);
/* Delete the delayed signal. */
pcmLimiter_Reset(self->hLimiter);
}
}
+ /* Set applyExtGain if DRC processing is enabled and if
+ progRefLevelPresent is present for the first time. Consequences: The
+ headroom of the output signal can be set to AACDEC_DRC_GAIN_SCALING
+ only for audio formats which support legacy DRC Level Normalization.
+ For all other audio formats the headroom of the output
+ signal is set to PCM_OUT_HEADROOM. */
+ if (self->hDrcInfo->enable &&
+ (self->hDrcInfo->progRefLevelPresent == 1)) {
+ self->hDrcInfo->applyExtGain |= 1;
+ }
+
+ /* Check whether time data buffer is large enough. */
+ if (timeDataSize <
+ (self->streamInfo.numChannels * self->streamInfo.frameSize)) {
+ ErrorStatus = AAC_DEC_OUTPUT_BUFFER_TOO_SMALL;
+ goto bail;
+ }
+
if (self->limiterEnableCurr) {
/* use workBufferCore2 buffer for interleaving */
PCM_LIM *pInterleaveBuffer;
@@ -1818,44 +1866,72 @@ aacDecoder_DecodeFrame(HANDLE_AACDECODER self, INT_PCM *pTimeData_extern,
/* Set actual signal parameters */
pcmLimiter_SetNChannels(self->hLimiter, self->streamInfo.numChannels);
pcmLimiter_SetSampleRate(self->hLimiter, self->streamInfo.sampleRate);
- pcmLimiterScale += PCM_OUT_HEADROOM;
if ((self->streamInfo.numChannels == 1) || (self->sbrEnabled) ||
(self->mpsEnableCurr)) {
- pInterleaveBuffer = (PCM_LIM *)pTimeDataPcmPost;
+ pInterleaveBuffer = (PCM_LIM *)pTimeData2;
} else {
- pInterleaveBuffer = (PCM_LIM *)pTimeData;
+ pInterleaveBuffer = (PCM_LIM *)self->workBufferCore2;
+
/* applyLimiter requests for interleaved data */
/* Interleave ouput buffer */
- FDK_interleave(pTimeDataPcmPost, pInterleaveBuffer,
+ FDK_interleave(pTimeData2, pInterleaveBuffer,
self->streamInfo.numChannels, blockLength,
self->streamInfo.frameSize);
}
+ FIXP_DBL *pGainPerSample = NULL;
+
+ if (self->hDrcInfo->enable && self->hDrcInfo->applyExtGain) {
+ pGainPerSample = self->workBufferCore1;
+
+ if ((INT)GetRequiredMemWorkBufferCore1() <
+ (INT)(self->streamInfo.frameSize * sizeof(FIXP_DBL))) {
+ ErrorStatus = AAC_DEC_UNKNOWN;
+ goto bail;
+ }
+
+ pcmLimiterScale = applyDrcLevelNormalization(
+ self->hDrcInfo, (PCM_DEC *)pInterleaveBuffer, self->extGain,
+ pGainPerSample, pcmLimiterScale, self->extGainDelay,
+ self->streamInfo.frameSize, self->streamInfo.numChannels, 1, 1);
+ }
+
pcmLimiter_Apply(self->hLimiter, pInterleaveBuffer, pTimeData,
- self->extGain, &pcmLimiterScale, 1,
- self->extGainDelay, self->streamInfo.frameSize);
+ pGainPerSample, pcmLimiterScale,
+ self->streamInfo.frameSize);
{
/* Announce the additional limiter output delay */
self->streamInfo.outputDelay += pcmLimiter_GetDelay(self->hLimiter);
}
} else {
+ if (self->hDrcInfo->enable && self->hDrcInfo->applyExtGain) {
+ pcmLimiterScale = applyDrcLevelNormalization(
+ self->hDrcInfo, pTimeData2, self->extGain, NULL,
+ pcmLimiterScale, self->extGainDelay, self->streamInfo.frameSize,
+ self->streamInfo.numChannels,
+ (interleaved || (self->streamInfo.numChannels == 1))
+ ? 1
+ : self->streamInfo.frameSize,
+ 0);
+ }
+
/* If numChannels = 1 we do not need interleaving. The same applies if
SBR or MPS are used, since their output is interleaved already
(resampled or not) */
if ((self->streamInfo.numChannels == 1) || (self->sbrEnabled) ||
(self->mpsEnableCurr)) {
scaleValuesSaturate(
- pTimeData, pTimeDataPcmPost,
+ pTimeData, pTimeData2,
self->streamInfo.frameSize * self->streamInfo.numChannels,
- PCM_OUT_HEADROOM);
+ pcmLimiterScale);
} else {
scaleValuesSaturate(
- (INT_PCM *)self->workBufferCore2, pTimeDataPcmPost,
+ (INT_PCM *)self->workBufferCore2, pTimeData2,
self->streamInfo.frameSize * self->streamInfo.numChannels,
- PCM_OUT_HEADROOM);
+ pcmLimiterScale);
/* Interleave ouput buffer */
FDK_interleave((INT_PCM *)self->workBufferCore2, pTimeData,
self->streamInfo.numChannels,
@@ -1951,20 +2027,8 @@ bail:
ErrorStatus = AAC_DEC_UNKNOWN;
}
- /* Check whether external output buffer is large enough. */
- if (timeDataSize_extern <
- self->streamInfo.numChannels * self->streamInfo.frameSize) {
- ErrorStatus = AAC_DEC_OUTPUT_BUFFER_TOO_SMALL;
- }
-
- /* Update external output buffer. */
- if (IS_OUTPUT_VALID(ErrorStatus)) {
- FDKmemcpy(pTimeData_extern, pTimeData,
- self->streamInfo.numChannels * self->streamInfo.frameSize *
- sizeof(*pTimeData));
- } else {
- FDKmemclear(pTimeData_extern,
- timeDataSize_extern * sizeof(*pTimeData_extern));
+ if (!IS_OUTPUT_VALID(ErrorStatus)) {
+ FDKmemclear(pTimeData, timeDataSize * sizeof(*pTimeData));
}
return ErrorStatus;