[FFmpeg-cvslog] avcodec: add SDX2 DPCM decoder

Paul B Mahol git at videolan.org
Mon Oct 26 10:32:16 CET 2015


ffmpeg | branch: master | Paul B Mahol <onemda at gmail.com> | Sat Oct 24 20:41:32 2015 +0200| [035ae3c0096f6c0a3f199d331ed4094ff5beafd1] | committer: Paul B Mahol

avcodec: add SDX2 DPCM decoder

Signed-off-by: Paul B Mahol <onemda at gmail.com>

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=035ae3c0096f6c0a3f199d331ed4094ff5beafd1
---

 Changelog               |    1 +
 doc/general.texi        |    2 ++
 libavcodec/Makefile     |    1 +
 libavcodec/allcodecs.c  |    1 +
 libavcodec/avcodec.h    |    2 ++
 libavcodec/codec_desc.c |    7 +++++++
 libavcodec/dpcm.c       |   32 ++++++++++++++++++++++++++++----
 libavcodec/utils.c      |    1 +
 libavcodec/version.h    |    2 +-
 libavformat/aiff.h      |    1 +
 libavformat/aiffdec.c   |    1 +
 libavformat/genh.c      |    4 ++++
 12 files changed, 50 insertions(+), 5 deletions(-)

diff --git a/Changelog b/Changelog
index abaac19..6081bf6 100644
--- a/Changelog
+++ b/Changelog
@@ -25,6 +25,7 @@ version <next>:
 - 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 c558856..942ae63 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.
+ at 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 f85fc18..4afb473 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 7279620..52606a3 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 7d47698..490bcd2 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 2f5cefd..32f1f8a 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 c13945e..52a2c61 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 83a2078..f85cbad 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 ea0f0bd..ea9e89a 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 4470254..392f326 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 8d2701a..17c0011 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 6e4abae..97068b4 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);
     }



More information about the ffmpeg-cvslog mailing list