]> git.sesse.net Git - ffmpeg/blob - libavcodec/dxtory.c
Remove all SH4 architecture optimizations
[ffmpeg] / libavcodec / dxtory.c
1 /*
2  * Dxtory decoder
3  *
4  * Copyright (c) 2011 Konstantin Shishkov
5  *
6  * This file is part of Libav.
7  *
8  * Libav 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  * Libav 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 Libav; 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
32 static int dxtory_decode_v1_rgb(AVCodecContext *avctx, AVFrame *pic,
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 * 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
59 static int dxtory_decode_v1_410(AVCodecContext *avctx, AVFrame *pic,
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 * 18 / 16) {
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
102 static int dxtory_decode_v1_420(AVCodecContext *avctx, AVFrame *pic,
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 * 3 / 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
139 static int dxtory_decode_v1_444(AVCodecContext *avctx, AVFrame *pic,
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 * 3) {
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 const uint8_t def_lru[8] = { 0x00, 0x20, 0x40, 0x60, 0x80, 0xA0, 0xC0, 0xFF };
173 const uint8_t def_lru_555[8] = { 0x00, 0x08, 0x10, 0x18, 0x1F };
174 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
211 static int dx2_decode_slice_565(GetBitContext *gb, int width, int height,
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
238 static int dxtory_decode_v2_565(AVCodecContext *avctx, AVFrame *pic,
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
297 static int dx2_decode_slice_rgb(GetBitContext *gb, int width, int height,
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
319 static int dxtory_decode_v2_rgb(AVCodecContext *avctx, AVFrame *pic,
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
378 static int dx2_decode_slice_410(GetBitContext *gb, int width, int height,
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
405 static int dxtory_decode_v2_410(AVCodecContext *avctx, AVFrame *pic,
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
481 static int dx2_decode_slice_420(GetBitContext *gb, int width, int height,
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
509 static int dxtory_decode_v2_420(AVCodecContext *avctx, AVFrame *pic,
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
585 static int dx2_decode_slice_444(GetBitContext *gb, int width, int height,
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
610 static int dxtory_decode_v2_444(AVCodecContext *avctx, AVFrame *pic,
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,
716                                    AV_PIX_FMT_RGB565LE, 2);
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,
724                                    AV_PIX_FMT_RGB555LE, 2);
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
738     pic->pict_type = AV_PICTURE_TYPE_I;
739     pic->key_frame = 1;
740     *got_frame = 1;
741
742     return avpkt->size;
743 }
744
745 AVCodec ff_dxtory_decoder = {
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 };