Mercurial > libavcodec.hg
changeset 4800:d6b2ddac2c5e libavcodec
THP PCM decoder, used on the Nintendo GameCube.
patch by Marco Gerards, mgerards xs4all nl
author | diego |
---|---|
date | Sat, 07 Apr 2007 16:03:23 +0000 |
parents | 812f759a7c59 |
children | 66ef3690d108 |
files | Makefile adpcm.c allcodecs.c avcodec.h |
diffstat | 4 files changed, 72 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/Makefile Sat Apr 07 15:15:45 2007 +0000 +++ b/Makefile Sat Apr 07 16:03:23 2007 +0000 @@ -250,6 +250,7 @@ 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
--- a/adpcm.c Sat Apr 07 15:15:45 2007 +0000 +++ b/adpcm.c Sat Apr 07 16:03:23 2007 +0000 @@ -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 @@ 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_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
--- a/allcodecs.c Sat Apr 07 15:15:45 2007 +0000 +++ b/allcodecs.c Sat Apr 07 16:03:23 2007 +0000 @@ -244,6 +244,7 @@ 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);
--- a/avcodec.h Sat Apr 07 15:15:45 2007 +0000 +++ b/avcodec.h Sat Apr 07 16:03:23 2007 +0000 @@ -200,6 +200,7 @@ 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_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);