GCC Code Coverage Report
Directory: ../../../ffmpeg/ Exec Total Coverage
File: src/libavcodec/dds.c Lines: 342 436 78.4 %
Date: 2019-11-20 04:07:19 Branches: 173 273 63.4 %

Line Branch Exec Source
1
/*
2
 * DirectDraw Surface image decoder
3
 * Copyright (C) 2015 Vittorio Giovara <vittorio.giovara@gmail.com>
4
 *
5
 * This file is part of FFmpeg.
6
 *
7
 * FFmpeg is free software; you can redistribute it and/or
8
 * modify it under the terms of the GNU Lesser General Public
9
 * License as published by the Free Software Foundation; either
10
 * version 2.1 of the License, or (at your option) any later version.
11
 *
12
 * FFmpeg is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 * Lesser General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Lesser General Public
18
 * License along with FFmpeg; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
 */
21
22
/**
23
 * @file
24
 * DDS decoder
25
 *
26
 * https://msdn.microsoft.com/en-us/library/bb943982%28v=vs.85%29.aspx
27
 */
28
29
#include <stdint.h>
30
31
#include "libavutil/libm.h"
32
#include "libavutil/imgutils.h"
33
34
#include "avcodec.h"
35
#include "bytestream.h"
36
#include "internal.h"
37
#include "texturedsp.h"
38
#include "thread.h"
39
40
#define DDPF_FOURCC    (1 <<  2)
41
#define DDPF_PALETTE   (1 <<  5)
42
#define DDPF_NORMALMAP (1U << 31)
43
44
enum DDSPostProc {
45
    DDS_NONE = 0,
46
    DDS_ALPHA_EXP,
47
    DDS_NORMAL_MAP,
48
    DDS_RAW_YCOCG,
49
    DDS_SWAP_ALPHA,
50
    DDS_SWIZZLE_A2XY,
51
    DDS_SWIZZLE_RBXG,
52
    DDS_SWIZZLE_RGXB,
53
    DDS_SWIZZLE_RXBG,
54
    DDS_SWIZZLE_RXGB,
55
    DDS_SWIZZLE_XGBR,
56
    DDS_SWIZZLE_XRBG,
57
    DDS_SWIZZLE_XGXR,
58
};
59
60
enum DDSDXGIFormat {
61
    DXGI_FORMAT_R16G16B16A16_TYPELESS       =  9,
62
    DXGI_FORMAT_R16G16B16A16_FLOAT          = 10,
63
    DXGI_FORMAT_R16G16B16A16_UNORM          = 11,
64
    DXGI_FORMAT_R16G16B16A16_UINT           = 12,
65
    DXGI_FORMAT_R16G16B16A16_SNORM          = 13,
66
    DXGI_FORMAT_R16G16B16A16_SINT           = 14,
67
68
    DXGI_FORMAT_R8G8B8A8_TYPELESS           = 27,
69
    DXGI_FORMAT_R8G8B8A8_UNORM              = 28,
70
    DXGI_FORMAT_R8G8B8A8_UNORM_SRGB         = 29,
71
    DXGI_FORMAT_R8G8B8A8_UINT               = 30,
72
    DXGI_FORMAT_R8G8B8A8_SNORM              = 31,
73
    DXGI_FORMAT_R8G8B8A8_SINT               = 32,
74
75
    DXGI_FORMAT_BC1_TYPELESS                = 70,
76
    DXGI_FORMAT_BC1_UNORM                   = 71,
77
    DXGI_FORMAT_BC1_UNORM_SRGB              = 72,
78
    DXGI_FORMAT_BC2_TYPELESS                = 73,
79
    DXGI_FORMAT_BC2_UNORM                   = 74,
80
    DXGI_FORMAT_BC2_UNORM_SRGB              = 75,
81
    DXGI_FORMAT_BC3_TYPELESS                = 76,
82
    DXGI_FORMAT_BC3_UNORM                   = 77,
83
    DXGI_FORMAT_BC3_UNORM_SRGB              = 78,
84
    DXGI_FORMAT_BC4_TYPELESS                = 79,
85
    DXGI_FORMAT_BC4_UNORM                   = 80,
86
    DXGI_FORMAT_BC4_SNORM                   = 81,
87
    DXGI_FORMAT_BC5_TYPELESS                = 82,
88
    DXGI_FORMAT_BC5_UNORM                   = 83,
89
    DXGI_FORMAT_BC5_SNORM                   = 84,
90
    DXGI_FORMAT_B5G6R5_UNORM                = 85,
91
    DXGI_FORMAT_B8G8R8A8_UNORM              = 87,
92
    DXGI_FORMAT_B8G8R8X8_UNORM              = 88,
93
    DXGI_FORMAT_B8G8R8A8_TYPELESS           = 90,
94
    DXGI_FORMAT_B8G8R8A8_UNORM_SRGB         = 91,
95
    DXGI_FORMAT_B8G8R8X8_TYPELESS           = 92,
96
    DXGI_FORMAT_B8G8R8X8_UNORM_SRGB         = 93,
97
};
98
99
typedef struct DDSContext {
100
    TextureDSPContext texdsp;
101
    GetByteContext gbc;
102
103
    int compressed;
104
    int paletted;
105
    int bpp;
106
    enum DDSPostProc postproc;
107
108
    const uint8_t *tex_data; // Compressed texture
109
    int tex_ratio;           // Compression ratio
110
    int slice_count;         // Number of slices for threaded operations
111
112
    /* Pointer to the selected compress or decompress function. */
113
    int (*tex_funct)(uint8_t *dst, ptrdiff_t stride, const uint8_t *block);
114
} DDSContext;
115
116
96
static int parse_pixel_format(AVCodecContext *avctx)
117
{
118
96
    DDSContext *ctx = avctx->priv_data;
119
96
    GetByteContext *gbc = &ctx->gbc;
120
    uint32_t flags, fourcc, gimp_tag;
121
    enum DDSDXGIFormat dxgi;
122
    int size, bpp, r, g, b, a;
123
    int alpha_exponent, ycocg_classic, ycocg_scaled, normal_map, array;
124
125
    /* Alternative DDS implementations use reserved1 as custom header. */
126
96
    bytestream2_skip(gbc, 4 * 3);
127
96
    gimp_tag = bytestream2_get_le32(gbc);
128
96
    alpha_exponent = gimp_tag == MKTAG('A', 'E', 'X', 'P');
129
96
    ycocg_classic  = gimp_tag == MKTAG('Y', 'C', 'G', '1');
130
96
    ycocg_scaled   = gimp_tag == MKTAG('Y', 'C', 'G', '2');
131
96
    bytestream2_skip(gbc, 4 * 7);
132
133
    /* Now the real DDPF starts. */
134
96
    size = bytestream2_get_le32(gbc);
135
96
    if (size != 32) {
136
        av_log(avctx, AV_LOG_ERROR, "Invalid pixel format header %d.\n", size);
137
        return AVERROR_INVALIDDATA;
138
    }
139
96
    flags = bytestream2_get_le32(gbc);
140
96
    ctx->compressed = flags & DDPF_FOURCC;
141
96
    ctx->paletted   = flags & DDPF_PALETTE;
142
96
    normal_map      = flags & DDPF_NORMALMAP;
143
96
    fourcc = bytestream2_get_le32(gbc);
144
145

96
    if (ctx->compressed && ctx->paletted) {
146
        av_log(avctx, AV_LOG_WARNING,
147
               "Disabling invalid palette flag for compressed dds.\n");
148
        ctx->paletted = 0;
149
    }
150
151
96
    bpp = ctx->bpp = bytestream2_get_le32(gbc); // rgbbitcount
152
96
    r   = bytestream2_get_le32(gbc); // rbitmask
153
96
    g   = bytestream2_get_le32(gbc); // gbitmask
154
96
    b   = bytestream2_get_le32(gbc); // bbitmask
155
96
    a   = bytestream2_get_le32(gbc); // abitmask
156
157
96
    bytestream2_skip(gbc, 4); // caps
158
96
    bytestream2_skip(gbc, 4); // caps2
159
96
    bytestream2_skip(gbc, 4); // caps3
160
96
    bytestream2_skip(gbc, 4); // caps4
161
96
    bytestream2_skip(gbc, 4); // reserved2
162
163
96
    av_log(avctx, AV_LOG_VERBOSE, "fourcc %s bpp %d "
164
96
           "r 0x%x g 0x%x b 0x%x a 0x%x\n", av_fourcc2str(fourcc), bpp, r, g, b, a);
165
96
    if (gimp_tag)
166
10
        av_log(avctx, AV_LOG_VERBOSE, "and GIMP-DDS tag %s\n", av_fourcc2str(gimp_tag));
167
168
96
    if (ctx->compressed)
169
68
        avctx->pix_fmt = AV_PIX_FMT_RGBA;
170
171
96
    if (ctx->compressed) {
172




68
        switch (fourcc) {
173
6
        case MKTAG('D', 'X', 'T', '1'):
174
6
            ctx->tex_ratio = 8;
175
6
            ctx->tex_funct = ctx->texdsp.dxt1a_block;
176
68
            break;
177
2
        case MKTAG('D', 'X', 'T', '2'):
178
2
            ctx->tex_ratio = 16;
179
2
            ctx->tex_funct = ctx->texdsp.dxt2_block;
180
2
            break;
181
2
        case MKTAG('D', 'X', 'T', '3'):
182
2
            ctx->tex_ratio = 16;
183
2
            ctx->tex_funct = ctx->texdsp.dxt3_block;
184
2
            break;
185
2
        case MKTAG('D', 'X', 'T', '4'):
186
2
            ctx->tex_ratio = 16;
187
2
            ctx->tex_funct = ctx->texdsp.dxt4_block;
188
2
            break;
189
24
        case MKTAG('D', 'X', 'T', '5'):
190
24
            ctx->tex_ratio = 16;
191
24
            if (ycocg_scaled)
192
2
                ctx->tex_funct = ctx->texdsp.dxt5ys_block;
193
22
            else if (ycocg_classic)
194
2
                ctx->tex_funct = ctx->texdsp.dxt5y_block;
195
            else
196
20
                ctx->tex_funct = ctx->texdsp.dxt5_block;
197
24
            break;
198
2
        case MKTAG('R', 'X', 'G', 'B'):
199
2
            ctx->tex_ratio = 16;
200
2
            ctx->tex_funct = ctx->texdsp.dxt5_block;
201
            /* This format may be considered as a normal map,
202
             * but it is handled differently in a separate postproc. */
203
2
            ctx->postproc = DDS_SWIZZLE_RXGB;
204
2
            normal_map = 0;
205
2
            break;
206
2
        case MKTAG('A', 'T', 'I', '1'):
207
        case MKTAG('B', 'C', '4', 'U'):
208
2
            ctx->tex_ratio = 8;
209
2
            ctx->tex_funct = ctx->texdsp.rgtc1u_block;
210
2
            break;
211
2
        case MKTAG('B', 'C', '4', 'S'):
212
2
            ctx->tex_ratio = 8;
213
2
            ctx->tex_funct = ctx->texdsp.rgtc1s_block;
214
2
            break;
215
4
        case MKTAG('A', 'T', 'I', '2'):
216
            /* RGT2 variant with swapped R and G (3Dc)*/
217
4
            ctx->tex_ratio = 16;
218
4
            ctx->tex_funct = ctx->texdsp.dxn3dc_block;
219
4
            break;
220
        case MKTAG('B', 'C', '5', 'U'):
221
            ctx->tex_ratio = 16;
222
            ctx->tex_funct = ctx->texdsp.rgtc2u_block;
223
            break;
224
2
        case MKTAG('B', 'C', '5', 'S'):
225
2
            ctx->tex_ratio = 16;
226
2
            ctx->tex_funct = ctx->texdsp.rgtc2s_block;
227
2
            break;
228
2
        case MKTAG('U', 'Y', 'V', 'Y'):
229
2
            ctx->compressed = 0;
230
2
            avctx->pix_fmt = AV_PIX_FMT_UYVY422;
231
2
            break;
232
2
        case MKTAG('Y', 'U', 'Y', '2'):
233
2
            ctx->compressed = 0;
234
2
            avctx->pix_fmt = AV_PIX_FMT_YUYV422;
235
2
            break;
236
2
        case MKTAG('P', '8', ' ', ' '):
237
            /* ATI Palette8, same as normal palette */
238
2
            ctx->compressed = 0;
239
2
            ctx->paletted   = 1;
240
2
            avctx->pix_fmt  = AV_PIX_FMT_PAL8;
241
2
            break;
242
2
        case MKTAG('G', '1', ' ', ' '):
243
2
            ctx->compressed = 0;
244
2
            avctx->pix_fmt  = AV_PIX_FMT_MONOBLACK;
245
2
            break;
246
12
        case MKTAG('D', 'X', '1', '0'):
247
            /* DirectX 10 extra header */
248
12
            dxgi = bytestream2_get_le32(gbc);
249
12
            bytestream2_skip(gbc, 4); // resourceDimension
250
12
            bytestream2_skip(gbc, 4); // miscFlag
251
12
            array = bytestream2_get_le32(gbc);
252
12
            bytestream2_skip(gbc, 4); // miscFlag2
253
254
12
            if (array != 0)
255
12
                av_log(avctx, AV_LOG_VERBOSE,
256
                       "Found array of size %d (ignored).\n", array);
257
258
            /* Only BC[1-5] are actually compressed. */
259

12
            ctx->compressed = (dxgi >= 70) && (dxgi <= 84);
260
261
12
            av_log(avctx, AV_LOG_VERBOSE, "DXGI format %d.\n", dxgi);
262
            switch (dxgi) {
263
            /* RGB types. */
264
            case DXGI_FORMAT_R16G16B16A16_TYPELESS:
265
            case DXGI_FORMAT_R16G16B16A16_FLOAT:
266
            case DXGI_FORMAT_R16G16B16A16_UNORM:
267
            case DXGI_FORMAT_R16G16B16A16_UINT:
268
            case DXGI_FORMAT_R16G16B16A16_SNORM:
269
            case DXGI_FORMAT_R16G16B16A16_SINT:
270
                avctx->pix_fmt = AV_PIX_FMT_BGRA64;
271
                break;
272
            case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
273
                avctx->colorspace = AVCOL_SPC_RGB;
274
            case DXGI_FORMAT_R8G8B8A8_TYPELESS:
275
            case DXGI_FORMAT_R8G8B8A8_UNORM:
276
            case DXGI_FORMAT_R8G8B8A8_UINT:
277
            case DXGI_FORMAT_R8G8B8A8_SNORM:
278
            case DXGI_FORMAT_R8G8B8A8_SINT:
279
                avctx->pix_fmt = AV_PIX_FMT_BGRA;
280
                break;
281
            case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
282
                avctx->colorspace = AVCOL_SPC_RGB;
283
            case DXGI_FORMAT_B8G8R8A8_TYPELESS:
284
            case DXGI_FORMAT_B8G8R8A8_UNORM:
285
                avctx->pix_fmt = AV_PIX_FMT_RGBA;
286
                break;
287
            case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
288
                avctx->colorspace = AVCOL_SPC_RGB;
289
            case DXGI_FORMAT_B8G8R8X8_TYPELESS:
290
            case DXGI_FORMAT_B8G8R8X8_UNORM:
291
                avctx->pix_fmt = AV_PIX_FMT_RGBA; // opaque
292
                break;
293
            case DXGI_FORMAT_B5G6R5_UNORM:
294
                avctx->pix_fmt = AV_PIX_FMT_RGB565LE;
295
                break;
296
            /* Texture types. */
297
            case DXGI_FORMAT_BC1_UNORM_SRGB:
298
                avctx->colorspace = AVCOL_SPC_RGB;
299
4
            case DXGI_FORMAT_BC1_TYPELESS:
300
            case DXGI_FORMAT_BC1_UNORM:
301
4
                ctx->tex_ratio = 8;
302
4
                ctx->tex_funct = ctx->texdsp.dxt1a_block;
303
4
                break;
304
            case DXGI_FORMAT_BC2_UNORM_SRGB:
305
                avctx->colorspace = AVCOL_SPC_RGB;
306
2
            case DXGI_FORMAT_BC2_TYPELESS:
307
            case DXGI_FORMAT_BC2_UNORM:
308
2
                ctx->tex_ratio = 16;
309
2
                ctx->tex_funct = ctx->texdsp.dxt3_block;
310
2
                break;
311
            case DXGI_FORMAT_BC3_UNORM_SRGB:
312
                avctx->colorspace = AVCOL_SPC_RGB;
313
2
            case DXGI_FORMAT_BC3_TYPELESS:
314
            case DXGI_FORMAT_BC3_UNORM:
315
2
                ctx->tex_ratio = 16;
316
2
                ctx->tex_funct = ctx->texdsp.dxt5_block;
317
2
                break;
318
2
            case DXGI_FORMAT_BC4_TYPELESS:
319
            case DXGI_FORMAT_BC4_UNORM:
320
2
                ctx->tex_ratio = 8;
321
2
                ctx->tex_funct = ctx->texdsp.rgtc1u_block;
322
2
                break;
323
            case DXGI_FORMAT_BC4_SNORM:
324
                ctx->tex_ratio = 8;
325
                ctx->tex_funct = ctx->texdsp.rgtc1s_block;
326
                break;
327
2
            case DXGI_FORMAT_BC5_TYPELESS:
328
            case DXGI_FORMAT_BC5_UNORM:
329
2
                ctx->tex_ratio = 16;
330
2
                ctx->tex_funct = ctx->texdsp.rgtc2u_block;
331
2
                break;
332
            case DXGI_FORMAT_BC5_SNORM:
333
                ctx->tex_ratio = 16;
334
                ctx->tex_funct = ctx->texdsp.rgtc2s_block;
335
                break;
336
            default:
337
                av_log(avctx, AV_LOG_ERROR,
338
                       "Unsupported DXGI format %d.\n", dxgi);
339
                return AVERROR_INVALIDDATA;
340
            }
341
12
            break;
342
        default:
343
            av_log(avctx, AV_LOG_ERROR, "Unsupported %s fourcc.\n", av_fourcc2str(fourcc));
344
            return AVERROR_INVALIDDATA;
345
        }
346
28
    } else if (ctx->paletted) {
347
2
        if (bpp == 8) {
348
2
            avctx->pix_fmt = AV_PIX_FMT_PAL8;
349
        } else {
350
            av_log(avctx, AV_LOG_ERROR, "Unsupported palette bpp %d.\n", bpp);
351
            return AVERROR_INVALIDDATA;
352
        }
353
    } else {
354
        /*  4 bpp */
355


26
        if (bpp == 4 && r == 0 && g == 0 && b == 0 && a == 0)
356
            avctx->pix_fmt = AV_PIX_FMT_PAL8;
357
        /*  8 bpp */
358


26
        else if (bpp == 8 && r == 0xff && g == 0 && b == 0 && a == 0)
359
2
            avctx->pix_fmt = AV_PIX_FMT_GRAY8;
360


24
        else if (bpp == 8 && r == 0 && g == 0 && b == 0 && a == 0xff)
361
2
            avctx->pix_fmt = AV_PIX_FMT_GRAY8;
362
        /* 16 bpp */
363


22
        else if (bpp == 16 && r == 0xff && g == 0 && b == 0 && a == 0xff00)
364
2
            avctx->pix_fmt = AV_PIX_FMT_YA8;
365


20
        else if (bpp == 16 && r == 0xff00 && g == 0 && b == 0 && a == 0xff) {
366
            avctx->pix_fmt = AV_PIX_FMT_YA8;
367
            ctx->postproc = DDS_SWAP_ALPHA;
368
        }
369


20
        else if (bpp == 16 && r == 0xffff && g == 0 && b == 0 && a == 0)
370
            avctx->pix_fmt = AV_PIX_FMT_GRAY16LE;
371


20
        else if (bpp == 16 && r == 0x7c00 && g == 0x3e0 && b == 0x1f && a == 0)
372
2
            avctx->pix_fmt = AV_PIX_FMT_RGB555LE;
373


18
        else if (bpp == 16 && r == 0x7c00 && g == 0x3e0 && b == 0x1f && a == 0x8000)
374
2
            avctx->pix_fmt = AV_PIX_FMT_RGB555LE; // alpha ignored
375


16
        else if (bpp == 16 && r == 0xf800 && g == 0x7e0 && b == 0x1f && a == 0)
376
2
            avctx->pix_fmt = AV_PIX_FMT_RGB565LE;
377
        /* 24 bpp */
378


14
        else if (bpp == 24 && r == 0xff0000 && g == 0xff00 && b == 0xff && a == 0)
379
2
            avctx->pix_fmt = AV_PIX_FMT_BGR24;
380
        /* 32 bpp */
381


12
        else if (bpp == 32 && r == 0xff0000 && g == 0xff00 && b == 0xff && a == 0)
382
2
            avctx->pix_fmt = AV_PIX_FMT_BGR0; // opaque
383


10
        else if (bpp == 32 && r == 0xff && g == 0xff00 && b == 0xff0000 && a == 0)
384
2
            avctx->pix_fmt = AV_PIX_FMT_RGB0; // opaque
385


8
        else if (bpp == 32 && r == 0xff0000 && g == 0xff00 && b == 0xff && a == 0xff000000)
386
8
            avctx->pix_fmt = AV_PIX_FMT_BGRA;
387
        else if (bpp == 32 && r == 0xff && g == 0xff00 && b == 0xff0000 && a == 0xff000000)
388
            avctx->pix_fmt = AV_PIX_FMT_RGBA;
389
        /* give up */
390
        else {
391
            av_log(avctx, AV_LOG_ERROR, "Unknown pixel format "
392
                   "[bpp %d r 0x%x g 0x%x b 0x%x a 0x%x].\n", bpp, r, g, b, a);
393
            return AVERROR_INVALIDDATA;
394
        }
395
    }
396
397
    /* Set any remaining post-proc that should happen before frame is ready. */
398
96
    if (alpha_exponent)
399
4
        ctx->postproc = DDS_ALPHA_EXP;
400
92
    else if (normal_map)
401
4
        ctx->postproc = DDS_NORMAL_MAP;
402

88
    else if (ycocg_classic && !ctx->compressed)
403
2
        ctx->postproc = DDS_RAW_YCOCG;
404
405
    /* ATI/NVidia variants sometimes add swizzling in bpp. */
406


96
    switch (bpp) {
407
2
    case MKTAG('A', '2', 'X', 'Y'):
408
2
        ctx->postproc = DDS_SWIZZLE_A2XY;
409
2
        break;
410
2
    case MKTAG('x', 'G', 'B', 'R'):
411
2
        ctx->postproc = DDS_SWIZZLE_XGBR;
412
2
        break;
413
2
    case MKTAG('x', 'R', 'B', 'G'):
414
2
        ctx->postproc = DDS_SWIZZLE_XRBG;
415
2
        break;
416
2
    case MKTAG('R', 'B', 'x', 'G'):
417
2
        ctx->postproc = DDS_SWIZZLE_RBXG;
418
2
        break;
419
2
    case MKTAG('R', 'G', 'x', 'B'):
420
2
        ctx->postproc = DDS_SWIZZLE_RGXB;
421
2
        break;
422
2
    case MKTAG('R', 'x', 'B', 'G'):
423
2
        ctx->postproc = DDS_SWIZZLE_RXBG;
424
2
        break;
425
2
    case MKTAG('x', 'G', 'x', 'R'):
426
2
        ctx->postproc = DDS_SWIZZLE_XGXR;
427
2
        break;
428
2
    case MKTAG('A', '2', 'D', '5'):
429
2
        ctx->postproc = DDS_NORMAL_MAP;
430
2
        break;
431
    }
432
433
96
    return 0;
434
}
435
436
60
static int decompress_texture_thread(AVCodecContext *avctx, void *arg,
437
                                     int slice, int thread_nb)
