FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/dxv.c
Date: 2024-11-20 23:03:26
Exec Total Coverage
Lines: 626 728 86.0%
Functions: 15 16 93.8%
Branches: 230 348 66.1%

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