Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
 help / color / mirror / Atom feed
* [FFmpeg-devel] [PATCH] A few new decoders and a parser from almpeg (PR #20325)
@ 2025-08-24  3:01 michaelni via ffmpeg-devel
  0 siblings, 0 replies; only message in thread
From: michaelni via ffmpeg-devel @ 2025-08-24  3:01 UTC (permalink / raw)
  To: ffmpeg-devel; +Cc: michaelni

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

These are taken from before the switch to GPLv3+
If people prefer, we can merge the GPLv3+ switch for these modules too and put them under --enable-gpl and --enable-v3


From 560ebf42e09e4e378c420908f2eed81d893f9df6 Mon Sep 17 00:00:00 2001
From: Paul B Mahol <onemda@gmail.com>
Date: Mon, 18 Nov 2024 19:04:23 +0000
Subject: [PATCH 01/15] avcodec: add AHX decoder

(cherry picked from commit 039dc23d185214b8b0ef2bbccae197ceb5ad42a2)
---
 libavcodec/Makefile                |  1 +
 libavcodec/allcodecs.c             |  1 +
 libavcodec/bitstream_filters.c     |  1 +
 libavcodec/bsf/Makefile            |  1 +
 libavcodec/bsf/ahx_to_mp2.c        | 62 ++++++++++++++++++++++++++++++
 libavcodec/codec_desc.c            |  7 ++++
 libavcodec/codec_id.h              |  1 +
 libavcodec/mpegaudiodec_float.c    | 18 +++++++++
 libavcodec/mpegaudiodec_template.c |  3 +-
 9 files changed, 94 insertions(+), 1 deletion(-)
 create mode 100644 libavcodec/bsf/ahx_to_mp2.c

diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 3d036de4b6..e1cce1275b 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -219,6 +219,7 @@ OBJS-$(CONFIG_AC3_FIXED_ENCODER)       += ac3enc_fixed.o ac3enc.o ac3tab.o ac3.o
 OBJS-$(CONFIG_AC3_MF_ENCODER)          += mfenc.o mf_utils.o
 OBJS-$(CONFIG_ACELP_KELVIN_DECODER)    += g729dec.o lsp.o celp_filters.o acelp_filters.o acelp_pitch_delay.o acelp_vectors.o g729postfilter.o
 OBJS-$(CONFIG_AGM_DECODER)             += agm.o jpegquanttables.o
+OBJS-$(CONFIG_AHX_DECODER)             += mpegaudiodec_float.o
 OBJS-$(CONFIG_AIC_DECODER)             += aic.o
 OBJS-$(CONFIG_ALAC_DECODER)            += alac.o alac_data.o alacdsp.o
 OBJS-$(CONFIG_ALAC_ENCODER)            += alacenc.o alac_data.o
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index f5ec2e01e8..017d100848 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -434,6 +434,7 @@ extern const FFCodec ff_ac3_decoder;
 extern const FFCodec ff_ac3_fixed_encoder;
 extern const FFCodec ff_ac3_fixed_decoder;
 extern const FFCodec ff_acelp_kelvin_decoder;
+extern const FFCodec ff_ahx_decoder;
 extern const FFCodec ff_alac_encoder;
 extern const FFCodec ff_alac_decoder;
 extern const FFCodec ff_als_decoder;
diff --git a/libavcodec/bitstream_filters.c b/libavcodec/bitstream_filters.c
index c277bc1a71..b4b852c7e6 100644
--- a/libavcodec/bitstream_filters.c
+++ b/libavcodec/bitstream_filters.c
@@ -25,6 +25,7 @@
 #include "bsf_internal.h"
 
 extern const FFBitStreamFilter ff_aac_adtstoasc_bsf;
+extern const FFBitStreamFilter ff_ahx_to_mp2_bsf;
 extern const FFBitStreamFilter ff_apv_metadata_bsf;
 extern const FFBitStreamFilter ff_av1_frame_merge_bsf;
 extern const FFBitStreamFilter ff_av1_frame_split_bsf;
diff --git a/libavcodec/bsf/Makefile b/libavcodec/bsf/Makefile
index 8e2e6f7b14..48a2f85ac7 100644
--- a/libavcodec/bsf/Makefile
+++ b/libavcodec/bsf/Makefile
@@ -3,6 +3,7 @@ clean::
 
 OBJS-$(CONFIG_AAC_ADTSTOASC_BSF)          += bsf/aac_adtstoasc.o
 OBJS-$(CONFIG_APV_METADATA_BSF)           += bsf/apv_metadata.o
+OBJS-$(CONFIG_AHX_TO_MP2_BSF)             += bsf/ahx_to_mp2.o
 OBJS-$(CONFIG_AV1_FRAME_MERGE_BSF)        += bsf/av1_frame_merge.o
 OBJS-$(CONFIG_AV1_FRAME_SPLIT_BSF)        += bsf/av1_frame_split.o
 OBJS-$(CONFIG_AV1_METADATA_BSF)           += bsf/av1_metadata.o
diff --git a/libavcodec/bsf/ahx_to_mp2.c b/libavcodec/bsf/ahx_to_mp2.c
new file mode 100644
index 0000000000..eae71fe5ee
--- /dev/null
+++ b/libavcodec/bsf/ahx_to_mp2.c
@@ -0,0 +1,62 @@
+/*
+ * AHX to MP2 bitstream filter
+ * Copyright (c) 2024 Paul B Mahol
+ *
+ * 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
+ */
+
+/**
+ * @file
+ * AHX to MP2 bitstream filter.
+ */
+
+#include "libavutil/intreadwrite.h"
+#include "bsf.h"
+#include "bsf_internal.h"
+
+static av_cold int init(AVBSFContext *ctx)
+{
+    ctx->par_out->codec_id = AV_CODEC_ID_MP2;
+
+    return 0;
+}
+
+static int filter(AVBSFContext *ctx, AVPacket *pkt)
+{
+    int ret;
+
+    ret = ff_bsf_get_packet_ref(ctx, pkt);
+    if (ret < 0)
+        return ret;
+
+    if (pkt->size < 1044) {
+        ret = av_grow_packet(pkt, 1044-pkt->size);
+        if (ret < 0) {
+            av_packet_unref(pkt);
+            return ret;
+        }
+    }
+
+    return 0;
+}
+
+const FFBitStreamFilter ff_ahx_to_mp2_bsf = {
+    .p.name         = "ahx_to_mp2",
+    .p.codec_ids    = (const enum AVCodecID []){ AV_CODEC_ID_AHX, AV_CODEC_ID_NONE },
+    .init           = init,
+    .filter         = filter,
+};
diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c
index a065556e51..284d1861c4 100644
--- a/libavcodec/codec_desc.c
+++ b/libavcodec/codec_desc.c
@@ -3495,6 +3495,13 @@ static const AVCodecDescriptor codec_descriptors[] = {
         .long_name = NULL_IF_CONFIG_SMALL("G.728"),
         .props     = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY,
     },
+    {
+        .id        = AV_CODEC_ID_AHX,
+        .type      = AVMEDIA_TYPE_AUDIO,
+        .name      = "ahx",
+        .long_name = NULL_IF_CONFIG_SMALL("CRI AHX"),
+        .props     = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY,
+    },
 
     /* subtitle codecs */
     {
diff --git a/libavcodec/codec_id.h b/libavcodec/codec_id.h
index c4842e61ff..455bc4b839 100644
--- a/libavcodec/codec_id.h
+++ b/libavcodec/codec_id.h
@@ -556,6 +556,7 @@ enum AVCodecID {
     AV_CODEC_ID_QOA,
     AV_CODEC_ID_LC3,
     AV_CODEC_ID_G728,
+    AV_CODEC_ID_AHX,
 
     /* subtitle codecs */
     AV_CODEC_ID_FIRST_SUBTITLE = 0x17000,          ///< A dummy ID pointing at the start of subtitle codecs.
diff --git a/libavcodec/mpegaudiodec_float.c b/libavcodec/mpegaudiodec_float.c
index 05e2e399e4..232e2fa201 100644
--- a/libavcodec/mpegaudiodec_float.c
+++ b/libavcodec/mpegaudiodec_float.c
@@ -103,6 +103,24 @@ const FFCodec ff_mp2float_decoder = {
     CODEC_SAMPLEFMTS(AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_FLT),
 };
 #endif
+#if CONFIG_AHX_DECODER
+const FFCodec ff_ahx_decoder = {
+    .p.name         = "ahx",
+    CODEC_LONG_NAME("CRI AHX"),
+    .p.type         = AVMEDIA_TYPE_AUDIO,
+    .p.id           = AV_CODEC_ID_AHX,
+    .priv_data_size = sizeof(MPADecodeContext),
+    .init           = decode_init,
+    FF_CODEC_DECODE_CB(decode_frame),
+    .p.capabilities = AV_CODEC_CAP_CHANNEL_CONF |
+                      AV_CODEC_CAP_DR1,
+    .flush          = flush,
+    .p.sample_fmts  = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP,
+                                                      AV_SAMPLE_FMT_FLT,
+                                                      AV_SAMPLE_FMT_NONE },
+    .bsfs           = "ahx_to_mp2",
+};
+#endif
 #if CONFIG_MP3FLOAT_DECODER
 const FFCodec ff_mp3float_decoder = {
     .p.name         = "mp3float",
diff --git a/libavcodec/mpegaudiodec_template.c b/libavcodec/mpegaudiodec_template.c
index d7c5210eb8..005e9ba2fa 100644
--- a/libavcodec/mpegaudiodec_template.c
+++ b/libavcodec/mpegaudiodec_template.c
@@ -1604,7 +1604,8 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *frame,
     if (ret >= 0) {
         s->frame->nb_samples = avctx->frame_size;
         *got_frame_ptr       = 1;
-        avctx->sample_rate   = s->sample_rate;
+        if (avctx->codec_id != AV_CODEC_ID_AHX)
+            avctx->sample_rate = s->sample_rate;
         //FIXME maybe move the other codec info stuff from above here too
     } else {
         av_log(avctx, AV_LOG_ERROR, "Error while decoding MPEG audio frame.\n");
-- 
2.49.1


From 8a11b844ff4fb4596be42ac9714060f718426212 Mon Sep 17 00:00:00 2001
From: Paul B Mahol <onemda@gmail.com>
Date: Tue, 19 Nov 2024 09:20:52 +0000
Subject: [PATCH 02/15] avcodec: add AHX parser

(cherry picked from commit ddcb47c4c512bf49b22cc6b2d07fade0f96377e3)
---
 libavcodec/Makefile     |  1 +
 libavcodec/ahx_parser.c | 78 +++++++++++++++++++++++++++++++++++++++++
 libavcodec/parsers.c    |  1 +
 3 files changed, 80 insertions(+)
 create mode 100644 libavcodec/ahx_parser.c

diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index e1cce1275b..3005e4a31a 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -1217,6 +1217,7 @@ OBJS-$(CONFIG_AAC_PARSER)              += aac_parser.o aac_ac3_parser.o
 OBJS-$(CONFIG_AC3_PARSER)              += aac_ac3_parser.o ac3tab.o \
                                           ac3_channel_layout_tab.o
 OBJS-$(CONFIG_ADX_PARSER)              += adx_parser.o
+OBJS-$(CONFIG_AHX_PARSER)              += ahx_parser.o
 OBJS-$(CONFIG_AMR_PARSER)              += amr_parser.o
 OBJS-$(CONFIG_APV_PARSER)              += apv_parser.o
 OBJS-$(CONFIG_AV1_PARSER)              += av1_parser.o av1_parse.o
diff --git a/libavcodec/ahx_parser.c b/libavcodec/ahx_parser.c
new file mode 100644
index 0000000000..4be037f666
--- /dev/null
+++ b/libavcodec/ahx_parser.c
@@ -0,0 +1,78 @@
+/*
+ * 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
+ */
+
+/**
+ * @file
+ * AHX audio parser
+ *
+ * Splits packets into individual blocks.
+ */
+
+#include "libavutil/intreadwrite.h"
+#include "parser.h"
+
+typedef struct AHXParseContext {
+    ParseContext pc;
+    uint32_t header;
+    int size;
+} AHXParseContext;
+
+static int ahx_parse(AVCodecParserContext *s1,
+                     AVCodecContext *avctx,
+                     const uint8_t **poutbuf, int *poutbuf_size,
+                     const uint8_t *buf, int buf_size)
+{
+    AHXParseContext *s = s1->priv_data;
+    ParseContext *pc = &s->pc;
+    uint32_t state = pc->state;
+    int next = END_NOT_FOUND;
+
+    for (int i = 0; i < buf_size; i++) {
+        state = (state << 8) | buf[i];
+        s->size++;
+        if (s->size == 4 && !s->header)
+            s->header = state;
+        if (s->size > 4 && state == s->header) {
+            next = i - 3;
+            s->size = 0;
+            break;
+        }
+    }
+    pc->state = state;
+
+    if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) {
+        *poutbuf      = NULL;
+        *poutbuf_size = 0;
+        return buf_size;
+    }
+
+    s1->duration = 1152;
+    s1->key_frame = 1;
+
+    *poutbuf = buf;
+    *poutbuf_size = buf_size;
+
+    return next;
+}
+
+const AVCodecParser ff_ahx_parser = {
+    .codec_ids      = { AV_CODEC_ID_AHX },
+    .priv_data_size = sizeof(AHXParseContext),
+    .parser_parse   = ahx_parse,
+    .parser_close   = ff_parse_close,
+};
diff --git a/libavcodec/parsers.c b/libavcodec/parsers.c
index b12c48f79f..42b40643f9 100644
--- a/libavcodec/parsers.c
+++ b/libavcodec/parsers.c
@@ -24,6 +24,7 @@ extern const AVCodecParser ff_aac_parser;
 extern const AVCodecParser ff_aac_latm_parser;
 extern const AVCodecParser ff_ac3_parser;
 extern const AVCodecParser ff_adx_parser;
+extern const AVCodecParser ff_ahx_parser;
 extern const AVCodecParser ff_amr_parser;
 extern const AVCodecParser ff_apv_parser;
 extern const AVCodecParser ff_av1_parser;
-- 
2.49.1


From 87faa2fa9048f6edd6ed45f285e9dcfa735600b9 Mon Sep 17 00:00:00 2001
From: Paul B Mahol <onemda@gmail.com>
Date: Sun, 1 Aug 2021 21:12:55 +0200
Subject: [PATCH 03/15] avcodec: add ADPCM IMA HVQM4 decoder

Signed-off-by: Paul B Mahol <onemda@gmail.com>
(cherry picked from commit bae3cecfa6f1fbc765d95d84ef4a377aedbca8bb)
---
 libavcodec/Makefile     |  1 +
 libavcodec/adpcm.c      | 64 +++++++++++++++++++++++++++++++++++++++++
 libavcodec/allcodecs.c  |  1 +
 libavcodec/codec_desc.c |  7 +++++
 libavcodec/codec_id.h   |  1 +
 5 files changed, 74 insertions(+)

diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 3005e4a31a..6311cd1821 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -984,6 +984,7 @@ OBJS-$(CONFIG_ADPCM_IMA_DK3_DECODER)      += adpcm.o adpcm_data.o
 OBJS-$(CONFIG_ADPCM_IMA_DK4_DECODER)      += adpcm.o adpcm_data.o
 OBJS-$(CONFIG_ADPCM_IMA_EA_EACS_DECODER)  += adpcm.o adpcm_data.o
 OBJS-$(CONFIG_ADPCM_IMA_EA_SEAD_DECODER)  += adpcm.o adpcm_data.o
+OBJS-$(CONFIG_ADPCM_IMA_HVMQ4_DECODER)    += adpcm.o adpcm_data.o
 OBJS-$(CONFIG_ADPCM_IMA_ISS_DECODER)      += adpcm.o adpcm_data.o
 OBJS-$(CONFIG_ADPCM_IMA_MOFLEX_DECODER)   += adpcm.o adpcm_data.o
 OBJS-$(CONFIG_ADPCM_IMA_MTF_DECODER)      += adpcm.o adpcm_data.o
diff --git a/libavcodec/adpcm.c b/libavcodec/adpcm.c
index 4c15be6207..bc3b0c9730 100644
--- a/libavcodec/adpcm.c
+++ b/libavcodec/adpcm.c
@@ -544,6 +544,49 @@ int16_t ff_adpcm_ima_qt_expand_nibble(ADPCMChannelStatus *c, int nibble)
     return c->predictor;
 }
 
+static void decode_adpcm_ima_hvqm4(AVCodecContext *avctx, int16_t *outbuf, int samples_to_do,
+                                   int frame_format, GetByteContext *gb)
+{
+    ADPCMDecodeContext *c = avctx->priv_data;
+    int st = avctx->ch_layout.nb_channels == 2;
+    unsigned tmp;
+
+    for (int ch = 0; ch < avctx->ch_layout.nb_channels; ch++) {
+        switch (frame_format) {
+        case 1: /* combined hist+index */
+            tmp = bytestream2_get_be16(gb);
+            c->status[ch].predictor  = sign_extend(tmp & 0xFF80, 16);
+            c->status[ch].step_index = tmp & 0x7f;
+            break;
+        case 2:  /* no hist/index (continues from previous frame) */
+        default:
+            break;
+        case 3: /* separate hist+index */
+            tmp = bytestream2_get_be16(gb);
+            c->status[ch].predictor  = sign_extend(tmp, 16);
+            c->status[ch].step_index = bytestream2_get_byte(gb);
+            break;
+        }
+
+        c->status[ch].step_index = av_clip(c->status[ch].step_index, 0, 88);
+    }
+
+    if (frame_format == 1 || frame_format == 3) {
+        for (int ch = 0; ch < avctx->ch_layout.nb_channels; ch++)
+            *outbuf++ = (int16_t)c->status[st - ch].predictor;
+        samples_to_do--;
+    }
+
+    for (int i = 0; i < samples_to_do; i++) {
+        uint8_t nibble = bytestream2_get_byte(gb);
+
+        *outbuf++ = ff_adpcm_ima_qt_expand_nibble(&c->status[st], nibble & 0xF);
+        *outbuf++ = ff_adpcm_ima_qt_expand_nibble(&c->status[ 0], nibble >>  4);
+    }
+
+    bytestream2_seek(gb, 0, SEEK_END);
+}
+
 static inline int16_t adpcm_ms_expand_nibble(ADPCMChannelStatus *c, int nibble)
 {
     int predictor;
@@ -1100,6 +1143,20 @@ static int get_nb_samples(AVCodecContext *avctx, GetByteContext *gb,
         *coded_samples -= *coded_samples % 28;
         nb_samples      = (buf_size - 12) / (ch == 2 ? 30 : 15) * 28;
         break;
+    case AV_CODEC_ID_ADPCM_IMA_HVQM4:
+        {
+            int frame_format = bytestream2_get_be16(gb);
+            int skip = 6;
+
+            if (frame_format == 1)
+                skip += 2 * ch;
+            if (frame_format == 3)
+                skip += 3 * ch;
+
+            nb_samples = (buf_size - skip) * 2 / ch;
+            bytestream2_seek(gb, 0, SEEK_SET);
+        }
+        break;
     case AV_CODEC_ID_ADPCM_IMA_EA_EACS:
         has_coded_samples = 1;
         *coded_samples = bytestream2_get_le32(gb);
@@ -1686,6 +1743,12 @@ static int adpcm_decode_frame(AVCodecContext *avctx, AVFrame *frame,
             *samples++ = adpcm_ima_expand_nibble(&c->status[st], v & 0x0F, 3);
         }
         ) /* End of CASE */
+    CASE(ADPCM_IMA_HVQM4,
+        int format = bytestream2_get_be16(&gb);
+
+        bytestream2_skip(&gb, 4);
+        decode_adpcm_ima_hvqm4(avctx, samples, nb_samples, format, &gb);
+        ) /* End of CASE */
     CASE(ADPCM_IMA_SSI,
         for (int n = nb_samples >> (1 - st); n > 0; n--) {
             int v = bytestream2_get_byteu(&gb);
@@ -2636,6 +2699,7 @@ ADPCM_DECODER(ADPCM_IMA_DK3,     sample_fmts_s16,  adpcm_ima_dk3,     "ADPCM IMA
 ADPCM_DECODER(ADPCM_IMA_DK4,     sample_fmts_s16,  adpcm_ima_dk4,     "ADPCM IMA Duck DK4")
 ADPCM_DECODER(ADPCM_IMA_EA_EACS, sample_fmts_s16,  adpcm_ima_ea_eacs, "ADPCM IMA Electronic Arts EACS")
 ADPCM_DECODER(ADPCM_IMA_EA_SEAD, sample_fmts_s16,  adpcm_ima_ea_sead, "ADPCM IMA Electronic Arts SEAD")
+ADPCM_DECODER(ADPCM_IMA_HVQM4,   sample_fmts_s16,  adpcm_ima_hvqm4,   "ADPCM IMA HVQM4")
 ADPCM_DECODER(ADPCM_IMA_ISS,     sample_fmts_s16,  adpcm_ima_iss,     "ADPCM IMA Funcom ISS")
 ADPCM_DECODER(ADPCM_IMA_MOFLEX,  sample_fmts_s16p, adpcm_ima_moflex,  "ADPCM IMA MobiClip MOFLEX")
 ADPCM_DECODER(ADPCM_IMA_MTF,     sample_fmts_s16,  adpcm_ima_mtf,     "ADPCM IMA Capcom's MT Framework")
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index 017d100848..b81dda8161 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -677,6 +677,7 @@ extern const FFCodec ff_adpcm_ima_dk3_decoder;
 extern const FFCodec ff_adpcm_ima_dk4_decoder;
 extern const FFCodec ff_adpcm_ima_ea_eacs_decoder;
 extern const FFCodec ff_adpcm_ima_ea_sead_decoder;
+extern const FFCodec ff_adpcm_ima_hvqm4_decoder;
 extern const FFCodec ff_adpcm_ima_iss_decoder;
 extern const FFCodec ff_adpcm_ima_moflex_decoder;
 extern const FFCodec ff_adpcm_ima_mtf_decoder;
diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c
index 284d1861c4..101aabb11c 100644
--- a/libavcodec/codec_desc.c
+++ b/libavcodec/codec_desc.c
@@ -2634,6 +2634,13 @@ static const AVCodecDescriptor codec_descriptors[] = {
         .long_name = NULL_IF_CONFIG_SMALL("ADPCM Sanyo"),
         .props     = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY,
     },
+    {
+        .id        = AV_CODEC_ID_ADPCM_IMA_HVQM4,
+        .type      = AVMEDIA_TYPE_AUDIO,
+        .name      = "adpcm_ima_hvqm4",
+        .long_name = NULL_IF_CONFIG_SMALL("ADPCM IMA HVQM4"),
+        .props     = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY,
+    },
 
     /* AMR */
     {
diff --git a/libavcodec/codec_id.h b/libavcodec/codec_id.h
index 455bc4b839..ee964184a5 100644
--- a/libavcodec/codec_id.h
+++ b/libavcodec/codec_id.h
@@ -427,6 +427,7 @@ enum AVCodecID {
     AV_CODEC_ID_ADPCM_XMD,
     AV_CODEC_ID_ADPCM_IMA_XBOX,
     AV_CODEC_ID_ADPCM_SANYO,
+    AV_CODEC_ID_ADPCM_IMA_HVQM4,
 
     /* AMR */
     AV_CODEC_ID_AMR_NB = 0x12000,
-- 
2.49.1


From 2f541e6f871d801c2b5bb465aea057ffb48e1b0e Mon Sep 17 00:00:00 2001
From: Paul B Mahol <onemda@gmail.com>
Date: Mon, 13 May 2024 10:20:06 +0200
Subject: [PATCH 04/15] avcodec: add ADPCM IMA PDA decoder

(cherry picked from commit ab9f7513d55cfd87d1a1ce22d02abffbfb9bb296)
---
 libavcodec/Makefile     |  1 +
 libavcodec/adpcm.c      | 25 +++++++++++++++++++++++++
 libavcodec/allcodecs.c  |  1 +
 libavcodec/codec_desc.c |  7 +++++++
 libavcodec/codec_id.h   |  1 +
 libavcodec/utils.c      |  1 +
 6 files changed, 36 insertions(+)

diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 6311cd1821..5a325bf174 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -988,6 +988,7 @@ OBJS-$(CONFIG_ADPCM_IMA_HVMQ4_DECODER)    += adpcm.o adpcm_data.o
 OBJS-$(CONFIG_ADPCM_IMA_ISS_DECODER)      += adpcm.o adpcm_data.o
 OBJS-$(CONFIG_ADPCM_IMA_MOFLEX_DECODER)   += adpcm.o adpcm_data.o
 OBJS-$(CONFIG_ADPCM_IMA_MTF_DECODER)      += adpcm.o adpcm_data.o
+OBJS-$(CONFIG_ADPCM_IMA_PDA_DECODER)      += adpcm.o adpcm_data.o
 OBJS-$(CONFIG_ADPCM_IMA_OKI_DECODER)      += adpcm.o adpcm_data.o
 OBJS-$(CONFIG_ADPCM_IMA_QT_DECODER)       += adpcm.o adpcm_data.o
 OBJS-$(CONFIG_ADPCM_IMA_QT_ENCODER)       += adpcmenc.o adpcm_data.o
diff --git a/libavcodec/adpcm.c b/libavcodec/adpcm.c
index bc3b0c9730..55e48d193d 100644
--- a/libavcodec/adpcm.c
+++ b/libavcodec/adpcm.c
@@ -1207,6 +1207,11 @@ static int get_nb_samples(AVCodecContext *avctx, GetByteContext *gb,
             buf_size = FFMIN(buf_size, avctx->block_align);
         nb_samples = (buf_size - 4 * ch) * 2 / ch;
         break;
+    case AV_CODEC_ID_ADPCM_IMA_PDA:
+        if (avctx->block_align > 0)
+            buf_size = FFMIN(buf_size, avctx->block_align);
+        nb_samples = (buf_size - 4 * ch) * 2 / ch;
+        break;
     CASE(ADPCM_IMA_WAV,
         int bsize = ff_adpcm_ima_block_sizes[avctx->bits_per_coded_sample - 2];
         int bsamples = ff_adpcm_ima_block_samples[avctx->bits_per_coded_sample - 2];
@@ -2202,6 +2207,25 @@ static int adpcm_decode_frame(AVCodecContext *avctx, AVFrame *frame,
             }
         }
         ) /* End of CASE */
+    CASE(ADPCM_IMA_PDA,
+        for (int i = 0; i < channels; i++) {
+            c->status[i].predictor = sign_extend(bytestream2_get_le16u(&gb), 16);
+            c->status[i].step_index = bytestream2_get_byteu(&gb);
+            bytestream2_skipu(&gb, 1);
+            if (c->status[i].step_index > 88u) {
+                av_log(avctx, AV_LOG_ERROR, "ERROR: step_index = %i\n",
+                       c->status[i].step_index);
+                return AVERROR_INVALIDDATA;
+            }
+        }
+
+        for (int n = nb_samples >> (1 - st); n > 0; n--) {
+            int v = bytestream2_get_byteu(&gb);
+
+            *samples++ = ff_adpcm_ima_qt_expand_nibble(&c->status[0 ], v >> 4 );
+            *samples++ = ff_adpcm_ima_qt_expand_nibble(&c->status[st], v & 0xf);
+        }
+        ) /* End of CASE */
     CASE(ADPCM_IMA_SMJPEG,
         for (int i = 0; i < channels; i++) {
             c->status[i].predictor = sign_extend(bytestream2_get_be16u(&gb), 16);
@@ -2704,6 +2728,7 @@ ADPCM_DECODER(ADPCM_IMA_ISS,     sample_fmts_s16,  adpcm_ima_iss,     "ADPCM IMA
 ADPCM_DECODER(ADPCM_IMA_MOFLEX,  sample_fmts_s16p, adpcm_ima_moflex,  "ADPCM IMA MobiClip MOFLEX")
 ADPCM_DECODER(ADPCM_IMA_MTF,     sample_fmts_s16,  adpcm_ima_mtf,     "ADPCM IMA Capcom's MT Framework")
 ADPCM_DECODER(ADPCM_IMA_OKI,     sample_fmts_s16,  adpcm_ima_oki,     "ADPCM IMA Dialogic OKI")
+ADPCM_DECODER(ADPCM_IMA_PDA,     sample_fmts_s16,  adpcm_ima_pda,     "ADPCM IMA PlayDate")
 ADPCM_DECODER(ADPCM_IMA_QT,      sample_fmts_s16p, adpcm_ima_qt,      "ADPCM IMA QuickTime")
 ADPCM_DECODER(ADPCM_IMA_RAD,     sample_fmts_s16,  adpcm_ima_rad,     "ADPCM IMA Radical")
 ADPCM_DECODER(ADPCM_IMA_SSI,     sample_fmts_s16,  adpcm_ima_ssi,     "ADPCM IMA Simon & Schuster Interactive")
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index b81dda8161..2fb3b0c2ea 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -682,6 +682,7 @@ extern const FFCodec ff_adpcm_ima_iss_decoder;
 extern const FFCodec ff_adpcm_ima_moflex_decoder;
 extern const FFCodec ff_adpcm_ima_mtf_decoder;
 extern const FFCodec ff_adpcm_ima_oki_decoder;
+extern const FFCodec ff_adpcm_ima_pda_decoder;
 extern const FFCodec ff_adpcm_ima_qt_encoder;
 extern const FFCodec ff_adpcm_ima_qt_decoder;
 extern const FFCodec ff_adpcm_ima_rad_decoder;
diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c
index 101aabb11c..4128bf2ecb 100644
--- a/libavcodec/codec_desc.c
+++ b/libavcodec/codec_desc.c
@@ -2641,6 +2641,13 @@ static const AVCodecDescriptor codec_descriptors[] = {
         .long_name = NULL_IF_CONFIG_SMALL("ADPCM IMA HVQM4"),
         .props     = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY,
     },
+    {
+        .id        = AV_CODEC_ID_ADPCM_IMA_PDA,
+        .type      = AVMEDIA_TYPE_AUDIO,
+        .name      = "adpcm_ima_pda",
+        .long_name = NULL_IF_CONFIG_SMALL("ADPCM IMA PlayDate"),
+        .props     = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY,
+    },
 
     /* AMR */
     {
diff --git a/libavcodec/codec_id.h b/libavcodec/codec_id.h
index ee964184a5..6e4b215bf1 100644
--- a/libavcodec/codec_id.h
+++ b/libavcodec/codec_id.h
@@ -428,6 +428,7 @@ enum AVCodecID {
     AV_CODEC_ID_ADPCM_IMA_XBOX,
     AV_CODEC_ID_ADPCM_SANYO,
     AV_CODEC_ID_ADPCM_IMA_HVQM4,
+    AV_CODEC_ID_ADPCM_IMA_PDA,
 
     /* AMR */
     AV_CODEC_ID_AMR_NB = 0x12000,
diff --git a/libavcodec/utils.c b/libavcodec/utils.c
index cfa35d0e04..735edaf7a6 100644
--- a/libavcodec/utils.c
+++ b/libavcodec/utils.c
@@ -675,6 +675,7 @@ static int get_audio_frame_duration(enum AVCodecID id, int sr, int ch, int ba,
             case AV_CODEC_ID_ADPCM_IMA_ACORN:
             case AV_CODEC_ID_ADPCM_IMA_DAT4:
             case AV_CODEC_ID_ADPCM_IMA_ISS:
+            case AV_CODEC_ID_ADPCM_IMA_PDA:
                 return (frame_bytes - 4 * ch) * 2 / ch;
             case AV_CODEC_ID_ADPCM_IMA_SMJPEG:
                 return (frame_bytes - 4) * 2 / ch;
-- 
2.49.1


From 56e5c562a00260dd56e54cabb6a3c181bc5c737b Mon Sep 17 00:00:00 2001
From: Paul B Mahol <onemda@gmail.com>
Date: Mon, 25 Nov 2024 13:01:16 +0000
Subject: [PATCH 05/15] avcodec: add ADPCM Silicon Graphics N64 decoder

(cherry picked from commit 13484237fdf19c9d927b8a64b81d00100a4178c3)
---
 libavcodec/Makefile     |  1 +
 libavcodec/adpcm.c      | 89 +++++++++++++++++++++++++++++++++++++++++
 libavcodec/allcodecs.c  |  1 +
 libavcodec/codec_desc.c |  7 ++++
 libavcodec/codec_id.h   |  1 +
 libavcodec/utils.c      |  5 +++
 6 files changed, 104 insertions(+)

diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 5a325bf174..3af81c368e 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -1004,6 +1004,7 @@ OBJS-$(CONFIG_ADPCM_IMA_XBOX_DECODER)     += adpcm.o adpcm_data.o
 OBJS-$(CONFIG_ADPCM_MS_DECODER)           += adpcm.o adpcm_data.o
 OBJS-$(CONFIG_ADPCM_MS_ENCODER)           += adpcmenc.o adpcm_data.o
 OBJS-$(CONFIG_ADPCM_MTAF_DECODER)         += adpcm.o adpcm_data.o
+OBJS-$(CONFIG_ADPCM_N64_DECODER)          += adpcm.o adpcm_data.o
 OBJS-$(CONFIG_ADPCM_PSX_DECODER)          += adpcm.o adpcm_data.o
 OBJS-$(CONFIG_ADPCM_SANYO_DECODER)        += adpcm.o adpcm_data.o
 OBJS-$(CONFIG_ADPCM_SBPRO_2_DECODER)      += adpcm.o adpcm_data.o
diff --git a/libavcodec/adpcm.c b/libavcodec/adpcm.c
index 55e48d193d..49bc2e9e70 100644
--- a/libavcodec/adpcm.c
+++ b/libavcodec/adpcm.c
@@ -259,6 +259,7 @@ static av_cold int adpcm_decode_init(AVCodecContext * avctx)
 
     switch(avctx->codec->id) {
     case AV_CODEC_ID_ADPCM_IMA_AMV:
+    case AV_CODEC_ID_ADPCM_N64:
         max_channels = 1;
         break;
     case AV_CODEC_ID_ADPCM_SANYO:
@@ -350,6 +351,7 @@ static av_cold int adpcm_decode_init(AVCodecContext * avctx)
     case AV_CODEC_ID_ADPCM_MTAF:
     case AV_CODEC_ID_ADPCM_ARGO:
     case AV_CODEC_ID_ADPCM_IMA_MOFLEX:
+    case AV_CODEC_ID_ADPCM_N64:
         avctx->sample_fmt = AV_SAMPLE_FMT_S16P;
         break;
     case AV_CODEC_ID_ADPCM_IMA_WS:
@@ -1093,6 +1095,9 @@ static int get_nb_samples(AVCodecContext *avctx, GetByteContext *gb,
             return 0;
         nb_samples = 64;
         break;
+    case AV_CODEC_ID_ADPCM_N64:
+        nb_samples = (buf_size / 9) * 16;
+        break;
     /* simple 4-bit adpcm */
     case AV_CODEC_ID_ADPCM_CT:
     case AV_CODEC_ID_ADPCM_IMA_APC:
@@ -2491,6 +2496,89 @@ static int adpcm_decode_frame(AVCodecContext *avctx, AVFrame *frame,
                 bytestream2_seek(&gb, 0, SEEK_SET);
         }
         ) /* End of CASE */
+    CASE(ADPCM_N64,
+        ADPCMChannelStatus *cs = &c->status[0];
+        int coefs[8*2*8] = { 0 };
+
+        if (avctx->extradata) {
+            int version, order, entries;
+            GetByteContext cb;
+
+            bytestream2_init(&cb, avctx->extradata, avctx->extradata_size);
+
+            version = bytestream2_get_be16(&cb);
+            order = bytestream2_get_be16(&cb);
+            entries = bytestream2_get_be16(&cb);
+            if (version != 1 || order != 2 || entries > 8)
+                return AVERROR_INVALIDDATA;
+
+            for (int n = 0; n < order * entries * 8; n++)
+                coefs[n] = sign_extend(bytestream2_get_be16(&cb), 16);
+        }
+
+        for (int block = 0; block < avpkt->size / 9; block++) {
+            int scale, index, codes[16];
+            int16_t hist[8] = { 0 };
+            const int order = 2;
+            int16_t out[16];
+
+            hist[6] = cs->sample2;
+            hist[7] = cs->sample1;
+
+            samples = samples_p[0] + block * 16;
+
+            scale = (buf[0] >> 4) & 0xF;
+            index = (buf[0] >> 0) & 0xF;
+            scale = 1 << scale;
+            index = FFMIN(index, 8);
+
+            for (int i = 0, j = 0; i < 16; i += 2, j++) {
+                int n0 = (buf[j+1] >> 4) & 0xF;
+                int n1 = (buf[j+1] >> 0) & 0xF;
+
+                if (n0 & 8)
+                    n0 = n0 - 16;
+                if (n1 & 8)
+                    n1 = n1 - 16;
+
+                codes[i+0] = n0 * scale;
+                codes[i+1] = n1 * scale;
+            }
+
+            for (int j = 0; j < 2; j++) {
+                int *sf_codes = &codes[j*8];
+                int16_t *sf_out = &out[j*8];
+
+                for (int i = 0; i < 8; i++) {
+                    int sample, delta = 0;
+
+                    for (int o = 0; o < order; o++)
+                        delta += coefs[o*8 + i] * hist[(8 - order) + o];
+
+                    for (int k = i-1; k > -1; k--) {
+                        for (int o = 1; o < order; o++)
+                            delta += sf_codes[(i-1) - k] * coefs[(o*8) + k];
+                    }
+
+                    sample = sf_codes[i] * 2048;
+                    sample = (sample + delta) / 2048;
+                    sample = av_clip_int16(sample);
+                    sf_out[i] = sample;
+                }
+
+                for (int i = 8 - order; i < 8; i++)
+                    hist[i] = sf_out[i];
+            }
+
+            memcpy(samples, out, sizeof(out));
+
+            cs->sample2 = hist[6];
+            cs->sample1 = hist[7];
+
+            buf += 9;
+        }
+        bytestream2_seek(&gb, 0, SEEK_END);
+        ) /* End of CASE */
     CASE(ADPCM_PSX,
         for (int block = 0; block < avpkt->size / FFMAX(avctx->block_align, 16 * channels); block++) {
             int nb_samples_per_block = 28 * FFMAX(avctx->block_align, 16 * channels) / (16 * channels);
@@ -2739,6 +2827,7 @@ ADPCM_DECODER(ADPCM_IMA_WS,      sample_fmts_both, adpcm_ima_ws,      "ADPCM IMA
 ADPCM_DECODER(ADPCM_IMA_XBOX,    sample_fmts_s16p, adpcm_ima_xbox,    "ADPCM IMA Xbox")
 ADPCM_DECODER(ADPCM_MS,          sample_fmts_both, adpcm_ms,          "ADPCM Microsoft")
 ADPCM_DECODER(ADPCM_MTAF,        sample_fmts_s16p, adpcm_mtaf,        "ADPCM MTAF")
+ADPCM_DECODER(ADPCM_N64,         sample_fmts_s16p, adpcm_n64,         "ADPCM Silicon Graphics N64")
 ADPCM_DECODER(ADPCM_PSX,         sample_fmts_s16p, adpcm_psx,         "ADPCM Playstation")
 ADPCM_DECODER(ADPCM_SANYO,       sample_fmts_s16p, adpcm_sanyo,       "ADPCM Sanyo")
 ADPCM_DECODER(ADPCM_SBPRO_2,     sample_fmts_s16,  adpcm_sbpro_2,     "ADPCM Sound Blaster Pro 2-bit")
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index 2fb3b0c2ea..f3a252e241 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -697,6 +697,7 @@ extern const FFCodec ff_adpcm_ima_xbox_decoder;
 extern const FFCodec ff_adpcm_ms_encoder;
 extern const FFCodec ff_adpcm_ms_decoder;
 extern const FFCodec ff_adpcm_mtaf_decoder;
+extern const FFCodec ff_adpcm_n64_decoder;
 extern const FFCodec ff_adpcm_psx_decoder;
 extern const FFCodec ff_adpcm_sanyo_decoder;
 extern const FFCodec ff_adpcm_sbpro_2_decoder;
diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c
index 4128bf2ecb..b758e43f33 100644
--- a/libavcodec/codec_desc.c
+++ b/libavcodec/codec_desc.c
@@ -2648,6 +2648,13 @@ static const AVCodecDescriptor codec_descriptors[] = {
         .long_name = NULL_IF_CONFIG_SMALL("ADPCM IMA PlayDate"),
         .props     = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY,
     },
+    {
+        .id        = AV_CODEC_ID_ADPCM_N64,
+        .type      = AVMEDIA_TYPE_AUDIO,
+        .name      = "adpcm_n64",
+        .long_name = NULL_IF_CONFIG_SMALL("ADPCM Silicon Graphics N64"),
+        .props     = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY,
+    },
 
     /* AMR */
     {
diff --git a/libavcodec/codec_id.h b/libavcodec/codec_id.h
index 6e4b215bf1..8930b2957e 100644
--- a/libavcodec/codec_id.h
+++ b/libavcodec/codec_id.h
@@ -429,6 +429,7 @@ enum AVCodecID {
     AV_CODEC_ID_ADPCM_SANYO,
     AV_CODEC_ID_ADPCM_IMA_HVQM4,
     AV_CODEC_ID_ADPCM_IMA_PDA,
+    AV_CODEC_ID_ADPCM_N64,
 
     /* AMR */
     AV_CODEC_ID_AMR_NB = 0x12000,
diff --git a/libavcodec/utils.c b/libavcodec/utils.c
index 735edaf7a6..c5230e646a 100644
--- a/libavcodec/utils.c
+++ b/libavcodec/utils.c
@@ -665,6 +665,11 @@ static int get_audio_frame_duration(enum AVCodecID id, int sr, int ch, int ba,
                 return (frame_bytes - 4 * ch) / (128 * ch) * 256;
             case AV_CODEC_ID_ADPCM_AFC:
                 return frame_bytes / (9 * ch) * 16;
+            case AV_CODEC_ID_ADPCM_N64:
+                frame_bytes /= 9 * ch;
+                if (frame_bytes > INT_MAX / 16)
+                    return 0;
+                return frame_bytes * 16;
             case AV_CODEC_ID_ADPCM_PSX:
             case AV_CODEC_ID_ADPCM_DTK:
                 frame_bytes /= 16 * ch;
-- 
2.49.1


From dc13da259d28d93cb329f19480076ed0e1967171 Mon Sep 17 00:00:00 2001
From: Paul B Mahol <onemda@gmail.com>
Date: Mon, 25 Nov 2024 19:34:44 +0000
Subject: [PATCH 06/15] avcodec/adpcm: fix overflow in mono ADPCM IMA HVQM4

(cherry picked from commit 6a9b0f7272a0725abbe6f887f766fb5f1f119a66)
---
 libavcodec/adpcm.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libavcodec/adpcm.c b/libavcodec/adpcm.c
index 49bc2e9e70..3f4c392939 100644
--- a/libavcodec/adpcm.c
+++ b/libavcodec/adpcm.c
@@ -579,7 +579,7 @@ static void decode_adpcm_ima_hvqm4(AVCodecContext *avctx, int16_t *outbuf, int s
         samples_to_do--;
     }
 
-    for (int i = 0; i < samples_to_do; i++) {
+    for (int i = 0; i < samples_to_do; i += 1+(!st)) {
         uint8_t nibble = bytestream2_get_byte(gb);
 
         *outbuf++ = ff_adpcm_ima_qt_expand_nibble(&c->status[st], nibble & 0xF);
-- 
2.49.1


From ac1fbf530503e893946974aed5b0390686eba9f6 Mon Sep 17 00:00:00 2001
From: Paul B Mahol <onemda@gmail.com>
Date: Mon, 25 Nov 2024 19:06:53 +0000
Subject: [PATCH 07/15] avcodec: add ADPCM IMA HVQM2 decoder

(cherry picked from commit 480e36592d5fc27a47e378d62570824613f26b7b)
---
 libavcodec/Makefile     |  3 ++-
 libavcodec/adpcm.c      | 47 +++++++++++++++++++++++++++++++++++++++++
 libavcodec/allcodecs.c  |  1 +
 libavcodec/codec_desc.c |  7 ++++++
 libavcodec/codec_id.h   |  1 +
 5 files changed, 58 insertions(+), 1 deletion(-)

diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 3af81c368e..0cf8c80b2e 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -984,7 +984,8 @@ OBJS-$(CONFIG_ADPCM_IMA_DK3_DECODER)      += adpcm.o adpcm_data.o
 OBJS-$(CONFIG_ADPCM_IMA_DK4_DECODER)      += adpcm.o adpcm_data.o
 OBJS-$(CONFIG_ADPCM_IMA_EA_EACS_DECODER)  += adpcm.o adpcm_data.o
 OBJS-$(CONFIG_ADPCM_IMA_EA_SEAD_DECODER)  += adpcm.o adpcm_data.o
-OBJS-$(CONFIG_ADPCM_IMA_HVMQ4_DECODER)    += adpcm.o adpcm_data.o
+OBJS-$(CONFIG_ADPCM_IMA_HVQM2_DECODER)    += adpcm.o adpcm_data.o
+OBJS-$(CONFIG_ADPCM_IMA_HVQM4_DECODER)    += adpcm.o adpcm_data.o
 OBJS-$(CONFIG_ADPCM_IMA_ISS_DECODER)      += adpcm.o adpcm_data.o
 OBJS-$(CONFIG_ADPCM_IMA_MOFLEX_DECODER)   += adpcm.o adpcm_data.o
 OBJS-$(CONFIG_ADPCM_IMA_MTF_DECODER)      += adpcm.o adpcm_data.o
diff --git a/libavcodec/adpcm.c b/libavcodec/adpcm.c
index 3f4c392939..a131088b7c 100644
--- a/libavcodec/adpcm.c
+++ b/libavcodec/adpcm.c
@@ -546,6 +546,43 @@ int16_t ff_adpcm_ima_qt_expand_nibble(ADPCMChannelStatus *c, int nibble)
     return c->predictor;
 }
 
+static void decode_adpcm_ima_hvqm2(AVCodecContext *avctx, int16_t *outbuf, int samples_to_do,
+                                   int frame_format, GetByteContext *gb)
+{
+    ADPCMDecodeContext *c = avctx->priv_data;
+    int st = avctx->ch_layout.nb_channels == 2;
+    uint8_t nibble;
+
+    for (int ch = 0; ch < avctx->ch_layout.nb_channels; ch++) {
+        unsigned tmp;
+
+        switch (frame_format) {
+        case 0: /* combined hist+index */
+            tmp = bytestream2_get_be16(gb);
+            c->status[ch].predictor  = sign_extend(tmp & 0xFF80, 16);
+            c->status[ch].step_index = tmp & 0x7f;
+            *outbuf++ = c->status[ch].predictor;
+            samples_to_do--;
+            break;
+        default:
+            break;
+        }
+
+        c->status[ch].step_index = av_clip(c->status[ch].step_index, 0, 88);
+    }
+
+    for (int i = 0; i < samples_to_do; i++) {
+        if (!(i&1)) {
+            nibble = bytestream2_get_byte(gb);
+            *outbuf++ = ff_adpcm_ima_qt_expand_nibble(&c->status[st], nibble >>  4);
+        } else {
+            *outbuf++ = ff_adpcm_ima_qt_expand_nibble(&c->status[ 0], nibble & 0xF);
+        }
+    }
+
+    bytestream2_seek(gb, 0, SEEK_END);
+}
+
 static void decode_adpcm_ima_hvqm4(AVCodecContext *avctx, int16_t *outbuf, int samples_to_do,
                                    int frame_format, GetByteContext *gb)
 {
@@ -1148,6 +1185,9 @@ static int get_nb_samples(AVCodecContext *avctx, GetByteContext *gb,
         *coded_samples -= *coded_samples % 28;
         nb_samples      = (buf_size - 12) / (ch == 2 ? 30 : 15) * 28;
         break;
+    case AV_CODEC_ID_ADPCM_IMA_HVQM2:
+        nb_samples = ((bytestream2_peek_be64(gb) >> 16) & 0xFFFF);
+        break;
     case AV_CODEC_ID_ADPCM_IMA_HVQM4:
         {
             int frame_format = bytestream2_get_be16(gb);
@@ -1753,6 +1793,12 @@ static int adpcm_decode_frame(AVCodecContext *avctx, AVFrame *frame,
             *samples++ = adpcm_ima_expand_nibble(&c->status[st], v & 0x0F, 3);
         }
         ) /* End of CASE */
+    CASE(ADPCM_IMA_HVQM2,
+        int format = bytestream2_get_be16(&gb);
+
+        bytestream2_skip(&gb, 4);
+        decode_adpcm_ima_hvqm2(avctx, samples, nb_samples, format, &gb);
+        ) /* End of CASE */
     CASE(ADPCM_IMA_HVQM4,
         int format = bytestream2_get_be16(&gb);
 
@@ -2811,6 +2857,7 @@ ADPCM_DECODER(ADPCM_IMA_DK3,     sample_fmts_s16,  adpcm_ima_dk3,     "ADPCM IMA
 ADPCM_DECODER(ADPCM_IMA_DK4,     sample_fmts_s16,  adpcm_ima_dk4,     "ADPCM IMA Duck DK4")
 ADPCM_DECODER(ADPCM_IMA_EA_EACS, sample_fmts_s16,  adpcm_ima_ea_eacs, "ADPCM IMA Electronic Arts EACS")
 ADPCM_DECODER(ADPCM_IMA_EA_SEAD, sample_fmts_s16,  adpcm_ima_ea_sead, "ADPCM IMA Electronic Arts SEAD")
+ADPCM_DECODER(ADPCM_IMA_HVQM2,   sample_fmts_s16,  adpcm_ima_hvqm2,   "ADPCM IMA HVQM2")
 ADPCM_DECODER(ADPCM_IMA_HVQM4,   sample_fmts_s16,  adpcm_ima_hvqm4,   "ADPCM IMA HVQM4")
 ADPCM_DECODER(ADPCM_IMA_ISS,     sample_fmts_s16,  adpcm_ima_iss,     "ADPCM IMA Funcom ISS")
 ADPCM_DECODER(ADPCM_IMA_MOFLEX,  sample_fmts_s16p, adpcm_ima_moflex,  "ADPCM IMA MobiClip MOFLEX")
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index f3a252e241..5891c04211 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -677,6 +677,7 @@ extern const FFCodec ff_adpcm_ima_dk3_decoder;
 extern const FFCodec ff_adpcm_ima_dk4_decoder;
 extern const FFCodec ff_adpcm_ima_ea_eacs_decoder;
 extern const FFCodec ff_adpcm_ima_ea_sead_decoder;
+extern const FFCodec ff_adpcm_ima_hvqm2_decoder;
 extern const FFCodec ff_adpcm_ima_hvqm4_decoder;
 extern const FFCodec ff_adpcm_ima_iss_decoder;
 extern const FFCodec ff_adpcm_ima_moflex_decoder;
diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c
index b758e43f33..ea22c0a668 100644
--- a/libavcodec/codec_desc.c
+++ b/libavcodec/codec_desc.c
@@ -2655,6 +2655,13 @@ static const AVCodecDescriptor codec_descriptors[] = {
         .long_name = NULL_IF_CONFIG_SMALL("ADPCM Silicon Graphics N64"),
         .props     = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY,
     },
+    {
+        .id        = AV_CODEC_ID_ADPCM_IMA_HVQM2,
+        .type      = AVMEDIA_TYPE_AUDIO,
+        .name      = "adpcm_ima_hvqm2",
+        .long_name = NULL_IF_CONFIG_SMALL("ADPCM IMA HVQM2"),
+        .props     = AV_CODEC_PROP_LOSSY,
+    },
 
     /* AMR */
     {
diff --git a/libavcodec/codec_id.h b/libavcodec/codec_id.h
index 8930b2957e..cc22f24ba9 100644
--- a/libavcodec/codec_id.h
+++ b/libavcodec/codec_id.h
@@ -430,6 +430,7 @@ enum AVCodecID {
     AV_CODEC_ID_ADPCM_IMA_HVQM4,
     AV_CODEC_ID_ADPCM_IMA_PDA,
     AV_CODEC_ID_ADPCM_N64,
+    AV_CODEC_ID_ADPCM_IMA_HVQM2,
 
     /* AMR */
     AV_CODEC_ID_AMR_NB = 0x12000,
-- 
2.49.1


From e35ac402c2a9f477b68a038086d72de9c7ea75e3 Mon Sep 17 00:00:00 2001
From: Paul B Mahol <onemda@gmail.com>
Date: Sun, 15 Dec 2024 13:48:11 +0000
Subject: [PATCH 08/15] avcodec/adpcm: explicitly clear 4 upper bits for PSX
 when sign extending

(cherry picked from commit 49f6621d88392e21360efc1fb99d1241fa3ce469)
---
 libavcodec/adpcm.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libavcodec/adpcm.c b/libavcodec/adpcm.c
index a131088b7c..eccb574cd7 100644
--- a/libavcodec/adpcm.c
+++ b/libavcodec/adpcm.c
@@ -2651,7 +2651,7 @@ static int adpcm_decode_frame(AVCodecContext *avctx, AVFrame *frame,
                             scale = sign_extend(byte >> 4, 4);
                         } else {
                             byte  = bytestream2_get_byteu(&gb);
-                            scale = sign_extend(byte, 4);
+                            scale = sign_extend(byte & 0xF, 4);
                         }
 
                         if (flag < 0x07) {
-- 
2.49.1


From 37dd4362116f66306954527ece6ff38b39738ce3 Mon Sep 17 00:00:00 2001
From: Paul B Mahol <onemda@gmail.com>
Date: Tue, 21 Jan 2025 17:29:45 +0000
Subject: [PATCH 09/15] avcodec: add ADPCM IMA Magix decoder

(cherry picked from commit 2ec3ad2122484ce2c84f6ba055c5ebc1661c5b14)
---
 libavcodec/Makefile     |  1 +
 libavcodec/adpcm.c      | 24 ++++++++++++++++++++++++
 libavcodec/allcodecs.c  |  1 +
 libavcodec/codec_desc.c |  7 +++++++
 libavcodec/codec_id.h   |  1 +
 libavcodec/utils.c      |  1 +
 6 files changed, 35 insertions(+)

diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 0cf8c80b2e..6ab6313412 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -988,6 +988,7 @@ OBJS-$(CONFIG_ADPCM_IMA_HVQM2_DECODER)    += adpcm.o adpcm_data.o
 OBJS-$(CONFIG_ADPCM_IMA_HVQM4_DECODER)    += adpcm.o adpcm_data.o
 OBJS-$(CONFIG_ADPCM_IMA_ISS_DECODER)      += adpcm.o adpcm_data.o
 OBJS-$(CONFIG_ADPCM_IMA_MOFLEX_DECODER)   += adpcm.o adpcm_data.o
+OBJS-$(CONFIG_ADPCM_IMA_MAGIX_DECODER)    += adpcm.o adpcm_data.o
 OBJS-$(CONFIG_ADPCM_IMA_MTF_DECODER)      += adpcm.o adpcm_data.o
 OBJS-$(CONFIG_ADPCM_IMA_PDA_DECODER)      += adpcm.o adpcm_data.o
 OBJS-$(CONFIG_ADPCM_IMA_OKI_DECODER)      += adpcm.o adpcm_data.o
diff --git a/libavcodec/adpcm.c b/libavcodec/adpcm.c
index eccb574cd7..c641f4bef4 100644
--- a/libavcodec/adpcm.c
+++ b/libavcodec/adpcm.c
@@ -1161,6 +1161,7 @@ static int get_nb_samples(AVCodecContext *avctx, GetByteContext *gb,
         case AV_CODEC_ID_ADPCM_AGM:
         case AV_CODEC_ID_ADPCM_IMA_ACORN:
         case AV_CODEC_ID_ADPCM_IMA_DAT4:
+        case AV_CODEC_ID_ADPCM_IMA_MAGIX:
         case AV_CODEC_ID_ADPCM_IMA_MOFLEX:
         case AV_CODEC_ID_ADPCM_IMA_ISS:     header_size = 4 * ch;      break;
         case AV_CODEC_ID_ADPCM_IMA_SMJPEG:  header_size = 4 * ch;      break;
@@ -1724,6 +1725,28 @@ static int adpcm_decode_frame(AVCodecContext *avctx, AVFrame *frame,
         if ((bytestream2_tell(&gb) & 1))
             bytestream2_skip(&gb, 1);
         ) /* End of CASE */
+    CASE(ADPCM_IMA_MAGIX,
+        for (int channel = 0; channel < channels; channel++) {
+            ADPCMChannelStatus *cs = &c->status[channel];
+            cs->predictor  = sign_extend(bytestream2_get_le16u(&gb), 16);
+            cs->step_index = sign_extend(bytestream2_get_le16u(&gb), 16);
+            if (cs->step_index > 88u){
+                av_log(avctx, AV_LOG_ERROR, "ERROR: step_index[%d] = %i\n",
+                       channel, cs->step_index);
+                return AVERROR_INVALIDDATA;
+            }
+        }
+
+        for (int m = 0; m < avctx->block_align-8; m += 8) {
+            uint32_t v0 = bytestream2_get_le32u(&gb);
+            uint32_t v1 = bytestream2_get_le32u(&gb);
+
+            for (int n = 8; n > 0; n--, v0 >>= 4, v1 >>= 4, samples += 2) {
+                samples[0] = adpcm_ima_expand_nibble(&c->status[0], v0 & 15, 3);
+                samples[1] = adpcm_ima_expand_nibble(&c->status[1], v1 & 15, 3);
+            }
+        }
+        ) /* End of CASE */
     CASE(ADPCM_IMA_ISS,
         for (int channel = 0; channel < channels; channel++) {
             ADPCMChannelStatus *cs = &c->status[channel];
@@ -2860,6 +2883,7 @@ ADPCM_DECODER(ADPCM_IMA_EA_SEAD, sample_fmts_s16,  adpcm_ima_ea_sead, "ADPCM IMA
 ADPCM_DECODER(ADPCM_IMA_HVQM2,   sample_fmts_s16,  adpcm_ima_hvqm2,   "ADPCM IMA HVQM2")
 ADPCM_DECODER(ADPCM_IMA_HVQM4,   sample_fmts_s16,  adpcm_ima_hvqm4,   "ADPCM IMA HVQM4")
 ADPCM_DECODER(ADPCM_IMA_ISS,     sample_fmts_s16,  adpcm_ima_iss,     "ADPCM IMA Funcom ISS")
+ADPCM_DECODER(ADPCM_IMA_MAGIX,   sample_fmts_s16,  adpcm_ima_magix,   "ADPCM IMA Magix")
 ADPCM_DECODER(ADPCM_IMA_MOFLEX,  sample_fmts_s16p, adpcm_ima_moflex,  "ADPCM IMA MobiClip MOFLEX")
 ADPCM_DECODER(ADPCM_IMA_MTF,     sample_fmts_s16,  adpcm_ima_mtf,     "ADPCM IMA Capcom's MT Framework")
 ADPCM_DECODER(ADPCM_IMA_OKI,     sample_fmts_s16,  adpcm_ima_oki,     "ADPCM IMA Dialogic OKI")
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index 5891c04211..9064e470d3 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -680,6 +680,7 @@ extern const FFCodec ff_adpcm_ima_ea_sead_decoder;
 extern const FFCodec ff_adpcm_ima_hvqm2_decoder;
 extern const FFCodec ff_adpcm_ima_hvqm4_decoder;
 extern const FFCodec ff_adpcm_ima_iss_decoder;
+extern const FFCodec ff_adpcm_ima_magix_decoder;
 extern const FFCodec ff_adpcm_ima_moflex_decoder;
 extern const FFCodec ff_adpcm_ima_mtf_decoder;
 extern const FFCodec ff_adpcm_ima_oki_decoder;
diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c
index ea22c0a668..421ecf6926 100644
--- a/libavcodec/codec_desc.c
+++ b/libavcodec/codec_desc.c
@@ -2662,6 +2662,13 @@ static const AVCodecDescriptor codec_descriptors[] = {
         .long_name = NULL_IF_CONFIG_SMALL("ADPCM IMA HVQM2"),
         .props     = AV_CODEC_PROP_LOSSY,
     },
+    {
+        .id        = AV_CODEC_ID_ADPCM_IMA_MAGIX,
+        .type      = AVMEDIA_TYPE_AUDIO,
+        .name      = "adpcm_ima_magix",
+        .long_name = NULL_IF_CONFIG_SMALL("ADPCM IMA Magix"),
+        .props     = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY,
+    },
 
     /* AMR */
     {
diff --git a/libavcodec/codec_id.h b/libavcodec/codec_id.h
index cc22f24ba9..c69e81582a 100644
--- a/libavcodec/codec_id.h
+++ b/libavcodec/codec_id.h
@@ -431,6 +431,7 @@ enum AVCodecID {
     AV_CODEC_ID_ADPCM_IMA_PDA,
     AV_CODEC_ID_ADPCM_N64,
     AV_CODEC_ID_ADPCM_IMA_HVQM2,
+    AV_CODEC_ID_ADPCM_IMA_MAGIX,
 
     /* AMR */
     AV_CODEC_ID_AMR_NB = 0x12000,
diff --git a/libavcodec/utils.c b/libavcodec/utils.c
index c5230e646a..039315a2ce 100644
--- a/libavcodec/utils.c
+++ b/libavcodec/utils.c
@@ -465,6 +465,7 @@ int av_get_exact_bits_per_sample(enum AVCodecID codec_id)
     case AV_CODEC_ID_ADPCM_IMA_APC:
     case AV_CODEC_ID_ADPCM_IMA_APM:
     case AV_CODEC_ID_ADPCM_IMA_EA_SEAD:
+    case AV_CODEC_ID_ADPCM_IMA_MAGIX:
     case AV_CODEC_ID_ADPCM_IMA_OKI:
     case AV_CODEC_ID_ADPCM_IMA_WS:
     case AV_CODEC_ID_ADPCM_IMA_SSI:
-- 
2.49.1


From 9970be5a6ddb9d2cb589d9381b19fa92db8672bb Mon Sep 17 00:00:00 2001
From: Paul B Mahol <onemda@gmail.com>
Date: Wed, 19 Feb 2025 20:24:39 +0000
Subject: [PATCH 10/15] avcodec/adpcm: fix non-4bit adpcm ima wav decoding

(cherry picked from commit f4e05abeded46515bd7b4248fc7d65df82d9af2a)
---
 libavcodec/adpcm.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/libavcodec/adpcm.c b/libavcodec/adpcm.c
index c641f4bef4..a1906ac26c 100644
--- a/libavcodec/adpcm.c
+++ b/libavcodec/adpcm.c
@@ -509,7 +509,9 @@ static inline int16_t adpcm_ima_wav_expand_nibble(ADPCMChannelStatus *c, GetBitC
 
     sign = nibble & (1 << shift);
     delta = av_zero_extend(nibble, shift);
-    diff = ((2 * delta + 1) * step) >> shift;
+    diff = step >> shift;
+    for (int i = 0; i < shift; i++)
+        diff += (step >> (shift-1-i)) * !!(delta & (1 << i));
     predictor = c->predictor;
     if (sign) predictor -= diff;
     else predictor += diff;
-- 
2.49.1


From cc38ce87b3fb06a8fb75c0fc51fb87b3e57d196b Mon Sep 17 00:00:00 2001
From: Paul B Mahol <onemda@gmail.com>
Date: Mon, 24 Feb 2025 12:19:03 +0000
Subject: [PATCH 11/15] avcodec: add ADPCM PSXC audio decoder

(cherry picked from commit a4055b5cc6d77c26867948e24de6bdfd5c0e6a3b)
---
 libavcodec/Makefile     |  1 +
 libavcodec/adpcm.c      | 44 +++++++++++++++++++++++++++++++++++++++++
 libavcodec/allcodecs.c  |  1 +
 libavcodec/codec_desc.c |  7 +++++++
 libavcodec/codec_id.h   |  1 +
 libavcodec/utils.c      |  5 +++++
 6 files changed, 59 insertions(+)

diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 6ab6313412..08c5240a4c 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -1008,6 +1008,7 @@ OBJS-$(CONFIG_ADPCM_MS_ENCODER)           += adpcmenc.o adpcm_data.o
 OBJS-$(CONFIG_ADPCM_MTAF_DECODER)         += adpcm.o adpcm_data.o
 OBJS-$(CONFIG_ADPCM_N64_DECODER)          += adpcm.o adpcm_data.o
 OBJS-$(CONFIG_ADPCM_PSX_DECODER)          += adpcm.o adpcm_data.o
+OBJS-$(CONFIG_ADPCM_PSXC_DECODER)         += adpcm.o adpcm_data.o
 OBJS-$(CONFIG_ADPCM_SANYO_DECODER)        += adpcm.o adpcm_data.o
 OBJS-$(CONFIG_ADPCM_SBPRO_2_DECODER)      += adpcm.o adpcm_data.o
 OBJS-$(CONFIG_ADPCM_SBPRO_3_DECODER)      += adpcm.o adpcm_data.o
diff --git a/libavcodec/adpcm.c b/libavcodec/adpcm.c
index a1906ac26c..9381bdcf2a 100644
--- a/libavcodec/adpcm.c
+++ b/libavcodec/adpcm.c
@@ -290,6 +290,11 @@ static av_cold int adpcm_decode_init(AVCodecContext * avctx)
             avctx->block_align % (16 * avctx->ch_layout.nb_channels))
             return AVERROR_INVALIDDATA;
         break;
+    case AV_CODEC_ID_ADPCM_PSXC:
+        max_channels = 8;
+        if (avctx->ch_layout.nb_channels <= 0)
+            return AVERROR_INVALIDDATA;
+        break;
     case AV_CODEC_ID_ADPCM_IMA_DAT4:
     case AV_CODEC_ID_ADPCM_THP:
     case AV_CODEC_ID_ADPCM_THP_LE:
@@ -347,6 +352,7 @@ static av_cold int adpcm_decode_init(AVCodecContext * avctx)
     case AV_CODEC_ID_ADPCM_AFC:
     case AV_CODEC_ID_ADPCM_DTK:
     case AV_CODEC_ID_ADPCM_PSX:
+    case AV_CODEC_ID_ADPCM_PSXC:
     case AV_CODEC_ID_ADPCM_SANYO:
     case AV_CODEC_ID_ADPCM_MTAF:
     case AV_CODEC_ID_ADPCM_ARGO:
@@ -1351,6 +1357,9 @@ static int get_nb_samples(AVCodecContext *avctx, GetByteContext *gb,
     case AV_CODEC_ID_ADPCM_PSX:
         nb_samples = buf_size / (16 * ch) * 28;
         break;
+    case AV_CODEC_ID_ADPCM_PSXC:
+        nb_samples = ((buf_size - 1) / ch) * 2;
+        break;
     case AV_CODEC_ID_ADPCM_ARGO:
         nb_samples = buf_size / avctx->block_align * 32;
         break;
@@ -2691,6 +2700,40 @@ static int adpcm_decode_frame(AVCodecContext *avctx, AVFrame *frame,
             }
         }
         ) /* End of CASE */
+    CASE(ADPCM_PSXC,
+        for (int block = 0; block < avpkt->size / avctx->block_align; block++) {
+            int nb_samples_per_block = ((avctx->block_align - 1) / channels) * 2;
+            for (int channel = 0; channel < channels; channel++) {
+                int filter, shift, byte;
+
+                samples = samples_p[channel] + block * nb_samples_per_block;
+                av_assert0((block + 1) * nb_samples_per_block <= nb_samples);
+
+                filter = bytestream2_get_byteu(&gb);
+                shift  = filter & 0xf;
+                filter = filter >> 4;
+                if (filter >= FF_ARRAY_ELEMS(xa_adpcm_table))
+                    return AVERROR_INVALIDDATA;
+
+                for (int n = 0; n < nb_samples_per_block; n++) {
+                    int sample = 0, scale;
+
+                    if (n & 1) {
+                        scale = sign_extend(byte >> 4, 4);
+                    } else {
+                        byte  = bytestream2_get_byteu(&gb);
+                        scale = sign_extend(byte & 0xF, 4);
+                    }
+
+                    scale  = scale * (1 << 12);
+                    sample = (int)((scale >> shift) + (c->status[channel].sample1 * xa_adpcm_table[filter][0] + c->status[channel].sample2 * xa_adpcm_table[filter][1]) / 64);
+                    *samples++ = av_clip_int16(sample);
+                    c->status[channel].sample2 = c->status[channel].sample1;
+                    c->status[channel].sample1 = sample;
+                }
+            }
+        }
+        ) /* End of CASE */
     CASE(ADPCM_SANYO,
         int (*expand)(ADPCMChannelStatus *c, int bits);
         GetBitContext g;
@@ -2902,6 +2945,7 @@ ADPCM_DECODER(ADPCM_MS,          sample_fmts_both, adpcm_ms,          "ADPCM Mic
 ADPCM_DECODER(ADPCM_MTAF,        sample_fmts_s16p, adpcm_mtaf,        "ADPCM MTAF")
 ADPCM_DECODER(ADPCM_N64,         sample_fmts_s16p, adpcm_n64,         "ADPCM Silicon Graphics N64")
 ADPCM_DECODER(ADPCM_PSX,         sample_fmts_s16p, adpcm_psx,         "ADPCM Playstation")
+ADPCM_DECODER(ADPCM_PSXC,        sample_fmts_s16p, adpcm_psxc,        "ADPCM Playstation C")
 ADPCM_DECODER(ADPCM_SANYO,       sample_fmts_s16p, adpcm_sanyo,       "ADPCM Sanyo")
 ADPCM_DECODER(ADPCM_SBPRO_2,     sample_fmts_s16,  adpcm_sbpro_2,     "ADPCM Sound Blaster Pro 2-bit")
 ADPCM_DECODER(ADPCM_SBPRO_3,     sample_fmts_s16,  adpcm_sbpro_3,     "ADPCM Sound Blaster Pro 2.6-bit")
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index 9064e470d3..67e02ef7bb 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -701,6 +701,7 @@ extern const FFCodec ff_adpcm_ms_decoder;
 extern const FFCodec ff_adpcm_mtaf_decoder;
 extern const FFCodec ff_adpcm_n64_decoder;
 extern const FFCodec ff_adpcm_psx_decoder;
+extern const FFCodec ff_adpcm_psxc_decoder;
 extern const FFCodec ff_adpcm_sanyo_decoder;
 extern const FFCodec ff_adpcm_sbpro_2_decoder;
 extern const FFCodec ff_adpcm_sbpro_3_decoder;
diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c
index 421ecf6926..1493f34730 100644
--- a/libavcodec/codec_desc.c
+++ b/libavcodec/codec_desc.c
@@ -2669,6 +2669,13 @@ static const AVCodecDescriptor codec_descriptors[] = {
         .long_name = NULL_IF_CONFIG_SMALL("ADPCM IMA Magix"),
         .props     = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY,
     },
+    {
+        .id        = AV_CODEC_ID_ADPCM_PSXC,
+        .type      = AVMEDIA_TYPE_AUDIO,
+        .name      = "adpcm_psxc",
+        .long_name = NULL_IF_CONFIG_SMALL("ADPCM Playstation C"),
+        .props     = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY,
+    },
 
     /* AMR */
     {
diff --git a/libavcodec/codec_id.h b/libavcodec/codec_id.h
index c69e81582a..975ebbe880 100644
--- a/libavcodec/codec_id.h
+++ b/libavcodec/codec_id.h
@@ -432,6 +432,7 @@ enum AVCodecID {
     AV_CODEC_ID_ADPCM_N64,
     AV_CODEC_ID_ADPCM_IMA_HVQM2,
     AV_CODEC_ID_ADPCM_IMA_MAGIX,
+    AV_CODEC_ID_ADPCM_PSXC,
 
     /* AMR */
     AV_CODEC_ID_AMR_NB = 0x12000,
diff --git a/libavcodec/utils.c b/libavcodec/utils.c
index 039315a2ce..b65e10827e 100644
--- a/libavcodec/utils.c
+++ b/libavcodec/utils.c
@@ -677,6 +677,11 @@ static int get_audio_frame_duration(enum AVCodecID id, int sr, int ch, int ba,
                 if (frame_bytes > INT_MAX / 28)
                     return 0;
                 return frame_bytes * 28;
+            case AV_CODEC_ID_ADPCM_PSXC:
+                frame_bytes = (frame_bytes - 1) / ch;
+                if (frame_bytes > INT_MAX / 2)
+                    return 0;
+                return frame_bytes * 2;
             case AV_CODEC_ID_ADPCM_4XM:
             case AV_CODEC_ID_ADPCM_IMA_ACORN:
             case AV_CODEC_ID_ADPCM_IMA_DAT4:
-- 
2.49.1


From c1bb24c3f29b1bf78ec36e0d5270ed22e9d901a5 Mon Sep 17 00:00:00 2001
From: Paul B Mahol <onemda@gmail.com>
Date: Fri, 28 Feb 2025 16:05:05 +0000
Subject: [PATCH 12/15] avcodec: add ADPCM Circus decoder

(cherry picked from commit cdd3d794c7e01e4d6f485e7b975a4b9107d3f2fd)
---
 libavcodec/Makefile     |  1 +
 libavcodec/adpcm.c      | 31 +++++++++++++++++++++++++++++++
 libavcodec/allcodecs.c  |  1 +
 libavcodec/codec_desc.c |  7 +++++++
 libavcodec/codec_id.h   |  1 +
 libavcodec/utils.c      |  1 +
 6 files changed, 42 insertions(+)

diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 08c5240a4c..1e6e00b154 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -956,6 +956,7 @@ OBJS-$(CONFIG_ADPCM_AGM_DECODER)          += adpcm.o adpcm_data.o
 OBJS-$(CONFIG_ADPCM_AICA_DECODER)         += adpcm.o adpcm_data.o
 OBJS-$(CONFIG_ADPCM_ARGO_DECODER)         += adpcm.o adpcm_data.o
 OBJS-$(CONFIG_ADPCM_ARGO_ENCODER)         += adpcm.o adpcm_data.o adpcmenc.o
+OBJS-$(CONFIG_ADPCM_CIRCUS_DECODER)       += adpcm.o adpcm_data.o
 OBJS-$(CONFIG_ADPCM_CT_DECODER)           += adpcm.o adpcm_data.o
 OBJS-$(CONFIG_ADPCM_DTK_DECODER)          += adpcm.o adpcm_data.o
 OBJS-$(CONFIG_ADPCM_EA_DECODER)           += adpcm.o adpcm_data.o
diff --git a/libavcodec/adpcm.c b/libavcodec/adpcm.c
index 9381bdcf2a..76404bcf08 100644
--- a/libavcodec/adpcm.c
+++ b/libavcodec/adpcm.c
@@ -738,6 +738,27 @@ static inline int16_t adpcm_mtaf_expand_nibble(ADPCMChannelStatus *c, uint8_t ni
     return c->predictor;
 }
 
+static inline int16_t adpcm_circus_expand_nibble(ADPCMChannelStatus *c, uint8_t nibble)
+{
+    int32_t sample = c->predictor;
+    int32_t scale = c->step;
+    int32_t code = sign_extend(nibble, 8);
+
+    sample += code * (1 << scale);
+    if (code == 0) {
+        scale--;
+    } else if (code == 127 || code == -128) {
+        scale++;
+    }
+    scale = av_clip(scale, 0, 8);
+    sample = av_clip_int16(sample);
+
+    c->predictor = sample;
+    c->step = scale;
+
+    return sample;
+}
+
 static inline int16_t adpcm_zork_expand_nibble(ADPCMChannelStatus *c, uint8_t nibble)
 {
     int16_t index = c->step_index;
@@ -1363,6 +1384,7 @@ static int get_nb_samples(AVCodecContext *avctx, GetByteContext *gb,
     case AV_CODEC_ID_ADPCM_ARGO:
         nb_samples = buf_size / avctx->block_align * 32;
         break;
+    case AV_CODEC_ID_ADPCM_CIRCUS:
     case AV_CODEC_ID_ADPCM_ZORK:
         nb_samples = buf_size / ch;
         break;
@@ -2794,6 +2816,14 @@ static int adpcm_decode_frame(AVCodecContext *avctx, AVFrame *frame,
             }
         }
         ) /* End of CASE */
+    CASE(ADPCM_CIRCUS,
+        for (int n = 0; n < nb_samples; n++) {
+            for (int ch = 0; ch < channels; ch++) {
+                int v = bytestream2_get_byteu(&gb);
+                *samples++ = adpcm_circus_expand_nibble(&c->status[ch], v);
+            }
+        }
+        ) /* End of CASE */
     CASE(ADPCM_ZORK,
         for (int n = 0; n < nb_samples * channels; n++) {
             int v = bytestream2_get_byteu(&gb);
@@ -2907,6 +2937,7 @@ ADPCM_DECODER(ADPCM_AFC,         sample_fmts_s16p, adpcm_afc,         "ADPCM Nin
 ADPCM_DECODER(ADPCM_AGM,         sample_fmts_s16,  adpcm_agm,         "ADPCM AmuseGraphics Movie")
 ADPCM_DECODER(ADPCM_AICA,        sample_fmts_s16p, adpcm_aica,        "ADPCM Yamaha AICA")
 ADPCM_DECODER(ADPCM_ARGO,        sample_fmts_s16p, adpcm_argo,        "ADPCM Argonaut Games")
+ADPCM_DECODER(ADPCM_CIRCUS,      sample_fmts_s16,  adpcm_circus,      "ADPCM Circus")
 ADPCM_DECODER(ADPCM_CT,          sample_fmts_s16,  adpcm_ct,          "ADPCM Creative Technology")
 ADPCM_DECODER(ADPCM_DTK,         sample_fmts_s16p, adpcm_dtk,         "ADPCM Nintendo Gamecube DTK")
 ADPCM_DECODER(ADPCM_EA,          sample_fmts_s16,  adpcm_ea,          "ADPCM Electronic Arts")
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index 67e02ef7bb..77a13d9b0c 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -649,6 +649,7 @@ extern const FFCodec ff_adpcm_agm_decoder;
 extern const FFCodec ff_adpcm_aica_decoder;
 extern const FFCodec ff_adpcm_argo_decoder;
 extern const FFCodec ff_adpcm_argo_encoder;
+extern const FFCodec ff_adpcm_circus_decoder;
 extern const FFCodec ff_adpcm_ct_decoder;
 extern const FFCodec ff_adpcm_dtk_decoder;
 extern const FFCodec ff_adpcm_ea_decoder;
diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c
index 1493f34730..30793a2a26 100644
--- a/libavcodec/codec_desc.c
+++ b/libavcodec/codec_desc.c
@@ -2676,6 +2676,13 @@ static const AVCodecDescriptor codec_descriptors[] = {
         .long_name = NULL_IF_CONFIG_SMALL("ADPCM Playstation C"),
         .props     = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY,
     },
+    {
+        .id        = AV_CODEC_ID_ADPCM_CIRCUS,
+        .type      = AVMEDIA_TYPE_AUDIO,
+        .name      = "adpcm_circus",
+        .long_name = NULL_IF_CONFIG_SMALL("ADPCM Circus"),
+        .props     = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY,
+    },
 
     /* AMR */
     {
diff --git a/libavcodec/codec_id.h b/libavcodec/codec_id.h
index 975ebbe880..feb4d61708 100644
--- a/libavcodec/codec_id.h
+++ b/libavcodec/codec_id.h
@@ -433,6 +433,7 @@ enum AVCodecID {
     AV_CODEC_ID_ADPCM_IMA_HVQM2,
     AV_CODEC_ID_ADPCM_IMA_MAGIX,
     AV_CODEC_ID_ADPCM_PSXC,
+    AV_CODEC_ID_ADPCM_CIRCUS,
 
     /* AMR */
     AV_CODEC_ID_AMR_NB = 0x12000,
diff --git a/libavcodec/utils.c b/libavcodec/utils.c
index b65e10827e..d89e886a08 100644
--- a/libavcodec/utils.c
+++ b/libavcodec/utils.c
@@ -488,6 +488,7 @@ int av_get_exact_bits_per_sample(enum AVCodecID codec_id)
     case AV_CODEC_ID_CBD2_DPCM:
     case AV_CODEC_ID_DERF_DPCM:
     case AV_CODEC_ID_WADY_DPCM:
+    case AV_CODEC_ID_ADPCM_CIRCUS:
         return 8;
     case AV_CODEC_ID_PCM_S16BE:
     case AV_CODEC_ID_PCM_S16BE_PLANAR:
-- 
2.49.1


From da35b4f120683790e5c1dbaf2998d1b46dc5b6aa Mon Sep 17 00:00:00 2001
From: Paul B Mahol <onemda@gmail.com>
Date: Sat, 8 Mar 2025 19:40:46 +0000
Subject: [PATCH 13/15] avcodec: add ADPCM IMA Escape audio decoder

(cherry picked from commit 4a663e78c4421da226e7d480d6767de803ee2122)
---
 libavcodec/Makefile     |  1 +
 libavcodec/adpcm.c      | 32 ++++++++++++++++++++++++++++++++
 libavcodec/allcodecs.c  |  1 +
 libavcodec/codec_desc.c |  7 +++++++
 libavcodec/codec_id.h   |  1 +
 libavformat/rpl.c       |  2 +-
 6 files changed, 43 insertions(+), 1 deletion(-)

diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 1e6e00b154..6c2412df0d 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -985,6 +985,7 @@ OBJS-$(CONFIG_ADPCM_IMA_DK3_DECODER)      += adpcm.o adpcm_data.o
 OBJS-$(CONFIG_ADPCM_IMA_DK4_DECODER)      += adpcm.o adpcm_data.o
 OBJS-$(CONFIG_ADPCM_IMA_EA_EACS_DECODER)  += adpcm.o adpcm_data.o
 OBJS-$(CONFIG_ADPCM_IMA_EA_SEAD_DECODER)  += adpcm.o adpcm_data.o
+OBJS-$(CONFIG_ADPCM_IMA_ESCAPE_DECODER)   += adpcm.o adpcm_data.o
 OBJS-$(CONFIG_ADPCM_IMA_HVQM2_DECODER)    += adpcm.o adpcm_data.o
 OBJS-$(CONFIG_ADPCM_IMA_HVQM4_DECODER)    += adpcm.o adpcm_data.o
 OBJS-$(CONFIG_ADPCM_IMA_ISS_DECODER)      += adpcm.o adpcm_data.o
diff --git a/libavcodec/adpcm.c b/libavcodec/adpcm.c
index 76404bcf08..c782ed007e 100644
--- a/libavcodec/adpcm.c
+++ b/libavcodec/adpcm.c
@@ -418,6 +418,29 @@ static inline int16_t adpcm_agm_expand_nibble(ADPCMChannelStatus *c, int8_t nibb
     return pred;
 }
 
+static inline int16_t adpcm_ima_escape_expand_nibble(ADPCMChannelStatus *c, int8_t nibble)
+{
+    int step_index;
+    int predictor;
+    int sign, delta, diff, step;
+
+    step = ff_adpcm_step_table[c->step_index];
+    step_index = c->step_index + ff_adpcm_index_table[(unsigned)nibble];
+    step_index = av_clip(step_index, 0, 88);
+
+    sign = nibble & 8;
+    delta = nibble & 7;
+    diff = (delta * step) >> 2;
+    predictor = c->predictor;
+    if (sign) predictor -= diff;
+    else predictor += diff;
+
+    c->predictor = av_clip_int16(predictor);
+    c->step_index = step_index;
+
+    return (int16_t)c->predictor;
+}
+
 static inline int16_t adpcm_ima_expand_nibble(ADPCMChannelStatus *c, int8_t nibble, int shift)
 {
     int step_index;
@@ -1169,6 +1192,7 @@ static int get_nb_samples(AVCodecContext *avctx, GetByteContext *gb,
     case AV_CODEC_ID_ADPCM_IMA_APC:
     case AV_CODEC_ID_ADPCM_IMA_CUNNING:
     case AV_CODEC_ID_ADPCM_IMA_EA_SEAD:
+    case AV_CODEC_ID_ADPCM_IMA_ESCAPE:
     case AV_CODEC_ID_ADPCM_IMA_OKI:
     case AV_CODEC_ID_ADPCM_IMA_WS:
     case AV_CODEC_ID_ADPCM_YAMAHA:
@@ -2013,6 +2037,13 @@ static int adpcm_decode_frame(AVCodecContext *avctx, AVFrame *frame,
             bytestream2_skip(&gb, bytes_remaining);
         }
         ) /* End of CASE */
+    CASE(ADPCM_IMA_ESCAPE,
+        for (int n = nb_samples >> (1 - st); n > 0; n--) {
+            int byte = bytestream2_get_byteu(&gb);
+            *samples++ = adpcm_ima_escape_expand_nibble(&c->status[0],  byte >> 4);
+            *samples++ = adpcm_ima_escape_expand_nibble(&c->status[st], byte & 0xF);
+        }
+        ) /* End of CASE */
     CASE(ADPCM_IMA_EA_EACS,
         for (int i = 0; i <= st; i++) {
             c->status[i].step_index = bytestream2_get_le32u(&gb);
@@ -2956,6 +2987,7 @@ ADPCM_DECODER(ADPCM_IMA_DK3,     sample_fmts_s16,  adpcm_ima_dk3,     "ADPCM IMA
 ADPCM_DECODER(ADPCM_IMA_DK4,     sample_fmts_s16,  adpcm_ima_dk4,     "ADPCM IMA Duck DK4")
 ADPCM_DECODER(ADPCM_IMA_EA_EACS, sample_fmts_s16,  adpcm_ima_ea_eacs, "ADPCM IMA Electronic Arts EACS")
 ADPCM_DECODER(ADPCM_IMA_EA_SEAD, sample_fmts_s16,  adpcm_ima_ea_sead, "ADPCM IMA Electronic Arts SEAD")
+ADPCM_DECODER(ADPCM_IMA_ESCAPE,  sample_fmts_s16,  adpcm_ima_escape,  "ADPCM IMA Acorn Escape")
 ADPCM_DECODER(ADPCM_IMA_HVQM2,   sample_fmts_s16,  adpcm_ima_hvqm2,   "ADPCM IMA HVQM2")
 ADPCM_DECODER(ADPCM_IMA_HVQM4,   sample_fmts_s16,  adpcm_ima_hvqm4,   "ADPCM IMA HVQM4")
 ADPCM_DECODER(ADPCM_IMA_ISS,     sample_fmts_s16,  adpcm_ima_iss,     "ADPCM IMA Funcom ISS")
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index 77a13d9b0c..ae48c414e8 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -678,6 +678,7 @@ extern const FFCodec ff_adpcm_ima_dk3_decoder;
 extern const FFCodec ff_adpcm_ima_dk4_decoder;
 extern const FFCodec ff_adpcm_ima_ea_eacs_decoder;
 extern const FFCodec ff_adpcm_ima_ea_sead_decoder;
+extern const FFCodec ff_adpcm_ima_escape_decoder;
 extern const FFCodec ff_adpcm_ima_hvqm2_decoder;
 extern const FFCodec ff_adpcm_ima_hvqm4_decoder;
 extern const FFCodec ff_adpcm_ima_iss_decoder;
diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c
index 30793a2a26..526a85e262 100644
--- a/libavcodec/codec_desc.c
+++ b/libavcodec/codec_desc.c
@@ -2683,6 +2683,13 @@ static const AVCodecDescriptor codec_descriptors[] = {
         .long_name = NULL_IF_CONFIG_SMALL("ADPCM Circus"),
         .props     = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY,
     },
+    {
+        .id        = AV_CODEC_ID_ADPCM_IMA_ESCAPE,
+        .type      = AVMEDIA_TYPE_AUDIO,
+        .name      = "adpcm_ima_escape",
+        .long_name = NULL_IF_CONFIG_SMALL("ADPCM IMA Acorn Escape"),
+        .props     = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY,
+    },
 
     /* AMR */
     {
diff --git a/libavcodec/codec_id.h b/libavcodec/codec_id.h
index feb4d61708..8c98ac6335 100644
--- a/libavcodec/codec_id.h
+++ b/libavcodec/codec_id.h
@@ -434,6 +434,7 @@ enum AVCodecID {
     AV_CODEC_ID_ADPCM_IMA_MAGIX,
     AV_CODEC_ID_ADPCM_PSXC,
     AV_CODEC_ID_ADPCM_CIRCUS,
+    AV_CODEC_ID_ADPCM_IMA_ESCAPE,
 
     /* AMR */
     AV_CODEC_ID_AMR_NB = 0x12000,
diff --git a/libavformat/rpl.c b/libavformat/rpl.c
index b30d769efb..781dabf7ba 100644
--- a/libavformat/rpl.c
+++ b/libavformat/rpl.c
@@ -250,7 +250,7 @@ static int rpl_read_header(AVFormatContext *s)
                     // are all unsigned.
                     ast->codecpar->codec_id = AV_CODEC_ID_PCM_U8;
                 } else if (ast->codecpar->bits_per_coded_sample == 4) {
-                    ast->codecpar->codec_id = AV_CODEC_ID_ADPCM_IMA_EA_SEAD;
+                    ast->codecpar->codec_id = AV_CODEC_ID_ADPCM_IMA_ESCAPE;
                 }
                 break;
         }
-- 
2.49.1


From 5ea4971647978ff29d12ed89ee8106ee6ff795ac Mon Sep 17 00:00:00 2001
From: Paul B Mahol <onemda@gmail.com>
Date: Mon, 17 Mar 2025 21:01:16 +0000
Subject: [PATCH 14/15] avcodec/adpcm: improve decooding output for 4-bit ADPCM
 IMA WAV

(cherry picked from commit f11422f1a6251e2b3c42b4044efbc722b863778d)
---
 libavcodec/adpcm.c                     | 4 ++--
 tests/ref/acodec/adpcm-ima_wav         | 4 ++--
 tests/ref/acodec/adpcm-ima_wav-trellis | 4 ++--
 tests/ref/fate/adpcm-ima_wav-stereo    | 2 +-
 4 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/libavcodec/adpcm.c b/libavcodec/adpcm.c
index c782ed007e..13003db760 100644
--- a/libavcodec/adpcm.c
+++ b/libavcodec/adpcm.c
@@ -1549,8 +1549,8 @@ static int adpcm_decode_frame(AVCodecContext *avctx, AVFrame *frame,
                     samples = &samples_p[i][1 + n * 8];
                     for (int m = 0; m < 8; m += 2) {
                         int v = bytestream2_get_byteu(&gb);
-                        samples[m    ] = adpcm_ima_expand_nibble(cs, v & 0x0F, 3);
-                        samples[m + 1] = adpcm_ima_expand_nibble(cs, v >> 4  , 3);
+                        samples[m    ] = ff_adpcm_ima_qt_expand_nibble(cs, v & 0x0F);
+                        samples[m + 1] = ff_adpcm_ima_qt_expand_nibble(cs, v >> 4);
                     }
                 }
             }
diff --git a/tests/ref/acodec/adpcm-ima_wav b/tests/ref/acodec/adpcm-ima_wav
index 44ca53a565..b2cc518b1e 100644
--- a/tests/ref/acodec/adpcm-ima_wav
+++ b/tests/ref/acodec/adpcm-ima_wav
@@ -1,4 +1,4 @@
 af0b82a719762cc6e1a952a6081231cf *tests/data/fate/acodec-adpcm-ima_wav.wav
 267324 tests/data/fate/acodec-adpcm-ima_wav.wav
-78a2af1c895792d0c221d127bdd48ece *tests/data/fate/acodec-adpcm-ima_wav.out.wav
-stddev:  903.51 PSNR: 37.21 MAXDIFF:34026 bytes:  1058400/  1061748
+a57d7b0ca564b5fed4bf78fc9f91d8e2 *tests/data/fate/acodec-adpcm-ima_wav.out.wav
+stddev:  903.56 PSNR: 37.21 MAXDIFF:34029 bytes:  1058400/  1061748
diff --git a/tests/ref/acodec/adpcm-ima_wav-trellis b/tests/ref/acodec/adpcm-ima_wav-trellis
index 29c28edddf..008d1e4b62 100644
--- a/tests/ref/acodec/adpcm-ima_wav-trellis
+++ b/tests/ref/acodec/adpcm-ima_wav-trellis
@@ -1,4 +1,4 @@
 6f0df0f3275f833c341d63b9054caebb *tests/data/fate/acodec-adpcm-ima_wav-trellis.wav
 267324 tests/data/fate/acodec-adpcm-ima_wav-trellis.wav
-26a9b280c14737b159c56e60181f1170 *tests/data/fate/acodec-adpcm-ima_wav-trellis.out.wav
-stddev:  710.03 PSNR: 39.30 MAXDIFF:25944 bytes:  1058400/  1061748
+1af83218cde84bd7cd2297c04ef97f79 *tests/data/fate/acodec-adpcm-ima_wav-trellis.out.wav
+stddev:  710.09 PSNR: 39.30 MAXDIFF:25941 bytes:  1058400/  1061748
diff --git a/tests/ref/fate/adpcm-ima_wav-stereo b/tests/ref/fate/adpcm-ima_wav-stereo
index cb6a481999..2a36800951 100644
--- a/tests/ref/fate/adpcm-ima_wav-stereo
+++ b/tests/ref/fate/adpcm-ima_wav-stereo
@@ -1 +1 @@
-1ee96f1efc09251a732621049dc5b66e
+b4697f4f64c12afb37acfebd5f7a756c
-- 
2.49.1


From 02ea6cf9a8fb678bb36322b9b71d5a8d43427440 Mon Sep 17 00:00:00 2001
From: asivery <asivery@protonmail.com>
Date: Sat, 15 Jun 2024 07:47:40 +0200
Subject: [PATCH 15/15] avformat/aeadec, avcodec/atrac1: Fix 8 and 4-channel
 ATRAC1 support

Signed-off-by: asivery <asivery@protonmail.com>
(cherry picked from commit 81cdf42222961c2959f1ede2d86fea0d1dcbbfcb)
---
 libavcodec/atrac1.c  | 12 ++++++------
 libavformat/aeadec.c |  2 +-
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/libavcodec/atrac1.c b/libavcodec/atrac1.c
index f0bef9b9e6..b708c31897 100644
--- a/libavcodec/atrac1.c
+++ b/libavcodec/atrac1.c
@@ -49,7 +49,7 @@
 #define AT1_SU_SAMPLES   512                ///< number of samples in a sound unit
 #define AT1_FRAME_SIZE   AT1_SU_SIZE * 2
 #define AT1_SU_MAX_BITS  AT1_SU_SIZE * 8
-#define AT1_MAX_CHANNELS 2
+#define AT1_MAX_CHANNELS 8
 
 #define AT1_QMF_BANDS    3
 #define IDX_LOW_BAND     0
@@ -339,7 +339,7 @@ static av_cold int atrac1_decode_init(AVCodecContext *avctx)
     AVFloatDSPContext *fdsp;
     int channels = avctx->ch_layout.nb_channels;
     float scale = -1.0 / (1 << 15);
-    int ret;
+    int ret, ch;
 
     avctx->sample_fmt = AV_SAMPLE_FMT_FLTP;
 
@@ -380,10 +380,10 @@ static av_cold int atrac1_decode_init(AVCodecContext *avctx)
     q->bands[2] = q->high;
 
     /* Prepare the mdct overlap buffers */
-    q->SUs[0].spectrum[0] = q->SUs[0].spec1;
-    q->SUs[0].spectrum[1] = q->SUs[0].spec2;
-    q->SUs[1].spectrum[0] = q->SUs[1].spec1;
-    q->SUs[1].spectrum[1] = q->SUs[1].spec2;
+    for (ch = 0; ch < AT1_MAX_CHANNELS; ch++) {
+        q->SUs[ch].spectrum[0] = q->SUs[ch].spec1;
+        q->SUs[ch].spectrum[1] = q->SUs[ch].spec2;
+    }
 
     return 0;
 }
diff --git a/libavformat/aeadec.c b/libavformat/aeadec.c
index be18e7b725..0a3d09a89d 100644
--- a/libavformat/aeadec.c
+++ b/libavformat/aeadec.c
@@ -84,7 +84,7 @@ static int aea_read_header(AVFormatContext *s)
     st->codecpar->sample_rate    = 44100;
     st->codecpar->bit_rate       = 146000 * channels;
 
-    if (channels != 1 && channels != 2) {
+    if (channels < 1 || channels > 8) {
         av_log(s, AV_LOG_ERROR, "Channels %d not supported!\n", channels);
         return AVERROR_INVALIDDATA;
     }
-- 
2.49.1

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2025-08-24  3:02 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-08-24  3:01 [FFmpeg-devel] [PATCH] A few new decoders and a parser from almpeg (PR #20325) michaelni via ffmpeg-devel

Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

This inbox may be cloned and mirrored by anyone:

	git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \
		ffmpegdev@gitmailbox.com
	public-inbox-index ffmpegdev

Example config snippet for mirrors.


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git