FFmpeg
dxv.c
Go to the documentation of this file.
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 {
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 
89 {
90  DXVContext *ctx = avctx->priv_data;
91  GetByteContext *gbc = &ctx->gbc;
92  uint32_t value, prev, op;
93  int idx = 0, state = 0;
94  int pos = 2;
95 
96  /* Copy the first two elements */
97  AV_WL32(ctx->tex_data, bytestream2_get_le32(gbc));
98  AV_WL32(ctx->tex_data + 4, bytestream2_get_le32(gbc));
99 
100  /* Process input until the whole texture has been filled */
101  while (pos + 2 <= ctx->tex_size / 4) {
102  CHECKPOINT(2);
103 
104  /* Copy two elements from a previous offset or from the input buffer */
105  if (op) {
106  prev = AV_RL32(ctx->tex_data + 4 * (pos - idx));
107  AV_WL32(ctx->tex_data + 4 * pos, prev);
108  pos++;
109 
110  prev = AV_RL32(ctx->tex_data + 4 * (pos - idx));
111  AV_WL32(ctx->tex_data + 4 * pos, prev);
112  pos++;
113  } else {
114  CHECKPOINT(2);
115 
116  if (op)
117  prev = AV_RL32(ctx->tex_data + 4 * (pos - idx));
118  else
119  prev = bytestream2_get_le32(gbc);
120  AV_WL32(ctx->tex_data + 4 * pos, prev);
121  pos++;
122 
123  CHECKPOINT(2);
124 
125  if (op)
126  prev = AV_RL32(ctx->tex_data + 4 * (pos - idx));
127  else
128  prev = bytestream2_get_le32(gbc);
129  AV_WL32(ctx->tex_data + 4 * pos, prev);
130  pos++;
131  }
132  }
133 
134  return 0;
135 }
136 
137 typedef struct OpcodeTable {
138  int16_t next;
139  uint8_t val1;
140  uint8_t val2;
141 } OpcodeTable;
142 
143 static int fill_ltable(GetByteContext *gb, uint32_t *table, int *nb_elements)
144 {
145  unsigned half = 512, bits = 1023, left = 1024, input, mask;
146  int value, counter = 0, rshift = 10, lshift = 30;
147 
148  mask = bytestream2_get_le32(gb) >> 2;
149  while (left) {
150  if (counter >= 256)
151  return AVERROR_INVALIDDATA;
152  value = bits & mask;
153  left -= bits & mask;
154  mask >>= rshift;
155  lshift -= rshift;
156  table[counter++] = value;
157  if (lshift < 16) {
158  if (bytestream2_get_bytes_left(gb) <= 0)
159  return AVERROR_INVALIDDATA;
160 
161  input = bytestream2_get_le16(gb);
162  mask += input << lshift;
163  lshift += 16;
164  }
165  if (left < half) {
166  half >>= 1;
167  bits >>= 1;
168  rshift--;
169  }
170  }
171 
172  for (; !table[counter - 1]; counter--)
173  if (counter <= 0)
174  return AVERROR_INVALIDDATA;
175 
176  *nb_elements = counter;
177 
178  if (counter < 256)
179  memset(&table[counter], 0, 4 * (256 - counter));
180 
181  if (lshift >= 16)
182  bytestream2_seek(gb, -2, SEEK_CUR);
183 
184  return 0;
185 }
186 
187 static int fill_optable(unsigned *table0, OpcodeTable *table1, int nb_elements)
188 {
189  unsigned table2[256] = { 0 };
190  unsigned x = 0;
191  int val0, val1, i, j = 2, k = 0;
192 
193  table2[0] = table0[0];
194  for (i = 0; i < nb_elements - 1; i++, table2[i] = val0) {
195  val0 = table0[i + 1] + table2[i];
196  }
197 
198  if (!table2[0]) {
199  do {
200  k++;
201  } while (!table2[k]);
202  }
203 
204  j = 2;
205  for (i = 1024; i > 0; i--) {
206  for (table1[x].val1 = k; k < 256 && j > table2[k]; k++);
207  x = (x - 383) & 0x3FF;
208  j++;
209  }
210 
211  if (nb_elements > 0)
212  memcpy(&table2[0], table0, 4 * nb_elements);
213 
214  for (i = 0; i < 1024; i++) {
215  val0 = table1[i].val1;
216  val1 = table2[val0];
217  table2[val0]++;
218  x = 31 - ff_clz(val1);
219  if (x > 10)
220  return AVERROR_INVALIDDATA;
221  table1[i].val2 = 10 - x;
222  table1[i].next = (val1 << table1[i].val2) - 1024;
223  }
224 
225  return 0;
226 }
227 
228 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  const uint8_t *src = gb->buffer;
236 
237  ret = fill_optable(table, optable, nb_elements);
238  if (ret < 0)
239  return ret;
240 
241  size_in_bits = bytestream2_get_le32(gb);
242  endoffset = ((size_in_bits + 7) >> 3) - 4;
243  if ((int)endoffset <= 0 || bytestream2_get_bytes_left(gb) < endoffset)
244  return AVERROR_INVALIDDATA;
245 
246  offset = endoffset;
247  next = AV_RL32(src + endoffset);
248  rshift = (((size_in_bits & 0xFF) - 1) & 7) + 15;
249  lshift = 32 - rshift;
250  idx = (next >> rshift) & 0x3FF;
251  for (i = 0; i < op_size; i++) {
252  dst[i] = optable[idx].val1;
253  val = optable[idx].val2;
254  sum = val + lshift;
255  x = (next << lshift) >> 1 >> (31 - val);
256  newoffset = offset - (sum >> 3);
257  lshift = sum & 7;
258  idx = x + optable[idx].next;
259  offset = newoffset;
260  if (offset > endoffset)
261  return AVERROR_INVALIDDATA;
262  next = AV_RL32(src + offset);
263  }
264 
265  bytestream2_skip(gb, (size_in_bits + 7 >> 3) - 4);
266 
267  return 0;
268 }
269 
270 static int dxv_decompress_opcodes(GetByteContext *gb, void *dstp, size_t op_size)
271 {
272  int pos = bytestream2_tell(gb);
273  int flag = bytestream2_peek_byte(gb);
274 
275  if ((flag & 3) == 0) {
276  bytestream2_skip(gb, 1);
277  bytestream2_get_buffer(gb, dstp, op_size);
278  } 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  int ret, elements = 0;
284 
285  ret = fill_ltable(gb, table, &elements);
286  if (ret < 0)
287  return ret;
288  ret = get_opcodes(gb, table, dstp, op_size, elements);
289  if (ret < 0)
290  return ret;
291  }
292  return bytestream2_tell(gb) - pos;
293 }
294 
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  uint8_t *dst = *dstp;
304  uint8_t *tptr0, *tptr1, *tptr3;
305  int oi = *oindex;
306  int state = *statep;
307  int opcode, v, vv;
308 
309  if (state <= 0) {
310  if (oi >= op_size)
311  return AVERROR_INVALIDDATA;
312  opcode = op_data[oi++];
313  if (!opcode) {
314  v = bytestream2_get_byte(gb);
315  if (v == 255) {
316  do {
317  if (bytestream2_get_bytes_left(gb) <= 0)
318  return AVERROR_INVALIDDATA;
319  opcode = bytestream2_get_le16(gb);
320  v += opcode;
321  } while (opcode == 0xFFFF);
322  }
323  AV_WL32(dst, AV_RL32(dst - (8 + offset)));
324  AV_WL32(dst + 4, AV_RL32(dst - (4 + offset)));
325  state = v + 4;
326  goto done;
327  }
328 
329  switch (opcode) {
330  case 1:
331  AV_WL32(dst, AV_RL32(dst - (8 + offset)));
332  AV_WL32(dst + 4, AV_RL32(dst - (4 + offset)));
333  break;
334  case 2:
335  vv = (8 + offset) * (bytestream2_get_le16(gb) + 1);
336  if (vv < 0 || vv > dst - tex_data)
337  return AVERROR_INVALIDDATA;
338  tptr0 = dst - vv;
339  v = AV_RL32(tptr0);
340  AV_WL32(dst, AV_RL32(tptr0));
341  AV_WL32(dst + 4, AV_RL32(tptr0 + 4));
342  tab0[0x9E3779B1 * (uint16_t)v >> 24] = dst;
343  tab1[0x9E3779B1 * (AV_RL32(dst + 2) & 0xFFFFFFu) >> 24] = dst + 2;
344  break;
345  case 3:
346  AV_WL32(dst, bytestream2_get_le32(gb));
347  AV_WL32(dst + 4, bytestream2_get_le32(gb));
348  tab0[0x9E3779B1 * AV_RL16(dst) >> 24] = dst;
349  tab1[0x9E3779B1 * (AV_RL32(dst + 2) & 0xFFFFFFu) >> 24] = dst + 2;
350  break;
351  case 4:
352  tptr3 = tab1[bytestream2_get_byte(gb)];
353  if (!tptr3)
354  return AVERROR_INVALIDDATA;
355  AV_WL16(dst, bytestream2_get_le16(gb));
356  AV_WL16(dst + 2, AV_RL16(tptr3));
357  dst[4] = tptr3[2];
358  AV_WL16(dst + 5, bytestream2_get_le16(gb));
359  dst[7] = bytestream2_get_byte(gb);
360  tab0[0x9E3779B1 * AV_RL16(dst) >> 24] = dst;
361  break;
362  case 5:
363  tptr3 = tab1[bytestream2_get_byte(gb)];
364  if (!tptr3)
365  return AVERROR_INVALIDDATA;
366  AV_WL16(dst, bytestream2_get_le16(gb));
367  AV_WL16(dst + 2, bytestream2_get_le16(gb));
368  dst[4] = bytestream2_get_byte(gb);
369  AV_WL16(dst + 5, AV_RL16(tptr3));
370  dst[7] = tptr3[2];
371  tab0[0x9E3779B1 * AV_RL16(dst) >> 24] = dst;
372  tab1[0x9E3779B1 * (AV_RL32(dst + 2) & 0xFFFFFFu) >> 24] = dst + 2;
373  break;
374  case 6:
375  tptr0 = tab1[bytestream2_get_byte(gb)];
376  if (!tptr0)
377  return AVERROR_INVALIDDATA;
378  tptr1 = tab1[bytestream2_get_byte(gb)];
379  if (!tptr1)
380  return AVERROR_INVALIDDATA;
381  AV_WL16(dst, bytestream2_get_le16(gb));
382  AV_WL16(dst + 2, AV_RL16(tptr0));
383  dst[4] = tptr0[2];
384  AV_WL16(dst + 5, AV_RL16(tptr1));
385  dst[7] = tptr1[2];
386  tab0[0x9E3779B1 * AV_RL16(dst) >> 24] = dst;
387  break;
388  case 7:
389  v = (8 + offset) * (bytestream2_get_le16(gb) + 1);
390  if (v < 0 || v > dst - tex_data)
391  return AVERROR_INVALIDDATA;
392  tptr0 = dst - v;
393  AV_WL16(dst, bytestream2_get_le16(gb));
394  AV_WL16(dst + 2, AV_RL16(tptr0 + 2));
395  AV_WL32(dst + 4, AV_RL32(tptr0 + 4));
396  tab0[0x9E3779B1 * AV_RL16(dst) >> 24] = dst;
397  tab1[0x9E3779B1 * (AV_RL32(dst + 2) & 0xFFFFFFu) >> 24] = dst + 2;
398  break;
399  case 8:
400  tptr1 = tab0[bytestream2_get_byte(gb)];
401  if (!tptr1)
402  return AVERROR_INVALIDDATA;
403  AV_WL16(dst, AV_RL16(tptr1));
404  AV_WL16(dst + 2, bytestream2_get_le16(gb));
405  AV_WL32(dst + 4, bytestream2_get_le32(gb));
406  tab1[0x9E3779B1 * (AV_RL32(dst + 2) & 0xFFFFFFu) >> 24] = dst + 2;
407  break;
408  case 9:
409  tptr1 = tab0[bytestream2_get_byte(gb)];
410  if (!tptr1)
411  return AVERROR_INVALIDDATA;
412  tptr3 = tab1[bytestream2_get_byte(gb)];
413  if (!tptr3)
414  return AVERROR_INVALIDDATA;
415  AV_WL16(dst, AV_RL16(tptr1));
416  AV_WL16(dst + 2, AV_RL16(tptr3));
417  dst[4] = tptr3[2];
418  AV_WL16(dst + 5, bytestream2_get_le16(gb));
419  dst[7] = bytestream2_get_byte(gb);
420  tab1[0x9E3779B1 * (AV_RL32(dst + 2) & 0xFFFFFFu) >> 24] = dst + 2;
421  break;
422  case 10:
423  tptr1 = tab0[bytestream2_get_byte(gb)];
424  if (!tptr1)
425  return AVERROR_INVALIDDATA;
426  tptr3 = tab1[bytestream2_get_byte(gb)];
427  if (!tptr3)
428  return AVERROR_INVALIDDATA;
429  AV_WL16(dst, AV_RL16(tptr1));
430  AV_WL16(dst + 2, bytestream2_get_le16(gb));
431  dst[4] = bytestream2_get_byte(gb);
432  AV_WL16(dst + 5, AV_RL16(tptr3));
433  dst[7] = tptr3[2];
434  tab1[0x9E3779B1 * (AV_RL32(dst + 2) & 0xFFFFFFu) >> 24] = dst + 2;
435  break;
436  case 11:
437  tptr0 = tab0[bytestream2_get_byte(gb)];
438  if (!tptr0)
439  return AVERROR_INVALIDDATA;
440  tptr3 = tab1[bytestream2_get_byte(gb)];
441  if (!tptr3)
442  return AVERROR_INVALIDDATA;
443  tptr1 = tab1[bytestream2_get_byte(gb)];
444  if (!tptr1)
445  return AVERROR_INVALIDDATA;
446  AV_WL16(dst, AV_RL16(tptr0));
447  AV_WL16(dst + 2, AV_RL16(tptr3));
448  dst[4] = tptr3[2];
449  AV_WL16(dst + 5, AV_RL16(tptr1));
450  dst[7] = tptr1[2];
451  break;
452  case 12:
453  tptr1 = tab0[bytestream2_get_byte(gb)];
454  if (!tptr1)
455  return AVERROR_INVALIDDATA;
456  v = (8 + offset) * (bytestream2_get_le16(gb) + 1);
457  if (v < 0 || v > dst - tex_data)
458  return AVERROR_INVALIDDATA;
459  tptr0 = dst - v;
460  AV_WL16(dst, AV_RL16(tptr1));
461  AV_WL16(dst + 2, AV_RL16(tptr0 + 2));
462  AV_WL32(dst + 4, AV_RL32(tptr0 + 4));
463  tab1[0x9E3779B1 * (AV_RL32(dst + 2) & 0xFFFFFFu) >> 24] = dst + 2;
464  break;
465  case 13:
466  AV_WL16(dst, AV_RL16(dst - (8 + offset)));
467  AV_WL16(dst + 2, bytestream2_get_le16(gb));
468  AV_WL32(dst + 4, bytestream2_get_le32(gb));
469  tab1[0x9E3779B1 * (AV_RL32(dst + 2) & 0xFFFFFFu) >> 24] = dst + 2;
470  break;
471  case 14:
472  tptr3 = tab1[bytestream2_get_byte(gb)];
473  if (!tptr3)
474  return AVERROR_INVALIDDATA;
475  AV_WL16(dst, AV_RL16(dst - (8 + offset)));
476  AV_WL16(dst + 2, AV_RL16(tptr3));
477  dst[4] = tptr3[2];
478  AV_WL16(dst + 5, bytestream2_get_le16(gb));
479  dst[7] = bytestream2_get_byte(gb);
480  tab1[0x9E3779B1 * (AV_RL32(dst + 2) & 0xFFFFFFu) >> 24] = dst + 2;
481  break;
482  case 15:
483  tptr3 = tab1[bytestream2_get_byte(gb)];
484  if (!tptr3)
485  return AVERROR_INVALIDDATA;
486  AV_WL16(dst, AV_RL16(dst - (8 + offset)));
487  AV_WL16(dst + 2, bytestream2_get_le16(gb));
488  dst[4] = bytestream2_get_byte(gb);
489  AV_WL16(dst + 5, AV_RL16(tptr3));
490  dst[7] = tptr3[2];
491  tab1[0x9E3779B1 * (AV_RL32(dst + 2) & 0xFFFFFFu) >> 24] = dst + 2;
492  break;
493  case 16:
494  tptr3 = tab1[bytestream2_get_byte(gb)];
495  if (!tptr3)
496  return AVERROR_INVALIDDATA;
497  tptr1 = tab1[bytestream2_get_byte(gb)];
498  if (!tptr1)
499  return AVERROR_INVALIDDATA;
500  AV_WL16(dst, AV_RL16(dst - (8 + offset)));
501  AV_WL16(dst + 2, AV_RL16(tptr3));
502  dst[4] = tptr3[2];
503  AV_WL16(dst + 5, AV_RL16(tptr1));
504  dst[7] = tptr1[2];
505  break;
506  case 17:
507  v = (8 + offset) * (bytestream2_get_le16(gb) + 1);
508  if (v < 0 || v > dst - tex_data)
509  return AVERROR_INVALIDDATA;
510  AV_WL16(dst, AV_RL16(dst - (8 + offset)));
511  AV_WL16(dst + 2, AV_RL16(&dst[-v + 2]));
512  AV_WL32(dst + 4, AV_RL32(&dst[-v + 4]));
513  tab1[0x9E3779B1 * (AV_RL32(dst + 2) & 0xFFFFFFu) >> 24] = dst + 2;
514  break;
515  default:
516  break;
517  }
518  } else {
519 done:
520  AV_WL32(dst, AV_RL32(dst - (8 + offset)));
521  AV_WL32(dst + 4, AV_RL32(dst - (4 + offset)));
522  state--;
523  }
524  if (dst - tex_data + 8 > tex_size)
525  return AVERROR_INVALIDDATA;
526  dst += 8;
527 
528  *oindex = oi;
529  *dstp = dst;
530  *statep = state;
531 
532  return 0;
533 }
534 
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  uint8_t *dst, *tab2[256] = { 0 }, *tab0[256] = { 0 }, *tab3[256] = { 0 }, *tab1[256] = { 0 };
541  int op_offset = bytestream2_get_le32(gb);
542  unsigned op_size0 = bytestream2_get_le32(gb);
543  unsigned op_size1 = bytestream2_get_le32(gb);
544  int data_start = bytestream2_tell(gb);
545  int skip0, skip1, oi0 = 0, oi1 = 0;
546  int ret, state0 = 0, state1 = 0;
547 
548  if (op_offset < 12 || op_offset - 12 > bytestream2_get_bytes_left(gb))
549  return AVERROR_INVALIDDATA;
550 
551  dst = tex_data;
552  bytestream2_skip(gb, op_offset - 12);
553  if (op_size0 > max_op_size0)
554  return AVERROR_INVALIDDATA;
555  skip0 = dxv_decompress_opcodes(gb, op_data0, op_size0);
556  if (skip0 < 0)
557  return skip0;
558  if (op_size1 > max_op_size1)
559  return AVERROR_INVALIDDATA;
560  skip1 = dxv_decompress_opcodes(gb, op_data1, op_size1);
561  if (skip1 < 0)
562  return skip1;
563  bytestream2_seek(gb, data_start, SEEK_SET);
564 
565  AV_WL32(dst, bytestream2_get_le32(gb));
566  AV_WL32(dst + 4, bytestream2_get_le32(gb));
567  AV_WL32(dst + 8, bytestream2_get_le32(gb));
568  AV_WL32(dst + 12, bytestream2_get_le32(gb));
569 
570  tab0[0x9E3779B1 * AV_RL16(dst) >> 24] = dst;
571  tab1[0x9E3779B1 * (AV_RL32(dst + 2) & 0xFFFFFF) >> 24] = dst + 2;
572  tab2[0x9E3779B1 * AV_RL16(dst + 8) >> 24] = dst + 8;
573  tab3[0x9E3779B1 * (AV_RL32(dst + 10) & 0xFFFFFF) >> 24] = dst + 10;
574  dst += 16;
575  while (dst + 10 < tex_data + tex_size) {
576  ret = dxv_decompress_cgo(ctx, gb, tex_data, tex_size, op_data0, &oi0, op_size0,
577  &dst, &state0, tab0, tab1, 8);
578  if (ret < 0)
579  return ret;
580  ret = dxv_decompress_cgo(ctx, gb, tex_data, tex_size, op_data1, &oi1, op_size1,
581  &dst, &state1, tab2, tab3, 8);
582  if (ret < 0)
583  return ret;
584  }
585 
586  bytestream2_seek(gb, data_start - 12 + op_offset + skip0 + skip1, SEEK_SET);
587 
588  return 0;
589 }
590 
592  uint8_t *tex_data, int tex_size,
593  uint8_t *op_data, int max_op_size)
594 {
595  int op_offset = bytestream2_get_le32(gb);
596  unsigned op_size = bytestream2_get_le32(gb);
597  int data_start = bytestream2_tell(gb);
598  uint8_t *dst, *table0[256] = { 0 }, *table1[256] = { 0 };
599  int ret, state = 0, skip, oi = 0, v, vv;
600 
601  if (op_offset < 8 || op_offset - 8 > bytestream2_get_bytes_left(gb))
602  return AVERROR_INVALIDDATA;
603 
604  dst = tex_data;
605  bytestream2_skip(gb, op_offset - 8);
606  if (op_size > max_op_size)
607  return AVERROR_INVALIDDATA;
608  skip = dxv_decompress_opcodes(gb, op_data, op_size);
609  if (skip < 0)
610  return skip;
611  bytestream2_seek(gb, data_start, SEEK_SET);
612 
613  v = bytestream2_get_le32(gb);
614  AV_WL32(dst, v);
615  vv = bytestream2_get_le32(gb);
616  table0[0x9E3779B1 * (uint16_t)v >> 24] = dst;
617  AV_WL32(dst + 4, vv);
618  table1[0x9E3779B1 * (AV_RL32(dst + 2) & 0xFFFFFF) >> 24] = dst + 2;
619  dst += 8;
620 
621  while (dst < tex_data + tex_size) {
622  ret = dxv_decompress_cgo(ctx, gb, tex_data, tex_size, op_data, &oi, op_size,
623  &dst, &state, table0, table1, 0);
624  if (ret < 0)
625  return ret;
626  }
627 
628  bytestream2_seek(gb, data_start + op_offset + skip - 8, SEEK_SET);
629 
630  return 0;
631 }
632 
634 {
635  DXVContext *ctx = avctx->priv_data;
636  GetByteContext *gb = &ctx->gbc;
637  int ret;
638 
639  ret = dxv_decompress_yo(ctx, gb, ctx->tex_data, ctx->tex_size,
640  ctx->op_data[0], ctx->op_size[0]);
641  if (ret < 0)
642  return ret;
643 
644  return dxv_decompress_cocg(ctx, gb, ctx->ctex_data, ctx->ctex_size,
645  ctx->op_data[1], ctx->op_data[2],
646  ctx->op_size[1], ctx->op_size[2]);
647 }
648 
650 {
651  DXVContext *ctx = avctx->priv_data;
652  GetByteContext *gb = &ctx->gbc;
653  int ret;
654 
655  ret = dxv_decompress_cocg(ctx, gb, ctx->tex_data, ctx->tex_size,
656  ctx->op_data[0], ctx->op_data[3],
657  ctx->op_size[0], ctx->op_size[3]);
658  if (ret < 0)
659  return ret;
660 
661  return dxv_decompress_cocg(ctx, gb, ctx->ctex_data, ctx->ctex_size,
662  ctx->op_data[1], ctx->op_data[2],
663  ctx->op_size[1], ctx->op_size[2]);
664 }
665 
667 {
668  DXVContext *ctx = avctx->priv_data;
669  GetByteContext *gbc = &ctx->gbc;
670  uint32_t value, op, prev;
671  int idx, state = 0;
672  int pos = 4;
673  int run = 0;
674  int probe, check;
675 
676  /* Copy the first four elements */
677  AV_WL32(ctx->tex_data + 0, bytestream2_get_le32(gbc));
678  AV_WL32(ctx->tex_data + 4, bytestream2_get_le32(gbc));
679  AV_WL32(ctx->tex_data + 8, bytestream2_get_le32(gbc));
680  AV_WL32(ctx->tex_data + 12, bytestream2_get_le32(gbc));
681 
682  /* Process input until the whole texture has been filled */
683  while (pos + 2 <= ctx->tex_size / 4) {
684  if (run) {
685  run--;
686 
687  prev = AV_RL32(ctx->tex_data + 4 * (pos - 4));
688  AV_WL32(ctx->tex_data + 4 * pos, prev);
689  pos++;
690  prev = AV_RL32(ctx->tex_data + 4 * (pos - 4));
691  AV_WL32(ctx->tex_data + 4 * pos, prev);
692  pos++;
693  } else {
694  if (bytestream2_get_bytes_left(gbc) < 1)
695  return AVERROR_INVALIDDATA;
696  if (state == 0) {
697  value = bytestream2_get_le32(gbc);
698  state = 16;
699  }
700  op = value & 0x3;
701  value >>= 2;
702  state--;
703 
704  switch (op) {
705  case 0:
706  /* Long copy */
707  check = bytestream2_get_byte(gbc) + 1;
708  if (check == 256) {
709  do {
710  probe = bytestream2_get_le16(gbc);
711  check += probe;
712  } while (probe == 0xFFFF);
713  }
714  while (check && pos + 4 <= ctx->tex_size / 4) {
715  prev = AV_RL32(ctx->tex_data + 4 * (pos - 4));
716  AV_WL32(ctx->tex_data + 4 * pos, prev);
717  pos++;
718 
719  prev = AV_RL32(ctx->tex_data + 4 * (pos - 4));
720  AV_WL32(ctx->tex_data + 4 * pos, prev);
721  pos++;
722 
723  prev = AV_RL32(ctx->tex_data + 4 * (pos - 4));
724  AV_WL32(ctx->tex_data + 4 * pos, prev);
725  pos++;
726 
727  prev = AV_RL32(ctx->tex_data + 4 * (pos - 4));
728  AV_WL32(ctx->tex_data + 4 * pos, prev);
729  pos++;
730 
731  check--;
732  }
733 
734  /* Restart (or exit) the loop */
735  continue;
736  break;
737  case 1:
738  /* Load new run value */
739  run = bytestream2_get_byte(gbc);
740  if (run == 255) {
741  do {
742  probe = bytestream2_get_le16(gbc);
743  run += probe;
744  } while (probe == 0xFFFF);
745  }
746 
747  /* Copy two dwords from previous data */
748  prev = AV_RL32(ctx->tex_data + 4 * (pos - 4));
749  AV_WL32(ctx->tex_data + 4 * pos, prev);
750  pos++;
751 
752  prev = AV_RL32(ctx->tex_data + 4 * (pos - 4));
753  AV_WL32(ctx->tex_data + 4 * pos, prev);
754  pos++;
755  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  CHECKPOINT(4);
783  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  if (op) {
788  if (idx > pos || (unsigned int)(pos - idx) + 2 > ctx->tex_size / 4)
789  return AVERROR_INVALIDDATA;
790  prev = AV_RL32(ctx->tex_data + 4 * (pos - idx));
791  AV_WL32(ctx->tex_data + 4 * pos, prev);
792  pos++;
793 
794  prev = AV_RL32(ctx->tex_data + 4 * (pos - idx));
795  AV_WL32(ctx->tex_data + 4 * pos, prev);
796  pos++;
797  } else {
798  CHECKPOINT(4);
799 
800  if (op && (idx > pos || (unsigned int)(pos - idx) + 2 > ctx->tex_size / 4))
801  return AVERROR_INVALIDDATA;
802  if (op)
803  prev = AV_RL32(ctx->tex_data + 4 * (pos - idx));
804  else
805  prev = bytestream2_get_le32(gbc);
806  AV_WL32(ctx->tex_data + 4 * pos, prev);
807  pos++;
808 
809  CHECKPOINT(4);
810 
811  if (op)
812  prev = AV_RL32(ctx->tex_data + 4 * (pos - idx));
813  else
814  prev = bytestream2_get_le32(gbc);
815  AV_WL32(ctx->tex_data + 4 * pos, prev);
816  pos++;
817  }
818  }
819 
820  return 0;
821 }
822 
824 {
825  DXVContext *ctx = avctx->priv_data;
826  return ff_lzf_uncompress(&ctx->gbc, &ctx->tex_data, &ctx->tex_size);
827 }
828 
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 
842  int *got_frame, AVPacket *avpkt)
843 {
844  DXVContext *ctx = avctx->priv_data;
845  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  int version_major, version_minor = 0;
851  int size = 0, old_type = 0;
852  int ret;
853 
854  bytestream2_init(gbc, avpkt->data, avpkt->size);
855 
856  avctx->pix_fmt = AV_PIX_FMT_RGBA;
857  avctx->colorspace = AVCOL_SPC_RGB;
858 
859  tag = bytestream2_get_le32(gbc);
860  switch (tag) {
861  case DXV_FMT_DXT1:
862  decompress_tex = dxv_decompress_dxt1;
863  texdsp_ctx.tex_funct = ctx->texdsp.dxt1_block;
864  texdsp_ctx.tex_ratio = 8;
865  texdsp_ctx.raw_ratio = 16;
866  msgcomp = "DXTR1";
867  msgtext = "DXT1";
868  break;
869  case DXV_FMT_DXT5:
870  decompress_tex = dxv_decompress_dxt5;
871  /* DXV misnomers DXT5, alpha is premultiplied so use DXT4 instead */
872  texdsp_ctx.tex_funct = ctx->texdsp.dxt4_block;
873  texdsp_ctx.tex_ratio = 16;
874  texdsp_ctx.raw_ratio = 16;
875  msgcomp = "DXTR5";
876  msgtext = "DXT5";
877  break;
878  case DXV_FMT_YCG6:
879  decompress_tex = dxv_decompress_ycg6;
880  texdsp_ctx.tex_funct = ctx->texdsp.rgtc1u_gray_block;
881  texdsp_ctx.tex_ratio = 8;
882  texdsp_ctx.raw_ratio = 4;
883  ctexdsp_ctx.tex_funct = ctx->texdsp.rgtc1u_gray_block;
884  ctexdsp_ctx.tex_ratio = 16;
885  ctexdsp_ctx.raw_ratio = 4;
886  msgcomp = "YOCOCG6";
887  msgtext = "YCG6";
888  avctx->pix_fmt = AV_PIX_FMT_YUV420P;
889  avctx->colorspace = AVCOL_SPC_YCOCG;
890  break;
891  case DXV_FMT_YG10:
892  decompress_tex = dxv_decompress_yg10;
893  texdsp_ctx.tex_funct = ctx->texdsp.rgtc1u_gray_block;
894  texdsp_ctx.tex_ratio = 16;
895  texdsp_ctx.raw_ratio = 4;
896  ctexdsp_ctx.tex_funct = ctx->texdsp.rgtc1u_gray_block;
897  ctexdsp_ctx.tex_ratio = 16;
898  ctexdsp_ctx.raw_ratio = 4;
899  msgcomp = "YAOCOCG10";
900  msgtext = "YG10";
901  avctx->pix_fmt = AV_PIX_FMT_YUVA420P;
902  avctx->colorspace = AVCOL_SPC_YCOCG;
903  break;
904  default:
905  /* Old version does not have a real header, just size and type. */
906  size = tag & 0x00FFFFFF;
907  old_type = tag >> 24;
908  version_major = (old_type & 0x0F) - 1;
909 
910  if (old_type & 0x80) {
911  msgcomp = "RAW";
912  decompress_tex = dxv_decompress_raw;
913  } else {
914  msgcomp = "LZF";
915  decompress_tex = dxv_decompress_lzf;
916  }
917 
918  if (old_type & 0x40) {
919  tag = DXV_FMT_DXT5;
920  msgtext = "DXT5";
921 
922  texdsp_ctx.tex_funct = ctx->texdsp.dxt4_block;
923  texdsp_ctx.tex_ratio = 16;
924  texdsp_ctx.raw_ratio = 16;
925  } else if (old_type & 0x20 || version_major == 1) {
926  tag = DXV_FMT_DXT1;
927  msgtext = "DXT1";
928 
929  texdsp_ctx.tex_funct = ctx->texdsp.dxt1_block;
930  texdsp_ctx.tex_ratio = 8;
931  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  break;
937  }
938 
939  texdsp_ctx.slice_count = av_clip(avctx->thread_count, 1,
940  avctx->coded_height / TEXTURE_BLOCK_H);
941  ctexdsp_ctx.slice_count = av_clip(avctx->thread_count, 1,
942  avctx->coded_height / 2 / TEXTURE_BLOCK_H);
943 
944  /* New header is 12 bytes long. */
945  if (!old_type) {
946  version_major = bytestream2_get_byte(gbc) - 1;
947  version_minor = bytestream2_get_byte(gbc);
948 
949  /* Encoder copies texture data when compression is not advantageous. */
950  if (bytestream2_get_byte(gbc)) {
951  msgcomp = "RAW";
952  decompress_tex = dxv_decompress_raw;
953  }
954 
955  bytestream2_skip(gbc, 1); // unknown
956  size = bytestream2_get_le32(gbc);
957  }
958  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  if (size != bytestream2_get_bytes_left(gbc)) {
963  av_log(avctx, AV_LOG_ERROR,
964  "Incomplete or invalid file (header %d, left %u).\n",
966  return AVERROR_INVALIDDATA;
967  }
968 
969  ctx->tex_size = avctx->coded_width / (texdsp_ctx.raw_ratio / (avctx->pix_fmt == AV_PIX_FMT_RGBA ? 4 : 1)) *
970  avctx->coded_height / TEXTURE_BLOCK_H *
971  texdsp_ctx.tex_ratio;
972  ret = av_reallocp(&ctx->tex_data, ctx->tex_size + AV_INPUT_BUFFER_PADDING_SIZE);
973  if (ret < 0)
974  return ret;
975 
976  if (avctx->pix_fmt != AV_PIX_FMT_RGBA) {
977  int i;
978 
979  ctx->ctex_size = avctx->coded_width / 2 / ctexdsp_ctx.raw_ratio *
980  avctx->coded_height / 2 / TEXTURE_BLOCK_H *
981  ctexdsp_ctx.tex_ratio;
982 
983  ctx->op_size[0] = avctx->coded_width * avctx->coded_height / 16;
984  ctx->op_size[1] = avctx->coded_width * avctx->coded_height / 32;
985  ctx->op_size[2] = avctx->coded_width * avctx->coded_height / 32;
986  ctx->op_size[3] = avctx->coded_width * avctx->coded_height / 16;
987 
988  ret = av_reallocp(&ctx->ctex_data, ctx->ctex_size + AV_INPUT_BUFFER_PADDING_SIZE);
989  if (ret < 0)
990  return ret;
991  for (i = 0; i < 4; i++) {
992  ret = av_reallocp(&ctx->op_data[i], ctx->op_size[i]);
993  if (ret < 0)
994  return ret;
995  }
996  }
997 
998  /* Decompress texture out of the intermediate compression. */
999  ret = decompress_tex(avctx);
1000  if (ret < 0)
1001  return ret;
1002 
1003  ret = ff_thread_get_buffer(avctx, frame, 0);
1004  if (ret < 0)
1005  return ret;
1006 
1007  texdsp_ctx.width = avctx->coded_width;
1008  texdsp_ctx.height = avctx->coded_height;
1009  ctexdsp_ctx.width = avctx->coded_width / 2;
1010  ctexdsp_ctx.height = avctx->coded_height / 2;
1011  switch (tag) {
1012  case DXV_FMT_YG10:
1013  /* BC5 texture with alpha in the second half of each block */
1014  texdsp_ctx.tex_data.in = ctx->tex_data + texdsp_ctx.tex_ratio / 2;
1015  texdsp_ctx.frame_data.out = frame->data[3];
1016  texdsp_ctx.stride = frame->linesize[3];
1017  ret = ff_texturedsp_exec_decompress_threads(avctx, &texdsp_ctx);
1018  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  ctexdsp_ctx.tex_data.in = ctx->ctex_data;
1024  ctexdsp_ctx.frame_data.out = frame->data[2];
1025  ctexdsp_ctx.stride = frame->linesize[2];
1026  ret = ff_texturedsp_exec_decompress_threads(avctx, &ctexdsp_ctx);
1027  if (ret < 0)
1028  return ret;
1029  ctexdsp_ctx.tex_data.in = ctx->ctex_data + ctexdsp_ctx.tex_ratio / 2;
1030  ctexdsp_ctx.frame_data.out = frame->data[1];
1031  ctexdsp_ctx.stride = frame->linesize[1];
1032  ret = ff_texturedsp_exec_decompress_threads(avctx, &ctexdsp_ctx);
1033  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  texdsp_ctx.tex_data.in = ctx->tex_data;
1042  texdsp_ctx.frame_data.out = frame->data[0];
1043  texdsp_ctx.stride = frame->linesize[0];
1044  ret = ff_texturedsp_exec_decompress_threads(avctx, &texdsp_ctx);
1045  if (ret < 0)
1046  return ret;
1047  break;
1048  }
1049 
1050  /* Frame is ready to be output. */
1051  *got_frame = 1;
1052 
1053  return avpkt->size;
1054 }
1055 
1056 static int dxv_init(AVCodecContext *avctx)
1057 {
1058  DXVContext *ctx = avctx->priv_data;
1059  int ret = av_image_check_size(avctx->width, avctx->height, 0, avctx);
1060 
1061  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  avctx->coded_width = FFALIGN(avctx->width, TEXTURE_BLOCK_W);
1069  avctx->coded_height = FFALIGN(avctx->height, TEXTURE_BLOCK_H);
1070 
1071  ff_texturedsp_init(&ctx->texdsp);
1072 
1073  return 0;
1074 }
1075 
1076 static int dxv_close(AVCodecContext *avctx)
1077 {
1078  DXVContext *ctx = avctx->priv_data;
1079 
1080  av_freep(&ctx->tex_data);
1081  av_freep(&ctx->ctex_data);
1082  av_freep(&ctx->op_data[0]);
1083  av_freep(&ctx->op_data[1]);
1084  av_freep(&ctx->op_data[2]);
1085  av_freep(&ctx->op_data[3]);
1086 
1087  return 0;
1088 }
1089 
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,
1097  .close = dxv_close,
1098  .priv_data_size = sizeof(DXVContext),
1099  .p.capabilities = AV_CODEC_CAP_DR1 |
1102  .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
1103 };
DXV_FMT_DXT5
@ DXV_FMT_DXT5
Definition: dxv.h:29
DXV_FMT_DXT1
@ DXV_FMT_DXT1
Definition: dxv.h:28
av_clip
#define av_clip
Definition: common.h:100
FF_CODEC_CAP_INIT_CLEANUP
#define FF_CODEC_CAP_INIT_CLEANUP
The codec allows calling the close function for deallocation even if the init function returned a fai...
Definition: codec_internal.h:43
AV_WL32
#define AV_WL32(p, v)
Definition: intreadwrite.h:422
AVCodecContext::colorspace
enum AVColorSpace colorspace
YUV colorspace type.
Definition: avcodec.h:691
dxv_decompress_yg10
static int dxv_decompress_yg10(AVCodecContext *avctx)
Definition: dxv.c:649
TEXTURE_BLOCK_H
#define TEXTURE_BLOCK_H
Definition: texturedsp.h:43
elements
static const ElemCat * elements[ELEMENT_COUNT]
Definition: signature.h:565
TextureDSPThreadContext::frame_data
union TextureDSPThreadContext::@234 frame_data
GetByteContext
Definition: bytestream.h:33
u
#define u(width, name, range_min, range_max)
Definition: cbs_h2645.c:251
DXVContext::ctex_data
uint8_t * ctex_data
Definition: dxv.c:41
dxv_decode
static int dxv_decode(AVCodecContext *avctx, AVFrame *frame, int *got_frame, AVPacket *avpkt)
Definition: dxv.c:841
TextureDSPThreadContext::tex_data
union TextureDSPThreadContext::@235 tex_data
fill_optable
static int fill_optable(unsigned *table0, OpcodeTable *table1, int nb_elements)
Definition: dxv.c:187
int64_t
long long int64_t
Definition: coverity.c:34
ff_clz
#define ff_clz
Definition: intmath.h:143
mask
int mask
Definition: mediacodecdec_common.c:154
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:389
bytestream2_seek
static av_always_inline int bytestream2_seek(GetByteContext *g, int offset, int whence)
Definition: bytestream.h:212
AVCOL_SPC_YCOCG
@ AVCOL_SPC_YCOCG
Definition: pixfmt.h:650
AVPacket::data
uint8_t * data
Definition: packet.h:539
TextureDSPThreadContext::tex_ratio
int tex_ratio
Definition: texturedsp.h:80
table
static const uint16_t table[]
Definition: prosumer.c:203
half
static uint8_t half(int a, int b)
Definition: mobiclip.c:539
FFCodec
Definition: codec_internal.h:127
AVCOL_SPC_RGB
@ AVCOL_SPC_RGB
order of coefficients is actually GBR, also IEC 61966-2-1 (sRGB), YZX and ST 428-1
Definition: pixfmt.h:641
TextureDSPContext
Definition: texturedsp.h:45
dxv_init
static int dxv_init(AVCodecContext *avctx)
Definition: dxv.c:1056
DXVContext::gbc
GetByteContext gbc
Definition: dxv.c:38
OpcodeTable
Definition: dxv.c:137
thread.h
DXVContext::ctex_size
int64_t ctex_size
Definition: dxv.c:44
DXVContext::tex_data
uint8_t * tex_data
Definition: dxv.c:40
CHECKPOINT
#define CHECKPOINT(x)
Definition: dxv.c:56
dxv_decompress_ycg6
static int dxv_decompress_ycg6(AVCodecContext *avctx)
Definition: dxv.c:633
bytestream2_skip
static av_always_inline void bytestream2_skip(GetByteContext *g, unsigned int size)
Definition: bytestream.h:168
texturedsp.h
FFCodec::p
AVCodec p
The public AVCodec.
Definition: codec_internal.h:131
dxv_decompress_lzf
static int dxv_decompress_lzf(AVCodecContext *avctx)
Definition: dxv.c:823
AVCodecContext::thread_count
int thread_count
thread count is used to decide how many independent tasks should be passed to execute()
Definition: avcodec.h:1593
TextureDSPThreadContext::width
int width
Definition: texturedsp.h:75
val
static double val(void *priv, double ch)
Definition: aeval.c:77
DXVContext::op_data
uint8_t * op_data[4]
Definition: dxv.c:46
tab2
const int16_t * tab2
Definition: mace.c:145
AVCodecContext::coded_height
int coded_height
Definition: avcodec.h:639
dxv_decompress_cgo
static int dxv_decompress_cgo(DXVContext *ctx, GetByteContext *gb, uint8_t *tex_data, int tex_size, uint8_t *op_data, int *oindex, int op_size, uint8_t **dstp, int *statep, uint8_t **tab0, uint8_t **tab1, int offset)
Definition: dxv.c:295
tab1
const int16_t * tab1
Definition: mace.c:145
TextureDSPThreadContext
Definition: texturedsp.h:69
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:209
check
#define check(x, y, S, v)
Definition: motion_est_template.c:405
fill_ltable
static int fill_ltable(GetByteContext *gb, uint32_t *table, int *nb_elements)
Definition: dxv.c:143
DXV_FMT_YG10
@ DXV_FMT_YG10
Definition: dxv.h:31
FF_CODEC_DECODE_CB
#define FF_CODEC_DECODE_CB(func)
Definition: codec_internal.h:311
get_opcodes
static int get_opcodes(GetByteContext *gb, uint32_t *table, uint8_t *dst, int op_size, int nb_elements)
Definition: dxv.c:228
AV_PIX_FMT_YUVA420P
@ AV_PIX_FMT_YUVA420P
planar YUV 4:2:0, 20bpp, (1 Cr & Cb sample per 2x2 Y & A samples)
Definition: pixfmt.h:108
op
static int op(uint8_t **dst, const uint8_t *dst_end, GetByteContext *gb, int pixel, int count, int *x, int width, int linesize)
Perform decode operation.
Definition: anm.c:76
ff_thread_get_buffer
int ff_thread_get_buffer(AVCodecContext *avctx, AVFrame *f, int flags)
Wrapper around get_buffer() for frame-multithreaded codecs.
Definition: pthread_frame.c:1049
GetByteContext::buffer
const uint8_t * buffer
Definition: bytestream.h:34
bits
uint8_t bits
Definition: vp3data.h:128
TextureDSPThreadContext::out
uint8_t * out
Definition: texturedsp.h:72
AV_LOG_DEBUG
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:230
ctx
AVFormatContext * ctx
Definition: movenc.c:49
ff_texturedsp_init
av_cold void ff_texturedsp_init(TextureDSPContext *c)
Definition: texturedsp.c:640
AV_RL16
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_WL32 unsigned int_TMPL AV_WL24 unsigned int_TMPL AV_RL16
Definition: bytestream.h:94
AV_PIX_FMT_YUV420P
@ AV_PIX_FMT_YUV420P
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition: pixfmt.h:73
dxv_close
static int dxv_close(AVCodecContext *avctx)
Definition: dxv.c:1076
CODEC_LONG_NAME
#define CODEC_LONG_NAME(str)
Definition: codec_internal.h:296
AV_PIX_FMT_RGBA
@ AV_PIX_FMT_RGBA
packed RGBA 8:8:8:8, 32bpp, RGBARGBA...
Definition: pixfmt.h:100
TextureDSPThreadContext::stride
ptrdiff_t stride
Definition: texturedsp.h:74
AV_CODEC_CAP_FRAME_THREADS
#define AV_CODEC_CAP_FRAME_THREADS
Codec supports frame-level multithreading.
Definition: codec.h:110
run
uint8_t run
Definition: svq3.c:204
state
static struct @466 state
dxv_decompress_dxt1
static int dxv_decompress_dxt1(AVCodecContext *avctx)
Definition: dxv.c:88
TextureDSPThreadContext::height
int height
Definition: texturedsp.h:75
bytestream2_get_buffer
static av_always_inline unsigned int bytestream2_get_buffer(GetByteContext *g, uint8_t *dst, unsigned int size)
Definition: bytestream.h:267
bytestream2_get_bytes_left
static av_always_inline int bytestream2_get_bytes_left(GetByteContext *g)
Definition: bytestream.h:158
bytestream2_tell
static av_always_inline int bytestream2_tell(GetByteContext *g)
Definition: bytestream.h:192
ff_texturedsp_exec_decompress_threads
int ff_texturedsp_exec_decompress_threads(struct AVCodecContext *avctx, TextureDSPThreadContext *ctx)
AV_CODEC_CAP_DR1
#define AV_CODEC_CAP_DR1
Codec uses get_buffer() or get_encode_buffer() for allocating buffers and supports custom allocators.
Definition: codec.h:52
AVPacket::size
int size
Definition: packet.h:540
codec_internal.h
dst
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition: dsp.h:83
DXV_FMT_YCG6
@ DXV_FMT_YCG6
Definition: dxv.h:30
AV_CODEC_ID_DXV
@ AV_CODEC_ID_DXV
Definition: codec_id.h:245
size
int size
Definition: twinvq_data.h:10344
av_reallocp
int av_reallocp(void *ptr, size_t size)
Allocate, reallocate, or free a block of memory through a pointer to a pointer.
Definition: mem.c:188
ff_lzf_uncompress
int ff_lzf_uncompress(GetByteContext *gb, uint8_t **buf, int64_t *size)
Definition: lzf.c:40
DXVContext::op_size
int64_t op_size[4]
Definition: dxv.c:47
OpcodeTable::val2
uint8_t val2
Definition: dxv.c:140
AV_WL16
#define AV_WL16(p, v)
Definition: intreadwrite.h:408
AV_CODEC_CAP_SLICE_THREADS
#define AV_CODEC_CAP_SLICE_THREADS
Codec supports slice-based (or partition-based) multithreading.
Definition: codec.h:114
offset
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf offset
Definition: writing_filters.txt:86
input
and forward the test the status of outputs and forward it to the corresponding return FFERROR_NOT_READY If the filters stores internally one or a few frame for some input
Definition: filter_design.txt:172
DXVContext
Definition: dxv.c:36
flag
#define flag(name)
Definition: cbs_av1.c:474
OpcodeTable::next
int16_t next
Definition: dxv.c:138
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
ff_dxv_decoder
const FFCodec ff_dxv_decoder
Definition: dxv.c:1090
TextureDSPThreadContext::slice_count
int slice_count
Definition: texturedsp.h:82
value
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf default value
Definition: writing_filters.txt:86
TEXTURE_BLOCK_W
#define TEXTURE_BLOCK_W
Definition: texturedsp.h:42
AVCodec::name
const char * name
Name of the codec implementation.
Definition: codec.h:194
dxv_decompress_yo
static int dxv_decompress_yo(DXVContext *ctx, GetByteContext *gb, uint8_t *tex_data, int tex_size, uint8_t *op_data, int max_op_size)
Definition: dxv.c:591
AVCodecContext::height
int height
Definition: avcodec.h:624
AVCodecContext::pix_fmt
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition: avcodec.h:663
avcodec.h
tag
uint32_t tag
Definition: movenc.c:1879
ret
ret
Definition: filter_design.txt:187
frame
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several the filter must be ready for frames arriving randomly on any input any filter with several inputs will most likely require some kind of queuing mechanism It is perfectly acceptable to have a limited queue and to drop frames when the inputs are too unbalanced request_frame For filters that do not use the this method is called when a frame is wanted on an output For a it should directly call filter_frame on the corresponding output For a if there are queued frames already one of these frames should be pushed If the filter should request a frame on one of its repeatedly until at least one frame has been pushed Return or at least make progress towards producing a frame
Definition: filter_design.txt:264
DXVContext::tex_size
int64_t tex_size
Definition: dxv.c:43
pos
unsigned int pos
Definition: spdifenc.c:414
AV_INPUT_BUFFER_PADDING_SIZE
#define AV_INPUT_BUFFER_PADDING_SIZE
Definition: defs.h:40
left
Tag MUST be and< 10hcoeff half pel interpolation filter coefficients, hcoeff[0] are the 2 middle coefficients[1] are the next outer ones and so on, resulting in a filter like:...eff[2], hcoeff[1], hcoeff[0], hcoeff[0], hcoeff[1], hcoeff[2] ... the sign of the coefficients is not explicitly stored but alternates after each coeff and coeff[0] is positive, so ...,+,-,+,-,+,+,-,+,-,+,... hcoeff[0] is not explicitly stored but found by subtracting the sum of all stored coefficients with signs from 32 hcoeff[0]=32 - hcoeff[1] - hcoeff[2] - ... a good choice for hcoeff and htaps is htaps=6 hcoeff={40,-10, 2} an alternative which requires more computations at both encoder and decoder side and may or may not be better is htaps=8 hcoeff={42,-14, 6,-2}ref_frames minimum of the number of available reference frames and max_ref_frames for example the first frame after a key frame always has ref_frames=1spatial_decomposition_type wavelet type 0 is a 9/7 symmetric compact integer wavelet 1 is a 5/3 symmetric compact integer wavelet others are reserved stored as delta from last, last is reset to 0 if always_reset||keyframeqlog quality(logarithmic quantizer scale) stored as delta from last, last is reset to 0 if always_reset||keyframemv_scale stored as delta from last, last is reset to 0 if always_reset||keyframe FIXME check that everything works fine if this changes between framesqbias dequantization bias stored as delta from last, last is reset to 0 if always_reset||keyframeblock_max_depth maximum depth of the block tree stored as delta from last, last is reset to 0 if always_reset||keyframequant_table quantization tableHighlevel bitstream structure:==============================--------------------------------------------|Header|--------------------------------------------|------------------------------------|||Block0||||split?||||yes no||||......... intra?||||:Block01 :yes no||||:Block02 :....... ..........||||:Block03 ::y DC ::ref index:||||:Block04 ::cb DC ::motion x :||||......... :cr DC ::motion y :||||....... ..........|||------------------------------------||------------------------------------|||Block1|||...|--------------------------------------------|------------ ------------ ------------|||Y subbands||Cb subbands||Cr subbands||||--- ---||--- ---||--- ---|||||LL0||HL0||||LL0||HL0||||LL0||HL0|||||--- ---||--- ---||--- ---||||--- ---||--- ---||--- ---|||||LH0||HH0||||LH0||HH0||||LH0||HH0|||||--- ---||--- ---||--- ---||||--- ---||--- ---||--- ---|||||HL1||LH1||||HL1||LH1||||HL1||LH1|||||--- ---||--- ---||--- ---||||--- ---||--- ---||--- ---|||||HH1||HL2||||HH1||HL2||||HH1||HL2|||||...||...||...|||------------ ------------ ------------|--------------------------------------------Decoding process:=================------------|||Subbands|------------||||------------|Intra DC||||LL0 subband prediction ------------|\ Dequantization ------------------- \||Reference frames|\ IDWT|------- -------|Motion \|||Frame 0||Frame 1||Compensation . OBMC v -------|------- -------|--------------. \------> Frame n output Frame Frame<----------------------------------/|...|------------------- Range Coder:============Binary Range Coder:------------------- The implemented range coder is an adapted version based upon "Range encoding: an algorithm for removing redundancy from a digitised message." by G. N. N. Martin. The symbols encoded by the Snow range coder are bits(0|1). The associated probabilities are not fix but change depending on the symbol mix seen so far. bit seen|new state ---------+----------------------------------------------- 0|256 - state_transition_table[256 - old_state];1|state_transition_table[old_state];state_transition_table={ 0, 0, 0, 0, 0, 0, 0, 0, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 190, 191, 192, 194, 194, 195, 196, 197, 198, 199, 200, 201, 202, 202, 204, 205, 206, 207, 208, 209, 209, 210, 211, 212, 213, 215, 215, 216, 217, 218, 219, 220, 220, 222, 223, 224, 225, 226, 227, 227, 229, 229, 230, 231, 232, 234, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 248, 0, 0, 0, 0, 0, 0, 0};FIXME Range Coding of integers:------------------------- FIXME Neighboring Blocks:===================left and top are set to the respective blocks unless they are outside of the image in which case they are set to the Null block top-left is set to the top left block unless it is outside of the image in which case it is set to the left block if this block has no larger parent block or it is at the left side of its parent block and the top right block is not outside of the image then the top right block is used for top-right else the top-left block is used Null block y, cb, cr are 128 level, ref, mx and my are 0 Motion Vector Prediction:=========================1. the motion vectors of all the neighboring blocks are scaled to compensate for the difference of reference frames scaled_mv=(mv *(256 *(current_reference+1)/(mv.reference+1))+128)> the median of the scaled left
Definition: snow.txt:386
AV_RL32
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_RL32
Definition: bytestream.h:92
AVCodecContext
main external API structure.
Definition: avcodec.h:451
probe
static int probe(const AVProbeData *p)
Definition: act.c:39
dxv_decompress_opcodes
static int dxv_decompress_opcodes(GetByteContext *gb, void *dstp, size_t op_size)
Definition: dxv.c:270
OpcodeTable::val1
uint8_t val1
Definition: dxv.c:139
TextureDSPThreadContext::tex_funct
int(* tex_funct)(uint8_t *dst, ptrdiff_t stride, const uint8_t *block)
Definition: texturedsp.h:85
AVCodecContext::coded_width
int coded_width
Bitstream width / height, may be different from width/height e.g.
Definition: avcodec.h:639
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
mem.h
TextureDSPThreadContext::raw_ratio
int raw_ratio
Definition: texturedsp.h:81
dxv.h
FFALIGN
#define FFALIGN(x, a)
Definition: macros.h:78
AVPacket
This structure stores compressed data.
Definition: packet.h:516
AVCodecContext::priv_data
void * priv_data
Definition: avcodec.h:478
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:34
TextureDSPThreadContext::in
const uint8_t * in
Definition: texturedsp.h:71
AVCodecContext::width
int width
picture width / height.
Definition: avcodec.h:624
bytestream.h
imgutils.h
bytestream2_init
static av_always_inline void bytestream2_init(GetByteContext *g, const uint8_t *buf, int buf_size)
Definition: bytestream.h:137
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
AVERROR_INVALIDDATA
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:61
dxv_decompress_dxt5
static int dxv_decompress_dxt5(AVCodecContext *avctx)
Definition: dxv.c:666
dxv_decompress_cocg
static int dxv_decompress_cocg(DXVContext *ctx, GetByteContext *gb, uint8_t *tex_data, int tex_size, uint8_t *op_data0, uint8_t *op_data1, int max_op_size0, int max_op_size1)
Definition: dxv.c:535
av_image_check_size
int av_image_check_size(unsigned int w, unsigned int h, int log_offset, void *log_ctx)
Check if the given dimension of an image is valid, meaning that all bytes of the image can be address...
Definition: imgutils.c:318
dxv_decompress_raw
static int dxv_decompress_raw(AVCodecContext *avctx)
Definition: dxv.c:829
lzf.h
skip
static void BS_FUNC() skip(BSCTX *bc, unsigned int n)
Skip n bits in the buffer.
Definition: bitstream_template.h:375
src
#define src
Definition: vp8dsp.c:248
DXVContext::texdsp
TextureDSPContext texdsp
Definition: dxv.c:37