Browse code

avcodec: add SDX2 DPCM decoder

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

Paul B Mahol authored on 2015/10/25 03:41:32
Showing 12 changed files
... ...
@@ -25,6 +25,7 @@ version <next>:
25 25
 - wve demuxer
26 26
 - zero-copy Intel QSV transcoding in ffmpeg
27 27
 - shuffleframes filter
28
+- SDX2 DPCM decoder
28 29
 
29 30
 
30 31
 version 2.8:
... ...
@@ -960,6 +960,8 @@ following image formats are supported:
960 960
     @tab Used in Quake III, Jedi Knight 2 and other computer games.
961 961
 @item DPCM Interplay         @tab     @tab  X
962 962
     @tab Used in various Interplay computer games.
963
+@item DPCM Squareroot-Delta-Exact
964
+    @tab Used in various games.
963 965
 @item DPCM Sierra Online     @tab     @tab  X
964 966
     @tab Used in Sierra Online game audio files.
965 967
 @item DPCM Sol               @tab     @tab  X
... ...
@@ -458,6 +458,7 @@ OBJS-$(CONFIG_S302M_DECODER)           += s302m.o
458 458
 OBJS-$(CONFIG_S302M_ENCODER)           += s302menc.o
459 459
 OBJS-$(CONFIG_SANM_DECODER)            += sanm.o
460 460
 OBJS-$(CONFIG_SCREENPRESSO_DECODER)    += screenpresso.o
461
+OBJS-$(CONFIG_SDX2_DPCM_DECODER)       += dpcm.o
461 462
 OBJS-$(CONFIG_SGI_DECODER)             += sgidec.o
462 463
 OBJS-$(CONFIG_SGI_ENCODER)             += sgienc.o rle.o
463 464
 OBJS-$(CONFIG_SGIRLE_DECODER)          += sgirledec.o
... ...
@@ -287,6 +287,7 @@ void avcodec_register_all(void)
287 287
     REGISTER_ENCDEC (S302M,             s302m);
288 288
     REGISTER_DECODER(SANM,              sanm);
289 289
     REGISTER_DECODER(SCREENPRESSO,      screenpresso);
290
+    REGISTER_DECODER(SDX2_DPCM,         sdx2_dpcm);
290 291
     REGISTER_ENCDEC (SGI,               sgi);
291 292
     REGISTER_DECODER(SGIRLE,            sgirle);
292 293
     REGISTER_DECODER(SMACKER,           smacker);
... ...
@@ -410,6 +410,8 @@ enum AVCodecID {
410 410
     AV_CODEC_ID_XAN_DPCM,
411 411
     AV_CODEC_ID_SOL_DPCM,
412 412
 
413
+    AV_CODEC_ID_SDX2_DPCM = 0x14800,
414
+
413 415
     /* audio codecs */
414 416
     AV_CODEC_ID_MP2 = 0x15000,
415 417
     AV_CODEC_ID_MP3, ///< preferred ID for decoding MPEG audio layer 1, 2 or 3
... ...
@@ -2054,6 +2054,13 @@ static const AVCodecDescriptor codec_descriptors[] = {
2054 2054
         .long_name = NULL_IF_CONFIG_SMALL("DPCM Sol"),
2055 2055
         .props     = AV_CODEC_PROP_LOSSY,
2056 2056
     },
2057
+    {
2058
+        .id        = AV_CODEC_ID_SDX2_DPCM,
2059
+        .type      = AVMEDIA_TYPE_AUDIO,
2060
+        .name      = "sdx2_dpcm",
2061
+        .long_name = NULL_IF_CONFIG_SMALL("DPCM Squareroot-Delta-Exact"),
2062
+        .props     = AV_CODEC_PROP_LOSSY,
2063
+    },
2057 2064
 
2058 2065
     /* audio codecs */
2059 2066
     {
... ...
@@ -44,7 +44,7 @@
44 44
 #include "mathops.h"
45 45
 
46 46
 typedef struct DPCMContext {
47
-    int16_t roq_square_array[256];
47
+    int16_t square_array[256];
48 48
     int sample[2];                  ///< previous sample (for SOL_DPCM)
49 49
     const int8_t *sol_table;        ///< delta table for SOL_DPCM
50 50
 } DPCMContext;
... ...
@@ -130,8 +130,8 @@ static av_cold int dpcm_decode_init(AVCodecContext *avctx)
130 130
         /* initialize square table */
131 131
         for (i = 0; i < 128; i++) {
132 132
             int16_t square = i * i;
133
-            s->roq_square_array[i      ] =  square;
134
-            s->roq_square_array[i + 128] = -square;
133
+            s->square_array[i      ] =  square;
134
+            s->square_array[i + 128] = -square;
135 135
         }
136 136
         break;
137 137
 
... ...
@@ -153,6 +153,13 @@ static av_cold int dpcm_decode_init(AVCodecContext *avctx)
153 153
         }
154 154
         break;
155 155
 
156
+    case AV_CODEC_ID_SDX2_DPCM:
157
+        for (i = -128; i < 128; i++) {
158
+            int16_t square = i * i * 2;
159
+            s->square_array[i+128] = i < 0 ? -square: square;
160
+        }
161
+        break;
162
+
156 163
     default:
157 164
         break;
158 165
     }
... ...
@@ -200,6 +207,9 @@ static int dpcm_decode_frame(AVCodecContext *avctx, void *data,
200 200
         else
201 201
             out = buf_size;
202 202
         break;
203
+    case AV_CODEC_ID_SDX2_DPCM:
204
+        out = buf_size;
205
+        break;
203 206
     }
