diff options
author | Manuel Lauss <manuel.lauss@gmail.com> | 2025-08-16 10:44:06 +0200 |
---|---|---|
committer | Manuel Lauss <manuel.lauss@gmail.com> | 2025-08-20 11:20:14 +0200 |
commit | 9141fe9653dc078d81bff8308ffdd2aaaf35495c (patch) | |
tree | eacbddbc5db560b50bb1e37879b041df4c988000 | |
parent | 1e95f1b269e25dd8907ac65f2963de54d2b73142 (diff) | |
download | ffmpeg-9141fe9653dc078d81bff8308ffdd2aaaf35495c.tar.gz |
avcodec/vima: IMA4 subtag support
Support decoding of the IMA4 ADPCM QT scheme used in some LucasArts
SANM files.
Signed-off-by: Manuel Lauss <manuel.lauss@gmail.com>
-rw-r--r-- | libavcodec/vima.c | 15 |
1 files changed, 15 insertions, 0 deletions
diff --git a/libavcodec/vima.c b/libavcodec/vima.c index 56cc1b7a85..0423fff091 100644 --- a/libavcodec/vima.c +++ b/libavcodec/vima.c @@ -28,6 +28,7 @@ #include "libavutil/channel_layout.h" #include "libavutil/thread.h" +#include "adpcm.h" #include "adpcm_data.h" #include "avcodec.h" #include "codec_internal.h" @@ -159,6 +160,19 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *frame, if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) return ret; + if (show_bits_long(&gb, 32) == MKBETAG('I','M','A','4')) { + int16_t *dest = (int16_t *)frame->data[0]; + ADPCMChannelStatus cs; + + skip_bits_long(&gb, 32); /* skip the 'IMA4' tag */ + cs.predictor = (int16_t)get_xbits_le(&gb, 16); + cs.step_index = av_clip(get_bits(&gb, 8), 0, 88); + for (int i = 0; i < samples; i++) { + ff_adpcm_ima_qt_expand_nibble(&cs, get_bits(&gb, 4)); + for (int j = 0; j < channels; j++) + *dest++ = cs.predictor; + } + } else { for (chan = 0; chan < channels; chan++) { uint16_t *dest = (uint16_t *)frame->data[0] + chan; int step_index = channel_hint[chan]; @@ -200,6 +214,7 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *frame, step_index += step_index_tables[lookup_size - 2][lookup]; } + } } *got_frame_ptr = 1; |