Browse code

Merge commit '5c018ee18895f88e9e1d2174059dcdd48bf872d2'

* commit '5c018ee18895f88e9e1d2174059dcdd48bf872d2':
DirectDraw Surface image decoder

Conflicts:
Changelog
configure
doc/general.texi
libavcodec/Makefile
libavcodec/version.h
tests/fate/image.mak

Merged-by: Michael Niedermayer <michaelni@gmx.at>

Michael Niedermayer authored on 2015/06/23 06:24:10
Showing 54 changed files
... ...
@@ -5,6 +5,7 @@ version <next>:
5 5
 - colorkey video filter
6 6
 - BFSTM/BCSTM demuxer
7 7
 - little-endian ADPCM_THP decoder
8
+- DirectDraw Surface image/texture decoder
8 9
 
9 10
 
10 11
 version 2.7:
... ...
@@ -2158,6 +2158,7 @@ cook_decoder_select="audiodsp mdct sinewin"
2158 2158
 cscd_decoder_select="lzo"
2159 2159
 cscd_decoder_suggest="zlib"
2160 2160
 dca_decoder_select="fmtconvert mdct"
2161
+dds_decoder_select="texturedsp"
2161 2162
 dirac_decoder_select="dwt golomb videodsp mpegvideoenc"
2162 2163
 dnxhd_decoder_select="blockdsp idctdsp"
2163 2164
 dnxhd_encoder_select="aandcttables blockdsp fdctdsp idctdsp mpegvideoenc pixblockdsp"
... ...
@@ -275,6 +275,7 @@ library:
275 275
 @item Deluxe Paint Animation    @tab   @tab X
276 276
 @item DFA                       @tab   @tab X
277 277
     @tab This format is used in Chronomaster game
278
+@item DirectDraw Surface        @tab   @tab X
278 279
 @item DSD Stream File (DSF)     @tab   @tab X
279 280
 @item DV video                  @tab X @tab X
280 281
 @item DXA                       @tab   @tab X
... ...
@@ -205,6 +205,7 @@ OBJS-$(CONFIG_DCA_DECODER)             += dcadec.o dca.o dcadsp.o      \
205 205
                                           dcadata.o dca_exss.o         \
206 206
                                           dca_xll.o synth_filter.o
207 207
 OBJS-$(CONFIG_DCA_ENCODER)             += dcaenc.o dca.o dcadata.o
208
+OBJS-$(CONFIG_DDS_DECODER)             += dds.o
208 209
 OBJS-$(CONFIG_DIRAC_DECODER)           += diracdec.o dirac.o diracdsp.o \
209 210
                                           dirac_arith.o mpeg12data.o dirac_dwt.o
210 211
 OBJS-$(CONFIG_DFA_DECODER)             += dfa.o
... ...
@@ -140,6 +140,7 @@ void avcodec_register_all(void)
140 140
     REGISTER_DECODER(CPIA,              cpia);
141 141
     REGISTER_DECODER(CSCD,              cscd);
142 142
     REGISTER_DECODER(CYUV,              cyuv);
143
+    REGISTER_DECODER(DDS,               dds);
143 144
     REGISTER_DECODER(DFA,               dfa);
144 145
     REGISTER_DECODER(DIRAC,             dirac);
145 146
     REGISTER_ENCDEC (DNXHD,             dnxhd);