438
{
439
60
    DDSContext *ctx = avctx->priv_data;
440
60
    AVFrame *frame = arg;
441
60
    const uint8_t *d = ctx->tex_data;
442
60
    int w_block = avctx->coded_width / TEXTURE_BLOCK_W;
443
60
    int h_block = avctx->coded_height / TEXTURE_BLOCK_H;
444
    int x, y;
445
    int start_slice, end_slice;
446
60
    int base_blocks_per_slice = h_block / ctx->slice_count;
447
60
    int remainder_blocks = h_block % ctx->slice_count;
448
449
    /* When the frame height (in blocks) doesn't divide evenly between the
450
     * number of slices, spread the remaining blocks evenly between the first
451
     * operations */
452
60
    start_slice = slice * base_blocks_per_slice;
453
    /* Add any extra blocks (one per slice) that have been added before this slice */
454
60
    start_slice += FFMIN(slice, remainder_blocks);
455
456
60
    end_slice = start_slice + base_blocks_per_slice;
457
    /* Add an extra block if there are still remainder blocks to be accounted for */
458
60
    if (slice < remainder_blocks)
459
        end_slice++;
460
461
1020
    for (y = start_slice; y < end_slice; y++) {
462
960
        uint8_t *p = frame->data[0] + y * frame->linesize[0] * TEXTURE_BLOCK_H;
463
960
        int off  = y * w_block;
464
16832
        for (x = 0; x < w_block; x++) {
465
15872
            ctx->tex_funct(p + x * 16, frame->linesize[0],
466
15872
                           d + (off + x) * ctx->tex_ratio);
467
        }
468
    }
469
470
60
    return 0;
471
}
472
473
26
static void do_swizzle(AVFrame *frame, int x, int y)
474
{
475
    int i;
476
106522
    for (i = 0; i < frame->linesize[0] * frame->height; i += 4) {
477
106496
        uint8_t *src = frame->data[0] + i;
478
106496
        FFSWAP(uint8_t, src[x], src[y]);
479
    }
480
26
}
481
482
28
static void run_postproc(AVCodecContext *avctx, AVFrame *frame)
483
{
484
28
    DDSContext *ctx = avctx->priv_data;
485
    int i, x_off;
486
487



28
    switch (ctx->postproc) {
488
4
    case DDS_ALPHA_EXP:
489
        /* Alpha-exponential mode divides each channel by the maximum
490
         * R, G or B value, and stores the multiplying factor in the
491
         * alpha channel. */
492
4
        av_log(avctx, AV_LOG_DEBUG, "Post-processing alpha exponent.\n");
493
494
16388
        for (i = 0; i < frame->linesize[0] * frame->height; i += 4) {
495
16384
            uint8_t *src = frame->data[0] + i;
496
16384
            int r = src[0];
497
16384
            int g = src[1];
498
16384
            int b = src[2];
499
16384
            int a = src[3];
500
501
16384
            src[0] = r * a / 255;
502
16384
            src[1] = g * a / 255;
503
16384
            src[2] = b * a / 255;
504
16384
            src[3] = 255;
505
        }
506
4
        break;
507
6
    case DDS_NORMAL_MAP:
508
        /* Normal maps work in the XYZ color space and they encode
509
         * X in R or in A, depending on the texture type, Y in G and
510
         * derive Z with a square root of the distance.
511
         *
512
         * http://www.realtimecollisiondetection.net/blog/?p=28 */
513
6
        av_log(avctx, AV_LOG_DEBUG, "Post-processing normal map.\n");
514
515
6
        x_off = ctx->tex_ratio == 8 ? 0 : 3;
516
24582
        for (i = 0; i < frame->linesize[0] * frame->height; i += 4) {
517
24576
            uint8_t *src = frame->data[0] + i;
518
24576
            int x = src[x_off];
519
24576
            int y = src[1];
520
24576
            int z = 127;
521
522
24576
            int d = (255 * 255 - x * x - y * y) / 2;
523
24576
            if (d > 0)
524
20740
                z = lrint(sqrtf(d));
525
526
24576
            src[0] = x;
527
24576
            src[1] = y;
528
24576
            src[2] = z;
529
24576
            src[3] = 255;
530
        }
531
6
        break;
532
2
    case DDS_RAW_YCOCG:
533
        /* Data is Y-Co-Cg-A and not RGBA, but they are represented
534
         * with the same masks in the DDPF header. */
535
2
        av_log(avctx, AV_LOG_DEBUG, "Post-processing raw YCoCg.\n");
536
537
8194
        for (i = 0; i < frame->linesize[0] * frame->height; i += 4) {
538
8192
            uint8_t *src = frame->data[0] + i;
539
8192
            int a  = src[0];
540
8192
            int cg = src[1] - 128;
541
8192
            int co = src[2] - 128;
542
8192
            int y  = src[3];
543
544
8192
            src[0] = av_clip_uint8(y + co - cg);
545
8192
            src[1] = av_clip_uint8(y + cg);
546
8192
            src[2] = av_clip_uint8(y - co - cg);
547
8192
            src[3] = a;
548
        }
549
2
        break;
550
    case DDS_SWAP_ALPHA:
551
        /* Alpha and Luma are stored swapped. */
552
        av_log(avctx, AV_LOG_DEBUG, "Post-processing swapped Luma/Alpha.\n");
553
554
        for (i = 0; i < frame->linesize[0] * frame->height; i += 2) {
555
            uint8_t *src = frame->data[0] + i;
556
            FFSWAP(uint8_t, src[0], src[1]);
557
        }
558
        break;
559
2
    case DDS_SWIZZLE_A2XY:
560
        /* Swap R and G, often used to restore a standard RGTC2. */
561
2
        av_log(avctx, AV_LOG_DEBUG, "Post-processing A2XY swizzle.\n");
562
2
        do_swizzle(frame, 0, 1);
563
2
        break;
564
2
    case DDS_SWIZZLE_RBXG:
565
        /* Swap G and A, then B and new A (G). */
566
2
        av_log(avctx, AV_LOG_DEBUG, "Post-processing RBXG swizzle.\n");
567
2
        do_swizzle(frame, 1, 3);
568
2
        do_swizzle(frame, 2, 3);
569
2
        break;
570
2
    case DDS_SWIZZLE_RGXB:
571
        /* Swap B and A. */
572
2
        av_log(avctx, AV_LOG_DEBUG, "Post-processing RGXB swizzle.\n");
573
2
        do_swizzle(frame, 2, 3);
574
2
        break;
575
2
    case DDS_SWIZZLE_RXBG:
576
        /* Swap G and A. */
577
2
        av_log(avctx, AV_LOG_DEBUG, "Post-processing RXBG swizzle.\n");
578
2
        do_swizzle(frame, 1, 3);
579
2
        break;
580
2
    case DDS_SWIZZLE_RXGB:
581
        /* Swap R and A (misleading name). */
582
2
        av_log(avctx, AV_LOG_DEBUG, "Post-processing RXGB swizzle.\n");
583
2
        do_swizzle(frame, 0, 3);
584
2
        break;
585
2
    case DDS_SWIZZLE_XGBR:
586
        /* Swap B and A, then R and new A (B). */
587
2
        av_log(avctx, AV_LOG_DEBUG, "Post-processing XGBR swizzle.\n");
588
2
        do_swizzle(frame, 2, 3);
589
2
        do_swizzle(frame, 0, 3);
590
2
        break;
591
2
    case DDS_SWIZZLE_XGXR:
592
        /* Swap G and A, then R and new A (G), then new R (G) and new G (A).
593
         * This variant does not store any B component. */
594
2
        av_log(avctx, AV_LOG_DEBUG, "Post-processing XGXR swizzle.\n");
595
2
        do_swizzle(frame, 1, 3);
596
2
        do_swizzle(frame, 0, 3);
597
2
        do_swizzle(frame, 0, 1);
598
2
        break;
599
2
    case DDS_SWIZZLE_XRBG:
600
        /* Swap G and A, then R and new A (G). */
601
2
        av_log(avctx, AV_LOG_DEBUG, "Post-processing XRBG swizzle.\n");
602
2
        do_swizzle(frame, 1, 3);
603
2
        do_swizzle(frame, 0, 3);
604
2
        break;
605
    }
606
28
}
607
608
96
static int dds_decode(AVCodecContext *avctx, void *data,
609
                      int *got_frame, AVPacket *avpkt)
