mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-12-23 12:43:46 +02:00
avcodec: add decoder for argonaut games' adpcm codec
Adds support for the ADPCM variant used by some Argonaut Games' games, such as 'Croc! Legend of the Gobbos', and 'Croc 2'. Signed-off-by: Zane van Iperen <zane@zanevaniperen.com>
This commit is contained in:
parent
15d160cc0b
commit
bf890ae0d7
@ -30,6 +30,7 @@ version <next>:
|
||||
- MPEG-H 3D Audio support in mp4
|
||||
- thistogram filter
|
||||
- freezeframes filter
|
||||
- Argonaut Games ADPCM decoder
|
||||
|
||||
|
||||
version 4.2:
|
||||
|
@ -1079,6 +1079,7 @@ following image formats are supported:
|
||||
@item ACELP.KELVIN @tab @tab X
|
||||
@item ADPCM 4X Movie @tab @tab X
|
||||
@item APDCM Yamaha AICA @tab @tab X
|
||||
@item ADPCM Argonaut Games @tab @tab X
|
||||
@item ADPCM CDROM XA @tab @tab X
|
||||
@item ADPCM Creative Technology @tab @tab X
|
||||
@tab 16 -> 4, 8 -> 4, 8 -> 3, 8 -> 2
|
||||
|
@ -817,6 +817,7 @@ OBJS-$(CONFIG_ADPCM_ADX_ENCODER) += adxenc.o adx.o
|
||||
OBJS-$(CONFIG_ADPCM_AFC_DECODER) += adpcm.o adpcm_data.o
|
||||
OBJS-$(CONFIG_ADPCM_AGM_DECODER) += adpcm.o adpcm_data.o
|
||||
OBJS-$(CONFIG_ADPCM_AICA_DECODER) += adpcm.o adpcm_data.o
|
||||
OBJS-$(CONFIG_ADPCM_ARGO_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
|
||||
|
@ -12,6 +12,7 @@
|
||||
* EA ADPCM XAS decoder by Peter Ross (pross@xvid.org)
|
||||
* MAXIS EA ADPCM decoder by Robert Marston (rmarston@gmail.com)
|
||||
* THP ADPCM decoder by Marco Gerards (mgerards@xs4all.nl)
|
||||
* Argonaut Games ADPCM decoder by Zane van Iperen (zane@zanevaniperen.com)
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
@ -148,6 +149,10 @@ static av_cold int adpcm_decode_init(AVCodecContext * avctx)
|
||||
if (avctx->extradata && avctx->extradata_size >= 2)
|
||||
c->vqa_version = AV_RL16(avctx->extradata);
|
||||
break;
|
||||
case AV_CODEC_ID_ADPCM_ARGO:
|
||||
if (avctx->bits_per_coded_sample != 4)
|
||||
return AVERROR_INVALIDDATA;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -169,6 +174,7 @@ static av_cold int adpcm_decode_init(AVCodecContext * avctx)
|
||||
case AV_CODEC_ID_ADPCM_DTK:
|
||||
case AV_CODEC_ID_ADPCM_PSX:
|
||||
case AV_CODEC_ID_ADPCM_MTAF:
|
||||
case AV_CODEC_ID_ADPCM_ARGO:
|
||||
avctx->sample_fmt = AV_SAMPLE_FMT_S16P;
|
||||
break;
|
||||
case AV_CODEC_ID_ADPCM_IMA_WS:
|
||||
@ -546,6 +552,11 @@ static void adpcm_swf_decode(AVCodecContext *avctx, const uint8_t *buf, int buf_
|
||||
}
|
||||
}
|
||||
|
||||
static inline int16_t adpcm_argo_expand_nibble(int nibble, int shift, int16_t prev0, int16_t prev1)
|
||||
{
|
||||
return ((8 * prev0) - (4 * prev1) + (nibble * (1 << shift))) >> 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of samples that will be decoded from the packet.
|
||||
* In one case, this is actually the maximum number of samples possible to
|
||||
@ -584,6 +595,11 @@ static int get_nb_samples(AVCodecContext *avctx, GetByteContext *gb,
|
||||
return 0;
|
||||
nb_samples = 64;
|
||||
break;
|
||||
case AV_CODEC_ID_ADPCM_ARGO:
|
||||
if (buf_size < 17 * ch)
|
||||
return 0;
|
||||
nb_samples = 32;
|
||||
break;
|
||||
/* simple 4-bit adpcm */
|
||||
case AV_CODEC_ID_ADPCM_CT:
|
||||
case AV_CODEC_ID_ADPCM_IMA_APC:
|
||||
@ -1770,7 +1786,57 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data,
|
||||
}
|
||||
}
|
||||
break;
|
||||
case AV_CODEC_ID_ADPCM_ARGO:
|
||||
/*
|
||||
* The format of each block:
|
||||
* uint8_t left_control;
|
||||
* uint4_t left_samples[nb_samples];
|
||||
* ---- and if stereo ----
|
||||
* uint8_t right_control;
|
||||
* uint4_t right_samples[nb_samples];
|
||||
*
|
||||
* Format of the control byte:
|
||||
* MSB [SSSSDRRR] LSB
|
||||
* S = (Shift Amount - 2)
|
||||
* D = Decoder flag.
|
||||
* R = Reserved
|
||||
*
|
||||
* Each block relies on the previous two samples of each channel.
|
||||
* They should be 0 initially.
|
||||
*/
|
||||
for (channel = 0; channel < avctx->channels; channel++) {
|
||||
int control, shift, sample, nibble;
|
||||
|
||||
samples = samples_p[channel];
|
||||
cs = c->status + channel;
|
||||
|
||||
/* Get the control byte and decode the samples, 2 at a time. */
|
||||
control = bytestream2_get_byteu(&gb);
|
||||
shift = (control >> 4) + 2;
|
||||
|
||||
for (n = 0; n < nb_samples / 2; n++) {
|
||||
sample = bytestream2_get_byteu(&gb);
|
||||
|
||||
nibble = sign_extend(sample >> 4, 4);
|
||||
if (control & 0x04)
|
||||
*samples = adpcm_argo_expand_nibble(nibble, shift, cs->sample1, cs->sample2);
|
||||
else
|
||||
*samples = adpcm_argo_expand_nibble(nibble, shift, cs->sample1, cs->sample1);
|
||||
|
||||
cs->sample2 = cs->sample1;
|
||||
cs->sample1 = *samples++;
|
||||
|
||||
nibble = sign_extend(sample >> 0, 4);
|
||||
if (control & 0x04)
|
||||
*samples = adpcm_argo_expand_nibble(nibble, shift, cs->sample1, cs->sample2);
|
||||
else
|
||||
*samples = adpcm_argo_expand_nibble(nibble, shift, cs->sample1, cs->sample1);
|
||||
|
||||
cs->sample2 = cs->sample1;
|
||||
cs->sample1 = *samples++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
av_assert0(0); // unsupported codec_id should not happen
|
||||
}
|
||||
@ -1824,6 +1890,7 @@ ADPCM_DECODER(AV_CODEC_ID_ADPCM_4XM, sample_fmts_s16p, adpcm_4xm,
|
||||
ADPCM_DECODER(AV_CODEC_ID_ADPCM_AFC, sample_fmts_s16p, adpcm_afc, "ADPCM Nintendo Gamecube AFC");
|
||||
ADPCM_DECODER(AV_CODEC_ID_ADPCM_AGM, sample_fmts_s16, adpcm_agm, "ADPCM AmuseGraphics Movie");
|
||||
ADPCM_DECODER(AV_CODEC_ID_ADPCM_AICA, sample_fmts_s16p, adpcm_aica, "ADPCM Yamaha AICA");
|
||||
ADPCM_DECODER(AV_CODEC_ID_ADPCM_ARGO, sample_fmts_s16p, adpcm_argo, "ADPCM Argonaut Games");
|
||||
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");
|
||||
|
@ -582,6 +582,7 @@ extern AVCodec ff_adpcm_adx_decoder;
|
||||
extern AVCodec ff_adpcm_afc_decoder;
|
||||
extern AVCodec ff_adpcm_agm_decoder;
|
||||
extern AVCodec ff_adpcm_aica_decoder;
|
||||
extern AVCodec ff_adpcm_argo_decoder;
|
||||
extern AVCodec ff_adpcm_ct_decoder;
|
||||
extern AVCodec ff_adpcm_dtk_decoder;
|
||||
extern AVCodec ff_adpcm_ea_decoder;
|
||||
|
@ -545,6 +545,7 @@ enum AVCodecID {
|
||||
AV_CODEC_ID_ADPCM_IMA_DAT4,
|
||||
AV_CODEC_ID_ADPCM_MTAF,
|
||||
AV_CODEC_ID_ADPCM_AGM,
|
||||
AV_CODEC_ID_ADPCM_ARGO,
|
||||
|
||||
/* AMR */
|
||||
AV_CODEC_ID_AMR_NB = 0x12000,
|
||||
|
@ -2297,6 +2297,13 @@ static const AVCodecDescriptor codec_descriptors[] = {
|
||||
.long_name = NULL_IF_CONFIG_SMALL("ADPCM AmuseGraphics Movie AGM"),
|
||||
.props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY,
|
||||
},
|
||||
{
|
||||
.id = AV_CODEC_ID_ADPCM_ARGO,
|
||||
.type = AVMEDIA_TYPE_AUDIO,
|
||||
.name = "adpcm_argo",
|
||||
.long_name = NULL_IF_CONFIG_SMALL("ADPCM Argonaut Games"),
|
||||
.props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY,
|
||||
},
|
||||
|
||||
/* AMR */
|
||||
{
|
||||
|
@ -28,8 +28,8 @@
|
||||
#include "libavutil/version.h"
|
||||
|
||||
#define LIBAVCODEC_VERSION_MAJOR 58
|
||||
#define LIBAVCODEC_VERSION_MINOR 66
|
||||
#define LIBAVCODEC_VERSION_MICRO 101
|
||||
#define LIBAVCODEC_VERSION_MINOR 67
|
||||
#define LIBAVCODEC_VERSION_MICRO 100
|
||||
|
||||
#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
|
||||
LIBAVCODEC_VERSION_MINOR, \
|
||||
|
Loading…
Reference in New Issue
Block a user