From 3ce7751a440cafe41ff2eefb105b03096fbe122c Mon Sep 17 00:00:00 2001
From: Fraunhofer IIS FDK <audio-fdk@iis.fraunhofer.de>
Date: Thu, 20 Dec 2018 15:52:47 +0100
Subject: Perform sanity check on DRC sets and improve the selection process

Bug: 137282770
Bug: 141883493
Test: atest DecoderTestXheAac ; atest DecoderTestAacDrc
Change-Id: Ie8e17c82653cb0d9adcdb10ec3f4875b6207ac6f
---
 libDRCdec/src/FDK_drcDecLib.cpp | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

(limited to 'libDRCdec/src/FDK_drcDecLib.cpp')

diff --git a/libDRCdec/src/FDK_drcDecLib.cpp b/libDRCdec/src/FDK_drcDecLib.cpp
index 4f8ebc7..e43279f 100644
--- a/libDRCdec/src/FDK_drcDecLib.cpp
+++ b/libDRCdec/src/FDK_drcDecLib.cpp
@@ -145,6 +145,10 @@ struct s_drc_decoder {
   SEL_PROC_OUTPUT selProcOutput;
 } DRC_DECODER;
 
+static int _getGainStatus(HANDLE_UNI_DRC_GAIN hUniDrcGain) {
+  return hUniDrcGain->status;
+}
+
 static int isResetNeeded(HANDLE_DRC_DECODER hDrcDec,
                          const SEL_PROC_OUTPUT oldSelProcOutput) {
   int i, resetNeeded = 0;
@@ -729,7 +733,9 @@ FDK_drcDec_ReadUniDrcGain(HANDLE_DRC_DECODER hDrcDec,
       &(hDrcDec->uniDrcGain));
   if (dErr) return DRC_DEC_NOT_OK;
 
-  hDrcDec->status = DRC_DEC_NEW_GAIN_PAYLOAD;
+  if (_getGainStatus(&(hDrcDec->uniDrcGain))) {
+    hDrcDec->status = DRC_DEC_NEW_GAIN_PAYLOAD;
+  }
 
   return DRC_DEC_OK;
 }
@@ -751,7 +757,9 @@ FDK_drcDec_ReadUniDrc(HANDLE_DRC_DECODER hDrcDec,
   startSelectionProcess(hDrcDec);
   if (dErr) return DRC_DEC_NOT_OK;
 
-  hDrcDec->status = DRC_DEC_NEW_GAIN_PAYLOAD;
+  if (_getGainStatus(&(hDrcDec->uniDrcGain))) {
+    hDrcDec->status = DRC_DEC_NEW_GAIN_PAYLOAD;
+  }
 
   return DRC_DEC_OK;
 }
-- 
cgit v1.2.3


From 31f66f6d3ffcfa429c170b2c35250982d11f5082 Mon Sep 17 00:00:00 2001
From: Fraunhofer IIS FDK <audio-fdk@iis.fraunhofer.de>
Date: Thu, 19 Dec 2019 17:21:07 +0100
Subject: Extend decoder API with audio output loudness info (FDKdec v3.1.3).

Bug: 148385721
Test: atest DecoderTestXheAac DecoderTestAacDrc
Change-Id: I68b09883def21baef259c9ab914922567ab8cee3
---
 documentation/aacDecoder.pdf              | Bin 488412 -> 494126 bytes
 libAACdec/include/aacdecoder_lib.h        |  28 ++++++++++++++++--------
 libAACdec/src/aacdecoder.cpp              |   2 ++
 libAACdec/src/aacdecoder_lib.cpp          |  34 +++++++++++++++++++++++++++++-
 libDRCdec/include/FDK_drcDecLib.h         |  11 +++++++---
 libDRCdec/src/FDK_drcDecLib.cpp           |   2 ++
 libDRCdec/src/drcDec_selectionProcess.cpp |  11 +++++-----
 libDRCdec/src/drcDec_selectionProcess.h   |   2 ++
 8 files changed, 71 insertions(+), 19 deletions(-)

