]> git.sesse.net Git - ffmpeg/blob - libavcodec/dxtory.c
avcodec/dxtory: add missed rgb555/rgb565 formats for vflip case
[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 #include "libavutil/common.h"
26 #include "libavutil/intreadwrite.h"
27
28 #define BITSTREAM_READER_LE
29 #include "avcodec.h"
30 #include "bytestream.h"
31 #include "get_bits.h"
32 #include "internal.h"
33 #include "unary.h"
34
35 static int64_t get_raw_size(enum AVPixelFormat fmt, int width, int height)
36 {
37     switch (fmt) {
38     case AV_PIX_FMT_RGB555LE:
39     case AV_PIX_FMT_RGB565LE:
40         return width * height * 2LL;
41     case AV_PIX_FMT_RGB24:
42     case AV_PIX_FMT_BGR24:
43     case AV_PIX_FMT_YUV444P:
44         return width * height * 3LL;
45     case AV_PIX_FMT_YUV420P:
46         return (int64_t)(width * height) + AV_CEIL_RSHIFT(width, 1) * AV_CEIL_RSHIFT(height, 1);
47     case AV_PIX_FMT_YUV410P:
48         return (int64_t)(width * height) + AV_CEIL_RSHIFT(width, 2) * AV_CEIL_RSHIFT(height, 2);
49     }
50
51     return 0;
52 }
53
54 static void do_vflip(AVCodecContext *avctx, AVFrame *pic, int vflip)
55 {
56     if (!vflip)
57         return;
58
59     switch (pic->format) {
60     case AV_PIX_FMT_YUV444P:
61         pic->data[1] += (avctx->height - 1) * pic->linesize[1];
62         pic->linesize[1] = -pic->linesize[1];
63         pic->data[2] += (avctx->height - 1) * pic->linesize[2];
64         pic->linesize[2] = -pic->linesize[2];
65     case AV_PIX_FMT_RGB555LE:
66     case AV_PIX_FMT_RGB565LE:
67     case AV_PIX_FMT_BGR24:
68     case AV_PIX_FMT_RGB24:
69         pic->data[0] += (avctx->height - 1) * pic->linesize[0];
70         pic->linesize[0] = -pic->linesize[0];
71         break;
72     case AV_PIX_FMT_YUV410P:
73         pic->data[0] += (avctx->height - 1) * pic->linesize[0];
74         pic->linesize[0] = -pic->linesize[0];
75         pic->data[1] += (AV_CEIL_RSHIFT(avctx->height, 2) - 1) * pic->linesize[1];
76         pic->linesize[1] = -pic->linesize[1];
77         pic->data[2] += (AV_CEIL_RSHIFT(avctx->height, 2) - 1) * pic->linesize[2];
78         pic->linesize[2] = -pic->linesize[2];
79         break;
80     case AV_PIX_FMT_YUV420P:
81         pic->data[0] += (avctx->height - 1) * pic->linesize[0];
82         pic->linesize[0] = -pic->linesize[0];
83         pic->data[1] += (AV_CEIL_RSHIFT(avctx->height, 1) - 1) * pic->linesize[1];
84         pic->linesize[1] = -pic->linesize[1];
85         pic->data[2] += (AV_CEIL_RSHIFT(avctx->height, 1) - 1) * pic->linesize[2];
86         pic->linesize[2] = -pic->linesize[2];
87         break;
88     }
89 }
90
91 static int dxtory_decode_v1_rgb(AVCodecContext *avctx, AVFrame *pic,
92                                 const uint8_t *src, int src_size,
93                                 int id, int bpp, uint32_t vflipped)
94 {
95     int h;
96     uint8_t *dst;
97     int ret;
98
99     if (src_size < get_raw_size(id, avctx->width, avctx->height)) {
100         av_log(avctx, AV_LOG_ERROR, "packet too small\n");
101         return AVERROR_INVALIDDATA;
102     }
103
104     avctx->pix_fmt = id;
105     if ((ret = ff_get_buffer(avctx, pic, 0)) < 0)
106         return ret;
107
108     do_vflip(avctx, pic, vflipped);
109
110     dst = pic->data[0];
111     for (h = 0; h < avctx->height; h++) {
112         memcpy(dst, src, avctx->width * bpp);
113         src += avctx->width * bpp;
114         dst += pic->linesize[0];
115     }
116
117     do_vflip(avctx, pic, vflipped);
118
119     return 0;
120 }
121
122 static int dxtory_decode_v1_410(AVCodecContext *avctx, AVFrame *pic,
123                                 const uint8_t *src, int src_size,
124                                 uint32_t vflipped)
125 {
126     int h, w;
127     uint8_t *Y1, *Y2, *Y3, *Y4, *U, *V;
128     int height, width, hmargin, vmargin;
129     int huvborder;
130     int ret;
131
132     if (src_size < get_raw_size(AV_PIX_FMT_YUV410P, avctx->width, avctx->height)) {
133         av_log(avctx, AV_LOG_ERROR, "packet too small\n");
134         return AVERROR_INVALIDDATA;
135     }
136
137     avctx->pix_fmt = AV_PIX_FMT_YUV410P;
138     if ((ret = ff_get_buffer(avctx, pic, 0)) < 0)
139         return ret;
140
141     do_vflip(avctx, pic, vflipped);
142
143     height = avctx->height & ~3;
144     width  = avctx->width  & ~3;
145     hmargin = avctx->width  - width;
146     vmargin = avctx->height - height;
147     huvborder = AV_CEIL_RSHIFT(avctx->width, 2) - 1;
148
149     Y1 = pic->data[0];
150     Y2 = pic->data[0] + pic->linesize[0];
151     Y3 = pic->data[0] + pic->linesize[0] * 2;
152     Y4 = pic->data[0] + pic->linesize[0] * 3;
153     U  = pic->data[1];
154     V  = pic->data[2];
155     for (h = 0; h < height; h += 4) {
156         for (w = 0; w < width; w += 4) {
157             AV_COPY32U(Y1 + w, src);
158             AV_COPY32U(Y2 + w, src + 4);
159             AV_COPY32U(Y3 + w, src + 8);
160             AV_COPY32U(Y4 + w, src + 12);
161             U[w >> 2] = src[16] + 0x80;
162             V[w >> 2] = src[17] + 0x80;
163             src += 18;
164         }
165         if (hmargin) {
166             for (w = 0; w < hmargin; w++) {
167                 Y1[width + w] = src[w];
168                 Y2[width + w] = src[w + hmargin * 1];
169                 Y3[width + w] = src[w + hmargin * 2];
170                 Y4[width + w] = src[w + hmargin * 3];
171             }
172             src += 4 * hmargin;
173             U[huvborder] = src[0] + 0x80;
174             V[huvborder] = src[1] + 0x80;
175             src += 2;
176         }
177         Y1 += pic->linesize[0] << 2;
178         Y2 += pic->linesize[0] << 2;
179         Y3 += pic->linesize[0] << 2;
180         Y4 += pic->linesize[0] << 2;
181         U  += pic->linesize[1];
182         V  += pic->linesize[2];
183     }
184
185     if (vmargin) {
186         for (w = 0; w < width; w += 4) {
187             AV_COPY32U(Y1 + w, src);
188             if (vmargin > 1)
189                 AV_COPY32U(Y2 + w, src + 4);
190             if (vmargin > 2)
191                 AV_COPY32U(Y3 + w, src + 8);
192             src += 4 * vmargin;
193             U[w >> 2] = src[0] + 0x80;
194             V[w >> 2] = src[1] + 0x80;
195             src += 2;
196         }
197         if (hmargin) {
198             for (w = 0; w < hmargin; w++) {
199                 AV_COPY32U(Y1 + w, src);
200                 if (vmargin > 1)
201                     AV_COPY32U(Y2 + w, src + 4);
202                 if (vmargin > 2)
203                     AV_COPY32U(Y3 + w, src + 8);
204                 src += 4 * vmargin;
205             }
206             U[huvborder] = src[0] + 0x80;
207             V[huvborder] = src[1] + 0x80;
208             src += 2;
209         }
210     }
211
212     do_vflip(avctx, pic, vflipped);
213
214     return 0;
215 }
216
217 static int dxtory_decode_v1_420(AVCodecContext *avctx, AVFrame *pic,
218                                 const uint8_t *src, int src_size,
219                                 uint32_t vflipped)
220 {
221     int h, w;
222     uint8_t *Y1, *Y2, *U, *V;
223     int height, width, hmargin, vmargin;
224     int huvborder;
225     int ret;
226
227     if (src_size < get_raw_size(AV_PIX_FMT_YUV420P, avctx->width, avctx->height)) {
228         av_log(avctx, AV_LOG_ERROR, "packet too small\n");
229         return AVERROR_INVALIDDATA;
230     }
231
232     avctx->pix_fmt = AV_PIX_FMT_YUV420P;
233     if ((ret = ff_get_buffer(avctx, pic, 0)) < 0)
234         return ret;
235
236     do_vflip(avctx, pic, vflipped);
237
238     height = avctx->height & ~1;
239     width  = avctx->width  & ~1;
240     hmargin = avctx->width  - width;
241     vmargin = avctx->height - height;
242     huvborder = AV_CEIL_RSHIFT(avctx->width, 1) - 1;
243
244     Y1 = pic->data[0];
245     Y2 = pic->data[0] + pic->linesize[0];
246     U  = pic->data[1];
247     V  = pic->data[2];
248     for (h = 0; h < height; h += 2) {
249         for (w = 0; w < width; w += 2) {
250             AV_COPY16(Y1 + w, src);
251             AV_COPY16(Y2 + w, src + 2);
252             U[w >> 1] = src[4] + 0x80;
253             V[w >> 1] = src[5] + 0x80;
254             src += 6;
255         }
256         if (hmargin) {
257             Y1[width + 1] = src[0];
258             Y2[width + 1] = src[1];
259             U[huvborder] = src[2] + 0x80;
260             V[huvborder] = src[3] + 0x80;
261             src += 4;
262         }
263         Y1 += pic->linesize[0] << 1;
264         Y2 += pic->linesize[0] << 1;
265         U  += pic->linesize[1];
266         V  += pic->linesize[2];
267     }
268
269     if (vmargin) {
270         for (w = 0; w < width; w += 2) {
271             AV_COPY16U(Y1 + w, src);
272             U[w >> 1] = src[0] + 0x80;
273             V[w >> 1] = src[1] + 0x80;
274             src += 4;
275         }
276         if (hmargin) {
277             Y1[w] = src[0];
278             U[huvborder] = src[1] + 0x80;
279             V[huvborder] = src[2] + 0x80;
280             src += 3;
281         }
282     }
283
284     do_vflip(avctx, pic, vflipped);
285
286     return 0;
287 }
288
289 static int dxtory_decode_v1_444(AVCodecContext *avctx, AVFrame *pic,
290                                 const uint8_t *src, int src_size,
291                                 uint32_t vflipped)
292 {
293     int h, w;
294     uint8_t *Y, *U, *V;
295     int ret;
296
297     if (src_size < get_raw_size(AV_PIX_FMT_YUV444P, avctx->width, avctx->height)) {
298         av_log(avctx, AV_LOG_ERROR, "packet too small\n");
299         return AVERROR_INVALIDDATA;
300     }
301
302     avctx->pix_fmt = AV_PIX_FMT_YUV444P;
303     if ((ret = ff_get_buffer(avctx, pic, 0)) < 0)
304         return ret;
305
306     do_vflip(avctx, pic, vflipped);
307
308     Y = pic->data[0];
309     U = pic->data[1];
310     V = pic->data[2];
311     for (h = 0; h < avctx->height; h++) {
312         for (w = 0; w < avctx->width; w++) {
313             Y[w] = *src++;
314             U[w] = *src++ ^ 0x80;
315             V[w] = *src++ ^ 0x80;
316         }
317         Y += pic->linesize[0];
318         U += pic->linesize[1];
319         V += pic->linesize[2];
320     }
321
322     do_vflip(avctx, pic, vflipped);
323
324     return 0;
325 }
326
327 static const uint8_t def_lru[8] = { 0x00, 0x20, 0x40, 0x60, 0x80, 0xA0, 0xC0, 0xFF };
328 static const uint8_t def_lru_555[8] = { 0x00, 0x08, 0x10, 0x18, 0x1F };
329 static const uint8_t def_lru_565[8] = { 0x00, 0x08, 0x10, 0x20, 0x30, 0x3F };
330
331 static inline uint8_t decode_sym(GetBitContext *gb, uint8_t lru[8])
332 {
333     uint8_t c, val;
334
335     c = get_unary(gb, 0, 8);
336     if (!c) {
337         val = get_bits(gb, 8);
338         memmove(lru + 1, lru, sizeof(*lru) * (8 - 1));
339     } else {
340         val = lru[c - 1];
341         memmove(lru + 1, lru, sizeof(*lru) * (c - 1));
342     }
343     lru[0] = val;
344
345     return val;
346 }
347
348 static int check_slice_size(AVCodecContext *avctx,
349                             const uint8_t *src, int src_size,
350                             int slice_size, int off)
351 {
352     int cur_slice_size;
353
354     if (slice_size > src_size - off) {
355         av_log(avctx, AV_LOG_ERROR,
356                "invalid slice size %d (only %d 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 %d\n",
362                slice_size);
363         return AVERROR_INVALIDDATA;
364     }
365
366     cur_slice_size = AV_RL32(src + off);
367     if (cur_slice_size != slice_size - 16) {
368         av_log(avctx, AV_LOG_ERROR,
369                "Slice sizes mismatch: got %d instead of %d\n",
370                cur_slice_size, slice_size - 16);
371     }
372
373     return 0;
374 }
375
376 static int load_buffer(AVCodecContext *avctx,
377                        const uint8_t *src, int src_size,
378                        GetByteContext *gb,
379                        int *nslices, int *off)
380 {
381     bytestream2_init(gb, src, src_size);
382     *nslices = bytestream2_get_le16(gb);
383     *off = FFALIGN(*nslices * 4 + 2, 16);
384     if (src_size < *off) {
385         av_log(avctx, AV_LOG_ERROR, "no slice data\n");
386         return AVERROR_INVALIDDATA;
387     }
388
389     if (!*nslices) {
390         avpriv_request_sample(avctx, "%d slices for %dx%d", *nslices,
391                               avctx->width, avctx->height);
392         return AVERROR_PATCHWELCOME;
393     }
394
395     return 0;
396 }
397
398 static inline uint8_t decode_sym_565(GetBitContext *gb, uint8_t lru[8],
399                                      int bits)
400 {
401     uint8_t c, val;
402
403     c = get_unary(gb, 0, bits);
404     if (!c) {
405         val = get_bits(gb, bits);
406         memmove(lru + 1, lru, sizeof(*lru) * (6 - 1));
407     } else {
408         val = lru[c - 1];
409         memmove(lru + 1, lru, sizeof(*lru) * (c - 1));
410     }
411     lru[0] = val;
412
413     return val;
414 }
415
416 typedef int (*decode_slice_func)(GetBitContext *gb, AVFrame *frame,
417                                  int line, int height, uint8_t lru[3][8]);
418
419 typedef void (*setup_lru_func)(uint8_t lru[3][8]);
420
421 static int dxtory_decode_v2(AVCodecContext *avctx, AVFrame *pic,
422                             const uint8_t *src, int src_size,
423                             decode_slice_func decode_slice,
424                             setup_lru_func setup_lru,
425                             enum AVPixelFormat fmt,
426                             uint32_t vflipped)
427 {
428     GetByteContext gb, gb_check;
429     GetBitContext  gb2;
430     int nslices, slice, line = 0;
431     uint32_t off, slice_size;
432     uint64_t off_check;
433     uint8_t lru[3][8];
434     int ret;
435
436     ret = load_buffer(avctx, src, src_size, &gb, &nslices, &off);
437     if (ret < 0)
438         return ret;
439
440     off_check = off;
441     gb_check = gb;
442     for (slice = 0; slice < nslices; slice++) {
443         slice_size = bytestream2_get_le32(&gb_check);
444
445         if (slice_size <= 16 + (avctx->height * avctx->width / (8 * nslices)))
446             return AVERROR_INVALIDDATA;
447         off_check += slice_size;
448     }
449
450     if (off_check - avctx->discard_damaged_percentage*off_check/100 > src_size)
451         return AVERROR_INVALIDDATA;
452
453     avctx->pix_fmt = fmt;
454     if ((ret = ff_get_buffer(avctx, pic, 0)) < 0)
455         return ret;
456
457     do_vflip(avctx, pic, vflipped);
458
459     for (slice = 0; slice < nslices; slice++) {
460         slice_size = bytestream2_get_le32(&gb);
461
462         setup_lru(lru);
463
464         ret = check_slice_size(avctx, src, src_size, slice_size, off);
465         if (ret < 0)
466             return ret;
467
468         if ((ret = init_get_bits8(&gb2, src + off + 16, slice_size - 16)) < 0)
469             return ret;
470
471         line += decode_slice(&gb2, pic, line, avctx->height - line, lru);
472
473         off += slice_size;
474     }
475
476     if (avctx->height - line) {
477         avpriv_request_sample(avctx, "Not enough slice data available");
478     }
479
480     do_vflip(avctx, pic, vflipped);
481
482     return 0;
483 }
484
485 av_always_inline
486 static int dx2_decode_slice_5x5(GetBitContext *gb, AVFrame *frame,
487                                 int line, int left, uint8_t lru[3][8],
488                                 int is_565)
489 {
490     int x, y;
491     int r, g, b;
492     int width    = frame->width;
493     int stride   = frame->linesize[0];
494     uint8_t *dst = frame->data[0] + stride * line;
495
496     for (y = 0; y < left && get_bits_left(gb) >= 3 * width; y++) {
497         for (x = 0; x < width; x++) {
498             b = decode_sym_565(gb, lru[0], 5);
499             g = decode_sym_565(gb, lru[1], is_565 ? 6 : 5);
500             r = decode_sym_565(gb, lru[2], 5);
501             dst[x * 3 + 0] = (r << 3) | (r >> 2);
502             dst[x * 3 + 1] = is_565 ? (g << 2) | (g >> 4) : (g << 3) | (g >> 2);
503             dst[x * 3 + 2] = (b << 3) | (b >> 2);
504         }
505
506         dst += stride;
507     }
508
509     return y;
510 }
511
512 static void setup_lru_555(uint8_t lru[3][8])
513 {
514     memcpy(lru[0], def_lru_555, 8 * sizeof(*def_lru));
515     memcpy(lru[1], def_lru_555, 8 * sizeof(*def_lru));
516     memcpy(lru[2], def_lru_555, 8 * sizeof(*def_lru));
517 }
518
519 static void setup_lru_565(uint8_t lru[3][8])
520 {
521     memcpy(lru[0], def_lru_555, 8 * sizeof(*def_lru));
522     memcpy(lru[1], def_lru_565, 8 * sizeof(*def_lru));
523     memcpy(lru[2], def_lru_555, 8 * sizeof(*def_lru));
524 }
525
526 static int dx2_decode_slice_555(GetBitContext *gb, AVFrame *frame,
527                                 int line, int left, uint8_t lru[3][8])
528 {
529     return dx2_decode_slice_5x5(gb, frame, line, left, lru, 0);
530 }
531
532 static int dx2_decode_slice_565(GetBitContext *gb, AVFrame *frame,
533                                 int line, int left, uint8_t lru[3][8])
534 {
535     return dx2_decode_slice_5x5(gb, frame, line, left, lru, 1);
536 }
537
538 static int dxtory_decode_v2_565(AVCodecContext *avctx, AVFrame *pic,
539                                 const uint8_t *src, int src_size, int is_565,
540                                 uint32_t vflipped)
541 {
542     enum AVPixelFormat fmt = AV_PIX_FMT_RGB24;
543     if (is_565)
544         return dxtory_decode_v2(avctx, pic, src, src_size,
545                                 dx2_decode_slice_565,
546                                 setup_lru_565,
547                                 fmt, vflipped);
548     else
549         return dxtory_decode_v2(avctx, pic, src, src_size,
550                                 dx2_decode_slice_555,
551                                 setup_lru_555,
552                                 fmt, vflipped);
553 }
554
555 static int dx2_decode_slice_rgb(GetBitContext *gb, AVFrame *frame,
556                                 int line, int left, uint8_t lru[3][8])
557 {
558     int x, y;
559     int width    = frame->width;
560     int stride   = frame->linesize[0];
561     uint8_t *dst = frame->data[0] + stride * line;
562
563     for (y = 0; y < left && get_bits_left(gb) >= 3 * width; y++) {
564         for (x = 0; x < width; x++) {
565             dst[x * 3 + 0] = decode_sym(gb, lru[0]);
566             dst[x * 3 + 1] = decode_sym(gb, lru[1]);
567             dst[x * 3 + 2] = decode_sym(gb, lru[2]);
568         }
569
570         dst += stride;
571     }
572
573     return y;
574 }
575
576 static void default_setup_lru(uint8_t lru[3][8])
577 {
578     int i;
579
580     for (i = 0; i < 3; i++)
581         memcpy(lru[i], def_lru, 8 * sizeof(*def_lru));
582 }
583
584 static int dxtory_decode_v2_rgb(AVCodecContext *avctx, AVFrame *pic,
585                                 const uint8_t *src, int src_size,
586                                 uint32_t vflipped)
587 {
588     return dxtory_decode_v2(avctx, pic, src, src_size,
589                             dx2_decode_slice_rgb,
590                             default_setup_lru,
591                             AV_PIX_FMT_BGR24, vflipped);
592 }
593
594 static int dx2_decode_slice_410(GetBitContext *gb, AVFrame *frame,
595                                 int line, int left,
596                                 uint8_t lru[3][8])
597 {
598     int x, y, i, j;
599     int width   = frame->width;
600
601     int ystride = frame->linesize[0];
602     int ustride = frame->linesize[1];
603     int vstride = frame->linesize[2];
604
605     uint8_t *Y  = frame->data[0] + ystride * line;
606     uint8_t *U  = frame->data[1] + (ustride >> 2) * line;
607     uint8_t *V  = frame->data[2] + (vstride >> 2) * line;
608
609     int h, w, hmargin, vmargin;
610     int huvborder;
611
612     h = frame->height & ~3;
613     w = frame->width  & ~3;
614     hmargin = frame->width  - w;
615     vmargin = frame->height - h;
616     huvborder = AV_CEIL_RSHIFT(frame->width, 2) - 1;
617
618     for (y = 0; y < left - 3 && get_bits_left(gb) >= 18 * w / 4 + hmargin * 4 + (!!hmargin * 2); y += 4) {
619         for (x = 0; x < w; x += 4) {
620             for (j = 0; j < 4; j++)
621                 for (i = 0; i < 4; i++)
622                     Y[x + i + j * ystride] = decode_sym(gb, lru[0]);
623             U[x >> 2] = decode_sym(gb, lru[1]) ^ 0x80;
624             V[x >> 2] = decode_sym(gb, lru[2]) ^ 0x80;
625         }
626         if (hmargin) {
627             for (j = 0; j < 4; j++)
628                 for (i = 0; i < hmargin; i++)
629                     Y[x + i + j * ystride] = decode_sym(gb, lru[0]);
630             U[huvborder] = decode_sym(gb, lru[1]) ^ 0x80;
631             V[huvborder] = decode_sym(gb, lru[2]) ^ 0x80;
632         }
633
634         Y += ystride << 2;
635         U += ustride;
636         V += vstride;
637     }
638
639     if (vmargin && y + vmargin == left) {
640         for (x = 0; x < width; x += 4) {
641             for (j = 0; j < vmargin; j++)
642                 for (i = 0; i < 4; i++)
643                     Y[x + i + j * ystride] = decode_sym(gb, lru[0]);
644             U[x >> 2] = decode_sym(gb, lru[1]) ^ 0x80;
645             V[x >> 2] = decode_sym(gb, lru[2]) ^ 0x80;
646         }
647         if (hmargin) {
648             for (j = 0; j < vmargin; j++) {
649                 for (i = 0; i < hmargin; i++)
650                     Y[x + i + j * ystride] = decode_sym(gb, lru[0]);
651             }
652             U[huvborder] = decode_sym(gb, lru[1]) ^ 0x80;
653             V[huvborder] = decode_sym(gb, lru[2]) ^ 0x80;
654         }
655
656         y += vmargin;
657     }
658
659     return y;
660 }
661
662
663 static int dxtory_decode_v2_410(AVCodecContext *avctx, AVFrame *pic,
664                                 const uint8_t *src, int src_size,
665                                 uint32_t vflipped)
666 {
667     return dxtory_decode_v2(avctx, pic, src, src_size,
668                             dx2_decode_slice_410,
669                             default_setup_lru,
670                             AV_PIX_FMT_YUV410P, vflipped);
671 }
672
673 static int dx2_decode_slice_420(GetBitContext *gb, AVFrame *frame,
674                                 int line, int left,
675                                 uint8_t lru[3][8])
676 {
677     int x, y;
678
679     int width    = frame->width;
680
681     int ystride = frame->linesize[0];
682     int ustride = frame->linesize[1];
683     int vstride = frame->linesize[2];
684
685     uint8_t *Y  = frame->data[0] + ystride * line;
686     uint8_t *U  = frame->data[1] + (ustride >> 1) * line;
687     uint8_t *V  = frame->data[2] + (vstride >> 1) * line;
688
689     int h, w, hmargin, vmargin;
690     int huvborder;
691
692     h = frame->height & ~1;
693     w = frame->width  & ~1;
694     hmargin = frame->width  - w;
695     vmargin = frame->height - h;
696     huvborder = AV_CEIL_RSHIFT(frame->width, 1) - 1;
697
698     for (y = 0; y < left - 1 && get_bits_left(gb) >= 3 * w + hmargin * 4; y += 2) {
699         for (x = 0; x < w; x += 2) {
700             Y[x + 0 + 0 * ystride] = decode_sym(gb, lru[0]);
701             Y[x + 1 + 0 * ystride] = decode_sym(gb, lru[0]);
702             Y[x + 0 + 1 * ystride] = decode_sym(gb, lru[0]);
703             Y[x + 1 + 1 * ystride] = decode_sym(gb, lru[0]);
704             U[x >> 1] = decode_sym(gb, lru[1]) ^ 0x80;
705             V[x >> 1] = decode_sym(gb, lru[2]) ^ 0x80;
706         }
707         if (hmargin) {
708             Y[x + 0 * ystride] = decode_sym(gb, lru[0]);
709             Y[x + 1 * ystride] = decode_sym(gb, lru[0]);
710             U[huvborder] = decode_sym(gb, lru[1]) ^ 0x80;
711             V[huvborder] = decode_sym(gb, lru[2]) ^ 0x80;
712         }
713
714         Y += ystride << 1;
715         U += ustride;
716         V += vstride;
717     }
718
719     if (vmargin) {
720         for (x = 0; x < width; x += 2) {
721             Y[x + 0]  = decode_sym(gb, lru[0]);
722             U[x >> 1] = decode_sym(gb, lru[1]) ^ 0x80;
723             V[x >> 1] = decode_sym(gb, lru[2]) ^ 0x80;
724         }
725         if (hmargin) {
726             Y[x]         = decode_sym(gb, lru[0]);
727             U[huvborder] = decode_sym(gb, lru[1]) ^ 0x80;
728             V[huvborder] = decode_sym(gb, lru[2]) ^ 0x80;
729         }
730     }
731
732     return y;
733 }
734
735 static int dxtory_decode_v2_420(AVCodecContext *avctx, AVFrame *pic,
736                                 const uint8_t *src, int src_size,
737                                 uint32_t vflipped)
738 {
739     return dxtory_decode_v2(avctx, pic, src, src_size,
740                             dx2_decode_slice_420,
741                             default_setup_lru,
742                             AV_PIX_FMT_YUV420P, vflipped);
743 }
744
745 static int dx2_decode_slice_444(GetBitContext *gb, AVFrame *frame,
746                                 int line, int left,
747                                 uint8_t lru[3][8])
748 {
749     int x, y;
750
751     int width   = frame->width;
752
753     int ystride = frame->linesize[0];
754     int ustride = frame->linesize[1];
755     int vstride = frame->linesize[2];
756
757     uint8_t *Y  = frame->data[0] + ystride * line;
758     uint8_t *U  = frame->data[1] + ustride * line;
759     uint8_t *V  = frame->data[2] + vstride * line;
760
761     for (y = 0; y < left && get_bits_left(gb) >= 3 * width; y++) {
762         for (x = 0; x < width; x++) {
763             Y[x] = decode_sym(gb, lru[0]);
764             U[x] = decode_sym(gb, lru[1]) ^ 0x80;
765             V[x] = decode_sym(gb, lru[2]) ^ 0x80;
766         }
767
768         Y += ystride;
769         U += ustride;
770         V += vstride;
771     }
772
773     return y;
774 }
775
776 static int dxtory_decode_v2_444(AVCodecContext *avctx, AVFrame *pic,
777                                 const uint8_t *src, int src_size,
778                                 uint32_t vflipped)
779 {
780     return dxtory_decode_v2(avctx, pic, src, src_size,
781                             dx2_decode_slice_444,
782                             default_setup_lru,
783                             AV_PIX_FMT_YUV444P, vflipped);
784 }
785
786 static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
787                         AVPacket *avpkt)
788 {
789     AVFrame *pic = data;
790     const uint8_t *src = avpkt->data;
791     uint32_t type;
792     int vflipped, ret;
793
794     if (avpkt->size < 16) {
795         av_log(avctx, AV_LOG_ERROR, "packet too small\n");
796         return AVERROR_INVALIDDATA;
797     }
798
799     type = AV_RB32(src);
800     vflipped = !!(type & 0x20);
801
802     switch (type) {
803     case 0x01000021:
804     case 0x01000001:
805         ret = dxtory_decode_v1_rgb(avctx, pic, src + 16, avpkt->size - 16,
806                                    AV_PIX_FMT_BGR24, 3, vflipped);
807         break;
808     case 0x01000029:
809     case 0x01000009:
810         ret = dxtory_decode_v2_rgb(avctx, pic, src + 16, avpkt->size - 16, vflipped);
811         break;
812     case 0x02000021:
813     case 0x02000001:
814         ret = dxtory_decode_v1_420(avctx, pic, src + 16, avpkt->size - 16, vflipped);
815         break;
816     case 0x02000029:
817     case 0x02000009:
818         ret = dxtory_decode_v2_420(avctx, pic, src + 16, avpkt->size - 16, vflipped);
819         break;
820     case 0x03000021:
821     case 0x03000001:
822         ret = dxtory_decode_v1_410(avctx, pic, src + 16, avpkt->size - 16, vflipped);
823         break;
824     case 0x03000029:
825     case 0x03000009:
826         ret = dxtory_decode_v2_410(avctx, pic, src + 16, avpkt->size - 16, vflipped);
827         break;
828     case 0x04000021:
829     case 0x04000001:
830         ret = dxtory_decode_v1_444(avctx, pic, src + 16, avpkt->size - 16, vflipped);
831         break;
832     case 0x04000029:
833     case 0x04000009:
834         ret = dxtory_decode_v2_444(avctx, pic, src + 16, avpkt->size - 16, vflipped);
835         break;
836     case 0x17000021:
837     case 0x17000001:
838         ret = dxtory_decode_v1_rgb(avctx, pic, src + 16, avpkt->size - 16,
839                                    AV_PIX_FMT_RGB565LE, 2, vflipped);
840         break;
841     case 0x17000029:
842     case 0x17000009:
843         ret = dxtory_decode_v2_565(avctx, pic, src + 16, avpkt->size - 16, 1, vflipped);
844         break;
845     case 0x18000021:
846     case 0x19000021:
847     case 0x18000001:
848     case 0x19000001:
849         ret = dxtory_decode_v1_rgb(avctx, pic, src + 16, avpkt->size - 16,
850                                    AV_PIX_FMT_RGB555LE, 2, vflipped);
851         break;
852     case 0x18000029:
853     case 0x19000029:
854     case 0x18000009:
855     case 0x19000009:
856         ret = dxtory_decode_v2_565(avctx, pic, src + 16, avpkt->size - 16, 0, vflipped);
857         break;
858     default:
859         avpriv_request_sample(avctx, "Frame header %"PRIX32, type);
860         return AVERROR_PATCHWELCOME;
861     }
862
863     if (ret)
864         return ret;
865
866     pic->pict_type = AV_PICTURE_TYPE_I;
867     pic->key_frame = 1;
868     *got_frame = 1;
869
870     return avpkt->size;
871 }
872
873 AVCodec ff_dxtory_decoder = {
874     .name           = "dxtory",
875     .long_name      = NULL_IF_CONFIG_SMALL("Dxtory"),
876     .type           = AVMEDIA_TYPE_VIDEO,
877     .id             = AV_CODEC_ID_DXTORY,
878     .decode         = decode_frame,
879     .capabilities   = AV_CODEC_CAP_DR1,
880 };