Skip to content

Commit

Permalink
avcodec: add ADPCM IMA MTF decoder
Browse files Browse the repository at this point in the history
  • Loading branch information
richardpl committed Mar 17, 2020
1 parent c149f16 commit 230703a
Show file tree
Hide file tree
Showing 6 changed files with 44 additions and 0 deletions.
1 change: 1 addition & 0 deletions Changelog
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ version <next>:
- AMQP 0-9-1 protocol (RabbitMQ)
- Vulkan support
- avgblur_vulkan, overlay_vulkan, scale_vulkan and chromaber_vulkan filters
- ADPCM IMA MTF decoder


version 4.2:
Expand Down
1 change: 1 addition & 0 deletions libavcodec/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -843,6 +843,7 @@ OBJS-$(CONFIG_ADPCM_IMA_DK4_DECODER) += adpcm.o adpcm_data.o
OBJS-$(CONFIG_ADPCM_IMA_EA_EACS_DECODER) += adpcm.o adpcm_data.o
OBJS-$(CONFIG_ADPCM_IMA_EA_SEAD_DECODER) += adpcm.o adpcm_data.o
OBJS-$(CONFIG_ADPCM_IMA_ISS_DECODER) += adpcm.o adpcm_data.o
OBJS-$(CONFIG_ADPCM_IMA_MTF_DECODER) += adpcm.o adpcm_data.o
OBJS-$(CONFIG_ADPCM_IMA_OKI_DECODER) += adpcm.o adpcm_data.o
OBJS-$(CONFIG_ADPCM_IMA_QT_DECODER) += adpcm.o adpcm_data.o
OBJS-$(CONFIG_ADPCM_IMA_QT_ENCODER) += adpcmenc.o adpcm_data.o
Expand Down
33 changes: 33 additions & 0 deletions libavcodec/adpcm.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,11 @@ static const int8_t zork_index_table[8] = {
-1, -1, -1, 1, 4, 7, 10, 12,
};

static const int8_t mtf_index_table[16] = {
8, 6, 4, 2, -1, -1, -1, -1,
-1, -1, -1, -1, 2, 4, 6, 8,
};

/* end of tables */

typedef struct ADPCMDecodeContext {
Expand Down Expand Up @@ -304,6 +309,22 @@ static inline int16_t adpcm_ima_alp_expand_nibble(ADPCMChannelStatus *c, int8_t
return (int16_t)c->predictor;
}

static inline int16_t adpcm_ima_mtf_expand_nibble(ADPCMChannelStatus *c, int nibble)
{
int step_index, step, delta, predictor;

step = ff_adpcm_step_table[c->step_index];

delta = step * (2 * nibble - 15);
predictor = c->predictor + delta;

step_index = c->step_index + mtf_index_table[(unsigned)nibble];
c->predictor = av_clip_int16(predictor >> 4);
c->step_index = av_clip(step_index, 0, 88);

return (int16_t)c->predictor;
}

static inline int16_t adpcm_ima_wav_expand_nibble(ADPCMChannelStatus *c, GetBitContext *gb, int bps)
{
int nibble, step_index, predictor, sign, delta, diff, step, shift;
Expand Down Expand Up @@ -700,6 +721,7 @@ static int get_nb_samples(AVCodecContext *avctx, GetByteContext *gb,
case AV_CODEC_ID_ADPCM_IMA_SSI:
case AV_CODEC_ID_ADPCM_IMA_APM:
case AV_CODEC_ID_ADPCM_IMA_ALP:
case AV_CODEC_ID_ADPCM_IMA_MTF:
nb_samples = buf_size * 2 / ch;
break;
}
Expand Down Expand Up @@ -1956,6 +1978,16 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data,
*samples++ = adpcm_zork_expand_nibble(&c->status[n % avctx->channels], v);
}
break;
case AV_CODEC_ID_ADPCM_IMA_MTF:
for (n = nb_samples / 2; n > 0; n--) {
for (channel = 0; channel < avctx->channels; channel++) {
int v = bytestream2_get_byteu(&gb);
*samples++ = adpcm_ima_mtf_expand_nibble(&c->status[channel], v >> 4);
samples[st] = adpcm_ima_mtf_expand_nibble(&c->status[channel], v & 0x0F);
}
samples += avctx->channels;
}
break;
default:
av_assert0(0); // unsupported codec_id should not happen
}
Expand Down Expand Up @@ -2027,6 +2059,7 @@ ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_DK4, sample_fmts_s16, adpcm_ima_dk4,
ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_EA_EACS, sample_fmts_s16, adpcm_ima_ea_eacs, "ADPCM IMA Electronic Arts EACS");
ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_EA_SEAD, sample_fmts_s16, adpcm_ima_ea_sead, "ADPCM IMA Electronic Arts SEAD");
ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_ISS, sample_fmts_s16, adpcm_ima_iss, "ADPCM IMA Funcom ISS");
ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_MTF, sample_fmts_s16, adpcm_ima_mtf, "ADPCM IMA Capcom's MT Framework");
ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_OKI, sample_fmts_s16, adpcm_ima_oki, "ADPCM IMA Dialogic OKI");
ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_QT, sample_fmts_s16p, adpcm_ima_qt, "ADPCM IMA QuickTime");
ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_RAD, sample_fmts_s16, adpcm_ima_rad, "ADPCM IMA Radical");
Expand Down
1 change: 1 addition & 0 deletions libavcodec/allcodecs.c
Original file line number Diff line number Diff line change
Expand Up @@ -608,6 +608,7 @@ extern AVCodec ff_adpcm_ima_dk4_decoder;
extern AVCodec ff_adpcm_ima_ea_eacs_decoder;
extern AVCodec ff_adpcm_ima_ea_sead_decoder;
extern AVCodec ff_adpcm_ima_iss_decoder;
extern AVCodec ff_adpcm_ima_mtf_decoder;
extern AVCodec ff_adpcm_ima_oki_decoder;
extern AVCodec ff_adpcm_ima_qt_encoder;
extern AVCodec ff_adpcm_ima_qt_decoder;
Expand Down
1 change: 1 addition & 0 deletions libavcodec/avcodec.h
Original file line number Diff line number Diff line change
Expand Up @@ -553,6 +553,7 @@ enum AVCodecID {
AV_CODEC_ID_ADPCM_ZORK,
AV_CODEC_ID_ADPCM_IMA_APM,
AV_CODEC_ID_ADPCM_IMA_ALP,
AV_CODEC_ID_ADPCM_IMA_MTF,

/* AMR */
AV_CODEC_ID_AMR_NB = 0x12000,
Expand Down
7 changes: 7 additions & 0 deletions libavcodec/codec_desc.c
Original file line number Diff line number Diff line change
Expand Up @@ -2332,6 +2332,13 @@ static const AVCodecDescriptor codec_descriptors[] = {
.long_name = NULL_IF_CONFIG_SMALL("ADPCM IMA High Voltage Software ALP"),
.props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY,
},
{
.id = AV_CODEC_ID_ADPCM_IMA_MTF,
.type = AVMEDIA_TYPE_AUDIO,
.name = "adpcm_ima_mtf",
.long_name = NULL_IF_CONFIG_SMALL("ADPCM IMA Capcom's MT Framework"),
.props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY,
},

/* AMR */
{
Expand Down

0 comments on commit 230703a

Please sign in to comment.