FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/dxv.c
Date: 2025-08-19 23:55:23
Exec Total Coverage
Lines: 641 745 86.0%
Functions: 15 16 93.8%
Branches: 234 356 65.7%

Line Branch Exec Source
1 /*
2 * Resolume DXV decoder
3 * Copyright (C) 2015 Vittorio Giovara <vittorio.giovara@gmail.com>
4 * Copyright (C) 2018 Paul B Mahol
5 *
6 * This file is part of FFmpeg.
7 *
8 * FFmpeg is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * FFmpeg is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with FFmpeg; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23 #include <stdint.h>
24
25 #include "libavutil/imgutils.h"
26 #include "libavutil/mem.h"
27
28 #include "avcodec.h"
29 #include "bytestream.h"
30 #include "codec_internal.h"
31 #include "dxv.h"
32 #include "lzf.h"
33 #include "texturedsp.h"
34 #include "thread.h"
35
36 typedef struct DXVContext {
37 TextureDSPContext texdsp;
38 GetByteContext gbc;
39
40 uint8_t *tex_data; // Compressed texture
41 unsigned tex_data_size;
42 uint8_t *ctex_data; // Compressed chroma texture
43 unsigned ctex_data_size;
44
45 size_t tex_size; // Texture size
46 int64_t ctex_size; // Chroma texture size
47
48 uint8_t *op_data[4]; // Opcodes
49 unsigned op_data_size[4];
50 int64_t op_size[4]; // Opcodes size
51 } DXVContext;
52
53 /* This scheme addresses already decoded elements depending on 2-bit status:
54 * 0 -> copy new element
55 * 1 -> copy one element from position -x
56 * 2 -> copy one element from position -(get_byte() + 2) * x
57 * 3 -> copy one element from position -(get_16le() + 0x102) * x
58 * x is always 2 for dxt1 and 4 for dxt5. */
59 #define CHECKPOINT(x) \
60 do { \
61 if (state == 0) { \
62 if (bytestream2_get_bytes_left(gbc) < 4) \
63 return AVERROR_INVALIDDATA; \
64 value = bytestream2_get_le32(gbc); \
65 state = 16; \
66 } \
67 op = value & 0x3; \
68 value >>= 2; \
69 state--; \
70 switch (op) { \
71 case 1: \
72 idx = x; \
73 break; \
74 case 2: \
75 idx = (bytestream2_get_byte(gbc) + 2) * x; \
76 if (idx > pos) { \
77 av_log(avctx, AV_LOG_ERROR, "idx %d > %d\n", idx, pos); \
78 return AVERROR_INVALIDDATA; \
79 } \
80 break; \
81 case 3: \
82 idx = (bytestream2_get_le16(gbc) + 0x102) * x; \
83 if (idx > pos) { \
84 av_log(avctx, AV_LOG_ERROR, "idx %d > %d\n", idx, pos); \
85 return AVERROR_INVALIDDATA; \
86 } \
87 break; \
88 } \
89 } while(0)
90
91 2 static int dxv_decompress_dxt1(AVCodecContext *avctx)
92 {
93 2 DXVContext *ctx = avctx->priv_data;
94 2 GetByteContext *gbc = &ctx->gbc;
95 uint32_t value, prev, op;
96 2 int idx = 0, state = 0;
97 2 int pos = 2;
98
99 /* Copy the first two elements */
100 2 AV_WL32(ctx->tex_data, bytestream2_get_le32(gbc));
101 2 AV_WL32(ctx->tex_data + 4, bytestream2_get_le32(gbc));
102
103 /* Process input until the whole texture has been filled */
104
2/2
✓ Branch 0 taken 259198 times.
✓ Branch 1 taken 2 times.
259200 while (pos + 2 <= ctx->tex_size / 4) {
105
9/12
✓ Branch 0 taken 16202 times.
✓ Branch 1 taken 242996 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 16202 times.
✓ Branch 6 taken 214724 times.
✓ Branch 7 taken 1804 times.
✓ Branch 8 taken 36462 times.
✓ Branch 9 taken 6208 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 1804 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 36462 times.
259198 CHECKPOINT(2);
106
107 /* Copy two elements from a previous offset or from the input buffer */
108
2/2
✓ Branch 0 taken 252990 times.
✓ Branch 1 taken 6208 times.
259198 if (op) {
109 252990 prev = AV_RL32(ctx->tex_data + 4 * (pos - idx));
110 252990 AV_WL32(ctx->tex_data + 4 * pos, prev);
111 252990 pos++;
112
113 252990 prev = AV_RL32(ctx->tex_data + 4 * (pos - idx));
114 252990 AV_WL32(ctx->tex_data + 4 * pos, prev);
115 252990 pos++;
116 } else {
117
9/12
✓ Branch 0 taken 384 times.
✓ Branch 1 taken 5824 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 384 times.
✓ Branch 6 taken 318 times.
✓ Branch 7 taken 62 times.
✓ Branch 8 taken 1222 times.
✓ Branch 9 taken 4606 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 62 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 1222 times.
6208 CHECKPOINT(2);
118
119
2/2
✓ Branch 0 taken 1602 times.
✓ Branch 1 taken 4606 times.
6208 if (op)
120 1602 prev = AV_RL32(ctx->tex_data + 4 * (pos - idx));
121 else
122 4606 prev = bytestream2_get_le32(gbc);
123 6208 AV_WL32(ctx->tex_data + 4 * pos, prev);
124 6208 pos++;
125
126
9/12
✓ Branch 0 taken 390 times.
✓ Branch 1 taken 5818 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 390 times.
✓ Branch 6 taken 1368 times.
✓ Branch 7 taken 1180 times.
✓ Branch 8 taken 648 times.
✓ Branch 9 taken 3012 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 1180 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 648 times.
6208 CHECKPOINT(2);
127
128
2/2
✓ Branch 0 taken 3196 times.
✓ Branch 1 taken 3012 times.
6208 if (op)
129 3196 prev = AV_RL32(ctx->tex_data + 4 * (pos - idx));
130 else
131 3012 prev = bytestream2_get_le32(gbc);
132 6208 AV_WL32(ctx->tex_data + 4 * pos, prev);
133 6208 pos++;
134 }
135 }
136
137 2 return 0;
138 }
139
140 typedef struct OpcodeTable {
141 int16_t next;
142 uint8_t val1;
143 uint8_t val2;
144 } OpcodeTable;
145
146 12 static int fill_ltable(GetByteContext *gb, uint32_t *table, int *nb_elements)
147 {
148 12 unsigned half = 512, bits = 1023, left = 1024, input, mask;
149 12 int value, counter = 0, rshift = 10, lshift = 30;
150
151 12 mask = bytestream2_get_le32(gb) >> 2;
152
2/2
✓ Branch 0 taken 200 times.
✓ Branch 1 taken 12 times.
212 while (left) {
153
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 200 times.
200 if (counter >= 256)
154 return AVERROR_INVALIDDATA;
155 200 value = bits & mask;
156 200 left -= bits & mask;
157 200 mask >>= rshift;
158 200 lshift -= rshift;
159 200 table[counter++] = value;
160
2/2
✓ Branch 0 taken 88 times.
✓ Branch 1 taken 112 times.
200 if (lshift < 16) {
161
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 88 times.
88 if (bytestream2_get_bytes_left(gb) <= 0)
162 return AVERROR_INVALIDDATA;
163
164 88 input = bytestream2_get_le16(gb);
165 88 mask += input << lshift;
166 88 lshift += 16;
167 }
168
2/2
✓ Branch 0 taken 88 times.
✓ Branch 1 taken 112 times.
200 if (left < half) {
169 88 half >>= 1;
170 88 bits >>= 1;
171 88 rshift--;
172 }
173 }
174
175
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 for (; !table[counter - 1]; counter--)
176 if (counter <= 0)
177 return AVERROR_INVALIDDATA;
178
179 12 *nb_elements = counter;
180
181
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 if (counter < 256)
182 12 memset(&table[counter], 0, 4 * (256 - counter));
183
184
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 if (lshift >= 16)
185 12 bytestream2_seek(gb, -2, SEEK_CUR);
186
187 12 return 0;
188 }
189
190 12 static int fill_optable(unsigned *table0, OpcodeTable *table1, int nb_elements)
191 {
192 12 unsigned table2[256] = { 0 };
193 12 unsigned x = 0;
194 12 int val0, val1, i, j = 2, k = 0;
195
196 12 table2[0] = table0[0];
197
2/2
✓ Branch 0 taken 188 times.
✓ Branch 1 taken 12 times.
200 for (i = 0; i < nb_elements - 1; i++, table2[i] = val0) {
198 188 val0 = table0[i + 1] + table2[i];
199 }
200
201
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (!table2[0]) {
202 do {
203 k++;
204 } while (!table2[k]);
205 }
206
207 12 j = 2;
208
2/2
✓ Branch 0 taken 12288 times.
✓ Branch 1 taken 12 times.
12300 for (i = 1024; i > 0; i--) {
209
4/4
✓ Branch 0 taken 15348 times.
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 3072 times.
✓ Branch 3 taken 12276 times.
15360 for (table1[x].val1 = k; k < 256 && j > table2[k]; k++);
210 12288 x = (x - 383) & 0x3FF;
211 12288 j++;
212 }
213
214
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 if (nb_elements > 0)
215 12 memcpy(&table2[0], table0, 4 * nb_elements);
216
217
2/2
✓ Branch 0 taken 12288 times.
✓ Branch 1 taken 12 times.
12300 for (i = 0; i < 1024; i++) {
218 12288 val0 = table1[i].val1;
219 12288 val1 = table2[val0];
220 12288 table2[val0]++;
221 12288 x = 31 - ff_clz(val1);
222
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12288 times.
12288 if (x > 10)
223 return AVERROR_INVALIDDATA;
224 12288 table1[i].val2 = 10 - x;
225 12288 table1[i].next = (val1 << table1[i].val2) - 1024;
226 }
227
228 12 return 0;
229 }
230
231 12 static int get_opcodes(GetByteContext *gb, uint32_t *table, uint8_t *dst, int op_size, int nb_elements)
232 {
233 OpcodeTable optable[1024];
234 int sum, x, val, lshift, rshift, ret, i, idx;
235 int64_t size_in_bits;
236 unsigned endoffset, newoffset, offset;
237 unsigned next;
238 12 const uint8_t *src = gb->buffer;
239
240 12 ret = fill_optable(table, optable, nb_elements);
241
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (ret < 0)
242 return ret;
243
244 12 size_in_bits = bytestream2_get_le32(gb);
245 12 endoffset = ((size_in_bits + 7) >> 3) - 4;
246
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 12 times.
12 if ((int)endoffset <= 0 || bytestream2_get_bytes_left(gb) < endoffset)
247 return AVERROR_INVALIDDATA;
248
249 12 offset = endoffset;
250 12 next = AV_RL32(src + endoffset);
251 12 rshift = (((size_in_bits & 0xFF) - 1) & 7) + 15;
252 12 lshift = 32 - rshift;
253 12 idx = (next >> rshift) & 0x3FF;
254
2/2
✓ Branch 0 taken 13886 times.
✓ Branch 1 taken 12 times.
13898 for (i = 0; i < op_size; i++) {
255 13886 dst[i] = optable[idx].val1;
256 13886 val = optable[idx].val2;
257 13886 sum = val + lshift;
258 13886 x = (next << lshift) >> 1 >> (31 - val);
259 13886 newoffset = offset - (sum >> 3);
260 13886 lshift = sum & 7;
261 13886 idx = x + optable[idx].next;
262 13886 offset = newoffset;
263
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13886 times.
13886 if (offset > endoffset)
264 return AVERROR_INVALIDDATA;
265 13886 next = AV_RL32(src + offset);
266 }
267
268 12 bytestream2_skip(gb, (size_in_bits + 7 >> 3) - 4);
269
270 12 return 0;
271 }
272
273 14 static int dxv_decompress_opcodes(GetByteContext *gb, void *dstp, size_t op_size)
274 {
275 14 int pos = bytestream2_tell(gb);
276 14 int flag = bytestream2_peek_byte(gb);
277
278
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 12 times.
14 if ((flag & 3) == 0) {
279 2 bytestream2_skip(gb, 1);
280 2 int read_size = bytestream2_get_buffer(gb, dstp, op_size);
281
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (read_size != op_size)
282 return AVERROR_INVALIDDATA;
283
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 } else if ((flag & 3) == 1) {
284 bytestream2_skip(gb, 1);
285 memset(dstp, bytestream2_get_byte(gb), op_size);
286 } else {
287 uint32_t table[256];
288 12 int ret, elements = 0;
289
290 12 ret = fill_ltable(gb, table, &elements);
291
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (ret < 0)
292 return ret;
293 12 ret = get_opcodes(gb, table, dstp, op_size, elements);
294
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (ret < 0)
295 return ret;
296 }
297 14 return bytestream2_tell(gb) - pos;
298 }
299
300 32754 static int dxv_decompress_cgo(DXVContext *ctx, GetByteContext *gb,
301 uint8_t *tex_data, int tex_size,
302 uint8_t *op_data, int *oindex,
303 int op_size,
304 uint8_t **dstp, int *statep,
305 uint8_t **tab0, uint8_t **tab1,
306 int offset)
307 {
308 32754 uint8_t *dst = *dstp;
309 uint8_t *tptr0, *tptr1, *tptr3;
310 32754 int oi = *oindex;
311 32754 int state = *statep;
312 int opcode, v, vv;
313
314
2/2
✓ Branch 0 taken 13886 times.
✓ Branch 1 taken 18868 times.
32754 if (state <= 0) {
315
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13886 times.
13886 if (oi >= op_size)
316 return AVERROR_INVALIDDATA;
317 13886 opcode = op_data[oi++];
318
2/2
✓ Branch 0 taken 1866 times.
✓ Branch 1 taken 12020 times.
13886 if (!opcode) {
319 1866 v = bytestream2_get_byte(gb);
320
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1864 times.
1866 if (v == 255) {
321 do {
322
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (bytestream2_get_bytes_left(gb) <= 0)
323 return AVERROR_INVALIDDATA;
324 2 opcode = bytestream2_get_le16(gb);
325 2 v += opcode;
326
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 } while (opcode == 0xFFFF);
327 }
328 1866 AV_WL32(dst, AV_RL32(dst - (8 + offset)));
329 1866 AV_WL32(dst + 4, AV_RL32(dst - (4 + offset)));
330 1866 state = v + 4;
331 1866 goto done;
332 }
333
334
17/18
✓ Branch 0 taken 4116 times.
✓ Branch 1 taken 5232 times.
✓ Branch 2 taken 140 times.
✓ Branch 3 taken 40 times.
✓ Branch 4 taken 184 times.
✓ Branch 5 taken 16 times.
✓ Branch 6 taken 772 times.
✓ Branch 7 taken 68 times.
✓ Branch 8 taken 88 times.
✓ Branch 9 taken 112 times.
✓ Branch 10 taken 228 times.
✓ Branch 11 taken 796 times.
✓ Branch 12 taken 40 times.
✓ Branch 13 taken 64 times.
✓ Branch 14 taken 60 times.
✓ Branch 15 taken 44 times.
✓ Branch 16 taken 20 times.
✗ Branch 17 not taken.
12020 switch (opcode) {
335 4116 case 1:
336 4116 AV_WL32(dst, AV_RL32(dst - (8 + offset)));
337 4116 AV_WL32(dst + 4, AV_RL32(dst - (4 + offset)));
338 4116 break;
339 5232 case 2:
340 5232 vv = (8 + offset) * (bytestream2_get_le16(gb) + 1);
341
2/4
✓ Branch 0 taken 5232 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5232 times.
5232 if (vv < 0 || vv > dst - tex_data)
342 return AVERROR_INVALIDDATA;
343 5232 tptr0 = dst - vv;
344 5232 v = AV_RL32(tptr0);
345 5232 AV_WL32(dst, AV_RL32(tptr0));
346 5232 AV_WL32(dst + 4, AV_RL32(tptr0 + 4));
347 5232 tab0[0x9E3779B1 * (uint16_t)v >> 24] = dst;
348 5232 tab1[0x9E3779B1 * (AV_RL32(dst + 2) & 0xFFFFFFu) >> 24] = dst + 2;
349 5232 break;
350 140 case 3:
351 140 AV_WL32(dst, bytestream2_get_le32(gb));
352 140 AV_WL32(dst + 4, bytestream2_get_le32(gb));
353 140 tab0[0x9E3779B1 * AV_RL16(dst) >> 24] = dst;
354 140 tab1[0x9E3779B1 * (AV_RL32(dst + 2) & 0xFFFFFFu) >> 24] = dst + 2;
355 140 break;
356 40 case 4:
357 40 tptr3 = tab1[bytestream2_get_byte(gb)];
358
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
40 if (!tptr3)
359 return AVERROR_INVALIDDATA;
360 40 AV_WL16(dst, bytestream2_get_le16(gb));
361 40 AV_WL16(dst + 2, AV_RL16(tptr3));
362 40 dst[4] = tptr3[2];
363 40 AV_WL16(dst + 5, bytestream2_get_le16(gb));
364 40 dst[7] = bytestream2_get_byte(gb);
365 40 tab0[0x9E3779B1 * AV_RL16(dst) >> 24] = dst;
366 40 break;
367 184 case 5:
368 184 tptr3 = tab1[bytestream2_get_byte(gb)];
369
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 184 times.
184 if (!tptr3)
370 return AVERROR_INVALIDDATA;
371 184 AV_WL16(dst, bytestream2_get_le16(gb));
372 184 AV_WL16(dst + 2, bytestream2_get_le16(gb));
373 184 dst[4] = bytestream2_get_byte(gb);
374 184 AV_WL16(dst + 5, AV_RL16(tptr3));
375 184 dst[7] = tptr3[2];
376 184 tab0[0x9E3779B1 * AV_RL16(dst) >> 24] = dst;
377 184 tab1[0x9E3779B1 * (AV_RL32(dst + 2) & 0xFFFFFFu) >> 24] = dst + 2;
378 184 break;
379 16 case 6:
380 16 tptr0 = tab1[bytestream2_get_byte(gb)];
381
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (!tptr0)
382 return AVERROR_INVALIDDATA;
383 16 tptr1 = tab1[bytestream2_get_byte(gb)];
384
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (!tptr1)
385 return AVERROR_INVALIDDATA;
386 16 AV_WL16(dst, bytestream2_get_le16(gb));
387 16 AV_WL16(dst + 2, AV_RL16(tptr0));
388 16 dst[4] = tptr0[2];
389 16 AV_WL16(dst + 5, AV_RL16(tptr1));
390 16 dst[7] = tptr1[2];
391 16 tab0[0x9E3779B1 * AV_RL16(dst) >> 24] = dst;
392 16 break;
393 772 case 7:
394 772 v = (8 + offset) * (bytestream2_get_le16(gb) + 1);
395
2/4
✓ Branch 0 taken 772 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 772 times.
772 if (v < 0 || v > dst - tex_data)
396 return AVERROR_INVALIDDATA;
397 772 tptr0 = dst - v;
398 772 AV_WL16(dst, bytestream2_get_le16(gb));
399 772 AV_WL16(dst + 2, AV_RL16(tptr0 + 2));
400 772 AV_WL32(dst + 4, AV_RL32(tptr0 + 4));
401 772 tab0[0x9E3779B1 * AV_RL16(dst) >> 24] = dst;
402 772 tab1[0x9E3779B1 * (AV_RL32(dst + 2) & 0xFFFFFFu) >> 24] = dst + 2;
403 772 break;
404 68 case 8:
405 68 tptr1 = tab0[bytestream2_get_byte(gb)];
406
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 68 times.
68 if (!tptr1)
407 return AVERROR_INVALIDDATA;
408 68 AV_WL16(dst, AV_RL16(tptr1));
409 68 AV_WL16(dst + 2, bytestream2_get_le16(gb));
410 68 AV_WL32(dst + 4, bytestream2_get_le32(gb));
411 68 tab1[0x9E3779B1 * (AV_RL32(dst + 2) & 0xFFFFFFu) >> 24] = dst + 2;
412 68 break;
413 88 case 9:
414 88 tptr1 = tab0[bytestream2_get_byte(gb)];
415
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 88 times.
88 if (!tptr1)
416 return AVERROR_INVALIDDATA;
417 88 tptr3 = tab1[bytestream2_get_byte(gb)];
418
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 88 times.
88 if (!tptr3)
419 return AVERROR_INVALIDDATA;
420 88 AV_WL16(dst, AV_RL16(tptr1));
421 88 AV_WL16(dst + 2, AV_RL16(tptr3));
422 88 dst[4] = tptr3[2];
423 88 AV_WL16(dst + 5, bytestream2_get_le16(gb));
424 88 dst[7] = bytestream2_get_byte(gb);
425 88 tab1[0x9E3779B1 * (AV_RL32(dst + 2) & 0xFFFFFFu) >> 24] = dst + 2;
426 88 break;
427 112 case 10:
428 112 tptr1 = tab0[bytestream2_get_byte(gb)];
429
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 112 times.
112 if (!tptr1)
430 return AVERROR_INVALIDDATA;
431 112 tptr3 = tab1[bytestream2_get_byte(gb)];
432
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 112 times.
112 if (!tptr3)
433 return AVERROR_INVALIDDATA;
434 112 AV_WL16(dst, AV_RL16(tptr1));
435 112 AV_WL16(dst + 2, bytestream2_get_le16(gb));
436 112 dst[4] = bytestream2_get_byte(gb);
437 112 AV_WL16(dst + 5, AV_RL16(tptr3));
438 112 dst[7] = tptr3[2];
439 112 tab1[0x9E3779B1 * (AV_RL32(dst + 2) & 0xFFFFFFu) >> 24] = dst + 2;
440 112 break;
441 228 case 11:
442 228 tptr0 = tab0[bytestream2_get_byte(gb)];
443
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 228 times.
228 if (!tptr0)
444 return AVERROR_INVALIDDATA;
445 228 tptr3 = tab1[bytestream2_get_byte(gb)];
446
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 228 times.
228 if (!tptr3)
447 return AVERROR_INVALIDDATA;
448 228 tptr1 = tab1[bytestream2_get_byte(gb)];
449
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 228 times.
228 if (!tptr1)
450 return AVERROR_INVALIDDATA;
451 228 AV_WL16(dst, AV_RL16(tptr0));
452 228 AV_WL16(dst + 2, AV_RL16(tptr3));
453 228 dst[4] = tptr3[2];
454 228 AV_WL16(dst + 5, AV_RL16(tptr1));
455 228 dst[7] = tptr1[2];
456 228 break;
457 796 case 12:
458 796 tptr1 = tab0[bytestream2_get_byte(gb)];
459
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 796 times.
796 if (!tptr1)
460 return AVERROR_INVALIDDATA;
461 796 v = (8 + offset) * (bytestream2_get_le16(gb) + 1);
462
2/4
✓ Branch 0 taken 796 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 796 times.
796 if (v < 0 || v > dst - tex_data)
463 return AVERROR_INVALIDDATA;
464 796 tptr0 = dst - v;
465 796 AV_WL16(dst, AV_RL16(tptr1));
466 796 AV_WL16(dst + 2, AV_RL16(tptr0 + 2));
467 796 AV_WL32(dst + 4, AV_RL32(tptr0 + 4));
468 796 tab1[0x9E3779B1 * (AV_RL32(dst + 2) & 0xFFFFFFu) >> 24] = dst + 2;
469 796 break;
470 40 case 13:
471 40 AV_WL16(dst, AV_RL16(dst - (8 + offset)));
472 40 AV_WL16(dst + 2, bytestream2_get_le16(gb));
473 40 AV_WL32(dst + 4, bytestream2_get_le32(gb));
474 40 tab1[0x9E3779B1 * (AV_RL32(dst + 2) & 0xFFFFFFu) >> 24] = dst + 2;
475 40 break;
476 64 case 14:
477 64 tptr3 = tab1[bytestream2_get_byte(gb)];
478
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 64 times.
64 if (!tptr3)
479 return AVERROR_INVALIDDATA;
480 64 AV_WL16(dst, AV_RL16(dst - (8 + offset)));
481 64 AV_WL16(dst + 2, AV_RL16(tptr3));
482 64 dst[4] = tptr3[2];
483 64 AV_WL16(dst + 5, bytestream2_get_le16(gb));
484 64 dst[7] = bytestream2_get_byte(gb);
485 64 tab1[0x9E3779B1 * (AV_RL32(dst + 2) & 0xFFFFFFu) >> 24] = dst + 2;
486 64 break;
487 60 case 15:
488 60 tptr3 = tab1[bytestream2_get_byte(gb)];
489
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 60 times.
60 if (!tptr3)
490 return AVERROR_INVALIDDATA;
491 60 AV_WL16(dst, AV_RL16(dst - (8 + offset)));
492 60 AV_WL16(dst + 2, bytestream2_get_le16(gb));
493 60 dst[4] = bytestream2_get_byte(gb);
494 60 AV_WL16(dst + 5, AV_RL16(tptr3));
495 60 dst[7] = tptr3[2];
496 60 tab1[0x9E3779B1 * (AV_RL32(dst + 2) & 0xFFFFFFu) >> 24] = dst + 2;
497 60 break;
498 44 case 16:
499 44 tptr3 = tab1[bytestream2_get_byte(gb)];
500
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 44 times.
44 if (!tptr3)
501 return AVERROR_INVALIDDATA;
502 44 tptr1 = tab1[bytestream2_get_byte(gb)];
503
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 44 times.
44 if (!tptr1)
504 return AVERROR_INVALIDDATA;
505 44 AV_WL16(dst, AV_RL16(dst - (8 + offset)));
506 44 AV_WL16(dst + 2, AV_RL16(tptr3));
507 44 dst[4] = tptr3[2];
508 44 AV_WL16(dst + 5, AV_RL16(tptr1));
509 44 dst[7] = tptr1[2];
510 44 break;
511 20 case 17:
512 20 v = (8 + offset) * (bytestream2_get_le16(gb) + 1);
513
2/4
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 20 times.
20 if (v < 0 || v > dst - tex_data)
514 return AVERROR_INVALIDDATA;
515 20 AV_WL16(dst, AV_RL16(dst - (8 + offset)));
516 20 AV_WL16(dst + 2, AV_RL16(&dst[-v + 2]));
517 20 AV_WL32(dst + 4, AV_RL32(&dst[-v + 4]));
518 20 tab1[0x9E3779B1 * (AV_RL32(dst + 2) & 0xFFFFFFu) >> 24] = dst + 2;
519 20 break;
520 default:
521 break;
522 }
523 } else {
524 18868 done:
525 20734 AV_WL32(dst, AV_RL32(dst - (8 + offset)));
526 20734 AV_WL32(dst + 4, AV_RL32(dst - (4 + offset)));
527 20734 state--;
528 }
529
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32754 times.
32754 if (dst - tex_data + 8 > tex_size)
530 return AVERROR_INVALIDDATA;
531 32754 dst += 8;
532
533 32754 *oindex = oi;
534 32754 *dstp = dst;
535 32754 *statep = state;
536
537 32754 return 0;
538 }
539
540 6 static int dxv_decompress_cocg(DXVContext *ctx, GetByteContext *gb,
541 uint8_t *tex_data, int tex_size,
542 uint8_t *op_data0, uint8_t *op_data1,
543 int max_op_size0, int max_op_size1)
544 {
545 6 uint8_t *dst, *tab2[256] = { 0 }, *tab0[256] = { 0 }, *tab3[256] = { 0 }, *tab1[256] = { 0 };
546 6 int op_offset = bytestream2_get_le32(gb);
547 6 unsigned op_size0 = bytestream2_get_le32(gb);
548 6 unsigned op_size1 = bytestream2_get_le32(gb);
549 6 int data_start = bytestream2_tell(gb);
550 6 int skip0, skip1, oi0 = 0, oi1 = 0;
551 6 int ret, state0 = 0, state1 = 0;
552
553
2/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
6 if (op_offset < 12 || op_offset - 12 > bytestream2_get_bytes_left(gb))
554 return AVERROR_INVALIDDATA;
555
556 6 dst = tex_data;
557 6 bytestream2_skip(gb, op_offset - 12);
558
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (op_size0 > max_op_size0)
559 return AVERROR_INVALIDDATA;
560 6 skip0 = dxv_decompress_opcodes(gb, op_data0, op_size0);
561
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (skip0 < 0)
562 return skip0;
563
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (op_size1 > max_op_size1)
564 return AVERROR_INVALIDDATA;
565 6 skip1 = dxv_decompress_opcodes(gb, op_data1, op_size1);
566
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (skip1 < 0)
567 return skip1;
568 6 bytestream2_seek(gb, data_start, SEEK_SET);
569
570 6 AV_WL32(dst, bytestream2_get_le32(gb));
571 6 AV_WL32(dst + 4, bytestream2_get_le32(gb));
572 6 AV_WL32(dst + 8, bytestream2_get_le32(gb));
573 6 AV_WL32(dst + 12, bytestream2_get_le32(gb));
574
575 6 tab0[0x9E3779B1 * AV_RL16(dst) >> 24] = dst;
576 6 tab1[0x9E3779B1 * (AV_RL32(dst + 2) & 0xFFFFFF) >> 24] = dst + 2;
577 6 tab2[0x9E3779B1 * AV_RL16(dst + 8) >> 24] = dst + 8;
578 6 tab3[0x9E3779B1 * (AV_RL32(dst + 10) & 0xFFFFFF) >> 24] = dst + 10;
579 6 dst += 16;
580
2/2
✓ Branch 0 taken 12282 times.
✓ Branch 1 taken 6 times.
12288 while (dst + 10 < tex_data + tex_size) {
581 12282 ret = dxv_decompress_cgo(ctx, gb, tex_data, tex_size, op_data0, &oi0, op_size0,
582 &dst, &state0, tab0, tab1, 8);
583
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12282 times.
12282 if (ret < 0)
584 return ret;
585 12282 ret = dxv_decompress_cgo(ctx, gb, tex_data, tex_size, op_data1, &oi1, op_size1,
586 &dst, &state1, tab2, tab3, 8);
587
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12282 times.
12282 if (ret < 0)
588 return ret;
589 }
590
591 6 bytestream2_seek(gb, data_start - 12 + op_offset + skip0 + skip1, SEEK_SET);
592
593 6 return 0;
594 }
595
596 2 static int dxv_decompress_yo(DXVContext *ctx, GetByteContext *gb,
597 uint8_t *tex_data, int tex_size,
598 uint8_t *op_data, int max_op_size)
599 {
600 2 int op_offset = bytestream2_get_le32(gb);
601 2 unsigned op_size = bytestream2_get_le32(gb);
602 2 int data_start = bytestream2_tell(gb);
603 2 uint8_t *dst, *table0[256] = { 0 }, *table1[256] = { 0 };
604 2 int ret, state = 0, skip, oi = 0, v, vv;
605
606
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
2 if (op_offset < 8 || op_offset - 8 > bytestream2_get_bytes_left(gb))
607 return AVERROR_INVALIDDATA;
608
609 2 dst = tex_data;
610 2 bytestream2_skip(gb, op_offset - 8);
611
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (op_size > max_op_size)
612 return AVERROR_INVALIDDATA;
613 2 skip = dxv_decompress_opcodes(gb, op_data, op_size);
614
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (skip < 0)
615 return skip;
616 2 bytestream2_seek(gb, data_start, SEEK_SET);
617
618 2 v = bytestream2_get_le32(gb);
619 2 AV_WL32(dst, v);
620 2 vv = bytestream2_get_le32(gb);
621 2 table0[0x9E3779B1 * (uint16_t)v >> 24] = dst;
622 2 AV_WL32(dst + 4, vv);
623 2 table1[0x9E3779B1 * (AV_RL32(dst + 2) & 0xFFFFFF) >> 24] = dst + 2;
624 2 dst += 8;
625
626
2/2
✓ Branch 0 taken 8190 times.
✓ Branch 1 taken 2 times.
8192 while (dst < tex_data + tex_size) {
627 8190 ret = dxv_decompress_cgo(ctx, gb, tex_data, tex_size, op_data, &oi, op_size,
628 &dst, &state, table0, table1, 0);
629
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8190 times.
8190 if (ret < 0)
630 return ret;
631 }
632
633 2 bytestream2_seek(gb, data_start + op_offset + skip - 8, SEEK_SET);
634
635 2 return 0;
636 }
637
638 2 static int dxv_decompress_ycg6(AVCodecContext *avctx)
639 {
640 2 DXVContext *ctx = avctx->priv_data;
641 2 GetByteContext *gb = &ctx->gbc;
642 int ret;
643
644 2 ret = dxv_decompress_yo(ctx, gb, ctx->tex_data, ctx->tex_size,
645 2 ctx->op_data[0], ctx->op_size[0]);
646
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0)
647 return ret;
648
649 2 return dxv_decompress_cocg(ctx, gb, ctx->ctex_data, ctx->ctex_size,
650 ctx->op_data[1], ctx->op_data[2],
651 2 ctx->op_size[1], ctx->op_size[2]);
652 }
653
654 2 static int dxv_decompress_yg10(AVCodecContext *avctx)
655 {
656 2 DXVContext *ctx = avctx->priv_data;
657 2 GetByteContext *gb = &ctx->gbc;
658 int ret;
659
660 2 ret = dxv_decompress_cocg(ctx, gb, ctx->tex_data, ctx->tex_size,
661 ctx->op_data[0], ctx->op_data[3],
662 2 ctx->op_size[0], ctx->op_size[3]);
663
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0)
664 return ret;
665
666 2 return dxv_decompress_cocg(ctx, gb, ctx->ctex_data, ctx->ctex_size,
667 ctx->op_data[1], ctx->op_data[2],
668 2 ctx->op_size[1], ctx->op_size[2]);
669 }
670
671 2 static int dxv_decompress_dxt5(AVCodecContext *avctx)
672 {
673 2 DXVContext *ctx = avctx->priv_data;
674 2 GetByteContext *gbc = &ctx->gbc;
675 uint32_t value, op, prev;
676 2 int idx, state = 0;
677 2 int pos = 4;
678 2 int run = 0;
679 int probe, check;
680
681 /* Copy the first four elements */
682 2 AV_WL32(ctx->tex_data + 0, bytestream2_get_le32(gbc));
683 2 AV_WL32(ctx->tex_data + 4, bytestream2_get_le32(gbc));
684 2 AV_WL32(ctx->tex_data + 8, bytestream2_get_le32(gbc));
685 2 AV_WL32(ctx->tex_data + 12, bytestream2_get_le32(gbc));
686
687 /* Process input until the whole texture has been filled */
688
2/2
✓ Branch 0 taken 251404 times.
✓ Branch 1 taken 2 times.
251406 while (pos + 2 <= ctx->tex_size / 4) {
689
2/2
✓ Branch 0 taken 251400 times.
✓ Branch 1 taken 4 times.
251404 if (run) {
690 251400 run--;
691
692 251400 prev = AV_RL32(ctx->tex_data + 4 * (pos - 4));
693 251400 AV_WL32(ctx->tex_data + 4 * pos, prev);
694 251400 pos++;
695 251400 prev = AV_RL32(ctx->tex_data + 4 * (pos - 4));
696 251400 AV_WL32(ctx->tex_data + 4 * pos, prev);
697 251400 pos++;
698 } else {
699
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if (bytestream2_get_bytes_left(gbc) < 1)
700 return AVERROR_INVALIDDATA;
701
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (state == 0) {
702 2 value = bytestream2_get_le32(gbc);
703 2 state = 16;
704 }
705 4 op = value & 0x3;
706 4 value >>= 2;
707 4 state--;
708
709
2/5
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
4 switch (op) {
710 2 case 0:
711 /* Long copy */
712 2 check = bytestream2_get_byte(gbc) + 1;
713
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (check == 256) {
714 do {
715 2 probe = bytestream2_get_le16(gbc);
716 2 check += probe;
717
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 } while (probe == 0xFFFF);
718 }
719
3/4
✓ Branch 0 taken 7796 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 7796 times.
✗ Branch 3 not taken.
7798 while (check && pos + 4 <= ctx->tex_size / 4) {
720 7796 prev = AV_RL32(ctx->tex_data + 4 * (pos - 4));
721 7796 AV_WL32(ctx->tex_data + 4 * pos, prev);
722 7796 pos++;
723
724 7796 prev = AV_RL32(ctx->tex_data + 4 * (pos - 4));
725 7796 AV_WL32(ctx->tex_data + 4 * pos, prev);
726 7796 pos++;
727
728 7796 prev = AV_RL32(ctx->tex_data + 4 * (pos - 4));
729 7796 AV_WL32(ctx->tex_data + 4 * pos, prev);
730 7796 pos++;
731
732 7796 prev = AV_RL32(ctx->tex_data + 4 * (pos - 4));
733 7796 AV_WL32(ctx->tex_data + 4 * pos, prev);
734 7796 pos++;
735
736 7796 check--;
737 }
738
739 /* Restart (or exit) the loop */
740 2 continue;
741 break;
742 2 case 1:
743 /* Load new run value */
744 2 run = bytestream2_get_byte(gbc);
745
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (run == 255) {
746 do {
747 4 probe = bytestream2_get_le16(gbc);
748 4 run += probe;
749
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 } while (probe == 0xFFFF);
750 }
751
752 /* Copy two dwords from previous data */
753 2 prev = AV_RL32(ctx->tex_data + 4 * (pos - 4));
754 2 AV_WL32(ctx->tex_data + 4 * pos, prev);
755 2 pos++;
756
757 2 prev = AV_RL32(ctx->tex_data + 4 * (pos - 4));
758 2 AV_WL32(ctx->tex_data + 4 * pos, prev);
759 2 pos++;
760 2 break;
761 case 2:
762 /* Copy two dwords from a previous index */
763 idx = 8 + 4 * bytestream2_get_le16(gbc);
764 if (idx > pos || (unsigned int)(pos - idx) + 2 > ctx->tex_size / 4)
765 return AVERROR_INVALIDDATA;
766 prev = AV_RL32(ctx->tex_data + 4 * (pos - idx));
767 AV_WL32(ctx->tex_data + 4 * pos, prev);
768 pos++;
769
770 prev = AV_RL32(ctx->tex_data + 4 * (pos - idx));
771 AV_WL32(ctx->tex_data + 4 * pos, prev);
772 pos++;
773 break;
774 case 3:
775 /* Copy two dwords from input */
776 prev = bytestream2_get_le32(gbc);
777 AV_WL32(ctx->tex_data + 4 * pos, prev);
778 pos++;
779
780 prev = bytestream2_get_le32(gbc);
781 AV_WL32(ctx->tex_data + 4 * pos, prev);
782 pos++;
783 break;
784 }
785 }
786
787
9/12
✓ Branch 0 taken 15706 times.
✓ Branch 1 taken 235696 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 15706 times.
✓ Branch 6 taken 206930 times.
✓ Branch 7 taken 1804 times.
✓ Branch 8 taken 36456 times.
✓ Branch 9 taken 6212 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 1804 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 36456 times.
251402 CHECKPOINT(4);
788
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 251402 times.
251402 if (pos + 2 > ctx->tex_size / 4)
789 return AVERROR_INVALIDDATA;
790
791 /* Copy two elements from a previous offset or from the input buffer */
792
2/2
✓ Branch 0 taken 245190 times.
✓ Branch 1 taken 6212 times.
251402 if (op) {
793
2/4
✓ Branch 0 taken 245190 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 245190 times.
245190 if (idx > pos || (unsigned int)(pos - idx) + 2 > ctx->tex_size / 4)
794 return AVERROR_INVALIDDATA;
795 245190 prev = AV_RL32(ctx->tex_data + 4 * (pos - idx));
796 245190 AV_WL32(ctx->tex_data + 4 * pos, prev);
797 245190 pos++;
798
799 245190 prev = AV_RL32(ctx->tex_data + 4 * (pos - idx));
800 245190 AV_WL32(ctx->tex_data + 4 * pos, prev);
801 245190 pos++;
802 } else {
803
9/12
✓ Branch 0 taken 398 times.
✓ Branch 1 taken 5814 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 398 times.
✓ Branch 6 taken 320 times.
✓ Branch 7 taken 62 times.
✓ Branch 8 taken 1226 times.
✓ Branch 9 taken 4604 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 62 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 1226 times.
6212 CHECKPOINT(4);
804
805
4/6
✓ Branch 0 taken 1608 times.
✓ Branch 1 taken 4604 times.
✓ Branch 2 taken 1608 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1608 times.
6212 if (op && (idx > pos || (unsigned int)(pos - idx) + 2 > ctx->tex_size / 4))
806 return AVERROR_INVALIDDATA;
807
2/2
✓ Branch 0 taken 1608 times.
✓ Branch 1 taken 4604 times.
6212 if (op)
808 1608 prev = AV_RL32(ctx->tex_data + 4 * (pos - idx));
809 else
810 4604 prev = bytestream2_get_le32(gbc);
811 6212 AV_WL32(ctx->tex_data + 4 * pos, prev);
812 6212 pos++;
813
814
9/12
✓ Branch 0 taken 384 times.
✓ Branch 1 taken 5828 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 384 times.
✓ Branch 6 taken 1364 times.
✓ Branch 7 taken 1178 times.
✓ Branch 8 taken 650 times.
✓ Branch 9 taken 3020 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 1178 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 650 times.
6212 CHECKPOINT(4);
815
816
2/2
✓ Branch 0 taken 3192 times.
✓ Branch 1 taken 3020 times.
6212 if (op)
817 3192 prev = AV_RL32(ctx->tex_data + 4 * (pos - idx));
818 else
819 3020 prev = bytestream2_get_le32(gbc);
820 6212 AV_WL32(ctx->tex_data + 4 * pos, prev);
821 6212 pos++;
822 }
823 }
824
825 2 return 0;
826 }
827
828 4 static int dxv_decompress_lzf(AVCodecContext *avctx)
829 {
830 4 DXVContext *ctx = avctx->priv_data;
831 4 return ff_lzf_uncompress(&ctx->gbc, &ctx->tex_data, &ctx->tex_size, &ctx->tex_data_size);
832 }
833
834 static int dxv_decompress_raw(AVCodecContext *avctx)
835 {
836 DXVContext *ctx = avctx->priv_data;
837 GetByteContext *gbc = &ctx->gbc;
838
839 if (bytestream2_get_bytes_left(gbc) < ctx->tex_size)
840 return AVERROR_INVALIDDATA;
841
842 bytestream2_get_buffer(gbc, ctx->tex_data, ctx->tex_size);
843 return 0;
844 }
845
846 12 static int dxv_decode(AVCodecContext *avctx, AVFrame *frame,
847 int *got_frame, AVPacket *avpkt)
848 {
849 12 DXVContext *ctx = avctx->priv_data;
850 12 GetByteContext *gbc = &ctx->gbc;
851 TextureDSPThreadContext texdsp_ctx, ctexdsp_ctx;
852 int (*decompress_tex)(AVCodecContext *avctx);
853 const char *msgcomp, *msgtext;
854 uint32_t tag;
855 12 int version_major, version_minor = 0;
856 12 int size = 0, old_type = 0;
857 int ret;
858
859 12 bytestream2_init(gbc, avpkt->data, avpkt->size);
860
861 12 avctx->pix_fmt = AV_PIX_FMT_RGBA;
862 12 avctx->colorspace = AVCOL_SPC_RGB;
863
864 12 tag = bytestream2_get_le32(gbc);
865
5/5
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 4 times.
12 switch (tag) {
866 2 case DXV_FMT_DXT1:
867 2 decompress_tex = dxv_decompress_dxt1;
868 2 texdsp_ctx.tex_funct = ctx->texdsp.dxt1_block;
869 2 texdsp_ctx.tex_ratio = 8;
870 2 texdsp_ctx.raw_ratio = 16;
871 2 msgcomp = "DXTR1";
872 2 msgtext = "DXT1";
873 2 break;
874 2 case DXV_FMT_DXT5:
875 2 decompress_tex = dxv_decompress_dxt5;
876 /* DXV misnomers DXT5, alpha is premultiplied so use DXT4 instead */
877 2 texdsp_ctx.tex_funct = ctx->texdsp.dxt4_block;
878 2 texdsp_ctx.tex_ratio = 16;
879 2 texdsp_ctx.raw_ratio = 16;
880 2 msgcomp = "DXTR5";
881 2 msgtext = "DXT5";
882 2 break;
883 2 case DXV_FMT_YCG6:
884 2 decompress_tex = dxv_decompress_ycg6;
885 2 texdsp_ctx.tex_funct = ctx->texdsp.rgtc1u_gray_block;
886 2 texdsp_ctx.tex_ratio = 8;
887 2 texdsp_ctx.raw_ratio = 4;
888 2 ctexdsp_ctx.tex_funct = ctx->texdsp.rgtc1u_gray_block;
889 2 ctexdsp_ctx.tex_ratio = 16;
890 2 ctexdsp_ctx.raw_ratio = 4;
891 2 msgcomp = "YOCOCG6";
892 2 msgtext = "YCG6";
893 2 avctx->pix_fmt = AV_PIX_FMT_YUV420P;
894 2 avctx->colorspace = AVCOL_SPC_YCOCG;
895 2 break;
896 2 case DXV_FMT_YG10:
897 2 decompress_tex = dxv_decompress_yg10;
898 2 texdsp_ctx.tex_funct = ctx->texdsp.rgtc1u_gray_block;
899 2 texdsp_ctx.tex_ratio = 16;
900 2 texdsp_ctx.raw_ratio = 4;
901 2 ctexdsp_ctx.tex_funct = ctx->texdsp.rgtc1u_gray_block;
902 2 ctexdsp_ctx.tex_ratio = 16;
903 2 ctexdsp_ctx.raw_ratio = 4;
904 2 msgcomp = "YAOCOCG10";
905 2 msgtext = "YG10";
906 2 avctx->pix_fmt = AV_PIX_FMT_YUVA420P;
907 2 avctx->colorspace = AVCOL_SPC_YCOCG;
908 2 break;
909 4 default:
910 /* Old version does not have a real header, just size and type. */
911 4 size = tag & 0x00FFFFFF;
912 4 old_type = tag >> 24;
913 4 version_major = (old_type & 0x0F) - 1;
914
915
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (old_type & 0x80) {
916 msgcomp = "RAW";
917 decompress_tex = dxv_decompress_raw;
918 } else {
919 4 msgcomp = "LZF";
920 4 decompress_tex = dxv_decompress_lzf;
921 }
922
923
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (old_type & 0x40) {
924 2 tag = DXV_FMT_DXT5;
925 2 msgtext = "DXT5";
926
927 2 texdsp_ctx.tex_funct = ctx->texdsp.dxt4_block;
928 2 texdsp_ctx.tex_ratio = 16;
929 2 texdsp_ctx.raw_ratio = 16;
930
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
2 } else if (old_type & 0x20 || version_major == 1) {
931 2 tag = DXV_FMT_DXT1;
932 2 msgtext = "DXT1";
933
934 2 texdsp_ctx.tex_funct = ctx->texdsp.dxt1_block;
935 2 texdsp_ctx.tex_ratio = 8;
936 2 texdsp_ctx.raw_ratio = 16;
937 } else {
938 av_log(avctx, AV_LOG_ERROR, "Unsupported header (0x%08"PRIX32")\n.", tag);
939 return AVERROR_INVALIDDATA;
940 }
941 4 break;
942 }
943
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (avctx->coded_height / 2 / TEXTURE_BLOCK_H < 1)
944 return AVERROR_INVALIDDATA;
945
946 12 texdsp_ctx.slice_count = av_clip(avctx->thread_count, 1,
947 12 avctx->coded_height / TEXTURE_BLOCK_H);
948 12 ctexdsp_ctx.slice_count = av_clip(avctx->thread_count, 1,
949 12 avctx->coded_height / 2 / TEXTURE_BLOCK_H);
950
951 /* New header is 12 bytes long. */
952
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 4 times.
12 if (!old_type) {
953 8 version_major = bytestream2_get_byte(gbc) - 1;
954 8 version_minor = bytestream2_get_byte(gbc);
955
956 /* Encoder copies texture data when compression is not advantageous. */
957
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 if (bytestream2_get_byte(gbc)) {
958 msgcomp = "RAW";
959 decompress_tex = dxv_decompress_raw;
960 }
961
962 8 bytestream2_skip(gbc, 1); // unknown
963 8 size = bytestream2_get_le32(gbc);
964 }
965 12 av_log(avctx, AV_LOG_DEBUG,
966 "%s compression with %s texture (version %d.%d)\n",
967 msgcomp, msgtext, version_major, version_minor);
968
969
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
12 if (size != bytestream2_get_bytes_left(gbc)) {
970 av_log(avctx, AV_LOG_ERROR,
971 "Incomplete or invalid file (header %d, left %u).\n",
972 size, bytestream2_get_bytes_left(gbc));
973 return AVERROR_INVALIDDATA;
974 }
975
976
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 4 times.
12 ctx->tex_size = avctx->coded_width / (texdsp_ctx.raw_ratio / (avctx->pix_fmt == AV_PIX_FMT_RGBA ? 4 : 1)) *
977 12 avctx->coded_height / TEXTURE_BLOCK_H *
978 12 texdsp_ctx.tex_ratio;
979 12 unsigned old_size = ctx->tex_data_size;
980 12 void *ptr = av_fast_realloc(ctx->tex_data, &ctx->tex_data_size, ctx->tex_size + AV_INPUT_BUFFER_PADDING_SIZE);
981
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (!ptr)
982 return AVERROR(ENOMEM);
983 12 ctx->tex_data = ptr;
984
985
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 if (ctx->tex_data_size > old_size)
986 12 memset(ctx->tex_data + old_size, 0, ctx->tex_data_size - old_size);
987
988
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 8 times.
12 if (avctx->pix_fmt != AV_PIX_FMT_RGBA) {
989 int i;
990
991 4 ctx->ctex_size = avctx->coded_width / 2 / ctexdsp_ctx.raw_ratio *
992 4 avctx->coded_height / 2 / TEXTURE_BLOCK_H *
993 4 ctexdsp_ctx.tex_ratio;
994
995 4 ctx->op_size[0] = avctx->coded_width * avctx->coded_height / 16;
996 4 ctx->op_size[1] = avctx->coded_width * avctx->coded_height / 32;
997 4 ctx->op_size[2] = avctx->coded_width * avctx->coded_height / 32;
998 4 ctx->op_size[3] = avctx->coded_width * avctx->coded_height / 16;
999
1000 4 old_size = ctx->ctex_data_size;
1001 4 ptr = av_fast_realloc(ctx->ctex_data, &ctx->ctex_data_size, ctx->ctex_size + AV_INPUT_BUFFER_PADDING_SIZE);
1002
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!ptr)
1003 return AVERROR(ENOMEM);
1004 4 ctx->ctex_data = ptr;
1005
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (old_size < ctx->ctex_data_size)
1006 4 memset(ctx->ctex_data + old_size, 0, ctx->ctex_data_size - old_size);
1007
1008
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 4 times.
20 for (i = 0; i < 4; i++) {
1009 16 old_size = ctx->op_data_size[i];
1010 16 ptr = av_fast_realloc(ctx->op_data[i], &ctx->op_data_size[i], ctx->op_size[i]);
1011
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (!ptr)
1012 return AVERROR(ENOMEM);
1013 16 ctx->op_data[i] = ptr;
1014 }
1015 }
1016
1017 /* Decompress texture out of the intermediate compression. */
1018 12 ret = decompress_tex(avctx);
1019
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (ret < 0)
1020 return ret;
1021
1022 12 ret = ff_thread_get_buffer(avctx, frame, 0);
1023
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (ret < 0)
1024 return ret;
1025
1026 12 texdsp_ctx.width = avctx->coded_width;
1027 12 texdsp_ctx.height = avctx->coded_height;
1028 12 ctexdsp_ctx.width = avctx->coded_width / 2;
1029 12 ctexdsp_ctx.height = avctx->coded_height / 2;
1030
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
12 switch (tag) {
1031 2 case DXV_FMT_YG10:
1032 /* BC5 texture with alpha in the second half of each block */
1033 2 texdsp_ctx.tex_data.in = ctx->tex_data + texdsp_ctx.tex_ratio / 2;
1034 2 texdsp_ctx.frame_data.out = frame->data[3];
1035 2 texdsp_ctx.stride = frame->linesize[3];
1036 2 ret = ff_texturedsp_exec_decompress_threads(avctx, &texdsp_ctx);
1037
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0)
1038 return ret;
1039 /* fallthrough */
1040 case DXV_FMT_YCG6:
1041 /* BC5 texture with Co in the first half of each block and Cg in the second */
1042 4 ctexdsp_ctx.tex_data.in = ctx->ctex_data;
1043 4 ctexdsp_ctx.frame_data.out = frame->data[2];
1044 4 ctexdsp_ctx.stride = frame->linesize[2];
1045 4 ret = ff_texturedsp_exec_decompress_threads(avctx, &ctexdsp_ctx);
1046
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ret < 0)
1047 return ret;
1048 4 ctexdsp_ctx.tex_data.in = ctx->ctex_data + ctexdsp_ctx.tex_ratio / 2;
1049 4 ctexdsp_ctx.frame_data.out = frame->data[1];
1050 4 ctexdsp_ctx.stride = frame->linesize[1];
1051 4 ret = ff_texturedsp_exec_decompress_threads(avctx, &ctexdsp_ctx);
1052
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ret < 0)
1053 return ret;
1054 /* fallthrough */
1055 case DXV_FMT_DXT1:
1056 case DXV_FMT_DXT5:
1057 /* For DXT1 and DXT5, self explanatory
1058 * For YCG6, BC4 texture for Y
1059 * For YG10, BC5 texture with Y in the first half of each block */
1060 12 texdsp_ctx.tex_data.in = ctx->tex_data;
1061 12 texdsp_ctx.frame_data.out = frame->data[0];
1062 12 texdsp_ctx.stride = frame->linesize[0];
1063 12 ret = ff_texturedsp_exec_decompress_threads(avctx, &texdsp_ctx);
1064
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (ret < 0)
1065 return ret;
1066 12 break;
1067 }
1068
1069 /* Frame is ready to be output. */
1070 12 *got_frame = 1;
1071
1072 12 return avpkt->size;
1073 }
1074
1075 12 static av_cold int dxv_init(AVCodecContext *avctx)
1076 {
1077 12 DXVContext *ctx = avctx->priv_data;
1078 12 int ret = av_image_check_size(avctx->width, avctx->height, 0, avctx);
1079
1080
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (ret < 0) {
1081 av_log(avctx, AV_LOG_ERROR, "Invalid image size %dx%d.\n",
1082 avctx->width, avctx->height);
1083 return ret;
1084 }
1085
1086 /* Since codec is based on 4x4 blocks, size is aligned to 4 */
1087 12 avctx->coded_width = FFALIGN(avctx->width, TEXTURE_BLOCK_W);
1088 12 avctx->coded_height = FFALIGN(avctx->height, TEXTURE_BLOCK_H);
1089
1090 12 ff_texturedsp_init(&ctx->texdsp);
1091
1092 12 return 0;
1093 }
1094
1095 12 static av_cold int dxv_close(AVCodecContext *avctx)
1096 {
1097 12 DXVContext *ctx = avctx->priv_data;
1098
1099 12 av_freep(&ctx->tex_data);
1100 12 ctx->tex_data_size = 0;
1101
1102 12 av_freep(&ctx->ctex_data);
1103 12 ctx->ctex_data_size = 0;
1104
1105 12 av_freep(&ctx->op_data[0]);
1106 12 av_freep(&ctx->op_data[1]);
1107 12 av_freep(&ctx->op_data[2]);
1108 12 av_freep(&ctx->op_data[3]);
1109 12 memset(ctx->op_data_size, 0, sizeof(ctx->op_data_size));
1110
1111 12 return 0;
1112 }
1113
1114 const FFCodec ff_dxv_decoder = {
1115 .p.name = "dxv",
1116 CODEC_LONG_NAME("Resolume DXV"),
1117 .p.type = AVMEDIA_TYPE_VIDEO,
1118 .p.id = AV_CODEC_ID_DXV,
1119 .init = dxv_init,
1120 FF_CODEC_DECODE_CB(dxv_decode),
1121 .close = dxv_close,
1122 .priv_data_size = sizeof(DXVContext),
1123 .p.capabilities = AV_CODEC_CAP_DR1 |
1124 AV_CODEC_CAP_SLICE_THREADS |
1125 AV_CODEC_CAP_FRAME_THREADS,
1126 .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
1127 };
1128