From: Paul B Mahol <[email protected]>
Signed-off-by: Paul B Mahol <[email protected]>
---
Changelog | 1 +
doc/general.texi | 2 ++
libavcodec/Makefile | 1 +
libavcodec/allcodecs.c | 1 +
libavcodec/avcodec.h | 1 +
libavcodec/codec_desc.c | 7 +++++++
libavcodec/dpcm.c | 32 ++++++++++++++++++++++++++++----
libavcodec/utils.c | 1 +
libavformat/aiff.h | 1 +
libavformat/aiffdec.c | 1 +
libavformat/genh.c | 7 +++++++
11 files changed, 51 insertions(+), 4 deletions(-)
diff --git a/Changelog b/Changelog
index aac87a3..caaff57 100644
--- a/Changelog
+++ b/Changelog
@@ -53,6 +53,7 @@ version <next>:
- GIF demuxer
- GENH demuxer
- ACT demuxer
+- SDX2 DPCM decoder
version 11:
diff --git a/doc/general.texi b/doc/general.texi
index 6572877..991d4d5 100644
--- a/doc/general.texi
+++ b/doc/general.texi
@@ -865,6 +865,8 @@ following image formats are supported:
@tab Used in Quake III, Jedi Knight 2, other computer games.
@item DPCM Interplay @tab @tab X
@tab Used in various Interplay computer games.
+@item DPCM Squareroot-Delta-Exact @tab @tab X
+ @tab Used in various games.
@item DPCM Sierra Online @tab @tab X
@tab Used in Sierra Online game audio files.
@item DPCM Sol @tab @tab X
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 0cca9ce..071a0f2 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -388,6 +388,7 @@ OBJS-$(CONFIG_RV40_DECODER) += rv40.o rv34.o
rv40dsp.o
OBJS-$(CONFIG_S302M_DECODER) += s302m.o
OBJS-$(CONFIG_SANM_DECODER) += sanm.o
OBJS-$(CONFIG_SCREENPRESSO_DECODER) += screenpresso.o
+OBJS-$(CONFIG_SDX2_DPCM_DECODER) += dpcm.o
OBJS-$(CONFIG_SGI_DECODER) += sgidec.o
OBJS-$(CONFIG_SGI_ENCODER) += sgienc.o rle.o
OBJS-$(CONFIG_SGIRLE_DECODER) += sgirledec.o
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index 0ad102c..1944b58 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -250,6 +250,7 @@ void avcodec_register_all(void)
REGISTER_DECODER(S302M, s302m);
REGISTER_DECODER(SANM, sanm);
REGISTER_DECODER(SCREENPRESSO, screenpresso);
+ REGISTER_DECODER(SDX2_DPCM, sdx2_dpcm);
REGISTER_ENCDEC (SGI, sgi);
REGISTER_DECODER(SGIRLE, sgirle);
REGISTER_DECODER(SMACKER, smacker);
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index 57dce36..1e215ab 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -382,6 +382,7 @@ enum AVCodecID {
AV_CODEC_ID_INTERPLAY_DPCM,
AV_CODEC_ID_XAN_DPCM,
AV_CODEC_ID_SOL_DPCM,
+ AV_CODEC_ID_SDX2_DPCM,
/* audio codecs */
AV_CODEC_ID_MP2 = 0x15000,
diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c
index 0d3dac2..9581310 100644
--- a/libavcodec/codec_desc.c
+++ b/libavcodec/codec_desc.c
@@ -1890,6 +1890,13 @@ static const AVCodecDescriptor codec_descriptors[] = {
.long_name = NULL_IF_CONFIG_SMALL("DPCM Sol"),
.props = AV_CODEC_PROP_LOSSY,
},
+ {
+ .id = AV_CODEC_ID_SDX2_DPCM,
+ .type = AVMEDIA_TYPE_AUDIO,
+ .name = "sdx2_dpcm",
+ .long_name = NULL_IF_CONFIG_SMALL("DPCM Squareroot-Delta-Exact"),
+ .props = AV_CODEC_PROP_LOSSY,
+ },
/* audio codecs */
{
diff --git a/libavcodec/dpcm.c b/libavcodec/dpcm.c
index b9f5b93..e3a9972 100644
--- a/libavcodec/dpcm.c
+++ b/libavcodec/dpcm.c
@@ -44,7 +44,7 @@
#include "mathops.h"
typedef struct DPCMContext {
- int16_t roq_square_array[256];
+ int16_t square_array[256];
int sample[2]; ///< previous sample (for SOL_DPCM)
const int8_t *sol_table; ///< delta table for SOL_DPCM
} DPCMContext;
@@ -130,8 +130,8 @@ static av_cold int dpcm_decode_init(AVCodecContext *avctx)
/* initialize square table */
for (i = 0; i < 128; i++) {
int16_t square = i * i;
- s->roq_square_array[i ] = square;
- s->roq_square_array[i + 128] = -square;
+ s->square_array[i ] = square;
+ s->square_array[i + 128] = -square;
}
break;
@@ -153,6 +153,13 @@ static av_cold int dpcm_decode_init(AVCodecContext *avctx)
}
break;
+ case AV_CODEC_ID_SDX2_DPCM:
+ for (i = -128; i < 128; i++) {
+ int16_t square = i * i * 2;
+ s->square_array[i+128] = i < 0 ? -square: square;
+ }
+ break;
+
default:
break;
}
@@ -200,6 +207,9 @@ static int dpcm_decode_frame(AVCodecContext *avctx, void
*data,
else
out = buf_size;
break;
+ case AV_CODEC_ID_SDX2_DPCM:
+ out = buf_size;
+ break;
}
if (out <= 0) {
av_log(avctx, AV_LOG_ERROR, "packet is too small\n");
@@ -229,7 +239,7 @@ static int dpcm_decode_frame(AVCodecContext *avctx, void
*data,
/* decode the samples */
while (output_samples < samples_end) {
- predictor[ch] += s->roq_square_array[bytestream2_get_byteu(&gb)];
+ predictor[ch] += s->square_array[bytestream2_get_byteu(&gb)];
predictor[ch] = av_clip_int16(predictor[ch]);
*output_samples++ = predictor[ch];
@@ -317,6 +327,19 @@ static int dpcm_decode_frame(AVCodecContext *avctx, void
*data,
}
}
break;
+
+ case AV_CODEC_ID_SDX2_DPCM:
+ while (output_samples < samples_end) {
+ int8_t n = bytestream2_get_byteu(&gb);
+
+ if (!(n & 1))
+ s->sample[ch] = 0;
+ s->sample[ch] += s->square_array[n + 128];
+ s->sample[ch] = av_clip_int16(s->sample[ch]);
+ *output_samples++ = s->sample[ch];
+ ch ^= stereo;
+ }
+ break;
}
*got_frame_ptr = 1;
@@ -338,5 +361,6 @@ AVCodec ff_ ## name_ ## _decoder = {
\
DPCM_DECODER(AV_CODEC_ID_INTERPLAY_DPCM, interplay_dpcm, "DPCM Interplay");
DPCM_DECODER(AV_CODEC_ID_ROQ_DPCM, roq_dpcm, "DPCM id RoQ");
+DPCM_DECODER(AV_CODEC_ID_SDX2_DPCM, sdx2_dpcm, "DPCM
Squareroot-Delta-Exact");
DPCM_DECODER(AV_CODEC_ID_SOL_DPCM, sol_dpcm, "DPCM Sol");
DPCM_DECODER(AV_CODEC_ID_XAN_DPCM, xan_dpcm, "DPCM Xan");
diff --git a/libavcodec/utils.c b/libavcodec/utils.c
index f8c501d..47a0ff5 100644
--- a/libavcodec/utils.c
+++ b/libavcodec/utils.c
@@ -1956,6 +1956,7 @@ int av_get_exact_bits_per_sample(enum AVCodecID codec_id)
case AV_CODEC_ID_PCM_S8:
case AV_CODEC_ID_PCM_U8:
case AV_CODEC_ID_PCM_ZORK:
+ case AV_CODEC_ID_SDX2_DPCM:
return 8;
case AV_CODEC_ID_PCM_S16BE:
case AV_CODEC_ID_PCM_S16BE_PLANAR:
diff --git a/libavformat/aiff.h b/libavformat/aiff.h
index 4ed135b..5b7db26 100644
--- a/libavformat/aiff.h
+++ b/libavformat/aiff.h
@@ -49,6 +49,7 @@ static const AVCodecTag ff_codec_aiff_tags[] = {
{ AV_CODEC_ID_ADPCM_IMA_QT, MKTAG('i','m','a','4') },
{ AV_CODEC_ID_QDM2, MKTAG('Q','D','M','2') },
{ AV_CODEC_ID_QCELP, MKTAG('Q','c','l','p') },
+ { AV_CODEC_ID_SDX2_DPCM, MKTAG('S','D','X','2') },
{ AV_CODEC_ID_NONE, 0 },
};
diff --git a/libavformat/aiffdec.c b/libavformat/aiffdec.c
index fc0b7eb..f5d8f57 100644
--- a/libavformat/aiffdec.c
+++ b/libavformat/aiffdec.c
@@ -138,6 +138,7 @@ static unsigned int get_aiff_header(AVFormatContext *s, int
size,
break;
case AV_CODEC_ID_ADPCM_G722:
case AV_CODEC_ID_MACE6:
+ case AV_CODEC_ID_SDX2_DPCM:
codec->block_align = 1*codec->channels;
break;
case AV_CODEC_ID_GSM:
diff --git a/libavformat/genh.c b/libavformat/genh.c
index 64f4c32..f2c63d0 100644
--- a/libavformat/genh.c
+++ b/libavformat/genh.c
@@ -100,6 +100,9 @@ static int genh_read_header(AVFormatContext *s)
else
st->codec->codec_id = AV_CODEC_ID_PCM_S8;
break;
+ case 6:
+ st->codec->codec_id = AV_CODEC_ID_SDX2_DPCM;
+ break;
case 7:
st->codec->extradata_size = 2;
st->codec->extradata = av_malloc(2);
@@ -205,6 +208,10 @@ static int genh_read_packet(AVFormatContext *s, AVPacket
*pkt)
pkt->data[ch * 8 + i*c->interleave_size+1] = avio_r8(s->pb);
}
}
+ } else if (codec->codec_id == AV_CODEC_ID_SDX2_DPCM) {
+ ret = av_get_packet(s->pb, pkt, 1024 * codec->block_align);
+ if (ret < 0)
+ return ret;
} else {
int block_align = codec->block_align ? codec->block_align
: 1024 * codec->channels;
--
2.6.3
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel