| 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 |