FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/dxv.c
Date: 2026-05-02 03:33:10
Exec Total Coverage
Lines: 645 750 86.0%
Functions: 15 16 93.8%
Branches: 235 358 65.6%

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