... ...
@@ -294,6 +294,7 @@ enum AVCodecID {
294 294
     AV_CODEC_ID_TDSC,
295 295
     AV_CODEC_ID_HQ_HQA,
296 296
     AV_CODEC_ID_HAP,
297
+    AV_CODEC_ID_DDS,
297 298
 
298 299
     AV_CODEC_ID_BRENDER_PIX= MKBETAG('B','P','I','X'),
299 300
     AV_CODEC_ID_Y41P       = MKBETAG('Y','4','1','P'),
... ...
@@ -1283,6 +1283,14 @@ static const AVCodecDescriptor codec_descriptors[] = {
1283 1283
         .props     = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS,
1284 1284
     },
1285 1285
     {
1286
+        .id        = AV_CODEC_ID_DDS,
1287
+        .type      = AVMEDIA_TYPE_VIDEO,
1288
+        .name      = "dds",
1289
+        .long_name = NULL_IF_CONFIG_SMALL("DirectDraw Surface image decoder"),
1290
+        .props     = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY |
1291
+                     AV_CODEC_PROP_LOSSLESS,
1292
+    },
1293
+    {
1286 1294
         .id        = AV_CODEC_ID_DPX,
1287 1295
         .type      = AVMEDIA_TYPE_VIDEO,
1288 1296
         .name      = "dpx",
1289 1297
new file mode 100644
... ...
@@ -0,0 +1,660 @@
0
+/*
1
+ * DirectDraw Surface image decoder
2
+ * Copyright (C) 2015 Vittorio Giovara <vittorio.giovara@gmail.com>
3
+ *
4
+ * This file is part of FFmpeg.
5
+ *
6
+ * FFmpeg is free software; you can redistribute it and/or
7
+ * modify it under the terms of the GNU Lesser General Public
8
+ * License as published by the Free Software Foundation; either
9
+ * version 2.1 of the License, or (at your option) any later version.
10
+ *
11
+ * FFmpeg is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
+ * Lesser General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU Lesser General Public
17
+ * License along with FFmpeg; if not, write to the Free Software
18
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
+ */
20
+
21
+/**
22
+ * @file
23
+ * DDS decoder
24
+ *
25
+ * https://msdn.microsoft.com/en-us/library/bb943982%28v=vs.85%29.aspx
26
+ */
27
+
28
+#include <stdint.h>
29
+
30
+#include "libavutil/imgutils.h"
31
+
32
+#include "avcodec.h"
33
+#include "bytestream.h"
34
+#include "internal.h"
35
+#include "texturedsp.h"
36
+#include "thread.h"
37
+
38
+#define DDPF_FOURCC    (1 <<  2)
39
+#define DDPF_PALETTE   (1 <<  5)
40
+#define DDPF_NORMALMAP (1 << 31)
41
+
42
+enum DDSPostProc {
43
+    DDS_NONE = 0,
44
+    DDS_ALPHA_EXP,
45
+    DDS_NORMAL_MAP,
46
+    DDS_RAW_YCOCG,
47
+    DDS_SWAP_ALPHA,
48
+    DDS_SWIZZLE_A2XY,
49
+    DDS_SWIZZLE_RBXG,
50
+    DDS_SWIZZLE_RGXB,
51
+    DDS_SWIZZLE_RXBG,
52
+    DDS_SWIZZLE_RXGB,
53
+    DDS_SWIZZLE_XGBR,
54
+    DDS_SWIZZLE_XRBG,
55
+    DDS_SWIZZLE_XGXR,
56
+} DDSPostProc;
57
+
58
+enum DDSDXGIFormat {
59
+    DXGI_FORMAT_R16G16B16A16_TYPELESS       =  9,
60
+    DXGI_FORMAT_R16G16B16A16_FLOAT          = 10,
61
+    DXGI_FORMAT_R16G16B16A16_UNORM          = 11,
62
+    DXGI_FORMAT_R16G16B16A16_UINT           = 12,
63
+    DXGI_FORMAT_R16G16B16A16_SNORM          = 13,
64
+    DXGI_FORMAT_R16G16B16A16_SINT           = 14,
65
+
66
+    DXGI_FORMAT_R8G8B8A8_TYPELESS           = 27,
67
+    DXGI_FORMAT_R8G8B8A8_UNORM              = 28,
68
+    DXGI_FORMAT_R8G8B8A8_UNORM_SRGB         = 29,
69
+    DXGI_FORMAT_R8G8B8A8_UINT               = 30,
70
+    DXGI_FORMAT_R8G8B8A8_SNORM              = 31,
71
+    DXGI_FORMAT_R8G8B8A8_SINT               = 32,
72
+
73
+    DXGI_FORMAT_BC1_TYPELESS                = 70,
74
+    DXGI_FORMAT_BC1_UNORM                   = 71,
75
+    DXGI_FORMAT_BC1_UNORM_SRGB              = 72,
76
+    DXGI_FORMAT_BC2_TYPELESS                = 73,
77
+    DXGI_FORMAT_BC2_UNORM                   = 74,
78
+    DXGI_FORMAT_BC2_UNORM_SRGB              = 75,
79
+    DXGI_FORMAT_BC3_TYPELESS                = 76,
80
+    DXGI_FORMAT_BC3_UNORM                   = 77,
81
+    DXGI_FORMAT_BC3_UNORM_SRGB              = 78,
82
+    DXGI_FORMAT_BC4_TYPELESS                = 79,
83
+    DXGI_FORMAT_BC4_UNORM                   = 80,
84
+    DXGI_FORMAT_BC4_SNORM                   = 81,
85
+    DXGI_FORMAT_BC5_TYPELESS                = 82,
86
+    DXGI_FORMAT_BC5_UNORM                   = 83,
87
+    DXGI_FORMAT_BC5_SNORM                   = 84,
88
+    DXGI_FORMAT_B5G6R5_UNORM                = 85,
89
+    DXGI_FORMAT_B8G8R8A8_UNORM              = 87,
90
+    DXGI_FORMAT_B8G8R8X8_UNORM              = 88,
91
+    DXGI_FORMAT_B8G8R8A8_TYPELESS           = 90,
92
+    DXGI_FORMAT_B8G8R8A8_UNORM_SRGB         = 91,
93
+    DXGI_FORMAT_B8G8R8X8_TYPELESS           = 92,
94
+    DXGI_FORMAT_B8G8R8X8_UNORM_SRGB         = 93,
95
+} DDSDXGIFormat;
96
+
97
+typedef struct DDSContext {
98
+    TextureDSPContext texdsp;
99
+    GetByteContext gbc;
100
+
101
+    int compressed;
102
+    int paletted;
103
+    enum DDSPostProc postproc;
104
+
105
+    const uint8_t *tex_data; // Compressed texture
106
+    int tex_ratio;           // Compression ratio
107
+
108
+    /* Pointer to the selected compress or decompress function. */
109
+    int (*tex_funct)(uint8_t *dst, ptrdiff_t stride, const uint8_t *block);
110
+} DDSContext;
111
+
112
+static int parse_pixel_format(AVCodecContext *avctx)
113
+{
114
+    DDSContext *ctx = avctx->priv_data;
115
+    GetByteContext *gbc = &ctx->gbc;
116
+    char buf[32];
117
+    uint32_t flags, fourcc, gimp_tag;
118
+    enum DDSDXGIFormat dxgi;
119
+    int size, bpp, r, g, b, a;
120
+    int alpha_exponent, ycocg_classic, ycocg_scaled, normal_map, array;
121
+
122
+    /* Alternative DDS implementations use reserved1 as custom header. */
123
+    bytestream2_skip(gbc, 4 * 3);
124
+    gimp_tag = bytestream2_get_le32(gbc);
125
+    alpha_exponent = gimp_tag == MKTAG('A', 'E', 'X', 'P');
126
+    ycocg_classic  = gimp_tag == MKTAG('Y', 'C', 'G', '1');
127
+    ycocg_scaled   = gimp_tag == MKTAG('Y', 'C', 'G', '2');
128
+    bytestream2_skip(gbc, 4 * 7);
129
+
130
+    /* Now the real DDPF starts. */
131
+    size = bytestream2_get_le32(gbc);
132
+    if (size != 32) {
133
+        av_log(avctx, AV_LOG_ERROR, "Invalid pixel format header %d.\n", size);
134
+        return AVERROR_INVALIDDATA;
135
+    }
136
+    flags = bytestream2_get_le32(gbc);
137
+    ctx->compressed = flags & DDPF_FOURCC;
138
+    ctx->paletted   = flags & DDPF_PALETTE;
139
+    normal_map      = flags & DDPF_NORMALMAP;
140
+    fourcc = bytestream2_get_le32(gbc);
141
+
142
+    bpp = bytestream2_get_le32(gbc); // rgbbitcount
143
+    r   = bytestream2_get_le32(gbc); // rbitmask
144
+    g   = bytestream2_get_le32(gbc); // gbitmask
145
+    b   = bytestream2_get_le32(gbc); // bbitmask
146
+    a   = bytestream2_get_le32(gbc); // abitmask
147
+
148
+    bytestream2_skip(gbc, 4); // caps
149
+    bytestream2_skip(gbc, 4); // caps2
150
+    bytestream2_skip(gbc, 4); // caps3
151
+    bytestream2_skip(gbc, 4); // caps4
152
+    bytestream2_skip(gbc, 4); // reserved2
153
+
154
+    av_get_codec_tag_string(buf, sizeof(buf), fourcc);
155
+    av_log(avctx, AV_LOG_VERBOSE, "fourcc %s bpp %d "
156
+           "r 0x%x g 0x%x b 0x%x a 0x%x\n", buf, bpp, r, g, b, a);
157
+    if (gimp_tag) {
158
+        av_get_codec_tag_string(buf, sizeof(buf), gimp_tag);
159
+        av_log(avctx, AV_LOG_VERBOSE, "and GIMP-DDS tag %s\n", buf);
160
+    }
161
+
162
+    if (ctx->compressed)
163
+        avctx->pix_fmt = AV_PIX_FMT_RGBA;
164
+
165
+    if (ctx->compressed) {
166
+        switch (fourcc) {
167
+        case MKTAG('D', 'X', 'T', '1'):
168
+            ctx->tex_ratio = 8;
169
+            ctx->tex_funct = ctx->texdsp.dxt1a_block;
170
+            break;
171
+        case MKTAG('D', 'X', 'T', '2'):
172
+            ctx->tex_ratio = 16;
173
+            ctx->tex_funct = ctx->texdsp.dxt2_block;
174
+            break;
175
+        case MKTAG('D', 'X', 'T', '3'):
176
+            ctx->tex_ratio = 16;
177
+            ctx->tex_funct = ctx->texdsp.dxt3_block;
178
+            break;
179
+        case MKTAG('D', 'X', 'T', '4'):
180
+            ctx->tex_ratio = 16;
181
+            ctx->tex_funct = ctx->texdsp.dxt4_block;
182
+            break;
183
+        case MKTAG('D', 'X', 'T', '5'):
184
+            ctx->tex_ratio = 16;
185
+            if (ycocg_scaled)
186
+                ctx->tex_funct = ctx->texdsp.dxt5ys_block;
187
+            else if (ycocg_classic)
188
+                ctx->tex_funct = ctx->texdsp.dxt5y_block;
189
+            else
190
+                ctx->tex_funct = ctx->texdsp.dxt5_block;
191
+            break;
192
+        case MKTAG('R', 'X', 'G', 'B'):
193
+            ctx->tex_ratio = 16;
194
+            ctx->tex_funct = ctx->texdsp.dxt5_block;
195
+            /* This format may be considered as a normal map,
196
+             * but it is handled differently in a separate postproc. */
197
+            ctx->postproc = DDS_SWIZZLE_RXGB;
198
+            normal_map = 0;
199
+            break;
200
+        case MKTAG('A', 'T', 'I', '1'):
201
+        case MKTAG('B', 'C', '4', 'U'):
202
+            ctx->tex_ratio = 8;
203
+            ctx->tex_funct = ctx->texdsp.rgtc1u_block;
204
+            break;
205
+        case MKTAG('B', 'C', '4', 'S'):
206
+            ctx->tex_ratio = 8;
207
+            ctx->tex_funct = ctx->texdsp.rgtc1s_block;
208
+            break;
209
+        case MKTAG('A', 'T', 'I', '2'):
210
+            /* RGT2 variant with swapped R and G (3Dc)*/
211
+            ctx->tex_ratio = 16;
212
+            ctx->tex_funct = ctx->texdsp.dxn3dc_block;
213
+            break;
214
+        case MKTAG('B', 'C', '5', 'U'):
215
+            ctx->tex_ratio = 16;
216
+            ctx->tex_funct = ctx->texdsp.rgtc2u_block;
217
+            break;
218
+        case MKTAG('B', 'C', '5', 'S'):
219
+            ctx->tex_ratio = 16;
220
+            ctx->tex_funct = ctx->texdsp.rgtc2s_block;
221
+            break;
222
+        case MKTAG('U', 'Y', 'V', 'Y'):
223
+            ctx->compressed = 0;
224
+            avctx->pix_fmt = AV_PIX_FMT_UYVY422;
225
+            break;
226
+        case MKTAG('Y', 'U', 'Y', '2'):
227
+            ctx->compressed = 0;
228
+            avctx->pix_fmt = AV_PIX_FMT_YUYV422;
229
+            break;
230
+        case MKTAG('P', '8', ' ', ' '):
231
+            /* ATI Palette8, same as normal palette */
232
+            ctx->compressed = 0;
233
+            ctx->paletted   = 1;
234
+            avctx->pix_fmt  = AV_PIX_FMT_PAL8;
235
+            break;
236
+        case MKTAG('D', 'X', '1', '0'):
237
+            /* DirectX 10 extra header */
238
+            dxgi = bytestream2_get_le32(gbc);
239
+            bytestream2_skip(gbc, 4); // resourceDimension
240
+            bytestream2_skip(gbc, 4); // miscFlag
241
+            array = bytestream2_get_le32(gbc);
242
+            bytestream2_skip(gbc, 4); // miscFlag2
243
+
244
+            if (array != 0)
245
+                av_log(avctx, AV_LOG_VERBOSE,
246
+                       "Found array of size %d (ignored).\n", array);
247
+
248
+            /* Only BC[1-5] are actually compressed. */
249
+            ctx->compressed = (dxgi >= 70) && (dxgi <= 84);
250
+
251
+            av_log(avctx, AV_LOG_VERBOSE, "DXGI format %d.\n", dxgi);
252
+            switch (dxgi) {
253
+            /* RGB types. */
254
+            case DXGI_FORMAT_R16G16B16A16_TYPELESS:
255
+            case DXGI_FORMAT_R16G16B16A16_FLOAT:
256
+            case DXGI_FORMAT_R16G16B16A16_UNORM:
257
+            case DXGI_FORMAT_R16G16B16A16_UINT:
258
+            case DXGI_FORMAT_R16G16B16A16_SNORM:
259
+            case DXGI_FORMAT_R16G16B16A16_SINT:
260
+                avctx->pix_fmt = AV_PIX_FMT_BGRA64;
261
+                break;
262
+            case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
263
+                avctx->colorspace = AVCOL_SPC_RGB;
264
+            case DXGI_FORMAT_R8G8B8A8_TYPELESS:
265
+            case DXGI_FORMAT_R8G8B8A8_UNORM:
266
+            case DXGI_FORMAT_R8G8B8A8_UINT:
267
+            case DXGI_FORMAT_R8G8B8A8_SNORM:
268
+            case DXGI_FORMAT_R8G8B8A8_SINT:
269
+                avctx->pix_fmt = AV_PIX_FMT_BGRA;
270
+                break;
271
+            case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
272
+                avctx->colorspace = AVCOL_SPC_RGB;
273
+            case DXGI_FORMAT_B8G8R8A8_TYPELESS:
274
+            case DXGI_FORMAT_B8G8R8A8_UNORM:
275
+                avctx->pix_fmt = AV_PIX_FMT_RGBA;
276
+                break;
277
+            case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
278
+                avctx->colorspace = AVCOL_SPC_RGB;
279
+            case DXGI_FORMAT_B8G8R8X8_TYPELESS:
280
+            case DXGI_FORMAT_B8G8R8X8_UNORM:
281
+                avctx->pix_fmt = AV_PIX_FMT_RGBA; // opaque
282
+                break;
283
+            case DXGI_FORMAT_B5G6R5_UNORM:
284
+                avctx->pix_fmt = AV_PIX_FMT_RGB565LE;
285
+                break;
286
+            /* Texture types. */
287
+            case DXGI_FORMAT_BC1_UNORM_SRGB:
288
+                avctx->colorspace = AVCOL_SPC_RGB;
289
+            case DXGI_FORMAT_BC1_TYPELESS:
290
+            case DXGI_FORMAT_BC1_UNORM:
291
+                ctx->tex_ratio = 8;
292
+                ctx->tex_funct = ctx->texdsp.dxt1a_block;
293
+                break;
294
+            case DXGI_FORMAT_BC2_UNORM_SRGB:
295
+                avctx->colorspace = AVCOL_SPC_RGB;
296
+            case DXGI_FORMAT_BC2_TYPELESS:
297
+            case DXGI_FORMAT_BC2_UNORM:
298
+                ctx->tex_ratio = 16;
299
+                ctx->tex_funct = ctx->texdsp.dxt3_block;
300
+                break;
301
+            case DXGI_FORMAT_BC3_UNORM_SRGB:
302
+                avctx->colorspace = AVCOL_SPC_RGB;
303
+            case DXGI_FORMAT_BC3_TYPELESS:
304
+            case DXGI_FORMAT_BC3_UNORM:
305
+                ctx->tex_ratio = 16;
306
+                ctx->tex_funct = ctx->texdsp.dxt5_block;
307
+                break;
308
+            case DXGI_FORMAT_BC4_TYPELESS:
309
+            case DXGI_FORMAT_BC4_UNORM:
310
+                ctx->tex_ratio = 8;
311
+                ctx->tex_funct = ctx->texdsp.rgtc1u_block;
312
+                break;
313
+            case DXGI_FORMAT_BC4_SNORM:
314
+                ctx->tex_ratio = 8;
315
+                ctx->tex_funct = ctx->texdsp.rgtc1s_block;
316
+                break;
317
+            case DXGI_FORMAT_BC5_TYPELESS:
318
+            case DXGI_FORMAT_BC5_UNORM:
319
+                ctx->tex_ratio = 16;
320
+                ctx->tex_funct = ctx->texdsp.rgtc2u_block;
321
+                break;
322
+            case DXGI_FORMAT_BC5_SNORM:
323
+                ctx->tex_ratio = 16;
324
+                ctx->tex_funct = ctx->texdsp.rgtc2s_block;
325
+                break;
326
+            default:
327
+                av_log(avctx, AV_LOG_ERROR,
328
+                       "Unsupported DXGI format %d.\n", dxgi);
329
+                return AVERROR_INVALIDDATA;
330
+            }
331
+            break;
332
+        default:
333
+            av_log(avctx, AV_LOG_ERROR, "Unsupported %s fourcc.\n", buf);
334
+            return AVERROR_INVALIDDATA;
335
+        }
336
+    } else if (ctx->paletted) {
337
+        if (bpp == 8) {
338
+            avctx->pix_fmt = AV_PIX_FMT_PAL8;
339
+        } else {
340
+            av_log(avctx, AV_LOG_ERROR, "Unsupported palette bpp %d.\n", bpp);
341
+            return AVERROR_INVALIDDATA;
342
+        }
343
+    } else {
344
+        /*  8 bpp */
345
+        if (bpp == 8 && r == 0xff && g == 0 && b == 0 && a == 0)
346
+            avctx->pix_fmt = AV_PIX_FMT_GRAY8;
347
+        /* 16 bpp */
348
+        else if (bpp == 16 && r == 0xff && g == 0 && b == 0 && a == 0xff00)
349
+            avctx->pix_fmt = AV_PIX_FMT_YA8;
350
+        else if (bpp == 16 && r == 0xffff && g == 0 && b == 0 && a == 0)
351
+            avctx->pix_fmt = AV_PIX_FMT_GRAY16LE;
352
+        else if (bpp == 16 && r == 0xf800 && g == 0x7e0 && b == 0x1f && a == 0)
353
+            avctx->pix_fmt = AV_PIX_FMT_RGB565LE;
354
+        /* 24 bpp */
355
+        else if (bpp == 24 && r == 0xff0000 && g == 0xff00 && b == 0xff && a == 0)
356
+            avctx->pix_fmt = AV_PIX_FMT_BGR24;
357
+        /* 32 bpp */
358
+        else if (bpp == 32 && r == 0xff0000 && g == 0xff00 && b == 0xff && a == 0)
359
+            avctx->pix_fmt = AV_PIX_FMT_RGBA; // opaque
360
+        else if (bpp == 32 && r == 0xff && g == 0xff00 && b == 0xff0000 && a == 0)
361
+            avctx->pix_fmt = AV_PIX_FMT_BGRA; // opaque
362
+        else if (bpp == 32 && r == 0xff0000 && g == 0xff00 && b == 0xff && a == 0xff000000)
363
+            avctx->pix_fmt = AV_PIX_FMT_RGBA;
364
+        else if (bpp == 32 && r == 0xff && g == 0xff00 && b == 0xff0000 && a == 0xff000000)
365
+            avctx->pix_fmt = AV_PIX_FMT_BGRA;
366
+        /* give up */
367
+        else {
368
+            av_log(avctx, AV_LOG_ERROR, "Unknown pixel format "
369
+                   "[bpp %d r 0x%x g 0x%x b 0x%x a 0x%x].\n", bpp, r, g, b, a);
370
+            return AVERROR_INVALIDDATA;
371
+        }
372
+    }
373
+
374
+    /* Set any remaining post-proc that should happen before frame is ready. */
375
+    if (alpha_exponent)
376
+        ctx->postproc = DDS_ALPHA_EXP;
377
+    else if (normal_map)
378
+        ctx->postproc = DDS_NORMAL_MAP;
379
+    else if (ycocg_classic && !ctx->compressed)
380
+        ctx->postproc = DDS_RAW_YCOCG;
381
+    else if (avctx->pix_fmt == AV_PIX_FMT_YA8)
382
+        ctx->postproc = DDS_SWAP_ALPHA;
383
+
384
+    /* ATI/NVidia variants sometimes add swizzling in bpp. */
385
+    switch (bpp) {
386
+    case MKTAG('A', '2', 'X', 'Y'):
387
+        ctx->postproc = DDS_SWIZZLE_A2XY;
388
+        break;
389
+    case MKTAG('x', 'G', 'B', 'R'):
390
+        ctx->postproc = DDS_SWIZZLE_XGBR;
391
+        break;
392
+    case MKTAG('x', 'R', 'B', 'G'):
393
+        ctx->postproc = DDS_SWIZZLE_XRBG;
394
+        break;
395
+    case MKTAG('R', 'B', 'x', 'G'):
396
+        ctx->postproc = DDS_SWIZZLE_RBXG;
397
+        break;
398
+    case MKTAG('R', 'G', 'x', 'B'):
399
+        ctx->postproc = DDS_SWIZZLE_RGXB;
400
+        break;
401
+    case MKTAG('R', 'x', 'B', 'G'):
402
+        ctx->postproc = DDS_SWIZZLE_RXBG;
403
+        break;
404
+    case MKTAG('x', 'G', 'x', 'R'):
405
+        ctx->postproc = DDS_SWIZZLE_XGXR;
406
+        break;
407
+    case MKTAG('A', '2', 'D', '5'):
408
+        ctx->postproc = DDS_NORMAL_MAP;
409
+        break;
410
+    }
411
+
412
+    return 0;
413
+}
414
+
415
+static int decompress_texture_thread(AVCodecContext *avctx, void *arg,
416
+                                     int block_nb, int thread_nb)
417
+{
418
+    DDSContext *ctx = avctx->priv_data;
419
+    AVFrame *frame = arg;
420
+    int x = (TEXTURE_BLOCK_W * block_nb) % avctx->coded_width;
421
+    int y = TEXTURE_BLOCK_H * (TEXTURE_BLOCK_W * block_nb / avctx->coded_width);
422
+    uint8_t *p = frame->data[0] + x * 4 + y * frame->linesize[0];
423
+    const uint8_t *d = ctx->tex_data + block_nb * ctx->tex_ratio;
424
+
425
+    ctx->tex_funct(p, frame->linesize[0], d);
426
+    return 0;
427
+}
428
+
429
+static void do_swizzle(AVFrame *frame, int x, int y)
430
+{
431
+    int i;
432
+    for (i = 0; i < frame->linesize[0] * frame->height; i += 4) {
433
+        uint8_t *src = frame->data[0] + i;
434
+        FFSWAP(uint8_t, src[x], src[y]);
435
+    }
436
+}
437
+
438
+static void run_postproc(AVCodecContext *avctx, AVFrame *frame)
439
+{
440
+    DDSContext *ctx = avctx->priv_data;
441
+    int i, x_off;
442
+
443
+    switch (ctx->postproc) {
444
+    case DDS_ALPHA_EXP:
445
+        /* Alpha-exponential mode divides each channel by the maximum
446
+         * R, G or B value, and stores the multiplying factor in the
447
+         * alpha channel. */
448
+        av_log(avctx, AV_LOG_DEBUG, "Post-processing alpha exponent.\n");
449
+
450
+        for (i = 0; i < frame->linesize[0] * frame->height; i += 4) {
451
+            uint8_t *src = frame->data[0] + i;
452
+            int r = src[0];
453
+            int g = src[1];
454
+            int b = src[2];
455
+            int a = src[3];
456
+
457
+            src[0] = r * a / 255;
458
+            src[1] = g * a / 255;
459
+            src[2] = b * a / 255;
460
+            src[3] = 255;
461
+        }
462
+        break;
463
+    case DDS_NORMAL_MAP:
464
+        /* Normal maps work in the XYZ color space and they encode
465
+         * X in R or in A, depending on the texture type, Y in G and
466
+         * derive Z with a square root of the distance.
467
+         *
468
+         * http://www.realtimecollisiondetection.net/blog/?p=28 */
469
+        av_log(avctx, AV_LOG_DEBUG, "Post-processing normal map.\n");
470
+
471
+        x_off = ctx->tex_ratio == 8 ? 0 : 3;
472
+        for (i = 0; i < frame->linesize[0] * frame->height; i += 4) {
473
+            uint8_t *src = frame->data[0] + i;
474
+            int x = src[x_off];
475
+            int y = src[1];
476
+            int z = 127;
477
+
478
+            int d = (255 * 255 - x * x - y * y) / 2;
479
+            if (d > 0)
480
+                z = rint(sqrtf(d));
481
+
482
+            src[0] = x;
483
+            src[1] = y;
484
+            src[2] = z;
485
+            src[3] = 255;
486
+        }
487
+        break;
488
+    case DDS_RAW_YCOCG:
489
+        /* Data is Y-Co-Cg-A and not RGBA, but they are represented
490
+         * with the same masks in the DDPF header. */
491
+        av_log(avctx, AV_LOG_DEBUG, "Post-processing raw YCoCg.\n");
492
+
493
+        for (i = 0; i < frame->linesize[0] * frame->height; i += 4) {
494
+            uint8_t *src = frame->data[0] + i;
495
+            int a  = src[0];
496
+            int cg = src[1] - 128;
497
+            int co = src[2] - 128;
498
+            int y  = src[3];
499
+
500
+            src[0] = av_clip_uint8(y + co - cg);
501
+            src[1] = av_clip_uint8(y + cg);
502
+            src[2] = av_clip_uint8(y - co - cg);
503
+            src[3] = a;
504
+        }
505
+        break;
506
+    case DDS_SWAP_ALPHA:
507
+        /* Alpha and Luma are stored swapped. */
508
+        av_log(avctx, AV_LOG_DEBUG, "Post-processing swapped Luma/Alpha.\n");
509
+
510
+        for (i = 0; i < frame->linesize[0] * frame->height; i += 2) {
511
+            uint8_t *src = frame->data[0] + i;
512
+            FFSWAP(uint8_t, src[0], src[1]);
513
+        }
514
+        break;
515
+    case DDS_SWIZZLE_A2XY:
516
+        /* Swap R and G, often used to restore a standard RGTC2. */
517
+        av_log(avctx, AV_LOG_DEBUG, "Post-processing A2XY swizzle.\n");
518
+        do_swizzle(frame, 0, 1);
519
+        break;
520
+    case DDS_SWIZZLE_RBXG:
521
+        /* Swap G and A, then B and new A (G). */
522
+        av_log(avctx, AV_LOG_DEBUG, "Post-processing RBXG swizzle.\n");
523
+        do_swizzle(frame, 1, 3);
524
+        do_swizzle(frame, 2, 3);
525
+        break;
526
+    case DDS_SWIZZLE_RGXB:
527
+        /* Swap B and A. */
528
+        av_log(avctx, AV_LOG_DEBUG, "Post-processing RGXB swizzle.\n");
529
+        do_swizzle(frame, 2, 3);
530
+        break;
531
+    case DDS_SWIZZLE_RXBG:
532
+        /* Swap G and A. */
533
+        av_log(avctx, AV_LOG_DEBUG, "Post-processing RXBG swizzle.\n");
534
+        do_swizzle(frame, 1, 3);
535
+        break;
536
+    case DDS_SWIZZLE_RXGB:
537
+        /* Swap R and A (misleading name). */
538
+        av_log(avctx, AV_LOG_DEBUG, "Post-processing RXGB swizzle.\n");
539
+        do_swizzle(frame, 0, 3);
540
+        break;
541
+    case DDS_SWIZZLE_XGBR:
542
+        /* Swap B and A, then R and new A (B). */
543
+        av_log(avctx, AV_LOG_DEBUG, "Post-processing XGBR swizzle.\n");
544
+        do_swizzle(frame, 2, 3);
545
+        do_swizzle(frame, 0, 3);
546
+        break;
547
+    case DDS_SWIZZLE_XGXR:
548
+        /* Swap G and A, then R and new A (G), then new R (G) and new G (A).
549
+         * This variant does not store any B component. */
550
+        av_log(avctx, AV_LOG_DEBUG, "Post-processing XGXR swizzle.\n");
551
+        do_swizzle(frame, 1, 3);
552
+        do_swizzle(frame, 0, 3);
553
+        do_swizzle(frame, 0, 1);
554
+        break;
555
+    case DDS_SWIZZLE_XRBG:
556
+        /* Swap G and A, then R and new A (G). */
557
+        av_log(avctx, AV_LOG_DEBUG, "Post-processing XRBG swizzle.\n");
558
+        do_swizzle(frame, 1, 3);
559
+        do_swizzle(frame, 0, 3);
560
+        break;
561
+    }
562
+}
563
+
564
+static int dds_decode(AVCodecContext *avctx, void *data,
565
+                      int *got_frame, AVPacket *avpkt)
566
+{
567
+    DDSContext *ctx = avctx->priv_data;
568
+    GetByteContext *gbc = &ctx->gbc;
569
+    AVFrame *frame = data;
570
+    int blocks, mipmap;
571
+    int ret;
572
+
573
+    ff_texturedsp_init(&ctx->texdsp);
574
+    bytestream2_init(gbc, avpkt->data, avpkt->size);
575
+
576
+    if (bytestream2_get_bytes_left(gbc) < 128) {
577
+        av_log(avctx, AV_LOG_ERROR, "Frame is too small (%d).",
578
+               bytestream2_get_bytes_left(gbc));
579
+        return AVERROR_INVALIDDATA;
580
+    }
581
+
582
+    if (bytestream2_get_le32(gbc) != MKTAG('D', 'D', 'S', ' ') ||
583
+        bytestream2_get_le32(gbc) != 124) { // header size
584
+        av_log(avctx, AV_LOG_ERROR, "Invalid DDS header.");
585
+        return AVERROR_INVALIDDATA;
586
+    }
587
+
588
+    bytestream2_skip(gbc, 4); // flags
589
+
590
+    avctx->height = bytestream2_get_le32(gbc);
591
+    avctx->width  = bytestream2_get_le32(gbc);
592
+    ret = av_image_check_size(avctx->width, avctx->height, 0, avctx);
593
+    if (ret < 0) {
594
+        av_log(avctx, AV_LOG_ERROR, "Invalid image size %dx%d.\n",
595
+               avctx->width, avctx->height);
596
+        return ret;
597
+    }
598
+
599
+    /* Since codec is based on 4x4 blocks, size is aligned to 4. */
600
+    avctx->coded_width  = FFALIGN(avctx->width,  TEXTURE_BLOCK_W);
601
+    avctx->coded_height = FFALIGN(avctx->height, TEXTURE_BLOCK_H);
602
+
603
+    bytestream2_skip(gbc, 4); // pitch
604
+    bytestream2_skip(gbc, 4); // depth
605
+    mipmap = bytestream2_get_le32(gbc);
606
+    if (mipmap != 0)
607
+        av_log(avctx, AV_LOG_VERBOSE, "Found %d mipmaps (ignored).\n", mipmap);
608
+
609
+    /* Extract pixel format information, considering additional elements
610
+     * in reserved1 and reserved2. */
611
+    ret = parse_pixel_format(avctx);
612
+    if (ret < 0)
613
+        return ret;
614
+
615
+    ret = ff_get_buffer(avctx, frame, 0);
616
+    if (ret < 0)
617
+        return ret;
618
+
619
+    if (ctx->compressed) {
620
+        /* Use the decompress function on the texture, one block per thread. */
621
+        ctx->tex_data = gbc->buffer;
622
+        blocks = avctx->coded_width * avctx->coded_height / (TEXTURE_BLOCK_W * TEXTURE_BLOCK_H);
623
+        avctx->execute2(avctx, decompress_texture_thread, frame, NULL, blocks);
624
+    } else {
625
+        int linesize = av_image_get_linesize(avctx->pix_fmt, frame->width, 0);
626
+
627
+        if (ctx->paletted) {
628
+            /* Use the first 1024 bytes as palette, then copy the rest. */
629
+            bytestream2_get_buffer(gbc, frame->data[1], 256 * 4);
630
+            frame->palette_has_changed = 1;
631
+        }
632
+
633
+        av_image_copy_plane(frame->data[0], frame->linesize[0],
634
+                            gbc->buffer, linesize,
635
+                            linesize, frame->height);
636
+    }
637
+
638
+    /* Run any post processing here if needed. */
639
+    if (avctx->pix_fmt == AV_PIX_FMT_RGBA || avctx->pix_fmt == AV_PIX_FMT_YA8)
640
+        run_postproc(avctx, frame);
641
+
642
+    /* Frame is ready to be output. */
643
+    frame->pict_type = AV_PICTURE_TYPE_I;
644
+    frame->key_frame = 1;
645
+    *got_frame = 1;
646
+
647
+    return avpkt->size;
648
+}
649
+
650
+AVCodec ff_dds_decoder = {
651
+    .name           = "dds",
652
+    .long_name      = NULL_IF_CONFIG_SMALL("DirectDraw Surface image decoder"),
653
+    .type           = AVMEDIA_TYPE_VIDEO,
654
+    .id             = AV_CODEC_ID_DDS,
655
+    .decode         = dds_decode,
656
+    .priv_data_size = sizeof(DDSContext),
657
+    .capabilities   = CODEC_CAP_DR1 | CODEC_CAP_SLICE_THREADS,
658
+    .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE
659
+};
... ...
@@ -29,7 +29,7 @@
29 29
 #include "libavutil/version.h"
30 30
 
31 31
 #define LIBAVCODEC_VERSION_MAJOR 56
32
-#define LIBAVCODEC_VERSION_MINOR  43
32
+#define LIBAVCODEC_VERSION_MINOR  44
33 33
 #define LIBAVCODEC_VERSION_MICRO 100
34 34
 
35 35
 #define LIBAVCODEC_VERSION_INT  AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
... ...
@@ -45,6 +45,7 @@ static const IdStrMap img_tags[] = {
45 45
     { AV_CODEC_ID_PBM,        "pbm"      },
46 46
     { AV_CODEC_ID_PAM,        "pam"      },
47 47
     { AV_CODEC_ID_ALIAS_PIX,  "pix"      },
48
+    { AV_CODEC_ID_DDS,        "dds"      },
48 49
     { AV_CODEC_ID_MPEG1VIDEO, "mpg1-img" },
49 50
     { AV_CODEC_ID_MPEG2VIDEO, "mpg2-img" },
50 51
     { AV_CODEC_ID_MPEG4,      "mpg4-img" },
... ...
@@ -30,6 +30,18 @@ fate-brenderpix: $(FATE_BRENDERPIX-yes)
30 30
 FATE_IMAGE-$(call PARSERDEMDEC, BMP, IMAGE2PIPE, BMP) += fate-bmpparser
31 31
 fate-bmpparser: CMD = framecrc -f image2pipe -i $(TARGET_SAMPLES)/bmp/numbers.bmp -pix_fmt rgb24
32 32
 
33
+define FATE_IMGSUITE_DDS
34
+FATE_DDS += fate-dds-$(1)
35
+fate-dds-$(1): CMD = framecrc -i $(TARGET_SAMPLES)/dds/fate_$(1).dds -sws_flags +accurate_rnd+bitexact -pix_fmt rgba
36
+endef
37
+
38
+DDS_FMT = argb argb-aexp dx10-bc1 dx10-bc1a dx10-bc2 dx10-bc3 dx10-bc4 dx10-bc5 dxt1 dxt1a dxt1-normalmap dxt2 dxt3 dxt4 dxt5 dxt5-aexp dxt5-normalmap dxt5-normalmap-ati dxt5-rbxg dxt5-rgxb dxt5-rxbg dxt5-rxgb dxt5-xgbr dxt5-xgxr dxt5-xrbg dxt5-ycocg dxt5-ycocg-scaled pal pal-ati rgb16 rgb24 rgtc1s rgtc1u rgtc2s rgtc2u rgtc2u-xy uyvy xbgr xrgb y ya ycocg yuyv
39
+$(foreach FMT,$(DDS_FMT),$(eval $(call FATE_IMGSUITE_DDS,$(FMT))))
40
+
41
+FATE_DDS-$(call DEMDEC, IMAGE2, DDS) += $(FATE_DDS)
42
+FATE_IMAGE += $(FATE_DDS-yes)
43
+fate-dds: $(FATE_DDS-yes)
44
+
33 45
 FATE_IMAGE-$(call DEMDEC, IMAGE2, DPX) += fate-dpx
34 46
 fate-dpx: CMD = framecrc -i $(TARGET_SAMPLES)/dpx/lighthouse_rgb48.dpx
35 47
 
36 48
new file mode 100644
... ...
@@ -0,0 +1,2 @@
0
+#tb 0: 1/25
1
+0,          0,          0,        1,    56320, 0xfcaa920b
0 2
new file mode 100644
... ...
@@ -0,0 +1,2 @@
0
+#tb 0: 1/25
1
+0,          0,          0,        1,    16384, 0xfdd37c43
0 2
new file mode 100644
... ...
@@ -0,0 +1,2 @@
0
+#tb 0: 1/25
1
+0,          0,          0,        1,    16384, 0xed2f850f
0 2
new file mode 100644
... ...
@@ -0,0 +1,2 @@
0
+#tb 0: 1/25
1
+0,          0,          0,        1,    16384, 0x473b484b
0 2
new file mode 100644
... ...
@@ -0,0 +1,2 @@
0
+#tb 0: 1/25
1
+0,          0,          0,        1,    16384, 0x2bce3baa
0 2
new file mode 100644
... ...
@@ -0,0 +1,2 @@
0
+#tb 0: 1/25
1
+0,          0,          0,        1,    16384, 0xb91d3c62
0 2
new file mode 100644
... ...
@@ -0,0 +1,2 @@
0
+#tb 0: 1/25
1
+0,          0,          0,        1,    16384, 0xfdfd1751
0 2
new file mode 100644
... ...
@@ -0,0 +1,2 @@
0
+#tb 0: 1/25
1
+0,          0,          0,        1,    16384, 0x79bd207e
0 2
new file mode 100644
... ...
@@ -0,0 +1,2 @@
0
+#tb 0: 1/25
1
+0,          0,          0,        1,    32768, 0xf52adc80
0 2
new file mode 100644
... ...
@@ -0,0 +1,2 @@
0
+#tb 0: 1/25
1
+0,          0,          0,        1,    16384, 0x2b411855
0 2
new file mode 100644
... ...
@@ -0,0 +1,2 @@
0
+#tb 0: 1/25
1
+0,          0,          0,        1,    16384, 0xcabb50ea
0 2
new file mode 100644
... ...
@@ -0,0 +1,2 @@
0
+#tb 0: 1/25
1
+0,          0,          0,        1,    16384, 0x11cebeb0
0 2
new file mode 100644
... ...
@@ -0,0 +1,2 @@
0
+#tb 0: 1/25
1
+0,          0,          0,        1,    16384, 0x729b74ba
0 2
new file mode 100644
... ...
@@ -0,0 +1,2 @@
0
+#tb 0: 1/25
1
+0,          0,          0,        1,    16384, 0x31aaacd6
0 2
new file mode 100644
... ...
@@ -0,0 +1,2 @@
0
+#tb 0: 1/25
1
+0,          0,          0,        1,    16384, 0xfd3166aa
0 2
new file mode 100644
... ...
@@ -0,0 +1,2 @@
0
+#tb 0: 1/25
1
+0,          0,          0,        1,    16384, 0x3c987914
0 2
new file mode 100644
... ...
@@ -0,0 +1,2 @@
0
+#tb 0: 1/25
1
+0,          0,          0,        1,    16384, 0xd29b1ea1
0 2
new file mode 100644
... ...
@@ -0,0 +1,2 @@
0
+#tb 0: 1/25
1
+0,          0,          0,        1,    16384, 0x54cb212f
0 2
new file mode 100644
... ...
@@ -0,0 +1,2 @@
0
+#tb 0: 1/25
1
+0,          0,          0,        1,    16384, 0x37588d12
0 2
new file mode 100644
... ...
@@ -0,0 +1,2 @@
0
+#tb 0: 1/25
1
+0,          0,          0,        1,    16384, 0xfb6b91cf
0 2
new file mode 100644
... ...
@@ -0,0 +1,2 @@
0
+#tb 0: 1/25
1
+0,          0,          0,        1,    16384, 0xc6cb8cbe
0 2
new file mode 100644
... ...
@@ -0,0 +1,2 @@
0
+#tb 0: 1/25
1
+0,          0,          0,        1,    16384, 0xb67d936a
0 2
new file mode 100644
... ...
@@ -0,0 +1,2 @@
0
+#tb 0: 1/25
1
+0,          0,          0,        1,    16384, 0xb0e69293
0 2
new file mode 100644
... ...
@@ -0,0 +1,2 @@
0
+#tb 0: 1/25
1
+0,          0,          0,        1,    16384, 0xa93de1ad
0 2
new file mode 100644
... ...
@@ -0,0 +1,2 @@
0
+#tb 0: 1/25
1
+0,          0,          0,        1,    16384, 0xf20d8b69
0 2
new file mode 100644
... ...
@@ -0,0 +1,2 @@
0
+#tb 0: 1/25
1
+0,          0,          0,        1,    16384, 0x0d0c8d20
0 2
new file mode 100644
... ...
@@ -0,0 +1,2 @@
0
+#tb 0: 1/25
1
+0,          0,          0,        1,    16384, 0x5a089973
0 2
new file mode 100644
... ...
@@ -0,0 +1,2 @@
0
+#tb 0: 1/25
1
+0,          0,          0,        1,    65536, 0xbffee5cd
0 2
new file mode 100644
... ...
@@ -0,0 +1,2 @@
0
+#tb 0: 1/25
1
+0,          0,          0,        1,    16384, 0x23068060
0 2
new file mode 100644
... ...
@@ -0,0 +1,2 @@
0
+#tb 0: 1/25
1
+0,          0,          0,        1,    32768, 0x1ec4fed2
0 2
new file mode 100644
... ...
@@ -0,0 +1,2 @@
0
+#tb 0: 1/25
1
+0,          0,          0,        1,    32768, 0xcf0f7833
0 2
new file mode 100644
... ...
@@ -0,0 +1,2 @@
0
+#tb 0: 1/25
1
+0,          0,          0,        1,    16384, 0xcda652a4
0 2
new file mode 100644
... ...
@@ -0,0 +1,2 @@
0
+#tb 0: 1/25
1
+0,          0,          0,        1,    16384, 0x629a1b44
0 2
new file mode 100644
... ...
@@ -0,0 +1,2 @@
0
+#tb 0: 1/25
1
+0,          0,          0,        1,    16384, 0xa0135ca8
0 2
new file mode 100644
... ...
@@ -0,0 +1,2 @@
0
+#tb 0: 1/25
1
+0,          0,          0,        1,    16384, 0x38cb221a
0 2
new file mode 100644
... ...
@@ -0,0 +1,2 @@
0
+#tb 0: 1/25
1
+0,          0,          0,        1,    16384, 0x79bd207e
0 2
new file mode 100644
... ...
@@ -0,0 +1,2 @@
0
+#tb 0: 1/25
1
+0,          0,          0,        1,    16384, 0xd579a59e
0 2
new file mode 100644
... ...
@@ -0,0 +1,2 @@
0
+#tb 0: 1/25
1
+0,          0,          0,        1,    16384, 0x702f6a28
0 2
new file mode 100644
... ...
@@ -0,0 +1,2 @@
0
+#tb 0: 1/25
1
+0,          0,          0,        1,    16384, 0x702f6a28
0 2
new file mode 100644
... ...
@@ -0,0 +1,2 @@
0
+#tb 0: 1/25
1
+0,          0,          0,        1,    32768, 0xc51add1c
0 2
new file mode 100644
... ...
@@ -0,0 +1,2 @@
0
+#tb 0: 1/25
1
+0,          0,          0,        1,    56320, 0xa614eb1e
0 2
new file mode 100644
... ...
@@ -0,0 +1,2 @@
0
+#tb 0: 1/25
1
+0,          0,          0,        1,    16384, 0x4cb08d0a
0 2
new file mode 100644
... ...
@@ -0,0 +1,2 @@
0
+#tb 0: 1/25
1
+0,          0,          0,        1,    16384, 0xd579a59e