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

This commit implements support for decoding of MPEG Surround data, USAC variant.


>From 30099bd2c8b1c901e49f3f79bee3e03f5431066e Mon Sep 17 00:00:00 2001
From: Lynne <[email protected]>
Date: Thu, 13 Nov 2025 15:57:55 +0100
Subject: [PATCH 1/3] aacdec_tab: split up tables init

---
 libavcodec/aac/aacdec_tab.c | 39 ++++++++++++++++++++++++-------------
 1 file changed, 25 insertions(+), 14 deletions(-)

diff --git a/libavcodec/aac/aacdec_tab.c b/libavcodec/aac/aacdec_tab.c
index 45a84a9a72..dce1ebb39e 100644
--- a/libavcodec/aac/aacdec_tab.c
+++ b/libavcodec/aac/aacdec_tab.c
@@ -258,17 +258,33 @@ static const int8_t sbr_vlc_offsets[10] = {
     -60, -60, -24, -24, -31, -31, -12, -12, -31, -12
 };
 
+
 const VLCElem *ff_aac_sbr_vlc[10];
 
-static av_cold void aacdec_common_init(void)
+static av_cold void init_sbr_tables(void)
 {
-    static VLCElem vlc_buf[(304 + 270 + 550 + 300 + 328 +
-                            294 + 306 + 268 + 510 + 366 + 462) +
-                           (1098 + 1092 + 768 + 1026 + 1058 +
+    static VLCElem vlc_buf[(1098 + 1092 + 768 + 1026 + 1058 +
                             1052 +  544 + 544 +  592 + 512)];
     VLCInitState state = VLC_INIT_STATE(vlc_buf);
     const uint8_t (*tab)[2] = sbr_huffman_tab;
 
+    // SBR VLC table initialization
+    for (int i = 0; i < FF_ARRAY_ELEMS(ff_aac_sbr_vlc); i++) {
+        ff_aac_sbr_vlc[i] =
+            ff_vlc_init_tables_from_lengths(&state, 9, sbr_huffman_nb_codes[i],
+                                            &tab[0][1], 2,
+                                            &tab[0][0], 2, 1,
+                                            sbr_vlc_offsets[i], 0);
+        tab += sbr_huffman_nb_codes[i];
+    }
+}
+
+static av_cold void init_base_tables(void)
+{
+    static VLCElem vlc_buf[(304 + 270 + 550 + 300 + 328 +
+                            294 + 306 + 268 + 510 + 366 + 462)];
+    VLCInitState state = VLC_INIT_STATE(vlc_buf);
+
     for (unsigned i = 0; i < 11; i++) {
 #define TAB_WRAP_SIZE(name) name[i], sizeof(name[i][0]), sizeof(name[i][0])
         ff_vlc_spectral[i] =
@@ -287,17 +303,12 @@ static av_cold void aacdec_common_init(void)
                           ff_aac_scalefactor_code,
                           sizeof(ff_aac_scalefactor_code[0]),
                           sizeof(ff_aac_scalefactor_code[0]), 0);
+}
 
-    // SBR VLC table initialization
-    for (int i = 0; i < FF_ARRAY_ELEMS(ff_aac_sbr_vlc); i++) {
-        ff_aac_sbr_vlc[i] =
-            ff_vlc_init_tables_from_lengths(&state, 9, sbr_huffman_nb_codes[i],
-                                            &tab[0][1], 2,
-                                            &tab[0][0], 2, 1,
-                                            sbr_vlc_offsets[i], 0);
-        tab += sbr_huffman_nb_codes[i];
-    }
-
+static av_cold void aacdec_common_init(void)
+{
+    init_base_tables();
+    init_sbr_tables();
     ff_ps_init_common();
 }
 
-- 
2.52.0


>From 32964c1345c486c8c912af904434560b91e8b390 Mon Sep 17 00:00:00 2001
From: Lynne <[email protected]>
Date: Thu, 13 Nov 2025 15:58:16 +0100
Subject: [PATCH 2/3] aacdec_tab: add Mps212 tables

To be used in the following commit.
---
 libavcodec/aac/aacdec_tab.c | 466 ++++++++++++++++++++++++++++++++++++
 libavcodec/aac/aacdec_tab.h |  27 +++
 2 files changed, 493 insertions(+)

diff --git a/libavcodec/aac/aacdec_tab.c b/libavcodec/aac/aacdec_tab.c
index dce1ebb39e..a78230e3f8 100644
--- a/libavcodec/aac/aacdec_tab.c
+++ b/libavcodec/aac/aacdec_tab.c
@@ -279,6 +279,472 @@ static av_cold void init_sbr_tables(void)
     }
 }
 
