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