From 047ba1051d5e03b2a54d2aad514dd4501750bc71 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tomas=20H=C3=A4rdin?= <git@haerdin.se>
Date: Tue, 26 Dec 2023 14:32:20 +0100
Subject: [PATCH 5/6] Add ADPCM IMA CRYO APC encoder
No trellis quantization yet
---
Changelog | 1 +
doc/general_contents.texi | 2 +-
libavcodec/adpcmenc.c | 33 +++++++++++++++++++++++++++++++++
libavcodec/allcodecs.c | 1 +
libavcodec/version.h | 2 +-
tests/fate/acodec.mak | 2 ++
tests/ref/acodec/adpcm-ima_apc | 4 ++++
7 files changed, 43 insertions(+), 2 deletions(-)
create mode 100644 tests/ref/acodec/adpcm-ima_apc
@@ -4,6 +4,7 @@ releases are sorted from youngest to oldest.
version <next>:
- LEAD MCMP decoder
- CRYO APC muxer
+- ADPCM IMA APC encoder
version 6.1:
- libaribcaption decoder
@@ -1169,7 +1169,7 @@ following image formats are supported:
@item ADPCM IMA Acorn Replay @tab @tab X
@item ADPCM IMA AMV @tab X @tab X
@tab Used in AMV files
-@item ADPCM IMA APC @tab @tab X
+@item ADPCM IMA APC @tab X @tab X
@tab Codec used in games by Cryo Interactive
@item ADPCM IMA Cunning Developments @tab @tab X
@item ADPCM IMA Electronic Arts EACS @tab @tab X
@@ -74,6 +74,7 @@ typedef struct ADPCMEncodeContext {
TrellisNode *node_buf;
TrellisNode **nodep_buf;
uint8_t *trellis_hash;
+ int extradata_updated;
} ADPCMEncodeContext;
#define FREEZE_INTERVAL 128
@@ -157,6 +158,15 @@ static av_cold int adpcm_encode_init(AVCodecContext *avctx)
bytestream_put_le16(&extradata, ff_adpcm_AdaptCoeff2[i] * 4);
}
) /* End of CASE */
+ CASE(ADPCM_IMA_APC,
+ if (avctx->trellis) {
+ av_log(avctx, AV_LOG_ERROR, "trellis encoding not implemented for CRYO APC\n");
+ return AVERROR_PATCHWELCOME;
+ }
+ //extradata will be output in adpcm_encode_frame()
+ avctx->frame_size = s->block_size * 2 / channels;
+ avctx->block_align = s->block_size;
+ ) /* End of CASE */
CASE(ADPCM_YAMAHA,
avctx->frame_size = s->block_size * 2 / channels;
avctx->block_align = s->block_size;
@@ -622,6 +632,28 @@ static int adpcm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
dst = avpkt->data;
switch(avctx->codec->id) {
+ CASE(ADPCM_IMA_APC,
+ //initialize predictors using initial samples
+ if (!c->extradata_updated) {
+ uint8_t *side_data = av_packet_new_side_data(
+ avpkt, AV_PKT_DATA_NEW_EXTRADATA, 8);
+
+ if (!side_data) {
+ return AVERROR(ENOMEM);
+ }
+
+ for (int ch = 0; ch < channels; ch++) {
+ c->status[ch].prev_sample = samples[ch];
+ bytestream_put_le32(&side_data, c->status[ch].prev_sample);
+ }
+ c->extradata_updated = 1;
+ }
+ for (int i = 0; i < frame->nb_samples*channels/2; i++) {
+ uint8_t l = adpcm_ima_compress_sample(&c->status[0], samples[2*i+0]);
+ uint8_t r = adpcm_ima_compress_sample(&c->status[st], samples[2*i+1]);
+ *dst++ = (l<<4) | r;
+ }
+ ) /* End of CASE */
CASE(ADPCM_IMA_WAV,
int blocks = (frame->nb_samples - 1) / 8;
@@ -1028,6 +1060,7 @@ ADPCM_ENCODER(ADPCM_IMA_QT, adpcm_ima_qt, sample_fmts_p, 0,
ADPCM_ENCODER(ADPCM_IMA_SSI, adpcm_ima_ssi, sample_fmts, AV_CODEC_CAP_SMALL_LAST_FRAME, "ADPCM IMA Simon & Schuster Interactive")
ADPCM_ENCODER(ADPCM_IMA_WAV, adpcm_ima_wav, sample_fmts_p, 0, "ADPCM IMA WAV")
ADPCM_ENCODER(ADPCM_IMA_WS, adpcm_ima_ws, sample_fmts, AV_CODEC_CAP_SMALL_LAST_FRAME, "ADPCM IMA Westwood")
+ADPCM_ENCODER(ADPCM_IMA_APC, adpcm_ima_apc, sample_fmts, 0, "ADPCM IMA CRYO APC")
ADPCM_ENCODER(ADPCM_MS, adpcm_ms, sample_fmts, 0, "ADPCM Microsoft")
ADPCM_ENCODER(ADPCM_SWF, adpcm_swf, sample_fmts, 0, "ADPCM Shockwave Flash")
ADPCM_ENCODER(ADPCM_YAMAHA, adpcm_yamaha, sample_fmts, 0, "ADPCM Yamaha")
@@ -668,6 +668,7 @@ extern const FFCodec ff_adpcm_ima_amv_encoder;
extern const FFCodec ff_adpcm_ima_alp_decoder;
extern const FFCodec ff_adpcm_ima_alp_encoder;
extern const FFCodec ff_adpcm_ima_apc_decoder;
+extern const FFCodec ff_adpcm_ima_apc_encoder;
extern const FFCodec ff_adpcm_ima_apm_decoder;
extern const FFCodec ff_adpcm_ima_apm_encoder;
extern const FFCodec ff_adpcm_ima_cunning_decoder;
@@ -29,7 +29,7 @@
#include "version_major.h"
-#define LIBAVCODEC_VERSION_MINOR 33
+#define LIBAVCODEC_VERSION_MINOR 34
#define LIBAVCODEC_VERSION_MICRO 100
#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
@@ -48,6 +48,7 @@ fate-acodec-pcm-f%be: FMT = au
FATE_ACODEC_ADPCM_RESAMPLE-$(call ENCDEC, ADPCM_ADX, ADX) += adx
FATE_ACODEC_ADPCM_RESAMPLE-$(call ENCDEC, ADPCM_ARGO, ARGO_ASF) += argo
+FATE_ACODEC_ADPCM-$(call ENCDEC, ADPCM_IMA_APC, APC) += ima_apc
FATE_ACODEC_ADPCM-$(call ENCDEC, ADPCM_IMA_APM, APM) += ima_apm
FATE_ACODEC_ADPCM-$(call ENCDEC, ADPCM_IMA_ALP, ALP) += ima_alp
FATE_ACODEC_ADPCM_RESAMPLE-$(call ENCDEC, ADPCM_IMA_QT, AIFF) += ima_qt
@@ -69,6 +70,7 @@ fate-acodec-adpcm-%: CODEC = adpcm_$(@:fate-acodec-adpcm-%=%)
fate-acodec-adpcm-adx: FMT = adx
fate-acodec-adpcm-argo: FMT = argo_asf
+fate-acodec-adpcm-ima_apc: FMT = apc
fate-acodec-adpcm-ima_apm: FMT = apm
fate-acodec-adpcm-ima_qt: FMT = aiff
fate-acodec-adpcm-ima_ssi: FMT = kvag
new file mode 100644
@@ -0,0 +1,4 @@
+45aca515c679bb0c315df766432d5630 *tests/data/fate/acodec-adpcm-ima_apc.apc
+265248 tests/data/fate/acodec-adpcm-ima_apc.apc
+03fc41cf61b7a160359147cd6363562a *tests/data/fate/acodec-adpcm-ima_apc.out.wav
+stddev: 904.04 PSNR: 37.21 MAXDIFF:34026 bytes: 1058400/ 1060864
--
2.39.2