Coverage Report

Created: 2025-12-31 07:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ffmpeg/libavcodec/txd.c
Line
Count
Source
1
/*
2
 * Renderware TeXture Dictionary (.txd) image decoder
3
 * Copyright (c) 2007 Ivo van Poorten
4
 *
5
 * See also: http://wiki.multimedia.cx/index.php?title=TXD
6
 *
7
 * This file is part of FFmpeg.
8
 *
9
 * FFmpeg is free software; you can redistribute it and/or
10
 * modify it under the terms of the GNU Lesser General Public
11
 * License as published by the Free Software Foundation; either
12
 * version 2.1 of the License, or (at your option) any later version.
13
 *
14
 * FFmpeg is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17
 * Lesser General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU Lesser General Public
20
 * License along with FFmpeg; if not, write to the Free Software
21
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22
 */
23
24
#include "bytestream.h"
25
#include "avcodec.h"
26
#include "codec_internal.h"
27
#include "decode.h"
28
#include "texturedsp.h"
29
30
7.24k
#define TXD_DXT1 0x31545844
31
1.29k
#define TXD_DXT3 0x33545844
32
33
static int txd_decode_frame(AVCodecContext *avctx, AVFrame *p,
34
                            int *got_frame, AVPacket *avpkt)
35
237k
{
36
237k
    GetByteContext gb;
37
237k
    TextureDSPContext dxtc;
38
237k
    unsigned int version, w, h, d3d_format, depth, stride, flags;
39
237k
    unsigned int y, v;
40
237k
    uint8_t *ptr;
41
237k
    uint32_t *pal;
42
237k
    int i, j;
43
237k
    int ret;
44
45
237k
    if (avpkt->size < 88)
46
153k
        return AVERROR_INVALIDDATA;
47
48
83.4k
    ff_texturedsp_init(&dxtc);
49
50
83.4k
    bytestream2_init(&gb, avpkt->data, avpkt->size);
51
83.4k
    version         = bytestream2_get_le32(&gb);
52
83.4k
    bytestream2_skip(&gb, 72);
53
83.4k
    d3d_format      = bytestream2_get_le32(&gb);
54
83.4k
    w               = bytestream2_get_le16(&gb);
55
83.4k
    h               = bytestream2_get_le16(&gb);
56
83.4k
    depth           = bytestream2_get_byte(&gb);
57
83.4k
    bytestream2_skip(&gb, 2);
58
83.4k
    flags           = bytestream2_get_byte(&gb);
59
60
83.4k
    if (version < 8 || version > 9) {
61
1.41k
        avpriv_report_missing_feature(avctx, "Texture data version %u", version);
62
1.41k
        return AVERROR_PATCHWELCOME;
63
1.41k
    }
64
65
82.0k
    if (depth == 8) {
66
3.00k
        avctx->pix_fmt = AV_PIX_FMT_PAL8;
67
3.00k
        if (bytestream2_get_bytes_left(&gb) < w * h + 4 * 256)
68
388
            return AVERROR_INVALIDDATA;
69
79.0k
    } else if (depth == 16) {
70
12.2k
        avctx->pix_fmt = AV_PIX_FMT_RGBA;
71
12.2k
        switch (d3d_format) {
72
1.20k
        case 0:
73
1.20k
            if (!(flags & 1))
74
227
                goto unsupported;
75
6.49k
        case TXD_DXT1:
76
6.49k
            if (bytestream2_get_bytes_left(&gb) < AV_CEIL_RSHIFT(w, 2) * AV_CEIL_RSHIFT(h, 2) * 8 + 4)
77
5.52k
                return AVERROR_INVALIDDATA;
78
969
            break;
79
969
        case TXD_DXT3:
80
927
            if (bytestream2_get_bytes_left(&gb) < AV_CEIL_RSHIFT(w, 2) * AV_CEIL_RSHIFT(h, 2) * 16 + 4)
81
245
                return AVERROR_INVALIDDATA;
82
12.2k
        }
83
66.8k
    } else if (depth == 32) {
84
65.3k
        avctx->pix_fmt = AV_PIX_FMT_RGBA;
85
65.3k
        if (bytestream2_get_bytes_left(&gb) < h * w * 4)
86
630
            return AVERROR_INVALIDDATA;
87
65.3k
    } else {
88
1.47k
        avpriv_report_missing_feature(avctx, "Color depth of %u", depth);
89
1.47k
        return AVERROR_PATCHWELCOME;
90
1.47k
    }
91
92
73.5k
    if ((ret = ff_set_dimensions(avctx, w, h)) < 0)
93
1.54k
        return ret;
94
95
72.0k
    avctx->coded_width  = FFALIGN(w, 4);
96
72.0k
    avctx->coded_height = FFALIGN(h, 4);
97
98
72.0k
    if ((ret = ff_get_buffer(avctx, p, 0)) < 0)
99
385
        return ret;
100
101
71.6k
    p->pict_type = AV_PICTURE_TYPE_I;
102
103
71.6k
    ptr    = p->data[0];
104
71.6k
    stride = p->linesize[0];
105
106
71.6k
    if (depth == 8) {
107
2.61k
        pal = (uint32_t *) p->data[1];
108
672k
        for (y = 0; y < 256; y++) {
109
669k
            v = bytestream2_get_be32(&gb);
110
669k
            pal[y] = (v >> 8) + (v << 24);
111
669k
        }
112
2.61k
        bytestream2_skip(&gb, 4);
113
549k
        for (y=0; y<h; y++) {
114
547k
            bytestream2_get_buffer(&gb, ptr, w);
115
547k
            ptr += stride;
116
547k
        }
117
69.0k
    } else if (depth == 16) {
118
4.48k
        bytestream2_skip(&gb, 4);
119
4.48k
        switch (d3d_format) {
120
398
        case 0:
121
750
        case TXD_DXT1:
122
58.4k
            for (j = 0; j < avctx->height; j += 4) {
123
303k
                for (i = 0; i < avctx->width; i += 4) {
124
245k
                    uint8_t *p = ptr + i * 4 + j * stride;
125
245k
                    int step = dxtc.dxt1_block(p, stride, gb.buffer);
126
245k
                    bytestream2_skip(&gb, step);
127
245k
                }
128
57.6k
            }
129
750
            break;
130
363
        case TXD_DXT3:
131
1.48k
            for (j = 0; j < avctx->height; j += 4) {
132
100k
                for (i = 0; i < avctx->width; i += 4) {
133
99.3k
                    uint8_t *p = ptr + i * 4 + j * stride;
134
99.3k
                    int step = dxtc.dxt3_block(p, stride, gb.buffer);
135
99.3k
                    bytestream2_skip(&gb, step);
136
99.3k
                }
137
1.12k
            }
138
363
            break;
139
3.37k
        default:
140
3.37k
            goto unsupported;
141
4.48k
        }
142
64.5k
    } else if (depth == 32) {
143
64.5k
        switch (d3d_format) {
144
64.2k
        case 0x15:
145
64.2k
        case 0x16:
146
593k
            for (y=0; y<h; y++) {
147
529k
                bytestream2_get_buffer(&gb, ptr, w * 4);
148
529k
                ptr += stride;
149
529k
            }
150
64.2k
            break;
151
329
        default:
152
329
            goto unsupported;
153
64.5k
        }
154
64.5k
    }
155
156
67.9k
    *got_frame = 1;
157
158
67.9k
    return avpkt->size;
159
160
3.93k
unsupported:
161
3.93k
    avpriv_report_missing_feature(avctx, "d3d format (%08x)", d3d_format);
162
3.93k
    return AVERROR_PATCHWELCOME;
163
71.6k
}
164
165
const FFCodec ff_txd_decoder = {
166
    .p.name         = "txd",
167
    CODEC_LONG_NAME("Renderware TXD (TeXture Dictionary) image"),
168
    .p.type         = AVMEDIA_TYPE_VIDEO,
169
    .p.id           = AV_CODEC_ID_TXD,
170
    .p.capabilities = AV_CODEC_CAP_DR1,
171
    FF_CODEC_DECODE_CB(txd_decode_frame),
172
};