(limited to 'libDRCdec/src/FDK_drcDecLib.cpp')

diff --git a/documentation/aacDecoder.pdf b/documentation/aacDecoder.pdf
index eb2a75e..f2131ed 100644
Binary files a/documentation/aacDecoder.pdf and b/documentation/aacDecoder.pdf differ
diff --git a/libAACdec/include/aacdecoder_lib.h b/libAACdec/include/aacdecoder_lib.h
index 6c2fda4..6084bd3 100644
--- a/libAACdec/include/aacdecoder_lib.h
+++ b/libAACdec/include/aacdecoder_lib.h
@@ -892,15 +892,25 @@ typedef struct {
                           1770. If no level has been found in the bitstream the
                           value is -1. */
   SCHAR
-  drcPresMode; /*!< DRC presentation mode. According to ETSI TS 101 154,
-                  this field indicates whether   light (MPEG-4 Dynamic Range
-                  Control tool) or heavy compression (DVB heavy
-                  compression)   dynamic range control shall take priority
-                  on the outputs.   For details, see ETSI TS 101 154, table
-                  C.33. Possible values are: \n   -1: No corresponding
-                  metadata found in the bitstream \n   0: DRC presentation
-                  mode not indicated \n   1: DRC presentation mode 1 \n   2:
-                  DRC presentation mode 2 \n   3: Reserved */
+  drcPresMode;        /*!< DRC presentation mode. According to ETSI TS 101 154,
+                         this field indicates whether   light (MPEG-4 Dynamic Range
+                         Control tool) or heavy compression (DVB heavy
+                         compression)   dynamic range control shall take priority
+                         on the outputs.   For details, see ETSI TS 101 154, table
+                         C.33. Possible values are: \n   -1: No corresponding
+                         metadata found in the bitstream \n   0: DRC presentation
+                         mode not indicated \n   1: DRC presentation mode 1 \n   2:
+                         DRC presentation mode 2 \n   3: Reserved */
+  INT outputLoudness; /*!< Audio output loudness in steps of -0.25 dB. Range: 0
+                         (0 dBFS) to 231 (-57.75 dBFS).\n  A value of -1
+                         indicates that no loudness metadata is present.\n  If
+                         loudness normalization is active, the value corresponds
+                         to the target loudness value set with
+                         ::AAC_DRC_REFERENCE_LEVEL.\n  If loudness normalization
+                         is not active, the output loudness value corresponds to
+                         the loudness metadata given in the bitstream.\n
+                           Loudness metadata can originate from MPEG-4 DRC or
+                         MPEG-D DRC. */
 
 } CStreamInfo;
 
diff --git a/libAACdec/src/aacdecoder.cpp b/libAACdec/src/aacdecoder.cpp
index bd12d96..f747b2d 100644
--- a/libAACdec/src/aacdecoder.cpp
+++ b/libAACdec/src/aacdecoder.cpp
@@ -1225,6 +1225,8 @@ static void CStreamInfoInit(CStreamInfo *pStreamInfo) {
   pStreamInfo->drcProgRefLev =
       -1; /* set program reference level to not indicated */
   pStreamInfo->drcPresMode = -1; /* default: presentation mode not indicated */
+
+  pStreamInfo->outputLoudness = -1; /* default: no loudness metadata present */
 }
 
 /*!
diff --git a/libAACdec/src/aacdecoder_lib.cpp b/libAACdec/src/aacdecoder_lib.cpp
index e90dbef..2ba0e86 100644
--- a/libAACdec/src/aacdecoder_lib.cpp
+++ b/libAACdec/src/aacdecoder_lib.cpp
@@ -120,7 +120,7 @@ amm-info@iis.fraunhofer.de
 /* Decoder library info */
 #define AACDECODER_LIB_VL0 3
 #define AACDECODER_LIB_VL1 1
