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_COPY32(Y1 + w, src);
86  AV_COPY32(Y2 + w, src + 4);
87  AV_COPY32(Y3 + w, src + 8);
88  AV_COPY32(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, ref_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 || avctx->height % nslices) {
428  avpriv_request_sample(avctx, "%d slices for %dx%d", nslices,
429  avctx->width, avctx->height);
430  return AVERROR_PATCHWELCOME;
431  }
432 
433  ref_slice_height = avctx->height / nslices;
434  if ((avctx->width & 3) || (avctx->height & 3)) {
435  avpriv_request_sample(avctx, "Frame dimensions %dx%d",
436  avctx->width, avctx->height);
437  }
438 
439  avctx->pix_fmt = AV_PIX_FMT_YUV410P;
440  if ((ret = ff_get_buffer(avctx, pic, 0)) < 0)
441  return ret;
442 
443  Y = pic->data[0];
444  U = pic->data[1];
445  V = pic->data[2];
446 
447  cur_y = 0;
448  next_y = ref_slice_height;
449  for (slice = 0; slice < nslices; slice++) {
450  slice_size = bytestream2_get_le32(&gb);
451  slice_height = (next_y & ~3) - (cur_y & ~3);
452  if (slice_size > src_size - off) {
453  av_log(avctx, AV_LOG_ERROR,
454  "invalid slice size %"PRIu32" (only %"PRIu32" bytes left)\n",
455  slice_size, src_size - off);
456  return AVERROR_INVALIDDATA;
457  }
458  if (slice_size <= 16) {
459  av_log(avctx, AV_LOG_ERROR, "invalid slice size %"PRIu32"\n", slice_size);
460  return AVERROR_INVALIDDATA;
461  }
462 
463  if (AV_RL32(src + off) != slice_size - 16) {
464  av_log(avctx, AV_LOG_ERROR,
465  "Slice sizes mismatch: got %"PRIu32" instead of %"PRIu32"\n",
466  AV_RL32(src + off), slice_size - 16);
467  }
468  init_get_bits(&gb2, src + off + 16, (slice_size - 16) * 8);
469  dx2_decode_slice_410(&gb2, avctx->width, slice_height, Y, U, V,
470  pic->linesize[0], pic->linesize[1],
471  pic->linesize[2]);
472 
473  Y += pic->linesize[0] * slice_height;
474  U += pic->linesize[1] * (slice_height >> 2);
475  V += pic->linesize[2] * (slice_height >> 2);
476  off += slice_size;
477  cur_y = next_y;
478  next_y += ref_slice_height;
479  }
480 
481  return 0;
482 }
483 
485  uint8_t *Y, uint8_t *U, uint8_t *V,
486  int ystride, int ustride, int vstride)
487 {
488  int x, y, i;
489  uint8_t lru[3][8];
490 
491  for (i = 0; i < 3; i++)
492  memcpy(lru[i], def_lru, 8 * sizeof(*def_lru));
493 
494  for (y = 0; y < height; y+=2) {
495  for (x = 0; x < width; x += 2) {
496  Y[x + 0 + 0 * ystride] = decode_sym(gb, lru[0]);
497  Y[x + 1 + 0 * ystride] = decode_sym(gb, lru[0]);
498  Y[x + 0 + 1 * ystride] = decode_sym(gb, lru[0]);
499  Y[x + 1 + 1 * ystride] = decode_sym(gb, lru[0]);
500  U[x >> 1] = decode_sym(gb, lru[1]) ^ 0x80;
501  V[x >> 1] = decode_sym(gb, lru[2]) ^ 0x80;
502  }
503 
504  Y += ystride << 1;
505  U += ustride;
506  V += vstride;
507  }
508 
509  return 0;
510 }
511 
513  const uint8_t *src, int src_size)
514 {
515  GetByteContext gb;
516  GetBitContext gb2;
517  int nslices, slice, slice_height, ref_slice_height;
518  int cur_y, next_y;
519  uint32_t off, slice_size;
520  uint8_t *Y, *U, *V;
521  int ret;
522 
523  bytestream2_init(&gb, src, src_size);
524  nslices = bytestream2_get_le16(&gb);
525  off = FFALIGN(nslices * 4 + 2, 16);
526  if (src_size < off) {
527  av_log(avctx, AV_LOG_ERROR, "no slice data\n");
528  return AVERROR_INVALIDDATA;
529  }
530 
531  if (!nslices || avctx->height % nslices) {
532  avpriv_request_sample(avctx, "%d slices for %dx%d", nslices,
533  avctx->width, avctx->height);
534  return AVERROR_PATCHWELCOME;
535  }
536 
537  ref_slice_height = avctx->height / nslices;
538  if ((avctx->width & 1) || (avctx->height & 1)) {
539  avpriv_request_sample(avctx, "Frame dimensions %dx%d",
540  avctx->width, avctx->height);
541  }
542 
543  avctx->pix_fmt = AV_PIX_FMT_YUV420P;
544  if ((ret = ff_get_buffer(avctx, pic, 0)) < 0)
545  return ret;
546 
547  Y = pic->data[0];
548  U = pic->data[1];
549  V = pic->data[2];
550 
551  cur_y = 0;
552  next_y = ref_slice_height;
553  for (slice = 0; slice < nslices; slice++) {
554  slice_size = bytestream2_get_le32(&gb);
555  slice_height = (next_y & ~1) - (cur_y & ~1);
556  if (slice_size > src_size - off) {
557  av_log(avctx, AV_LOG_ERROR,
558  "invalid slice size %"PRIu32" (only %"PRIu32" bytes left)\n",
559  slice_size, src_size - off);
560  return AVERROR_INVALIDDATA;
561  }
562  if (slice_size <= 16) {
563  av_log(avctx, AV_LOG_ERROR, "invalid slice size %"PRIu32"\n", slice_size);
564  return AVERROR_INVALIDDATA;
565  }
566 
567  if (AV_RL32(src + off) != slice_size - 16) {
568  av_log(avctx, AV_LOG_ERROR,
569  "Slice sizes mismatch: got %"PRIu32" instead of %"PRIu32"\n",
570  AV_RL32(src + off), slice_size - 16);
571  }
572  init_get_bits(&gb2, src + off + 16, (slice_size - 16) * 8);
573  dx2_decode_slice_420(&gb2, avctx->width, slice_height, Y, U, V,
574  pic->linesize[0], pic->linesize[1],
575  pic->linesize[2]);
576 
577  Y += pic->linesize[0] * slice_height;
578  U += pic->linesize[1] * (slice_height >> 1);
579  V += pic->linesize[2] * (slice_height >> 1);
580  off += slice_size;
581  cur_y = next_y;
582  next_y += ref_slice_height;
583  }
584 
585  return 0;
586 }
587 
589  uint8_t *Y, uint8_t *U, uint8_t *V,
590  int ystride, int ustride, int vstride)
591 {
592  int x, y, i;
593  uint8_t lru[3][8];
594 
595  for (i = 0; i < 3; i++)
596  memcpy(lru[i], def_lru, 8 * sizeof(*def_lru));
597 
598  for (y = 0; y < height; y++) {
599  for (x = 0; x < width; x++) {
600  Y[x] = decode_sym(gb, lru[0]);
601  U[x] = decode_sym(gb, lru[1]) ^ 0x80;
602  V[x] = decode_sym(gb, lru[2]) ^ 0x80;
603  }
604 
605  Y += ystride;
606  U += ustride;
607  V += vstride;
608  }
609 
610  return 0;
611 }
612 
614  const uint8_t *src, int src_size)
615 {
616  GetByteContext gb;
617  GetBitContext gb2;
618  int nslices, slice, slice_height;
619  uint32_t off, slice_size;
620  uint8_t *Y, *U, *V;
621  int ret;
622 
623  bytestream2_init(&gb, src, src_size);
624  nslices = bytestream2_get_le16(&gb);
625  off = FFALIGN(nslices * 4 + 2, 16);
626  if (src_size < off) {
627  av_log(avctx, AV_LOG_ERROR, "no slice data\n");
628  return AVERROR_INVALIDDATA;
629  }
630 
631  if (!nslices || avctx->height % nslices) {
632  avpriv_request_sample(avctx, "%d slices for %dx%d", nslices,
633  avctx->width, avctx->height);
634  return AVERROR_PATCHWELCOME;
635  }
636 
637  slice_height = avctx->height / nslices;
638 
639  avctx->pix_fmt = AV_PIX_FMT_YUV444P;
640  if ((ret = ff_get_buffer(avctx, pic, 0)) < 0)
641  return ret;
642 
643  Y = pic->data[0];
644  U = pic->data[1];
645  V = pic->data[2];
646 
647  for (slice = 0; slice < nslices; slice++) {
648  slice_size = bytestream2_get_le32(&gb);
649  if (slice_size > src_size - off) {
650  av_log(avctx, AV_LOG_ERROR,
651  "invalid slice size %"PRIu32" (only %"PRIu32" bytes left)\n",
652  slice_size, src_size - off);
653  return AVERROR_INVALIDDATA;
654  }
655  if (slice_size <= 16) {
656  av_log(avctx, AV_LOG_ERROR, "invalid slice size %"PRIu32"\n", slice_size);
657  return AVERROR_INVALIDDATA;
658  }
659 
660  if (AV_RL32(src + off) != slice_size - 16) {
661  av_log(avctx, AV_LOG_ERROR,
662  "Slice sizes mismatch: got %"PRIu32" instead of %"PRIu32"\n",
663  AV_RL32(src + off), slice_size - 16);
664  }
665  init_get_bits(&gb2, src + off + 16, (slice_size - 16) * 8);
666  dx2_decode_slice_444(&gb2, avctx->width, slice_height, Y, U, V,
667  pic->linesize[0], pic->linesize[1],
668  pic->linesize[2]);
669 
670  Y += pic->linesize[0] * slice_height;
671  U += pic->linesize[1] * slice_height;
672  V += pic->linesize[2] * slice_height;
673  off += slice_size;
674  }
675 
676  return 0;
677 }
678 
679 static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
680  AVPacket *avpkt)
681 {
682  AVFrame *pic = data;
683  const uint8_t *src = avpkt->data;
684  int ret;
685 
686  if (avpkt->size < 16) {
687  av_log(avctx, AV_LOG_ERROR, "packet too small\n");
688  return AVERROR_INVALIDDATA;
689  }
690 
691  switch (AV_RB32(src)) {
692  case 0x01000001:
693  ret = dxtory_decode_v1_rgb(avctx, pic, src + 16, avpkt->size - 16,
694  AV_PIX_FMT_BGR24, 3);
695  break;
696  case 0x01000009:
697  ret = dxtory_decode_v2_rgb(avctx, pic, src + 16, avpkt->size - 16);
698  break;
699  case 0x02000001:
700  ret = dxtory_decode_v1_420(avctx, pic, src + 16, avpkt->size - 16);
701  break;
702  case 0x02000009:
703  ret = dxtory_decode_v2_420(avctx, pic, src + 16, avpkt->size - 16);
704  break;
705  case 0x03000001:
706  ret = dxtory_decode_v1_410(avctx, pic, src + 16, avpkt->size - 16);
707  break;
708  case 0x03000009:
709  ret = dxtory_decode_v2_410(avctx, pic, src + 16, avpkt->size - 16);
710  break;
711  case 0x04000001:
712  ret = dxtory_decode_v1_444(avctx, pic, src + 16, avpkt->size - 16);
713  break;
714  case 0x04000009:
715  ret = dxtory_decode_v2_444(avctx, pic, src + 16, avpkt->size - 16);
716  break;
717  case 0x17000001:
718  ret = dxtory_decode_v1_rgb(avctx, pic, src + 16, avpkt->size - 16,
720  break;
721  case 0x17000009:
722  ret = dxtory_decode_v2_565(avctx, pic, src + 16, avpkt->size - 16, 1);
723  break;
724  case 0x18000001:
725  case 0x19000001:
726  ret = dxtory_decode_v1_rgb(avctx, pic, src + 16, avpkt->size - 16,
728  break;
729  case 0x18000009:
730  case 0x19000009:
731  ret = dxtory_decode_v2_565(avctx, pic, src + 16, avpkt->size - 16, 0);
732  break;
733  default:
734  avpriv_request_sample(avctx, "Frame header %"PRIX32, AV_RB32(src));
735  return AVERROR_PATCHWELCOME;
736  }
737 
738  if (ret)
739  return ret;
740 
742  pic->key_frame = 1;
743  *got_frame = 1;
744 
745  return avpkt->size;
746 }
747 
749  .name = "dxtory",
750  .long_name = NULL_IF_CONFIG_SMALL("Dxtory"),
751  .type = AVMEDIA_TYPE_VIDEO,
752  .id = AV_CODEC_ID_DXTORY,
753  .decode = decode_frame,
754  .capabilities = CODEC_CAP_DR1,
755 };