This is an automated email from the git hooks/post-receive script.

Git pushed a commit to branch master
in repository ffmpeg.

commit baad75cafa6bac298b72c177f657a2eb8e31cff1
Author:     Lynne <[email protected]>
AuthorDate: Mon Nov 17 06:29:19 2025 +0100
Commit:     Lynne <[email protected]>
CommitDate: Mon Feb 23 07:57:57 2026 +0100

    aacdec_usac: add support for parsing Mpsp212 (MPEG surround)
    
    This commit adds the full bitstream parsing for Mps212.
---
 libavcodec/aac.h                    |   4 +
 libavcodec/aac/Makefile             |   3 +-
 libavcodec/aac/aacdec.h             |  31 ++
 libavcodec/aac/aacdec_usac.c        | 173 ++++++-
 libavcodec/aac/aacdec_usac_mps212.c | 909 ++++++++++++++++++++++++++++++++++++
 libavcodec/aac/aacdec_usac_mps212.h |  65 +++
 6 files changed, 1180 insertions(+), 5 deletions(-)

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..9785576680 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,33 @@ 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];
+    int ott_idx[MPS_ELE_NB][MPS_MAX_PARAM_SETS][MPS_MAX_PARAM_BANDS];
+    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 +272,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 +362,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..bed9747e9c 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,164 @@ 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;
+    int nb_time_slots = usac->core_sbr_frame_len_idx == 4 ? 64 : 32;
+
+    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);
+
+    int extend_frame = mps->param_sets[mps->nb_param_sets - 1] !=
+                       (nb_time_slots - 1);
+
+    /* CLD */
+    err = ff_aac_ec_data_dec(gb, &mps->ott[MPS_CLD], MPS_CLD,
+                             0, 0, nb_bands,
+                             indep, indep, mps->nb_param_sets);
+    if (err < 0) {
+        av_log(ac->avctx, AV_LOG_ERROR, "Error parsing OTT CLD data!\n");
+        return err;
+    }
+    ff_aac_map_index_data(&mps->ott[MPS_CLD], MPS_CLD, mps->ott_idx[MPS_CLD],
+                          0, 0, nb_bands, mps->nb_param_sets,
+                          mps->param_sets, extend_frame);
+
+    /* ICC */
+    err = ff_aac_ec_data_dec(gb, &mps->ott[MPS_ICC], MPS_ICC, 0, 0, nb_bands,
+                             indep, indep, mps->nb_param_sets);
+    if (err < 0) {
+        av_log(ac->avctx, AV_LOG_ERROR, "Error parsing OTT ICC data!\n");
+        return err;
+    }
+    ff_aac_map_index_data(&mps->ott[MPS_ICC], MPS_ICC, mps->ott_idx[MPS_ICC],
+                          0, 0, nb_bands, mps->nb_param_sets,
+                          mps->param_sets, extend_frame);
+
+    /* IPD */
+    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,
+                                     indep, indep, mps->nb_param_sets);
+            ff_aac_map_index_data(&mps->ott[MPS_IPD], MPS_IPD, 
mps->ott_idx[MPS_IPD],
+                                  0, 0, nb_bands, mps->nb_param_sets,
+                                  mps->param_sets, extend_frame);
+            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 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 +1627,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 +1647,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..17f570c518
--- /dev/null
+++ b/libavcodec/aac/aacdec_usac_mps212.c
@@ -0,0 +1,909 @@
+/*
+ * 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])
+{
+    int 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];
+        if (data_bands == 1)
+            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]);
+    }
+}
+
+/* NB: NOT a standard integer log2! */
+static int mps_log2(int s) {
+    if (s)
+        s--;
+    int v = 0;
+    while (s) {
+        s >>= 1;
+        v++;
+    }
+    return v;
+}
+
+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] = mps_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[1]);
+    }
+
+    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,
+                          enum AACMPSDataType data_type,
+                          int dst_idx[MPS_MAX_PARAM_SETS][MPS_MAX_PARAM_BANDS],
+                          int default_value, int start_band, int stop_band,
+                          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..a14e479547
--- /dev/null
+++ b/libavcodec/aac/aacdec_usac_mps212.h
@@ -0,0 +1,65 @@
+/*
+ * 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,
+                          enum AACMPSDataType data_type,
+                          int dst_idx[MPS_MAX_PARAM_SETS][MPS_MAX_PARAM_BANDS],
+                          int default_value, int start_band, int stop_band,
+                          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 */

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

Reply via email to