-#define AACDECODER_LIB_VL2 2
+#define AACDECODER_LIB_VL2 3
 #define AACDECODER_LIB_TITLE "AAC Decoder Lib"
 #ifdef __ANDROID__
 #define AACDECODER_LIB_BUILD_DATE ""
@@ -1764,6 +1764,38 @@ aacDecoder_DecodeFrame(HANDLE_AACDECODER self, INT_PCM *pTimeData_extern,
           }
         }
       }
+      if (FDK_drcDec_GetParam(self->hUniDrcDecoder, DRC_DEC_IS_ACTIVE)) {
+        /* return output loudness information for MPEG-D DRC */
+        LONG outputLoudness =
+            FDK_drcDec_GetParam(self->hUniDrcDecoder, DRC_DEC_OUTPUT_LOUDNESS);
+        if (outputLoudness == DRC_DEC_LOUDNESS_NOT_PRESENT) {
+          /* no valid MPEG-D DRC loudness value contained */
+          self->streamInfo.outputLoudness = -1;
+        } else {
+          if (outputLoudness > 0) {
+            /* positive output loudness values (very unusual) are limited to 0
+             * dB */
+            self->streamInfo.outputLoudness = 0;
+          } else {
+            self->streamInfo.outputLoudness =
+                -(INT)outputLoudness >>
+                22; /* negate and scale from e = 7 to e = (31-2) */
+          }
+        }
+      } else {
+        /* return output loudness information for MPEG-4 DRC */
+        if (self->streamInfo.drcProgRefLev <
+            0) { /* no MPEG-4 DRC loudness metadata contained */
+          self->streamInfo.outputLoudness = -1;
+        } else {
+          if (self->defaultTargetLoudness <
+              0) { /* loudness normalization is off */
+            self->streamInfo.outputLoudness = self->streamInfo.drcProgRefLev;
+          } else {
+            self->streamInfo.outputLoudness = self->defaultTargetLoudness;
+          }
+        }
+      }
 
       if (self->streamInfo.extAot != AOT_AAC_SLS) {
         INT pcmLimiterScale = 0;
diff --git a/libDRCdec/include/FDK_drcDecLib.h b/libDRCdec/include/FDK_drcDecLib.h
index 2d28d23..79f8566 100644
--- a/libDRCdec/include/FDK_drcDecLib.h
+++ b/libDRCdec/include/FDK_drcDecLib.h
@@ -114,6 +114,8 @@ amm-info@iis.fraunhofer.de
 extern "C" {
 #endif
 
+#define DRC_DEC_LOUDNESS_NOT_PRESENT (LONG)0x7FFFFFFE
+
 typedef struct s_drc_decoder* HANDLE_DRC_DECODER;
 typedef struct s_uni_drc_interface* HANDLE_UNI_DRC_INTERFACE;
 typedef struct s_selection_process_output* HANDLE_SEL_PROC_OUTPUT;
@@ -150,9 +152,12 @@ typedef enum {
   DRC_DEC_IS_ACTIVE, /**< MPEG-D DRC payload is present and at least one of
                         Dynamic Range Control (DRC) or Loudness Normalization
                         (LN) is activated */
-  DRC_DEC_TARGET_CHANNEL_COUNT_SELECTED /**< number of output channels if
-                                           appropriate downmixInstruction exists
-                                         */
+  DRC_DEC_TARGET_CHANNEL_COUNT_SELECTED, /**< number of output channels if
+                                            appropriate downmixInstruction
+                                            exists */
+  DRC_DEC_OUTPUT_LOUDNESS /**< output loudness in dB, with exponent e = 7, or
+                             DRC_DEC_LOUDNESS_NOT_PRESENT if no loudness is
+                             contained in the bitstream */
 } DRC_DEC_USERPARAM;
 
 typedef enum {
diff --git a/libDRCdec/src/FDK_drcDecLib.cpp b/libDRCdec/src/FDK_drcDecLib.cpp
index e43279f..83b5773 100644
--- a/libDRCdec/src/FDK_drcDecLib.cpp
+++ b/libDRCdec/src/FDK_drcDecLib.cpp
@@ -519,6 +519,8 @@ LONG FDK_drcDec_GetParam(HANDLE_DRC_DECODER hDrcDec,
     }
     case DRC_DEC_TARGET_CHANNEL_COUNT_SELECTED:
       return (LONG)hDrcDec->selProcOutput.targetChannelCount;
+    case DRC_DEC_OUTPUT_LOUDNESS:
+      return (LONG)hDrcDec->selProcOutput.outputLoudness;
     default:
       return 0;
   }
diff --git a/libDRCdec/src/drcDec_selectionProcess.cpp b/libDRCdec/src/drcDec_selectionProcess.cpp
index fe6034c..46ed740 100644
--- a/libDRCdec/src/drcDec_selectionProcess.cpp
+++ b/libDRCdec/src/drcDec_selectionProcess.cpp
@@ -103,8 +103,6 @@ amm-info@iis.fraunhofer.de
 #include "drcDec_selectionProcess.h"
 #include "drcDec_tools.h"
 
-#define UNDEFINED_LOUDNESS_VALUE (FIXP_DBL) MAXVAL_DBL
-
 typedef enum {
   DETR_NONE = 0,
   DETR_NIGHT = 1,
@@ -1136,9 +1134,8 @@ static DRCDEC_SELECTION_PROCESS_RETURN _preSelectionRequirement8(
 
   FIXP_DBL loudnessDeviationMax =
       ((FIXP_DBL)hSelProcInput->loudnessDeviationMax) << (DFRACT_BITS - 1 - 7);
-  ;
 
-  if (hSelProcInput->loudnessNormalizationOn) {
+  {
     retVal = _getLoudness(hLoudnessInfoSet, hSelProcInput->albumMode,
                           hSelProcInput->loudnessMeasurementMethod,
                           hSelProcInput->loudnessMeasurementSystem,
@@ -1147,9 +1144,10 @@ static DRCDEC_SELECTION_PROCESS_RETURN _preSelectionRequirement8(
                           hSelProcInput->downmixIdRequested[downmixIdIndex],
                           &loudnessNormalizationGainDb, &loudness);
     if (retVal) return (retVal);
-  } else {
+  }
+
+  if (!hSelProcInput->loudnessNormalizationOn) {
     loudnessNormalizationGainDb = (FIXP_DBL)0;
-    loudness = UNDEFINED_LOUDNESS_VALUE;
   }
 
   retVal = _getSignalPeakLevel(
@@ -2070,6 +2068,7 @@ static DRCDEC_SELECTION_PROCESS_RETURN _generateOutputInfo(
       pSelectionData->loudnessNormalizationGainDbAdjusted +
       hSelProcInput->loudnessNormalizationGainModificationDb;
   hSelProcOutput->outputPeakLevelDb = pSelectionData->outputPeakLevel;
+  hSelProcOutput->outputLoudness = pSelectionData->outputLoudness;
 
   hSelProcOutput->boost = boost;
   hSelProcOutput->compress = compress;
diff --git a/libDRCdec/src/drcDec_selectionProcess.h b/libDRCdec/src/drcDec_selectionProcess.h
index 420bae6..0f878cf 100644
--- a/libDRCdec/src/drcDec_selectionProcess.h
+++ b/libDRCdec/src/drcDec_selectionProcess.h
@@ -111,6 +111,8 @@ amm-info@iis.fraunhofer.de
 
 typedef struct s_drcdec_selection_process* HANDLE_DRC_SELECTION_PROCESS;
 
+#define UNDEFINED_LOUDNESS_VALUE (FIXP_DBL)(MAXVAL_DBL - 1)
+
 typedef enum {
   DRCDEC_SELECTION_PROCESS_NO_ERROR = 0,
 
-- 
cgit v1.2.3