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