diff options
author | Marco Gerards <mgerards@xs4all.nl> | 2007-04-07 16:03:23 +0000 |
---|---|---|
committer | Diego Biurrun <diego@biurrun.de> | 2007-04-07 16:03:23 +0000 |
commit | d1e0d21f9492215b324fe7872e050b2d48a55c1d (patch) | |
tree | 3e67a6ef88f4f739cdf795e07399202e72a9fd89 /libavcodec | |
parent | efd2afc2aef18e9c8d43a18dccc792d901528992 (diff) | |
download | ffmpeg-d1e0d21f9492215b324fe7872e050b2d48a55c1d.tar.gz |
THP PCM decoder, used on the Nintendo GameCube.
patch by Marco Gerards, mgerards xs4all nl
Originally committed as revision 8646 to svn://svn.ffmpeg.org/ffmpeg/trunk
Diffstat (limited to 'libavcodec')
-rw-r--r-- | libavcodec/Makefile | 1 | ||||
-rw-r--r-- | libavcodec/adpcm.c | 68 | ||||
-rw-r--r-- | libavcodec/allcodecs.c | 1 | ||||
-rw-r--r-- | libavcodec/avcodec.h | 2 |
4 files changed, 72 insertions, 0 deletions
diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 175755eb90..a07879e962 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -250,6 +250,7 @@ OBJS-$(CONFIG_ADPCM_SBPRO_4_DECODER) += adpcm.o OBJS-$(CONFIG_ADPCM_SBPRO_4_ENCODER) += adpcm.o OBJS-$(CONFIG_ADPCM_SWF_DECODER) += adpcm.o OBJS-$(CONFIG_ADPCM_SWF_ENCODER) += adpcm.o +OBJS-$(CONFIG_ADPCM_THP_DECODER) += adpcm.o OBJS-$(CONFIG_ADPCM_XA_DECODER) += adpcm.o OBJS-$(CONFIG_ADPCM_XA_ENCODER) += adpcm.o OBJS-$(CONFIG_ADPCM_YAMAHA_DECODER) += adpcm.o diff --git a/libavcodec/adpcm.c b/libavcodec/adpcm.c index 8800c3a20c..cf282f1071 100644 --- a/libavcodec/adpcm.c +++ b/libavcodec/adpcm.c @@ -29,6 +29,7 @@ * by Mike Melanson (melanson@pcisys.net) * CD-ROM XA ADPCM codec by BERO * EA ADPCM decoder by Robin Kay (komadori@myrealbox.com) + * THP ADPCM decoder by Marco Gerards (mgerards@xs4all.nl) * * Features and limitations: * @@ -1308,6 +1309,72 @@ static int adpcm_decode_frame(AVCodecContext *avctx, src++; } break; + case CODEC_ID_ADPCM_THP: + { + GetBitContext gb; + int table[16][2]; + unsigned int samplecnt; + int prev1[2], prev2[2]; + int ch; + + if (buf_size < 80) { + av_log(avctx, AV_LOG_ERROR, "frame too small\n"); + return -1; + } + + init_get_bits(&gb, src, buf_size * 8); + src += buf_size; + + get_bits_long(&gb, 32); /* Channel size */ + samplecnt = get_bits_long(&gb, 32); + + for (ch = 0; ch < 2; ch++) + for (i = 0; i < 16; i++) + table[i][ch] = get_sbits(&gb, 16); + + /* Initialize the previous sample. */ + for (ch = 0; ch < 2; ch++) { + prev1[ch] = get_sbits(&gb, 16); + prev2[ch] = get_sbits(&gb, 16); + } + + if (samplecnt >= (samples_end - samples) / (st + 1)) { + av_log(avctx, AV_LOG_ERROR, "allocated output buffer is too small\n"); + return -1; + } + + for (ch = 0; ch <= st; ch++) { + samples = (unsigned short *) data + ch; + + /* Read in every sample for this channel. */ + for (i = 0; i < samplecnt / 14; i++) { + uint8_t index = get_bits (&gb, 4) & 7; + unsigned int exp = get_bits (&gb, 4); + int factor1 = table[index * 2][ch]; + int factor2 = table[index * 2 + 1][ch]; + + /* Decode 14 samples. */ + for (n = 0; n < 14; n++) { + int sampledat = get_sbits (&gb, 4); + + *samples = ((prev1[ch]*factor1 + + prev2[ch]*factor2) >> 11) + (sampledat << exp); + prev2[ch] = prev1[ch]; + prev1[ch] = *samples++; + + /* In case of stereo, skip one sample, this sample + is for the other channel. */ + samples += st; + } + } + } + + /* In the previous loop, in case stereo is used, samples is + increased exactly one time too often. */ + samples -= st; + break; + } + default: return -1; } @@ -1368,5 +1435,6 @@ ADPCM_CODEC(CODEC_ID_ADPCM_YAMAHA, adpcm_yamaha); ADPCM_CODEC(CODEC_ID_ADPCM_SBPRO_4, adpcm_sbpro_4); ADPCM_CODEC(CODEC_ID_ADPCM_SBPRO_3, adpcm_sbpro_3); ADPCM_CODEC(CODEC_ID_ADPCM_SBPRO_2, adpcm_sbpro_2); +ADPCM_CODEC(CODEC_ID_ADPCM_THP, adpcm_thp); #undef ADPCM_CODEC diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 09612b40d2..be41c147f5 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -244,6 +244,7 @@ void avcodec_register_all(void) REGISTER_ENCDEC (ADPCM_SBPRO_3, adpcm_sbpro_3); REGISTER_ENCDEC (ADPCM_SBPRO_4, adpcm_sbpro_4); REGISTER_ENCDEC (ADPCM_SWF, adpcm_swf); + REGISTER_DECODER(ADPCM_THP, adpcm_thp); REGISTER_ENCDEC (ADPCM_XA, adpcm_xa); REGISTER_ENCDEC (ADPCM_YAMAHA, adpcm_yamaha); diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index b7ed16248d..421171a183 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -200,6 +200,7 @@ enum CodecID { CODEC_ID_ADPCM_SBPRO_4, CODEC_ID_ADPCM_SBPRO_3, CODEC_ID_ADPCM_SBPRO_2, + CODEC_ID_ADPCM_THP, /* AMR */ CODEC_ID_AMR_NB= 0x12000, @@ -2417,6 +2418,7 @@ PCM_CODEC(CODEC_ID_ADPCM_SBPRO_3, adpcm_sbpro_3); PCM_CODEC(CODEC_ID_ADPCM_SBPRO_4, adpcm_sbpro_4); PCM_CODEC(CODEC_ID_ADPCM_SMJPEG, adpcm_ima_smjpeg); PCM_CODEC(CODEC_ID_ADPCM_SWF, adpcm_swf); +PCM_CODEC(CODEC_ID_ADPCM_THP, adpcm_thp); PCM_CODEC(CODEC_ID_ADPCM_XA, adpcm_xa); PCM_CODEC(CODEC_ID_ADPCM_YAMAHA, adpcm_yamaha); |