From 271b4095ad6f383d410a6eaed35daf5bcc5706a4 Mon Sep 17 00:00:00 2001 From: Aurelien Jacobs Date: Sat, 3 Nov 2007 22:37:18 +0000 Subject: [PATCH] add Electronic Arts XAS ADPCM decoder based on a patch from Peter Ross Originally committed as revision 10913 to svn://svn.ffmpeg.org/ffmpeg/trunk --- libavcodec/Makefile | 1 + libavcodec/adpcm.c | 33 +++++++++++++++++++++++++++++++++ libavcodec/allcodecs.c | 1 + libavcodec/avcodec.h | 1 + 4 files changed, 36 insertions(+) diff --git a/libavcodec/Makefile b/libavcodec/Makefile index ea98e31e37..0265506327 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -266,6 +266,7 @@ OBJS-$(CONFIG_ADPCM_EA_DECODER) += adpcm.o OBJS-$(CONFIG_ADPCM_EA_R1_DECODER) += adpcm.o OBJS-$(CONFIG_ADPCM_EA_R2_DECODER) += adpcm.o OBJS-$(CONFIG_ADPCM_EA_R3_DECODER) += adpcm.o +OBJS-$(CONFIG_ADPCM_EA_XAS_DECODER) += adpcm.o OBJS-$(CONFIG_ADPCM_G726_DECODER) += g726.o OBJS-$(CONFIG_ADPCM_G726_ENCODER) += g726.o OBJS-$(CONFIG_ADPCM_IMA_AMV_DECODER) += adpcm.o diff --git a/libavcodec/adpcm.c b/libavcodec/adpcm.c index 8275c5509f..8997780158 100644 --- a/libavcodec/adpcm.c +++ b/libavcodec/adpcm.c @@ -33,6 +33,7 @@ * EA ADPCM R1/R2/R3 decoder by Peter Ross (pross@xvid.org) * EA IMA EACS decoder by Peter Ross (pross@xvid.org) * EA IMA SEAD decoder by Peter Ross (pross@xvid.org) + * EA ADPCM XAS decoder by Peter Ross (pross@xvid.org) * THP ADPCM decoder by Marco Gerards (mgerards@xs4all.nl) * * Features and limitations: @@ -1284,6 +1285,37 @@ static int adpcm_decode_frame(AVCodecContext *avctx, samples += 28 * samples_in_chunk * avctx->channels; break; } + case CODEC_ID_ADPCM_EA_XAS: + if (samples_end-samples < 32*4*avctx->channels + || buf_size < (4+15)*4*avctx->channels) { + src += buf_size; + break; + } + for (channel=0; channelchannels; channel++) { + int coeff[2][4], shift[4]; + short *s2, *s = &samples[channel]; + for (n=0; n<4; n++, s+=32*avctx->channels) { + for (i=0; i<2; i++) + coeff[i][n] = ea_adpcm_table[(src[0]&0x0F)+4*i]; + shift[n] = (src[2]&0x0F) + 8; + for (s2=s, i=0; i<2; i++, src+=2, s2+=avctx->channels) + s2[0] = (src[0]&0xF0) + (src[1]<<8); + } + + for (m=2; m<32; m+=2) { + s = &samples[m*avctx->channels + channel]; + for (n=0; n<4; n++, src++, s+=32*avctx->channels) { + for (s2=s, i=0; i<8; i+=4, s2+=avctx->channels) { + int level = ((*src & (0xF0>>i)) << (24+i)) >> shift[n]; + int pred = s2[-1*avctx->channels] * coeff[0][n] + + s2[-2*avctx->channels] * coeff[1][n]; + s2[0] = av_clip_int16((level + pred + 0x80) >> 8); + } + } + } + } + samples += 32*4*avctx->channels; + break; case CODEC_ID_ADPCM_IMA_AMV: case CODEC_ID_ADPCM_IMA_SMJPEG: c->status[0].predictor = (int16_t)bytestream_get_le16(&src); @@ -1554,6 +1586,7 @@ ADPCM_DECODER(CODEC_ID_ADPCM_EA, adpcm_ea); ADPCM_DECODER(CODEC_ID_ADPCM_EA_R1, adpcm_ea_r1); ADPCM_DECODER(CODEC_ID_ADPCM_EA_R2, adpcm_ea_r2); ADPCM_DECODER(CODEC_ID_ADPCM_EA_R3, adpcm_ea_r3); +ADPCM_DECODER(CODEC_ID_ADPCM_EA_XAS, adpcm_ea_xas); ADPCM_DECODER(CODEC_ID_ADPCM_IMA_AMV, adpcm_ima_amv); ADPCM_DECODER(CODEC_ID_ADPCM_IMA_DK3, adpcm_ima_dk3); ADPCM_DECODER(CODEC_ID_ADPCM_IMA_DK4, adpcm_ima_dk4); diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index f929c58f13..87dd09f8a5 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -250,6 +250,7 @@ void avcodec_register_all(void) REGISTER_DECODER (ADPCM_EA_R1, adpcm_ea_r1); REGISTER_DECODER (ADPCM_EA_R2, adpcm_ea_r2); REGISTER_DECODER (ADPCM_EA_R3, adpcm_ea_r3); + REGISTER_DECODER (ADPCM_EA_XAS, adpcm_ea_xas); REGISTER_ENCDEC (ADPCM_G726, adpcm_g726); REGISTER_DECODER (ADPCM_IMA_AMV, adpcm_ima_amv); REGISTER_DECODER (ADPCM_IMA_DK3, adpcm_ima_dk3); diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 775f76bbce..202f9e8aa1 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -216,6 +216,7 @@ enum CodecID { CODEC_ID_ADPCM_EA_R2, CODEC_ID_ADPCM_IMA_EA_SEAD, CODEC_ID_ADPCM_IMA_EA_EACS, + CODEC_ID_ADPCM_EA_XAS, /* AMR */ CODEC_ID_AMR_NB= 0x12000,