+const int16_t ff_aac_hcod_firstband_CLD[30][2] = {
+    {   2,   1 }, {   4,   3 }, {   6,   5 }, {   8,   7 }, {  10,   9 },
+    {  12,  11 }, {  14,  13 }, {  -8,  15 }, {  -9,  16 }, { -10,  17 },
+    { -18,  18 }, { -17, -19 }, { -16,  19 }, { -11, -20 }, { -15, -21 },
+    {  -7,  20 }, { -22,  21 }, { -12, -14 }, { -13, -23 }, {  23,  22 },
+    { -24, -31 }, {  -6,  24 }, { -25, -26 }, {  26,  25 }, {  -5, -27 },
+    { -28,  27 }, {  -4,  28 }, { -29,  29 }, {  -1, -30 }, {  -2,  -3 },
+};
+
+const int16_t ff_aac_hcod1D_CLD[2 /* DT/DF */][30][2] = {
+    { {  -1,   1 }, {  -2,   2 }, {  -3,   3 }, {  -4,   4 }, {  -5,   5 },
+      {  -6,   6 }, {  -7,   7 }, {   9,   8 }, {  -8,  10 }, {  -9,  11 },
+      { -10,  12 }, { -11,  13 }, { -12,  14 }, { -13,  15 }, { -14,  16 },
+      { -15,  17 }, { -16,  18 }, { -17,  19 }, { -18,  20 }, { -19, -20 },
+      { -21,  21 }, { -22,  22 }, { -23,  23 }, {  25,  24 }, { -24,  26 },
+      { -25,  27 }, {  29,  28 }, { -26, -31 }, { -29, -30 }, { -27, -28 }, },
+    { {  -1,   1 }, {  -2,   2 }, {  -3,   3 }, {  -4,   4 }, {  -5,   5 },
+      {  -6,   6 }, {  -7,   7 }, {  -8,   8 }, {  -9,   9 }, { -10,  10 },
+      { -11,  11 }, { -12,  12 }, { -13,  13 }, {  15,  14 }, { -14,  16 },
+      { -15,  17 }, { -16,  18 }, { -17,  19 }, { -18,  20 }, { -19,  21 },
+      { -20, -21 }, { -23,  22 }, { -22,  23 }, { -24,  24 }, { -25,  25 },
+      {  27,  26 }, {  29,  28 }, { -30, -31 }, { -28, -29 }, { -26, -27 }, },
+};
+
+const int16_t ff_aac_hcod2D_CLD_03[2 /* _TP/_FP */ ][2 /* DT_/DF_ */ ][15][2] 
= {
+    { { {  -1,   1 }, { -52,   2 }, {   4,   3 }, {  -2,   5 }, { -17,   6 },
+        { -18,   7 }, { -36, -51 }, {   9,   8 }, { -35,  10 }, { -34,  11 },
+        { -19, -33 }, {  -3,  12 }, { -20,  13 }, { -50,  14 }, {  -4, -49 }, 
},
+      { {  -1,   1 }, { -52,   2 }, { -17,   3 }, {   5,   4 }, { -36,   6 },
+        { -33,   7 }, {  -2, -18 }, { -20,   8 }, {  10,   9 }, { -34, -49 },
+        { -51,  11 }, { -35,  12 }, { -19,  13 }, {  -3,  14 }, {  -4, -50 }, 
}, },
+    { { {  -1,   1 }, { -52,   2 }, { -17,   3 }, {   5,   4 }, {  -2, -36 },
+        { -18,   6 }, {   8,   7 }, { -51,   9 }, { -33,  10 }, { -34,  11 },
+        { -20, -35 }, { -19,  12 }, {  -3,  13 }, { -49,  14 }, {  -4, -50 }, 
},
+      { {   2,   1 }, {  -1, -52 }, {   4,   3 }, {  -2,   5 }, { -51,   6 },
+        { -17, -18 }, {   8,   7 }, {  10,   9 }, {  -3, -36 }, { -19,  11 },
+        { -35, -50 }, { -34,  12 }, {  -4,  13 }, { -33,  14 }, { -20, -49 }, 
}, },
+};
+
+const int16_t ff_aac_hcod2D_CLD_05[2 /* _TP/_FP */ ][2 /* DT_/DF_ */ ][35][2] 
= {
+    { { {   2,   1 }, { -86,   3 }, {   5,   4 }, {  -1,   6 }, {   8,   7 },
+        { -17, -18 }, {  -2,   9 }, { -70,  10 }, { -85,  11 }, {  13,  12 },
+        { -69,  14 }, { -34,  15 }, {  17,  16 }, { -19,  18 }, { -33, -35 },
+        { -54,  19 }, { -53,  20 }, {  -3,  21 }, { -68,  22 }, { -84,  23 },
+        { -50,  24 }, { -52,  25 }, { -51,  26 }, { -20, -36 }, { -49,  27 },
+        { -38,  28 }, { -37,  29 }, {  -4, -83 }, { -67,  30 }, { -66,  31 },
+        { -21,  32 }, { -22, -65 }, {  -5,  33 }, { -82,  34 }, {  -6, -81 }, 
},
+    { {   2,   1 }, {   4,   3 }, { -86,   5 }, {  -1,   6 }, { -17,   7 },
+        { -70,   8 }, {  10,   9 }, { -18,  11 }, { -33,  12 }, { -54,  13 },
+        {  -2,  14 }, { -34,  15 }, { -38,  16 }, { -49,  17 }, { -85,  18 },
+        { -50,  19 }, { -69,  20 }, { -53, -65 }, { -22,  21 }, { -66,  22 },
+        { -19,  23 }, { -37,  24 }, { -35, -81 }, {  -3,  25 }, { -51,  26 },
+        { -68, -84 }, { -52,  27 }, {  29,  28 }, { -20,  30 }, {  -4, -36 },
+        { -83,  31 }, { -67,  32 }, { -21,  33 }, {  -5,  34 }, {  -6, -82 }, 
}, },
+    { { {   2,   1 }, { -86,   3 }, {  -1,   4 }, { -17,   5 }, {   7,   6 },
+        { -70,   8 }, {  -2, -18 }, {  10,   9 }, {  12,  11 }, { -85,  13 },
+        { -33,  14 }, { -34, -54 }, {  16,  15 }, { -69,  17 }, {  19,  18 },
+        { -50, -53 }, { -19,  20 }, { -38,  21 }, { -35, -49 }, {  -3,  22 },
+        {  24,  23 }, { -68,  25 }, { -84,  26 }, { -65,  27 }, { -51, -66 },
+        { -22, -37 }, { -52,  28 }, { -20,  29 }, { -36,  30 }, { -81,  31 },
+        {  -4, -83 }, { -67,  32 }, { -21,  33 }, {  -5,  34 }, {  -6, -82 }, 
},
+      { {   2,   1 }, {   4,   3 }, { -86,   5 }, {   7,   6 }, {   9,   8 },
+        {  -1,  -2 }, { -85,  10 }, { -18,  11 }, { -17,  12 }, {  14,  13 },
+        { -70,  15 }, {  17,  16 }, { -19, -69 }, { -84,  18 }, {  -3,  19 },
+        {  21,  20 }, { -34, -68 }, { -20,  22 }, { -35,  23 }, { -83,  24 },
+        { -33,  25 }, {  -4,  26 }, { -53,  27 }, { -54, -67 }, { -36,  28 },
+        { -21, -52 }, { -82,  29 }, {  -5, -50 }, { -51,  30 }, { -38,  31 },
+        { -37, -49 }, {  -6,  32 }, { -66,  33 }, { -65,  34 }, { -22, -81 }, 
}, },
+};
+
+const int16_t ff_aac_hcod2D_CLD_07[2 /* _TP/_FP */ ][2 /* DT_/DF_ */ ][63][2] 
= {
+    { { {   2,   1 }, {   4,   3 }, {-120,   5 }, {   7,   6 }, {   9,   8 },
+        {  -1,  10 }, { -18,  11 }, { -17,  12 }, {  -2,-104 }, {-119,  13 },
+        {  15,  14 }, {-103,  16 }, {  18,  17 }, { -34,  19 }, { -19,  20 },
+        {  22,  21 }, { -35,  23 }, { -33,  24 }, { -88,  25 }, { -87,  26 },
+        {  28,  27 }, {  -3,-102 }, { -86,  29 }, { -52,-118 }, {  31,  30 },
+        { -50,  32 }, { -51,  33 }, { -70,  34 }, { -36,  35 }, { -85,  36 },
+        { -20,  37 }, {  39,  38 }, { -69, -71 }, { -72,  40 }, { -49, -67 },
+        {  42,  41 }, { -68,  43 }, {  -4,-101 }, { -53,-117 }, { -37,  44 },
+        { -66,  45 }, { -55,  46 }, {  48,  47 }, { -54,  49 }, { -21,  50 },
+        { -84,-100 }, { -56, -65 }, {  52,  51 }, { -82, -83 }, {  54,  53 },
+        {  -5,-116 }, { -22,  55 }, { -38,  56 }, { -39, -40 }, {  58,  57 },
+        { -81,-115 }, { -98, -99 }, {  -6,  59 }, { -23,  60 }, { -24,  61 },
+        {  -7, -97 }, {-114,  62 }, {  -8,-113 }, },
+    { {   2,   1 }, {   4,   3 }, {   6,   5 }, {-120,   7 }, { -17,   8 },
+        {  -1,-104 }, {  10,   9 }, {  12,  11 }, { -18,  13 }, { -33, -88 },
+        {  15,  14 }, {  17,  16 }, {  -2,  18 }, { -34,  19 }, { -72,  20 },
+        { -49,  21 }, {-119,  22 }, { -50,  23 }, {-103,  24 }, { -56,  25 },
+        { -65,  26 }, {  28,  27 }, { -40, -87 }, { -66,  29 }, { -82,  30 },
+        {  32,  31 }, { -19, -81 }, { -71,  33 }, { -97,  34 }, { -35, -55 },
+        { -24,  35 }, {  37,  36 }, {  -3, -98 }, { -51,  38 }, { -67,  39 },
+        { -39,-118 }, {-113,  40 }, {-102,  41 }, { -86,  42 }, { -70, -83 },
+        {  44,  43 }, { -20, -54 }, { -52,  45 }, { -36,  46 }, {  -4,  47 },
+        { -68,  48 }, { -85,  49 }, {-101,-117 }, { -69,  50 }, {  52,  51 },
+        { -21, -37 }, { -53,  53 }, {  55,  54 }, {  -5,-100 }, {-116,  56 },
+        { -84,  57 }, { -38,  58 }, { -22, -99 }, {-115,  59 }, {  -6,  60 },
+        { -23,  61 }, {  -7,  62 }, {-114,   0 }, }, },
+    { { {   2,   1 }, {-120,   3 }, {  -1,   4 }, {   6,   5 }, { -17,   7 },
+        {-104,   8 }, { -18,   9 }, {  -2,  10 }, {  12,  11 }, {  14,  13 },
+        {-119,  15 }, { -33,  16 }, { -34, -88 }, {-103,  17 }, {  19,  18 },
+        {  21,  20 }, {  23,  22 }, {  25,  24 }, { -19, -72 }, { -50,  26 },
+        { -49,  27 }, { -87,  28 }, {  30,  29 }, {  32,  31 }, {  -3, -35 },
+        {  34,  33 }, { -56,  35 }, { -65, -66 }, { -40,  36 }, { -82,-118 },
+        { -71,  37 }, { -55,  38 }, { -67,-102 }, { -51,  39 }, { -70,  40 },
+        {  42,  41 }, { -81,  43 }, { -86,  44 }, { -52, -97 }, { -98,  45 },
+        { -24, -39 }, { -20,  46 }, { -54, -83 }, { -36,  47 }, { -85,  48 },
+        { -68,  49 }, {  -4,  50 }, { -69,-113 }, {-117,  51 }, { -37,-101 },
+        { -53,  52 }, { -21,  53 }, {  55,  54 }, { -84,-100 }, {  -5,  56 },
+        {-116,  57 }, { -22,  58 }, { -38,-115 }, {  60,  59 }, {  -6, -99 },
+        { -23,  61 }, {-114,  62 }, {  -7,  -8 }, },
+      { {   2,   1 }, {   4,   3 }, {-120,   5 }, {   7,   6 }, {   9,   8 },
+        {  11,  10 }, {  -1,  12 }, { -18,-119 }, {  -2,  13 }, {  15,  14 },
+        { -17,  16 }, {-104,  17 }, {  19,  18 }, { -19,  20 }, {-103,  21 },
+        {-118,  22 }, {  24,  23 }, {  -3,  25 }, {  27,  26 }, { -34,  28 },
+        {-102,  29 }, { -20,  30 }, { -35,  31 }, {  33,  32 }, {-117,  34 },
+        { -33,  35 }, { -88,  36 }, {  -4,  37 }, { -87,  38 }, {  40,  39 },
+        { -36,-101 }, { -86,  41 }, { -21, -37 }, { -85,-100 }, { -52,  42 },
+        { -22,  43 }, {-116,  44 }, { -50 , 45 }, {  47,  46 }, {  -5, -51 },
+        {-115,  48 }, { -70,  49 }, { -84,  50 }, { -38, -49 }, { -72, -99 },
+        { -53,  51 }, { -69, -71 }, { -23,  52 }, {  -6, -67 }, {-114,  53 },
+        {  -7,  54 }, { -66, -68 }, { -55,  55 }, {  57,  56 }, { -54, -65 },
+        {  -8, -56 }, { -82, -83 }, {  59,  58 }, { -39, -40 }, { -81,  60 },
+        { -98,  61 }, { -97,  62 }, { -24,-113 }, }, },
+};
+
+const int16_t ff_aac_hcod2D_CLD_09[2 /* _TP/_FP */ ][2 /* DT_/DF_ */ ][99][2] 
= {
+    { { {   2,   1 }, {   4,   3 }, {-154,   5 }, {   7,   6 }, {   9,   8 },
+        {  11,  10 }, {  -1,  12 }, { -18,  13 }, { -17,  14 }, {  -2,-138 },
+        {  16,  15 }, {-153,  17 }, {-137,  18 }, {  20,  19 }, {  22,  21 },
+        { -34,  23 }, { -19,  24 }, { -35,  25 }, {  27,  26 }, {  29,  28 },
+        {-121,  30 }, {-120,  31 }, {-136,  32 }, { -33,-122 }, {  34,  33 },
+        {-152,  35 }, {  -3,  36 }, { -51,  37 }, { -52,  38 }, { -69,  39 },
+        { -36,  40 }, { -50,  41 }, {  43,  42 }, { -20,  44 }, {-104,  45 },
+        {-103,  46 }, { -87,  47 }, {-119,  48 }, {-105,  49 }, { -86,  50 },
+        {-102,  51 }, {-106,  52 }, { -49,-135 }, { -68,  53 }, {  55,  54 },
+        { -53,  56 }, { -67,-151 }, {  -4,  57 }, { -84,  58 }, { -85,  59 },
+        { -66,  60 }, { -37,  61 }, { -70,  62 }, { -54, -88 }, { -21,  63 },
+        {  65,  64 }, { -89,  66 }, {-118,  67 }, { -72,  68 }, { -90,  69 },
+        { -71,  70 }, { -65,-134 }, {-150,  71 }, { -83,  72 }, {  -5,  73 },
+        {-101,-117 }, { -82,  74 }, {  76,  75 }, { -99,  77 }, { -38,  78 },
+        {-100,  79 }, { -22,  80 }, { -73,  81 }, { -39, -74 }, {  83,  82 },
+        { -55, -81 }, { -57,  84 }, {-133,-149 }, { -56,  85 }, {  -6,  86 },
+        { -98,  87 }, {-132,  88 }, { -23,  89 }, {-114,  90 }, {-116,  91 },
+        { -58,-115 }, { -24,  92 }, { -97,-148 }, { -40, -41 }, {  -7, -42 },
+        {-147,  93 }, {  95,  94 }, {-131,  96 }, {  -8,-130 }, { -25,-113 },
+        {  -9,  97 }, { -26,-129 }, {-146,  98 }, { -10,-145 }, },
+      { {   2,   1 }, {   4,   3 }, {   6,   5 }, {-154,   7 }, {   9,   8 },
+        { -17,  10 }, {-138,  11 }, {  -1,  12 }, {  14,  13 }, {  16,  15 },
+        { -33,-122 }, { -18,  17 }, {  19,  18 }, { -34,  20 }, {  -2,  21 },
+        {-106,  22 }, { -49,  23 }, {  25,  24 }, { -50,  26 }, {-153,  27 },
+        { -90,  28 }, {-137,  29 }, { -65,  30 }, {  32,  31 }, { -66,  33 },
+        {-121,  34 }, { -74,  35 }, { -81,  36 }, {  38,  37 }, { -42,  39 },
+        { -82,  40 }, {-105,  41 }, { -19,-114 }, { -58,  42 }, { -35,  43 },
+        { -97,  44 }, {  46,  45 }, {-129,  47 }, { -26, -89 }, { -57, -98 },
+        { -51,  48 }, {  -3,  49 }, {-113,  50 }, {-130,  51 }, {-152,  52 },
+        { -67, -73 }, { -99,-136 }, {-145,  53 }, {-120,  54 }, { -41,  55 },
+        { -83,  56 }, { -72,  57 }, {-104,  58 }, {-115,  59 }, { -20,  60 },
+        {  62,  61 }, { -36, -88 }, { -84,  63 }, { -52, -56 }, {  65,  64 },
+        {  -4, -87 }, { -68,  66 }, {-151,  67 }, {-100,-135 }, {  69,  68 },
+        { -69,-119 }, {-103,  70 }, { -71,  71 }, {  73,  72 }, { -21,  74 },
+        { -85,  75 }, { -37, -53 }, { -86,  76 }, {  78,  77 }, {-102,-150 },
+        {  -5,  79 }, {-134,  80 }, {-118,  81 }, { -54,-117 }, {  83,  82 },
+        { -38, -70 }, { -22,  84 }, {  -6,  85 }, {  87,  86 }, { -55,  88 },
+        {-101,  89 }, {-133,-149 }, { -24, -39 }, {  91,  90 }, {-132,  92 },
+        { -23,  93 }, {  -7,  94 }, {-147,-148 }, {-116,-131 }, { -25,  95 },
+        { -40,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 }, }, },
+    { { {   2,   1 }, {-154,   3 }, {   5,   4 }, {  -1,   6 }, {   8,   7 },
+        { -17,   9 }, {-138,  10 }, { -18,  11 }, {  -2,  12 }, {  14,  13 },
+        {  16,  15 }, {-153,  17 }, { -34,  18 }, { -33,-122 }, {  20,  19 },
+        {  22,  21 }, {-137,  23 }, {  25,  24 }, {  27,  26 }, {-106,  28 },
+        {  30,  29 }, { -50,  31 }, { -19,  32 }, { -49,-121 }, {  34,  33 },
+        {  36,  35 }, { -35,  37 }, { -90,  38 }, { -66,  39 }, {  -3,  40 },
+        {  42,  41 }, { -65,  43 }, {-105,  44 }, {  46,  45 }, { -74,  47 },
+        { -51,  48 }, { -82,-152 }, {-136,  49 }, { -81,  50 }, { -42, -89 },
+        {-114,  51 }, {  53,  52 }, { -57, -58 }, {-120,  54 }, { -98,  55 },
+        { -67,  56 }, { -97,  57 }, {  59,  58 }, { -99,  60 }, { -73,-104 },
+        { -72,  61 }, {-113,  62 }, { -20, -83 }, { -84,-130 }, { -36,  63 },
+        { -26,  64 }, { -41,  65 }, { -52,-129 }, { -87, -88 }, {  67,  66 },
+        {-115,  68 }, { -68,  69 }, { -56, -69 }, {  -4,-100 }, {-151,  70 },
+        {-135,  71 }, {-103,-119 }, {  73,  72 }, { -71,-145 }, {-102,  74 },
+        {  76,  75 }, { -53, -85 }, { -37,  77 }, { -21, -86 }, {  79,  78 },
+        {  -5,  80 }, { -54,-134 }, {-150,  81 }, {-118,  82 }, { -70,  83 },
+        {-117,  84 }, { -22, -38 }, {-101,  85 }, { -55,  86 }, {-149,  87 },
+        { -39,  88 }, {-133,  89 }, {  -6,  90 }, {-116,  91 }, { -24,  92 },
+        {  -7,-132 }, { -23,  93 }, { -40,  94 }, {-131,-148 }, { -25,  95 },
+        {-147,  96 }, {-146,  97 }, {  -8,   0 }, {   0,   0 }, },
+      { {   2,   1 }, {   4,   3 }, {   6,   5 }, {-154,   7 }, {   9,   8 },
+        {  11,  10 }, {  13,  12 }, {  15,  14 }, { -18,  16 }, {-153,  17 },
+        {  -1,  -2 }, {  19,  18 }, {-138,  20 }, { -17,  21 }, {  23,  22 },
+        {  25,  24 }, { -19,-137 }, {  27,  26 }, {-152,  28 }, {  30,  29 },
+        {  -3, -34 }, {  32,  31 }, {  34,  33 }, {  36,  35 }, {-136,  37 },
+        { -35,  38 }, { -20,  39 }, {-122,  40 }, {-151,  41 }, { -33,  42 },
+        {-121,  43 }, {  45,  44 }, {  47,  46 }, {  -4,  48 }, { -36,-120 },
+        {-135,  49 }, {  51,  50 }, { -21,  52 }, {  54,  53 }, {  56,  55 },
+        { -50,-150 }, {  58,  57 }, { -51,  59 }, {  61,  60 }, {-119,  62 },
+        { -52,  63 }, {  -5,  64 }, { -37,  65 }, {-117,-134 }, { -39, -54 },
+        { -22,  66 }, {-106,  67 }, { -69,-102 }, {-132,  68 }, {-105,  69 },
+        { -49,  70 }, {-149,  71 }, { -24,-104 }, {  73,  72 }, { -53,  74 },
+        { -38,-118 }, {-103,  75 }, {  -6,  76 }, { -66, -87 }, {-133,-147 },
+        { -23,  77 }, { -67,  78 }, { -68, -86 }, { -70,-101 }, { -40,-148 },
+        {-116,  79 }, { -55,  80 }, { -84,-131 }, {  82,  81 }, { -89, -90 },
+        {  -7, -25 }, { -85, -88 }, { -65,  83 }, { -72,-146 }, {  85,  84 },
+        {  -9, -71 }, { -83,  86 }, { -82,  87 }, {  -8,  88 }, {-100,  89 },
+        { -74, -99 }, { -73,  90 }, { -10, -81 }, { -56,  91 }, { -57, -98 },
+        {  93,  92 }, { -58,-114 }, { -97,-115 }, {  95,  94 }, { -41,  96 },
+        { -42,  97 }, { -26,-129 }, {-113,  98 }, {-130,-145 }, },
+    },
+};
+
+const int16_t ff_aac_hcod_firstband_ICC[7][2] = {
+    {   2,   1 }, {  -5,   3 }, {  -4,  -6 }, {  -3,   4 }, {  -2,   5 },
+    {  -1,   6 }, {  -7,  -8 },
+};
+
+const int16_t ff_aac_hcod1D_ICC[7][2] = {
+    {  -1,   1 }, {  -2,   2 }, {  -3,   3 }, {  -4,   4 }, {  -5,   5 },
+    {  -6,   6 }, {  -7,  -8 },
+};
+
+const int16_t ff_aac_hcod2D_ICC_01[2 /* _TP/_FP */ ][2 /* DT_/DF_ */ ][3][2] = 
{
+    { { {  -1,   1 }, { -18,   2 }, {  -2, -17 }, },
+      { {  -1,   1 }, { -18,   2 }, {  -2, -17 }, }, },
+    { { {  -1,   1 }, { -18,   2 }, {  -2, -17 }, },
+      { {  -1,   1 }, { -18,   2 }, {  -2, -17 }, }, },
+};
+
+const int16_t ff_aac_hcod2D_ICC_03[2 /* _TP/_FP */ ][2 /* DT_/DF_ */ ][15][2] 
= {
+    { { { -52,   1 }, {  -1,   2 }, {   4,   3 }, {  -2,   5 }, { -17, -18 },
+        { -51,   6 }, { -36,   7 }, {   9,   8 }, { -35,  10 }, {  -3,  11 },
+        { -19, -34 }, { -33,  12 }, { -50,  13 }, { -20,  14 }, {  -4, -49 }, 
},
+      { {   2,   1 }, {  -1, -52 }, { -17,   3 }, {   5,   4 }, { -36,   6 },
+        {  -2,   7 }, { -18, -33 }, {   9,   8 }, { -20,  10 }, { -34, -51 },
+        { -49,  11 }, { -35,  12 }, { -19,  13 }, {  -3,  14 }, {  -4, -50 }, 
}, },
+    { { { -52,   1 }, {  -1,   2 }, {   4,   3 }, {  -2, -17 }, { -18,   5 },
+        { -36,   6 }, { -51,   7 }, {   9,   8 }, { -33,  10 }, { -34,  11 },
+        { -35,  12 }, { -19, -20 }, {  -3,  13 }, { -49,  14 }, {  -4, -50 }, 
},
+      { {   2,   1 }, {  -1, -52 }, {  -2,   3 }, {   5,   4 }, { -51,   6 },
+        { -18,   7 }, { -17,   8 }, {  -3,   9 }, { -36,  10 }, { -19, -50 },
+        { -35,  11 }, {  -4,  12 }, { -34,  13 }, { -33,  14 }, { -20, -49 }, 
},},
+};
+
+const int16_t ff_aac_hcod2D_ICC_05[2 /* _TP/_FP */ ][2 /* DT_/DF_ */ ][35][2] 
= {
+    { { {   2,   1 }, { -86,   3 }, {  -1,   4 }, {   6,   5 }, { -18,   7 },
+        {  -2, -17 }, {   9,   8 }, { -70,  10 }, { -69, -85 }, { -35,  11 },
+        {  13,  12 }, { -34,  14 }, { -19,  15 }, { -53,  16 }, { -68,  17 },
+        { -33,  18 }, {  -3, -52 }, {  20,  19 }, { -54,  21 }, { -84,  22 },
+        { -50,  23 }, { -20, -51 }, { -36,  24 }, {  26,  25 }, { -83,  27 },
+        {  -4, -38 }, { -49,  28 }, { -37,  29 }, { -67,  30 }, {  -5,  31 },
+        { -21,  32 }, { -65, -66 }, { -82,  33 }, { -22,  34 }, {  -6, -81 }, 
},
+      { {   2,   1 }, { -86,   3 }, {  -1,   4 }, { -17,   5 }, {   7,   6 },
+        { -70,   8 }, { -33,   9 }, { -18,  10 }, {  -2,  11 }, { -54,  12 },
+        { -49,  13 }, { -38,  14 }, { -34, -65 }, { -85,  15 }, { -50,  16 },
+        { -69,  17 }, { -22,  18 }, { -53,  19 }, {  21,  20 }, { -19, -81 },
+        { -66,  22 }, {  -3, -35 }, {  24,  23 }, { -37,  25 }, { -68, -84 },
+        { -51,  26 }, {  28,  27 }, { -20, -52 }, {  30,  29 }, {  -4, -36 },
+        { -83,  31 }, { -67,  32 }, { -82,  33 }, { -21,  34 }, {  -5,  -6 }, 
}, },
+    { { {  -1,   1 }, { -86,   2 }, {   4,   3 }, { -17,   5 }, {  -2,   6 },
+        { -18,   7 }, { -70,   8 }, { -85,   9 }, {  11,  10 }, {  13,  12 },
+        { -33,  14 }, {  16,  15 }, { -34, -54 }, { -69,  17 }, { -38,  18 },
+        { -50,  19 }, { -35, -53 }, { -49,  20 }, { -19,  21 }, {  -3,  22 },
+        { -65,  23 }, { -68,  24 }, { -22,  25 }, { -81, -84 }, { -66,  26 },
+        { -37,  27 }, { -20, -51 }, {  29,  28 }, { -52,  30 }, {  -4, -83 },
+        { -36,  31 }, { -67,  32 }, {  -5,  33 }, { -82,  34 }, { -21,   0 }, 
},
+      { {   2,   1 }, { -86,   3 }, {  -1,   4 }, {   6,   5 }, {  -2,   7 },
+        { -85,   8 }, { -18,   9 }, {  11,  10 }, { -17,  12 }, {  14,  13 },
+        { -70,  15 }, {  -3, -19 }, { -69,  16 }, { -84,  17 }, { -68,  18 },
+        { -20, -35 }, { -34, -83 }, {  20,  19 }, {  -4,  21 }, { -33,  22 },
+        {  -5,  23 }, { -53,  24 }, { -36, -52 }, { -67,  25 }, { -21, -82 },
+        { -54,  26 }, {  -6,  27 }, { -51,  28 }, { -50,  29 }, { -49,  30 },
+        { -37,  31 }, { -38,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 }, 
}, },
+};
+
+const int16_t ff_aac_hcod2D_ICC_07[2 /* _TP/_FP */ ][2 /* DT_/DF_ */ ][63][2] 
= {
+    { { {   2,   1 }, {  -1,-120 }, {   4,   3 }, {   6,   5 }, { -18,   7 },
+        {   9,   8 }, { -17,  10 }, {  -2,  11 }, {-103,  12 }, { -52,  13 },
+        { -35,-104 }, {-119,  14 }, {  16,  15 }, { -69, -86 }, {  18,  17 },
+        { -34,  19 }, { -19,  20 }, {  22,  21 }, { -70,  23 }, { -87,  24 },
+        {-102,  25 }, { -85,  26 }, { -33,  27 }, { -36,  28 }, {  -3,  29 },
+        { -88,  30 }, { -51,  31 }, {-118,  32 }, {  34,  33 }, { -68,  35 },
+        { -53,  36 }, { -67,  37 }, { -20,  38 }, {-101,  39 }, { -50,  40 },
+        {  42,  41 }, { -37,  43 }, {-116,  44 }, {-117,  45 }, { -49,  46 },
+        { -21,-100 }, {  48,  47 }, { -55, -71 }, {  -4,  49 }, { -22, -84 },
+        {-115,  50 }, { -66, -82 }, { -72,  51 }, {  -5,  -6 }, { -54,  52 },
+        { -38,  53 }, { -83,  54 }, { -40,  55 }, { -39,  56 }, { -99,  57 },
+        { -23, -56 }, {  -7,  58 }, { -65, -97 }, {  -8,   0 }, {   0,   0 },
+        {   0,   0 }, {   0,   0 }, {   0,   0 }, },
+      { {   2,   1 }, {   4,   3 }, {  -1,-120 }, {   6,   5 }, {   8,   7 },
+        { -18,   9 }, {  -2,  10 }, {  12,  11 }, {  14,  13 }, { -17,-119 },
+        {  16,  15 }, {-103,  17 }, {-104,  18 }, { -52,  19 }, {  21,  20 },
+        { -69,  22 }, {  24,  23 }, {  -3, -35 }, { -19,  25 }, { -34, -85 },
+        {  27,  26 }, { -86,  28 }, {-118,  29 }, { -37,  30 }, {  32,  31 },
+        {-102,  33 }, { -20, -22 }, {  -4,-117 }, { -87,  34 }, {-100,  35 },
+        { -33, -36 }, {  37,  36 }, { -70, -88 }, {-101,  38 }, {  -5,  39 },
+        { -51, -53 }, { -50,  40 }, {-115,  41 }, { -21,  42 }, {-116,  43 },
+        { -38,  44 }, { -23, -84 }, { -49, -99 }, {  46,  45 }, {  -6,-114 },
+        {  -7, -72 }, { -71,  47 }, {  -8,   0 }, {   0,   0 }, {   0,   0 },
+        {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 },
+        {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 },
+        {   0,   0 }, {   0,   0 }, {   0,   0 }, }, },
+    { { {  -1,   1 }, {-120,   2 }, {   4,   3 }, { -17,   5 }, {  -2,   6 },
+        {   8,   7 }, { -18,   9 }, {-104,  10 }, {  12,  11 }, {  14,  13 },
+        {  16,  15 }, {-119,  17 }, { -81,  18 }, {  20,  19 }, { -33,  21 },
+        { -88,  22 }, {-103,  23 }, { -34,  24 }, { -56,  25 }, { -72,  26 },
+        { -49,  27 }, { -82,  28 }, { -50,  29 }, { -65,  30 }, { -55, -87 },
+        { -19,  31 }, { -67,  32 }, { -35, -40 }, {  34,  33 }, { -52, -71 },
+        { -66,  35 }, { -70,  36 }, {  38,  37 }, { -51, -97 }, { -86,-102 },
+        {  -3,  39 }, {-118,  40 }, {  42,  41 }, { -24, -85 }, { -54,  43 },
+        { -39,  44 }, { -98,-113 }, { -36, -37 }, { -20, -69 }, {  -4,  45 },
+        {  -5,  46 }, { -21,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 },
+        {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 },
+        {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 },
+        {   0,   0 }, {   0,   0 }, {   0,   0 }, },
+      { {   2,   1 }, {   4,   3 }, {  -1,-120 }, {   6,   5 }, {   8,   7 },
+        { -18,   9 }, {  -2,  10 }, {  12,  11 }, {  14,  13 }, { -17,-119 },
+        {  16,  15 }, {-103,  17 }, {-104,  18 }, { -52,  19 }, {  21,  20 },
+        { -69,  22 }, {  24,  23 }, {  -3, -35 }, { -19,  25 }, { -34, -85 },
+        {  27,  26 }, { -86,  28 }, {-118,  29 }, { -37,  30 }, {  32,  31 },
+        {-102,  33 }, { -20, -22 }, {  -4,-117 }, { -87,  34 }, {-100,  35 },
+        { -33, -36 }, {  37,  36 }, { -70, -88 }, {-101,  38 }, {  -5,  39 },
+        { -51, -53 }, { -50,  40 }, {-115,  41 }, { -21,  42 }, {-116,  43 },
+        { -38,  44 }, { -23, -84 }, { -49, -99 }, {  46,  45 }, {  -6,-114 },
+        {  -7, -72 }, { -71,  47 }, {  -8,   0 }, {   0,   0 }, {   0,   0 },
+        {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 },
+        {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 },
+        {   0,   0 }, {   0,   0 }, {   0,   0 }, }, },
+};
+
+const int16_t ff_aac_hcod_firstband_IPD[7][2] = {
+    {  -1,   1 }, {  -8,   2 }, {  -2,   3 }, {   5,   4 }, {  -7,   6 },
+    {  -3,  -5 }, {  -4,  -6 },
+};
+
+const int16_t ff_aac_hcod1D_IPD[2 /* DT, DF */ ][7][2] = {
+    { {  -1,   1 }, {  -2,   2 }, {  -8,   3 }, {  -3,   4 }, {  -7,   5 },
+      {  -4,   6 }, {  -5,  -6 }, }, /* DT */
+    { {  -1,   1 }, {  -8,   2 }, {  -2,   3 }, {   5,   4 }, {  -3,  -7 },
+      {  -6,   6 }, {  -4,  -5 }, }, /* DF */
+};
+
+const int16_t ff_aac_hcod2D_IPD_01[2 /* _TP/_FP */ ][2 /* DT_/DF_ */ ][3][2] = 
{
+    { { {  -1,   1 }, { -18,   2 }, { -17,   0 }, },
+      { {  -1,   1 }, { -18,   2 }, { -17,   0 }, }, },
+    { { {  -1,   1 }, { -18,   2 }, { -17,   0 }, },
+      { {  -1,   1 }, { -18,   2 }, { -17,   0 }, }, },
+};
+
+const int16_t ff_aac_hcod2D_IPD_03[2 /* _TP/_FP */ ][2 /* DT_/DF_ */ ][15][2] 
= {
+    { { {  -1,   1 }, {   3,   2 }, { -18,   4 }, { -52,   5 }, { -34, -36 },
+        { -35,   6 }, { -17,   7 }, { -33,   8 }, { -20,   9 }, { -49,   0 },
+        {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 }, 
},
+      { {  -1,   1 }, { -36,   2 }, { -18,   3 }, { -35,   4 }, { -52,   5 },
+        {   7,   6 }, { -34,   8 }, { -33, -49 }, { -20,   0 }, {   0,   0 },
+        {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 }, 
}, },
+    { { {  -1,   1 }, {   3,   2 }, { -18,   4 }, { -52,   5 }, { -34, -36 },
+        { -35,   6 }, { -17,   7 }, { -33,   8 }, { -20,   9 }, { -49,   0 },
+        {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 }, 
},
+      { {  -1,   1 }, { -36,   2 }, { -18,   3 }, { -35,   4 }, { -52,   5 },
+        {   7,   6 }, { -34,   8 }, { -33, -49 }, { -20,   0 }, {   0,   0 },
+        {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 }, 
}, },
+};
+
+const int16_t ff_aac_hcod2D_IPD_05[2 /* _TP/_FP */ ][2 /* DT_/DF_ */ ][35][2] 
= {
+    { { {  -1,   1 }, {   3,   2 }, { -52,   4 }, { -86,   5 }, { -35,   6 },
+        { -53,   7 }, { -70,   8 }, { -17,   9 }, { -37,  10 }, {  12,  11 },
+        { -38, -66 }, { -18,  13 }, { -51,  14 }, {  16,  15 }, { -34, -69 },
+        {  18,  17 }, { -54, -65 }, { -50,  19 }, { -33, -49 }, { -22,   0 },
+        {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 },
+        {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 },
+        {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 }, 
},
+      { {  -1,   1 }, {   3,   2 }, {   5,   4 }, { -86,   6 }, { -66,   7 },
+        {   9,   8 }, {  11,  10 }, { -18,  12 }, { -51,  13 }, { -37, -52 },
+        { -69,  14 }, { -38,  15 }, { -53,  16 }, { -35,  17 }, { -50, -70 },
+        { -22, -49 }, { -33,  18 }, { -17,  19 }, { -34, -65 }, { -81,  20 },
+        { -54,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 },
+        {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 },
+        {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 }, 
}, },
+    { { {  -1,   1 }, {   3,   2 }, { -52,   4 }, { -86,   5 }, { -35,   6 },
+        { -53,   7 }, { -70,   8 }, { -17,   9 }, { -37,  10 }, {  12,  11 },
+        { -38, -66 }, { -18,  13 }, { -51,  14 }, {  16,  15 }, { -34, -69 },
+        {  18,  17 }, { -54, -65 }, { -50,  19 }, { -33, -49 }, { -22,   0 },
+        {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 },
+        {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 },
+        {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 }, 
},
+      { {  -1,   1 }, {   3,   2 }, {   5,   4 }, { -86,   6 }, { -66,   7 },
+        {   9,   8 }, {  11,  10 }, { -18,  12 }, { -51,  13 }, { -37, -52 },
+        { -69,  14 }, { -38,  15 }, { -53,  16 }, { -35,  17 }, { -50, -70 },
+        { -22, -49 }, { -33,  18 }, { -17,  19 }, { -34, -65 }, { -81,  20 },
+        { -54,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 },
+        {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 },
+        {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 }, 
}, },
+};
+
+const int16_t ff_aac_hcod2D_IPD_07[2 /* _TP/_FP */ ][2 /* DT_/DF_ */ ][63][2] 
= {
+    { { {  -1,   1 }, { -69,   2 }, {   4,   3 }, {-120,   5 }, {   7,   6 },
+        {-113,   8 }, { -68,   9 }, {  11,  10 }, { -17,  12 }, { -52,  13 },
+        { -24,  14 }, { -18,  15 }, {  17,  16 }, {-104,  18 }, {  20,  19 },
+        { -54, -70 }, {  22,  21 }, {  24,  23 }, { -86, -97 }, {-103,  25 },
+        { -83,  26 }, { -35,  27 }, { -34, -98 }, { -40,  28 }, { -39, -67 },
+        {  30,  29 }, { -33, -51 }, { -87,  31 }, { -88,  32 }, { -82,  33 },
+        { -55, -81 }, { -56, -71 }, { -72,  34 }, { -50, -66 }, { -65,  35 },
+        { -49,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 },
+        {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 },
+        {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 },
+        {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 },
+        {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 },
+        {   0,   0 }, {   0,   0 }, {   0,   0 }, },
+      { {   2,   1 }, {   4,   3 }, {  -1,   5 }, { -69,   6 }, {-120,   7 },
+        { -68,   8 }, {  10,   9 }, {  12,  11 }, {  14,  13 }, { -52, -54 },
+        { -18,  15 }, { -70,  16 }, { -67,  17 }, {  19,  18 }, { -17,  20 },
+        {-113,  21 }, {  23,  22 }, { -83,  24 }, { -24,  25 }, {-103,-104 },
+        { -51, -55 }, {  27,  26 }, { -71,  28 }, { -86,  29 }, { -35,  30 },
+        { -66,  31 }, { -39, -50 }, { -82, -98 }, { -72,  32 }, { -56, -87 },
+        { -34,  33 }, { -33, -88 }, { -40, -97 }, { -65,  34 }, { -49,  35 },
+        { -81,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 },
+        {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 },
+        {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 },
+        {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 },
+        {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 },
+        {   0,   0 }, {   0,   0 }, {   0,   0 }, }, },
+    { { {  -1,   1 }, { -69,   2 }, {   4,   3 }, {-120,   5 }, {   7,   6 },
+        {-113,   8 }, { -68,   9 }, {  11,  10 }, { -17,  12 }, { -52,  13 },
+        { -24,  14 }, { -18,  15 }, {  17,  16 }, {-104,  18 }, {  20,  19 },
+        { -54, -70 }, {  22,  21 }, {  24,  23 }, { -86, -97 }, {-103,  25 },
+        { -83,  26 }, { -35,  27 }, { -34, -98 }, { -40,  28 }, { -39, -67 },
+        {  30,  29 }, { -33, -51 }, { -87,  31 }, { -88,  32 }, { -82,  33 },
+        { -55, -81 }, { -56, -71 }, { -72,  34 }, { -50, -66 }, { -65,  35 },
+        { -49,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 },
+        {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 },
+        {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 },
+        {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 },
+        {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 },
+        {   0,   0 }, {   0,   0 }, {   0,   0 }, },
+      { {   2,   1 }, {   4,   3 }, {  -1,   5 }, { -69,   6 }, {-120,   7 },
+        { -68,   8 }, {  10,   9 }, {  12,  11 }, {  14,  13 }, { -52, -54 },
+        { -18,  15 }, { -70,  16 }, { -67,  17 }, {  19,  18 }, { -17,  20 },
+        {-113,  21 }, {  23,  22 }, { -83,  24 }, { -24,  25 }, {-103,-104 },
+        { -51, -55 }, {  27,  26 }, { -71,  28 }, { -86,  29 }, { -35,  30 },
+        { -66,  31 }, { -39, -50 }, { -82, -98 }, { -72,  32 }, { -56, -87 },
+        { -34,  33 }, { -33, -88 }, { -40, -97 }, { -65,  34 }, { -49,  35 },
+        { -81,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 },
+        {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 },
+        {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 },
+        {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 },
+        {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 }, {   0,   0 },
+        {   0,   0 }, {   0,   0 }, {   0,   0 }, }, },
+};
+
+const int16_t ff_aac_hcod_lav_idx[3][2] = {
+    {  -1,   1 }, {  -2,   2 }, {  -3,  -4 },
+};
+
+const int16_t ff_aac_hcod2D_reshape[39][2] = {
+    {   2,   1 }, {   4,   3 }, {   6,   5 }, { -33,   7 }, { -17,   8 },
+    { -49,   9 }, { -34,  10 }, {  12,  11 }, { -18, -35 }, { -50,  13 },
+    {  15,  14 }, { -40,  16 }, { -36,  17 }, { -19,  18 }, {  -1, -37 },
+    { -51,  19 }, {  21,  20 }, { -38, -65 }, {  -2, -39 }, { -20,  22 },
+    { -52,  23 }, {  25,  24 }, { -21,  26 }, { -66,  27 }, { -53,  28 },
+    {  -3,  29 }, {  31,  30 }, { -22,  32 }, { -54,  33 }, {  -4,  34 },
+    { -56,  35 }, { -24, -67 }, { -23, -55 }, {  -8, -72 }, {  -5,  36 },
+    { -68,  37 }, {  -6,  38 }, {  -7, -69 }, { -70, -71 },
+};
+
+const uint8_t ff_aac_lav_tab_XXX[3][4] = {
+    { 3, 5, 7, 9 }, { 1, 3, 5, 7 }, { 7, 1, 3, 5 }
+};
+
 static av_cold void init_base_tables(void)
 {
     static VLCElem vlc_buf[(304 + 270 + 550 + 300 + 328 +
diff --git a/libavcodec/aac/aacdec_tab.h b/libavcodec/aac/aacdec_tab.h
index 70e49af202..e4b57527a1 100644
--- a/libavcodec/aac/aacdec_tab.h
+++ b/libavcodec/aac/aacdec_tab.h
@@ -50,6 +50,33 @@ extern const uint8_t ff_aac_channel_layout_map[16][16][3];
 extern const int16_t ff_aac_channel_map[3][4][6];
 
 extern const AVChannelLayout ff_aac_ch_layout[];
+
+extern const int16_t ff_aac_hcod_firstband_CLD[30][2];
+extern const int16_t ff_aac_hcod1D_CLD[2 /* DT_/DF_ */][30][2];
+extern const int16_t ff_aac_hcod2D_CLD_03[2 /* _TP/_FP */ ][2 /* DT_/DF_ */ 
][15][2];
+extern const int16_t ff_aac_hcod2D_CLD_05[2 /* _TP/_FP */ ][2 /* DT_/DF_ */ 
][35][2];
+extern const int16_t ff_aac_hcod2D_CLD_07[2 /* _TP/_FP */ ][2 /* DT_/DF_ */ 
][63][2];
+extern const int16_t ff_aac_hcod2D_CLD_09[2 /* _TP/_FP */ ][2 /* DT_/DF_ */ 
][99][2];
+
+extern const int16_t ff_aac_hcod_firstband_ICC[7][2];
+extern const int16_t ff_aac_hcod1D_ICC[7][2];
+extern const int16_t ff_aac_hcod2D_ICC_01[2 /* _TP/_FP */ ][2 /* DT_/DF_ */ 
][3][2];
+extern const int16_t ff_aac_hcod2D_ICC_03[2 /* _TP/_FP */ ][2 /* DT_/DF_ */ 
][15][2];
+extern const int16_t ff_aac_hcod2D_ICC_05[2 /* _TP/_FP */ ][2 /* DT_/DF_ */ 
][35][2];
+extern const int16_t ff_aac_hcod2D_ICC_07[2 /* _TP/_FP */ ][2 /* DT_/DF_ */ 
][63][2];
+
+extern const int16_t ff_aac_hcod_firstband_IPD[7][2];
+extern const int16_t ff_aac_hcod1D_IPD[2 /* DF, DT */ ][7][2];
+extern const int16_t ff_aac_hcod2D_IPD_01[2 /* _TP/_FP */ ][2 /* DT_/DF_ */ 
][3][2];
+extern const int16_t ff_aac_hcod2D_IPD_03[2 /* _TP/_FP */ ][2 /* DT_/DF_ */ 
][15][2];
+extern const int16_t ff_aac_hcod2D_IPD_05[2 /* _TP/_FP */ ][2 /* DT_/DF_ */ 
][35][2];
+extern const int16_t ff_aac_hcod2D_IPD_07[2 /* _TP/_FP */ ][2 /* DT_/DF_ */ 
][63][2];
+
+extern const int16_t ff_aac_hcod_lav_idx[3][2];
+
+extern const int16_t ff_aac_hcod2D_reshape[39][2];
+
+extern const uint8_t ff_aac_lav_tab_XXX[3][4];
 FF_VISIBILITY_POP_HIDDEN
 
 #endif /* AVCODEC_AAC_AACDEC_TAB_H */
-- 
2.52.0


>From e2554ae9524236a7a943d59c9fd9441e3d9e87cc Mon Sep 17 00:00:00 2001
From: Lynne <[email protected]>
Date: Mon, 17 Nov 2025 06:29:19 +0100
Subject: [PATCH 3/3] aacdec_usac: add support for decoding MPEG Surround
 (USAC-flavoured)

---
 libavcodec/aac.h                    |   4 +
 libavcodec/aac/Makefile             |   3 +-
 libavcodec/aac/aacdec.h             |  30 +
 libavcodec/aac/aacdec_usac.c        | 156 ++++-
 libavcodec/aac/aacdec_usac_mps212.c | 897 ++++++++++++++++++++++++++++
 libavcodec/aac/aacdec_usac_mps212.h |  64 ++
 6 files changed, 1149 insertions(+), 5 deletions(-)
 create mode 100644 libavcodec/aac/aacdec_usac_mps212.c
 create mode 100644 libavcodec/aac/aacdec_usac_mps212.h

diff --git a/libavcodec/aac.h b/libavcodec/aac.h
index 78026a5887..b77b6e7c18 100644
--- a/libavcodec/aac.h
+++ b/libavcodec/aac.h
@@ -36,6 +36,10 @@
 #define TNS_MAX_ORDER 20
 #define MAX_LTP_LONG_SFB 40
 
+#define MPS_MAX_PARAM_SETS 9
+#define MPS_MAX_PARAM_BANDS 28
+#define MPS_MAX_TIME_SLOTS 16 /* 64 in non-AAC MPEG Surround */
+
 enum RawDataBlockType {
     TYPE_SCE,
     TYPE_CPE,
diff --git a/libavcodec/aac/Makefile b/libavcodec/aac/Makefile
index 70b1dca274..b1ec21b188 100644
--- a/libavcodec/aac/Makefile
+++ b/libavcodec/aac/Makefile
@@ -3,6 +3,7 @@ clean::
 
 OBJS-$(CONFIG_AAC_DECODER)          +=  aac/aacdec.o aac/aacdec_tab.o \
                                         aac/aacdec_float.o aac/aacdec_usac.o \
-                                        aac/aacdec_ac.o aac/aacdec_lpd.o
+                                        aac/aacdec_ac.o aac/aacdec_lpd.o \
+                                        aac/aacdec_usac_mps212.o
 OBJS-$(CONFIG_AAC_FIXED_DECODER)    +=  aac/aacdec.o aac/aacdec_tab.o \
                                         aac/aacdec_fixed.o
diff --git a/libavcodec/aac/aacdec.h b/libavcodec/aac/aacdec.h
index b3763fdccc..84ffad83ff 100644
--- a/libavcodec/aac/aacdec.h
+++ b/libavcodec/aac/aacdec.h
@@ -43,6 +43,7 @@
 #include "libavcodec/mpeg4audio.h"
 
 #include "aacdec_ac.h"
+#include "aacdec_usac_mps212.h"
 
 typedef struct AACDecContext AACDecContext;
 
@@ -229,6 +230,32 @@ typedef struct SingleChannelElement {
     };
 } SingleChannelElement;
 
+typedef struct AACUsacMPSData {
+    /* Framing */
+    int framing_type;
+    int nb_param_sets;
+    int param_sets[MPS_MAX_PARAM_SETS];
+
+    /* OTT */
+    AACMPSLosslessData ott[MPS_ELE_NB];
+    bool opd_smoothing_mode;
+
+    /* SMG */
+    int smooth_mode[MPS_MAX_PARAM_SETS];
+    int smooth_time[MPS_MAX_PARAM_SETS];
+    int freq_res_stride_smg[MPS_MAX_PARAM_SETS];
+    bool smg_data[MPS_MAX_PARAM_SETS][MPS_MAX_PARAM_BANDS];
+
+    /* TSD */
+    bool tsd_enable;
+    bool temp_shape_enable;
+    bool temp_shape_enable_ch[2];
+    int16_t temp_shape_data[MPS_MAX_TIME_SLOTS];
+
+    int tsd_num_tr_slots;
+    int tsd_phase_data[64];
+} AACUsacMPSData;
+
 typedef struct AACUsacStereo {
     uint8_t common_window;
     uint8_t common_tw;
@@ -244,6 +271,8 @@ typedef struct AACUsacStereo {
 
     uint8_t pred_used[128];
 
+    AACUsacMPSData mps;
+
     INTFLOAT_ALIGNED_UNION(32, alpha_q_re, 1024);
     INTFLOAT_ALIGNED_UNION(32, alpha_q_im, 1024);
     INTFLOAT_ALIGNED_UNION(32, prev_alpha_q_re, 1024);
@@ -332,6 +361,7 @@ typedef struct AACUsacElemConfig {
         uint8_t high_rate_mode : 1; /* bsHighRateMode */
         uint8_t phase_coding : 1; /* bsPhaseCoding */
 
+        uint8_t otts_bands_phase_present; /* bsOttBandsPhasePresent */
         uint8_t otts_bands_phase; /* bsOttBandsPhase */
         uint8_t residual_coding; /* bsResidualCoding */
         uint8_t residual_bands; /* bsResidualBands */
diff --git a/libavcodec/aac/aacdec_usac.c b/libavcodec/aac/aacdec_usac.c
index 237a247d5b..f1bf75fe45 100644
--- a/libavcodec/aac/aacdec_usac.c
+++ b/libavcodec/aac/aacdec_usac.c
@@ -31,6 +31,8 @@
 #include "libavutil/mem.h"
 #include "libavutil/refstruct.h"
 
+#include "aacdec_usac_mps212.h"
+
 /* Number of scalefactor bands per complex prediction band, equal to 2. */
 #define SFB_PER_PRED_BAND 2
 
@@ -219,12 +221,15 @@ static int decode_usac_element_pair(AACDecContext *ac,
         e->mps.high_rate_mode = get_bits1(gb); /* bsHighRateMode */
         e->mps.phase_coding = get_bits1(gb); /* bsPhaseCoding */
 
-        if (get_bits1(gb)) /* bsOttBandsPhasePresent */
+        e->mps.otts_bands_phase_present = get_bits1(gb);
+        if (e->mps.otts_bands_phase_present) /* bsOttBandsPhasePresent */
             e->mps.otts_bands_phase = get_bits(gb, 5); /* bsOttBandsPhase */
 
         e->mps.residual_coding = e->stereo_config_index >= 2; /* 
bsResidualCoding */
         if (e->mps.residual_coding) {
             e->mps.residual_bands = get_bits(gb, 5); /* bsResidualBands */
+            e->mps.otts_bands_phase = FFMAX(e->mps.otts_bands_phase,
+                                            e->mps.residual_bands);
             e->mps.pseudo_lr = get_bits1(gb); /* bsPseudoLr */
         }
         if (e->mps.temp_shape_config == 2)
@@ -1343,6 +1348,147 @@ static void spectrum_decode(AACDecContext *ac, 
AACUSACConfig *usac,
     }
 }
 
+static const uint8_t mps_fr_nb_bands[8] = {
+    255 /* Reserved */, 28, 20, 14, 10, 7, 5, 4,
+};
+
+static const uint8_t mps_fr_stride_smg[4] = {
+    1, 2, 5, 28,
+};
+
+static void decode_tsd(GetBitContext *gb, int *data,
+                       int nb_tr_slots, int nb_slots)
+{
+    int nb_bits = av_log2(nb_slots / (nb_tr_slots + 1));
+    int s = get_bits(gb, nb_bits);
+    for (int k = 0; k < nb_slots; k++)
+        data[k]=0;
+
+    int p = nb_tr_slots + 1;
+    for (int k = nb_slots - 1; k >= 0; k--) {
+        if (p > k) {
+            for (; k >= 0; k--)
+                data[k] = 1;
+            break;
+        }
+        int64_t c = k - p + 1;
+        for (int h = 2; h <= p; h++) {
+            c *= k - p + h;
+            c /= h;
+        }
+        if (s >= (int)c) { /* c is long long for up to 32 slots */
+            s -= c;
+            data[k] = 1;
+            p--;
+            if (!p)
+                break;
+        }
+    }
+}
+
+static int parse_mps212(AACDecContext *ac, AACUSACConfig *usac,
+                        AACUsacMPSData *mps, AACUsacElemConfig *ec,
+                        GetBitContext *gb, int frame_indep_flag)
+{
+    int err;
+    int nb_bands = mps_fr_nb_bands[ec->mps.freq_res];
+ 
+    /* Framing info */
+    mps->framing_type = 0;
+    mps->nb_param_sets = 2;
+    if (ec->mps.high_rate_mode) {
+        mps->framing_type = get_bits1(gb);
+        mps->nb_param_sets = get_bits(gb, 3) + 1;
+    }
+    int param_slot_bits = usac->core_sbr_frame_len_idx == 4 ? 6 : 5;
+
+    if (mps->framing_type)
+        for (int i = 0; i < mps->nb_param_sets; i++)
+            mps->param_sets[i] = get_bits(gb, param_slot_bits);
+
+    int indep = frame_indep_flag;
+    if (!frame_indep_flag)
+        indep = get_bits1(gb);
+
+    /* OTT data */
+    err = ff_aac_ec_data_dec(gb, &mps->ott[MPS_CLD], MPS_CLD,
+                             0, 0, nb_bands,
+                             frame_indep_flag, indep, mps->nb_param_sets);
+    if (err < 0) {
+        av_log(ac->avctx, AV_LOG_ERROR, "Error parsing OTT CLD data!\n");
+        return err;
+    }
+    err = ff_aac_ec_data_dec(gb, &mps->ott[MPS_ICC], MPS_ICC, 0, 0, nb_bands,
+                             frame_indep_flag, indep, mps->nb_param_sets);
+    if (err < 0) {
+        av_log(ac->avctx, AV_LOG_ERROR, "Error parsing OTT ICC data!\n");
+        return err;
+    }
+    if (ec->mps.phase_coding) {
+        if (get_bits1(gb)) {
+            mps->opd_smoothing_mode = get_bits1(gb);
+            err = ff_aac_ec_data_dec(gb, &mps->ott[MPS_IPD], MPS_IPD, 0, 0,
+                                     ec->mps.otts_bands_phase,
+                                     frame_indep_flag, indep, 
mps->nb_param_sets);
+            if (err < 0) {
+                av_log(ac->avctx, AV_LOG_ERROR, "Error parsing OTT IPD 
data!\n");
+                return err;
+            }
+        }
+    }
+
+    /* SMG data */
+    memset(mps->smooth_mode, 0, sizeof(mps->smooth_mode));
+    if (ec->mps.high_rate_mode) {
+        for (int i = 0; i < mps->nb_param_sets; i++) {
+            mps->smooth_mode[i] = get_bits(gb, 2);
+            if (mps->smooth_mode[i] >= 2)
+                mps->smooth_time[i] = get_bits(gb, 2);
+            if (mps->smooth_mode[i] >= 3) {
+                mps->freq_res_stride_smg[i] = get_bits(gb, 2);
+                int nb_data_bands = (nb_bands - 1);
+                nb_data_bands /= 
(mps_fr_stride_smg[mps->freq_res_stride_smg[i]] + 1);
+                for (int j = 0; j < nb_data_bands; j++)
+                    mps->smg_data[i][j] = get_bits1(gb);
+            }
+        }
+    }
+
+    /* Temp shape data */
+    mps->tsd_enable = 0;
+    if (ec->mps.temp_shape_config == 3) {
+        mps->tsd_enable = get_bits1(gb);
+    } else if (ec->mps.temp_shape_config) {
+        mps->temp_shape_enable = get_bits1(gb);
+        if (mps->temp_shape_enable) {
+            for (int i = 0; i < 2; i++)
+                mps->temp_shape_enable_ch[i] = get_bits1(gb);
+            if (ec->mps.temp_shape_config == 2) {
+                err = ff_aac_huff_dec_reshape(gb, mps->temp_shape_data, 16);
+                if (err < 0) {
+                    av_log(ac->avctx, AV_LOG_ERROR, "Error parsing TSD reshape 
data!\n");
+                    return err;
+                }
+            }
+        }
+    }
+
+    /* TSD data */
+    if (mps->tsd_enable) {
+        mps->tsd_num_tr_slots = get_bits(gb, param_slot_bits - 1);
+        int nb_time_slots = usac->core_sbr_frame_len_idx == 4 ? 64 : 32;
+        int tsd_pos[64];
+        decode_tsd(gb, tsd_pos, mps->tsd_num_tr_slots, nb_time_slots);
+        for (int i = 0; i < nb_time_slots; i++) {
+            mps->tsd_phase_data[i] = 0;
+            if (tsd_pos[i])
+                mps->tsd_phase_data[i] = get_bits(gb, 3);
+        }
+    }
+
+    return 0;
+}
+
 static int decode_usac_core_coder(AACDecContext *ac, AACUSACConfig *usac,
                                   AACUsacElemConfig *ec, ChannelElement *che,
                                   GetBitContext *gb, int indep_flag, int 
nb_channels)
@@ -1464,7 +1610,8 @@ static int decode_usac_core_coder(AACDecContext *ac, 
AACUSACConfig *usac,
         if (get_bits1(gb)) { /* fac_data_present */
             const uint16_t len_8 = usac->core_frame_len / 8;
             const uint16_t len_16 = usac->core_frame_len / 16;
-            const uint16_t fac_len = ics->window_sequence[0] == 
EIGHT_SHORT_SEQUENCE ? len_16 : len_8;
+            const uint16_t fac_len = ics->window_sequence[0] == 
EIGHT_SHORT_SEQUENCE ?
+                                     len_16 : len_8;
             ret = ff_aac_parse_fac_data(ue, gb, 1, fac_len);
             if (ret < 0)
                 return ret;
@@ -1483,8 +1630,9 @@ static int decode_usac_core_coder(AACDecContext *ac, 
AACUSACConfig *usac,
     }
 
     if (ec->stereo_config_index) {
-        avpriv_report_missing_feature(ac->avctx, "AAC USAC Mps212");
-        return AVERROR_PATCHWELCOME;
+        ret = parse_mps212(ac, usac, &us->mps, ec, gb, indep_flag);
+        if (ret < 0)
+            return ret;
     }
 
     spectrum_decode(ac, usac, che, core_nb_channels);
diff --git a/libavcodec/aac/aacdec_usac_mps212.c 
b/libavcodec/aac/aacdec_usac_mps212.c
new file mode 100644
index 0000000000..9de47e1cc4
--- /dev/null
+++ b/libavcodec/aac/aacdec_usac_mps212.c
@@ -0,0 +1,897 @@
+/*
+ * Copyright (c) 2025 Lynne <[email protected]>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "aacdec_tab.h"
+#include "libavcodec/get_bits.h"
+#include "libavutil/macros.h"
+
+#include "aacdec_usac_mps212.h"
+
+static int huff_dec_1D(GetBitContext *gb, const int16_t (*tab)[2])
+{
+    int16_t idx = 0;
+    do {
+        /* Overreads are not possible here, the array forms a closed set */
+        idx = tab[idx][get_bits1(gb)];
+    } while (idx > 0);
+    return idx;
+}
+
+static int huff_dec_2D(GetBitContext *gb, const int16_t (*tab)[2], int16_t 
ret[2])
+{
+    int idx = huff_dec_1D(gb, tab);
+    if (!idx) { /* Escape */
+        ret[0] = 0;
+        ret[1] = 1;
+        return 1;
+    }
+
+    idx = -(idx + 1);
+    ret[0] = idx >> 4;
+    ret[1] = idx & 0xf;
+    return 0;
+}
+
+static int huff_data_1d(GetBitContext *gb, int16_t *data, int data_bands,
+                        enum AACMPSDataType data_type, int diff_freq, int 
p0_flag)
+{
+    const int16_t (*hcod_first_band)[2];
+    const int16_t (*hcod1D)[2];
+    switch (data_type) {
+    case MPS_CLD:
+        hcod_first_band = ff_aac_hcod_firstband_CLD;
+        hcod1D = ff_aac_hcod1D_CLD[diff_freq];
+        break;
+    case MPS_ICC:
+        hcod_first_band = ff_aac_hcod_firstband_ICC;
+        hcod1D = ff_aac_hcod1D_ICC;
+        break;
+    case MPS_IPD:
+        hcod_first_band = ff_aac_hcod_firstband_IPD;
+        hcod1D = ff_aac_hcod1D_IPD[diff_freq];
+        break;
+    }
+
+    if (p0_flag)
+        data[0] = -(huff_dec_1D(gb, hcod_first_band) + 1);
+
+    for (int off = diff_freq; off < data_bands; off++) {
+        int16_t val = -(huff_dec_1D(gb, hcod1D) + 1);
+        if (val && data_type != MPS_IPD)
+            val = get_bits1(gb) ? -val : val;
+        data[off] = val;
+    }
+
+    return 0;
+}
+
+static void symmetry_data(GetBitContext *gb, int16_t data[2],
+                          uint8_t lav, enum AACMPSDataType data_type)
+{
+    int16_t sum = data[0] + data[1];
+    int16_t diff = data[0] - data[1];
+
+    if (sum > lav) {
+        data[0] = -sum + (2*lav + 1);
+        data[1] = -diff;
+    } else {
+        data[0] = sum;
+        data[1] = diff;
+    }
+
+    if ((data_type != MPS_IPD) && (data[0] + data[1])) {
+        int sym = get_bits1(gb) ? -1 : 1;
+        data[0] *= sym;
+        data[1] *= sym;
+    }
+
+    if (data[0] - data[1]) {
+        if (get_bits1(gb))
+            FFSWAP(int16_t, data[0], data[1]);
+    }
+}
+
+static void pcm_decode(GetBitContext *gb, int16_t *data0, int16_t *data1,
+                       int16_t offset, int nb_pcm_data_bands,
+                       int nb_quant_steps, int nb_levels)
+{
+    int max_group_len;
+    switch (nb_levels) {
+    case  3: max_group_len = 5; break;
+    case  7: max_group_len = 6; break;
+    case 11: max_group_len = 2; break;
+    case 13: max_group_len = 4; break;
+    case 19: max_group_len = 4; break;
+    case 25: max_group_len = 3; break;
+    case 51: max_group_len = 4; break;
+    case  4: case  8: case 15: case 16: case 26: case 31:
+        max_group_len = 1;
+        break;
+    default:
+        return;
+    };
+
+    int pcm_chunk_size[7] = { 0 };
+
+    int tmp = 1;
+    for (int i = 1; i <= max_group_len; i++) {
+        tmp *= nb_levels;
+        pcm_chunk_size[i] = av_log2(tmp);
+    }
+
+    for (int i = 0; i < nb_pcm_data_bands; i+= max_group_len) {
+        int group_len = FFMIN(max_group_len, nb_pcm_data_bands - i);
+
+        int pcm = get_bits(gb, pcm_chunk_size[group_len]);
+        for (int j = 0; j < group_len; j++) {
+            int idx = i + (group_len - 1) - j;
+            int val = pcm % nb_levels;
+            if (data0 && data1) {
+                if (idx % 2)
+                    data1[idx / 2] = val - offset;
+                else
+                    data0[idx / 2] = val - offset;
+            } else if (!data1) {
+                data0[idx] = val - offset;
+            } else if (!data0) {
+                data1[idx] = val - offset;
+            }
+            pcm = (pcm - val) / nb_levels;
+        }
+    }
+}
+
+static void huff_data_2d(GetBitContext *gb, int16_t *part0_data[2], int16_t 
(*data)[2],
+                         int data_bands, int stride, enum AACMPSDataType 
data_type,
+                         int diff_freq, int freq_pair)
+{
+    int16_t lav_idx = huff_dec_1D(gb, ff_aac_hcod_lav_idx);
+    uint8_t lav = ff_aac_lav_tab_XXX[data_type][-(lav_idx + 1)];
+
+    const int16_t (*hcod1D)[2];
+    const int16_t (*hcod2D)[2];
+    switch (data_type) {
+    case MPS_CLD:
+        hcod1D = ff_aac_hcod_firstband_CLD;
+        switch (lav) {
+        case 3: hcod2D = ff_aac_hcod2D_CLD_03[freq_pair][diff_freq]; break;
+        case 5: hcod2D = ff_aac_hcod2D_CLD_05[freq_pair][diff_freq]; break;
+        case 7: hcod2D = ff_aac_hcod2D_CLD_07[freq_pair][diff_freq]; break;
+        case 9: hcod2D = ff_aac_hcod2D_CLD_09[freq_pair][diff_freq]; break;
+        }
+        break;
+    case MPS_ICC:
+        hcod1D = ff_aac_hcod_firstband_ICC;
+        switch (lav) {
+        case 1: hcod2D = ff_aac_hcod2D_ICC_01[freq_pair][diff_freq]; break;
+        case 3: hcod2D = ff_aac_hcod2D_ICC_03[freq_pair][diff_freq]; break;
+        case 5: hcod2D = ff_aac_hcod2D_ICC_05[freq_pair][diff_freq]; break;
+        case 7: hcod2D = ff_aac_hcod2D_ICC_07[freq_pair][diff_freq]; break;
+        }
+        break;
+    case MPS_IPD:
+        hcod1D = ff_aac_hcod_firstband_IPD;
+        switch (lav) {
+        case 1: hcod2D = ff_aac_hcod2D_IPD_01[freq_pair][diff_freq]; break;
+        case 3: hcod2D = ff_aac_hcod2D_IPD_03[freq_pair][diff_freq]; break;
+        case 5: hcod2D = ff_aac_hcod2D_IPD_05[freq_pair][diff_freq]; break;
+        case 7: hcod2D = ff_aac_hcod2D_IPD_07[freq_pair][diff_freq]; break;
+        }
+        break;
+    }
+
+    if (part0_data[0])
+        part0_data[0][0] = -(huff_dec_1D(gb, hcod1D) + 1);
+    if (part0_data[1])
+        part0_data[1][0] = -(huff_dec_1D(gb, hcod1D) + 1);
+
+    int i = 0;
+    int esc_cnt = 0;
+    int16_t esc_data[2][28];
+    int esc_idx[28];
+    for (; i < data_bands; i += stride) {
+        if (huff_dec_2D(gb, hcod2D, data[i]))
+            esc_idx[esc_cnt++] = i; /* Escape */
+        else
+            symmetry_data(gb, data[i], lav, data_type);
+    }
+
+    if (esc_cnt) {
+        pcm_decode(gb, esc_data[0], esc_data[1],
+                   0, 2*esc_cnt, 0, (2*lav + 1));
+        for (i = 0; i < esc_cnt; i++) {
+            data[esc_idx[i]][0] = esc_data[0][i] - lav;
+            data[esc_idx[i]][0] = esc_data[0][i] - lav;
+        }
+    }
+}
+
+static int huff_decode(GetBitContext *gb, int16_t *data[2],
+                       enum AACMPSDataType data_type, int diff_freq[2],
+                       int num_val, int *time_pair)
+{
+    int16_t pair_vec[28][2];
+    int num_val_ch[2] = { num_val, num_val };
+    int16_t *p0_data[2][2] = { 0 };
+    int df_rest_flag[2] = { 0, 0 };
+
+    /* Coding scheme */
+    int dim = get_bits1(gb);
+    if (dim) { /* 2D */
+        *time_pair = 0;
+        if (data[0] && data[1])
+            *time_pair = get_bits1(gb);
+
+        if (!time_pair) {
+            if (diff_freq[0] || diff_freq[1]) {
+                p0_data[0][0] = data[0];
+                p0_data[0][1] = data[1];
+
+                data[0] += 1;
+                data[1] += 1;
+
+                num_val_ch[0] -= 1;
+            }
+
+            int diff_mode = 1;
+            if (!diff_freq[0] || !diff_freq[1])
+                diff_mode = 0; // time
+
+            huff_data_2d(gb, p0_data[0], pair_vec, num_val_ch[0], 1, data_type,
+                         diff_mode, 0);
+
+            for (int i = 0; i < num_val_ch[0]; i++) {
+                data[0][i] = pair_vec[i][0];
+                data[1][i] = pair_vec[i][1];
+            }
+        } else {
+            if (data[0]) {
+                if (diff_freq[0]) {
+                    p0_data[0][0] = data[0];
+                    p0_data[0][1] = NULL;
+
+                    num_val_ch[0] -= 1;
+                    data[0]++;
+                }
+                df_rest_flag[0] = num_val_ch[0] % 2;
+                if (df_rest_flag[0])
+                    num_val_ch[0] -= 1;
+                if (num_val_ch[0] < 0)
+                    return AVERROR(EINVAL);
+            }
+
+            if (data[1]) {
+                if (diff_freq[1]) {
+                    p0_data[1][0] = NULL;
+                    p0_data[1][1] = data[1];
+
+                    num_val_ch[1] -= 1;
+                    data[1]++;
+                }
+                df_rest_flag[1] = num_val_ch[1] % 2;
+                if (df_rest_flag[1])
+                    num_val_ch[1] -= 1;
+                if (num_val_ch[1] < 0)
+                    return AVERROR(EINVAL);
+            }
+
+            if (data[0]) {
+                huff_data_2d(gb, p0_data[0], pair_vec, num_val_ch[0], 2, 
data_type,
+                             diff_freq[0], 1);
+                if (df_rest_flag[0])
+                    huff_data_1d(gb, data[0] + num_val_ch[0], 1,
+                                 data_type, !diff_freq[0], 0);
+            }
+            if (data[1]) {
+                huff_data_2d(gb, p0_data[1], pair_vec + 1, num_val_ch[1], 2, 
data_type,
+                             diff_freq[1], 1);
+                if (df_rest_flag[1])
+                    huff_data_1d(gb, data[1] + num_val_ch[1], 1,
+                                 data_type, !diff_freq[1], 0);
+            }
+        }
+    } else { /* 1D */
+        if (data[0])
+            huff_data_1d(gb, data[0], num_val, data_type, diff_freq[0], 
diff_freq[0]);
+        if (data[1])
+            huff_data_1d(gb, data[1], num_val, data_type, diff_freq[1], 
diff_freq[0]);
+    }
+
+    return 0;
+}
+
+static void diff_freq_decode(const int16_t *diff, int16_t *out, int nb_val)
+{
+    int i = 0;
+    out[0] = diff[0];
+    for (i = 1; i < nb_val; i++)
+        out[i] = out[i - 1] + diff[i];
+}
+
+static void diff_time_decode_backwards(const int16_t *prev, const int16_t 
*diff,
+                                       int16_t *out, const int mixed_diff_type,
+                                       const int nb_val)
+{
+    if (mixed_diff_type)
+        out[0] = diff[0];
+    for (int i = mixed_diff_type; i < nb_val; i++)
+        out[i] = prev[i] + diff[i];
+}
+
+static void diff_time_decode_forwards(const int16_t *prev, const int16_t *diff,
+                                      int16_t *out, const int mixed_diff_type,
+                                      const int nb_val)
+{
+    if (mixed_diff_type)
+        out[0] = diff[0];
+    for (int i = mixed_diff_type; i < nb_val; i++)
+        out[i] = prev[i] - diff[i];
+}
+
+static void attach_lsb(GetBitContext *gb, int16_t *data_msb,
+                       int offset, int nb_lsb, int nb_val,
+                       int16_t *data)
+{
+    for (int i = 0; i < nb_val; i++) {
+        int msb = data_msb[i];
+        if (nb_lsb > 0) {
+            uint32_t lsb = get_bits(gb, nb_lsb);
+            data[i] = ((msb << nb_lsb) | lsb) - offset;
+        } else {
+            data[i] = msb - offset;
+        }
+    }
+}
+
+static int ec_pair_dec(GetBitContext *gb,
+                       int16_t set1[MPS_MAX_PARAM_BANDS],
+                       int16_t set2[MPS_MAX_PARAM_BANDS], int16_t *last,
+                       enum AACMPSDataType data_type, int start_band, int 
nb_bands,
+                       int pair, int coarse,
+                       int diff_time_back)
+{
+    int attach_lsb_flag = 0;
+    int quant_levels = 0;
+    int quant_offset = 0;
+
+    switch (data_type) {
+    case MPS_CLD:
+        if (coarse) {
+            attach_lsb_flag = 0;
+            quant_levels = 15;
+            quant_offset = 7;
+      } else {
+            attach_lsb_flag = 0;
+            quant_levels = 31;
+            quant_offset = 15;
+        }
+        break;
+    case MPS_ICC:
+        if (coarse) {
+            attach_lsb_flag = 0;
+            quant_levels = 4;
+            quant_offset = 0;
+        } else {
+            attach_lsb_flag = 0;
+            quant_levels = 8;
+            quant_offset = 0;
+        }
+        break;
+    case MPS_IPD:
+        if (!coarse) {
+            attach_lsb_flag = 1;
+            quant_levels = 16;
+            quant_offset = 0;
+        } else {
+            attach_lsb_flag = 0;
+            quant_levels = 8;
+            quant_offset = 0;
+        }
+        break;
+    }
+
+    int16_t last_msb[28] = { 0 };
+    int16_t data_pair[2][28] = { 0 };
+    int16_t data_diff[2][28] = { 0 };
+    int16_t *p_data[2];
+
+    int pcm_coding = get_bits1(gb);
+    if (pcm_coding) { /* bsPcmCoding */
+        int nb_pcm_vals;
+        if (pair) {
+            p_data[0] = data_pair[0];
+            p_data[1] = data_pair[1];
+            nb_pcm_vals = 2 * nb_bands;
+        } else {
+            p_data[0] = data_pair[0];
+            p_data[1] = NULL;
+            nb_pcm_vals = nb_bands;
+        }
+
+        int nb_quant_steps;
+        switch (data_type) {
+        case MPS_CLD: nb_quant_steps = coarse ? 15 : 31; break;
+        case MPS_ICC: nb_quant_steps = coarse ?  4 :  8; break;
+        case MPS_IPD: nb_quant_steps = coarse ?  8 : 16; break;
+        }
+        pcm_decode(gb, p_data[0], p_data[1], quant_offset, nb_pcm_vals,
+                   nb_quant_steps, quant_levels);
+
+        memcpy(&set1[start_band], data_pair[0], 2*nb_bands);
+        if (pair)
+            memcpy(&set2[start_band], data_pair[1], 2*nb_bands);
+
+        return 0;
+    }
+
+    if (pair) {
+        p_data[0] = data_pair[0];
+        p_data[1] = data_pair[1];
+    } else {
+        p_data[0] = data_pair[0];
+        p_data[1] = NULL;
+    }
+
+    int diff_freq[2] = { 1, 1 };
+    int backwards = 1;
+
+    if (pair || diff_time_back)
+        diff_freq[0] = !get_bits1(gb);
+
+    if (pair && (diff_freq[0] || diff_time_back))
+        diff_freq[1] = !get_bits1(gb);
+
+    int time_pair;
+    huff_decode(gb, p_data, data_type, diff_freq,
+                nb_bands, &time_pair);
+
+    /* Differential decoding */
+    if (!diff_freq[0] || !diff_freq[1]) {
+        if (0 /* 1 if SAOC */) {
+            backwards = 1;
+        } else {
+            if (pair) {
+                if (!diff_freq[0] && !diff_time_back)
+                    backwards = 0;
+                else if (!diff_freq[1])
+                    backwards = 1;
+                else
+                    backwards = !get_bits1(gb);
+            } else {
+                backwards = 1;
+            }
+        }
+    }
+
+    int mixed_time_pair = (diff_freq[0] != diff_freq[1]) && time_pair;
+
+    if (backwards) {
+        if (diff_freq[0]) {
+            diff_freq_decode(data_diff[0], data_pair[0], nb_bands);
+        } else {
+            for (int i = 0; i < nb_bands; i++) {
+                last_msb[i] = last[i + start_band] + quant_offset;
+                if (attach_lsb_flag) {
+                    last_msb[i] >>= 1;
+                }
+            }
+            diff_time_decode_backwards(last_msb, data_diff[0], data_pair[0],
+                                       mixed_time_pair, nb_bands);
+        }
+
+        if (diff_freq[1])
+            diff_freq_decode(data_diff[1], data_pair[1], nb_bands);
+        else
+            diff_time_decode_backwards(data_pair[0], data_diff[1],
+                                       data_pair[1], mixed_time_pair, 
nb_bands);
+    } else {
+        diff_freq_decode(data_diff[1], data_pair[1], nb_bands);
+
+        if (diff_freq[0])
+          diff_freq_decode(data_diff[0], data_pair[0], nb_bands);
+        else
+          diff_time_decode_forwards(data_pair[1], data_diff[0], data_pair[0],
+                                    mixed_time_pair, nb_bands);
+    }
+
+    /* Decode LSBs */
+    attach_lsb(gb, p_data[0], quant_offset, attach_lsb_flag,
+               nb_bands, p_data[0]);
+    if (pair)
+        attach_lsb(gb, p_data[1], quant_offset, attach_lsb_flag,
+                   nb_bands, p_data[1]);
+
+    memcpy(&set1[start_band], data_pair[0], 2*nb_bands);
+    if (pair)
+        memcpy(&set2[start_band], data_pair[1], 2*nb_bands);
+
+    return 0;
+}
+
+static void coarse_to_fine(int16_t *data, enum AACMPSDataType data_type,
+                           int start_band, int end_band)
+{
+    for (int i = start_band; i < end_band; i++)
+        data[i] <<= 1;
+    if (data_type == MPS_CLD) {
+        for (int i = start_band; i < end_band; i++) {
+            if (data[i] == -14)
+                data[i] = -15;
+            else if (data[i] == 14)
+                data[i] = 15;
+        }
+    }
+}
+
+static void fine_to_coarse(int16_t *data, enum AACMPSDataType data_type,
+                           int start_band, int end_band)
+{
+    for (int i = start_band; i < end_band; i++) {
+        if (data_type == MPS_CLD)
+            data[i] /= 2;
+        else
+            data[i] >>= 1;
+    }
+}
+
+static int get_freq_strides(int16_t *freq_strides, int band_stride,
+                            int start_band, int end_band)
+{
+    int data_bands = (end_band - start_band - 1) / band_stride + 1;
+
+    freq_strides[0] = start_band;
+    for (int i = 1; i <= data_bands; i++)
+        freq_strides[i] = freq_strides[i - 1] + band_stride;
+
+    int offs = 0;
+    while (freq_strides[data_bands] > end_band) {
+        if (offs < data_bands)
+            offs++;
+        for (int i = offs; i <= data_bands; i++) {
+            freq_strides[i]--;
+        }
+    }
+
+    return data_bands;
+}
+
+static const int stride_table[4] = { 1, 2, 5, 28 };
+
+int ff_aac_ec_data_dec(GetBitContext *gb, AACMPSLosslessData *ld,
+                       enum AACMPSDataType data_type,
+                       int default_val,
+                       int start_band, int end_band, int frame_indep_flag,
+                       int indep_flag, int nb_param_sets)
+{
+    for (int i = 0; i < nb_param_sets; i++) {
+        ld->data_mode[i] = get_bits(gb, 2);
+        /* Error checking */
+        if ((indep_flag && !i && (ld->data_mode[i] == 1 || ld->data_mode[i] == 
2)) ||
+            ((i == (nb_param_sets - 1) && (ld->data_mode[i] == 2)))) {
+            return AVERROR(EINVAL);
+        }
+    }
+
+    int set_idx = 0;
+    int data_pair = 0;
+    bool old_coarse = ld->quant_coarse_prev;
+
+    for (int i = 0; i < nb_param_sets; i++) {
+        if (!ld->data_mode[i]) {
+            for (int j = start_band; j < end_band; j++)
+                ld->last_data[j] = default_val;
+            old_coarse = 0;
+        }
+
+        if (ld->data_mode[i] != 3) {
+            continue;
+        } else if (data_pair) {
+            data_pair = 0;
+            continue;
+        }
+
+        data_pair = get_bits1(gb);
+        ld->coarse_quant[set_idx] = get_bits1(gb);
+        ld->freq_res[set_idx] = get_bits(gb, 2);
+
+        if (ld->coarse_quant[set_idx] != old_coarse) {
+            if (old_coarse)
+                coarse_to_fine(ld->last_data, data_type, start_band, end_band);
+            else
+                fine_to_coarse(ld->last_data, data_type, start_band, end_band);
+        }
+
+        int data_bands = get_freq_strides(ld->freq_res,
+                                          stride_table[ld->freq_res[set_idx]],
+                                          start_band, end_band);
+
+        if (set_idx + data_pair > MPS_MAX_PARAM_SETS)
+            return AVERROR(EINVAL);
+
+        for (int j = 0; j < data_bands; j++)
+            ld->last_data[start_band + j] = ld->last_data[ld->freq_res[j]];
+
+        int err = ec_pair_dec(gb,
+                              ld->data[set_idx + 0], ld->data[set_idx + 1],
+                              ld->last_data, data_type, start_band, end_band - 
start_band,
+                              data_pair, ld->coarse_quant[set_idx],
+                              !(indep_flag && (i == 0)) || (set_idx > 0));
+        if (err < 0)
+            return err;
+
+        if (data_type == MPS_IPD) {
+            const int mask = ld->coarse_quant[set_idx] ? 0x7 : 0xF;
+            for (int j = 0; j < data_bands; j++)
+                for (int k = ld->freq_res[j + 0]; k < ld->freq_res[j + 1]; k++)
+                    ld->last_data[k] = ld->data[set_idx + 
data_pair][start_band + j] & mask;
+        } else {
+            for (int j = 0; j < data_bands; j++)
+                for (int k = ld->freq_res[j + 0]; k < ld->freq_res[j + 1]; k++)
+                    ld->last_data[k] = ld->data[set_idx + 
data_pair][start_band + j];
+        }
+
+        old_coarse = ld->coarse_quant[set_idx];
+        if (data_pair) {
+            ld->coarse_quant[set_idx + 1] = ld->coarse_quant[set_idx];
+            ld->freq_res[set_idx + 1] = ld->freq_res[set_idx];
+        }
+        set_idx += data_pair + 1;
+    }
+
+    ld->quant_coarse_prev = old_coarse;
+
+    return 0;
+}
+
+int ff_aac_huff_dec_reshape(GetBitContext *gb, int16_t *out_data,
+                            int nb_val)
+{
+    int val, len;
+    int val_received = 0;
+    int16_t rl_data[2] = { 0 };
+
+    while (val_received < nb_val) {
+        huff_dec_2D(gb, ff_aac_hcod2D_reshape, rl_data);
+        val = rl_data[0];
+        len = rl_data[1] + 1;
+        if (val_received + len > nb_val)
+            return AVERROR(EINVAL);
+        for (int i = val_received; i < val_received + len; i++)
+            out_data[i] = val;
+        val_received += len;
+    }
+
+    return 0;
+}
+
+static void create_mapping(int map[MPS_MAX_PARAM_BANDS + 1],
+                           int start_band, int stop_band, int stride)
+{
+    int diff[MPS_MAX_PARAM_BANDS + 1];
+    int src_bands = stop_band - start_band;
+    int dst_bands = (src_bands - 1) / stride + 1;
+
+    if (dst_bands < 1)
+        dst_bands = 1;
+
+    int bands_achived = dst_bands * stride;
+    int bands_diff = src_bands - bands_achived;
+    for (int i = 0; i < dst_bands; i++)
+        diff[i] = stride;
+
+    int incr, k;
+    if (bands_diff > 0) {
+        incr = -1;
+        k = dst_bands - 1;
+    } else {
+        incr = 1;
+        k = 0;
+    }
+
+    while (bands_diff != 0) {
+        diff[k] = diff[k] - incr;
+        k = k + incr;
+        bands_diff = bands_diff + incr;
+        if (k >= dst_bands) {
+            if (bands_diff > 0) {
+                k = dst_bands - 1;
+            } else if (bands_diff < 0) {
+                k = 0;
+            }
+        }
+    }
+
+    map[0] = start_band;
+    for (int i = 0; i < dst_bands; i++)
+        map[i + 1] = map[i] + diff[i];
+}
+
+static void map_freq(int16_t *dst, const int16_t *src,
+                     int *map, int nb_bands)
+{
+    for (int i = 0; i < nb_bands; i++) {
+        int value = src[i + map[0]];
+        int start_band = map[i];
+        int stop_band = map[i + 1];
+        for (int j = start_band; j < stop_band; j++) {
+            dst[j] = value;
+        }
+    }
+}
+
+static int deq_idx(int value, enum AACMPSDataType data_type)
+{
+    int idx = -1;
+
+    switch (data_type) {
+    case MPS_CLD:
+        if (((value + 15) >= 0) && ((value + 15) < 31))
+            idx = (value + 15);
+        break;
+    case MPS_ICC:
+        if ((value >= 0) && (value < 8))
+        idx = value;
+        break;
+    case MPS_IPD:
+        /* (+/-)15 * MAX_PARAMETER_BANDS for differential coding in frequency
+         * domain (according to rbl) */
+      if ((value >= -420) && (value <= 420))
+          idx = (value & 0xf);
+        break;
+    }
+
+    return idx;
+}
+
+int ff_aac_map_index_data(AACMPSLosslessData *ld, int **dst_idx,
+                          int paramIdx, enum AACMPSDataType data_type,
+                          int start_band, int stop_band, int default_value,
+                          int nb_param_sets, const int *param_set_idx,
+                          int extend_frame)
+{
+    if (nb_param_sets > MPS_MAX_PARAM_SETS)
+        return AVERROR(EINVAL);
+
+    int data_mode_3_idx[MPS_MAX_PARAM_SETS];
+    int nb_data_mode_3 = 0;
+    for (int i = 0; i < nb_param_sets; i++) {
+        if (ld->data_mode[i] == 3) {
+            data_mode_3_idx[nb_data_mode_3] = i;
+            nb_data_mode_3++;
+        }
+    }
+
+    int set_idx = 0;
+
+    /* Prepare data */
+    int interpolate[MPS_MAX_PARAM_SETS] = { 0 };
+    int16_t tmp_idx_data[MPS_MAX_PARAM_SETS][MPS_MAX_PARAM_BANDS];
+    for (int i = 0; i < nb_param_sets; i++) {
+        if (ld->data_mode[i] == 0) {
+            ld->coarse_quant_no[i] = 0;
+            for (int band = start_band; band < stop_band; band++) {
+                tmp_idx_data[i][band] = default_value;
+            }
+            for (int band = start_band; band < stop_band; band++) {
+                ld->last_data[band] = tmp_idx_data[i][band];
+            }
+            ld->quant_coarse_prev = 0;
+        }
+
+        if (ld->data_mode[i] == 1) {
+            for (int band = start_band; band < stop_band; band++) {
+                tmp_idx_data[i][band] = ld->last_data[band];
+            }
+            ld->coarse_quant_no[i] = ld->quant_coarse_prev;
+        }
+
+        if (ld->data_mode[i] == 2) {
+            for (int band = start_band; band < stop_band; band++) {
+                tmp_idx_data[i][band] = ld->last_data[band];
+            }
+            ld->coarse_quant_no[i] = ld->quant_coarse_prev;
+            interpolate[i] = 1;
+        } else {
+            interpolate[i] = 0;
+        }
+
+        if (ld->data_mode[i] == 3) {
+            int stride;
+
+            int parmSlot = data_mode_3_idx[set_idx];
+            stride = stride_table[ld->freq_res[set_idx]];
+            int dataBands = (stop_band - start_band - 1) / stride + 1;
+
+            int tmp[MPS_MAX_PARAM_BANDS + 1];
+            create_mapping(tmp, start_band, stop_band, stride);
+            map_freq(tmp_idx_data[parmSlot], ld->data[set_idx],
+                     tmp, dataBands);
+
+            for (int band = start_band; band < stop_band; band++)
+                ld->last_data[band] = tmp_idx_data[parmSlot][band];
+
+            ld->quant_coarse_prev = ld->coarse_quant[set_idx];
+            ld->coarse_quant_no[i] = ld->coarse_quant[set_idx];
+
+            set_idx++;
+        }
+    }
+
+    /* Map all coarse data to fine */
+    for (int i = 0; i < nb_param_sets; i++) {
+        if (ld->coarse_quant_no[i] == 1) {
+            coarse_to_fine(tmp_idx_data[i], data_type, start_band,
+                           stop_band - start_band);
+            ld->coarse_quant_no[i] = 0;
+        }
+    }
+
+    /* Interpolate */
+    int i1 = 0;
+    for (int i = 0; i < nb_param_sets; i++) {
+        if (interpolate[i] != 1) {
+            i1 = i;
+        } else {
+            int xi, i2, x1, x2;
+
+            for (i2 = i; i2 < nb_param_sets; i2++)
+                if (interpolate[i2] != 1)
+                    break;
+            if (i2 >= nb_param_sets)
+                return AVERROR(EINVAL);
+
+            x1 = param_set_idx[i1];
+            xi = param_set_idx[i];
+            x2 = param_set_idx[i2];
+
+            for (int band = start_band; band < stop_band; band++) {
+                int yi, y1, y2;
+                y1 = tmp_idx_data[i1][band];
+                y2 = tmp_idx_data[i2][band];
+                if (x1 != x2) {
+                    yi = y1 + (xi - x1) * (y2 - y1) / (x2 - x1);
+                } else {
+                    yi = y1 /*+ (xi-x1)*(y2-y1)/1e-12*/;
+                }
+                tmp_idx_data[i][band] = yi;
+            }
+        }
+    }
+
+    /* Dequantize data and apply factorCLD if necessary */
+    for (int ps = 0; ps < nb_param_sets; ps++) {
+        /* Dequantize data */
+        for (int band = start_band; band < stop_band; band++) {
+            dst_idx[ps][band] = deq_idx(tmp_idx_data[ps][band],
+                                        data_type);
+            if (dst_idx[ps][band] == -1)
+                dst_idx[ps][band] = default_value;
+        }
+    }
+
+    if (extend_frame) {
+        if (data_type == MPS_IPD)
+            ld->coarse_quant[nb_param_sets] = ld->coarse_quant[nb_param_sets - 
1];
+        for (int band = start_band; band < stop_band; band++)
+            dst_idx[nb_param_sets][band] = dst_idx[nb_param_sets - 1][band];
+    }
+
+    return 0;
+}
diff --git a/libavcodec/aac/aacdec_usac_mps212.h 
b/libavcodec/aac/aacdec_usac_mps212.h
new file mode 100644
index 0000000000..33299509bb
--- /dev/null
+++ b/libavcodec/aac/aacdec_usac_mps212.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2025 Lynne <[email protected]>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVCODEC_AAC_AACDEC_USAC_MPS212_H
+#define AVCODEC_AAC_AACDEC_USAC_MPS212_H
+
+#include <stdbool.h>
+
+#include "libavcodec/get_bits.h"
+#include "libavcodec/aac.h"
+
+enum AACMPSDataType {
+    MPS_CLD = 0,
+    MPS_ICC,
+    MPS_IPD,
+
+    MPS_ELE_NB,
+};
+
+typedef struct AACMPSLosslessData {
+    int16_t data[MPS_MAX_PARAM_SETS][MPS_MAX_PARAM_BANDS];
+    int16_t last_data[MPS_MAX_PARAM_BANDS];
+
+    int16_t data_mode[MPS_MAX_PARAM_SETS];
+    bool coarse_quant[MPS_MAX_PARAM_SETS];
+    int16_t freq_res[MPS_MAX_PARAM_SETS];
+    int16_t coarse_quant_no[MPS_MAX_PARAM_SETS];
+
+    bool quant_coarse_prev;
+} AACMPSLosslessData;
+
+int ff_aac_ec_data_dec(GetBitContext *gb, AACMPSLosslessData *ld,
+                       enum AACMPSDataType data_type,
+                       int default_val,
+                       int start_band, int end_band, int frame_indep_flag,
+                       int indep_flag, int nb_param_sets);
+
+int ff_aac_map_index_data(AACMPSLosslessData *ld, int **dst_idx,
+                          int paramIdx, enum AACMPSDataType data_type,
+                          int start_band, int stop_band, int default_value,
+                          int nb_param_sets, const int *param_set_idx,
+                          int extend_frame);
+
+int ff_aac_huff_dec_reshape(GetBitContext *gb, int16_t *out_data,
+                            int nb_val);
+
+#endif /* AVCODEC_AAC_AACDEC_USAC_MPS212_H */
-- 
2.52.0

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

Reply via email to