C2SoftAacDec: Add support for DRC

Bug: 110423231
Test: cts -m CtsMediaTestCases -t android.media.cts.DecoderTestAacDrc
Test: cts -m CtsMediaTestCases -t android.media.cts.DecoderTestXheAac

Change-Id: I6b6f856a34fdcf39cb61885f6853603226694748
diff --git a/media/codecs/aac/C2SoftAacDec.cpp b/media/codecs/aac/C2SoftAacDec.cpp
index 4848bd0..c7b1191 100644
--- a/media/codecs/aac/C2SoftAacDec.cpp
+++ b/media/codecs/aac/C2SoftAacDec.cpp
@@ -35,11 +35,12 @@
 
 #define FILEREAD_MAX_LAYERS 2
 
-#define DRC_DEFAULT_MOBILE_REF_LEVEL 64  /* 64*-0.25dB = -16 dB below full scale for mobile conf */
-#define DRC_DEFAULT_MOBILE_DRC_CUT   127 /* maximum compression of dynamic range for mobile conf */
-#define DRC_DEFAULT_MOBILE_DRC_BOOST 127 /* maximum compression of dynamic range for mobile conf */
-#define DRC_DEFAULT_MOBILE_DRC_HEAVY 1   /* switch for heavy compression for mobile conf */
-#define DRC_DEFAULT_MOBILE_ENC_LEVEL (-1) /* encoder target level; -1 => the value is unknown, otherwise dB step value (e.g. 64 for -16 dB) */
+#define DRC_DEFAULT_MOBILE_REF_LEVEL -16.0  /* 64*-0.25dB = -16 dB below full scale for mobile conf */
+#define DRC_DEFAULT_MOBILE_DRC_CUT   1.0 /* maximum compression of dynamic range for mobile conf */
+#define DRC_DEFAULT_MOBILE_DRC_BOOST 1.0 /* maximum compression of dynamic range for mobile conf */
+#define DRC_DEFAULT_MOBILE_DRC_HEAVY C2Config::DRC_COMPRESSION_HEAVY   /* switch for heavy compression for mobile conf */
+#define DRC_DEFAULT_MOBILE_DRC_EFFECT 3  /* MPEG-D DRC effect type; 3 => Limited playback range */
+#define DRC_DEFAULT_MOBILE_ENC_LEVEL (0.25) /* encoder target level; -1 => the value is unknown, otherwise dB step value (e.g. 64 for -16 dB) */
 #define MAX_CHANNEL_COUNT            8  /* maximum number of audio channels that can be decoded */
 // names of properties that can be used to override the default DRC settings
 #define PROP_DRC_OVERRIDE_REF_LEVEL  "aac_drc_reference_level"
@@ -47,6 +48,7 @@
 #define PROP_DRC_OVERRIDE_BOOST      "aac_drc_boost"
 #define PROP_DRC_OVERRIDE_HEAVY      "aac_drc_heavy"
 #define PROP_DRC_OVERRIDE_ENC_LEVEL "aac_drc_enc_target_level"
+#define PROP_DRC_OVERRIDE_EFFECT     "ro.aac_drc_effect_type"
 
 namespace android {
 
@@ -135,6 +137,65 @@
                 })
                 .withSetter(ProfileLevelSetter)
                 .build());