204 207
     if (out <= 0) {
205 208
         av_log(avctx, AV_LOG_ERROR, "packet is too small\n");
... ...
@@ -230,7 +240,7 @@ static int dpcm_decode_frame(AVCodecContext *avctx, void *data,
230 230
 
231 231
         /* decode the samples */
232 232
         while (output_samples < samples_end) {
233
-            predictor[ch] += s->roq_square_array[bytestream2_get_byteu(&gb)];
233
+            predictor[ch] += s->square_array[bytestream2_get_byteu(&gb)];
234 234
             predictor[ch]  = av_clip_int16(predictor[ch]);
235 235
             *output_samples++ = predictor[ch];
236 236
 
... ...
@@ -318,6 +328,19 @@ static int dpcm_decode_frame(AVCodecContext *avctx, void *data,
318 318
             }
319 319
         }
320 320
         break;
321
+
322
+    case AV_CODEC_ID_SDX2_DPCM:
323
+        while (output_samples < samples_end) {
324
+            int8_t n = bytestream2_get_byteu(&gb);
325
+
326
+            if (!(n & 1))
327
+                s->sample[ch] = 0;
328
+            s->sample[ch] += s->square_array[n + 128];
329
+            s->sample[ch]  = av_clip_int16(s->sample[ch]);
330
+            *output_samples++ = s->sample[ch];
331
+            ch ^= stereo;
332
+        }
333
+        break;
321 334
     }
322 335
 
323 336
     *got_frame_ptr = 1;
... ...
@@ -339,5 +362,6 @@ AVCodec ff_ ## name_ ## _decoder = {                        \
339 339
 
340 340
 DPCM_DECODER(AV_CODEC_ID_INTERPLAY_DPCM, interplay_dpcm, "DPCM Interplay");
341 341
 DPCM_DECODER(AV_CODEC_ID_ROQ_DPCM,       roq_dpcm,       "DPCM id RoQ");
342
+DPCM_DECODER(AV_CODEC_ID_SDX2_DPCM,      sdx2_dpcm,      "DPCM Squareroot-Delta-Exact");
342 343
 DPCM_DECODER(AV_CODEC_ID_SOL_DPCM,       sol_dpcm,       "DPCM Sol");
343 344
 DPCM_DECODER(AV_CODEC_ID_XAN_DPCM,       xan_dpcm,       "DPCM Xan");
... ...
@@ -2906,6 +2906,7 @@ int av_get_exact_bits_per_sample(enum AVCodecID codec_id)
2906 2906
     case AV_CODEC_ID_PCM_S8_PLANAR:
2907 2907
     case AV_CODEC_ID_PCM_U8:
2908 2908
     case AV_CODEC_ID_PCM_ZORK:
2909
+    case AV_CODEC_ID_SDX2_DPCM:
2909 2910
         return 8;
2910 2911
     case AV_CODEC_ID_PCM_S16BE:
2911 2912
     case AV_CODEC_ID_PCM_S16BE_PLANAR:
... ...
@@ -29,7 +29,7 @@
29 29
 #include "libavutil/version.h"
30 30
 
31 31
 #define LIBAVCODEC_VERSION_MAJOR  57
32
-#define LIBAVCODEC_VERSION_MINOR   9
32
+#define LIBAVCODEC_VERSION_MINOR  10
33 33
 #define LIBAVCODEC_VERSION_MICRO 100
34 34
 
35 35
 #define LIBAVCODEC_VERSION_INT  AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
... ...
@@ -52,6 +52,7 @@ static const AVCodecTag ff_codec_aiff_tags[] = {
52 52
     { AV_CODEC_ID_ADPCM_IMA_QT, MKTAG('i','m','a','4') },
53 53
     { AV_CODEC_ID_QDM2,         MKTAG('Q','D','M','2') },
54 54
     { AV_CODEC_ID_QCELP,        MKTAG('Q','c','l','p') },
55
+    { AV_CODEC_ID_SDX2_DPCM,    MKTAG('S','D','X','2') },
55 56
     { AV_CODEC_ID_NONE,         0 },
56 57
 };
57 58
 
... ...
@@ -159,6 +159,7 @@ static int get_aiff_header(AVFormatContext *s, int size,
159 159
             codec->bits_per_coded_sample = 5;
160 160
         case AV_CODEC_ID_ADPCM_G722:
161 161
         case AV_CODEC_ID_MACE6:
162
+        case AV_CODEC_ID_SDX2_DPCM:
162 163
             codec->block_align = 1*codec->channels;
163 164
             break;
164 165
         case AV_CODEC_ID_GSM:
... ...
@@ -84,6 +84,7 @@ static int genh_read_header(AVFormatContext *s)
84 84
     case  5: st->codec->codec_id = st->codec->block_align > 0 ?
85 85
                                    AV_CODEC_ID_PCM_S8_PLANAR :
86 86
                                    AV_CODEC_ID_PCM_S8;           break;
87
+    case  6: st->codec->codec_id = AV_CODEC_ID_SDX2_DPCM;        break;
87 88
     case  7: ret = ff_alloc_extradata(st->codec, 2);
88 89
              if (ret < 0)
89 90
                  return ret;
... ...
@@ -168,6 +169,9 @@ static int genh_read_packet(AVFormatContext *s, AVPacket *pkt)
168 168
             }
169 169
         }
170 170
         ret = 0;
171
+    } else if (codec->codec_id == AV_CODEC_ID_SDX2_DPCM) {
172
+        ret = av_get_packet(s->pb, pkt, codec->block_align * 1024);
173
+
171 174
     } else {
172 175
         ret = av_get_packet(s->pb, pkt, codec->block_align ? codec->block_align : 1024 * codec->channels);
173 176
     }