FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
dxtory.c
Go to the documentation of this file.
1 /*
2  * Dxtory decoder
3  *
4  * Copyright (c) 2011 Konstantin Shishkov
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 #define BITSTREAM_READER_LE
24 #include "avcodec.h"
25 #include "bytestream.h"
26 #include "get_bits.h"
27 #include "internal.h"
28 #include "unary.h"
29 #include "libavutil/common.h"
30 #include "libavutil/intreadwrite.h"
31 
33  const uint8_t *src, int src_size,
34  int id, int bpp)
35 {
36  int h;
37  uint8_t *dst;
38  int ret;
39 
40  if (src_size < avctx->width * avctx->height * (int64_t)bpp) {
41  av_log(avctx, AV_LOG_ERROR, "packet too small\n");
42  return AVERROR_INVALIDDATA;
43  }
44 
45  avctx->pix_fmt = id;
46  if ((ret = ff_get_buffer(avctx, pic, 0)) < 0)
47  return ret;
48 
49  dst = pic->data[0];
50  for (h = 0; h < avctx->height; h++) {
51  memcpy(dst, src, avctx->width * bpp);
52  src += avctx->width * bpp;
53  dst += pic->linesize[0];
54  }
55 
56  return 0;
57 }
58 
60  const uint8_t *src, int src_size)
61 {
62  int h, w;
63  uint8_t *Y1, *Y2, *Y3, *Y4, *U, *V;
64  int ret;
65 
66  if (src_size < avctx->width * avctx->height * 9L / 8) {
67  av_log(avctx, AV_LOG_ERROR, "packet too small\n");
68  return AVERROR_INVALIDDATA;
69  }
70 
71  avctx->pix_fmt = AV_PIX_FMT_YUV410P;
72  if ((ret = ff_get_buffer(avctx, pic, 0)) < 0)
73  return ret;
74 
75  Y1 = pic->data[0];
76  Y2 = pic->data[0] + pic->linesize[0];
77  Y3 = pic->data[0] + pic->linesize[0] * 2;
78  Y4 = pic->data[0] + pic->linesize[0] * 3;
79  U = pic->data[1];
80  V = pic->data[2];
81  for (h = 0; h < avctx->height; h += 4) {
82  for (w = 0; w < avctx->width; w += 4) {
83  AV_COPY32(Y1 + w, src);
84  AV_COPY32(Y2 + w, src + 4);
85  AV_COPY32(Y3 + w, src + 8);
86  AV_COPY32(Y4 + w, src + 12);
87  U[w >> 2] = src[16] + 0x80;
88  V[w >> 2] = src[17] + 0x80;
89  src += 18;
90  }
91  Y1 += pic->linesize[0] << 2;
92  Y2 += pic->linesize[0] << 2;
93  Y3 += pic->linesize[0] << 2;
94  Y4 += pic->linesize[0] << 2;
95  U += pic->linesize[1];
96  V += pic->linesize[2];
97  }
98 
99  return 0;
100 }
101 
103  const uint8_t *src, int src_size)
104 {
105  int h, w;
106  uint8_t *Y1, *Y2, *U, *V;
107  int ret;
108 
109  if (src_size < avctx->width * avctx->height * 3L / 2) {
110  av_log(avctx, AV_LOG_ERROR, "packet too small\n");
111  return AVERROR_INVALIDDATA;
112  }
113 
114  avctx->pix_fmt = AV_PIX_FMT_YUV420P;
115  if ((ret = ff_get_buffer(avctx, pic, 0)) < 0)
116  return ret;
117 
118  Y1 = pic->data[0];
119  Y2 = pic->data[0] + pic->linesize[0];
120  U = pic->data[1];
121  V = pic->data[2];
122  for (h = 0; h < avctx->height; h += 2) {
123  for (w = 0; w < avctx->width; w += 2) {
124  AV_COPY16(Y1 + w, src);
125  AV_COPY16(Y2 + w, src + 2);
126  U[w >> 1] = src[4] + 0x80;
127  V[w >> 1] = src[5] + 0x80;
128  src += 6;
129  }
130  Y1 += pic->linesize[0] << 1;
131  Y2 += pic->linesize[0] << 1;
132  U += pic->linesize[1];
133  V += pic->linesize[2];
134  }
135 
136  return 0;
137 }
138 
140  const uint8_t *src, int src_size)
141 {
142  int h, w;
143  uint8_t *Y, *U, *V;
144  int ret;
145 
146  if (src_size < avctx->width * avctx->height * 3L) {
147  av_log(avctx, AV_LOG_ERROR, "packet too small\n");
148  return AVERROR_INVALIDDATA;
149  }
150 
151  avctx->pix_fmt = AV_PIX_FMT_YUV444P;
152  if ((ret = ff_get_buffer(avctx, pic, 0)) < 0)
153  return ret;
154 
155  Y = pic->data[0];
156  U = pic->data[1];
157  V = pic->data[2];
158  for (h = 0; h < avctx->height; h++) {
159  for (w = 0; w < avctx->width; w++) {
160  Y[w] = *src++;
161  U[w] = *src++ ^ 0x80;
162  V[w] = *src++ ^ 0x80;
163  }
164  Y += pic->linesize[0];
165  U += pic->linesize[1];
166  V += pic->linesize[2];
167  }
168 
169  return 0;
170 }
171 
172 static const uint8_t def_lru[8] = { 0x00, 0x20, 0x40, 0x60, 0x80, 0xA0, 0xC0, 0xFF };
173 static const uint8_t def_lru_555[8] = { 0x00, 0x08, 0x10, 0x18, 0x1F };
174 static const uint8_t def_lru_565[8] = { 0x00, 0x08, 0x10, 0x20, 0x30, 0x3F };
175 
176 static inline uint8_t decode_sym(GetBitContext *gb, uint8_t lru[8])
177 {
178  uint8_t c, val;
179 
180  c = get_unary(gb, 0, 8);
181  if (!c) {
182  val = get_bits(gb, 8);
183  memmove(lru + 1, lru, sizeof(*lru) * (8 - 1));
184  } else {
185  val = lru[c - 1];
186  memmove(lru + 1, lru, sizeof(*lru) * (c - 1));
187  }
188  lru[0] = val;
189 
190  return val;
191 }
192 
193 static inline uint8_t decode_sym_565(GetBitContext *gb, uint8_t lru[8],
194  int bits)
195 {
196  uint8_t c, val;
197 
198  c = get_unary(gb, 0, bits);
199  if (!c) {
200  val = get_bits(gb, bits);
201  memmove(lru + 1, lru, sizeof(*lru) * (6 - 1));
202  } else {
203  val = lru[c - 1];
204  memmove(lru + 1, lru, sizeof(*lru) * (c - 1));
205  }
206  lru[0] = val;
207 
208  return val;
209 }
210 
212  uint8_t *dst, int stride, int is_565)
213 {
214  int x, y;
215  int r, g, b;
216  uint8_t lru[3][8];
217 
218  memcpy(lru[0], def_lru_555, 8 * sizeof(*def_lru));
219  memcpy(lru[1], is_565 ? def_lru_565 : def_lru_555, 8 * sizeof(*def_lru));
220  memcpy(lru[2], def_lru_555, 8 * sizeof(*def_lru));
221 
222  for (y = 0; y < height; y++) {
223  for (x = 0; x < width; x++) {
224  b = decode_sym_565(gb, lru[0], 5);
225  g = decode_sym_565(gb, lru[1], is_565 ? 6 : 5);
226  r = decode_sym_565(gb, lru[2], 5);
227  dst[x * 3 + 0] = (r << 3) | (r >> 2);
228  dst[x * 3 + 1] = is_565 ? (g << 2) | (g >> 4) : (g << 3) | (g >> 2);
229  dst[x * 3 + 2] = (b << 3) | (b >> 2);
230  }
231 
232  dst += stride;
233  }
234 
235  return 0;
236 }
237 
239  const uint8_t *src, int src_size, int is_565)
240 {
241  GetByteContext gb;
242  GetBitContext gb2;
243  int nslices, slice, slice_height;
244  uint32_t off, slice_size;
245  uint8_t *dst;
246  int ret;
247 
248  bytestream2_init(&gb, src, src_size);
249  nslices = bytestream2_get_le16(&gb);
250  off = FFALIGN(nslices * 4 + 2, 16);
251  if (src_size < off) {
252  av_log(avctx, AV_LOG_ERROR, "no slice data\n");
253  return AVERROR_INVALIDDATA;
254  }
255 
256  if (!nslices || avctx->height % nslices) {
257  avpriv_request_sample(avctx, "%d slices for %dx%d", nslices,
258  avctx->width, avctx->height);
259  return AVERROR_PATCHWELCOME;
260  }
261 
262  slice_height = avctx->height / nslices;
263  avctx->pix_fmt = AV_PIX_FMT_RGB24;
264  if ((ret = ff_get_buffer(avctx, pic, 0)) < 0)
265  return ret;
266 
267  dst = pic->data[0];
268  for (slice = 0; slice < nslices; slice++) {
269  slice_size = bytestream2_get_le32(&gb);
270  if (slice_size > src_size - off) {
271  av_log(avctx, AV_LOG_ERROR,
272  "invalid slice size %d (only %d bytes left)\n",
273  slice_size, src_size - off);
274  return AVERROR_INVALIDDATA;
275  }
276  if (slice_size <= 16) {
277  av_log(avctx, AV_LOG_ERROR, "invalid slice size %d\n", slice_size);
278  return AVERROR_INVALIDDATA;
279  }
280 
281  if (AV_RL32(src + off) != slice_size - 16) {
282  av_log(avctx, AV_LOG_ERROR,
283  "Slice sizes mismatch: got %d instead of %d\n",
284  AV_RL32(src + off), slice_size - 16);
285  }
286  init_get_bits(&gb2, src + off + 16, (slice_size - 16) * 8);
287  dx2_decode_slice_565(&gb2, avctx->width, slice_height, dst,
288  pic->linesize[0], is_565);
289 
290  dst += pic->linesize[0] * slice_height;
291  off += slice_size;
292  }
293 
294  return 0;
295 }
296 
298  uint8_t *dst, int stride)
299 {
300  int x, y, i;
301  uint8_t lru[3][8];
302 
303  for (i = 0; i < 3; i++)
304  memcpy(lru[i], def_lru, 8 * sizeof(*def_lru));
305 
306  for (y = 0; y < height; y++) {
307  for (x = 0; x < width; x++) {
308  dst[x * 3 + 0] = decode_sym(gb, lru[0]);
309  dst[x * 3 + 1] = decode_sym(gb, lru[1]);
310  dst[x * 3 + 2] = decode_sym(gb, lru[2]);
311  }
312 
313  dst += stride;
314  }
315 
316  return 0;
317 }
318 
320  const uint8_t *src, int src_size)
321 {
322  GetByteContext gb;
323  GetBitContext gb2;
324  int nslices, slice, slice_height;
325  uint32_t off, slice_size;
326  uint8_t *dst;
327  int ret;
328 
329  bytestream2_init(&gb, src, src_size);
330  nslices = bytestream2_get_le16(&gb);
331  off = FFALIGN(nslices * 4 + 2, 16);
332  if (src_size < off) {
333  av_log(avctx, AV_LOG_ERROR, "no slice data\n");
334  return AVERROR_INVALIDDATA;
335  }
336 
337  if (!nslices || avctx->height % nslices) {
338  avpriv_request_sample(avctx, "%d slices for %dx%d", nslices,
339  avctx->width, avctx->height);
340  return AVERROR_PATCHWELCOME;
341  }
342 
343  slice_height = avctx->height / nslices;
344  avctx->pix_fmt = AV_PIX_FMT_BGR24;
345  if ((ret = ff_get_buffer(avctx, pic, 0)) < 0)
346  return ret;
347 
348  dst = pic->data[0];
349  for (slice = 0; slice < nslices; slice++) {
350  slice_size = bytestream2_get_le32(&gb);
351  if (slice_size > src_size - off) {
352  av_log(avctx, AV_LOG_ERROR,
353  "invalid slice size %d (only %d bytes left)\n",
354  slice_size, src_size - off);
355  return AVERROR_INVALIDDATA;
356  }
357  if (slice_size <= 16) {
358  av_log(avctx, AV_LOG_ERROR, "invalid slice size %d\n", slice_size);
359  return AVERROR_INVALIDDATA;
360  }
361 
362  if (AV_RL32(src + off) != slice_size - 16) {
363  av_log(avctx, AV_LOG_ERROR,
364  "Slice sizes mismatch: got %d instead of %d\n",
365  AV_RL32(src + off), slice_size - 16);
366  }
367  init_get_bits(&gb2, src + off + 16, (slice_size - 16) * 8);
368  dx2_decode_slice_rgb(&gb2, avctx->width, slice_height, dst,
369  pic->linesize[0]);
370 
371  dst += pic->linesize[0] * slice_height;
372  off += slice_size;
373  }
374 
375  return 0;
376 }
377 
379  uint8_t *Y, uint8_t *U, uint8_t *V,
380  int ystride, int ustride, int vstride)
381 {
382  int x, y, i, j;
383  uint8_t lru[3][8];
384 
385  for (i = 0; i < 3; i++)
386  memcpy(lru[i], def_lru, 8 * sizeof(*def_lru));
387 
388  for (y = 0; y < height; y += 4) {
389  for (x = 0; x < width; x += 4) {
390  for (j = 0; j < 4; j++)
391  for (i = 0; i < 4; i++)
392  Y[x + i + j * ystride] = decode_sym(gb, lru[0]);
393  U[x >> 2] = decode_sym(gb, lru[1]) ^ 0x80;
394  V[x >> 2] = decode_sym(gb, lru[2]) ^ 0x80;
395  }
396 
397  Y += ystride << 2;
398  U += ustride;
399  V += vstride;
400  }
401 
402  return 0;
403 }
404 
406  const uint8_t *src, int src_size)
407 {
408  GetByteContext gb;
409  GetBitContext gb2;
410  int nslices, slice, slice_height, ref_slice_height;
411  int cur_y, next_y;
412  uint32_t off, slice_size;
413  uint8_t *Y, *U, *V;
414  int ret;
415 
416  bytestream2_init(&gb, src, src_size);
417  nslices = bytestream2_get_le16(&gb);
418  off = FFALIGN(nslices * 4 + 2, 16);
419  if (src_size < off) {
420  av_log(avctx, AV_LOG_ERROR, "no slice data\n");
421  return AVERROR_INVALIDDATA;
422  }
423 
424  if (!nslices || avctx->height % nslices) {
425  avpriv_request_sample(avctx, "%d slices for %dx%d", nslices,
426  avctx->width, avctx->height);
427  return AVERROR_PATCHWELCOME;
428  }
429 
430  ref_slice_height = avctx->height / nslices;
431  if ((avctx->width & 3) || (avctx->height & 3)) {
432  avpriv_request_sample(avctx, "Frame dimensions %dx%d",
433  avctx->width, avctx->height);
434  }
435 
436  avctx->pix_fmt = AV_PIX_FMT_YUV410P;
437  if ((ret = ff_get_buffer(avctx, pic, 0)) < 0)
438  return ret;
439 
440  Y = pic->data[0];
441  U = pic->data[1];
442  V = pic->data[2];
443 
444  cur_y = 0;
445  next_y = ref_slice_height;
446  for (slice = 0; slice < nslices; slice++) {
447  slice_size = bytestream2_get_le32(&gb);
448  slice_height = (next_y & ~3) - (cur_y & ~3);
449  if (slice_size > src_size - off) {
450  av_log(avctx, AV_LOG_ERROR,
451  "invalid slice size %d (only %d bytes left)\n",
452  slice_size, src_size - off);
453  return AVERROR_INVALIDDATA;
454  }
455  if (slice_size <= 16) {
456  av_log(avctx, AV_LOG_ERROR, "invalid slice size %d\n", slice_size);
457  return AVERROR_INVALIDDATA;
458  }
459 
460  if (AV_RL32(src + off) != slice_size - 16) {
461  av_log(avctx, AV_LOG_ERROR,
462  "Slice sizes mismatch: got %d instead of %d\n",
463  AV_RL32(src + off), slice_size - 16);
464  }
465  init_get_bits(&gb2, src + off + 16, (slice_size - 16) * 8);
466  dx2_decode_slice_410(&gb2, avctx->width, slice_height, Y, U, V,
467  pic->linesize[0], pic->linesize[1],
468  pic->linesize[2]);
469 
470  Y += pic->linesize[0] * slice_height;
471  U += pic->linesize[1] * (slice_height >> 2);
472  V += pic->linesize[2] * (slice_height >> 2);
473  off += slice_size;
474  cur_y = next_y;
475  next_y += ref_slice_height;
476  }
477 
478  return 0;
479 }
480 
482  uint8_t *Y, uint8_t *U, uint8_t *V,
483  int ystride, int ustride, int vstride)
484 {
485  int x, y, i;
486  uint8_t lru[3][8];
487 
488  for (i = 0; i < 3; i++)
489  memcpy(lru[i], def_lru, 8 * sizeof(*def_lru));
490 
491  for (y = 0; y < height; y+=2) {
492  for (x = 0; x < width; x += 2) {
493  Y[x + 0 + 0 * ystride] = decode_sym(gb, lru[0]);
494  Y[x + 1 + 0 * ystride] = decode_sym(gb, lru[0]);
495  Y[x + 0 + 1 * ystride] = decode_sym(gb, lru[0]);
496  Y[x + 1 + 1 * ystride] = decode_sym(gb, lru[0]);
497  U[x >> 1] = decode_sym(gb, lru[1]) ^ 0x80;
498  V[x >> 1] = decode_sym(gb, lru[2]) ^ 0x80;
499  }
500 
501  Y += ystride << 1;
502  U += ustride;
503  V += vstride;
504  }
505 
506  return 0;
507 }
508 
510  const uint8_t *src, int src_size)
511 {
512  GetByteContext gb;
513  GetBitContext gb2;
514  int nslices, slice, slice_height, ref_slice_height;
515  int cur_y, next_y;
516  uint32_t off, slice_size;
517  uint8_t *Y, *U, *V;
518  int ret;
519 
520  bytestream2_init(&gb, src, src_size);
521  nslices = bytestream2_get_le16(&gb);
522  off = FFALIGN(nslices * 4 + 2, 16);
523  if (src_size < off) {
524  av_log(avctx, AV_LOG_ERROR, "no slice data\n");
525  return AVERROR_INVALIDDATA;
526  }
527 
528  if (!nslices || avctx->height % nslices) {
529  avpriv_request_sample(avctx, "%d slices for %dx%d", nslices,
530  avctx->width, avctx->height);
531  return AVERROR_PATCHWELCOME;
532  }
533 
534  ref_slice_height = avctx->height / nslices;
535  if ((avctx->width & 1) || (avctx->height & 1)) {
536  avpriv_request_sample(avctx, "Frame dimensions %dx%d",
537  avctx->width, avctx->height);
538  }
539 
540  avctx->pix_fmt = AV_PIX_FMT_YUV420P;
541  if ((ret = ff_get_buffer(avctx, pic, 0)) < 0)
542  return ret;
543 
544  Y = pic->data[0];
545  U = pic->data[1];
546  V = pic->data[2];
547 
548  cur_y = 0;
549  next_y = ref_slice_height;
550  for (slice = 0; slice < nslices; slice++) {
551  slice_size = bytestream2_get_le32(&gb);
552  slice_height = (next_y & ~1) - (cur_y & ~1);
553  if (slice_size > src_size - off) {
554  av_log(avctx, AV_LOG_ERROR,
555  "invalid slice size %d (only %d bytes left)\n",
556  slice_size, src_size - off);
557  return AVERROR_INVALIDDATA;
558  }
559  if (slice_size <= 16) {
560  av_log(avctx, AV_LOG_ERROR, "invalid slice size %d\n", slice_size);
561  return AVERROR_INVALIDDATA;
562  }
563 
564  if (AV_RL32(src + off) != slice_size - 16) {
565  av_log(avctx, AV_LOG_ERROR,
566  "Slice sizes mismatch: got %d instead of %d\n",
567  AV_RL32(src + off), slice_size - 16);
568  }
569  init_get_bits(&gb2, src + off + 16, (slice_size - 16) * 8);
570  dx2_decode_slice_420(&gb2, avctx->width, slice_height, Y, U, V,
571  pic->linesize[0], pic->linesize[1],
572  pic->linesize[2]);
573 
574  Y += pic->linesize[0] * slice_height;
575  U += pic->linesize[1] * (slice_height >> 1);
576  V += pic->linesize[2] * (slice_height >> 1);
577  off += slice_size;
578  cur_y = next_y;
579  next_y += ref_slice_height;
580  }
581 
582  return 0;
583 }
584 
586  uint8_t *Y, uint8_t *U, uint8_t *V,
587  int ystride, int ustride, int vstride)
588 {
589  int x, y, i;
590  uint8_t lru[3][8];
591 
592  for (i = 0; i < 3; i++)
593  memcpy(lru[i], def_lru, 8 * sizeof(*def_lru));
594 
595  for (y = 0; y < height; y++) {
596  for (x = 0; x < width; x++) {
597  Y[x] = decode_sym(gb, lru[0]);
598  U[x] = decode_sym(gb, lru[1]) ^ 0x80;
599  V[x] = decode_sym(gb, lru[2]) ^ 0x80;
600  }
601 
602  Y += ystride;
603  U += ustride;
604  V += vstride;
605  }
606 
607  return 0;
608 }
609 
611  const uint8_t *src, int src_size)
612 {
613  GetByteContext gb;
614  GetBitContext gb2;
615  int nslices, slice, slice_height;
616  uint32_t off, slice_size;
617  uint8_t *Y, *U, *V;
618  int ret;
619 
620  bytestream2_init(&gb, src, src_size);
621  nslices = bytestream2_get_le16(&gb);
622  off = FFALIGN(nslices * 4 + 2, 16);
623  if (src_size < off) {
624  av_log(avctx, AV_LOG_ERROR, "no slice data\n");
625  return AVERROR_INVALIDDATA;
626  }
627 
628  if (!nslices || avctx->height % nslices) {
629  avpriv_request_sample(avctx, "%d slices for %dx%d", nslices,
630  avctx->width, avctx->height);
631  return AVERROR_PATCHWELCOME;
632  }
633 
634  slice_height = avctx->height / nslices;
635 
636  avctx->pix_fmt = AV_PIX_FMT_YUV444P;
637  if ((ret = ff_get_buffer(avctx, pic, 0)) < 0)
638  return ret;
639 
640  Y = pic->data[0];
641  U = pic->data[1];
642  V = pic->data[2];
643 
644  for (slice = 0; slice < nslices; slice++) {
645  slice_size = bytestream2_get_le32(&gb);
646  if (slice_size > src_size - off) {
647  av_log(avctx, AV_LOG_ERROR,
648  "invalid slice size %d (only %d bytes left)\n",
649  slice_size, src_size - off);
650  return AVERROR_INVALIDDATA;
651  }
652  if (slice_size <= 16) {
653  av_log(avctx, AV_LOG_ERROR, "invalid slice size %d\n", slice_size);
654  return AVERROR_INVALIDDATA;
655  }
656 
657  if (AV_RL32(src + off) != slice_size - 16) {
658  av_log(avctx, AV_LOG_ERROR,
659  "Slice sizes mismatch: got %d instead of %d\n",
660  AV_RL32(src + off), slice_size - 16);
661  }
662  init_get_bits(&gb2, src + off + 16, (slice_size - 16) * 8);
663  dx2_decode_slice_444(&gb2, avctx->width, slice_height, Y, U, V,
664  pic->linesize[0], pic->linesize[1],
665  pic->linesize[2]);
666 
667  Y += pic->linesize[0] * slice_height;
668  U += pic->linesize[1] * slice_height;
669  V += pic->linesize[2] * slice_height;
670  off += slice_size;
671  }
672 
673  return 0;
674 }
675 
676 static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
677  AVPacket *avpkt)
678 {
679  AVFrame *pic = data;
680  const uint8_t *src = avpkt->data;
681  int ret;
682 
683  if (avpkt->size < 16) {
684  av_log(avctx, AV_LOG_ERROR, "packet too small\n");
685  return AVERROR_INVALIDDATA;
686  }
687 
688  switch (AV_RB32(src)) {
689  case 0x01000001:
690  ret = dxtory_decode_v1_rgb(avctx, pic, src + 16, avpkt->size - 16,
691  AV_PIX_FMT_BGR24, 3);
692  break;
693  case 0x01000009:
694  ret = dxtory_decode_v2_rgb(avctx, pic, src + 16, avpkt->size - 16);
695  break;
696  case 0x02000001:
697  ret = dxtory_decode_v1_420(avctx, pic, src + 16, avpkt->size - 16);
698  break;
699  case 0x02000009:
700  ret = dxtory_decode_v2_420(avctx, pic, src + 16, avpkt->size - 16);
701  break;
702  case 0x03000001:
703  ret = dxtory_decode_v1_410(avctx, pic, src + 16, avpkt->size - 16);
704  break;
705  case 0x03000009:
706  ret = dxtory_decode_v2_410(avctx, pic, src + 16, avpkt->size - 16);
707  break;
708  case 0x04000001:
709  ret = dxtory_decode_v1_444(avctx, pic, src + 16, avpkt->size - 16);
710  break;
711  case 0x04000009:
712  ret = dxtory_decode_v2_444(avctx, pic, src + 16, avpkt->size - 16);
713  break;
714  case 0x17000001:
715  ret = dxtory_decode_v1_rgb(avctx, pic, src + 16, avpkt->size - 16,
717  break;
718  case 0x17000009:
719  ret = dxtory_decode_v2_565(avctx, pic, src + 16, avpkt->size - 16, 1);
720  break;
721  case 0x18000001:
722  case 0x19000001:
723  ret = dxtory_decode_v1_rgb(avctx, pic, src + 16, avpkt->size - 16,
725  break;
726  case 0x18000009:
727  case 0x19000009:
728  ret = dxtory_decode_v2_565(avctx, pic, src + 16, avpkt->size - 16, 0);
729  break;
730  default:
731  avpriv_request_sample(avctx, "Frame header %X", AV_RB32(src));
732  return AVERROR_PATCHWELCOME;
733  }
734 
735  if (ret)
736  return ret;
737 
739  pic->key_frame = 1;
740  *got_frame = 1;
741 
742  return avpkt->size;
743 }
744 
746  .name = "dxtory",
747  .long_name = NULL_IF_CONFIG_SMALL("Dxtory"),
748  .type = AVMEDIA_TYPE_VIDEO,
749  .id = AV_CODEC_ID_DXTORY,
750  .decode = decode_frame,
751  .capabilities = CODEC_CAP_DR1,
752 };