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 |