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