+
+        addParameter(
+                DefineParam(mDrcCompressMode, C2_PARAMKEY_DRC_COMPRESSION_MODE)
+                .withDefault(new C2StreamDrcCompressionModeTuning::input(0u, C2Config::DRC_COMPRESSION_HEAVY))
+                .withFields({
+                    C2F(mDrcCompressMode, value).oneOf({
+                            C2Config::DRC_COMPRESSION_ODM_DEFAULT,
+                            C2Config::DRC_COMPRESSION_NONE,
+                            C2Config::DRC_COMPRESSION_LIGHT,
+                            C2Config::DRC_COMPRESSION_HEAVY})
+                })
+                .withSetter(Setter<decltype(*mDrcCompressMode)>::StrictValueWithNoDeps)
+                .build());
+
+        addParameter(
+                DefineParam(mDrcTargetRefLevel, C2_PARAMKEY_DRC_TARGET_REFERENCE_LEVEL)
+                .withDefault(new C2StreamDrcTargetReferenceLevelTuning::input(0u, DRC_DEFAULT_MOBILE_REF_LEVEL))
+                .withFields({C2F(mDrcTargetRefLevel, value).inRange(-31.75, 0.25)})
+                .withSetter(Setter<decltype(*mDrcTargetRefLevel)>::StrictValueWithNoDeps)
+                .build());
+
+        addParameter(
+                DefineParam(mDrcEncTargetLevel, C2_PARAMKEY_DRC_ENCODED_TARGET_LEVEL)
+                .withDefault(new C2StreamDrcEncodedTargetLevelTuning::input(0u, DRC_DEFAULT_MOBILE_ENC_LEVEL))
+                .withFields({C2F(mDrcEncTargetLevel, value).inRange(-31.75, 0.25)})
+                .withSetter(Setter<decltype(*mDrcEncTargetLevel)>::StrictValueWithNoDeps)
+                .build());
+
+        addParameter(
+                DefineParam(mDrcBoostFactor, C2_PARAMKEY_DRC_BOOST_FACTOR)
+                .withDefault(new C2StreamDrcBoostFactorTuning::input(0u, DRC_DEFAULT_MOBILE_DRC_BOOST))
+                .withFields({C2F(mDrcBoostFactor, value).inRange(0, 1.)})
+                .withSetter(Setter<decltype(*mDrcBoostFactor)>::StrictValueWithNoDeps)
+                .build());
+
+        addParameter(
+                DefineParam(mDrcAttenuationFactor, C2_PARAMKEY_DRC_ATTENUATION_FACTOR)
+                .withDefault(new C2StreamDrcAttenuationFactorTuning::input(0u, DRC_DEFAULT_MOBILE_DRC_CUT))
+                .withFields({C2F(mDrcAttenuationFactor, value).inRange(0, 1.)})
+                .withSetter(Setter<decltype(*mDrcAttenuationFactor)>::StrictValueWithNoDeps)
+                .build());
+
+        addParameter(
+                DefineParam(mDrcEffectType, C2_PARAMKEY_DRC_EFFECT_TYPE)
+                .withDefault(new C2StreamDrcEffectTypeTuning::input(0u, C2Config::DRC_EFFECT_LIMITED_PLAYBACK_RANGE))
+                .withFields({
+                    C2F(mDrcEffectType, value).oneOf({
+                            C2Config::DRC_EFFECT_ODM_DEFAULT,
+                            C2Config::DRC_EFFECT_OFF,
+                            C2Config::DRC_EFFECT_NONE,
+                            C2Config::DRC_EFFECT_LATE_NIGHT,
+                            C2Config::DRC_EFFECT_NOISY_ENVIRONMENT,
+                            C2Config::DRC_EFFECT_LIMITED_PLAYBACK_RANGE,
+                            C2Config::DRC_EFFECT_LOW_PLAYBACK_LEVEL,
+                            C2Config::DRC_EFFECT_DIALOG_ENHANCEMENT,
+                            C2Config::DRC_EFFECT_GENERAL_COMPRESSION})
+                })
+                .withSetter(Setter<decltype(*mDrcEffectType)>::StrictValueWithNoDeps)
+                .build());
     }
 
     bool isAdts() const { return mAacFormat->value == C2AacStreamFormatAdts; }
@@ -143,8 +204,14 @@
         (void)me;  // TODO: validate
         return C2R::Ok();
     }
