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] XMD demuxer and decoder
@ 2023-01-25 21:28 Paul B Mahol
  2023-01-27 22:42 ` Michael Niedermayer
  0 siblings, 1 reply; 3+ messages in thread
From: Paul B Mahol @ 2023-01-25 21:28 UTC (permalink / raw)
  To: FFmpeg development discussions and patches

[-- Attachment #1: Type: text/plain, Size: 16 bytes --]

Patch attached.

[-- Attachment #2: 0001-avcodec-add-ADPCM-XMD-decoder.patch --]
[-- Type: text/x-patch, Size: 6748 bytes --]

From 8a48d62c020d6361a0ae1d4a4124c0594ecfe669 Mon Sep 17 00:00:00 2001
From: Paul B Mahol <onemda@gmail.com>
Date: Wed, 25 Jan 2023 19:31:44 +0100
Subject: [PATCH 1/2] avcodec: add ADPCM XMD decoder

Signed-off-by: Paul B Mahol <onemda@gmail.com>
---
 libavcodec/Makefile     |  1 +
 libavcodec/adpcm.c      | 44 +++++++++++++++++++++++++++++++++++++++++
 libavcodec/allcodecs.c  |  1 +
 libavcodec/codec_desc.c |  7 +++++++
 libavcodec/codec_id.h   |  1 +
 libavcodec/utils.c      |  3 +++
 6 files changed, 57 insertions(+)

diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index e691c8d180..286a0bf528 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -959,6 +959,7 @@ OBJS-$(CONFIG_ADPCM_THP_DECODER)          += adpcm.o adpcm_data.o
 OBJS-$(CONFIG_ADPCM_THP_LE_DECODER)       += adpcm.o adpcm_data.o
 OBJS-$(CONFIG_ADPCM_VIMA_DECODER)         += vima.o adpcm_data.o
 OBJS-$(CONFIG_ADPCM_XA_DECODER)           += adpcm.o adpcm_data.o
+OBJS-$(CONFIG_ADPCM_XMD_DECODER)          += adpcm.o adpcm_data.o
 OBJS-$(CONFIG_ADPCM_YAMAHA_DECODER)       += adpcm.o adpcm_data.o
 OBJS-$(CONFIG_ADPCM_YAMAHA_ENCODER)       += adpcmenc.o adpcm_data.o
 OBJS-$(CONFIG_ADPCM_ZORK_DECODER)         += adpcm.o adpcm_data.o
diff --git a/libavcodec/adpcm.c b/libavcodec/adpcm.c
index 841538b138..451696932d 100644
--- a/libavcodec/adpcm.c
+++ b/libavcodec/adpcm.c
@@ -324,6 +324,7 @@ static av_cold int adpcm_decode_init(AVCodecContext * avctx)
     case AV_CODEC_ID_ADPCM_IMA_WAV:
     case AV_CODEC_ID_ADPCM_4XM:
     case AV_CODEC_ID_ADPCM_XA:
+    case AV_CODEC_ID_ADPCM_XMD:
     case AV_CODEC_ID_ADPCM_EA_R1:
     case AV_CODEC_ID_ADPCM_EA_R2:
     case AV_CODEC_ID_ADPCM_EA_R3:
@@ -1043,6 +1044,9 @@ static int get_nb_samples(AVCodecContext *avctx, GetByteContext *gb,
     case AV_CODEC_ID_ADPCM_XA:
         nb_samples = (buf_size / 128) * 224 / ch;
         break;
+    case AV_CODEC_ID_ADPCM_XMD:
+        nb_samples = buf_size / (21 * ch) * 32;
+        break;
     case AV_CODEC_ID_ADPCM_DTK:
     case AV_CODEC_ID_ADPCM_PSX:
         nb_samples = buf_size / (16 * ch) * 28;
@@ -1553,6 +1557,45 @@ static int adpcm_decode_frame(AVCodecContext *avctx, AVFrame *frame,
         }
         bytestream2_seek(&gb, 0, SEEK_END);
         ) /* End of CASE */
+    CASE(ADPCM_XMD,
+        int bytes_remaining, block = 0;
+        while (bytestream2_get_bytes_left(&gb) >= 21 * channels) {
+            for (int channel = 0; channel < channels; channel++) {
+                int16_t *out = samples_p[channel] + block * 32;
+                int16_t history[2];
+                uint16_t scale;
+
+                history[1] = sign_extend(bytestream2_get_le16(&gb), 16);
+                history[0] = sign_extend(bytestream2_get_le16(&gb), 16);
+                scale = bytestream2_get_le16(&gb);
+
+                out[0] = history[1];
+                out[1] = history[0];
+
+                for (int n = 0; n < 15; n++) {
+                    unsigned byte = bytestream2_get_byte(&gb);
+                    int32_t nibble[2];
+
+                    nibble[0] = sign_extend(byte & 15, 4);
+                    nibble[1] = sign_extend(byte >> 4, 4);
+
+                    out[2+n*2] = (nibble[0]*(scale<<14) + (history[0]*29336) - (history[1]*13136)) >> 14;
+                    history[1] = history[0];
+                    history[0] = out[2+n*2];
+
+                    out[2+n*2+1] = (nibble[1]*(scale<<14) + (history[0]*29336) - (history[1]*13136)) >> 14;
+                    history[1] = history[0];
+                    history[0] = out[2+n*2+1];
+                }
+            }
+
+            block++;
+        }
+        bytes_remaining = bytestream2_get_bytes_left(&gb);
+        if (bytes_remaining > 0) {
+            bytestream2_skip(&gb, bytes_remaining);
+        }
+        ) /* End of CASE */
     CASE(ADPCM_XA,
         int16_t *out0 = samples_p[0];
         int16_t *out1 = samples_p[1];
@@ -2350,5 +2393,6 @@ ADPCM_DECODER(ADPCM_SWF,         sample_fmts_s16,  adpcm_swf,         "ADPCM Sho
 ADPCM_DECODER(ADPCM_THP_LE,      sample_fmts_s16p, adpcm_thp_le,      "ADPCM Nintendo THP (little-endian)")
 ADPCM_DECODER(ADPCM_THP,         sample_fmts_s16p, adpcm_thp,         "ADPCM Nintendo THP")
 ADPCM_DECODER(ADPCM_XA,          sample_fmts_s16p, adpcm_xa,          "ADPCM CDROM XA")
+ADPCM_DECODER(ADPCM_XMD,         sample_fmts_s16p, adpcm_xmd,         "ADPCM Konami XMD")
 ADPCM_DECODER(ADPCM_YAMAHA,      sample_fmts_s16,  adpcm_yamaha,      "ADPCM Yamaha")
 ADPCM_DECODER(ADPCM_ZORK,        sample_fmts_s16,  adpcm_zork,        "ADPCM Zork")
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index 74e1b00e96..95b8d935d3 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -696,6 +696,7 @@ extern const FFCodec ff_adpcm_thp_decoder;
 extern const FFCodec ff_adpcm_thp_le_decoder;
 extern const FFCodec ff_adpcm_vima_decoder;
 extern const FFCodec ff_adpcm_xa_decoder;
+extern const FFCodec ff_adpcm_xmd_decoder;
 extern const FFCodec ff_adpcm_yamaha_encoder;
 extern const FFCodec ff_adpcm_yamaha_decoder;
 extern const FFCodec ff_adpcm_zork_decoder;
diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c
index 6ecdf1002b..782a93218f 100644
--- a/libavcodec/codec_desc.c
+++ b/libavcodec/codec_desc.c
@@ -2536,6 +2536,13 @@ static const AVCodecDescriptor codec_descriptors[] = {
         .long_name = NULL_IF_CONFIG_SMALL("ADPCM IMA Acorn Replay"),
         .props     = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY,
     },
+    {
+        .id        = AV_CODEC_ID_ADPCM_XMD,
+        .type      = AVMEDIA_TYPE_AUDIO,
+        .name      = "adpcm_xmd",
+        .long_name = NULL_IF_CONFIG_SMALL("ADPCM Konami XMD"),
+        .props     = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY,
+    },
 
     /* AMR */
     {
diff --git a/libavcodec/codec_id.h b/libavcodec/codec_id.h
index ba3b432387..97d0aee86e 100644
--- a/libavcodec/codec_id.h
+++ b/libavcodec/codec_id.h
@@ -413,6 +413,7 @@ enum AVCodecID {
     AV_CODEC_ID_ADPCM_IMA_CUNNING,
     AV_CODEC_ID_ADPCM_IMA_MOFLEX,
     AV_CODEC_ID_ADPCM_IMA_ACORN,
+    AV_CODEC_ID_ADPCM_XMD,
 
     /* AMR */
     AV_CODEC_ID_AMR_NB = 0x12000,
diff --git a/libavcodec/utils.c b/libavcodec/utils.c
index 808a7b8f5b..182ff64ee1 100644
--- a/libavcodec/utils.c
+++ b/libavcodec/utils.c
@@ -767,6 +767,9 @@ static int get_audio_frame_duration(enum AVCodecID id, int sr, int ch, int ba,
                 case AV_CODEC_ID_ADPCM_MTAF:
                     tmp = blocks * (ba - 16LL) * 2 / ch;
                     break;
+                case AV_CODEC_ID_ADPCM_XMD:
+                    tmp = blocks * 32;
+                    break;
                 }
                 if (tmp) {
                     if (tmp != (int)tmp)
-- 
2.39.1


[-- Attachment #3: 0002-avformat-add-XMD-demuxer.patch --]
[-- Type: text/x-patch, Size: 4254 bytes --]

From 280452a604103dbc1088bbeebaf533fdc4bc8eba Mon Sep 17 00:00:00 2001
From: Paul B Mahol <onemda@gmail.com>
Date: Wed, 25 Jan 2023 19:16:03 +0100
Subject: [PATCH 2/2] avformat: add XMD demuxer

Signed-off-by: Paul B Mahol <onemda@gmail.com>
---
 libavformat/Makefile     |  1 +
 libavformat/allformats.c |  1 +
 libavformat/xmd.c        | 80 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 82 insertions(+)
 create mode 100644 libavformat/xmd.c

diff --git a/libavformat/Makefile b/libavformat/Makefile
index 9052b023a7..89dbde9454 100644
--- a/libavformat/Makefile
+++ b/libavformat/Makefile
@@ -622,6 +622,7 @@ OBJS-$(CONFIG_WVE_DEMUXER)               += wvedec.o pcm.o
 OBJS-$(CONFIG_WV_MUXER)                  += wvenc.o wv.o apetag.o img2.o
 OBJS-$(CONFIG_XA_DEMUXER)                += xa.o
 OBJS-$(CONFIG_XBIN_DEMUXER)              += bintext.o sauce.o
+OBJS-$(CONFIG_XMD_DEMUXER)               += xmd.o
 OBJS-$(CONFIG_XMV_DEMUXER)               += xmv.o
 OBJS-$(CONFIG_XVAG_DEMUXER)              += xvag.o
 OBJS-$(CONFIG_XWMA_DEMUXER)              += xwma.o
diff --git a/libavformat/allformats.c b/libavformat/allformats.c
index 7c01c7f098..b5a3d909bd 100644
--- a/libavformat/allformats.c
+++ b/libavformat/allformats.c
@@ -502,6 +502,7 @@ extern const AVInputFormat  ff_wv_demuxer;
 extern const AVOutputFormat ff_wv_muxer;
 extern const AVInputFormat  ff_xa_demuxer;
 extern const AVInputFormat  ff_xbin_demuxer;
+extern const AVInputFormat  ff_xmd_demuxer;
 extern const AVInputFormat  ff_xmv_demuxer;
 extern const AVInputFormat  ff_xvag_demuxer;
 extern const AVInputFormat  ff_xwma_demuxer;
diff --git a/libavformat/xmd.c b/libavformat/xmd.c
new file mode 100644
index 0000000000..3dd80f4fde
--- /dev/null
+++ b/libavformat/xmd.c
@@ -0,0 +1,80 @@
+/*
+ * XMD demuxer
+ * Copyright (c) 2023 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
+ */
+
+#include "libavutil/channel_layout.h"
+#include "libavutil/intreadwrite.h"
+#include "avformat.h"
+#include "demux.h"
+#include "internal.h"
+#include "pcm.h"
+
+static int xmd_probe(const AVProbeData *p)
+{
+    if ((AV_RL32(p->buf) & 0xFFFFFF) != MKTAG('x','m','d',0))
+        return 0;
+    if (p->buf[3] == 0 ||
+        AV_RL16(p->buf+4) == 0 ||
+        AV_RL32(p->buf+6) == 0)
+        return 0;
+
+    return AVPROBE_SCORE_MAX / 3;
+}
+
+static int xmd_read_header(AVFormatContext *s)
+{
+    AVIOContext *pb = s->pb;
+    AVCodecParameters *par;
+    int channels;
+    AVStream *st;
+
+    avio_skip(pb, 3);
+
+    st = avformat_new_stream(s, NULL);
+    if (!st)
+        return AVERROR(ENOMEM);
+
+    par              = st->codecpar;
+    par->codec_type  = AVMEDIA_TYPE_AUDIO;
+    par->codec_id    = AV_CODEC_ID_ADPCM_XMD;
+    channels         = avio_r8(pb);
+    if (channels == 0)
+        return AVERROR_INVALIDDATA;
+    av_channel_layout_default(&par->ch_layout, channels);
+    par->sample_rate = avio_rl16(pb);
+    if (par->sample_rate <= 0)
+        return AVERROR_INVALIDDATA;
+    par->block_align = 21 * channels;
+    st->duration = (avio_rl32(pb) / par->block_align) * 32LL;
+    avpriv_set_pts_info(st, 64, 1, par->sample_rate);
+    avio_skip(pb, 7);
+
+    return 0;
+}
+
+const AVInputFormat ff_xmd_demuxer = {
+    .name           = "xmd",
+    .long_name      = NULL_IF_CONFIG_SMALL("Konami XMD"),
+    .read_probe     = xmd_probe,
+    .read_header    = xmd_read_header,
+    .read_packet    = ff_pcm_read_packet,
+    .flags          = AVFMT_GENERIC_INDEX,
+    .extensions     = "xmd",
+};
-- 
2.39.1


[-- Attachment #4: Type: text/plain, Size: 251 bytes --]

_______________________________________________
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] 3+ messages in thread

end of thread, other threads:[~2023-01-30 17:37 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-01-25 21:28 [FFmpeg-devel] [PATCH] XMD demuxer and decoder Paul B Mahol
2023-01-27 22:42 ` Michael Niedermayer
2023-01-30 17:37   ` Paul B Mahol

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