PR #22846 opened by Lynne
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/22846
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/22846.patch

This implements support for DRC parameter decoding. Only focused on loudness 
normalization for now.


>From 8ae5e22bc5ff34d29a2881e2d801a9cfb50421b7 Mon Sep 17 00:00:00 2001
From: Lynne <[email protected]>
Date: Fri, 17 Apr 2026 18:13:40 +0200
Subject: [PATCH] aacdec_usac: implement basic DRC parameter decoding

---
 libavcodec/aac/aacdec.h      | 13 +++++++
 libavcodec/aac/aacdec_usac.c | 74 +++++++++++++++++++++++++++++++++++-
 2 files changed, 85 insertions(+), 2 deletions(-)

diff --git a/libavcodec/aac/aacdec.h b/libavcodec/aac/aacdec.h
index c67246e287..cf55bbe6c0 100644
--- a/libavcodec/aac/aacdec.h
+++ b/libavcodec/aac/aacdec.h
@@ -98,6 +98,12 @@ enum AACUSACLoudnessExt {
     UNIDRCLOUDEXT_EQ = 0x1,
 };
 
+enum AACUSACDRCExt {
+    UNIDRCCONFEXT_TERM = 0x0,
+    UNIDRCCONFEXT_PARAM_DRC = 0x1,
+    UNIDRCCONFEXT_V1 = 0x2,
+};
+
 // Supposed to be equal to AAC_RENAME() in case of USE_FIXED.
 #define RENAME_FIXED(name) name ## _fixed
 
@@ -377,6 +383,13 @@ typedef struct AACUsacElemConfig {
         uint32_t pl_data_offset;
         uint8_t *pl_buf;
     } ext;
+
+    struct {
+        struct {
+            int lower;
+            int upper;
+        } loudness;
+    } drc;
 } AACUsacElemConfig;
 
 typedef struct AACUSACConfig {
diff --git a/libavcodec/aac/aacdec_usac.c b/libavcodec/aac/aacdec_usac.c
index 0f1bb50a99..89f66ba06f 100644
--- a/libavcodec/aac/aacdec_usac.c
+++ b/libavcodec/aac/aacdec_usac.c
@@ -253,6 +253,76 @@ static int decode_usac_element_pair(AACDecContext *ac,
     return 0;
 }
 
+static int decode_drc_config(AACDecContext *ac, AACUsacElemConfig *e,
+                             GetBitContext *gb)
+{
+    e->drc.loudness.lower = -1;
+    e->drc.loudness.upper = -1;
+
+    if (get_bits1(gb))
+        skip_bits(gb, 18); /* bsSampleRate */
+
+    skip_bits(gb, 7); /* downmixInstructionsCount */
+
+    if (get_bits1(gb)) /* drcDescriptionBasicPresent */
+        skip_bits(gb, 3); /* drcCoefficientsBasicCount */
+
+    int nb_coeff_count = get_bits(gb, 3); /* drcCoefficientsUniDrcCount */
+    if (nb_coeff_count) {
+        avpriv_report_missing_feature(ac->avctx,
+                                      "AAC USAC DRC coeff/instruction 
handling");
+        return AVERROR_PATCHWELCOME;
+    }
+
+    int nb_instr_count = get_bits(gb, 6); /* drcInstructionsUniDrcCount */
+    for (int i = 0; i < nb_instr_count; i++) {
+        skip_bits(gb, 6); /* drcSetId */
+        skip_bits(gb, 4); /* drcLocation */
+        skip_bits(gb, 7); /* downmixId */
+        if (get_bits1(gb)) { /* additionalDownmixIdPresent */
+            int add_downmix_cnt = get_bits(gb, 3);
+            for (int i = 0; i < add_downmix_cnt; i++)
+                skip_bits(gb, 7);
+        }
+
+        int set_effects = get_bits(gb, 16);
+        if ((set_effects & (3 << 10)) == 0) {
+            if (get_bits1(gb))
+                skip_bits(gb, 8); /* bsLimiterPeakTarget */
+        }
+
+        if (get_bits1(gb)) { /* drcSetTargetLoudnessPresent */
+            e->drc.loudness.upper = get_bits(gb, 6);
+            if (get_bits1(gb))
+                e->drc.loudness.lower = get_bits(gb, 6);
+        }
+    }
+
+    {
+        int ch_count = get_bits(gb, 7); /* baseChannelCount */
+        if (get_bits1(gb)) {
+            if (get_bits(gb, 8) == 0)
+                for (int i = 0; i < ch_count; i++)
+                    skip_bits(gb, 7); /* speakerPosition */
+        }
+    }
+
+    if (get_bits1(gb)) { /* uniDrcConfigExtPresent */
+        enum AACUSACDRCExt type;
+        while ((type = get_bits(gb, 4)) != UNIDRCCONFEXT_TERM) {
+            uint8_t size_bits = get_bits(gb, 4) + 4;
+            uint8_t bit_size = get_bits(gb, size_bits) + 1;
+            switch (type) {
+            default:
+                for (int i = 0; i < bit_size; i++)
+                    skip_bits1(gb);
+            }
+        }
+    }
+
+    return 0;
+}
+
 static int decode_usac_extension(AACDecContext *ac, AACUsacElemConfig *e,
                                  GetBitContext *gb)
 {
@@ -276,9 +346,9 @@ static int decode_usac_extension(AACDecContext *ac, 
AACUsacElemConfig *e,
         break;
     case ID_EXT_ELE_SAOC:
         break;
-    case ID_EXT_ELE_UNI_DRC:
-        break;
 #endif
+    case ID_EXT_ELE_UNI_DRC:
+        return decode_drc_config(ac, e, gb);
     case ID_EXT_ELE_FILL:
         break; /* This is what the spec does */
     case ID_EXT_ELE_AUDIOPREROLL:
-- 
2.52.0

_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to