From e7814ed839d16bf2fe1ce3d4954af89b0323c99d Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 3 May 2013 18:07:13 -0300 Subject: ADPCM DTK decoder Signed-off-by: James Almer --- Changelog | 1 + doc/general.texi | 1 + libavcodec/Makefile | 1 + libavcodec/adpcm.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++++ libavcodec/adpcm.h | 4 ++-- libavcodec/allcodecs.c | 1 + libavcodec/avcodec.h | 1 + libavcodec/codec_desc.c | 7 +++++++ libavcodec/utils.c | 2 ++ libavcodec/version.h | 2 +- 10 files changed, 71 insertions(+), 3 deletions(-) diff --git a/Changelog b/Changelog index c8d4b81d90..b7ade4f5aa 100644 --- a/Changelog +++ b/Changelog @@ -40,6 +40,7 @@ version : - Matroska muxer can now put the index at the beginning of the file. - extractplanes filter - avectorscope filter +- ADPCM DTK decoder version 1.2: diff --git a/doc/general.texi b/doc/general.texi index b6e731a437..215abe6198 100644 --- a/doc/general.texi +++ b/doc/general.texi @@ -771,6 +771,7 @@ following image formats are supported: @item ADPCM Microsoft @tab X @tab X @item ADPCM MS IMA @tab X @tab X @item ADPCM Nintendo Gamecube AFC @tab @tab X +@item ADPCM Nintendo Gamecube DTK @tab @tab X @item ADPCM Nintendo Gamecube THP @tab @tab X @item ADPCM QT IMA @tab X @tab X @item ADPCM SEGA CRI ADX @tab X @tab X diff --git a/libavcodec/Makefile b/libavcodec/Makefile index ba53df80a5..34fb5c5601 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -569,6 +569,7 @@ OBJS-$(CONFIG_ADPCM_ADX_DECODER) += adxdec.o adx.o OBJS-$(CONFIG_ADPCM_ADX_ENCODER) += adxenc.o adx.o OBJS-$(CONFIG_ADPCM_AFC_DECODER) += adpcm.o adpcm_data.o OBJS-$(CONFIG_ADPCM_CT_DECODER) += adpcm.o adpcm_data.o +OBJS-$(CONFIG_ADPCM_DTK_DECODER) += adpcm.o adpcm_data.o OBJS-$(CONFIG_ADPCM_EA_DECODER) += adpcm.o adpcm_data.o OBJS-$(CONFIG_ADPCM_EA_MAXIS_XA_DECODER) += adpcm.o adpcm_data.o OBJS-$(CONFIG_ADPCM_EA_R1_DECODER) += adpcm.o adpcm_data.o diff --git a/libavcodec/adpcm.c b/libavcodec/adpcm.c index d1c2aa7bdf..4edc46f222 100644 --- a/libavcodec/adpcm.c +++ b/libavcodec/adpcm.c @@ -95,6 +95,7 @@ static av_cold int adpcm_decode_init(AVCodecContext * avctx) unsigned int max_channels = 2; switch(avctx->codec->id) { + case AV_CODEC_ID_ADPCM_DTK: case AV_CODEC_ID_ADPCM_EA: min_channels = 2; break; @@ -147,6 +148,7 @@ static av_cold int adpcm_decode_init(AVCodecContext * avctx) case AV_CODEC_ID_ADPCM_EA_XAS: case AV_CODEC_ID_ADPCM_THP: case AV_CODEC_ID_ADPCM_AFC: + case AV_CODEC_ID_ADPCM_DTK: avctx->sample_fmt = AV_SAMPLE_FMT_S16P; break; case AV_CODEC_ID_ADPCM_IMA_WS: @@ -602,6 +604,9 @@ static int get_nb_samples(AVCodecContext *avctx, GetByteContext *gb, case AV_CODEC_ID_ADPCM_XA: nb_samples = (buf_size / 128) * 224 / ch; break; + case AV_CODEC_ID_ADPCM_DTK: + nb_samples = buf_size / (16 * ch) * 28; + break; } /* validate coded sample count */ @@ -1362,6 +1367,54 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data, } break; } + case AV_CODEC_ID_ADPCM_DTK: + for (channel = 0; channel < avctx->channels; channel++) { + samples = samples_p[channel]; + + /* Read in every sample for this channel. */ + for (i = 0; i < nb_samples / 28; i++) { + int byte, header; + if (channel) + bytestream2_skipu(&gb, 1); + header = bytestream2_get_byteu(&gb); + bytestream2_skipu(&gb, 3 - channel); + + /* Decode 28 samples. */ + for (n = 0; n < 28; n++) { + int32_t sampledat, prev; + + switch (header >> 4) { + case 1: + prev = (c->status[channel].sample1 * 0x3c); + break; + case 2: + prev = (c->status[channel].sample1 * 0x73) - (c->status[channel].sample2 * 0x34); + break; + case 3: + prev = (c->status[channel].sample1 * 0x62) - (c->status[channel].sample2 * 0x37); + break; + default: + prev = 0; + } + + prev = av_clip((prev + 0x20) >> 6, -0x200000, 0x1fffff); + + byte = bytestream2_get_byteu(&gb); + if (!channel) + sampledat = sign_extend(byte, 4); + else + sampledat = sign_extend(byte >> 4, 4); + + sampledat = (((sampledat << 12) >> (header & 0xf)) << 6) + prev; + *samples++ = av_clip_int16(sampledat >> 6); + c->status[channel].sample2 = c->status[channel].sample1; + c->status[channel].sample1 = sampledat; + } + } + if (!channel) + bytestream2_seek(&gb, 0, SEEK_SET); + } + break; default: return -1; @@ -1403,6 +1456,7 @@ AVCodec ff_ ## name_ ## _decoder = { \ ADPCM_DECODER(AV_CODEC_ID_ADPCM_4XM, sample_fmts_s16p, adpcm_4xm, "ADPCM 4X Movie"); ADPCM_DECODER(AV_CODEC_ID_ADPCM_AFC, sample_fmts_s16p, adpcm_afc, "ADPCM Nintendo Gamecube AFC"); ADPCM_DECODER(AV_CODEC_ID_ADPCM_CT, sample_fmts_s16, adpcm_ct, "ADPCM Creative Technology"); +ADPCM_DECODER(AV_CODEC_ID_ADPCM_DTK, sample_fmts_s16p, adpcm_dtk, "ADPCM Nintendo Gamecube DTK"); ADPCM_DECODER(AV_CODEC_ID_ADPCM_EA, sample_fmts_s16, adpcm_ea, "ADPCM Electronic Arts"); ADPCM_DECODER(AV_CODEC_ID_ADPCM_EA_MAXIS_XA, sample_fmts_s16, adpcm_ea_maxis_xa, "ADPCM Electronic Arts Maxis CDROM XA"); ADPCM_DECODER(AV_CODEC_ID_ADPCM_EA_R1, sample_fmts_s16p, adpcm_ea_r1, "ADPCM Electronic Arts R1"); diff --git a/libavcodec/adpcm.h b/libavcodec/adpcm.h index 08fd23f87b..f43a28cafe 100644 --- a/libavcodec/adpcm.h +++ b/libavcodec/adpcm.h @@ -38,8 +38,8 @@ typedef struct ADPCMChannelStatus { int prev_sample; /* MS version */ - int16_t sample1; - int16_t sample2; + int sample1; + int sample2; int coeff1; int coeff2; int idelta; diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index d5b69164e6..145f7e437f 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -419,6 +419,7 @@ void avcodec_register_all(void) REGISTER_ENCDEC (ADPCM_ADX, adpcm_adx); REGISTER_DECODER(ADPCM_AFC, adpcm_afc); REGISTER_DECODER(ADPCM_CT, adpcm_ct); + REGISTER_DECODER(ADPCM_DTK, adpcm_dtk); REGISTER_DECODER(ADPCM_EA, adpcm_ea); REGISTER_DECODER(ADPCM_EA_MAXIS_XA, adpcm_ea_maxis_xa); REGISTER_DECODER(ADPCM_EA_R1, adpcm_ea_r1); diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 1978054230..8db0af4849 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -362,6 +362,7 @@ enum AVCodecID { AV_CODEC_ID_VIMA = MKBETAG('V','I','M','A'), AV_CODEC_ID_ADPCM_AFC = MKBETAG('A','F','C',' '), AV_CODEC_ID_ADPCM_IMA_OKI = MKBETAG('O','K','I',' '), + AV_CODEC_ID_ADPCM_DTK = MKBETAG('D','T','K',' '), /* AMR */ AV_CODEC_ID_AMR_NB = 0x12000, diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c index c973025daa..a36aaad71f 100644 --- a/libavcodec/codec_desc.c +++ b/libavcodec/codec_desc.c @@ -1816,6 +1816,13 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("ADPCM IMA Dialogic OKI"), .props = AV_CODEC_PROP_LOSSY, }, + { + .id = AV_CODEC_ID_ADPCM_DTK, + .type = AVMEDIA_TYPE_AUDIO, + .name = "adpcm_dtk", + .long_name = NULL_IF_CONFIG_SMALL("ADPCM Nintendo Gamecube DTK"), + .props = AV_CODEC_PROP_LOSSY, + }, /* AMR */ { diff --git a/libavcodec/utils.c b/libavcodec/utils.c index 0d8306b54c..2040e6fc0d 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -2835,6 +2835,8 @@ int av_get_audio_frame_duration(AVCodecContext *avctx, int frame_bytes) switch (id) { case AV_CODEC_ID_ADPCM_AFC: return frame_bytes / (9 * ch) * 16; + case AV_CODEC_ID_ADPCM_DTK: + return frame_bytes / (16 * ch) * 28; case AV_CODEC_ID_ADPCM_4XM: case AV_CODEC_ID_ADPCM_IMA_ISS: return (frame_bytes - 4 * ch) * 2 / ch; diff --git a/libavcodec/version.h b/libavcodec/version.h index 859ed97abd..e34e506513 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -29,7 +29,7 @@ #include "libavutil/avutil.h" #define LIBAVCODEC_VERSION_MAJOR 55 -#define LIBAVCODEC_VERSION_MINOR 7 +#define LIBAVCODEC_VERSION_MINOR 8 #define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ -- cgit v1.2.3