Snap for 7277594 from edbf93589b1786557383451f2d6d34fd85d8e73d to mainline-documentsui-release

Change-Id: I0b92789091acd39674317db5b61c2fc442c1a83f
diff --git a/Android.bp b/Android.bp
index 1cf54fd..3f42c19 100644
--- a/Android.bp
+++ b/Android.bp
@@ -23,6 +23,7 @@
         "-Wuninitialized",
         "-Wno-self-assign",
         "-Wno-implicit-fallthrough",
+        "-DSUPPRESS_BUILD_DATE_INFO",
     ],
     sanitize: {
         misc_undefined:[
diff --git a/libAACdec/src/aac_ram.cpp b/libAACdec/src/aac_ram.cpp
index aa8f6a6..fac1540 100644
--- a/libAACdec/src/aac_ram.cpp
+++ b/libAACdec/src/aac_ram.cpp
@@ -1,7 +1,7 @@
 /* -----------------------------------------------------------------------------
 Software License for The Fraunhofer FDK AAC Codec Library for Android
 
-© Copyright  1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright  1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
 Forschung e.V. All rights reserved.
 
  1.    INTRODUCTION
@@ -148,7 +148,7 @@
 /*! The buffer holds time samples for the crossfade in case of an USAC DASH IPF
    config change Dimension: (8)
  */
-C_ALLOC_MEM2(TimeDataFlush, INT_PCM, TIME_DATA_FLUSH_SIZE, (8))
+C_ALLOC_MEM2(TimeDataFlush, PCM_DEC, TIME_DATA_FLUSH_SIZE, (8))
 
 /* @} */
 
diff --git a/libAACdec/src/aac_ram.h b/libAACdec/src/aac_ram.h
index b9b95b7..395b2b2 100644
--- a/libAACdec/src/aac_ram.h
+++ b/libAACdec/src/aac_ram.h
@@ -1,7 +1,7 @@
 /* -----------------------------------------------------------------------------
 Software License for The Fraunhofer FDK AAC Codec Library for Android
 
-© Copyright  1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright  1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
 Forschung e.V. All rights reserved.
 
  1.    INTRODUCTION
@@ -132,7 +132,7 @@
 H_ALLOC_MEM(SpectralCoeffs, FIXP_DBL)
 H_ALLOC_MEM(SpecScale, SHORT)
 
-H_ALLOC_MEM(TimeDataFlush, INT_PCM)
+H_ALLOC_MEM(TimeDataFlush, PCM_DEC)
 
 H_ALLOC_MEM_OVERLAY(WorkBufferCore1, CWorkBufferCore1)
 H_ALLOC_MEM_OVERLAY(WorkBufferCore2, FIXP_DBL)
diff --git a/libAACdec/src/aacdec_drc.cpp b/libAACdec/src/aacdec_drc.cpp
index b6f5b49..760a9ba 100644
--- a/libAACdec/src/aacdec_drc.cpp
+++ b/libAACdec/src/aacdec_drc.cpp
@@ -1,7 +1,7 @@
 /* -----------------------------------------------------------------------------
 Software License for The Fraunhofer FDK AAC Codec Library for Android
 
-© Copyright  1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright  1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
 Forschung e.V. All rights reserved.
 
  1.    INTRODUCTION
@@ -150,6 +150,19 @@
 }
 
 /*!
+\brief  Disable DRC
+
+\self Handle of DRC info
+
+\return none
+*/
+void aacDecoder_drcDisable(HANDLE_AAC_DRC self) {
+  self->enable = 0;
+  self->applyExtGain = 0;
+  self->progRefLevelPresent = 0;
+}
+
+/*!
 \brief Reset DRC information
 
 \self Handle of DRC info
diff --git a/libAACdec/src/aacdec_drc.h b/libAACdec/src/aacdec_drc.h
index 76a44d6..2bb945d 100644
--- a/libAACdec/src/aacdec_drc.h
+++ b/libAACdec/src/aacdec_drc.h
@@ -1,7 +1,7 @@
 /* -----------------------------------------------------------------------------
 Software License for The Fraunhofer FDK AAC Codec Library for Android
 
-© Copyright  1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright  1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
 Forschung e.V. All rights reserved.
 
  1.    INTRODUCTION
@@ -140,6 +140,8 @@
 /**
  * \brief DRC module interface functions
  */
+void aacDecoder_drcDisable(HANDLE_AAC_DRC self);
+
 void aacDecoder_drcReset(HANDLE_AAC_DRC self);
 
 void aacDecoder_drcInit(HANDLE_AAC_DRC self);
diff --git a/libAACdec/src/aacdec_hcrs.cpp b/libAACdec/src/aacdec_hcrs.cpp
index 44b32a5..5e3f9ac 100644
--- a/libAACdec/src/aacdec_hcrs.cpp
+++ b/libAACdec/src/aacdec_hcrs.cpp
@@ -1,7 +1,7 @@
 /* -----------------------------------------------------------------------------
 Software License for The Fraunhofer FDK AAC Codec Library for Android
 
-© Copyright  1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright  1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
 Forschung e.V. All rights reserved.
 
  1.    INTRODUCTION
@@ -173,7 +173,9 @@
     pHcr->segmentInfo.readDirection = FROM_RIGHT_TO_LEFT;
 
     /* Process sets subsequently */
+    numSet = fMin(numSet, (UCHAR)MAX_HCR_SETS);
     for (currentSet = 1; currentSet < numSet; currentSet++) {
+
       /* step 1 */
       numCodeword -=
           *pNumSegment; /* number of remaining non PCWs [for all sets] */
diff --git a/libAACdec/src/aacdecoder.cpp b/libAACdec/src/aacdecoder.cpp
index 965631b..c18e5e9 100644
--- a/libAACdec/src/aacdecoder.cpp
+++ b/libAACdec/src/aacdecoder.cpp
@@ -568,7 +568,7 @@
   \return  Error code
 */
 LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_PrepareCrossFade(
-    const INT_PCM *pTimeData, INT_PCM **pTimeDataFlush, const INT numChannels,
+    const PCM_DEC *pTimeData, PCM_DEC **pTimeDataFlush, const INT numChannels,
     const INT frameSize, const INT interleaved) {
   int i, ch, s1, s2;
   AAC_DECODER_ERROR ErrorStatus;
@@ -584,7 +584,7 @@
   }
 
   for (ch = 0; ch < numChannels; ch++) {
-    const INT_PCM *pIn = &pTimeData[ch * s1];
+    const PCM_DEC *pIn = &pTimeData[ch * s1];
     for (i = 0; i < TIME_DATA_FLUSH_SIZE; i++) {
       pTimeDataFlush[ch][i] = *pIn;
       pIn += s2;
@@ -606,7 +606,7 @@
   \return  Error code
 */
 LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_ApplyCrossFade(
-    INT_PCM *pTimeData, INT_PCM **pTimeDataFlush, const INT numChannels,
+    PCM_DEC *pTimeData, PCM_DEC **pTimeDataFlush, const INT numChannels,
     const INT frameSize, const INT interleaved) {
   int i, ch, s1, s2;
   AAC_DECODER_ERROR ErrorStatus;
@@ -622,15 +622,15 @@
   }
 
   for (ch = 0; ch < numChannels; ch++) {
-    INT_PCM *pIn = &pTimeData[ch * s1];
+    PCM_DEC *pIn = &pTimeData[ch * s1];
     for (i = 0; i < TIME_DATA_FLUSH_SIZE; i++) {
       FIXP_SGL alpha = (FIXP_SGL)i
                        << (FRACT_BITS - 1 - TIME_DATA_FLUSH_SIZE_SF);
-      FIXP_DBL time = FX_PCM2FX_DBL(*pIn);
-      FIXP_DBL timeFlush = FX_PCM2FX_DBL(pTimeDataFlush[ch][i]);
+      FIXP_DBL time = PCM_DEC2FIXP_DBL(*pIn);
+      FIXP_DBL timeFlush = PCM_DEC2FIXP_DBL(pTimeDataFlush[ch][i]);
 
-      *pIn = (INT_PCM)(FIXP_PCM)FX_DBL2FX_PCM(
-          timeFlush - fMult(timeFlush, alpha) + fMult(time, alpha));
+      *pIn = FIXP_DBL2PCM_DEC(timeFlush - fMult(timeFlush, alpha) +
+                              fMult(time, alpha));
       pIn += s2;
     }
   }
@@ -753,7 +753,12 @@
     /* We are interested in preroll AUs if an explicit or an implicit config
      * change is signalized in other words if the build up status is set. */
     if (self->buildUpStatus == AACDEC_USAC_BUILD_UP_ON) {
-      self->applyCrossfade |= FDKreadBit(hBs);
+      UCHAR applyCrossfade = FDKreadBit(hBs);
+      if (applyCrossfade) {
+        self->applyCrossfade |= AACDEC_CROSSFADE_BITMASK_PREROLL;
+      } else {
+        self->applyCrossfade &= ~AACDEC_CROSSFADE_BITMASK_PREROLL;
+      }
       FDKreadBit(hBs); /* reserved */
       /* Read num preroll AU's */
       *numPrerollAU = escapedValue(hBs, 2, 4, 0);
@@ -1397,6 +1402,31 @@
 }
 
 /*!
+ * \brief CAacDecoder_AcceptFlags Accept flags and element flags
+ *
+ * \param self          [o]   handle to AACDECODER structure
+ * \param asc           [i]   handle to ASC structure
+ * \param flags         [i]   flags
+ * \param elFlags       [i]   pointer to element flags
+ * \param streamIndex   [i]   stream index
+ * \param elementOffset [i]   element offset
+ *
+ * \return void
+ */
+static void CAacDecoder_AcceptFlags(HANDLE_AACDECODER self,
+                                    const CSAudioSpecificConfig *asc,
+                                    UINT flags, UINT *elFlags, int streamIndex,
+                                    int elementOffset) {
+  {
+    FDKmemcpy(
+        self->elFlags, elFlags,
+        sizeof(*elFlags) * (3 * ((8) * 2) + (((8) * 2)) / 2 + 4 * (1) + 1));
+  }
+
+  self->flags[streamIndex] = flags;
+}
+
+/*!
  * \brief CAacDecoder_CtrlCFGChange Set config change parameters.
  *
  * \param self           [i]   handle to AACDECODER structure
@@ -1493,6 +1523,9 @@
   const int streamIndex = 0;
   INT flushChannels = 0;
 
+  UINT flags;
+  UINT elFlags[(3 * ((8) * 2) + (((8) * 2)) / 2 + 4 * (1) + 1)];
+
   if (!self) return AAC_DEC_INVALID_HANDLE;
 
   UCHAR downscaleFactor = self->downscaleFactor;
@@ -1649,8 +1682,8 @@
   }
 
   /* Set syntax flags */
-  self->flags[streamIndex] = 0;
-  { FDKmemclear(self->elFlags, sizeof(self->elFlags)); }
+  flags = 0;
+  { FDKmemclear(elFlags, sizeof(elFlags)); }
 
   if ((asc->m_channelConfiguration > 0) || IS_USAC(asc->m_aot)) {
     if (IS_USAC(asc->m_aot)) {
@@ -1700,31 +1733,30 @@
           }
         }
 
-        self->elFlags[el] |=
-            (asc->m_sc.m_usacConfig.element[_el].m_noiseFilling)
-                ? AC_EL_USAC_NOISE
-                : 0;
-        self->elFlags[el] |=
+        elFlags[el] |= (asc->m_sc.m_usacConfig.element[_el].m_noiseFilling)
+                           ? AC_EL_USAC_NOISE
+                           : 0;
+        elFlags[el] |=
             (asc->m_sc.m_usacConfig.element[_el].m_stereoConfigIndex > 0)
                 ? AC_EL_USAC_MPS212
                 : 0;
-        self->elFlags[el] |= (asc->m_sc.m_usacConfig.element[_el].m_interTes)
-                                 ? AC_EL_USAC_ITES
-                                 : 0;
-        self->elFlags[el] |=
+        elFlags[el] |= (asc->m_sc.m_usacConfig.element[_el].m_interTes)
+                           ? AC_EL_USAC_ITES
+                           : 0;
+        elFlags[el] |=
             (asc->m_sc.m_usacConfig.element[_el].m_pvc) ? AC_EL_USAC_PVC : 0;
-        self->elFlags[el] |=
+        elFlags[el] |=
             (asc->m_sc.m_usacConfig.element[_el].usacElementType == ID_USAC_LFE)
                 ? AC_EL_USAC_LFE
                 : 0;
-        self->elFlags[el] |=
+        elFlags[el] |=
             (asc->m_sc.m_usacConfig.element[_el].usacElementType == ID_USAC_LFE)
                 ? AC_EL_LFE
                 : 0;
         if ((asc->m_sc.m_usacConfig.element[_el].usacElementType ==
              ID_USAC_CPE) &&
             ((self->usacStereoConfigIndex[el] == 0))) {
-          self->elFlags[el] |= AC_EL_USAC_CP_POSSIBLE;
+          elFlags[el] |= AC_EL_USAC_CP_POSSIBLE;
         }
       }
 
@@ -1791,9 +1823,17 @@
       downscaleFactorInBS =
           asc->m_samplingFrequency /
           asc->m_sc.m_eldSpecificConfig.m_downscaledSamplingFrequency;
-      if (downscaleFactorInBS == 1 || downscaleFactorInBS == 2 ||
-          downscaleFactorInBS == 3 || downscaleFactorInBS == 4) {
+      if ((downscaleFactorInBS == 1 || downscaleFactorInBS == 2 ||
+           (downscaleFactorInBS == 3 &&
+            asc->m_sc.m_eldSpecificConfig.m_frameLengthFlag) ||
+           downscaleFactorInBS == 4) &&
+          ((asc->m_samplingFrequency %
+            asc->m_sc.m_eldSpecificConfig.m_downscaledSamplingFrequency) ==
+           0)) {
         downscaleFactor = downscaleFactorInBS;
+      } else {
+        downscaleFactorInBS = 1;
+        downscaleFactor = 1;
       }
     }
   } else {
@@ -1838,8 +1878,8 @@
   if (configMode & AC_CM_ALLOC_MEM) {
     self->streamInfo.extSamplingRate = asc->m_extensionSamplingFrequency;
   }
-  self->flags[streamIndex] |= (asc->m_sbrPresentFlag) ? AC_SBR_PRESENT : 0;
-  self->flags[streamIndex] |= (asc->m_psPresentFlag) ? AC_PS_PRESENT : 0;
+  flags |= (asc->m_sbrPresentFlag) ? AC_SBR_PRESENT : 0;
+  flags |= (asc->m_psPresentFlag) ? AC_PS_PRESENT : 0;
   if (asc->m_sbrPresentFlag) {
     self->sbrEnabled = 1;
     self->sbrEnabledPrev = 1;
@@ -1865,51 +1905,47 @@
   }
 
   /* --------- vcb11 ------------ */
-  self->flags[streamIndex] |= (asc->m_vcb11Flag) ? AC_ER_VCB11 : 0;
+  flags |= (asc->m_vcb11Flag) ? AC_ER_VCB11 : 0;
 
   /* ---------- rvlc ------------ */
-  self->flags[streamIndex] |= (asc->m_rvlcFlag) ? AC_ER_RVLC : 0;
+  flags |= (asc->m_rvlcFlag) ? AC_ER_RVLC : 0;
 
   /* ----------- hcr ------------ */
-  self->flags[streamIndex] |= (asc->m_hcrFlag) ? AC_ER_HCR : 0;
+  flags |= (asc->m_hcrFlag) ? AC_ER_HCR : 0;
 
   if (asc->m_aot == AOT_ER_AAC_ELD) {
     self->mpsEnableCurr = 0;
-    self->flags[streamIndex] |= AC_ELD;
-    self->flags[streamIndex] |=
-        (asc->m_sbrPresentFlag)
-            ? AC_SBR_PRESENT
-            : 0; /* Need to set the SBR flag for backward-compatibility
-       reasons. Even if SBR is not supported. */
-    self->flags[streamIndex] |=
-        (asc->m_sc.m_eldSpecificConfig.m_sbrCrcFlag) ? AC_SBRCRC : 0;
-    self->flags[streamIndex] |=
-        (asc->m_sc.m_eldSpecificConfig.m_useLdQmfTimeAlign) ? AC_MPS_PRESENT
-                                                            : 0;
+    flags |= AC_ELD;
+    flags |= (asc->m_sbrPresentFlag)
+                 ? AC_SBR_PRESENT
+                 : 0; /* Need to set the SBR flag for backward-compatibility
+                               reasons. Even if SBR is not supported. */
+    flags |= (asc->m_sc.m_eldSpecificConfig.m_sbrCrcFlag) ? AC_SBRCRC : 0;
+    flags |= (asc->m_sc.m_eldSpecificConfig.m_useLdQmfTimeAlign)
+                 ? AC_MPS_PRESENT
+                 : 0;
     if (self->mpsApplicable) {
       self->mpsEnableCurr = asc->m_sc.m_eldSpecificConfig.m_useLdQmfTimeAlign;
     }
   }
-  self->flags[streamIndex] |= (asc->m_aot == AOT_ER_AAC_LD) ? AC_LD : 0;
-  self->flags[streamIndex] |= (asc->m_epConfig >= 0) ? AC_ER : 0;
+  flags |= (asc->m_aot == AOT_ER_AAC_LD) ? AC_LD : 0;
+  flags |= (asc->m_epConfig >= 0) ? AC_ER : 0;
 
   if (asc->m_aot == AOT_USAC) {
-    self->flags[streamIndex] |= AC_USAC;
-    self->flags[streamIndex] |=
-        (asc->m_sc.m_usacConfig.element[0].m_stereoConfigIndex > 0)
-            ? AC_MPS_PRESENT
-            : 0;
+    flags |= AC_USAC;
+    flags |= (asc->m_sc.m_usacConfig.element[0].m_stereoConfigIndex > 0)
+                 ? AC_MPS_PRESENT
+                 : 0;
   }
   if (asc->m_aot == AOT_DRM_AAC) {
-    self->flags[streamIndex] |= AC_DRM | AC_SBRCRC | AC_SCALABLE;
+    flags |= AC_DRM | AC_SBRCRC | AC_SCALABLE;
   }
   if (asc->m_aot == AOT_DRM_SURROUND) {
-    self->flags[streamIndex] |=
-        AC_DRM | AC_SBRCRC | AC_SCALABLE | AC_MPS_PRESENT;
+    flags |= AC_DRM | AC_SBRCRC | AC_SCALABLE | AC_MPS_PRESENT;
     FDK_ASSERT(!asc->m_psPresentFlag);
   }
   if ((asc->m_aot == AOT_AAC_SCAL) || (asc->m_aot == AOT_ER_AAC_SCAL)) {
-    self->flags[streamIndex] |= AC_SCALABLE;
+    flags |= AC_SCALABLE;
   }
 
   if ((asc->m_epConfig >= 0) && (asc->m_channelConfiguration <= 0)) {
@@ -1960,6 +1996,10 @@
     if (ascChanged != 0) {
       *configChanged = 1;
     }
+
+    CAacDecoder_AcceptFlags(self, asc, flags, elFlags, streamIndex,
+                            elementOffset);
+
     return err;
   }
 
@@ -1988,7 +2028,7 @@
         }
 
         if (usacStereoConfigIndex == 3) {
-          self->flags[streamIndex] |= AC_USAC_SCFGI3;
+          flags |= AC_USAC_SCFGI3;
         }
       }
       break;
@@ -2069,14 +2109,14 @@
       ch = aacChannelsOffset;
       int _numElements;
       _numElements = (((8)) + (8));
-      if (self->flags[streamIndex] & (AC_RSV603DA | AC_USAC)) {
+      if (flags & (AC_RSV603DA | AC_USAC)) {
         _numElements = (int)asc->m_sc.m_usacConfig.m_usacNumElements;
       }
       for (int _el = 0; _el < _numElements; _el++) {
         int el_channels = 0;
         int el = elementOffset + _el;
 
-        if (self->flags[streamIndex] &
+        if (flags &
             (AC_ER | AC_LD | AC_ELD | AC_RSV603DA | AC_USAC | AC_RSVD50)) {
           if (ch >= ascChannels) {
             break;
@@ -2176,15 +2216,14 @@
           if (self->pAacDecoderStaticChannelInfo[ch]->pOverlapBuffer == NULL) {
             goto bail;
           }
-          if (self->flags[streamIndex] &
-              (AC_USAC | AC_RSVD50 | AC_RSV603DA /*|AC_BSAC*/)) {
+          if (flags & (AC_USAC | AC_RSVD50 | AC_RSV603DA /*|AC_BSAC*/)) {
             self->pAacDecoderStaticChannelInfo[ch]->hArCo = CArco_Create();
             if (self->pAacDecoderStaticChannelInfo[ch]->hArCo == NULL) {
               goto bail;
             }
           }
 
-          if (!(self->flags[streamIndex] & (AC_USAC | AC_RSV603DA))) {
+          if (!(flags & (AC_USAC | AC_RSV603DA))) {
             CPns_UpdateNoiseState(
                 &self->pAacDecoderChannelInfo[ch]->data.aac.PnsData,
                 &self->pAacDecoderStaticChannelInfo[ch]->pnsCurrentSeed,
@@ -2195,7 +2234,7 @@
         chIdx++;
       }
 
-      if (self->flags[streamIndex] & AC_USAC) {
+      if (flags & AC_USAC) {
         for (int _ch = 0; _ch < flushChannels; _ch++) {
           ch = aacChannelsOffset + _ch;
           if (self->pTimeDataFlush[ch] == NULL) {
@@ -2207,7 +2246,7 @@
         }
       }
 
-      if (self->flags[streamIndex] & (AC_USAC | AC_RSV603DA)) {
+      if (flags & (AC_USAC | AC_RSV603DA)) {
         int complexStereoPredPossible = 0;
         ch = aacChannelsOffset;
         chIdx = aacChannelsOffsetIdx;
@@ -2223,7 +2262,7 @@
             elCh = 1;
           }
 
-          if (self->elFlags[el2] & AC_EL_USAC_CP_POSSIBLE) {
+          if (elFlags[el2] & AC_EL_USAC_CP_POSSIBLE) {
             complexStereoPredPossible = 1;
             if (self->cpeStaticData[el2] == NULL) {
               self->cpeStaticData[el2] = GetCpePersistentData();
@@ -2360,9 +2399,6 @@
     }
   }
 
-  /* Update externally visible copy of flags */
-  self->streamInfo.flags = self->flags[0];
-
   if (*configChanged) {
     int drcDecSampleRate, drcDecFrameSize;
 
@@ -2383,8 +2419,7 @@
 
   if (*configChanged) {
     if (asc->m_aot == AOT_USAC) {
-      self->hDrcInfo->enable = 0;
-      self->hDrcInfo->progRefLevelPresent = 0;
+      aacDecoder_drcDisable(self->hDrcInfo);
     }
   }
 
@@ -2393,6 +2428,12 @@
     pcmLimiter_SetThreshold(self->hLimiter, FL2FXCONST_DBL(0.89125094f));
   }
 
+  CAacDecoder_AcceptFlags(self, asc, flags, elFlags, streamIndex,
+                          elementOffset);
+
+  /* Update externally visible copy of flags */
+  self->streamInfo.flags = self->flags[0];
+
   return err;
 
 bail:
@@ -3194,11 +3235,12 @@
          * data in the bitstream. */
         self->flags[streamIndex] |= AC_DRC_PRESENT;
       } else {
-        self->hDrcInfo->enable = 0;
-        self->hDrcInfo->progRefLevelPresent = 0;
         ErrorStatus = AAC_DEC_UNSUPPORTED_FORMAT;
       }
     }
+    if (self->flags[streamIndex] & (AC_USAC | AC_RSV603DA)) {
+      aacDecoder_drcDisable(self->hDrcInfo);
+    }
 
     /* Create a reverse mapping table */
     UCHAR Reverse_chMapping[((8) * 2)];
@@ -3441,11 +3483,12 @@
          * data in the bitstream. */
         self->flags[streamIndex] |= AC_DRC_PRESENT;
       } else {
-        self->hDrcInfo->enable = 0;
-        self->hDrcInfo->progRefLevelPresent = 0;
         ErrorStatus = AAC_DEC_UNSUPPORTED_FORMAT;
       }
     }
+    if (self->flags[streamIndex] & (AC_USAC | AC_RSV603DA)) {
+      aacDecoder_drcDisable(self->hDrcInfo);
+    }
   }
 
   /* Add additional concealment delay */
diff --git a/libAACdec/src/aacdecoder.h b/libAACdec/src/aacdecoder.h
index bd1f38f..002807f 100644
--- a/libAACdec/src/aacdecoder.h
+++ b/libAACdec/src/aacdecoder.h
@@ -1,7 +1,7 @@
 /* -----------------------------------------------------------------------------
 Software License for The Fraunhofer FDK AAC Codec Library for Android
 
-© Copyright  1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright  1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
 Forschung e.V. All rights reserved.
 
  1.    INTRODUCTION
@@ -172,6 +172,12 @@
   AACDEC_RSV60_BUILD_UP_IDLE_IN_BAND = 5
 };
 
+#define AACDEC_CROSSFADE_BITMASK_OFF                                    \
+  ((UCHAR)0) /*!< No cross-fade between frames shall be applied at next \
+                config change. */
+#define AACDEC_CROSSFADE_BITMASK_PREROLL \
+  ((UCHAR)1 << 1) /*!< applyCrossfade is signaled in AudioPreRoll */
+
 typedef struct {
   /* Usac Extension Elements */
   USAC_EXT_ELEMENT_TYPE usacExtElementType[(3)];
@@ -325,7 +331,7 @@
   UINT loudnessInfoSetPosition[3];
   SCHAR defaultTargetLoudness;
 
-  INT_PCM
+  PCM_DEC
   *pTimeDataFlush[((8) * 2)]; /*!< Pointer to the flushed time data which
                                  will be used for the crossfade in case of
                                  an USAC DASH IPF config change */
@@ -341,8 +347,8 @@
                                                           start position in the
                                                           bitstream */
   INT accessUnit; /*!< Number of the actual processed preroll accessUnit */
-  UCHAR applyCrossfade; /*!< if set crossfade for seamless stream switching is
-                           applied */
+  UCHAR applyCrossfade; /*!< If any bit is set, cross-fade for seamless stream
+                           switching is applied */
 
   FDK_SignalDelay usacResidualDelay; /*!< Delay residual signal to compensate
                                         for eSBR delay of DMX signal in case of
@@ -439,12 +445,12 @@
 
 /* Prepare crossfade for USAC DASH IPF config change */
 LINKSPEC_H AAC_DECODER_ERROR CAacDecoder_PrepareCrossFade(
-    const INT_PCM *pTimeData, INT_PCM **pTimeDataFlush, const INT numChannels,
+    const PCM_DEC *pTimeData, PCM_DEC **pTimeDataFlush, const INT numChannels,
     const INT frameSize, const INT interleaved);
 
 /* Apply crossfade for USAC DASH IPF config change */
 LINKSPEC_H AAC_DECODER_ERROR CAacDecoder_ApplyCrossFade(
-    INT_PCM *pTimeData, INT_PCM **pTimeDataFlush, const INT numChannels,
+    PCM_DEC *pTimeData, PCM_DEC **pTimeDataFlush, const INT numChannels,
     const INT frameSize, const INT interleaved);
 
 /* Set flush and build up mode */
diff --git a/libAACdec/src/aacdecoder_lib.cpp b/libAACdec/src/aacdecoder_lib.cpp
index f5ce7e0..9d36d10 100644
--- a/libAACdec/src/aacdecoder_lib.cpp
+++ b/libAACdec/src/aacdecoder_lib.cpp
@@ -122,7 +122,7 @@
 #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
@@ -385,21 +385,19 @@
   return errTp;
 }
 
-static INT aacDecoder_SscCallback(void *handle, HANDLE_FDK_BITSTREAM hBs,
-                                  const AUDIO_OBJECT_TYPE coreCodec,
-                                  const INT samplingRate, const INT frameSize,
-                                  const INT stereoConfigIndex,
-                                  const INT coreSbrFrameLengthIndex,
-                                  const INT configBytes, const UCHAR configMode,
-                                  UCHAR *configChanged) {
+static INT aacDecoder_SscCallback(
+    void *handle, HANDLE_FDK_BITSTREAM hBs, const AUDIO_OBJECT_TYPE coreCodec,
+    const INT samplingRate, const INT frameSize, const INT numChannels,
+    const INT stereoConfigIndex, const INT coreSbrFrameLengthIndex,
+    const INT configBytes, const UCHAR configMode, UCHAR *configChanged) {
   SACDEC_ERROR err;
   TRANSPORTDEC_ERROR errTp;
   HANDLE_AACDECODER hAacDecoder = (HANDLE_AACDECODER)handle;
 
   err = mpegSurroundDecoder_Config(
       (CMpegSurroundDecoder *)hAacDecoder->pMpegSurroundDecoder, hBs, coreCodec,
-      samplingRate, frameSize, stereoConfigIndex, coreSbrFrameLengthIndex,
-      configBytes, configMode, configChanged);
+      samplingRate, frameSize, numChannels, stereoConfigIndex,
+      coreSbrFrameLengthIndex, configBytes, configMode, configChanged);
 
   switch (err) {
     case MPS_UNSUPPORTED_CONFIG:
@@ -443,12 +441,23 @@
   TRANSPORTDEC_ERROR errTp;
   HANDLE_AACDECODER hAacDecoder = (HANDLE_AACDECODER)handle;
   DRC_DEC_CODEC_MODE drcDecCodecMode = DRC_DEC_CODEC_MODE_UNDEFINED;
+  UCHAR dummyBuffer[4] = {0};
+  FDK_BITSTREAM dummyBs;
+  HANDLE_FDK_BITSTREAM hReadBs;
 
   if (subStreamIndex != 0) {
     return TRANSPORTDEC_OK;
   }
 
-  else if (aot == AOT_USAC) {
+  if (hBs == NULL) {
+    /* use dummy zero payload to clear memory */
+    hReadBs = &dummyBs;
+    FDKinitBitStream(hReadBs, dummyBuffer, 4, 24);
+  } else {
+    hReadBs = hBs;
+  }
+
+  if (aot == AOT_USAC) {
     drcDecCodecMode = DRC_DEC_MPEG_D_USAC;
   }
 
@@ -457,10 +466,10 @@
 
   if (payloadType == 0) /* uniDrcConfig */
   {
-    err = FDK_drcDec_ReadUniDrcConfig(hAacDecoder->hUniDrcDecoder, hBs);
+    err = FDK_drcDec_ReadUniDrcConfig(hAacDecoder->hUniDrcDecoder, hReadBs);
   } else /* loudnessInfoSet */
   {
-    err = FDK_drcDec_ReadLoudnessInfoSet(hAacDecoder->hUniDrcDecoder, hBs);
+    err = FDK_drcDec_ReadLoudnessInfoSet(hAacDecoder->hUniDrcDecoder, hReadBs);
     hAacDecoder->loudnessInfoSetPosition[1] = payloadStart;
     hAacDecoder->loudnessInfoSetPosition[2] = fullPayloadLength;
   }
@@ -822,6 +831,9 @@
 
     case AAC_DRC_ATTENUATION_FACTOR:
       /* DRC compression factor (where 0 is no and 127 is max compression) */
+      if ((value < 0) || (value > 127)) {
+        return AAC_DEC_SET_PARAM_FAIL;
+      }
       errorStatus = aacDecoder_drcSetParam(hDrcInfo, DRC_CUT_SCALE, value);
       uniDrcErr = FDK_drcDec_SetParam(self->hUniDrcDecoder, DRC_DEC_COMPRESS,
                                       value * (FL2FXCONST_DBL(0.5f / 127.0f)));
@@ -829,6 +841,9 @@
 
     case AAC_DRC_BOOST_FACTOR:
       /* DRC boost factor (where 0 is no and 127 is max boost) */
+      if ((value < 0) || (value > 127)) {
+        return AAC_DEC_SET_PARAM_FAIL;
+      }
       errorStatus = aacDecoder_drcSetParam(hDrcInfo, DRC_BOOST_SCALE, value);
       uniDrcErr = FDK_drcDec_SetParam(self->hUniDrcDecoder, DRC_DEC_BOOST,
                                       value * (FL2FXCONST_DBL(0.5f / 127.0f)));
@@ -1151,6 +1166,8 @@
   int applyCrossfade = 1;    /* flag indicates if flushing was possible */
   PCM_DEC *pTimeData2;
   PCM_AAC *pTimeData3;
+  INT pcmLimiterScale = 0;
+  INT interleaved = 0;
 
   if (self == NULL) {
     return AAC_DEC_INVALID_HANDLE;
@@ -1173,8 +1190,10 @@
       aacDecoder_FreeMemCallback(self, &asc);
       self->streamInfo.numChannels = 0;
       /* 3) restore AudioSpecificConfig */
-      transportDec_OutOfBandConfig(self->hInput, asc.config,
-                                   (asc.configBits + 7) >> 3, 0);
+      if (asc.configBits <= (TP_USAC_MAX_CONFIG_LEN << 3)) {
+        transportDec_OutOfBandConfig(self->hInput, asc.config,
+                                     (asc.configBits + 7) >> 3, 0);
+      }
     }
   }
 
@@ -1794,8 +1813,7 @@
       }
 
       if (self->streamInfo.extAot != AOT_AAC_SLS) {
-        INT pcmLimiterScale = 0;
-        INT interleaved = 0;
+        interleaved = 0;
         interleaved |= (self->sbrEnabled) ? 1 : 0;
         interleaved |= (self->mpsEnableCurr) ? 1 : 0;
         PCMDMX_ERROR dmxErr = PCMDMX_OK;
@@ -1826,145 +1844,38 @@
            * predictable behavior and thus maybe produce strange output. */
           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;
-          int blockLength = self->streamInfo.frameSize;
-
-          /* Set actual signal parameters */
-          pcmLimiter_SetNChannels(self->hLimiter, self->streamInfo.numChannels);
-          pcmLimiter_SetSampleRate(self->hLimiter, self->streamInfo.sampleRate);
-
-          if ((self->streamInfo.numChannels == 1) || (self->sbrEnabled) ||
-              (self->mpsEnableCurr)) {
-            pInterleaveBuffer = (PCM_LIM *)pTimeData2;
-          } else {
-            pInterleaveBuffer = (PCM_LIM *)self->workBufferCore2;
-
-            /* applyLimiter requests for interleaved data */
-            /* Interleave ouput buffer */
-            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,
-                           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, pTimeData2,
-                self->streamInfo.frameSize * self->streamInfo.numChannels,
-                pcmLimiterScale);
-
-          } else {
-            scaleValuesSaturate(
-                (INT_PCM *)self->workBufferCore2, pTimeData2,
-                self->streamInfo.frameSize * self->streamInfo.numChannels,
-                pcmLimiterScale);
-            /* Interleave ouput buffer */
-            FDK_interleave((INT_PCM *)self->workBufferCore2, pTimeData,
-                           self->streamInfo.numChannels,
-                           self->streamInfo.frameSize,
-                           self->streamInfo.frameSize);
-          }
-        }
-      } /* if (self->streamInfo.extAot != AOT_AAC_SLS)*/
+      }
 
       if (self->flags[0] & AC_USAC) {
         if (self->flushStatus == AACDEC_USAC_DASH_IPF_FLUSH_ON &&
             !(flags & AACDEC_CONCEAL)) {
-          CAacDecoder_PrepareCrossFade(pTimeData, self->pTimeDataFlush,
+          CAacDecoder_PrepareCrossFade(pTimeData2, self->pTimeDataFlush,
                                        self->streamInfo.numChannels,
-                                       self->streamInfo.frameSize, 1);
+                                       self->streamInfo.frameSize, interleaved);
         }
 
         /* prepare crossfade buffer for fade in */
-        if (!applyCrossfade && self->applyCrossfade &&
+        if (!applyCrossfade &&
+            (self->applyCrossfade != AACDEC_CROSSFADE_BITMASK_OFF) &&
             !(flags & AACDEC_CONCEAL)) {
           for (int ch = 0; ch < self->streamInfo.numChannels; ch++) {
             for (int i = 0; i < TIME_DATA_FLUSH_SIZE; i++) {
-              self->pTimeDataFlush[ch][i] = 0;
+              self->pTimeDataFlush[ch][i] = (PCM_DEC)0;
             }
           }
           applyCrossfade = 1;
         }
 
-        if (applyCrossfade && self->applyCrossfade &&
+        if (applyCrossfade &&
+            (self->applyCrossfade != AACDEC_CROSSFADE_BITMASK_OFF) &&
             !(accessUnit < numPrerollAU) &&
             (self->buildUpStatus == AACDEC_USAC_BUILD_UP_ON)) {
-          CAacDecoder_ApplyCrossFade(pTimeData, self->pTimeDataFlush,
+          CAacDecoder_ApplyCrossFade(pTimeData2, self->pTimeDataFlush,
                                      self->streamInfo.numChannels,
-                                     self->streamInfo.frameSize, 1);
-          self->applyCrossfade = 0;
+                                     self->streamInfo.frameSize, interleaved);
+          self->applyCrossfade =
+              AACDEC_CROSSFADE_BITMASK_OFF; /* disable cross-fade between frames
+                                               at nect config change */
         }
       }
 
@@ -2006,6 +1917,116 @@
            ((self->flushStatus == AACDEC_USAC_DASH_IPF_FLUSH_ON) &&
             !(flags & AACDEC_CONCEAL)));
 
+  if (self->streamInfo.extAot != AOT_AAC_SLS) {
+    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;
+      int blockLength = self->streamInfo.frameSize;
+
+      /* Set actual signal parameters */
+      pcmLimiter_SetNChannels(self->hLimiter, self->streamInfo.numChannels);
+      pcmLimiter_SetSampleRate(self->hLimiter, self->streamInfo.sampleRate);
+
+      if ((self->streamInfo.numChannels == 1) || (self->sbrEnabled) ||
+          (self->mpsEnableCurr)) {
+        pInterleaveBuffer = (PCM_LIM *)pTimeData2;
+      } else {
+        pInterleaveBuffer = (PCM_LIM *)self->workBufferCore2;
+
+        /* applyLimiter requests for interleaved data */
+        /* Interleave ouput buffer */
+        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,
+                       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, pTimeData2,
+            self->streamInfo.frameSize * self->streamInfo.numChannels,
+            pcmLimiterScale);
+
+      } else {
+        scaleValuesSaturate(
+            (INT_PCM *)self->workBufferCore2, pTimeData2,
+            self->streamInfo.frameSize * self->streamInfo.numChannels,
+            pcmLimiterScale);
+        /* Interleave ouput buffer */
+        FDK_interleave((INT_PCM *)self->workBufferCore2, pTimeData,
+                       self->streamInfo.numChannels, self->streamInfo.frameSize,
+                       self->streamInfo.frameSize);
+      }
+    }
+  } /* if (self->streamInfo.extAot != AOT_AAC_SLS)*/
+
 bail:
 
   /* error in renderer part occurred, ErrorStatus was set to invalid output */
diff --git a/libAACdec/src/channel.cpp b/libAACdec/src/channel.cpp
index a020034..7e62bfb 100644
--- a/libAACdec/src/channel.cpp
+++ b/libAACdec/src/channel.cpp
@@ -1,7 +1,7 @@
 /* -----------------------------------------------------------------------------
 Software License for The Fraunhofer FDK AAC Codec Library for Android
 
-© Copyright  1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright  1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
 Forschung e.V. All rights reserved.
 
  1.    INTRODUCTION
@@ -265,7 +265,9 @@
          stereo prediction since scaling has already been carried out. */
       int max_sfb_ste = (INT)(pAacDecoderChannelInfo[L]->icsInfo.max_sfb_ste);
 
-      if ((!CP_active) || (CP_active && (max_sfb_ste < noSfbs)) ||
+      if (!(CP_active && (max_sfb_ste == noSfbs)) ||
+          !(CP_active &&
+            !(pAacDecoderChannelInfo[ch]->pDynData->TnsData.Active)) ||
           ((flags & (AC_USAC | AC_RSVD50 | AC_RSV603DA)) &&
            (pAacDecoderChannelInfo[L]->pDynData->specificTo.usac.tns_on_lr ==
             0))) {
diff --git a/libAACenc/src/aacenc.cpp b/libAACenc/src/aacenc.cpp
index b6f733d..1af8a2e 100644
--- a/libAACenc/src/aacenc.cpp
+++ b/libAACenc/src/aacenc.cpp
@@ -1,7 +1,7 @@
 /* -----------------------------------------------------------------------------
 Software License for The Fraunhofer FDK AAC Codec Library for Android
 
-© Copyright  1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright  1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
 Forschung e.V. All rights reserved.
 
  1.    INTRODUCTION
@@ -245,6 +245,46 @@
   return bitrate;
 }
 
+/*-----------------------------------------------------------------------------
+
+    functionname: FDKaacEnc_AdjustVBRBitrateMode
+    description:  Adjust bitrate mode to given bitrate parameter
+    input params: int vbrQuality (VBR0, VBR1, VBR2)
+                  bitrate
+                  channelMode
+    returns:      vbr bitrate mode
+
+ ------------------------------------------------------------------------------*/
+AACENC_BITRATE_MODE FDKaacEnc_AdjustVBRBitrateMode(
+    AACENC_BITRATE_MODE bitrateMode, INT bitrate, CHANNEL_MODE channelMode) {
+  AACENC_BITRATE_MODE newBitrateMode = bitrateMode;
+
+  if (bitrate != -1) {
+    const INT monoStereoMode =
+        (FDKaacEnc_GetMonoStereoMode(channelMode) == EL_MODE_STEREO) ? 1 : 0;
+    const INT nChannelsEff =
+        FDKaacEnc_GetChannelModeConfiguration(channelMode)->nChannelsEff;
+    newBitrateMode = AACENC_BR_MODE_INVALID;
+
+    for (int idx = (int)(sizeof(configTabVBR) / sizeof(*configTabVBR)) - 1;
+         idx >= 0; idx--) {
+      if (bitrate >=
+          configTabVBR[idx].chanBitrate[monoStereoMode] * nChannelsEff) {
+        if (configTabVBR[idx].chanBitrate[monoStereoMode] * nChannelsEff <
+            FDKaacEnc_GetVBRBitrate(bitrateMode, channelMode)) {
+          newBitrateMode = configTabVBR[idx].bitrateMode;
+        } else {
+          newBitrateMode = bitrateMode;
+        }
+        break;
+      }
+    }
+  }
+
+  return AACENC_BR_MODE_IS_VBR(newBitrateMode) ? newBitrateMode
+                                               : AACENC_BR_MODE_INVALID;
+}
+
 /**
  * \brief  Convert encoder bitreservoir value for transport library.
  *
@@ -397,7 +437,6 @@
   FIXP_DBL mbfac, bw_ratio;
   QC_INIT qcInit;
   INT averageBitsPerFrame = 0;
-  int bitresMin = 0; /* the bitreservoir is always big for AAC-LC */
   const CHANNEL_MODE prevChannelMode = hAacEnc->encoderMode;
 
   if (config == NULL) return AAC_ENC_INVALID_HANDLE;
@@ -553,7 +592,6 @@
     qcInit.minBits = fixMin(qcInit.minBits, averageBitsPerFrame & ~7);
   } else {
     INT bitreservoir = -1; /* default bitreservoir size*/
-    bitresMin = BITRES_MIN;
     if (isLowDelay(config->audioObjectType)) {
       INT brPerChannel = config->bitRate / config->nChannels;
       brPerChannel = fMin(BITRATE_MAX_LD, fMax(BITRATE_MIN_LD, brPerChannel));
@@ -567,7 +605,6 @@
       bitreservoir = fMultI(slope, (INT)(BITRES_MAX_LD - BITRES_MIN_LD)) +
                      BITRES_MIN_LD;     /* interpolate */
       bitreservoir = bitreservoir & ~7; /* align to bytes */
-      bitresMin = BITRES_MIN_LD;
     }
 
     int maxBitres;
@@ -604,7 +641,8 @@
   qcInit.nSubFrames = config->nSubFrames;
   qcInit.padding.paddingRest = config->sampleRate;
 
-  if (qcInit.maxBits - qcInit.averageBits >= bitresMin * config->nChannels) {
+  if (qcInit.maxBits - qcInit.averageBits >=
+      ((qcInit.isLowDelay) ? BITRES_MIN_LD : BITRES_MIN) * config->nChannels) {
     qcInit.bitResMode = AACENC_BR_MODE_FULL; /* full bitreservoir */
   } else if (qcInit.maxBits > qcInit.averageBits) {
     qcInit.bitResMode = AACENC_BR_MODE_REDUCED; /* reduced bitreservoir */
diff --git a/libAACenc/src/aacenc.h b/libAACenc/src/aacenc.h
index 0e0d8c1..b7e0ef2 100644
--- a/libAACenc/src/aacenc.h
+++ b/libAACenc/src/aacenc.h
@@ -1,7 +1,7 @@
 /* -----------------------------------------------------------------------------
 Software License for The Fraunhofer FDK AAC Codec Library for Android
 
-© Copyright  1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright  1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
 Forschung e.V. All rights reserved.
 
  1.    INTRODUCTION
@@ -335,6 +335,19 @@
 
 /*-----------------------------------------------------------------------------
 
+    functionname: FDKaacEnc_AdjustVBRBitrateMode
+    description:  Adjust bitrate mode to given bitrate parameter
+    input params: int vbrQuality (VBR0, VBR1, VBR2)
+                  bitrate
+                  channelMode
+    returns:      vbr bitrate mode
+
+ ------------------------------------------------------------------------------*/
+AACENC_BITRATE_MODE FDKaacEnc_AdjustVBRBitrateMode(
+    AACENC_BITRATE_MODE bitrateMode, INT bitrate, CHANNEL_MODE channelMode);
+
+/*-----------------------------------------------------------------------------
+
      functionname: FDKaacEnc_AacInitDefaultConfig
      description:  gives reasonable default configuration
      returns:      ---
diff --git a/libAACenc/src/aacenc_lib.cpp b/libAACenc/src/aacenc_lib.cpp
index 2c2010f..caa62c5 100644
--- a/libAACenc/src/aacenc_lib.cpp
+++ b/libAACenc/src/aacenc_lib.cpp
@@ -1,7 +1,7 @@
 /* -----------------------------------------------------------------------------
 Software License for The Fraunhofer FDK AAC Codec Library for Android
 
-© Copyright  1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright  1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
 Forschung e.V. All rights reserved.
 
  1.    INTRODUCTION
@@ -112,7 +112,7 @@
 #define AACENCODER_LIB_VL1 0
 #define AACENCODER_LIB_VL2 1
 #define AACENCODER_LIB_TITLE "AAC Encoder"
-#ifdef __ANDROID__
+#ifdef SUPPRESS_BUILD_DATE_INFO
 #define AACENCODER_LIB_BUILD_DATE ""
 #define AACENCODER_LIB_BUILD_TIME ""
 #else
@@ -1028,6 +1028,13 @@
     case AACENC_BR_MODE_VBR_3:
     case AACENC_BR_MODE_VBR_4:
     case AACENC_BR_MODE_VBR_5:
+      /* Adjust bitrate mode in case given peak bitrate is lower than expected
+       * VBR bitrate. */
+      if ((INT)config->userPeakBitrate != -1) {
+        hAacConfig->bitrateMode = FDKaacEnc_AdjustVBRBitrateMode(
+            hAacConfig->bitrateMode, config->userPeakBitrate,
+            hAacConfig->channelMode);
+      }
       /* Get bitrate in VBR configuration */
       /* In VBR mode; SBR-modul depends on bitrate, core encoder on bitrateMode.
        */
@@ -1235,7 +1242,7 @@
 INT aacenc_SscCallback(void *self, HANDLE_FDK_BITSTREAM hBs,
                        const AUDIO_OBJECT_TYPE coreCodec,
                        const INT samplingRate, const INT frameSize,
-                       const INT stereoConfigIndex,
+                       const INT numChannels, const INT stereoConfigIndex,
                        const INT coreSbrFrameLengthIndex, const INT configBytes,
                        const UCHAR configMode, UCHAR *configChanged) {
   HANDLE_AACENCODER hAacEncoder = (HANDLE_AACENCODER)self;
@@ -1777,8 +1784,8 @@
                                                    hAacEncoder->nSamplesRead));
     INT_PCM *pIn =
         hAacEncoder->inputBuffer +
-        (hAacEncoder->inputBufferOffset + hAacEncoder->nSamplesRead) /
-            hAacEncoder->aacConfig.nChannels;
+        hAacEncoder->inputBufferOffset / hAacEncoder->aacConfig.nChannels +
+        hAacEncoder->nSamplesRead / hAacEncoder->extParam.nChannels;
     newSamples -=
         (newSamples %
          hAacEncoder->extParam
@@ -1820,12 +1827,13 @@
 
         /* clear out until end-of-buffer */
         if (nZeros) {
+          INT_PCM *pIn =
+              hAacEncoder->inputBuffer +
+              hAacEncoder->inputBufferOffset /
+                  hAacEncoder->aacConfig.nChannels +
+              hAacEncoder->nSamplesRead / hAacEncoder->extParam.nChannels;
           for (i = 0; i < (int)hAacEncoder->extParam.nChannels; i++) {
-            FDKmemclear(hAacEncoder->inputBuffer +
-                            i * hAacEncoder->inputBufferSizePerChannel +
-                            (hAacEncoder->inputBufferOffset +
-                             hAacEncoder->nSamplesRead) /
-                                hAacEncoder->extParam.nChannels,
+            FDKmemclear(pIn + i * hAacEncoder->inputBufferSizePerChannel,
                         sizeof(INT_PCM) * nZeros);
           }
           hAacEncoder->nZerosAppended += nZeros;
diff --git a/libAACenc/src/qc_main.cpp b/libAACenc/src/qc_main.cpp
index bcfaa23..9a42550 100644
--- a/libAACenc/src/qc_main.cpp
+++ b/libAACenc/src/qc_main.cpp
@@ -1,7 +1,7 @@
 /* -----------------------------------------------------------------------------
 Software License for The Fraunhofer FDK AAC Codec Library for Android
 
-© Copyright  1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright  1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
 Forschung e.V. All rights reserved.
 
  1.    INTRODUCTION
@@ -373,13 +373,8 @@
   hQC->invQuant = init->invQuant;
   hQC->maxIterations = init->maxIterations;
 
-  if (isConstantBitrateMode(hQC->bitrateMode)) {
-    /* 0: full bitreservoir, 1: reduced bitreservoir, 2: disabled bitreservoir
-     */
-    hQC->bitResMode = init->bitResMode;
-  } else {
-    hQC->bitResMode = AACENC_BR_MODE_FULL; /* full bitreservoir */
-  }
+  /* 0: full bitreservoir, 1: reduced bitreservoir, 2: disabled bitreservoir */
+  hQC->bitResMode = init->bitResMode;
 
   hQC->padding.paddingRest = init->padding.paddingRest;
 
@@ -800,10 +795,15 @@
   INT avgTotalDynBits = 0; /* maximal allowed dynamic bits for all frames */
   INT totalAvailableBits = 0;
   INT nSubFrames = 1;
+  const INT isCBRAdjustment = (isConstantBitrateMode(hQC->bitrateMode) ||
+                               (hQC->bitResMode != AACENC_BR_MODE_FULL))
+                                  ? 1
+                                  : 0;
 
   /*-------------------------------------------- */
   /* redistribute total bitreservoir to elements */
-  ErrorStatus = FDKaacEnc_BitResRedistribution(hQC, cm, avgTotalBits);
+  ErrorStatus = FDKaacEnc_BitResRedistribution(
+      hQC, cm, (isCBRAdjustment == 0) ? hQC->maxBitsPerFrame : avgTotalBits);
   if (ErrorStatus != AAC_ENC_OK) {
     return ErrorStatus;
   }
@@ -831,33 +831,22 @@
 
   /*-------------------------------------------- */
   /*-------------------------------------------- */
-  if (isConstantBitrateMode(hQC->bitrateMode)) {
-    /* calc granted dynamic bits for sub frame and
-       distribute it to each element */
-    ErrorStatus = FDKaacEnc_prepareBitDistribution(
-        hQC, psyOut, qcOut, cm, qcElement, avgTotalBits, &totalAvailableBits,
-        &avgTotalDynBits);
+  /* calc granted dynamic bits for sub frame and
+     distribute it to each element */
+  ErrorStatus = FDKaacEnc_prepareBitDistribution(
+      hQC, psyOut, qcOut, cm, qcElement,
+      (isCBRAdjustment == 0) ? hQC->maxBitsPerFrame : avgTotalBits,
+      &totalAvailableBits, &avgTotalDynBits);
 
-    if (ErrorStatus != AAC_ENC_OK) {
-      return ErrorStatus;
-    }
-  } else {
-    qcOut[0]->grantedDynBits =
-        ((hQC->maxBitsPerFrame - (hQC->globHdrBits)) & ~7) -
-        (qcOut[0]->globalExtBits + qcOut[0]->staticBits +
-         qcOut[0]->elementExtBits);
-    qcOut[0]->maxDynBits = qcOut[0]->grantedDynBits;
-
-    totalAvailableBits = hQC->maxBitsPerFrame;
-    avgTotalDynBits = 0;
+  if (ErrorStatus != AAC_ENC_OK) {
+    return ErrorStatus;
   }
 
   /* for ( all sub frames ) ... */
   for (c = 0; c < nSubFrames; c++) {
     /* for CBR and VBR mode */
     FDKaacEnc_AdjustThresholds(hQC->hAdjThr, qcElement[c], qcOut[c],
-                               psyOut[c]->psyOutElement,
-                               isConstantBitrateMode(hQC->bitrateMode), cm);
+                               psyOut[c]->psyOutElement, isCBRAdjustment, cm);
 
   } /* -end- sub frame counter */
 
diff --git a/libDRCdec/src/FDK_drcDecLib.cpp b/libDRCdec/src/FDK_drcDecLib.cpp
index 83b5773..26e5b78 100644
--- a/libDRCdec/src/FDK_drcDecLib.cpp
+++ b/libDRCdec/src/FDK_drcDecLib.cpp
@@ -112,7 +112,7 @@
 #define DRCDEC_LIB_VL1 1
 #define DRCDEC_LIB_VL2 0
 #define DRCDEC_LIB_TITLE "MPEG-D DRC Decoder Lib"
-#ifdef __ANDROID__
+#ifdef SUPPRESS_BUILD_DATE_INFO
 #define DRCDEC_LIB_BUILD_DATE ""
 #define DRCDEC_LIB_BUILD_TIME ""
 #else
diff --git a/libDRCdec/src/drcDec_reader.cpp b/libDRCdec/src/drcDec_reader.cpp
index 367a352..b3ec187 100644
--- a/libDRCdec/src/drcDec_reader.cpp
+++ b/libDRCdec/src/drcDec_reader.cpp
@@ -1,7 +1,7 @@
 /* -----------------------------------------------------------------------------
 Software License for The Fraunhofer FDK AAC Codec Library for Android
 
-© Copyright  1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright  1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
 Forschung e.V. All rights reserved.
 
  1.    INTRODUCTION
@@ -512,10 +512,13 @@
               fMin(tmpNNodes, (UCHAR)16) * sizeof(GAIN_NODE));
   }
 
-  hUniDrcGain->uniDrcGainExtPresent = FDKreadBits(hBs, 1);
-  if (hUniDrcGain->uniDrcGainExtPresent == 1) {
-    err = _readUniDrcGainExtension(hBs, &(hUniDrcGain->uniDrcGainExtension));
-    if (err) return err;
+  if (pCoef && (gainSequenceCount ==
+                pCoef->gainSequenceCount)) { /* all sequences have been read */
+    hUniDrcGain->uniDrcGainExtPresent = FDKreadBits(hBs, 1);
+    if (hUniDrcGain->uniDrcGainExtPresent == 1) {
+      err = _readUniDrcGainExtension(hBs, &(hUniDrcGain->uniDrcGainExtension));
+      if (err) return err;
+    }
   }
 
   if (err == DE_OK && gainSequenceCount > 0) {
diff --git a/libFDK/src/FDK_core.cpp b/libFDK/src/FDK_core.cpp
index 2f77179..48db17e 100644
--- a/libFDK/src/FDK_core.cpp
+++ b/libFDK/src/FDK_core.cpp
@@ -107,7 +107,7 @@
 #define FDK_TOOLS_LIB_VL1 1
 #define FDK_TOOLS_LIB_VL2 0
 #define FDK_TOOLS_LIB_TITLE "FDK Tools"
-#ifdef __ANDROID__
+#ifdef SUPPRESS_BUILD_DATE_INFO
 #define FDK_TOOLS_LIB_BUILD_DATE ""
 #define FDK_TOOLS_LIB_BUILD_TIME ""
 #else
diff --git a/libFDK/src/FDK_hybrid.cpp b/libFDK/src/FDK_hybrid.cpp
index 08d32a8..d208abd 100644
--- a/libFDK/src/FDK_hybrid.cpp
+++ b/libFDK/src/FDK_hybrid.cpp
@@ -1,7 +1,7 @@
 /* -----------------------------------------------------------------------------
 Software License for The Fraunhofer FDK AAC Codec Library for Android
 
-© Copyright  1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright  1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
 Forschung e.V. All rights reserved.
 
  1.    INTRODUCTION
@@ -539,11 +539,11 @@
   i6 = pQmfImag[pReadIdx[6]] >> 2;
 
   FDK_ASSERT((invert == 0) || (invert == 1));
-  mHybridReal[0 + invert] = (r6 + r1) << 1;
-  mHybridImag[0 + invert] = (i6 + i1) << 1;
+  mHybridReal[0 + invert] = SATURATE_LEFT_SHIFT((r6 + r1), 1, DFRACT_BITS);
+  mHybridImag[0 + invert] = SATURATE_LEFT_SHIFT((i6 + i1), 1, DFRACT_BITS);
 
-  mHybridReal[1 - invert] = (r6 - r1) << 1;
-  mHybridImag[1 - invert] = (i6 - i1) << 1;
+  mHybridReal[1 - invert] = SATURATE_LEFT_SHIFT((r6 - r1), 1, DFRACT_BITS);
+  mHybridImag[1 - invert] = SATURATE_LEFT_SHIFT((i6 - i1), 1, DFRACT_BITS);
 }
 
 static void fourChannelFiltering(const FIXP_DBL *const pQmfReal,
@@ -766,15 +766,15 @@
     mHybridReal[3] = pfft[FFT_IDX_R(1)] << sc;
     mHybridImag[3] = pfft[FFT_IDX_I(1)] << sc;
 
-    mHybridReal[4] = pfft[FFT_IDX_R(2)] << sc;
-    mHybridReal[4] += pfft[FFT_IDX_R(5)] << sc;
-    mHybridImag[4] = pfft[FFT_IDX_I(2)] << sc;
-    mHybridImag[4] += pfft[FFT_IDX_I(5)] << sc;
+    mHybridReal[4] = SATURATE_LEFT_SHIFT(
+        (pfft[FFT_IDX_R(2)] + pfft[FFT_IDX_R(5)]), sc, DFRACT_BITS);
+    mHybridImag[4] = SATURATE_LEFT_SHIFT(
+        (pfft[FFT_IDX_I(2)] + pfft[FFT_IDX_I(5)]), sc, DFRACT_BITS);
 
-    mHybridReal[5] = pfft[FFT_IDX_R(3)] << sc;
-    mHybridReal[5] += pfft[FFT_IDX_R(4)] << sc;
-    mHybridImag[5] = pfft[FFT_IDX_I(3)] << sc;
-    mHybridImag[5] += pfft[FFT_IDX_I(4)] << sc;
+    mHybridReal[5] = SATURATE_LEFT_SHIFT(
+        (pfft[FFT_IDX_R(3)] + pfft[FFT_IDX_R(4)]), sc, DFRACT_BITS);
+    mHybridImag[5] = SATURATE_LEFT_SHIFT(
+        (pfft[FFT_IDX_I(3)] + pfft[FFT_IDX_I(4)]), sc, DFRACT_BITS);
   } else {
     for (k = 0; k < 8; k++) {
       mHybridReal[k] = pfft[FFT_IDX_R(k)] << sc;
diff --git a/libFDK/src/dct.cpp b/libFDK/src/dct.cpp
index bd26736..35507b5 100644
--- a/libFDK/src/dct.cpp
+++ b/libFDK/src/dct.cpp
@@ -1,7 +1,7 @@
 /* -----------------------------------------------------------------------------
 Software License for The Fraunhofer FDK AAC Codec Library for Android
 
-© Copyright  1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright  1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
 Forschung e.V. All rights reserved.
 
  1.    INTRODUCTION
@@ -305,9 +305,8 @@
 
   {
     for (i = 0; i < M; i++) {
-      tmp[i] = pDat[2 * i] >> 1; /* dit_fft expects 1 bit scaled input values */
-      tmp[L - 1 - i] =
-          pDat[2 * i + 1] >> 1; /* dit_fft expects 1 bit scaled input values */
+      tmp[i] = pDat[2 * i] >> 2;
+      tmp[L - 1 - i] = pDat[2 * i + 1] >> 2;
     }
   }
 
@@ -337,15 +336,14 @@
     a1 = ((pTmp_0[0] >> 1) + (pTmp_1[0] >> 1));
     a2 = ((pTmp_0[1] >> 1) - (pTmp_1[1] >> 1));
 
-    cplxMultDiv2(&accu3, &accu4, (a1 + accu2), -(accu1 + a2),
-                 sin_twiddle[i * inc]);
-    pDat[L - i] = accu4;
-    pDat[i] = accu3;
+    cplxMult(&accu3, &accu4, (accu1 + a2), (a1 + accu2), sin_twiddle[i * inc]);
+    pDat[L - i] = -accu3;
+    pDat[i] = accu4;
 
-    cplxMultDiv2(&accu3, &accu4, (a1 - accu2), -(accu1 - a2),
-                 sin_twiddle[(M - i) * inc]);
-    pDat[M + i] = accu4;
-    pDat[M - i] = accu3;
+    cplxMult(&accu3, &accu4, (accu1 - a2), (a1 - accu2),
+             sin_twiddle[(M - i) * inc]);
+    pDat[M + i] = -accu3;
+    pDat[M - i] = accu4;
 
     /* Create index helper variables for (4*i)*inc indexed equivalent values of
      * short tables. */
@@ -356,12 +354,12 @@
     }
   }
 
-  cplxMultDiv2(&accu1, &accu2, tmp[M], tmp[M + 1], sin_twiddle[(M / 2) * inc]);
+  cplxMult(&accu1, &accu2, tmp[M], tmp[M + 1], sin_twiddle[(M / 2) * inc]);
   pDat[L - (M / 2)] = accu2;
   pDat[M / 2] = accu1;
 
-  pDat[0] = (tmp[0] >> 1) + (tmp[1] >> 1);
-  pDat[M] = fMult(((tmp[0] >> 1) - (tmp[1] >> 1)),
+  pDat[0] = tmp[0] + tmp[1];
+  pDat[M] = fMult(tmp[0] - tmp[1],
                   sin_twiddle[M * inc].v.re); /* cos((PI/(2*L))*M); */
 
   *pDat_e += 2;
diff --git a/libMpegTPDec/include/tp_data.h b/libMpegTPDec/include/tp_data.h
index b015332..b63087a 100644
--- a/libMpegTPDec/include/tp_data.h
+++ b/libMpegTPDec/include/tp_data.h
@@ -1,7 +1,7 @@
 /* -----------------------------------------------------------------------------
 Software License for The Fraunhofer FDK AAC Codec Library for Android
 
-© Copyright  1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright  1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
 Forschung e.V. All rights reserved.
 
  1.    INTRODUCTION
@@ -368,7 +368,7 @@
 typedef INT (*cbSsc_t)(void *, HANDLE_FDK_BITSTREAM,
                        const AUDIO_OBJECT_TYPE coreCodec,
                        const INT samplingRate, const INT frameSize,
-                       const INT stereoConfigIndex,
+                       const INT numChannels, const INT stereoConfigIndex,
                        const INT coreSbrFrameLengthIndex, const INT configBytes,
                        const UCHAR configMode, UCHAR *configChanged);
 
diff --git a/libMpegTPDec/src/tpdec_asc.cpp b/libMpegTPDec/src/tpdec_asc.cpp
index 82f840e..e46cb32 100644
--- a/libMpegTPDec/src/tpdec_asc.cpp
+++ b/libMpegTPDec/src/tpdec_asc.cpp
@@ -1,7 +1,7 @@
 /* -----------------------------------------------------------------------------
 Software License for The Fraunhofer FDK AAC Codec Library for Android
 
-© Copyright  1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright  1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
 Forschung e.V. All rights reserved.
 
  1.    INTRODUCTION
@@ -266,11 +266,118 @@
   return (err);
 }
 
+/**
+ * \brief Sanity checks for program config element.
+ *        Check order of elements according to ISO/IEC 13818-7:2003(E),
+ * chapter 8.5.1
+ *
+ * \param pPce  pointer to program config element.
+ *
+ * \return  0 if successful, otherwise 1.
+ */
+static int CProgramConfig_Check(CProgramConfig *pPce) {
+  INT i;
+  INT err = 0;
+  INT numBackChannels[3] = {0};
+  INT numSideChannels[3] = {0};
+  INT numFrontChannels[3] = {0};
+  UCHAR *pCpeFront = pPce->FrontElementIsCpe;
+  UCHAR *pCpeSide = pPce->SideElementIsCpe;
+  UCHAR *pCpeBack = pPce->BackElementIsCpe;
+  UCHAR *pHeight;
+
+  pHeight = pPce->BackElementHeightInfo;
+  for (i = 0; i < pPce->NumBackChannelElements; i++) {
+    numBackChannels[*pHeight] += pPce->BackElementIsCpe[i] ? 2 : 1;
+    pHeight++;
+  }
+  pHeight = pPce->SideElementHeightInfo;
+  for (i = 0; i < pPce->NumSideChannelElements; i++) {
+    numSideChannels[*pHeight] += pPce->SideElementIsCpe[i] ? 2 : 1;
+    pHeight++;
+  }
+  pHeight = pPce->FrontElementHeightInfo;
+  for (i = 0; i < pPce->NumFrontChannelElements; i++) {
+    numFrontChannels[*pHeight] += pPce->FrontElementIsCpe[i] ? 2 : 1;
+    pHeight++;
+  }
+
+  /* 0 = normal height channels, 1 = top height channels, 2 = bottom height
+   * channels */
+  for (i = 0; i < 3; i++) {
+    /* if number of channels is odd => first element must be a SCE (front center
+     * channel) */
+    if (numFrontChannels[i] & 1) {
+      if (*pCpeFront++ == ID_CPE) {
+        err = 1;
+        goto bail;
+      }
+      numFrontChannels[i]--;
+    }
+    while (numFrontChannels[i] > 0) {
+      /* must be CPE or paired SCE */
+      if (*pCpeFront++ == ID_SCE) {
+        if (*pCpeFront++ == ID_CPE) {
+          err = 1;
+          goto bail;
+        }
+      }
+      numFrontChannels[i] -= 2;
+    };
+
+    /* in case that a top center surround channel (Ts) is transmitted the number
+     * of channels can be odd */
+    if (i != 1) {
+      /* number of channels must be even */
+      if (numSideChannels[i] & 1) {
+        err = 1;
+        goto bail;
+      }
+      while (numSideChannels[i] > 0) {
+        /* must be CPE or paired SCE */
+        if (*pCpeSide++ == ID_SCE) {
+          if (*pCpeSide++ == ID_CPE) {
+            err = 1;
+            goto bail;
+          }
+        }
+        numSideChannels[i] -= 2;
+      };
+    }
+
+    while (numBackChannels[i] > 1) {
+      /* must be CPE or paired SCE */
+      if (*pCpeBack++ == ID_SCE) {
+        if (*pCpeBack++ == ID_CPE) {
+          err = 1;
+          goto bail;
+        }
+      }
+      numBackChannels[i] -= 2;
+    };
+    /* if number of channels is odd => last element must be a SCE (back center
+     * channel) */
+    if (numBackChannels[i]) {
+      if (*pCpeBack++ == ID_CPE) {
+        err = 1;
+        goto bail;
+      }
+    }
+  }
+
+bail:
+
+  return err;
+}
+
 void CProgramConfig_Read(CProgramConfig *pPce, HANDLE_FDK_BITSTREAM bs,
                          UINT alignmentAnchor) {
-  int i, err = 0;
+  int i;
   int commentBytes;
+  UCHAR tag, isCpe;
+  UCHAR checkElementTagSelect[3][PC_FSB_CHANNELS_MAX] = {{0}};
 
+  pPce->isValid = 1;
   pPce->NumEffectiveChannels = 0;
   pPce->NumChannels = 0;
   pPce->ElementInstanceTag = (UCHAR)FDKreadBits(bs, 4);
@@ -297,28 +404,60 @@
   }
 
   for (i = 0; i < pPce->NumFrontChannelElements; i++) {
-    pPce->FrontElementIsCpe[i] = (UCHAR)FDKreadBits(bs, 1);
-    pPce->FrontElementTagSelect[i] = (UCHAR)FDKreadBits(bs, 4);
+    pPce->FrontElementIsCpe[i] = isCpe = (UCHAR)FDKreadBits(bs, 1);
+    pPce->FrontElementTagSelect[i] = tag = (UCHAR)FDKreadBits(bs, 4);
     pPce->NumChannels += pPce->FrontElementIsCpe[i] ? 2 : 1;
+
+    /* Check element instance tag according to ISO/IEC 13818-7:2003(E),
+     * chapter 8.2.1.1 */
+    if (checkElementTagSelect[isCpe][tag] == 0) {
+      checkElementTagSelect[isCpe][tag] = 1;
+    } else {
+      pPce->isValid = 0;
+    }
   }
 
   for (i = 0; i < pPce->NumSideChannelElements; i++) {
-    pPce->SideElementIsCpe[i] = (UCHAR)FDKreadBits(bs, 1);
-    pPce->SideElementTagSelect[i] = (UCHAR)FDKreadBits(bs, 4);
+    pPce->SideElementIsCpe[i] = isCpe = (UCHAR)FDKreadBits(bs, 1);
+    pPce->SideElementTagSelect[i] = tag = (UCHAR)FDKreadBits(bs, 4);
     pPce->NumChannels += pPce->SideElementIsCpe[i] ? 2 : 1;
+
+    /* Check element instance tag according to ISO/IEC 13818-7:2003(E),
+     * chapter 8.2.1.1 */
+    if (checkElementTagSelect[isCpe][tag] == 0) {
+      checkElementTagSelect[isCpe][tag] = 1;
+    } else {
+      pPce->isValid = 0;
+    }
   }
 
   for (i = 0; i < pPce->NumBackChannelElements; i++) {
-    pPce->BackElementIsCpe[i] = (UCHAR)FDKreadBits(bs, 1);
-    pPce->BackElementTagSelect[i] = (UCHAR)FDKreadBits(bs, 4);
+    pPce->BackElementIsCpe[i] = isCpe = (UCHAR)FDKreadBits(bs, 1);
+    pPce->BackElementTagSelect[i] = tag = (UCHAR)FDKreadBits(bs, 4);
     pPce->NumChannels += pPce->BackElementIsCpe[i] ? 2 : 1;
+
+    /* Check element instance tag according to ISO/IEC 13818-7:2003(E),
+     * chapter 8.2.1.1 */
+    if (checkElementTagSelect[isCpe][tag] == 0) {
+      checkElementTagSelect[isCpe][tag] = 1;
+    } else {
+      pPce->isValid = 0;
+    }
   }
 
   pPce->NumEffectiveChannels = pPce->NumChannels;
 
   for (i = 0; i < pPce->NumLfeChannelElements; i++) {
-    pPce->LfeElementTagSelect[i] = (UCHAR)FDKreadBits(bs, 4);
+    pPce->LfeElementTagSelect[i] = tag = (UCHAR)FDKreadBits(bs, 4);
     pPce->NumChannels += 1;
+
+    /* Check element instance tag according to ISO/IEC 13818-7:2003(E),
+     * chapter 8.2.1.1 */
+    if (checkElementTagSelect[2][tag] == 0) {
+      checkElementTagSelect[2][tag] = 1;
+    } else {
+      pPce->isValid = 0;
+    }
   }
 
   for (i = 0; i < pPce->NumAssocDataElements; i++) {
@@ -336,7 +475,15 @@
   commentBytes = pPce->CommentFieldBytes;
 
   /* Search for height info extension and read it if available */
-  err = CProgramConfig_ReadHeightExt(pPce, bs, &commentBytes, alignmentAnchor);
+  if (CProgramConfig_ReadHeightExt(pPce, bs, &commentBytes, alignmentAnchor)) {
+    pPce->isValid = 0;
+  }
+
+  /* Check order of elements according to ISO / IEC 13818 - 7:2003(E),
+   * chapter 8.5.1 */
+  if (CProgramConfig_Check(pPce)) {
+    pPce->isValid = 0;
+  }
 
   for (i = 0; i < commentBytes; i++) {
     UCHAR text;
@@ -347,8 +494,6 @@
       pPce->Comment[i] = text;
     }
   }
-
-  pPce->isValid = (err) ? 0 : 1;
 }
 
 /*
@@ -1415,7 +1560,7 @@
               cb->cbSscData, hBs, asc->m_aot,
               asc->m_samplingFrequency << esc->m_sbrSamplingRate,
               asc->m_samplesPerFrame << esc->m_sbrSamplingRate,
-              1,  /* stereoConfigIndex */
+              asc->m_channelConfiguration, 1, /* stereoConfigIndex */
               -1, /* nTimeSlots: read from bitstream */
               eldExtLen, asc->configMode, &asc->SacConfigChanged);
           if (ErrorStatus != TRANSPORTDEC_OK) {
@@ -1633,6 +1778,10 @@
   int numConfigExtensions;
   CONFIG_EXT_ID usacConfigExtType;
   int usacConfigExtLength;
+  int loudnessInfoSetIndex =
+      -1; /* index of loudnessInfoSet config extension. -1 if not contained. */
+  int tmp_subStreamIndex = 0;
+  AUDIO_OBJECT_TYPE tmp_aot = AOT_USAC;
 
   numConfigExtensions = (int)escapedValue(hBs, 2, 4, 8) + 1;
   for (int confExtIdx = 0; confExtIdx < numConfigExtensions; confExtIdx++) {
@@ -1662,10 +1811,12 @@
           ErrorStatus = (TRANSPORTDEC_ERROR)cb->cbUniDrc(
               cb->cbUniDrcData, hBs, usacConfigExtLength,
               1, /* loudnessInfoSet */
-              0, loudnessInfoSetConfigExtensionPosition, AOT_USAC);
+              tmp_subStreamIndex, loudnessInfoSetConfigExtensionPosition,
+              tmp_aot);
           if (ErrorStatus != TRANSPORTDEC_OK) {
             return ErrorStatus;
           }
+          loudnessInfoSetIndex = confExtIdx;
         }
       } break;
       default:
@@ -1681,6 +1832,17 @@
     FDKpushFor(hBs, usacConfigExtLength);
   }
 
+  if (loudnessInfoSetIndex == -1 && cb->cbUniDrc != NULL) {
+    /* no loudnessInfoSet contained. Clear the loudnessInfoSet struct by feeding
+     * an empty config extension */
+    ErrorStatus = (TRANSPORTDEC_ERROR)cb->cbUniDrc(
+        cb->cbUniDrcData, NULL, 0, 1 /* loudnessInfoSet */, tmp_subStreamIndex,
+        0, tmp_aot);
+    if (ErrorStatus != TRANSPORTDEC_OK) {
+      return ErrorStatus;
+    }
+  }
+
   return ErrorStatus;
 }
 
@@ -1697,6 +1859,8 @@
   int channelElementIdx =
       0; /* index for elements which contain audio channels (sce, cpe, lfe) */
   SC_CHANNEL_CONFIG sc_chan_config = {0, 0, 0, 0};
+  int uniDrcElement =
+      -1; /* index of uniDrc extension element. -1 if not contained. */
 
   numberOfElements = (int)escapedValue(hBs, 4, 8, 16) + 1;
   usc->m_usacNumElements = numberOfElements;
@@ -1827,6 +1991,8 @@
               /* Mps212Config() ISO/IEC FDIS 23003-3 */
               if (cb->cbSsc(cb->cbSscData, hBs, asc->m_aot,
                             asc->m_extensionSamplingFrequency, samplesPerFrame,
+                            1, /* only downmix channels (residual channels are
+                                  not counted) */
                             usc->element[i].m_stereoConfigIndex,
                             usc->m_coreSbrFrameLengthIndex,
                             0, /* don't know the length */
@@ -1870,6 +2036,10 @@
       case ID_USAC_EXT:
         ErrorStatus = extElementConfig(&usc->element[i].extElement, hBs, cb, 0,
                                        asc->m_samplesPerFrame, 0, asc->m_aot);
+        if (usc->element[i].extElement.usacExtElementType ==
+            ID_EXT_ELE_UNI_DRC) {
+          uniDrcElement = i;
+        }
 
         if (ErrorStatus) {
           return ErrorStatus;
@@ -1898,6 +2068,18 @@
     }
   }
 
+  if (uniDrcElement == -1 && cb->cbUniDrc != NULL) {
+    /* no uniDrcConfig contained. Clear the uniDrcConfig struct by feeding an
+     * empty extension element */
+    int subStreamIndex = 0;
+    ErrorStatus = (TRANSPORTDEC_ERROR)cb->cbUniDrc(
+        cb->cbUniDrcData, NULL, 0, 0 /* uniDrcConfig */, subStreamIndex, 0,
+        asc->m_aot);
+    if (ErrorStatus != TRANSPORTDEC_OK) {
+      return ErrorStatus;
+    }
+  }
+
   return ErrorStatus;
 }
 
@@ -1984,6 +2166,14 @@
     if (err != TRANSPORTDEC_OK) {
       return err;
     }
+  } else if (cb->cbUniDrc != NULL) {
+    /* no loudnessInfoSet contained. Clear the loudnessInfoSet struct by feeding
+     * an empty config extension */
+    err = (TRANSPORTDEC_ERROR)cb->cbUniDrc(
+        cb->cbUniDrcData, NULL, 0, 1 /* loudnessInfoSet */, 0, 0, asc->m_aot);
+    if (err != TRANSPORTDEC_OK) {
+      return err;
+    }
   }
 
   /* sanity check whether number of channels signaled in UsacDecoderConfig()
@@ -1996,9 +2186,11 @@
 
   /* Copy UsacConfig() to asc->m_sc.m_usacConfig.UsacConfig[] buffer. */
   INT configSize_bits = (INT)FDKgetValidBits(hBs) - nbits;
-  StoreConfigAsBitstream(hBs, configSize_bits,
-                         asc->m_sc.m_usacConfig.UsacConfig,
-                         TP_USAC_MAX_CONFIG_LEN);
+  if (StoreConfigAsBitstream(hBs, configSize_bits,
+                             asc->m_sc.m_usacConfig.UsacConfig,
+                             TP_USAC_MAX_CONFIG_LEN)) {
+    return TRANSPORTDEC_PARSE_ERROR;
+  }
   asc->m_sc.m_usacConfig.UsacConfigBits = fAbs(configSize_bits);
 
   return err;
@@ -2219,7 +2411,7 @@
     case AOT_MPEGS:
       if (cb->cbSsc != NULL) {
         if (cb->cbSsc(cb->cbSscData, bs, self->m_aot, self->m_samplingFrequency,
-                      self->m_samplesPerFrame, 1,
+                      self->m_samplesPerFrame, self->m_channelConfiguration, 1,
                       -1, /* nTimeSlots: read from bitstream */
                       0,  /* don't know the length */
                       self->configMode, &self->SacConfigChanged)) {
@@ -2300,8 +2492,10 @@
   /* Copy config() to asc->config[] buffer. */
   if ((ErrorStatus == TRANSPORTDEC_OK) && (self->m_aot == AOT_USAC)) {
     INT configSize_bits = (INT)FDKgetValidBits(bs) - (INT)ascStartAnchor;
-    StoreConfigAsBitstream(bs, configSize_bits, self->config,
-                           TP_USAC_MAX_CONFIG_LEN);
+    if (StoreConfigAsBitstream(bs, configSize_bits, self->config,
+                               TP_USAC_MAX_CONFIG_LEN)) {
+      return TRANSPORTDEC_PARSE_ERROR;
+    }
     self->configBits = fAbs(configSize_bits);
   }
 
@@ -2415,6 +2609,8 @@
                 cb->cbSscData, hBs,
                 AOT_DRM_USAC, /* syntax differs from MPEG Mps212Config() */
                 asc->m_extensionSamplingFrequency, samplesPerFrame,
+                1, /* only downmix channels (residual channels are not
+                      counted) */
                 usc->element[elemIdx].m_stereoConfigIndex,
                 usc->m_coreSbrFrameLengthIndex, 0, /* don't know the length */
                 asc->configMode, &asc->SacConfigChanged);
diff --git a/libMpegTPDec/src/tpdec_lib.cpp b/libMpegTPDec/src/tpdec_lib.cpp
index ca35184..091d011 100644
--- a/libMpegTPDec/src/tpdec_lib.cpp
+++ b/libMpegTPDec/src/tpdec_lib.cpp
@@ -1769,7 +1769,7 @@
   info += i;
 
   info->module_id = FDK_TPDEC;
-#ifdef __ANDROID__
+#ifdef SUPPRESS_BUILD_DATE_INFO
   info->build_date = "";
   info->build_time = "";
 #else
diff --git a/libMpegTPEnc/include/tp_data.h b/libMpegTPEnc/include/tp_data.h
index 00de356..464c485 100644
--- a/libMpegTPEnc/include/tp_data.h
+++ b/libMpegTPEnc/include/tp_data.h
@@ -1,7 +1,7 @@
 /* -----------------------------------------------------------------------------
 Software License for The Fraunhofer FDK AAC Codec Library for Android
 
-© Copyright  1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright  1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
 Forschung e.V. All rights reserved.
 
  1.    INTRODUCTION
@@ -368,7 +368,7 @@
 typedef INT (*cbSsc_t)(void *, HANDLE_FDK_BITSTREAM,
                        const AUDIO_OBJECT_TYPE coreCodec,
                        const INT samplingRate, const INT frameSize,
-                       const INT stereoConfigIndex,
+                       const INT numChannels, const INT stereoConfigIndex,
                        const INT coreSbrFrameLengthIndex, const INT configBytes,
                        const UCHAR configMode, UCHAR *configChanged);
 
diff --git a/libMpegTPEnc/src/tpenc_asc.cpp b/libMpegTPEnc/src/tpenc_asc.cpp
index 0b484a0..9591ba8 100644
--- a/libMpegTPEnc/src/tpenc_asc.cpp
+++ b/libMpegTPEnc/src/tpenc_asc.cpp
@@ -1,7 +1,7 @@
 /* -----------------------------------------------------------------------------
 Software License for The Fraunhofer FDK AAC Codec Library for Android
 
-© Copyright  1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright  1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
 Forschung e.V. All rights reserved.
 
  1.    INTRODUCTION
@@ -795,7 +795,7 @@
 
     const INT eldExtLen =
         (cb->cbSsc(cb->cbSscData, NULL, config->aot, config->extSamplingRate, 0,
-                   0, 0, 0, 0, NULL) +
+                   0, 0, 0, 0, 0, NULL) +
          7) >>
         3;
     INT cnt = eldExtLen;
@@ -818,7 +818,7 @@
     }
 
     cb->cbSsc(cb->cbSscData, hBs, config->aot, config->extSamplingRate, 0, 0, 0,
-              0, 0, NULL);
+              0, 0, 0, NULL);
   }
 
   if (config->downscaleSamplingRate != 0 &&
diff --git a/libMpegTPEnc/src/tpenc_lib.cpp b/libMpegTPEnc/src/tpenc_lib.cpp
index 14ea5fe..77c19b5 100644
--- a/libMpegTPEnc/src/tpenc_lib.cpp
+++ b/libMpegTPEnc/src/tpenc_lib.cpp
@@ -647,7 +647,7 @@
   info->module_id = FDK_TPENC;
   info->version = LIB_VERSION(TP_LIB_VL0, TP_LIB_VL1, TP_LIB_VL2);
   LIB_VERSION_STRING(info);
-#ifdef __ANDROID__
+#ifdef SUPPRESS_BUILD_DATE_INFO
   info->build_date = "";
   info->build_time = "";
 #else
diff --git a/libPCMutils/src/version.h b/libPCMutils/src/version.h
index 05371f8..871aa90 100644
--- a/libPCMutils/src/version.h
+++ b/libPCMutils/src/version.h
@@ -108,7 +108,7 @@
 #define PCMUTIL_LIB_VL1 1
 #define PCMUTIL_LIB_VL2 0
 #define PCMUTIL_LIB_TITLE "PCM Utility Lib"
-#ifdef __ANDROID__
+#ifdef SUPPRESS_BUILD_DATE_INFO
 #define PCMUTIL_LIB_BUILD_DATE ""
 #define PCMUTIL_LIB_BUILD_TIME ""
 #else
diff --git a/libSACdec/include/sac_dec_lib.h b/libSACdec/include/sac_dec_lib.h
index 1827504..5aad4e0 100644
--- a/libSACdec/include/sac_dec_lib.h
+++ b/libSACdec/include/sac_dec_lib.h
@@ -1,7 +1,7 @@
 /* -----------------------------------------------------------------------------
 Software License for The Fraunhofer FDK AAC Codec Library for Android
 
-© Copyright  1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright  1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
 Forschung e.V. All rights reserved.
 
  1.    INTRODUCTION
@@ -316,8 +316,8 @@
 SACDEC_ERROR mpegSurroundDecoder_Config(
     CMpegSurroundDecoder *pMpegSurroundDecoder, HANDLE_FDK_BITSTREAM hBs,
     AUDIO_OBJECT_TYPE coreCodec, INT samplingRate, INT frameSize,
-    INT stereoConfigIndex, INT coreSbrFrameLengthIndex, INT configBytes,
-    const UCHAR configMode, UCHAR *configChanged);
+    INT numChannels, INT stereoConfigIndex, INT coreSbrFrameLengthIndex,
+    INT configBytes, const UCHAR configMode, UCHAR *configChanged);
 
 SACDEC_ERROR
 mpegSurroundDecoder_ConfigureQmfDomain(
diff --git a/libSACdec/src/sac_dec.cpp b/libSACdec/src/sac_dec.cpp
index a7b50df..a26e251 100644
--- a/libSACdec/src/sac_dec.cpp
+++ b/libSACdec/src/sac_dec.cpp
@@ -1,7 +1,7 @@
 /* -----------------------------------------------------------------------------
 Software License for The Fraunhofer FDK AAC Codec Library for Android
 
-© Copyright  1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright  1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
 Forschung e.V. All rights reserved.
 
  1.    INTRODUCTION
@@ -1098,6 +1098,28 @@
   }
 }
 
+/**
+ * \brief Set internal error and reset error status
+ *
+ * \param self         spatialDec handle.
+ * \param bypassMode   pointer to bypassMode.
+ * \param err          error status.
+ *
+ * \return  error status.
+ */
+static SACDEC_ERROR SpatialDecSetInternalError(spatialDec *self,
+                                               int *bypassMode,
+                                               SACDEC_ERROR err) {
+  *bypassMode = 1;
+
+  if (self->errInt == MPS_OK) {
+    /* store internal error before it gets overwritten */
+    self->errInt = err;
+  }
+
+  return MPS_OK;
+}
+
 /*******************************************************************************
  Functionname: SpatialDecApplyParameterSets
  *******************************************************************************
@@ -1118,7 +1140,7 @@
     const FDK_channelMapDescr *const mapDescr) {
   SACDEC_ERROR err = MPS_OK;
 
-  FIXP_SGL alpha;
+  FIXP_SGL alpha = FL2FXCONST_SGL(0.0);
 
   int ts;
   int ch;
@@ -1141,20 +1163,22 @@
        ts++, ts_io++) {
     int currSlot = frame->paramSlot[ps];
 
+    err = (currSlot < ts) ? MPS_WRONG_PARAMETERSETS : MPS_OK;
+    if (err != MPS_OK) {
+      err = SpatialDecSetInternalError(self, &bypassMode, err);
+    }
+
     /*
      * Get new parameter set
      */
     if (ts == prevSlot + 1) {
-      err = SpatialDecCalculateM1andM2(self, ps,
-                                       frame); /* input: ottCLD, ottICC, ... */
-      /* output: M1param(Real/Imag), M2(Real/Imag) */
-      if (err != MPS_OK) {
-        bypassMode = 1;
-        if (self->errInt == MPS_OK) {
-          /* store internal error befor it gets overwritten */
-          self->errInt = err;
+      if (bypassMode == 0) {
+        err = SpatialDecCalculateM1andM2(
+            self, ps, frame); /* input: ottCLD, ottICC, ... */
+                              /* output: M1param(Real/Imag), M2(Real/Imag) */
+        if (err != MPS_OK) {
+          err = SpatialDecSetInternalError(self, &bypassMode, err);
         }
-        err = MPS_OK;
       }
 
       if ((ps == 0) && (self->bOverwriteM1M2prev != 0)) {
@@ -1168,13 +1192,16 @@
         self->bOverwriteM1M2prev = 0;
       }
 
-      SpatialDecSmoothM1andM2(
-          self, frame,
-          ps); /* input: M1param(Real/Imag)(Prev), M2(Real/Imag)(Prev) */
-               /* output: M1param(Real/Imag), M2(Real/Imag) */
+      if (bypassMode == 0) {
+        SpatialDecSmoothM1andM2(
+            self, frame,
+            ps); /* input: M1param(Real/Imag)(Prev), M2(Real/Imag)(Prev) */
+      }          /* output: M1param(Real/Imag), M2(Real/Imag) */
     }
 
-    alpha = FX_DBL2FX_SGL(fDivNorm(ts - prevSlot, currSlot - prevSlot));
+    if (bypassMode == 0) {
+      alpha = FX_DBL2FX_SGL(fDivNorm(ts - prevSlot, currSlot - prevSlot));
+    }
 
     switch (mode) {
       case INPUTMODE_QMF_SBR:
@@ -1182,15 +1209,17 @@
           self->bShareDelayWithSBR = 0; /* We got no hybrid delay */
         else
           self->bShareDelayWithSBR = 1;
-        SpatialDecFeedQMF(self, qmfInDataReal, qmfInDataImag, ts_io, bypassMode,
-                          self->qmfInputReal__FDK, self->qmfInputImag__FDK,
-                          self->numInputChannels);
+        SpatialDecFeedQMF(
+            self, qmfInDataReal, qmfInDataImag, ts_io, bypassMode,
+            self->qmfInputReal__FDK, self->qmfInputImag__FDK,
+            (bypassMode) ? numInputChannels : self->numInputChannels);
         break;
       case INPUTMODE_TIME:
         self->bShareDelayWithSBR = 0;
-        SpatialDecQMFAnalysis(self, inData, ts_io, bypassMode,
-                              self->qmfInputReal__FDK, self->qmfInputImag__FDK,
-                              self->numInputChannels);
+        SpatialDecQMFAnalysis(
+            self, inData, ts_io, bypassMode, self->qmfInputReal__FDK,
+            self->qmfInputImag__FDK,
+            (bypassMode) ? numInputChannels : self->numInputChannels);
         break;
       default:
         break;
@@ -1360,7 +1389,7 @@
       }   /* !self->tempShapeConfig == 1 */
     }     /*  !bypassMode */
 
-    if (self->phaseCoding == 1) {
+    if ((self->phaseCoding == 1) && (bypassMode == 0)) {
       /* only if bsPhaseCoding == 1 and bsResidualCoding == 0 */
 
       SpatialDecApplyPhase(
diff --git a/libSACdec/src/sac_dec_lib.cpp b/libSACdec/src/sac_dec_lib.cpp
index 856a923..d30131f 100644
--- a/libSACdec/src/sac_dec_lib.cpp
+++ b/libSACdec/src/sac_dec_lib.cpp
@@ -1,7 +1,7 @@
 /* -----------------------------------------------------------------------------
 Software License for The Fraunhofer FDK AAC Codec Library for Android
 
-© Copyright  1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright  1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
 Forschung e.V. All rights reserved.
 
  1.    INTRODUCTION
@@ -700,9 +700,10 @@
 SACDEC_ERROR mpegSurroundDecoder_Config(
     CMpegSurroundDecoder *pMpegSurroundDecoder, HANDLE_FDK_BITSTREAM hBs,
     AUDIO_OBJECT_TYPE coreCodec, INT samplingRate, INT frameSize,
-    INT stereoConfigIndex, INT coreSbrFrameLengthIndex, INT configBytes,
-    const UCHAR configMode, UCHAR *configChanged) {
+    INT numChannels, INT stereoConfigIndex, INT coreSbrFrameLengthIndex,
+    INT configBytes, const UCHAR configMode, UCHAR *configChanged) {
   SACDEC_ERROR err = MPS_OK;
+  INT nInputChannels;
   SPATIAL_SPECIFIC_CONFIG spatialSpecificConfig;
   SPATIAL_SPECIFIC_CONFIG *pSsc =
       &pMpegSurroundDecoder->spatialSpecificConfigBackup;
@@ -716,12 +717,18 @@
         err = SpatialDecParseMps212Config(
             hBs, &spatialSpecificConfig, samplingRate, coreCodec,
             stereoConfigIndex, coreSbrFrameLengthIndex);
+        nInputChannels = spatialSpecificConfig.nInputChannels;
         pSsc = &spatialSpecificConfig;
       } else {
         err = SpatialDecParseMps212Config(
             hBs, &pMpegSurroundDecoder->spatialSpecificConfigBackup,
             samplingRate, coreCodec, stereoConfigIndex,
             coreSbrFrameLengthIndex);
+        nInputChannels =
+            pMpegSurroundDecoder->spatialSpecificConfigBackup.nInputChannels;
+      }
+      if ((err == MPS_OK) && (numChannels != nInputChannels)) {
+        err = MPS_PARSE_ERROR;
       }
       break;
     case AOT_ER_AAC_ELD:
@@ -731,11 +738,19 @@
          * into temporarily allocated structure */
         err = SpatialDecParseSpecificConfig(hBs, &spatialSpecificConfig,
                                             configBytes, coreCodec);
+        nInputChannels = spatialSpecificConfig.nInputChannels;
         pSsc = &spatialSpecificConfig;
       } else {
         err = SpatialDecParseSpecificConfig(
             hBs, &pMpegSurroundDecoder->spatialSpecificConfigBackup,
             configBytes, coreCodec);
+        nInputChannels =
+            pMpegSurroundDecoder->spatialSpecificConfigBackup.nInputChannels;
+      }
+      /* check number of channels for channel_configuration > 0  */
+      if ((err == MPS_OK) && (numChannels > 0) &&
+          (numChannels != nInputChannels)) {
+        err = MPS_PARSE_ERROR;
       }
       break;
     default:
@@ -1804,7 +1819,7 @@
   info += i;
 
   info->module_id = FDK_MPSDEC;
-#ifdef __ANDROID__
+#ifdef SUPPRESS_BUILD_DATE_INFO
   info->build_date = "";
   info->build_time = "";
 #else
diff --git a/libSACdec/src/sac_stp.cpp b/libSACdec/src/sac_stp.cpp
index bb66277..b328c82 100644
--- a/libSACdec/src/sac_stp.cpp
+++ b/libSACdec/src/sac_stp.cpp
@@ -1,7 +1,7 @@
 /* -----------------------------------------------------------------------------
 Software License for The Fraunhofer FDK AAC Codec Library for Android
 
-© Copyright  1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright  1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
 Forschung e.V. All rights reserved.
 
  1.    INTRODUCTION
@@ -369,15 +369,15 @@
     hStpDec->update_old_ener = 1;
     for (ch = 0; ch < self->numInputChannels; ch++) {
       hStpDec->oldDryEnerLD64[ch] =
-          CalcLdData(hStpDec->runDryEner[ch] + ABS_THR__FDK);
+          CalcLdData(fAddSaturate(hStpDec->runDryEner[ch], ABS_THR__FDK));
     }
     for (ch = 0; ch < self->numOutputChannels; ch++) {
       if (self->treeConfig == TREE_212)
         hStpDec->oldWetEnerLD64[ch] =
-            CalcLdData(hStpDec->runWetEner[ch] + ABS_THR__FDK);
+            CalcLdData(fAddSaturate(hStpDec->runWetEner[ch], ABS_THR__FDK));
       else
         hStpDec->oldWetEnerLD64[ch] =
-            CalcLdData(hStpDec->runWetEner[ch] + ABS_THR2__FDK);
+            CalcLdData(fAddSaturate(hStpDec->runWetEner[ch], ABS_THR2__FDK));
     }
   } else {
     hStpDec->update_old_ener++;
diff --git a/libSACenc/src/sacenc_lib.cpp b/libSACenc/src/sacenc_lib.cpp
index d6a1658..fcfe39b 100644
--- a/libSACenc/src/sacenc_lib.cpp
+++ b/libSACenc/src/sacenc_lib.cpp
@@ -130,7 +130,7 @@
 #define SACENC_LIB_VL1 0
 #define SACENC_LIB_VL2 0
 #define SACENC_LIB_TITLE "MPEG Surround Encoder"
-#ifdef __ANDROID__
+#ifdef SUPPRESS_BUILD_DATE_INFO
 #define SACENC_LIB_BUILD_DATE ""
 #define SACENC_LIB_BUILD_TIME ""
 #else
diff --git a/libSBRdec/src/env_calc.cpp b/libSBRdec/src/env_calc.cpp
index 0b2f651..ad5edfe 100644
--- a/libSBRdec/src/env_calc.cpp
+++ b/libSBRdec/src/env_calc.cpp
@@ -1,7 +1,7 @@
 /* -----------------------------------------------------------------------------
 Software License for The Fraunhofer FDK AAC Codec Library for Android
 
-© Copyright  1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright  1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
 Forschung e.V. All rights reserved.
 
  1.    INTRODUCTION
@@ -1398,6 +1398,17 @@
     */
     noise_e = (start_pos < no_cols) ? adj_e : final_e;
 
+    if (start_pos >= no_cols) {
+      int diff = h_sbr_cal_env->filtBufferNoise_e - noise_e;
+      if (diff > 0) {
+        int s = getScalefactor(h_sbr_cal_env->filtBufferNoise, noSubbands);
+        if (diff > s) {
+          final_e += diff - s;
+          noise_e = final_e;
+        }
+      }
+    }
+
     /*
       Convert energies to amplitude levels
     */
@@ -2741,6 +2752,9 @@
             fMult(direct_ratio, noiseLevel[k]);
       }
 
+      smoothedNoise = fMax(fMin(smoothedNoise, (FIXP_DBL)(MAXVAL_DBL / 2)),
+                           (FIXP_DBL)(MINVAL_DBL / 2));
+
       /*
         The next 2 multiplications constitute the actual envelope adjustment
         of the signal and should be carried out with full accuracy
@@ -2930,6 +2944,9 @@
             fMult(direct_ratio, noiseLevel[k]);
       }
 
+      smoothedNoise = fMax(fMin(smoothedNoise, (FIXP_DBL)(MAXVAL_DBL / 2)),
+                           (FIXP_DBL)(MINVAL_DBL / 2));
+
       /*
         The next 2 multiplications constitute the actual envelope adjustment
         of the signal and should be carried out with full accuracy
diff --git a/libSBRdec/src/sbrdec_drc.cpp b/libSBRdec/src/sbrdec_drc.cpp
index 2d73f32..089d046 100644
--- a/libSBRdec/src/sbrdec_drc.cpp
+++ b/libSBRdec/src/sbrdec_drc.cpp
@@ -1,7 +1,7 @@
 /* -----------------------------------------------------------------------------
 Software License for The Fraunhofer FDK AAC Codec Library for Android
 
-© Copyright  1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright  1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
 Forschung e.V. All rights reserved.
 
  1.    INTRODUCTION
@@ -233,14 +233,19 @@
     if (hDrcData->winSequenceCurr != 2) { /* long window */
       int j = col + (numQmfSubSamples >> 1);
 
-      if (hDrcData->drcInterpolationSchemeCurr == 0) {
-        INT k = (frameLenFlag) ? 0x4444445 : 0x4000000;
+      if (j < winBorderToColMap[15]) {
+        if (hDrcData->drcInterpolationSchemeCurr == 0) {
+          INT k = (frameLenFlag) ? 0x4444445 : 0x4000000;
 
-        alphaValue = (FIXP_DBL)(j * k);
-      } else {
-        if (j >= (int)winBorderToColMap[hDrcData->drcInterpolationSchemeCurr]) {
-          alphaValue = (FIXP_DBL)MAXVAL_DBL;
+          alphaValue = (FIXP_DBL)(j * k);
+        } else {
+          if (j >=
+              (int)winBorderToColMap[hDrcData->drcInterpolationSchemeCurr]) {
+            alphaValue = (FIXP_DBL)MAXVAL_DBL;
+          }
         }
+      } else {
+        alphaValue = (FIXP_DBL)MAXVAL_DBL;
       }
     } else { /* short windows */
       shortDrc = 1;
@@ -254,14 +259,19 @@
     if (hDrcData->winSequenceNext != 2) { /* next: long window */
       int j = col - (numQmfSubSamples >> 1);
 
-      if (hDrcData->drcInterpolationSchemeNext == 0) {
-        INT k = (frameLenFlag) ? 0x4444445 : 0x4000000;
+      if (j < winBorderToColMap[15]) {
+        if (hDrcData->drcInterpolationSchemeNext == 0) {
+          INT k = (frameLenFlag) ? 0x4444445 : 0x4000000;
 
-        alphaValue = (FIXP_DBL)(j * k);
-      } else {
-        if (j >= (int)winBorderToColMap[hDrcData->drcInterpolationSchemeNext]) {
-          alphaValue = (FIXP_DBL)MAXVAL_DBL;
+          alphaValue = (FIXP_DBL)(j * k);
+        } else {
+          if (j >=
+              (int)winBorderToColMap[hDrcData->drcInterpolationSchemeNext]) {
+            alphaValue = (FIXP_DBL)MAXVAL_DBL;
+          }
         }
+      } else {
+        alphaValue = (FIXP_DBL)MAXVAL_DBL;
       }
 
       fact_mag = hDrcData->nextFact_mag;
@@ -289,14 +299,19 @@
     if (hDrcData->winSequenceNext != 2) { /* long window */
       int j = col - (numQmfSubSamples >> 1);
 
-      if (hDrcData->drcInterpolationSchemeNext == 0) {
-        INT k = (frameLenFlag) ? 0x4444445 : 0x4000000;
+      if (j < winBorderToColMap[15]) {
+        if (hDrcData->drcInterpolationSchemeNext == 0) {
+          INT k = (frameLenFlag) ? 0x4444445 : 0x4000000;
 
-        alphaValue = (FIXP_DBL)(j * k);
-      } else {
-        if (j >= (int)winBorderToColMap[hDrcData->drcInterpolationSchemeNext]) {
-          alphaValue = (FIXP_DBL)MAXVAL_DBL;
+          alphaValue = (FIXP_DBL)(j * k);
+        } else {
+          if (j >=
+              (int)winBorderToColMap[hDrcData->drcInterpolationSchemeNext]) {
+            alphaValue = (FIXP_DBL)MAXVAL_DBL;
+          }
         }
+      } else {
+        alphaValue = (FIXP_DBL)MAXVAL_DBL;
       }
     } else { /* short windows */
       shortDrc = 1;
diff --git a/libSBRdec/src/sbrdecoder.cpp b/libSBRdec/src/sbrdecoder.cpp
index 55f929f..b101a4a 100644
--- a/libSBRdec/src/sbrdecoder.cpp
+++ b/libSBRdec/src/sbrdecoder.cpp
@@ -158,7 +158,7 @@
 #define SBRDECODER_LIB_VL1 1
 #define SBRDECODER_LIB_VL2 0
 #define SBRDECODER_LIB_TITLE "SBR Decoder"
-#ifdef __ANDROID__
+#ifdef SUPPRESS_BUILD_DATE_INFO
 #define SBRDECODER_LIB_BUILD_DATE ""
 #define SBRDECODER_LIB_BUILD_TIME ""
 #else
diff --git a/libSBRenc/src/env_est.cpp b/libSBRenc/src/env_est.cpp
index 0eb8425..cc8780a 100644
--- a/libSBRenc/src/env_est.cpp
+++ b/libSBRenc/src/env_est.cpp
@@ -1,7 +1,7 @@
 /* -----------------------------------------------------------------------------
 Software License for The Fraunhofer FDK AAC Codec Library for Android
 
-© Copyright  1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright  1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
 Forschung e.V. All rights reserved.
 
  1.    INTRODUCTION
@@ -1267,6 +1267,7 @@
     sbrExtrEnv->pre_transient_info[1] = ed->transient_info[1]; /* tran_flag */
     hEnvChan->encEnvData.noOfEnvelopes = ed->nEnvelopes =
         ed->frame_info->nEnvelopes; /* number of envelopes of current frame */
+    hEnvChan->encEnvData.currentAmpResFF = (AMP_RES)h_con->initAmpResFF;
 
     /*
       Check if the current frame is divided into one envelope only. If so, set
@@ -1274,8 +1275,9 @@
     */
     if ((hEnvChan->encEnvData.hSbrBSGrid->frameClass == FIXFIX) &&
         (ed->nEnvelopes == 1)) {
+      AMP_RES currentAmpResFF = SBR_AMP_RES_1_5;
       if (h_con->sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY) {
-        /* Note: global_tonaliy_float_value ==
+        /* Note: global_tonality_float_value ==
            ((float)hEnvChan->encEnvData.global_tonality/((INT64)(1)<<(31-(19+2)))/0.524288*(2.0/3.0)));
                  threshold_float_value ==
            ((float)h_con->thresholdAmpResFF_m/((INT64)(1)<<(31-(h_con->thresholdAmpResFF_e)))/0.524288*(2.0/3.0)));
@@ -1289,14 +1291,13 @@
         } else {
           hEnvChan->encEnvData.currentAmpResFF = SBR_AMP_RES_3_0;
         }
-      } else
-        hEnvChan->encEnvData.currentAmpResFF = SBR_AMP_RES_1_5;
+        currentAmpResFF = hEnvChan->encEnvData.currentAmpResFF;
+      }
 
-      if (hEnvChan->encEnvData.currentAmpResFF !=
-          hEnvChan->encEnvData.init_sbr_amp_res) {
+      if (currentAmpResFF != hEnvChan->encEnvData.init_sbr_amp_res) {
         FDKsbrEnc_InitSbrHuffmanTables(
             &hEnvChan->encEnvData, &hEnvChan->sbrCodeEnvelope,
-            &hEnvChan->sbrCodeNoiseFloor, hEnvChan->encEnvData.currentAmpResFF);
+            &hEnvChan->sbrCodeNoiseFloor, currentAmpResFF);
       }
     } else {
       if (sbrHeaderData->sbr_amp_res != hEnvChan->encEnvData.init_sbr_amp_res) {
@@ -1355,6 +1356,13 @@
     }
   }
 
+  if (h_con->sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY &&
+      stereoMode == SBR_SWITCH_LRC &&
+      h_envChan[0]->encEnvData.currentAmpResFF !=
+          h_envChan[1]->encEnvData.currentAmpResFF) {
+    stereoMode = SBR_LEFT_RIGHT;
+  }
+
   /*
     Extract envelope of current frame.
   */
diff --git a/libSBRenc/src/sbr_encoder.cpp b/libSBRenc/src/sbr_encoder.cpp
index df9e996..c3da072 100644
--- a/libSBRenc/src/sbr_encoder.cpp
+++ b/libSBRenc/src/sbr_encoder.cpp
@@ -1,7 +1,7 @@
 /* -----------------------------------------------------------------------------
 Software License for The Fraunhofer FDK AAC Codec Library for Android
 
-© Copyright  1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright  1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
 Forschung e.V. All rights reserved.
 
  1.    INTRODUCTION
@@ -1450,8 +1450,6 @@
                                     params->deltaTAcrossFrames, 0, 0))
     return (1);
 
-  sbrConfigData->initAmpResFF = params->init_amp_res_FF;
-
   if (FDKsbrEnc_InitSbrHuffmanTables(&hEnv->encEnvData, &hEnv->sbrCodeEnvelope,
                                      &hEnv->sbrCodeNoiseFloor,
                                      sbrHeaderData->sbr_amp_res))
@@ -1749,6 +1747,7 @@
     hSbrElement->sbrHeaderData.sbr_data_extra = 1;
 
   hSbrElement->sbrHeaderData.sbr_amp_res = (AMP_RES)params->amp_res;
+  hSbrElement->sbrConfigData.initAmpResFF = params->init_amp_res_FF;
 
   /* header_extra_1 */
   hSbrElement->sbrHeaderData.freqScale = params->freqScale;
@@ -2560,7 +2559,7 @@
   info->version =
       LIB_VERSION(SBRENCODER_LIB_VL0, SBRENCODER_LIB_VL1, SBRENCODER_LIB_VL2);
   LIB_VERSION_STRING(info);
-#ifdef __ANDROID__
+#ifdef SUPPRESS_BUILD_DATE_INFO
   info->build_date = "";
   info->build_time = "";
 #else