[FFmpeg-devel,1/3] avcodec: add Gremlin DPCM decoder

Submitted by Paul B Mahol on June 2, 2017, 7:56 p.m.

Details

Message ID 20170602195619.4374-1-onemda@gmail.com
State New
Headers show

Commit Message

Paul B Mahol June 2, 2017, 7:56 p.m.
Signed-off-by: Paul B Mahol <onemda@gmail.com>
---
 libavcodec/Makefile     |  1 +
 libavcodec/allcodecs.c  |  1 +
 libavcodec/avcodec.h    |  1 +
 libavcodec/codec_desc.c |  7 +++++++
 libavcodec/dpcm.c       | 44 ++++++++++++++++++++++++++++++++++++++------
 5 files changed, 48 insertions(+), 6 deletions(-)

Patch hide | download patch | download mbox

diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 0818950..759cc0c 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -310,6 +310,7 @@  OBJS-$(CONFIG_G723_1_ENCODER)          += g723_1enc.o g723_1.o \
 OBJS-$(CONFIG_G729_DECODER)            += g729dec.o lsp.o celp_math.o celp_filters.o acelp_filters.o acelp_pitch_delay.o acelp_vectors.o g729postfilter.o
 OBJS-$(CONFIG_GIF_DECODER)             += gifdec.o lzw.o
 OBJS-$(CONFIG_GIF_ENCODER)             += gif.o lzwenc.o
+OBJS-$(CONFIG_GREMLIN_DPCM_DECODER)    += dpcm.o
 OBJS-$(CONFIG_GSM_DECODER)             += gsmdec.o gsmdec_data.o msgsmdec.o
 OBJS-$(CONFIG_GSM_MS_DECODER)          += gsmdec.o gsmdec_data.o msgsmdec.o
 OBJS-$(CONFIG_H261_DECODER)            += h261dec.o h261data.o h261.o
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index 89fadcd..31a6010 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -518,6 +518,7 @@  static void register_all(void)
     REGISTER_DECODER(PCM_ZORK,          pcm_zork);
 
     /* DPCM codecs */
+    REGISTER_DECODER(GREMLIN_DPCM,      gremlin_dpcm);
     REGISTER_DECODER(INTERPLAY_DPCM,    interplay_dpcm);
     REGISTER_ENCDEC (ROQ_DPCM,          roq_dpcm);
     REGISTER_DECODER(SOL_DPCM,          sol_dpcm);
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index 00f9c82..59bd1c5 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -548,6 +548,7 @@  enum AVCodecID {
     AV_CODEC_ID_SOL_DPCM,
 
     AV_CODEC_ID_SDX2_DPCM = 0x14800,
+    AV_CODEC_ID_GREMLIN_DPCM,
 
     /* audio codecs */
     AV_CODEC_ID_MP2 = 0x15000,
diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c
index f0ca4ba..4cc5729 100644
--- a/libavcodec/codec_desc.c
+++ b/libavcodec/codec_desc.c
@@ -2249,6 +2249,13 @@  static const AVCodecDescriptor codec_descriptors[] = {
         .long_name = NULL_IF_CONFIG_SMALL("DPCM Squareroot-Delta-Exact"),
         .props     = AV_CODEC_PROP_LOSSY,
     },
+    {
+        .id        = AV_CODEC_ID_GREMLIN_DPCM,
+        .type      = AVMEDIA_TYPE_AUDIO,
+        .name      = "gremlin_dpcm",
+        .long_name = NULL_IF_CONFIG_SMALL("DPCM Gremlin"),
+        .props     = AV_CODEC_PROP_LOSSY,
+    },
 
     /* audio codecs */
     {
diff --git a/libavcodec/dpcm.c b/libavcodec/dpcm.c
index 2edd4d5..7d3934e 100644
--- a/libavcodec/dpcm.c
+++ b/libavcodec/dpcm.c
@@ -44,7 +44,7 @@ 
 #include "mathops.h"
 
 typedef struct DPCMContext {
-    int16_t square_array[256];
+    int16_t 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->square_array[i      ] =  square;
-            s->square_array[i + 128] = -square;
+            s->array[i      ] =  square;
+            s->array[i + 128] = -square;
         }
         break;
 
@@ -156,7 +156,25 @@  static av_cold int dpcm_decode_init(AVCodecContext *avctx)
     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;
+            s->array[i+128] = i < 0 ? -square: square;
+        }
+        break;
+
+    case AV_CODEC_ID_GREMLIN_DPCM: {
+        int delta = 0;
+        int code = 64;
+        int step = 45;
+
+        s->array[0] = 0;
+        for (i = 0; i < 127; i++) {
+            delta += (code >> 5);
+            code  += step;
+            step  += 2;
+
+            s->array[i*2 + 1] =  delta;
+            s->array[i*2 + 2] = -delta;
+        }
+        s->array[255] = delta + (code >> 5);
         }
         break;
 
@@ -207,6 +225,7 @@  static int dpcm_decode_frame(AVCodecContext *avctx, void *data,
         else
             out = buf_size;
         break;
+    case AV_CODEC_ID_GREMLIN_DPCM:
     case AV_CODEC_ID_SDX2_DPCM:
         out = buf_size;
         break;
@@ -240,7 +259,7 @@  static int dpcm_decode_frame(AVCodecContext *avctx, void *data,
 
         /* decode the samples */
         while (output_samples < samples_end) {
-            predictor[ch] += s->square_array[bytestream2_get_byteu(&gb)];
+            predictor[ch] += s->array[bytestream2_get_byteu(&gb)];
             predictor[ch]  = av_clip_int16(predictor[ch]);
             *output_samples++ = predictor[ch];
 
@@ -335,12 +354,24 @@  static int dpcm_decode_frame(AVCodecContext *avctx, void *data,
 
             if (!(n & 1))
                 s->sample[ch] = 0;
-            s->sample[ch] += s->square_array[n + 128];
+            s->sample[ch] += s->array[n + 128];
             s->sample[ch]  = av_clip_int16(s->sample[ch]);
             *output_samples++ = s->sample[ch];
             ch ^= stereo;
         }
         break;
+
+    case AV_CODEC_ID_GREMLIN_DPCM: {
+        int idx = 0;
+
+        while (output_samples < samples_end) {
+            uint8_t n = bytestream2_get_byteu(&gb);
+
+            *output_samples++ = s->sample[idx] += s->array[n];
+            idx ^= 1;
+        }
+        }
+        break;
     }
 
     *got_frame_ptr = 1;
@@ -360,6 +391,7 @@  AVCodec ff_ ## name_ ## _decoder = {                        \
     .capabilities   = AV_CODEC_CAP_DR1,                     \
 }
 
+DPCM_DECODER(AV_CODEC_ID_GREMLIN_DPCM,   gremlin_dpcm,   "DPCM Gremlin");
 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");