Coverage Report

Created: 2026-09-14 08:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ffmpeg/libavcodec/dds.c
Line
Count
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 <math.h>
30
#include <stdint.h>
31
32
#include "libavutil/attributes.h"
33
#include "libavutil/imgutils.h"
34
35
#include "avcodec.h"
36
#include "bytestream.h"
37
#include "codec_internal.h"
38
#include "decode.h"
39
#include "texturedsp.h"
40
41
68.1k
#define DDPF_FOURCC    (1 <<  2)
42
68.1k
#define DDPF_PALETTE   (1 <<  5)
43
68.1k
#define DDPF_NORMALMAP (1U << 31)
44
45
enum DDSPostProc {
46
    DDS_NONE = 0,
47
    DDS_ALPHA_EXP,
48
    DDS_NORMAL_MAP,
49
    DDS_RAW_YCOCG,
50
    DDS_SWAP_ALPHA,
51
    DDS_SWIZZLE_A2XY,
52
    DDS_SWIZZLE_RBXG,
53
    DDS_SWIZZLE_RGXB,
54
    DDS_SWIZZLE_RXBG,
55
    DDS_SWIZZLE_RXGB,
56
    DDS_SWIZZLE_XGBR,
57
    DDS_SWIZZLE_XRBG,
58
    DDS_SWIZZLE_XGXR,
59
};
60
61
enum DDSDXGIFormat {
62
    DXGI_FORMAT_R16G16B16A16_TYPELESS       =  9,
63
    DXGI_FORMAT_R16G16B16A16_FLOAT          = 10,
64
    DXGI_FORMAT_R16G16B16A16_UNORM          = 11,
65
    DXGI_FORMAT_R16G16B16A16_UINT           = 12,
66
    DXGI_FORMAT_R16G16B16A16_SNORM          = 13,
67
    DXGI_FORMAT_R16G16B16A16_SINT           = 14,
68
69
    DXGI_FORMAT_R8G8B8A8_TYPELESS           = 27,
70
    DXGI_FORMAT_R8G8B8A8_UNORM              = 28,
71
    DXGI_FORMAT_R8G8B8A8_UNORM_SRGB         = 29,
72
    DXGI_FORMAT_R8G8B8A8_UINT               = 30,
73
    DXGI_FORMAT_R8G8B8A8_SNORM              = 31,
74
    DXGI_FORMAT_R8G8B8A8_SINT               = 32,
75
76
    DXGI_FORMAT_BC1_TYPELESS                = 70,
77
    DXGI_FORMAT_BC1_UNORM                   = 71,
78
    DXGI_FORMAT_BC1_UNORM_SRGB              = 72,
79
    DXGI_FORMAT_BC2_TYPELESS                = 73,
80
    DXGI_FORMAT_BC2_UNORM                   = 74,
81
    DXGI_FORMAT_BC2_UNORM_SRGB              = 75,
82
    DXGI_FORMAT_BC3_TYPELESS                = 76,
83
    DXGI_FORMAT_BC3_UNORM                   = 77,
84
    DXGI_FORMAT_BC3_UNORM_SRGB              = 78,
85
    DXGI_FORMAT_BC4_TYPELESS                = 79,
86
    DXGI_FORMAT_BC4_UNORM                   = 80,
87
    DXGI_FORMAT_BC4_SNORM                   = 81,
88
    DXGI_FORMAT_BC5_TYPELESS                = 82,
89
    DXGI_FORMAT_BC5_UNORM                   = 83,
90
    DXGI_FORMAT_BC5_SNORM                   = 84,
91
    DXGI_FORMAT_B5G6R5_UNORM                = 85,
92
    DXGI_FORMAT_B8G8R8A8_UNORM              = 87,
93
    DXGI_FORMAT_B8G8R8X8_UNORM              = 88,
94
    DXGI_FORMAT_B8G8R8A8_TYPELESS           = 90,
95
    DXGI_FORMAT_B8G8R8A8_UNORM_SRGB         = 91,
96
    DXGI_FORMAT_B8G8R8X8_TYPELESS           = 92,
97
    DXGI_FORMAT_B8G8R8X8_UNORM_SRGB         = 93,
98
};
99
100
typedef struct DDSContext {
101
    TextureDSPContext texdsp;
102
    GetByteContext gbc;
103
104
    int compressed;
105
    int paletted;
106
    int bpp;
107
    enum DDSPostProc postproc;
108
109
    TextureDSPThreadContext dec;
110
} DDSContext;
111
112
static int parse_pixel_format(AVCodecContext *avctx)
113
69.4k
{
114
69.4k
    DDSContext *ctx = avctx->priv_data;
115
69.4k
    GetByteContext *gbc = &ctx->gbc;
116
69.4k
    uint32_t flags, fourcc, gimp_tag;
117
69.4k
    enum DDSDXGIFormat dxgi;
118
69.4k
    int size, bpp, r, g, b, a;
119
69.4k
    int alpha_exponent, ycocg_classic, ycocg_scaled, normal_map, array;
120
121
    /* Alternative DDS implementations use reserved1 as custom header. */
122
69.4k
    bytestream2_skip(gbc, 4 * 3);
123
69.4k
    gimp_tag = bytestream2_get_le32(gbc);
124
69.4k
    alpha_exponent = gimp_tag == MKTAG('A', 'E', 'X', 'P');
125
69.4k
    ycocg_classic  = gimp_tag == MKTAG('Y', 'C', 'G', '1');
126
69.4k
    ycocg_scaled   = gimp_tag == MKTAG('Y', 'C', 'G', '2');
127
69.4k
    bytestream2_skip(gbc, 4 * 7);
128
129
    /* Now the real DDPF starts. */
130
69.4k
    size = bytestream2_get_le32(gbc);
131
69.4k
    if (size != 32) {
132
1.33k
        av_log(avctx, AV_LOG_ERROR, "Invalid pixel format header %d.\n", size);
133
1.33k
        return AVERROR_INVALIDDATA;
134
1.33k
    }
135
68.1k
    flags = bytestream2_get_le32(gbc);
136
68.1k
    ctx->compressed = flags & DDPF_FOURCC;
137
68.1k
    ctx->paletted   = flags & DDPF_PALETTE;
138
68.1k
    normal_map      = flags & DDPF_NORMALMAP;
139
68.1k
    fourcc = bytestream2_get_le32(gbc);
140
141
68.1k
    if (ctx->compressed && ctx->paletted) {
142
1.46k
        av_log(avctx, AV_LOG_WARNING,
143
1.46k
               "Disabling invalid palette flag for compressed dds.\n");
144
1.46k
        ctx->paletted = 0;
145
1.46k
    }
146
147
68.1k
    bpp = ctx->bpp = bytestream2_get_le32(gbc); // rgbbitcount
148
68.1k
    r   = bytestream2_get_le32(gbc); // rbitmask
149
68.1k
    g   = bytestream2_get_le32(gbc); // gbitmask
150
68.1k
    b   = bytestream2_get_le32(gbc); // bbitmask
151
68.1k
    a   = bytestream2_get_le32(gbc); // abitmask
152
153
68.1k
    bytestream2_skip(gbc, 4); // caps
154
68.1k
    bytestream2_skip(gbc, 4); // caps2
155
68.1k
    bytestream2_skip(gbc, 4); // caps3
156
68.1k
    bytestream2_skip(gbc, 4); // caps4
157
68.1k
    bytestream2_skip(gbc, 4); // reserved2
158
159
68.1k
    av_log(avctx, AV_LOG_VERBOSE, "fourcc %s bpp %d "
160
68.1k
           "r 0x%x g 0x%x b 0x%x a 0x%x\n", av_fourcc2str(fourcc), bpp, r, g, b, a);
161
68.1k
    if (gimp_tag)
162
28.0k
        av_log(avctx, AV_LOG_VERBOSE, "and GIMP-DDS tag %s\n", av_fourcc2str(gimp_tag));
163
164
68.1k
    if (ctx->compressed)
165
26.8k
        avctx->pix_fmt = AV_PIX_FMT_RGBA;
166
167
68.1k
    if (ctx->compressed) {
168
26.8k
        ctx->dec.raw_ratio = 16;
169
26.8k
        switch (fourcc) {
170
9.09k
        case MKTAG('D', 'X', 'T', '1'):
171
9.09k
            ctx->dec.tex_ratio = 8;
172
9.09k
            ctx->dec.tex_funct = ctx->texdsp.dxt1a_block;
173
9.09k
            break;
174
447
        case MKTAG('D', 'X', 'T', '2'):
175
447
            ctx->dec.tex_ratio = 16;
176
447
            ctx->dec.tex_funct = ctx->texdsp.dxt2_block;
177
447
            break;
178
433
        case MKTAG('D', 'X', 'T', '3'):
179
433
            ctx->dec.tex_ratio = 16;
180
433
            ctx->dec.tex_funct = ctx->texdsp.dxt3_block;
181
433
            break;
182
371
        case MKTAG('D', 'X', 'T', '4'):
183
371
            ctx->dec.tex_ratio = 16;
184
371
            ctx->dec.tex_funct = ctx->texdsp.dxt4_block;
185
371
            break;
186
1.57k
        case MKTAG('D', 'X', 'T', '5'):
187
1.57k
            ctx->dec.tex_ratio = 16;
188
1.57k
            if (ycocg_scaled)
189
469
                ctx->dec.tex_funct = ctx->texdsp.dxt5ys_block;
190
1.10k
            else if (ycocg_classic)
191
292
                ctx->dec.tex_funct = ctx->texdsp.dxt5y_block;
192
809
            else
193
809
                ctx->dec.tex_funct = ctx->texdsp.dxt5_block;
194
1.57k
            break;
195
899
        case MKTAG('R', 'X', 'G', 'B'):
196
899
            ctx->dec.tex_ratio = 16;
197
899
            ctx->dec.tex_funct = ctx->texdsp.dxt5_block;
198
            /* This format may be considered as a normal map,
199
             * but it is handled differently in a separate postproc. */
200
899
            ctx->postproc = DDS_SWIZZLE_RXGB;
201
899
            normal_map = 0;
202
899
            break;
203
425
        case MKTAG('A', 'T', 'I', '1'):
204
647
        case MKTAG('B', 'C', '4', 'U'):
205
647
            ctx->dec.tex_ratio = 8;
206
647
            ctx->dec.tex_funct = ctx->texdsp.rgtc1u_block;
207
647
            break;
208
216
        case MKTAG('B', 'C', '4', 'S'):
209
216
            ctx->dec.tex_ratio = 8;
210
216
            ctx->dec.tex_funct = ctx->texdsp.rgtc1s_block;
211
216
            break;
212
297
        case MKTAG('A', 'T', 'I', '2'):
213
            /* RGT2 variant with swapped R and G (3Dc)*/
214
297
            ctx->dec.tex_ratio = 16;
215
297
            ctx->dec.tex_funct = ctx->texdsp.dxn3dc_block;
216
297
            break;
217
230
        case MKTAG('B', 'C', '5', 'U'):
218
230
            ctx->dec.tex_ratio = 16;
219
230
            ctx->dec.tex_funct = ctx->texdsp.rgtc2u_block;
220
230
            break;
221
224
        case MKTAG('B', 'C', '5', 'S'):
222
224
            ctx->dec.tex_ratio = 16;
223
224
            ctx->dec.tex_funct = ctx->texdsp.rgtc2s_block;
224
224
            break;
225
220
        case MKTAG('U', 'Y', 'V', 'Y'):
226
220
            ctx->compressed = 0;
227
220
            avctx->pix_fmt = AV_PIX_FMT_UYVY422;
228
220
            break;
229
473
        case MKTAG('Y', 'U', 'Y', '2'):
230
473
            ctx->compressed = 0;
231
473
            avctx->pix_fmt = AV_PIX_FMT_YUYV422;
232
473
            break;
233
213
        case MKTAG('P', '8', ' ', ' '):
234
            /* ATI Palette8, same as normal palette */
235
213
            ctx->compressed = 0;
236
213
            ctx->paletted   = 1;
237
213
            avctx->pix_fmt  = AV_PIX_FMT_PAL8;
238
213
            break;
239
1.97k
        case MKTAG('G', '1', ' ', ' '):
240
1.97k
            ctx->compressed = 0;
241
1.97k
            avctx->pix_fmt  = AV_PIX_FMT_MONOBLACK;
242
1.97k
            break;
243
8.34k
        case MKTAG('D', 'X', '1', '0'):
244
            /* DirectX 10 extra header */
245
8.34k
            dxgi = bytestream2_get_le32(gbc);
246
8.34k
            bytestream2_skip(gbc, 4); // resourceDimension
247
8.34k
            bytestream2_skip(gbc, 4); // miscFlag
248
8.34k
            array = bytestream2_get_le32(gbc);
249
8.34k
            bytestream2_skip(gbc, 4); // miscFlag2
250
251
8.34k
            if (array != 0)
252
1.97k
                av_log(avctx, AV_LOG_VERBOSE,
253
1.97k
                       "Found array of size %d (ignored).\n", array);
254
255
            /* Only BC[1-5] are actually compressed. */
256
8.34k
            ctx->compressed = (dxgi >= 70) && (dxgi <= 84);
257
258
8.34k
            av_log(avctx, AV_LOG_VERBOSE, "DXGI format %d.\n", dxgi);
259
8.34k
            switch (dxgi) {
260
            /* RGB types. */
261
200
            case DXGI_FORMAT_R16G16B16A16_TYPELESS:
262
407
            case DXGI_FORMAT_R16G16B16A16_FLOAT:
263
602
            case DXGI_FORMAT_R16G16B16A16_UNORM:
264
797
            case DXGI_FORMAT_R16G16B16A16_UINT:
265
1.00k
            case DXGI_FORMAT_R16G16B16A16_SNORM:
266
1.36k
            case DXGI_FORMAT_R16G16B16A16_SINT:
267
1.36k
                avctx->pix_fmt = AV_PIX_FMT_BGRA64;
268
1.36k
                break;
269
399
            case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
270
399
                avctx->colorspace = AVCOL_SPC_RGB;
271
399
                av_fallthrough;
272
595
            case DXGI_FORMAT_R8G8B8A8_TYPELESS:
273
789
            case DXGI_FORMAT_R8G8B8A8_UNORM:
274
1.03k
            case DXGI_FORMAT_R8G8B8A8_UINT:
275
1.23k
            case DXGI_FORMAT_R8G8B8A8_SNORM:
276
1.45k
            case DXGI_FORMAT_R8G8B8A8_SINT:
277
1.45k
                avctx->pix_fmt = AV_PIX_FMT_BGRA;
278
1.45k
                break;
279
198
            case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
280
198
                avctx->colorspace = AVCOL_SPC_RGB;
281
198
                av_fallthrough;
282
421
            case DXGI_FORMAT_B8G8R8A8_TYPELESS:
283
674
            case DXGI_FORMAT_B8G8R8A8_UNORM:
284
674
                avctx->pix_fmt = AV_PIX_FMT_RGBA;
285
674
                break;
286
194
            case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
287
194
                avctx->colorspace = AVCOL_SPC_RGB;
288
194
                av_fallthrough;
289
389
            case DXGI_FORMAT_B8G8R8X8_TYPELESS:
290
586
            case DXGI_FORMAT_B8G8R8X8_UNORM:
291
586
                avctx->pix_fmt = AV_PIX_FMT_RGBA; // opaque
292
586
                break;
293
196
            case DXGI_FORMAT_B5G6R5_UNORM:
294
196
                avctx->pix_fmt = AV_PIX_FMT_RGB565LE;
295
196
                break;
296
            /* Texture types. */
297
318
            case DXGI_FORMAT_BC1_UNORM_SRGB:
298
318
                avctx->colorspace = AVCOL_SPC_RGB;
299
318
                av_fallthrough;
300
565
            case DXGI_FORMAT_BC1_TYPELESS:
301
759
            case DXGI_FORMAT_BC1_UNORM:
302
759
                ctx->dec.tex_ratio = 8;
303
759
                ctx->dec.tex_funct = ctx->texdsp.dxt1a_block;
304
759
                break;
305
231
            case DXGI_FORMAT_BC2_UNORM_SRGB:
306
231
                avctx->colorspace = AVCOL_SPC_RGB;
307
231
                av_fallthrough;
308
427
            case DXGI_FORMAT_BC2_TYPELESS:
309
621
            case DXGI_FORMAT_BC2_UNORM:
310
621
                ctx->dec.tex_ratio = 16;
311
621
                ctx->dec.tex_funct = ctx->texdsp.dxt3_block;
312
621
                break;
313
198
            case DXGI_FORMAT_BC3_UNORM_SRGB:
314
198
                avctx->colorspace = AVCOL_SPC_RGB;
315
198
                av_fallthrough;
316
477
            case DXGI_FORMAT_BC3_TYPELESS:
317
756
            case DXGI_FORMAT_BC3_UNORM:
318
756
                ctx->dec.tex_ratio = 16;
319
756
                ctx->dec.tex_funct = ctx->texdsp.dxt5_block;
320
756
                break;
321
195
            case DXGI_FORMAT_BC4_TYPELESS:
322
392
            case DXGI_FORMAT_BC4_UNORM:
323
392
                ctx->dec.tex_ratio = 8;
324
392
                ctx->dec.tex_funct = ctx->texdsp.rgtc1u_block;
325
392
                break;
326
195
            case DXGI_FORMAT_BC4_SNORM:
327
195
                ctx->dec.tex_ratio = 8;
328
195
                ctx->dec.tex_funct = ctx->texdsp.rgtc1s_block;
329
195
                break;
330
195
            case DXGI_FORMAT_BC5_TYPELESS:
331
404
            case DXGI_FORMAT_BC5_UNORM:
332
404
                ctx->dec.tex_ratio = 16;
333
404
                ctx->dec.tex_funct = ctx->texdsp.rgtc2u_block;
334
404
                break;
335
216
            case DXGI_FORMAT_BC5_SNORM:
336
216
                ctx->dec.tex_ratio = 16;
337
216
                ctx->dec.tex_funct = ctx->texdsp.rgtc2s_block;
338
216
                break;
339
732
            default:
340
732
                av_log(avctx, AV_LOG_ERROR,
341
732
                       "Unsupported DXGI format %d.\n", dxgi);
342
732
                return AVERROR_INVALIDDATA;
343
8.34k
            }
344
7.61k
            break;
345
7.61k
        default:
346
1.20k
            av_log(avctx, AV_LOG_ERROR, "Unsupported %s fourcc.\n", av_fourcc2str(fourcc));
347
1.20k
            return AVERROR_INVALIDDATA;
348
26.8k
        }
349
41.2k
    } else if (ctx->paletted) {
350
2.63k
        if (bpp == 8) {
351
2.35k
            avctx->pix_fmt = AV_PIX_FMT_PAL8;
352
2.35k
        } else {
353
277
            av_log(avctx, AV_LOG_ERROR, "Unsupported palette bpp %d.\n", bpp);
354
277
            return AVERROR_INVALIDDATA;
355
277
        }
356
38.6k
    } else {
357
        /*  4 bpp */
358
38.6k
        if (bpp == 4 && r == 0 && g == 0 && b == 0 && a == 0)
359
25.5k
            avctx->pix_fmt = AV_PIX_FMT_PAL8;
360
        /*  8 bpp */
361
13.1k
        else if (bpp == 8 && r == 0xff && g == 0 && b == 0 && a == 0)
362
495
            avctx->pix_fmt = AV_PIX_FMT_GRAY8;
363
12.6k
        else if (bpp == 8 && r == 0 && g == 0 && b == 0 && a == 0xff)
364
220
            avctx->pix_fmt = AV_PIX_FMT_GRAY8;
365
        /* 16 bpp */
366
12.3k
        else if (bpp == 16 && r == 0xff && g == 0 && b == 0 && a == 0xff00)
367
196
            avctx->pix_fmt = AV_PIX_FMT_YA8;
368
12.1k
        else if (bpp == 16 && r == 0xff00 && g == 0 && b == 0 && a == 0xff) {
369
252
            avctx->pix_fmt = AV_PIX_FMT_YA8;
370
252
            ctx->postproc = DDS_SWAP_ALPHA;
371
252
        }
372
11.9k
        else if (bpp == 16 && r == 0xffff && g == 0 && b == 0 && a == 0)
373
198
            avctx->pix_fmt = AV_PIX_FMT_GRAY16LE;
374
11.7k
        else if (bpp == 16 && r == 0x7c00 && g == 0x3e0 && b == 0x1f && a == 0)
375
226
            avctx->pix_fmt = AV_PIX_FMT_RGB555LE;
376
11.5k
        else if (bpp == 16 && r == 0x7c00 && g == 0x3e0 && b == 0x1f && a == 0x8000)
377
230
            avctx->pix_fmt = AV_PIX_FMT_RGB555LE; // alpha ignored
378
11.2k
        else if (bpp == 16 && r == 0xf800 && g == 0x7e0 && b == 0x1f && a == 0)
379
203
            avctx->pix_fmt = AV_PIX_FMT_RGB565LE;
380
        /* 24 bpp */
381
11.0k
        else if (bpp == 24 && r == 0xff0000 && g == 0xff00 && b == 0xff && a == 0)
382
212
            avctx->pix_fmt = AV_PIX_FMT_BGR24;
383
        /* 32 bpp */
384
10.8k
        else if (bpp == 32 && r == 0xff0000 && g == 0xff00 && b == 0xff && a == 0)
385
319
            avctx->pix_fmt = AV_PIX_FMT_BGR0; // opaque
386
10.5k
        else if (bpp == 32 && r == 0xff && g == 0xff00 && b == 0xff0000 && a == 0)
387
195
            avctx->pix_fmt = AV_PIX_FMT_RGB0; // opaque
388
10.3k
        else if (bpp == 32 && r == 0xff0000 && g == 0xff00 && b == 0xff && a == 0xff000000)
389
203
            avctx->pix_fmt = AV_PIX_FMT_BGRA;
390
10.1k
        else if (bpp == 32 && r == 0xff && g == 0xff00 && b == 0xff0000 && a == 0xff000000)
391
241
            avctx->pix_fmt = AV_PIX_FMT_RGBA;
392
        /* give up */
393
9.91k
        else {
394
9.91k
            av_log(avctx, AV_LOG_ERROR, "Unknown pixel format "
395
9.91k
                   "[bpp %d r 0x%x g 0x%x b 0x%x a 0x%x].\n", bpp, r, g, b, a);
396
9.91k
            return AVERROR_INVALIDDATA;
397
9.91k
        }
398
38.6k
    }
399
400
    /* Set any remaining post-proc that should happen before frame is ready. */
401
56.0k
    if (alpha_exponent)
402
449
        ctx->postproc = DDS_ALPHA_EXP;
403
55.5k
    else if (normal_map)
404
2.93k
        ctx->postproc = DDS_NORMAL_MAP;
405
52.6k
    else if (ycocg_classic && !ctx->compressed)
406
678
        ctx->postproc = DDS_RAW_YCOCG;
407
408
    /* ATI/NVidia variants sometimes add swizzling in bpp. */
409
56.0k
    switch (bpp) {
410
389
    case MKTAG('A', '2', 'X', 'Y'):
411
389
        ctx->postproc = DDS_SWIZZLE_A2XY;
412
389
        break;
413
266
    case MKTAG('x', 'G', 'B', 'R'):
414
266
        ctx->postproc = DDS_SWIZZLE_XGBR;
415
266
        break;
416
238
    case MKTAG('x', 'R', 'B', 'G'):
417
238
        ctx->postproc = DDS_SWIZZLE_XRBG;
418
238
        break;
419
7.43k
    case MKTAG('R', 'B', 'x', 'G'):
420
7.43k
        ctx->postproc = DDS_SWIZZLE_RBXG;
421
7.43k
        break;
422
437
    case MKTAG('R', 'G', 'x', 'B'):
423
437
        ctx->postproc = DDS_SWIZZLE_RGXB;
424
437
        break;
425
347
    case MKTAG('R', 'x', 'B', 'G'):
426
347
        ctx->postproc = DDS_SWIZZLE_RXBG;
427
347
        break;
428
298
    case MKTAG('x', 'G', 'x', 'R'):
429
298
        ctx->postproc = DDS_SWIZZLE_XGXR;
430
298
        break;
431
342
    case MKTAG('A', '2', 'D', '5'):
432
342
        ctx->postproc = DDS_NORMAL_MAP;
433
342
        break;
434
56.0k
    }
435
436
56.0k
    return 0;
437
56.0k
}
438
439
static void do_swizzle(AVFrame *frame, int x, int y)
440
48.2k
{
441
48.2k
    int i;
442
10.0M
    for (i = 0; i < frame->linesize[0] * frame->height; i += 4) {
443
9.96M
        uint8_t *src = frame->data[0] + i;
444
9.96M
        FFSWAP(uint8_t, src[x], src[y]);
445
9.96M
    }
446
48.2k
}
447
448
static void run_postproc(AVCodecContext *avctx, AVFrame *frame)
449
32.3k
{
450
32.3k
    DDSContext *ctx = avctx->priv_data;
451
32.3k
    int i, x_off;
452
453
32.3k
    switch (ctx->postproc) {
454
559
    case DDS_ALPHA_EXP:
455
        /* Alpha-exponential mode divides each channel by the maximum
456
         * R, G or B value, and stores the multiplying factor in the
457
         * alpha channel. */
458
559
        av_log(avctx, AV_LOG_DEBUG, "Post-processing alpha exponent.\n");
459
460
934k
        for (i = 0; i < frame->linesize[0] * frame->height; i += 4) {
461
933k
            uint8_t *src = frame->data[0] + i;
462
933k
            int r = src[0];
463
933k
            int g = src[1];
464
933k
            int b = src[2];
465
933k
            int a = src[3];
466
467
933k
            src[0] = r * a / 255;
468
933k
            src[1] = g * a / 255;
469
933k
            src[2] = b * a / 255;
470
933k
            src[3] = 255;
471
933k
        }
472
559
        break;
473
3.98k
    case DDS_NORMAL_MAP:
474
        /* Normal maps work in the XYZ color space and they encode
475
         * X in R or in A, depending on the texture type, Y in G and
476
         * derive Z with a square root of the distance.
477
         *
478
         * http://www.realtimecollisiondetection.net/blog/?p=28 */
479
3.98k
        av_log(avctx, AV_LOG_DEBUG, "Post-processing normal map.\n");
480
481
3.98k
        x_off = ctx->dec.tex_ratio == 8 ? 0 : 3;
482
12.3M
        for (i = 0; i < frame->linesize[0] * frame->height; i += 4) {
483
12.3M
            uint8_t *src = frame->data[0] + i;
484
12.3M
            int x = src[x_off];
485
12.3M
            int y = src[1];
486
12.3M
            int z = 127;
487
488
12.3M
            int d = (255 * 255 - x * x - y * y) / 2;
489
12.3M
            if (d > 0)
490
10.1M
                z = lrint(sqrtf(d));
491
492
12.3M
            src[0] = x;
493
12.3M
            src[1] = y;
494
12.3M
            src[2] = z;
495
12.3M
            src[3] = 255;
496
12.3M
        }
497
3.98k
        break;
498
2.68k
    case DDS_RAW_YCOCG:
499
        /* Data is Y-Co-Cg-A and not RGBA, but they are represented
500
         * with the same masks in the DDPF header. */
501
2.68k
        av_log(avctx, AV_LOG_DEBUG, "Post-processing raw YCoCg.\n");
502
503
472k
        for (i = 0; i < frame->linesize[0] * frame->height; i += 4) {
504
469k
            uint8_t *src = frame->data[0] + i;
505
469k
            int a  = src[0];
506
469k
            int cg = src[1] - 128;
507
469k
            int co = src[2] - 128;
508
469k
            int y  = src[3];
509
510
469k
            src[0] = av_clip_uint8(y + co - cg);
511
469k
            src[1] = av_clip_uint8(y + cg);
512
469k
            src[2] = av_clip_uint8(y - co - cg);
513
469k
            src[3] = a;
514
469k
        }
515
2.68k
        break;
516
556
    case DDS_SWAP_ALPHA:
517
        /* Alpha and Luma are stored swapped. */
518
556
        av_log(avctx, AV_LOG_DEBUG, "Post-processing swapped Luma/Alpha.\n");
519
520
354k
        for (i = 0; i < frame->linesize[0] * frame->height; i += 2) {
521
354k
            uint8_t *src = frame->data[0] + i;
522
354k
            FFSWAP(uint8_t, src[0], src[1]);
523
354k
        }
524
556
        break;
525
402
    case DDS_SWIZZLE_A2XY:
526
        /* Swap R and G, often used to restore a standard RGTC2. */
527
402
        av_log(avctx, AV_LOG_DEBUG, "Post-processing A2XY swizzle.\n");
528
402
        do_swizzle(frame, 0, 1);
529
402
        break;
530
22.6k
    case DDS_SWIZZLE_RBXG:
531
        /* Swap G and A, then B and new A (G). */
532
22.6k
        av_log(avctx, AV_LOG_DEBUG, "Post-processing RBXG swizzle.\n");
533
22.6k
        do_swizzle(frame, 1, 3);
534
22.6k
        do_swizzle(frame, 2, 3);
535
22.6k
        break;
536
295
    case DDS_SWIZZLE_RGXB:
537
        /* Swap B and A. */
538
295
        av_log(avctx, AV_LOG_DEBUG, "Post-processing RGXB swizzle.\n");
539
295
        do_swizzle(frame, 2, 3);
540
295
        break;
541
208
    case DDS_SWIZZLE_RXBG:
542
        /* Swap G and A. */
543
208
        av_log(avctx, AV_LOG_DEBUG, "Post-processing RXBG swizzle.\n");
544
208
        do_swizzle(frame, 1, 3);
545
208
        break;
546
263
    case DDS_SWIZZLE_RXGB:
547
        /* Swap R and A (misleading name). */
548
263
        av_log(avctx, AV_LOG_DEBUG, "Post-processing RXGB swizzle.\n");
549
263
        do_swizzle(frame, 0, 3);
550
263
        break;
551
266
    case DDS_SWIZZLE_XGBR:
552
        /* Swap B and A, then R and new A (B). */
553
266
        av_log(avctx, AV_LOG_DEBUG, "Post-processing XGBR swizzle.\n");
554
266
        do_swizzle(frame, 2, 3);
555
266
        do_swizzle(frame, 0, 3);
556
266
        break;
557
283
    case DDS_SWIZZLE_XGXR:
558
        /* Swap G and A, then R and new A (G), then new R (G) and new G (A).
559
         * This variant does not store any B component. */
560
283
        av_log(avctx, AV_LOG_DEBUG, "Post-processing XGXR swizzle.\n");
561
283
        do_swizzle(frame, 1, 3);
562
283
        do_swizzle(frame, 0, 3);
563
283
        do_swizzle(frame, 0, 1);
564
283
        break;
565
263
    case DDS_SWIZZLE_XRBG:
566
        /* Swap G and A, then R and new A (G). */
567
263
        av_log(avctx, AV_LOG_DEBUG, "Post-processing XRBG swizzle.\n");
568
263
        do_swizzle(frame, 1, 3);
569
263
        do_swizzle(frame, 0, 3);
570
263
        break;
571
32.3k
    }
572
32.3k
}
573
574
static int dds_decode(AVCodecContext *avctx, AVFrame *frame,
575
                      int *got_frame, AVPacket *avpkt)