-private:
+    int32_t getDrcCompressMode() const { return mDrcCompressMode->value == C2Config::DRC_COMPRESSION_HEAVY ? 1 : 0; }
+    int32_t getDrcTargetRefLevel() const { return (mDrcTargetRefLevel->value <= 0 ? -mDrcTargetRefLevel->value * 4. + 0.5 : -1); }
+    int32_t getDrcEncTargetLevel() const { return (mDrcEncTargetLevel->value <= 0 ? -mDrcEncTargetLevel->value * 4. + 0.5 : -1); }
+    int32_t getDrcBoostFactor() const { return mDrcBoostFactor->value * 127. + 0.5; }
+    int32_t getDrcAttenuationFactor() const { return mDrcAttenuationFactor->value * 127. + 0.5; }
+    int32_t getDrcEffectType() const { return mDrcEffectType->value; }
 
+private:
     std::shared_ptr<C2StreamFormatConfig::input> mInputFormat;
     std::shared_ptr<C2StreamFormatConfig::output> mOutputFormat;
     std::shared_ptr<C2PortMimeConfig::input> mInputMediaType;
@@ -155,6 +222,13 @@
     std::shared_ptr<C2StreamMaxBufferSizeInfo::input> mInputMaxBufSize;
     std::shared_ptr<C2StreamAacFormatInfo::input> mAacFormat;
     std::shared_ptr<C2StreamProfileLevelInfo::input> mProfileLevel;
+    std::shared_ptr<C2StreamDrcCompressionModeTuning::input> mDrcCompressMode;
+    std::shared_ptr<C2StreamDrcTargetReferenceLevelTuning::input> mDrcTargetRefLevel;
+    std::shared_ptr<C2StreamDrcEncodedTargetLevelTuning::input> mDrcEncTargetLevel;
+    std::shared_ptr<C2StreamDrcBoostFactorTuning::input> mDrcBoostFactor;
+    std::shared_ptr<C2StreamDrcAttenuationFactorTuning::input> mDrcAttenuationFactor;
+    std::shared_ptr<C2StreamDrcEffectTypeTuning::input> mDrcEffectType;
+    // TODO Add : C2StreamAacSbrModeTuning
 };
 
 constexpr char COMPONENT_NAME[] = "c2.android.aac.decoder";
@@ -243,52 +317,37 @@
 
     // for streams that contain metadata, use the mobile profile DRC settings unless overridden by platform properties
     // TODO: change the DRC settings depending on audio output device type (HDMI, loadspeaker, headphone)
-    char value[PROPERTY_VALUE_MAX];
+
     //  DRC_PRES_MODE_WRAP_DESIRED_TARGET
-    if (property_get(PROP_DRC_OVERRIDE_REF_LEVEL, value, NULL)) {
-        unsigned refLevel = atoi(value);
-        ALOGV("AAC decoder using desired DRC target reference level of %d instead of %d", refLevel,
-                DRC_DEFAULT_MOBILE_REF_LEVEL);
-        mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_TARGET, refLevel);
-    } else {
-        mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_TARGET, DRC_DEFAULT_MOBILE_REF_LEVEL);
-    }
+    int32_t targetRefLevel = mIntf->getDrcTargetRefLevel();
+    ALOGV("AAC decoder using desired DRC target reference level of %d", targetRefLevel);
+    mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_TARGET, (unsigned)targetRefLevel);
+
     //  DRC_PRES_MODE_WRAP_DESIRED_ATT_FACTOR
-    if (property_get(PROP_DRC_OVERRIDE_CUT, value, NULL)) {
-        unsigned cut = atoi(value);
-        ALOGV("AAC decoder using desired DRC attenuation factor of %d instead of %d", cut,
-                DRC_DEFAULT_MOBILE_DRC_CUT);
-        mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_ATT_FACTOR, cut);
-    } else {
-        mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_ATT_FACTOR, DRC_DEFAULT_MOBILE_DRC_CUT);
-    }
+
+    int32_t attenuationFactor = mIntf->getDrcAttenuationFactor();
+    ALOGV("AAC decoder using desired DRC attenuation factor of %d", attenuationFactor);
+    mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_ATT_FACTOR, (unsigned)attenuationFactor);
+
     //  DRC_PRES_MODE_WRAP_DESIRED_BOOST_FACTOR
