diff options
author | Jean-Michel Trivi <jmtrivi@google.com> | 2014-05-20 17:24:06 -0700 |
---|---|---|
committer | Jean-Michel Trivi <jmtrivi@google.com> | 2014-05-20 17:24:06 -0700 |
commit | af967fcc55656a0d3c2a05982713f1ca43c1252b (patch) | |
tree | 8678c6321030a5340b3d3409a17b6335c91a62e6 | |
parent | fb2e845179a04cc259f1e66dcc68e023d2ef433a (diff) | |
download | fdk-aac-dabplus-af967fcc55656a0d3c2a05982713f1ca43c1252b.tar.gz fdk-aac-dabplus-af967fcc55656a0d3c2a05982713f1ca43c1252b.tar.bz2 fdk-aac-dabplus-af967fcc55656a0d3c2a05982713f1ca43c1252b.zip |
AAC Decoder: flush/seek improvements
Improve flushing and seeking.
Add field to the API stream info structure signaling the additional output
delay for flushing and delay compensation.
Bug 9428126
Change-Id: I808412905563ea3de50a2e77a9b5dfee829cd2ed
-rw-r--r-- | libAACdec/include/aacdecoder_lib.h | 26 | ||||
-rw-r--r-- | libAACdec/src/aacdecoder.cpp | 37 | ||||
-rw-r--r-- | libAACdec/src/aacdecoder.h | 5 | ||||
-rw-r--r-- | libAACdec/src/aacdecoder_lib.cpp | 14 | ||||
-rw-r--r-- | libSBRdec/include/sbrdecoder.h | 2 | ||||
-rw-r--r-- | libSBRdec/src/env_extr.h | 2 | ||||
-rw-r--r-- | libSBRdec/src/sbrdecoder.cpp | 48 |
7 files changed, 108 insertions, 26 deletions
diff --git a/libAACdec/include/aacdecoder_lib.h b/libAACdec/include/aacdecoder_lib.h index a281ab9..bf6dcfb 100644 --- a/libAACdec/include/aacdecoder_lib.h +++ b/libAACdec/include/aacdecoder_lib.h @@ -532,18 +532,18 @@ typedef enum */ typedef struct { - /* These three members are the only really relevant ones for the user. */ + /* These five members are the only really relevant ones for the user. */ INT sampleRate; /*!< The samplerate in Hz of the fully decoded PCM audio signal (after SBR processing). */ INT frameSize; /*!< The frame size of the decoded PCM audio signal. \n 1024 or 960 for AAC-LC \n 2048 or 1920 for HE-AAC (v2) \n 512 or 480 for AAC-LD and AAC-ELD */ INT numChannels; /*!< The number of output audio channels in the decoded and interleaved PCM audio signal. */ - AUDIO_CHANNEL_TYPE *pChannelType; /*!< Audio channel type of each output audio channel. */ - UCHAR *pChannelIndices; /*!< Audio channel index for each output audio channel. + AUDIO_CHANNEL_TYPE *pChannelType; /*!< Audio channel type of each output audio channel. */ + UCHAR *pChannelIndices; /*!< Audio channel index for each output audio channel. See ISO/IEC 13818-7:2005(E), 8.5.3.2 Explicit channel mapping using a program_config_element() */ /* Decoder internal members. */ - INT aacSampleRate; /*!< sampling rate in Hz without SBR (from configuration info). */ + INT aacSampleRate; /*!< Sampling rate in Hz without SBR (from configuration info). */ INT profile; /*!< MPEG-2 profile (from file header) (-1: not applicable (e. g. MPEG-4)). */ AUDIO_OBJECT_TYPE aot; /*!< Audio Object Type (from ASC): is set to the appropriate value for MPEG-2 bitstreams (e. g. 2 for AAC-LC). */ INT channelConfig; /*!< Channel configuration (0: PCE defined, 1: mono, 2: stereo, ... */ @@ -556,7 +556,9 @@ typedef struct AUDIO_OBJECT_TYPE extAot; /*!< Extension Audio Object Type (from ASC) */ INT extSamplingRate; /*!< Extension sampling rate in Hz (from ASC) */ - UINT flags; /*!< Copy if internal flags. Only to be written by the decoder, and only to be read externally. */ + UINT outputDelay; /*!< The number of samples the output is additionally delayed by the decoder. */ + + UINT flags; /*!< Copy of internal flags. Only to be written by the decoder, and only to be read externally. */ SCHAR epConfig; /*!< epConfig level (from ASC): only level 0 supported, -1 means no ER (e. g. AOT=2, MPEG-2 AAC, etc.) */ @@ -681,11 +683,15 @@ aacDecoder_Fill ( HANDLE_AACDECODER self, const UINT bufferSize[], UINT *bytesValid ); -#define AACDEC_CONCEAL 1 /*!< Flag for aacDecoder_DecodeFrame(): do not consider new input data. Do concealment. */ -#define AACDEC_FLUSH 2 /*!< Flag for aacDecoder_DecodeFrame(): Do not consider new input data. Flush filterbanks (output delayed audio). */ -#define AACDEC_INTR 4 /*!< Flag for aacDecoder_DecodeFrame(): Signal an input bit stream data discontinuity. Resync any internals as necessary. */ -#define AACDEC_CLRHIST 8 /*!< Flag for aacDecoder_DecodeFrame(): Clear all signal delay lines and history buffers. - Caution: This can cause discontinuities in the output signal. */ +#define AACDEC_CONCEAL 1 /*!< Flag for aacDecoder_DecodeFrame(): Trigger the built-in error concealment module \ + to generate a substitute signal for one lost frame. New input data will not be + considered. */ +#define AACDEC_FLUSH 2 /*!< Flag for aacDecoder_DecodeFrame(): Flush all filterbanks to get all delayed audio \ + without having new input data. Thus new input data will not be considered.*/ +#define AACDEC_INTR 4 /*!< Flag for aacDecoder_DecodeFrame(): Signal an input bit stream data discontinuity. \ + Resync any internals as necessary. */ +#define AACDEC_CLRHIST 8 /*!< Flag for aacDecoder_DecodeFrame(): Clear all signal delay lines and history buffers.\ + CAUTION: This can cause discontinuities in the output signal. */ /** * \brief Decode one audio frame diff --git a/libAACdec/src/aacdecoder.cpp b/libAACdec/src/aacdecoder.cpp index 18c9afa..15b47ab 100644 --- a/libAACdec/src/aacdecoder.cpp +++ b/libAACdec/src/aacdecoder.cpp @@ -717,6 +717,8 @@ void CStreamInfoInit(CStreamInfo *pStreamInfo) pStreamInfo->numChannels = 0; pStreamInfo->sampleRate = 0; pStreamInfo->frameSize = 0; + + pStreamInfo->outputDelay = 0; } /*! @@ -1184,11 +1186,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)); } } @@ -1508,10 +1507,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; } } @@ -1601,13 +1609,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; } } @@ -1687,6 +1699,11 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame( } + 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 */ @@ -1765,6 +1782,8 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame( ); } + /* Add additional concealment delay */ + self->streamInfo.outputDelay += CConcealment_GetDelay(&self->concealCommonData) * self->streamInfo.aacSamplesPerFrame; /* Reorder channel type information tables. */ { diff --git a/libAACdec/src/aacdecoder.h b/libAACdec/src/aacdecoder.h index bcbc040..3541773 100644 --- a/libAACdec/src/aacdecoder.h +++ b/libAACdec/src/aacdecoder.h @@ -198,7 +198,10 @@ struct AAC_DECODER_INSTANCE { 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. */ diff --git a/libAACdec/src/aacdecoder_lib.cpp b/libAACdec/src/aacdecoder_lib.cpp index 98ef0de..e2c757a 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 7 +#define AACDECODER_LIB_VL2 8 #define AACDECODER_LIB_TITLE "AAC Decoder Lib" #define AACDECODER_LIB_BUILD_DATE __DATE__ #define AACDECODER_LIB_BUILD_TIME __TIME__ @@ -842,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; @@ -857,6 +858,8 @@ 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. */ @@ -916,6 +919,9 @@ LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_DecodeFrame( 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 */ @@ -958,6 +964,9 @@ LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_DecodeFrame( self->streamInfo.frameSize = self->streamInfo.aacSamplesPerFrame << 1; } } + /* Correct the additional concealment delay figures */ + self->streamInfo.outputDelay -= self->sbrParams.bsDelay * self->streamInfo.aacSamplesPerFrame; + self->streamInfo.outputDelay += self->sbrParams.bsDelay * self->streamInfo.frameSize; if (self->psPossible) { self->flags |= AC_PS_PRESENT; @@ -1014,6 +1023,9 @@ LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_DecodeFrame( self->extGainDelay, self->streamInfo.frameSize ); + + /* Announce the additional limiter output delay */ + self->streamInfo.outputDelay += getLimiterDelay(self->hLimiter); } } diff --git a/libSBRdec/include/sbrdecoder.h b/libSBRdec/include/sbrdecoder.h index cb06dbc..36a4739 100644 --- a/libSBRdec/include/sbrdecoder.h +++ b/libSBRdec/include/sbrdecoder.h @@ -145,6 +145,8 @@ typedef enum SBR_SYSTEM_BITSTREAM_DELAY, /*!< System: Switch to enable an additional SBR bitstream delay of one frame. */ SBR_QMF_MODE, /*!< Set QMF mode, either complex or low power. */ SBR_LD_QMF_TIME_ALIGN, /*!< Set QMF type, either LD-MPS or CLDFB. Relevant for ELD streams only. */ + SBR_FLUSH_DATA, /*!< Set internal state to flush the decoder with the next process call. */ + SBR_CLEAR_HISTORY, /*!< Clear all internal states (delay lines, QMF states, ...). */ SBR_BS_INTERRUPTION /*!< Signal bit stream interruption. Value is ignored. */ } SBRDEC_PARAM; diff --git a/libSBRdec/src/env_extr.h b/libSBRdec/src/env_extr.h index 5db6d3d..ddbfa18 100644 --- a/libSBRdec/src/env_extr.h +++ b/libSBRdec/src/env_extr.h @@ -179,6 +179,8 @@ typedef FREQ_BAND_DATA *HANDLE_FREQ_BAND_DATA; #define SBRDEC_LOW_POWER 16 /* Flag indicating that Low Power QMF mode shall be used. */ #define SBRDEC_PS_DECODED 32 /* Flag indicating that PS was decoded and rendered. */ #define SBRDEC_LD_MPS_QMF 512 /* Flag indicating that the LD-MPS QMF shall be used. */ +#define SBRDEC_FLUSH 16384 /* Flag is used to flush all elements in use. */ +#define SBRDEC_FORCE_RESET 32768 /* Flag is used to force a reset of all elements in use. */ #define SBRDEC_HDR_STAT_RESET 1 #define SBRDEC_HDR_STAT_UPDATE 2 diff --git a/libSBRdec/src/sbrdecoder.cpp b/libSBRdec/src/sbrdecoder.cpp index 5734020..bed23c7 100644 --- a/libSBRdec/src/sbrdecoder.cpp +++ b/libSBRdec/src/sbrdecoder.cpp @@ -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 4 +#define SBRDECODER_LIB_VL2 5 #define SBRDECODER_LIB_TITLE "SBR Decoder" #define SBRDECODER_LIB_BUILD_DATE __DATE__ #define SBRDECODER_LIB_BUILD_TIME __TIME__ @@ -444,6 +444,7 @@ SBR_ERROR sbrDecoder_InitElement ( && self->coreCodec == coreCodec && self->pSbrElement[elementIndex] != NULL && self->pSbrElement[elementIndex]->elementID == elementID + && !(self->flags & SBRDEC_FORCE_RESET) ) { /* Nothing to do */ @@ -550,8 +551,9 @@ bail: if (nSbrElementsStart < self->numSbrElements) { /* Free the memory allocated for this element */ sbrDecoder_DestroyElement( self, elementIndex ); - } else if (self->pSbrElement[elementIndex] != NULL) { - /* Set error flag to trigger concealment */ + } else if ( (self->pSbrElement[elementIndex] != NULL) + && (elementIndex < (8))) + { /* Set error flag to trigger concealment */ self->pSbrElement[elementIndex]->frameErrorFlag[self->pSbrElement[elementIndex]->useFrameSlot] = 1; } } @@ -728,6 +730,24 @@ SBR_ERROR sbrDecoder_SetParam (HANDLE_SBRDECODER self, } } break; + case SBR_FLUSH_DATA: + if (value != 0) { + if (self == NULL) { + errorStatus = SBRDEC_NOT_INITIALIZED; + } else { + self->flags |= SBRDEC_FLUSH; + } + } + break; + case SBR_CLEAR_HISTORY: + if (value != 0) { + if (self == NULL) { + errorStatus = SBRDEC_NOT_INITIALIZED; + } else { + self->flags |= SBRDEC_FORCE_RESET; + } + } + break; case SBR_BS_INTERRUPTION: { int elementIndex; @@ -738,7 +758,8 @@ SBR_ERROR sbrDecoder_SetParam (HANDLE_SBRDECODER self, } /* Loop over SBR elements */ - for (elementIndex = 0; elementIndex < self->numSbrElements; elementIndex++) + for (elementIndex = 0; elementIndex < self->numSbrElements; elementIndex++) { + if (self->pSbrElement[elementIndex] != NULL) { HANDLE_SBR_HEADER_DATA hSbrHeader; int headerIndex = getHeaderSlot(self->pSbrElement[elementIndex]->useFrameSlot, @@ -750,7 +771,7 @@ SBR_ERROR sbrDecoder_SetParam (HANDLE_SBRDECODER self, This switches off bitstream parsing until a new header arrives. */ hSbrHeader->syncState = UPSAMPLING; hSbrHeader->status |= SBRDEC_HDR_STAT_UPDATE; - } + } } } break; default: @@ -1119,6 +1140,10 @@ SBR_ERROR sbrDecoder_Parse( } } } + } else { + /* The returned bit count will not be the actual payload size since we did not + parse the frame data. Return an error so that the caller can react respectively. */ + errorStatus = SBRDEC_PARSE_ERROR; } if (!fDoDecodeSbrData) { @@ -1198,6 +1223,15 @@ sbrDecoder_DecodeElement ( int stereo = (hSbrElement->elementID == ID_CPE) ? 1 : 0; int numElementChannels = hSbrElement->nChannels; /* Number of channels of the current SBR element */ + if (self->flags & SBRDEC_FLUSH) { + /* Move frame pointer to the next slot which is up to be decoded/applied next */ + hSbrElement->useFrameSlot = (hSbrElement->useFrameSlot+1) % (self->numDelayFrames+1); + /* Update header and frame data pointer because they have already been set */ + hSbrHeader = &self->sbrHeader[elementIndex][hSbrElement->useHeaderSlot[hSbrElement->useFrameSlot]]; + hFrameDataLeft = &hSbrElement->pSbrChannel[0]->frameData[hSbrElement->useFrameSlot]; + hFrameDataRight = &hSbrElement->pSbrChannel[1]->frameData[hSbrElement->useFrameSlot]; + } + /* Update the header error flag */ hSbrHeader->frameErrorFlag = hSbrElement->frameErrorFlag[hSbrElement->useFrameSlot]; @@ -1472,6 +1506,10 @@ SBR_ERROR sbrDecoder_Apply ( HANDLE_SBRDECODER self, + /* Clear reset and flush flag because everything seems to be done successfully. */ + self->flags &= ~SBRDEC_FORCE_RESET; + self->flags &= ~SBRDEC_FLUSH; + bail: return errorStatus; |