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 |