610
{
611
96
    DDSContext *ctx = avctx->priv_data;
612
96
    GetByteContext *gbc = &ctx->gbc;
613
96
    AVFrame *frame = data;
614
    int mipmap;
615
    int ret;
616
    int width, height;
617
618
96
    ff_texturedsp_init(&ctx->texdsp);
619
96
    bytestream2_init(gbc, avpkt->data, avpkt->size);
620
621
96
    if (bytestream2_get_bytes_left(gbc) < 128) {
622
        av_log(avctx, AV_LOG_ERROR, "Frame is too small (%d).\n",
623
               bytestream2_get_bytes_left(gbc));
624
        return AVERROR_INVALIDDATA;
625
    }
626
627

192
    if (bytestream2_get_le32(gbc) != MKTAG('D', 'D', 'S', ' ') ||
628
96
        bytestream2_get_le32(gbc) != 124) { // header size
629
        av_log(avctx, AV_LOG_ERROR, "Invalid DDS header.\n");
630
        return AVERROR_INVALIDDATA;
631
    }
632
633
96
    bytestream2_skip(gbc, 4); // flags
634
635
96
    height = bytestream2_get_le32(gbc);
636
96
    width  = bytestream2_get_le32(gbc);
637
96
    ret = ff_set_dimensions(avctx, width, height);
638
96
    if (ret < 0) {
639
        av_log(avctx, AV_LOG_ERROR, "Invalid image size %dx%d.\n",
640
               avctx->width, avctx->height);
641
        return ret;
642
    }
643
644
    /* Since codec is based on 4x4 blocks, size is aligned to 4. */
645
96
    avctx->coded_width  = FFALIGN(avctx->width,  TEXTURE_BLOCK_W);
646
96
    avctx->coded_height = FFALIGN(avctx->height, TEXTURE_BLOCK_H);
647
648
96
    bytestream2_skip(gbc, 4); // pitch
649
96
    bytestream2_skip(gbc, 4); // depth
650
96
    mipmap = bytestream2_get_le32(gbc);
651
96
    if (mipmap != 0)
652
56
        av_log(avctx, AV_LOG_VERBOSE, "Found %d mipmaps (ignored).\n", mipmap);
653
654
    /* Extract pixel format information, considering additional elements
655
     * in reserved1 and reserved2. */
656
96
    ret = parse_pixel_format(avctx);
657
96
    if (ret < 0)
658
        return ret;
659
660
96
    ret = ff_get_buffer(avctx, frame, 0);
661
96
    if (ret < 0)
662
        return ret;
663
664
96
    if (ctx->compressed) {
665
60
        int size = (avctx->coded_height / TEXTURE_BLOCK_H) *
666
60
                   (avctx->coded_width / TEXTURE_BLOCK_W) * ctx->tex_ratio;
667
60
        ctx->slice_count = av_clip(avctx->thread_count, 1,
668
60
                                   avctx->coded_height / TEXTURE_BLOCK_H);
669
670
60
        if (bytestream2_get_bytes_left(gbc) < size) {
671
            av_log(avctx, AV_LOG_ERROR,
672
                   "Compressed Buffer is too small (%d < %d).\n",
673
                   bytestream2_get_bytes_left(gbc), size);
674
            return AVERROR_INVALIDDATA;
675
        }
676
677
        /* Use the decompress function on the texture, one block per thread. */
678
60
        ctx->tex_data = gbc->buffer;
679
60
        avctx->execute2(avctx, decompress_texture_thread, frame, NULL, ctx->slice_count);
680

36
    } else if (!ctx->paletted && ctx->bpp == 4 && avctx->pix_fmt == AV_PIX_FMT_PAL8) {
681
        uint8_t *dst = frame->data[0];
682
        int x, y, i;
683
684
        /* Use the first 64 bytes as palette, then copy the rest. */
685
        bytestream2_get_buffer(gbc, frame->data[1], 16 * 4);
686
        for (i = 0; i < 16; i++) {
687
            AV_WN32(frame->data[1] + i*4,
688
                    (frame->data[1][2+i*4]<<0)+
689
                    (frame->data[1][1+i*4]<<8)+
690
                    (frame->data[1][0+i*4]<<16)+
691
                    ((unsigned)frame->data[1][3+i*4]<<24)
692
            );
693
        }
694
        frame->palette_has_changed = 1;
695
696
        if (bytestream2_get_bytes_left(gbc) < frame->height * frame->width / 2) {
697
            av_log(avctx, AV_LOG_ERROR, "Buffer is too small (%d < %d).\n",
698
                   bytestream2_get_bytes_left(gbc), frame->height * frame->width / 2);
699
            return AVERROR_INVALIDDATA;
700
        }
701
702
        for (y = 0; y < frame->height; y++) {
703
            for (x = 0; x < frame->width; x += 2) {
704
                uint8_t val = bytestream2_get_byte(gbc);
705
                dst[x    ] = val & 0xF;
706
                dst[x + 1] = val >> 4;
707
            }
708
            dst += frame->linesize[0];
709
        }
710
    } else {
711
36
        int linesize = av_image_get_linesize(avctx->pix_fmt, frame->width, 0);
712
713
36
        if (ctx->paletted) {
714
            int i;
715
            /* Use the first 1024 bytes as palette, then copy the rest. */
716
4
            bytestream2_get_buffer(gbc, frame->data[1], 256 * 4);
717
1028
            for (i = 0; i < 256; i++)
718
1024
                AV_WN32(frame->data[1] + i*4,
719
                        (frame->data[1][2+i*4]<<0)+
720
                        (frame->data[1][1+i*4]<<8)+
721
                        (frame->data[1][0+i*4]<<16)+
722
                        ((unsigned)frame->data[1][3+i*4]<<24)
723
                );
724
725
4
            frame->palette_has_changed = 1;
726
        }
727
728
36
        if (bytestream2_get_bytes_left(gbc) < frame->height * linesize) {
729
            av_log(avctx, AV_LOG_ERROR, "Buffer is too small (%d < %d).\n",
730
                   bytestream2_get_bytes_left(gbc), frame->height * linesize);
731
            return AVERROR_INVALIDDATA;
732
        }
733
734
36
        av_image_copy_plane(frame->data[0], frame->linesize[0],
735
                            gbc->buffer, linesize,
736
                            linesize, frame->height);
737
    }
738
739
    /* Run any post processing here if needed. */
740
96
    if (ctx->postproc != DDS_NONE)
741
28
        run_postproc(avctx, frame);
742
743
    /* Frame is ready to be output. */
744
96
    frame->pict_type = AV_PICTURE_TYPE_I;
745
96
    frame->key_frame = 1;
746
96
    *got_frame = 1;
747
748
96
    return avpkt->size;
749
}
750
751
AVCodec ff_dds_decoder = {
752
    .name           = "dds",
753
    .long_name      = NULL_IF_CONFIG_SMALL("DirectDraw Surface image decoder"),
754
    .type           = AVMEDIA_TYPE_VIDEO,
755
    .id             = AV_CODEC_ID_DDS,
756
    .decode         = dds_decode,
757
    .priv_data_size = sizeof(DDSContext),
758
    .capabilities   = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SLICE_THREADS,
759
    .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE
760
};