]> git.sesse.net Git - ffmpeg/blob - libavcodec/dxtory.c
avcodec/g2meet: Also clear tile dimensions on header_fail
[ffmpeg] / libavcodec / dxtory.c
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
34 static int dxtory_decode_v1_rgb(AVCodecContext *avctx, AVFrame *pic,
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
61 static int dxtory_decode_v1_410(AVCodecContext *avctx, AVFrame *pic,
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 * 9LL / 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
104 static int dxtory_decode_v1_420(AVCodecContext *avctx, AVFrame *pic,
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 * 3LL / 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
141 static int dxtory_decode_v1_444(AVCodecContext *avctx, AVFrame *pic,
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 * 3LL) {
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
213 static int dx2_decode_slice_565(GetBitContext *gb, int width, int height,
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
240 static int dxtory_decode_v2_565(AVCodecContext *avctx, AVFrame *pic,
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         if ((ret = init_get_bits8(&gb2, src + off + 16, slice_size - 16)) < 0)
289             return ret;
290         dx2_decode_slice_565(&gb2, avctx->width, slice_height, dst,
291                              pic->linesize[0], is_565);
292
293         dst += pic->linesize[0] * slice_height;
294         off += slice_size;
295     }
296
297     return 0;
298 }
299
300 static int dx2_decode_slice_rgb(GetBitContext *gb, int width, int height,
301                                 uint8_t *dst, int stride)
302 {
303     int x, y, i;
304     uint8_t lru[3][8];
305
306     for (i = 0; i < 3; i++)
307         memcpy(lru[i], def_lru, 8 * sizeof(*def_lru));
308
309     for (y = 0; y < height; y++) {
310         for (x = 0; x < width; x++) {
311             dst[x * 3 + 0] = decode_sym(gb, lru[0]);
312             dst[x * 3 + 1] = decode_sym(gb, lru[1]);
313             dst[x * 3 + 2] = decode_sym(gb, lru[2]);
314         }
315
316         dst += stride;
317     }
318
319     return 0;
320 }
321
322 static int dxtory_decode_v2_rgb(AVCodecContext *avctx, AVFrame *pic,
323                                 const uint8_t *src, int src_size)
324 {
325     GetByteContext gb;
326     GetBitContext  gb2;
327     int nslices, slice, slice_height;
328     uint32_t off, slice_size;
329     uint8_t *dst;
330     int ret;
331
332     bytestream2_init(&gb, src, src_size);
333     nslices = bytestream2_get_le16(&gb);
334     off = FFALIGN(nslices * 4 + 2, 16);
335     if (src_size < off) {
336         av_log(avctx, AV_LOG_ERROR, "no slice data\n");
337         return AVERROR_INVALIDDATA;
338     }
339
340     if (!nslices || avctx->height % nslices) {
341         avpriv_request_sample(avctx, "%d slices for %dx%d", nslices,
342                               avctx->width, avctx->height);
343         return AVERROR_PATCHWELCOME;
344     }
345
346     slice_height = avctx->height / nslices;
347     avctx->pix_fmt = AV_PIX_FMT_BGR24;
348     if ((ret = ff_get_buffer(avctx, pic, 0)) < 0)
349         return ret;
350
351     dst = pic->data[0];
352     for (slice = 0; slice < nslices; slice++) {
353         slice_size = bytestream2_get_le32(&gb);
354         if (slice_size > src_size - off) {
355             av_log(avctx, AV_LOG_ERROR,
356                    "invalid slice size %"PRIu32" (only %"PRIu32" bytes left)\n",
357                    slice_size, src_size - off);
358             return AVERROR_INVALIDDATA;
359         }
360         if (slice_size <= 16) {
361             av_log(avctx, AV_LOG_ERROR, "invalid slice size %"PRIu32"\n",
362                    slice_size);
363             return AVERROR_INVALIDDATA;
364         }
365
366         if (AV_RL32(src + off) != slice_size - 16) {
367             av_log(avctx, AV_LOG_ERROR,
368                    "Slice sizes mismatch: got %"PRIu32" instead of %"PRIu32"\n",
369                    AV_RL32(src + off), slice_size - 16);
370         }
371         if ((ret = init_get_bits8(&gb2, src + off + 16, slice_size - 16)) < 0)
372             return ret;
373         dx2_decode_slice_rgb(&gb2, avctx->width, slice_height, dst,
374                              pic->linesize[0]);
375
376         dst += pic->linesize[0] * slice_height;
377         off += slice_size;
378     }
379
380     return 0;
381 }
382
383 static int dx2_decode_slice_410(GetBitContext *gb, int width, int height,
384                                 uint8_t *Y, uint8_t *U, uint8_t *V,
385                                 int ystride, int ustride, int vstride)
386 {
387     int x, y, i, j;
388     uint8_t lru[3][8];
389
390     for (i = 0; i < 3; i++)
391         memcpy(lru[i], def_lru, 8 * sizeof(*def_lru));
392
393     for (y = 0; y < height; y += 4) {
394         for (x = 0; x < width; x += 4) {
395             for (j = 0; j < 4; j++)
396                 for (i = 0; i < 4; i++)
397                     Y[x + i + j * ystride] = decode_sym(gb, lru[0]);
398             U[x >> 2] = decode_sym(gb, lru[1]) ^ 0x80;
399             V[x >> 2] = decode_sym(gb, lru[2]) ^ 0x80;
400         }
401
402         Y += ystride << 2;
403         U += ustride;
404         V += vstride;
405     }
406
407     return 0;
408 }
409
410 static int dxtory_decode_v2_410(AVCodecContext *avctx, AVFrame *pic,
411                                 const uint8_t *src, int src_size)
412 {
413     GetByteContext gb;
414     GetBitContext  gb2;
415     int nslices, slice, slice_height;
416     int cur_y, next_y;
417     uint32_t off, slice_size;
418     uint8_t *Y, *U, *V;
419     int ret;
420
421     bytestream2_init(&gb, src, src_size);
422     nslices = bytestream2_get_le16(&gb);
423     off = FFALIGN(nslices * 4 + 2, 16);
424     if (src_size < off) {
425         av_log(avctx, AV_LOG_ERROR, "no slice data\n");
426         return AVERROR_INVALIDDATA;
427     }
428
429     if (!nslices) {
430         avpriv_request_sample(avctx, "%d slices for %dx%d", nslices,
431                               avctx->width, avctx->height);
432         return AVERROR_PATCHWELCOME;
433     }
434
435     if ((avctx->width & 3) || (avctx->height & 3)) {
436         avpriv_request_sample(avctx, "Frame dimensions %dx%d",
437                               avctx->width, avctx->height);
438     }
439
440     avctx->pix_fmt = AV_PIX_FMT_YUV410P;
441     if ((ret = ff_get_buffer(avctx, pic, 0)) < 0)
442         return ret;
443
444     Y = pic->data[0];
445     U = pic->data[1];
446     V = pic->data[2];
447
448     cur_y  = 0;
449     for (slice = 0; slice < nslices; slice++) {
450         slice_size   = bytestream2_get_le32(&gb);
451         next_y = ((slice + 1) * avctx->height) / nslices;
452         slice_height = (next_y & ~3) - (cur_y & ~3);
453         if (slice_size > src_size - off) {
454             av_log(avctx, AV_LOG_ERROR,
455                    "invalid slice size %"PRIu32" (only %"PRIu32" bytes left)\n",
456                    slice_size, src_size - off);
457             return AVERROR_INVALIDDATA;
458         }
459         if (slice_size <= 16) {
460             av_log(avctx, AV_LOG_ERROR, "invalid slice size %"PRIu32"\n", slice_size);
461             return AVERROR_INVALIDDATA;
462         }
463
464         if (AV_RL32(src + off) != slice_size - 16) {
465             av_log(avctx, AV_LOG_ERROR,
466                    "Slice sizes mismatch: got %"PRIu32" instead of %"PRIu32"\n",
467                    AV_RL32(src + off), slice_size - 16);
468         }
469         if ((ret = init_get_bits8(&gb2, src + off + 16, slice_size - 16)) < 0)
470             return ret;
471         dx2_decode_slice_410(&gb2, avctx->width, slice_height, Y, U, V,
472                              pic->linesize[0], pic->linesize[1],
473                              pic->linesize[2]);
474
475         Y += pic->linesize[0] *  slice_height;
476         U += pic->linesize[1] * (slice_height >> 2);
477         V += pic->linesize[2] * (slice_height >> 2);
478         off += slice_size;
479         cur_y   = next_y;
480     }
481
482     return 0;
483 }
484
485 static int dx2_decode_slice_420(GetBitContext *gb, int width, int height,
486                                 uint8_t *Y, uint8_t *U, uint8_t *V,
487                                 int ystride, int ustride, int vstride)
488 {
489     int x, y, i;
490     uint8_t lru[3][8];
491
492     for (i = 0; i < 3; i++)
493         memcpy(lru[i], def_lru, 8 * sizeof(*def_lru));
494
495     for (y = 0; y < height; y+=2) {
496         for (x = 0; x < width; x += 2) {
497             Y[x + 0 + 0 * ystride] = decode_sym(gb, lru[0]);
498             Y[x + 1 + 0 * ystride] = decode_sym(gb, lru[0]);
499             Y[x + 0 + 1 * ystride] = decode_sym(gb, lru[0]);
500             Y[x + 1 + 1 * ystride] = decode_sym(gb, lru[0]);
501             U[x >> 1] = decode_sym(gb, lru[1]) ^ 0x80;
502             V[x >> 1] = decode_sym(gb, lru[2]) ^ 0x80;
503         }
504
505         Y += ystride << 1;
506         U += ustride;
507         V += vstride;
508     }
509
510     return 0;
511 }
512
513 static int dxtory_decode_v2_420(AVCodecContext *avctx, AVFrame *pic,
514                                 const uint8_t *src, int src_size)
515 {
516     GetByteContext gb;
517     GetBitContext  gb2;
518     int nslices, slice, slice_height;
519     int cur_y, next_y;
520     uint32_t off, slice_size;
521     uint8_t *Y, *U, *V;
522     int ret;
523
524     bytestream2_init(&gb, src, src_size);
525     nslices = bytestream2_get_le16(&gb);
526     off = FFALIGN(nslices * 4 + 2, 16);
527     if (src_size < off) {
528         av_log(avctx, AV_LOG_ERROR, "no slice data\n");
529         return AVERROR_INVALIDDATA;
530     }
531
532     if (!nslices) {
533         avpriv_request_sample(avctx, "%d slices for %dx%d", nslices,
534                               avctx->width, avctx->height);
535         return AVERROR_PATCHWELCOME;
536     }
537
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     for (slice = 0; slice < nslices; slice++) {
553         slice_size   = bytestream2_get_le32(&gb);
554         next_y = ((slice + 1) * avctx->height) / nslices;
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         if ((ret = init_get_bits8(&gb2, src + off + 16, slice_size - 16)) < 0)
573             return ret;
574         dx2_decode_slice_420(&gb2, avctx->width, slice_height, Y, U, V,
575                              pic->linesize[0], pic->linesize[1],
576                              pic->linesize[2]);
577
578         Y += pic->linesize[0] *  slice_height;
579         U += pic->linesize[1] * (slice_height >> 1);
580         V += pic->linesize[2] * (slice_height >> 1);
581         off += slice_size;
582         cur_y   = next_y;
583     }
584
585     return 0;
586 }
587
588 static int dx2_decode_slice_444(GetBitContext *gb, int width, int height,
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
613 static int dxtory_decode_v2_444(AVCodecContext *avctx, AVFrame *pic,
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         if ((ret = init_get_bits8(&gb2, src + off + 16, slice_size - 16)) < 0)
666             return ret;
667         dx2_decode_slice_444(&gb2, avctx->width, slice_height, Y, U, V,
668                              pic->linesize[0], pic->linesize[1],
669                              pic->linesize[2]);
670
671         Y += pic->linesize[0] * slice_height;
672         U += pic->linesize[1] * slice_height;
673         V += pic->linesize[2] * slice_height;
674         off += slice_size;
675     }
676
677     return 0;
678 }
679
680 static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
681                         AVPacket *avpkt)
682 {
683     AVFrame *pic = data;
684     const uint8_t *src = avpkt->data;
685     int ret;
686
687     if (avpkt->size < 16) {
688         av_log(avctx, AV_LOG_ERROR, "packet too small\n");
689         return AVERROR_INVALIDDATA;
690     }
691
692     switch (AV_RB32(src)) {
693     case 0x01000001:
694         ret = dxtory_decode_v1_rgb(avctx, pic, src + 16, avpkt->size - 16,
695                                    AV_PIX_FMT_BGR24, 3);
696         break;
697     case 0x01000009:
698         ret = dxtory_decode_v2_rgb(avctx, pic, src + 16, avpkt->size - 16);
699         break;
700     case 0x02000001:
701         ret = dxtory_decode_v1_420(avctx, pic, src + 16, avpkt->size - 16);
702         break;
703     case 0x02000009:
704         ret = dxtory_decode_v2_420(avctx, pic, src + 16, avpkt->size - 16);
705         break;
706     case 0x03000001:
707         ret = dxtory_decode_v1_410(avctx, pic, src + 16, avpkt->size - 16);
708         break;
709     case 0x03000009:
710         ret = dxtory_decode_v2_410(avctx, pic, src + 16, avpkt->size - 16);
711         break;
712     case 0x04000001:
713         ret = dxtory_decode_v1_444(avctx, pic, src + 16, avpkt->size - 16);
714         break;
715     case 0x04000009:
716         ret = dxtory_decode_v2_444(avctx, pic, src + 16, avpkt->size - 16);
717         break;
718     case 0x17000001:
719         ret = dxtory_decode_v1_rgb(avctx, pic, src + 16, avpkt->size - 16,
720                                    AV_PIX_FMT_RGB565LE, 2);
721         break;
722     case 0x17000009:
723         ret = dxtory_decode_v2_565(avctx, pic, src + 16, avpkt->size - 16, 1);
724         break;
725     case 0x18000001:
726     case 0x19000001:
727         ret = dxtory_decode_v1_rgb(avctx, pic, src + 16, avpkt->size - 16,
728                                    AV_PIX_FMT_RGB555LE, 2);
729         break;
730     case 0x18000009:
731     case 0x19000009:
732         ret = dxtory_decode_v2_565(avctx, pic, src + 16, avpkt->size - 16, 0);
733         break;
734     default:
735         avpriv_request_sample(avctx, "Frame header %"PRIX32, AV_RB32(src));
736         return AVERROR_PATCHWELCOME;
737     }
738
739     if (ret)
740         return ret;
741
742     pic->pict_type = AV_PICTURE_TYPE_I;
743     pic->key_frame = 1;
744     *got_frame = 1;
745
746     return avpkt->size;
747 }
748
749 AVCodec ff_dxtory_decoder = {
750     .name           = "dxtory",
751     .long_name      = NULL_IF_CONFIG_SMALL("Dxtory"),
752     .type           = AVMEDIA_TYPE_VIDEO,
753     .id             = AV_CODEC_ID_DXTORY,
754     .decode         = decode_frame,
755     .capabilities   = AV_CODEC_CAP_DR1,
756 };