576
137k
{
577
137k
    DDSContext *ctx = avctx->priv_data;
578
137k
    GetByteContext *gbc = &ctx->gbc;
579
137k
    int mipmap;
580
137k
    int ret;
581
137k
    int width, height;
582
583
137k
    ff_texturedsp_init(&ctx->texdsp);
584
137k
    bytestream2_init(gbc, avpkt->data, avpkt->size);
585
586
137k
    if (bytestream2_get_bytes_left(gbc) < 128) {
587
65.1k
        av_log(avctx, AV_LOG_ERROR, "Frame is too small (%d).\n",
588
65.1k
               bytestream2_get_bytes_left(gbc));
589
65.1k
        return AVERROR_INVALIDDATA;
590
65.1k
    }
591
592
72.1k
    if (bytestream2_get_le32(gbc) != MKTAG('D', 'D', 'S', ' ') ||
593
71.5k
        bytestream2_get_le32(gbc) != 124) { // header size
594
943
        av_log(avctx, AV_LOG_ERROR, "Invalid DDS header.\n");
595
943
        return AVERROR_INVALIDDATA;
596
943
    }
597
598
71.2k
    bytestream2_skip(gbc, 4); // flags
599
600
71.2k
    height = bytestream2_get_le32(gbc);
601
71.2k
    width  = bytestream2_get_le32(gbc);
602
71.2k
    ret = ff_set_dimensions(avctx, width, height);
603
71.2k
    if (ret < 0) {
604
1.73k
        av_log(avctx, AV_LOG_ERROR, "Invalid image size %dx%d.\n",
605
1.73k
               avctx->width, avctx->height);
606
1.73k
        return ret;
607
1.73k
    }
608
609
    /* Since codec is based on 4x4 blocks, size is aligned to 4. */
610
69.4k
    avctx->coded_width  = FFALIGN(avctx->width,  TEXTURE_BLOCK_W);
611
69.4k
    avctx->coded_height = FFALIGN(avctx->height, TEXTURE_BLOCK_H);
612
613
69.4k
    bytestream2_skip(gbc, 4); // pitch
614
69.4k
    bytestream2_skip(gbc, 4); // depth
615
69.4k
    mipmap = bytestream2_get_le32(gbc);
616
69.4k
    if (mipmap != 0)
617
35.3k
        av_log(avctx, AV_LOG_VERBOSE, "Found %d mipmaps (ignored).\n", mipmap);
618
619
    /* Extract pixel format information, considering additional elements
620
     * in reserved1 and reserved2. */
621
69.4k
    ret = parse_pixel_format(avctx);
622
69.4k
    if (ret < 0)
623
13.4k
        return ret;
624
625
56.0k
    ret = ff_get_buffer(avctx, frame, 0);
626
56.0k
    if (ret < 0)
627
203
        return ret;
628
629
55.8k
    if (ctx->compressed) {
630
17.7k
        int size = (avctx->coded_height / TEXTURE_BLOCK_H) *
631
17.7k
                   (avctx->coded_width / TEXTURE_BLOCK_W) * ctx->dec.tex_ratio;
632
17.7k
        ctx->dec.slice_count = av_clip(avctx->thread_count, 1,
633
17.7k
                                       avctx->coded_height / TEXTURE_BLOCK_H);
634
635
17.7k
        if (bytestream2_get_bytes_left(gbc) < size) {
636
8.46k
            av_log(avctx, AV_LOG_ERROR,
637
8.46k
                   "Compressed Buffer is too small (%d < %d).\n",
638
8.46k
                   bytestream2_get_bytes_left(gbc), size);
639
8.46k
            return AVERROR_INVALIDDATA;
640
8.46k
        }
641
642
        /* Use the decompress function on the texture, one block per thread. */
643
9.30k
        ctx->dec.tex_data.in = gbc->buffer;
644
9.30k
        ctx->dec.frame_data.out = frame->data[0];
645
9.30k
        ctx->dec.stride = frame->linesize[0];
646
9.30k
        ctx->dec.width  = avctx->coded_width;
647
9.30k
        ctx->dec.height = avctx->coded_height;
648
9.30k
        ff_texturedsp_exec_decompress_threads(avctx, &ctx->dec);
649
38.0k
    } else if (!ctx->paletted && ctx->bpp == 4 && avctx->pix_fmt == AV_PIX_FMT_PAL8) {
650
25.3k
        uint8_t *dst = frame->data[0];
651
25.3k
        int x, y, i;
652
653
        /* Use the first 64 bytes as palette, then copy the rest. */
654
25.3k
        bytestream2_get_buffer(gbc, frame->data[1], 16 * 4);
655
431k
        for (i = 0; i < 16; i++) {
656
405k
            AV_WN32(frame->data[1] + i*4,
657
405k
                    (frame->data[1][2+i*4]<<0)+
658
405k
                    (frame->data[1][1+i*4]<<8)+
659
405k
                    (frame->data[1][0+i*4]<<16)+
660
405k
                    ((unsigned)frame->data[1][3+i*4]<<24)
661
405k
            );
662
405k
        }
663
664
25.3k
        if (bytestream2_get_bytes_left(gbc) < frame->height * frame->width / 2) {
665
530
            av_log(avctx, AV_LOG_ERROR, "Buffer is too small (%d < %d).\n",
666
530
                   bytestream2_get_bytes_left(gbc), frame->height * frame->width / 2);
667
530
            return AVERROR_INVALIDDATA;
668
530
        }
669
670
4.16M
        for (y = 0; y < frame->height; y++) {
671
8.32M
            for (x = 0; x < frame->width; x += 2) {
672
4.18M
                uint8_t val = bytestream2_get_byte(gbc);
673
4.18M
                dst[x    ] = val & 0xF;
674
4.18M
                dst[x + 1] = val >> 4;
675
4.18M
            }
676
4.13M
            dst += frame->linesize[0];
677
4.13M
        }
678
24.8k
    } else {
679
12.6k
        int linesize = av_image_get_linesize(avctx->pix_fmt, frame->width, 0);
680
681
12.6k
        if (ctx->paletted) {
682
2.57k
            int i;
683
            /* Use the first 1024 bytes as palette, then copy the rest. */
684
2.57k
            bytestream2_get_buffer(gbc, frame->data[1], 256 * 4);
685
660k
            for (i = 0; i < 256; i++)
686
657k
                AV_WN32(frame->data[1] + i*4,
687
2.57k
                        (frame->data[1][2+i*4]<<0)+
688
2.57k
                        (frame->data[1][1+i*4]<<8)+
689
2.57k
                        (frame->data[1][0+i*4]<<16)+
690
2.57k
                        ((unsigned)frame->data[1][3+i*4]<<24)
691
2.57k
                );
692
2.57k
        }
693
694
12.6k
        if (bytestream2_get_bytes_left(gbc) < frame->height * linesize) {
695
11.0k
            av_log(avctx, AV_LOG_ERROR, "Buffer is too small (%d < %d).\n",
696
11.0k
                   bytestream2_get_bytes_left(gbc), frame->height * linesize);
697
11.0k
            return AVERROR_INVALIDDATA;
698
11.0k
        }
699
700
1.59k
        av_image_copy_plane(frame->data[0], frame->linesize[0],
701
1.59k
                            gbc->buffer, linesize,
702
1.59k
                            linesize, frame->height);
703
1.59k
    }
704
705
    /* Run any post processing here if needed. */
706
35.7k
    if (ctx->postproc != DDS_NONE)
707
32.3k
        run_postproc(avctx, frame);
708
709
    /* Frame is ready to be output. */
710
35.7k
    *got_frame = 1;
711
712
35.7k
    return avpkt->size;
713
55.8k
}
714
715
const FFCodec ff_dds_decoder = {
716
    .p.name         = "dds",
717
    CODEC_LONG_NAME("DirectDraw Surface image decoder"),
718
    .p.type         = AVMEDIA_TYPE_VIDEO,
719
    .p.id           = AV_CODEC_ID_DDS,
720
    FF_CODEC_DECODE_CB(dds_decode),
721
    .priv_data_size = sizeof(DDSContext),
722
    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SLICE_THREADS,
723
};