* [FFmpeg-devel] [PATCH] avcodec/wmaprodec: add xma raw frame decoder (PR #20266)
@ 2025-08-17 8:49 Isaac Marovitz via ffmpeg-devel
0 siblings, 0 replies; only message in thread
From: Isaac Marovitz via ffmpeg-devel @ 2025-08-17 8:49 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Isaac Marovitz
PR #20266 opened by Isaac Marovitz (IsaacMarovitz)
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/20266
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/20266.patch
packets need to be handled externally
useful for hardware decoder emulation
Co-authored-by: Joel Linn <jl@conductive.de>
Signed-off-by: Isaac Marovitz <isaacryu@icloud.com>
From cc9a634af5b87ab0313fdfe84837532cd6750bb1 Mon Sep 17 00:00:00 2001
From: Isaac Marovitz <isaacryu@icloud.com>
Date: Sun, 6 Jul 2025 13:23:15 +0100
Subject: [PATCH] avcodec/wmaprodec: add xma raw frame decoder
packets need to be handled externally
useful for hardware decoder emulation
Co-authored-by: Joel Linn <jl@conductive.de>
Signed-off-by: Isaac Marovitz <isaacryu@icloud.com>
---
configure | 1 +
doc/APIchanges | 3 ++
doc/general_contents.texi | 2 +
libavcodec/Makefile | 1 +
libavcodec/allcodecs.c | 1 +
libavcodec/codec_desc.c | 7 ++++
libavcodec/codec_id.h | 1 +
libavcodec/version.h | 2 +-
libavcodec/wmaprodec.c | 88 +++++++++++++++++++++++++++++++++++++++
9 files changed, 105 insertions(+), 1 deletion(-)
diff --git a/configure b/configure
index e1809a3e58..ea70294559 100755
--- a/configure
+++ b/configure
@@ -3179,6 +3179,7 @@ wmv3_decoder_select="vc1_decoder"
wmv3image_decoder_select="wmv3_decoder"
xma1_decoder_select="wmapro_decoder"
xma2_decoder_select="wmapro_decoder"
+xmaframes_decoder_select="wmapro_decoder"
ylc_decoder_select="bswapdsp"
zerocodec_decoder_select="inflate_wrapper"
zlib_decoder_select="inflate_wrapper"
diff --git a/doc/APIchanges b/doc/APIchanges
index 1ed8337d04..0e88b10a31 100644
--- a/doc/APIchanges
+++ b/doc/APIchanges
@@ -2,6 +2,9 @@ The last version increases of all libraries were on 2025-03-28
API changes, most recent first:
+2025-08-17 - xxxxxxxxxx - lavc 62.13.100 - codec_id.h
+ Add AV_CODEC_ID_XMAFRAMES.
+
2025-07-29 - 1c85a3832af - lavc 62.10.100 - smpte_436m.h
Add a new public header smpte_436m.h with API for
manipulating AV_CODEC_ID_SMPTE_436M_ANC data.
diff --git a/doc/general_contents.texi b/doc/general_contents.texi
index b9dab580f1..f194a72de2 100644
--- a/doc/general_contents.texi
+++ b/doc/general_contents.texi
@@ -770,6 +770,8 @@ library:
@tab Audio format used on the PS3.
@item xWMA @tab @tab X
@tab Microsoft audio container used by XAudio 2.
+@item XMA Frames @tab @tab X
+ @tab Microsoft audio format used in Xbox 360 games.
@item eXtended BINary text (XBIN) @tab @tab X
@item YUV4MPEG pipe @tab X @tab X
@item Psygnosis YOP @tab @tab X
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index fb22541f8d..7dc034907a 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -860,6 +860,7 @@ OBJS-$(CONFIG_XFACE_ENCODER) += xfaceenc.o xface.o
OBJS-$(CONFIG_XL_DECODER) += xl.o
OBJS-$(CONFIG_XMA1_DECODER) += wmaprodec.o wma.o wma_common.o
OBJS-$(CONFIG_XMA2_DECODER) += wmaprodec.o wma.o wma_common.o
+OBJS-$(CONFIG_XMAFRAMES_DECODER) += wmaprodec.o wma.o wma_common.o
OBJS-$(CONFIG_XPM_DECODER) += xpmdec.o
OBJS-$(CONFIG_XSUB_DECODER) += xsubdec.o
OBJS-$(CONFIG_XSUB_ENCODER) += xsubenc.o
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index f5ec2e01e8..a55dbb036e 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -558,6 +558,7 @@ extern const FFCodec ff_wmavoice_decoder;
extern const FFCodec ff_ws_snd1_decoder;
extern const FFCodec ff_xma1_decoder;
extern const FFCodec ff_xma2_decoder;
+extern const FFCodec ff_xmaframes_decoder;
/* PCM codecs */
extern const FFCodec ff_pcm_alaw_encoder;
diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c
index a065556e51..1f819cb136 100644
--- a/libavcodec/codec_desc.c
+++ b/libavcodec/codec_desc.c
@@ -3306,6 +3306,13 @@ static const AVCodecDescriptor codec_descriptors[] = {
.long_name = NULL_IF_CONFIG_SMALL("Xbox Media Audio 2"),
.props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY,
},
+ {
+ .id = AV_CODEC_ID_XMAFRAMES,
+ .type = AVMEDIA_TYPE_AUDIO,
+ .name = "xmaframes",
+ .long_name = NULL_IF_CONFIG_SMALL("Xbox Media Audio raw frames"),
+ .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY,
+ },
{
.id = AV_CODEC_ID_DST,
.type = AVMEDIA_TYPE_AUDIO,
diff --git a/libavcodec/codec_id.h b/libavcodec/codec_id.h
index c4842e61ff..7dfa0052b6 100644
--- a/libavcodec/codec_id.h
+++ b/libavcodec/codec_id.h
@@ -604,6 +604,7 @@ enum AVCodecID {
AV_CODEC_ID_SMPTE_2038,
AV_CODEC_ID_LCEVC,
AV_CODEC_ID_SMPTE_436M_ANC,
+ AV_CODEC_ID_XMAFRAMES,
AV_CODEC_ID_PROBE = 0x19000, ///< codec_id is not known (like AV_CODEC_ID_NONE) but lavf should attempt to identify it
diff --git a/libavcodec/version.h b/libavcodec/version.h
index da2264a097..755c90bbc1 100644
--- a/libavcodec/version.h
+++ b/libavcodec/version.h
@@ -29,7 +29,7 @@
#include "version_major.h"
-#define LIBAVCODEC_VERSION_MINOR 12
+#define LIBAVCODEC_VERSION_MINOR 13
#define LIBAVCODEC_VERSION_MICRO 100
#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
diff --git a/libavcodec/wmaprodec.c b/libavcodec/wmaprodec.c
index d87ed0433e..6cd81ce5ce 100644
--- a/libavcodec/wmaprodec.c
+++ b/libavcodec/wmaprodec.c
@@ -400,6 +400,11 @@ static av_cold int decode_init(WMAProDecodeCtx *s, AVCodecContext *avctx, int nu
s->bits_per_sample = 16;
channel_mask = 0; /* would need to aggregate from all streams */
s->nb_channels = edata_ptr[8 + 20*num_stream + 17]; /* nth stream config */
+ } else if (avctx->codec_id == AV_CODEC_ID_XMAFRAMES) {
+ s->decode_flags = 0x10d6;
+ s->bits_per_sample = 16;
+ channel_mask = 0;
+ s->nb_channels = avctx->ch_layout.nb_channels;
} else if (avctx->codec_id == AV_CODEC_ID_WMAPRO && avctx->extradata_size >= 18) {
s->decode_flags = AV_RL16(edata_ptr+14);
channel_mask = AV_RL32(edata_ptr+2);
@@ -2082,6 +2087,74 @@ static void xma_flush(AVCodecContext *avctx)
s->flushed = 0;
}
+static av_cold int xmaframes_decode_init(AVCodecContext* avctx)
+{
+ WMAProDecodeCtx *s = avctx->priv_data;
+
+ avctx->block_align = 2048;
+
+ return decode_init(s, avctx, 0);
+}
+
+static av_cold int xmaframes_decode_end(AVCodecContext* avctx)
+{
+ WMAProDecodeCtx *s = avctx->priv_data;
+
+ decode_end(s);
+
+ return 0;
+}
+
+static int xmaframes_decode_packet(AVCodecContext *avctx, AVFrame *frame,
+ int *got_frame_ptr, AVPacket *avpkt)
+{
+ WMAProDecodeCtx *s = avctx->priv_data;
+ GetBitContext* gb = &s->gb;
+ int ret, xma_frame_len = 0;
+ uint8_t padding_start, padding_end = 0;
+
+ if (avpkt->size < 3) {
+ av_log(avctx, AV_LOG_ERROR, "XMA Frame is to small, %d bytes\n", avpkt->size);
+ return AVERROR_INVALIDDATA;
+ }
+
+ s->buf_bit_size = avpkt->size << 3;
+ init_get_bits(gb, avpkt->data, s->buf_bit_size);
+
+ /** get padding sizes from first byte */
+ padding_start = get_bits(gb, 3);
+ padding_end = get_bits(gb, 3);
+ skip_bits(gb, 2);
+
+ /** move bit reader to start of xma frame */
+ skip_bits(gb, padding_start);
+
+
+ /** validate buffer size */
+ xma_frame_len = show_bits(gb, s->log2_frame_size);
+ if (s->buf_bit_size !=
+ 8 + padding_start + xma_frame_len + padding_end) {
+ av_log(avctx, AV_LOG_ERROR, "XMA Frame sizing incorrent: \n"
+ " s->buf_bit_size != (8 + padding_start + xma_frame_len + padding_end)\n"
+ "=> %d != 8 + (%d + %d + %d)\n",
+ s->buf_bit_size, padding_start, xma_frame_len, padding_end);
+ return AVERROR_INVALIDDATA;
+ }
+
+ save_bits(s, gb, xma_frame_len, 0);
+
+ /** get output buffer */
+ frame->nb_samples = s->samples_per_frame;
+ if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) {
+ s->packet_loss = 1;
+ return 0;
+ }
+
+ decode_frame(s, frame, got_frame_ptr);
+
+ return avpkt->size;
+}
+
/**
*@brief wmapro decoder
*/
@@ -2129,3 +2202,18 @@ const FFCodec ff_xma2_decoder = {
CODEC_SAMPLEFMTS(AV_SAMPLE_FMT_FLTP),
.caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
};
+
+const FFCodec ff_xmaframes_decoder = {
+ .p.name = "xmaframes",
+ CODEC_LONG_NAME("Xbox Media Audio raw frames"),
+ .p.type = AVMEDIA_TYPE_AUDIO,
+ .p.id = AV_CODEC_ID_XMAFRAMES,
+ .priv_data_size = sizeof(WMAProDecodeCtx),
+ .init = xmaframes_decode_init,
+ .close = xmaframes_decode_end,
+ FF_CODEC_DECODE_CB(xmaframes_decode_packet),
+ .flush = wmapro_flush,
+ .p.capabilities = AV_CODEC_CAP_DR1,
+ CODEC_SAMPLEFMTS(AV_SAMPLE_FMT_FLTP),
+ .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
+};
--
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-17 8:49 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-08-17 8:49 [FFmpeg-devel] [PATCH] avcodec/wmaprodec: add xma raw frame decoder (PR #20266) Isaac Marovitz 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