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
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 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 @@
   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 @@
                   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 @@
   pStreamInfo->numChannels = 0;
   pStreamInfo->sampleRate = 0;
   pStreamInfo->frameSize = 0;
+
+  pStreamInfo->outputDelay = 0;
 }
 
 /*!
@@ -1184,11 +1186,8 @@
       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 @@
                 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 @@
     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 @@
       }
 
 
+      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 @@
           );
   }
 
+  /* 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 @@
   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 @@
 /* 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 @@
     /* 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 @@
       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 @@
       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 @@
            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 @@
               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 @@
   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 @@
 #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 @@
 /* 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 @@
      && self->coreCodec == coreCodec
      && self->pSbrElement[elementIndex] != NULL
      && self->pSbrElement[elementIndex]->elementID == elementID
+     && !(self->flags & SBRDEC_FORCE_RESET)
      )
   {
      /* Nothing to do */
@@ -550,8 +551,9 @@
     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 @@
       }
     }
     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 @@
       }
 
       /* 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 @@
            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 @@
         }
       }
     }
+  } 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 @@
   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 @@
 
 
 
+  /* Clear reset and flush flag because everything seems to be done successfully. */
+  self->flags &= ~SBRDEC_FORCE_RESET;
+  self->flags &= ~SBRDEC_FLUSH;
+
 bail:
 
   return errorStatus;