diff --git a/Changelog b/Changelog index abaac19d22..6081bf6852 100644 --- a/Changelog +++ b/Changelog @@ -25,6 +25,7 @@ version : - wve demuxer - zero-copy Intel QSV transcoding in ffmpeg - shuffleframes filter +- SDX2 DPCM decoder version 2.8: diff --git a/doc/general.texi b/doc/general.texi index c55885631d..942ae63d5e 100644 --- a/doc/general.texi +++ b/doc/general.texi @@ -960,6 +960,8 @@ following image formats are supported: @tab Used in Quake III, Jedi Knight 2 and other computer games. @item DPCM Interplay @tab @tab X @tab Used in various Interplay computer games. +@item DPCM Squareroot-Delta-Exact + @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 f85fc18a8d..4afb473e0f 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -458,6 +458,7 @@ OBJS-$(CONFIG_S302M_DECODER) += s302m.o OBJS-$(CONFIG_S302M_ENCODER) += s302menc.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 7279620fb6..52606a323c 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -287,6 +287,7 @@ void avcodec_register_all(void) REGISTER_ENCDEC (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 7d47698531..490bcd24ed 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -410,6 +410,8 @@ enum AVCodecID { AV_CODEC_ID_XAN_DPCM, AV_CODEC_ID_SOL_DPCM, + AV_CODEC_ID_SDX2_DPCM = 0x14800, + /* audio codecs */ AV_CODEC_ID_MP2 = 0x15000, AV_CODEC_ID_MP3, ///< preferred ID for decoding MPEG audio layer 1, 2 or 3 diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c index 2f5cefd16c..32f1f8aa44 100644 --- a/libavcodec/codec_desc.c +++ b/libavcodec/codec_desc.c @@ -2054,6 +2054,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 c13945edb6..52a2c616db 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"); @@ -230,7 +240,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]; @@ -318,6 +328,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; @@ -339,5 +362,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 83a20781ec..f85cbad7c2 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -2906,6 +2906,7 @@ int av_get_exact_bits_per_sample(enum AVCodecID codec_id) case AV_CODEC_ID_PCM_S8_PLANAR: 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/libavcodec/version.h b/libavcodec/version.h index ea0f0bd4af..ea9e89a31c 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -29,7 +29,7 @@ #include "libavutil/version.h" #define LIBAVCODEC_VERSION_MAJOR 57 -#define LIBAVCODEC_VERSION_MINOR 9 +#define LIBAVCODEC_VERSION_MINOR 10 #define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ diff --git a/libavformat/aiff.h b/libavformat/aiff.h index 4470254022..392f326be9 100644 --- a/libavformat/aiff.h +++ b/libavformat/aiff.h @@ -52,6 +52,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 8d2701a184..17c0011f99 100644 --- a/libavformat/aiffdec.c +++ b/libavformat/aiffdec.c @@ -159,6 +159,7 @@ static int get_aiff_header(AVFormatContext *s, int size, codec->bits_per_coded_sample = 5; 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 6e4abae7cf..97068b4483 100644 --- a/libavformat/genh.c +++ b/libavformat/genh.c @@ -84,6 +84,7 @@ static int genh_read_header(AVFormatContext *s) case 5: st->codec->codec_id = st->codec->block_align > 0 ? AV_CODEC_ID_PCM_S8_PLANAR : AV_CODEC_ID_PCM_S8; break; + case 6: st->codec->codec_id = AV_CODEC_ID_SDX2_DPCM; break; case 7: ret = ff_alloc_extradata(st->codec, 2); if (ret < 0) return ret; @@ -168,6 +169,9 @@ static int genh_read_packet(AVFormatContext *s, AVPacket *pkt) } } ret = 0; + } else if (codec->codec_id == AV_CODEC_ID_SDX2_DPCM) { + ret = av_get_packet(s->pb, pkt, codec->block_align * 1024); + } else { ret = av_get_packet(s->pb, pkt, codec->block_align ? codec->block_align : 1024 * codec->channels); }