-    if (property_get(PROP_DRC_OVERRIDE_BOOST, value, NULL)) {
-        unsigned boost = atoi(value);
-        ALOGV("AAC decoder using desired DRC boost factor of %d instead of %d", boost,
-                DRC_DEFAULT_MOBILE_DRC_BOOST);
-        mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_BOOST_FACTOR, boost);
-    } else {
-        mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_BOOST_FACTOR, DRC_DEFAULT_MOBILE_DRC_BOOST);
-    }
+    int32_t boostFactor = mIntf->getDrcBoostFactor();
+    ALOGV("AAC decoder using desired DRC boost factor of %d", boostFactor);
+    mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_BOOST_FACTOR, (unsigned)boostFactor);
+
     //  DRC_PRES_MODE_WRAP_DESIRED_HEAVY
-    if (property_get(PROP_DRC_OVERRIDE_HEAVY, value, NULL)) {
-        unsigned heavy = atoi(value);
-        ALOGV("AAC decoder using desried DRC heavy compression switch of %d instead of %d", heavy,
-                DRC_DEFAULT_MOBILE_DRC_HEAVY);
-        mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_HEAVY, heavy);
-    } else {
-        mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_HEAVY, DRC_DEFAULT_MOBILE_DRC_HEAVY);
-    }
+    int32_t compressMode = mIntf->getDrcCompressMode();
+    ALOGV("AAC decoder using desried DRC heavy compression switch of %d", compressMode);
+    mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_HEAVY, (unsigned)compressMode);
+
     // DRC_PRES_MODE_WRAP_ENCODER_TARGET
-    if (property_get(PROP_DRC_OVERRIDE_ENC_LEVEL, value, NULL)) {
-        unsigned encoderRefLevel = atoi(value);
-        ALOGV("AAC decoder using encoder-side DRC reference level of %d instead of %d",
-                encoderRefLevel, DRC_DEFAULT_MOBILE_ENC_LEVEL);
-        mDrcWrap.setParam(DRC_PRES_MODE_WRAP_ENCODER_TARGET, encoderRefLevel);
-    } else {
-        mDrcWrap.setParam(DRC_PRES_MODE_WRAP_ENCODER_TARGET, DRC_DEFAULT_MOBILE_ENC_LEVEL);
-    }
+    int32_t encTargetLevel = mIntf->getDrcEncTargetLevel();
+    ALOGV("AAC decoder using encoder-side DRC reference level of %d", encTargetLevel);
+    mDrcWrap.setParam(DRC_PRES_MODE_WRAP_ENCODER_TARGET, (unsigned)encTargetLevel);
+
+    // AAC_UNIDRC_SET_EFFECT
+    int32_t effectType = mIntf->getDrcEffectType();
+    ALOGV("AAC decoder using MPEG-D DRC effect type %d", effectType);
+    aacDecoder_SetParam(mAACDecoder, AAC_UNIDRC_SET_EFFECT, effectType);
 
     // By default, the decoder creates a 5.1 channel downmix signal.
     // For seven and eight channel input streams, enable 6.1 and 7.1 channel output
diff --git a/media/codecs/aac/DrcPresModeWrap.cpp b/media/codecs/aac/DrcPresModeWrap.cpp
index 74ab530..5b9aebc 100644
--- a/media/codecs/aac/DrcPresModeWrap.cpp
+++ b/media/codecs/aac/DrcPresModeWrap.cpp
@@ -24,7 +24,7 @@
 //#define DRC_PRES_MODE_WRAP_DEBUG
 
 #define GPM_ENCODER_TARGET_LEVEL 64
-#define MAX_TARGET_LEVEL 64
+#define MAX_TARGET_LEVEL 40
 
 CDrcPresModeWrapper::CDrcPresModeWrapper()
 {
@@ -164,7 +164,7 @@
     if (mDataUpdate) {
         // sanity check
         if (mDesTarget < MAX_TARGET_LEVEL){
-            mDesTarget = MAX_TARGET_LEVEL;  // limit target level to -16 dB or below
+            mDesTarget = MAX_TARGET_LEVEL;  // limit target level to -10 dB or below
             newTarget = MAX_TARGET_LEVEL;
         }