xref: /third_party/ffmpeg/libavcodec/argo.c (revision cabdff1a)
1/*
2 * Argonaut Games Video decoder
3 * Copyright (c) 2020 Paul B Mahol
4 *
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25
26#include "libavutil/imgutils.h"
27#include "libavutil/internal.h"
28#include "libavutil/intreadwrite.h"
29
30#include "avcodec.h"
31#include "bytestream.h"
32#include "codec_internal.h"
33#include "internal.h"
34
35typedef struct ArgoContext {
36    GetByteContext gb;
37
38    int bpp;
39    int key;
40    int mv0[128][2];
41    int mv1[16][2];
42    uint32_t pal[256];
43    AVFrame *frame;
44} ArgoContext;
45
46static int decode_pal8(AVCodecContext *avctx, uint32_t *pal)
47{
48    ArgoContext *s = avctx->priv_data;
49    GetByteContext *gb = &s->gb;
50    int start, count;
51
52    start = bytestream2_get_le16(gb);
53    count = bytestream2_get_le16(gb);
54
55    if (start + count > 256)
56        return AVERROR_INVALIDDATA;
57
58    if (bytestream2_get_bytes_left(gb) < 3 * count)
59        return AVERROR_INVALIDDATA;
60
61    for (int i = 0; i < count; i++)
62        pal[start + i] = (0xFFU << 24) | bytestream2_get_be24u(gb);
63
64    return 0;
65}
66
67static int decode_avcf(AVCodecContext *avctx, AVFrame *frame)
68{
69    ArgoContext *s = avctx->priv_data;
70    GetByteContext *gb = &s->gb;
71    const int l = frame->linesize[0];
72    const uint8_t *map = gb->buffer;
73    uint8_t *dst = frame->data[0];
74
75    if (bytestream2_get_bytes_left(gb) < 1024 + (frame->width / 2) * (frame->height / 2))
76        return AVERROR_INVALIDDATA;
77
78    bytestream2_skipu(gb, 1024);
79    for (int y = 0; y < frame->height; y += 2) {
80        for (int x = 0; x < frame->width; x += 2) {
81            int index = bytestream2_get_byteu(gb);
82            const uint8_t *block = map + index * 4;
83
84            dst[x+0]   = block[0];
85            dst[x+1]   = block[1];
86            dst[x+l]   = block[2];
87            dst[x+l+1] = block[3];
88        }
89
90        dst += frame->linesize[0] * 2;
91    }
92
93    return 0;
94}
95
96static int decode_alcd(AVCodecContext *avctx, AVFrame *frame)
97{
98    ArgoContext *s = avctx->priv_data;
99    GetByteContext *gb = &s->gb;
100    GetByteContext sb;
101    const int l = frame->linesize[0];
102    const uint8_t *map = gb->buffer;
103    uint8_t *dst = frame->data[0];
104    uint8_t codes = 0;
105    int count = 0;
106
107    if (bytestream2_get_bytes_left(gb) < 1024 + (((frame->width / 2) * (frame->height / 2) + 7) >> 3))
108        return AVERROR_INVALIDDATA;
109
110    bytestream2_skipu(gb, 1024);
111    sb = *gb;
112    bytestream2_skipu(gb, ((frame->width / 2) * (frame->height / 2) + 7) >> 3);
113
114    for (int y = 0; y < frame->height; y += 2) {
115        for (int x = 0; x < frame->width; x += 2) {
116            const uint8_t *block;
117            int index;
118
119            if (count == 0) {
120                codes = bytestream2_get_byteu(&sb);
121                count = 8;
122            }
123
124            if (codes & 0x80) {
125                index = bytestream2_get_byte(gb);
126                block = map + index * 4;
127
128                dst[x+0]   = block[0];
129                dst[x+1]   = block[1];
130                dst[x+l]   = block[2];
131                dst[x+l+1] = block[3];
132            }
133
134            codes <<= 1;
135            count--;
136        }
137
138        dst += frame->linesize[0] * 2;
139    }
140
141    return 0;
142}
143
144static int decode_mad1(AVCodecContext *avctx, AVFrame *frame)
145{
146    ArgoContext *s = avctx->priv_data;
147    GetByteContext *gb = &s->gb;
148    const int w = frame->width;
149    const int h = frame->height;
150    const int l = frame->linesize[0];
151
152    while (bytestream2_get_bytes_left(gb) > 0) {
153        int size, type, pos, dy;
154        uint8_t *dst;
155
156        type = bytestream2_get_byte(gb);
157        if (type == 0xFF)
158            break;
159
160        switch (type) {
161        case 8:
162            dst = frame->data[0];
163            for (int y = 0; y < h; y += 8) {
164                for (int x = 0; x < w; x += 8) {
165                    int fill = bytestream2_get_byte(gb);
166                    uint8_t *ddst = dst + x;
167
168                    for (int by = 0; by < 8; by++) {
169                        memset(ddst, fill, 8);
170                        ddst += l;
171                    }
172                }
173
174                dst += 8 * l;
175            }
176            break;
177        case 7:
178            while (bytestream2_get_bytes_left(gb) > 0) {
179                int bsize = bytestream2_get_byte(gb);
180                uint8_t *src;
181                int count;
182
183                if (!bsize)
184                    break;
185
186                count = bytestream2_get_be16(gb);
187                while (count > 0) {
188                    int mvx, mvy, a, b, c, mx, my;
189                    int bsize_w, bsize_h;
190
191                    bsize_w = bsize_h = bsize;
192                    if (bytestream2_get_bytes_left(gb) < 4)
193                        return AVERROR_INVALIDDATA;
194                    mvx = bytestream2_get_byte(gb) * bsize;
195                    mvy = bytestream2_get_byte(gb) * bsize;
196                    a = bytestream2_get_byte(gb);
197                    b = bytestream2_get_byte(gb);
198                    c = ((a & 0x3F) << 8) + b;
199                    mx = mvx + (c  & 0x7F) - 64;
200                    my = mvy + (c >>    7) - 64;
201
202                    if (mvy < 0 || mvy >= h)
203                        return AVERROR_INVALIDDATA;
204
205                    if (mvx < 0 || mvx >= w)
206                        return AVERROR_INVALIDDATA;
207
208                    if (my < 0 || my >= h)
209                        return AVERROR_INVALIDDATA;
210
211                    if (mx < 0 || mx >= w)
212                        return AVERROR_INVALIDDATA;
213
214                    dst = frame->data[0] + mvx + l * mvy;
215                    src = frame->data[0] + mx  + l * my;
216
217                    bsize_w = FFMIN3(bsize_w, w - mvx, w - mx);
218                    bsize_h = FFMIN3(bsize_h, h - mvy, h - my);
219
220                    if (mvy >= my && (mvy != my || mvx >= mx)) {
221                        src += (bsize_h - 1) * l;
222                        dst += (bsize_h - 1) * l;
223                        for (int by = 0; by < bsize_h; by++) {
224                            memmove(dst, src, bsize_w);
225                            src -= l;
226                            dst -= l;
227                        }
228                    } else {
229                        for (int by = 0; by < bsize_h; by++) {
230                            memmove(dst, src, bsize_w);
231                            src += l;
232                            dst += l;
233                        }
234                    }
235
236                    count--;
237                }
238            }
239            break;
240        case 6:
241            dst = frame->data[0];
242            if (bytestream2_get_bytes_left(gb) < w * h)
243                return AVERROR_INVALIDDATA;
244            for (int y = 0; y < h; y++) {
245                bytestream2_get_bufferu(gb, dst, w);
246                dst += l;
247            }
248            break;
249        case 5:
250            dst = frame->data[0];
251            for (int y = 0; y < h; y += 2) {
252                for (int x = 0; x < w; x += 2) {
253                    int fill = bytestream2_get_byte(gb);
254                    uint8_t *ddst = dst + x;
255
256                    fill = (fill << 8) | fill;
257                    for (int by = 0; by < 2; by++) {
258                            AV_WN16(ddst, fill);
259
260                        ddst += l;
261                    }
262                }
263
264                dst += 2 * l;
265            }
266            break;
267        case 3:
268            size = bytestream2_get_le16(gb);
269            if (size > 0) {
270                int x = bytestream2_get_byte(gb) * 4;
271                int y = bytestream2_get_byte(gb) * 4;
272                int count = bytestream2_get_byte(gb);
273                int fill = bytestream2_get_byte(gb);
274
275                av_log(avctx, AV_LOG_DEBUG, "%d %d %d %d\n", x, y, count, fill);
276                for (int i = 0; i < count; i++)
277                    ;
278                return AVERROR_PATCHWELCOME;
279            }
280            break;
281        case 2:
282            dst = frame->data[0];
283            pos = 0;
284            dy  = 0;
285            while (bytestream2_get_bytes_left(gb) > 0) {
286                int count = bytestream2_get_byteu(gb);
287                int skip = count & 0x3F;
288
289                count = count >> 6;
290                if (skip == 0x3F) {
291                    pos += 0x3E;
292                    while (pos >= w) {
293                        pos -= w;
294                        dst += l;
295                        dy++;
296                        if (dy >= h)
297                            return 0;
298                    }
299                } else {
300                    pos += skip;
301                    while (pos >= w) {
302                        pos -= w;
303                        dst += l;
304                        dy++;
305                        if (dy >= h)
306                            return 0;
307                    }
308                    while (count >= 0) {
309                        int bits = bytestream2_get_byte(gb);
310
311                        for (int i = 0; i < 4; i++) {
312                            switch (bits & 3) {
313                            case 0:
314                                break;
315                            case 1:
316                                if (dy < 1 && !pos)
317                                    return AVERROR_INVALIDDATA;
318                                else
319                                    dst[pos] = pos ? dst[pos - 1] : dst[-l + w - 1];
320                                break;
321                            case 2:
322                                if (dy < 1)
323                                    return AVERROR_INVALIDDATA;
324                                dst[pos] = dst[pos - l];
325                                break;
326                            case 3:
327                                dst[pos] = bytestream2_get_byte(gb);
328                                break;
329                            }
330
331                            pos++;
332                            if (pos >= w) {
333                                pos -= w;
334                                dst += l;
335                                dy++;
336                                if (dy >= h)
337                                    return 0;
338                            }
339                            bits >>= 2;
340                        }
341                        count--;
342                    }
343                }
344            }
345            break;
346        default:
347            return AVERROR_INVALIDDATA;
348        }
349    }
350
351    return 0;
352}
353
354static int decode_mad1_24(AVCodecContext *avctx, AVFrame *frame)
355{
356    ArgoContext *s = avctx->priv_data;
357    GetByteContext *gb = &s->gb;
358    const int w = frame->width;
359    const int h = frame->height;
360    const int l = frame->linesize[0] / 4;
361
362    while (bytestream2_get_bytes_left(gb) > 0) {
363        int osize, type, pos, dy, di, bcode, value, v14;
364        const uint8_t *bits;
365        uint32_t *dst;
366
367        type = bytestream2_get_byte(gb);
368        if (type == 0xFF)
369            return 0;
370
371        switch (type) {
372        case 8:
373            dst = (uint32_t *)frame->data[0];
374            for (int y = 0; y + 12 <= h; y += 12) {
375                for (int x = 0; x + 12 <= w; x += 12) {
376                    int fill = bytestream2_get_be24(gb);
377                    uint32_t *dstp = dst + x;
378
379                    for (int by = 0; by < 12; by++) {
380                        for (int bx = 0; bx < 12; bx++)
381                            dstp[bx] = fill;
382
383                        dstp += l;
384                    }
385                }
386
387                dst += 12 * l;
388            }
389            break;
390        case 7:
391            while (bytestream2_get_bytes_left(gb) > 0) {
392                int bsize = bytestream2_get_byte(gb);
393                uint32_t *src;
394                int count;
395
396                if (!bsize)
397                    break;
398
399                count = bytestream2_get_be16(gb);
400                while (count > 0) {
401                    int mvx, mvy, a, b, c, mx, my;
402                    int bsize_w, bsize_h;
403
404                    bsize_w = bsize_h = bsize;
405                    if (bytestream2_get_bytes_left(gb) < 4)
406                        return AVERROR_INVALIDDATA;
407                    mvx = bytestream2_get_byte(gb) * bsize;
408                    mvy = bytestream2_get_byte(gb) * bsize;
409                    a = bytestream2_get_byte(gb);
410                    b = bytestream2_get_byte(gb);
411                    c = ((a & 0x3F) << 8) + b;
412                    mx = mvx + (c  & 0x7F) - 64;
413                    my = mvy + (c >>    7) - 64;
414
415                    if (mvy < 0 || mvy >= h)
416                        return AVERROR_INVALIDDATA;
417
418                    if (mvx < 0 || mvx >= w)
419                        return AVERROR_INVALIDDATA;
420
421                    if (my < 0 || my >= h)
422                        return AVERROR_INVALIDDATA;
423
424                    if (mx < 0 || mx >= w)
425                        return AVERROR_INVALIDDATA;
426
427                    dst = (uint32_t *)frame->data[0] + mvx + l * mvy;
428                    src = (uint32_t *)frame->data[0] + mx  + l * my;
429
430                    bsize_w = FFMIN3(bsize_w, w - mvx, w - mx);
431                    bsize_h = FFMIN3(bsize_h, h - mvy, h - my);
432
433                    if (mvy >= my && (mvy != my || mvx >= mx)) {
434                        src += (bsize_h - 1) * l;
435                        dst += (bsize_h - 1) * l;
436                        for (int by = 0; by < bsize_h; by++) {
437                            memmove(dst, src, bsize_w * 4);
438                            src -= l;
439                            dst -= l;
440                        }
441                    } else {
442                        for (int by = 0; by < bsize_h; by++) {
443                            memmove(dst, src, bsize_w * 4);
444                            src += l;
445                            dst += l;
446                        }
447                    }
448
449                    count--;
450                }
451            }
452            break;
453        case 12:
454            osize = ((h + 3) / 4) * ((w + 3) / 4) + 7;
455            bits = gb->buffer;
456            di   = 0;
457            bcode = v14 = 0;
458            if (bytestream2_get_bytes_left(gb) < osize >> 3)
459                return AVERROR_INVALIDDATA;
460            bytestream2_skip(gb, osize >> 3);
461            for (int x = 0; x < w; x += 4) {
462                for (int y = 0; y < h; y += 4) {
463                    int astate = 0;
464
465                    if (bits[di >> 3] & (1 << (di & 7))) {
466                        int codes = bytestream2_get_byte(gb);
467
468                        for (int count = 0; count < 4; count++) {
469                            uint32_t *src = (uint32_t *)frame->data[0];
470                            size_t src_size = l * (h - 1) + (w - 1);
471                            int nv, v, code = codes & 3;
472
473                            pos = x;
474                            dy  = y + count;
475                            dst = (uint32_t *)frame->data[0] + pos + dy * l;
476                            if (code & 1)
477                                bcode = bytestream2_get_byte(gb);
478                            if (code == 3) {
479                                for (int j = 0; j < 4; j++) {
480                                    switch (bcode & 3) {
481                                    case 0:
482                                        break;
483                                    case 1:
484                                        if (dy < 1 && !pos)
485                                            return AVERROR_INVALIDDATA;
486                                        dst[0] = dst[-1];
487                                        break;
488                                    case 2:
489                                        if (dy < 1)
490                                            return AVERROR_INVALIDDATA;
491                                        dst[0] = dst[-l];
492                                        break;
493                                    case 3:
494                                        if (astate) {
495                                            nv = value >> 4;
496                                        } else {
497                                            value = bytestream2_get_byte(gb);
498                                            nv = value & 0xF;
499                                        }
500                                        astate ^= 1;
501                                        dst[0] = src[av_clip(l * (dy + s->mv1[nv][1]) + pos +
502                                                             s->mv1[nv][0], 0, src_size)];
503                                        break;
504                                    }
505
506                                    bcode >>= 2;
507                                    dst++;
508                                    pos++;
509                                }
510                            } else if (code) {
511                                if (code == 1)
512                                    v14 = bcode;
513                                else
514                                    bcode = v14;
515                                for (int j = 0; j < 4; j++) {
516                                    switch (bcode & 3) {
517                                    case 0:
518                                        break;
519                                    case 1:
520                                        if (dy < 1 && !pos)
521                                            return AVERROR_INVALIDDATA;
522                                        dst[0] = dst[-1];
523                                        break;
524                                    case 2:
525                                        if (dy < 1)
526                                            return AVERROR_INVALIDDATA;
527                                        dst[0] = dst[-l];
528                                        break;
529                                    case 3:
530                                        v = bytestream2_get_byte(gb);
531                                        if (v < 128) {
532                                            dst[0] = src[av_clip(l * (dy + s->mv0[v][1]) + pos +
533                                                                 s->mv0[v][0], 0, src_size)];
534                                        } else {
535                                            dst[0] = ((v & 0x7F) << 17) | bytestream2_get_be16(gb);
536                                        }
537                                        break;
538                                    }
539
540                                    bcode >>= 2;
541                                    dst++;
542                                    pos++;
543                                }
544                            }
545
546                            codes >>= 2;
547                        }
548                    }
549
550                    di++;
551                }
552            }
553            break;
554        default:
555            return AVERROR_INVALIDDATA;
556        }
557    }
558
559    return AVERROR_INVALIDDATA;
560}
561
562static int decode_rle(AVCodecContext *avctx, AVFrame *frame)
563{
564    ArgoContext *s = avctx->priv_data;
565    GetByteContext *gb = &s->gb;
566    const int w = frame->width;
567    const int h = frame->height;
568    const int l = frame->linesize[0];
569    uint8_t *dst = frame->data[0];
570    int pos = 0, y = 0;
571
572    while (bytestream2_get_bytes_left(gb) > 0) {
573        int count = bytestream2_get_byte(gb);
574        int pixel = bytestream2_get_byte(gb);
575
576        if (!count) {
577            pos += pixel;
578            while (pos >= w) {
579                pos -= w;
580                y++;
581                if (y >= h)
582                    return 0;
583            }
584        } else {
585            while (count > 0) {
586                dst[pos + y * l] = pixel;
587                count--;
588                pos++;
589                if (pos >= w) {
590                    pos = 0;
591                    y++;
592                    if (y >= h)
593                        return 0;
594                }
595            }
596        }
597    }
598
599    return 0;
600}
601
602static int decode_frame(AVCodecContext *avctx, AVFrame *rframe,
603                        int *got_frame, AVPacket *avpkt)
604{
605    ArgoContext *s = avctx->priv_data;
606    GetByteContext *gb = &s->gb;
607    AVFrame *frame = s->frame;
608    uint32_t chunk;
609    int ret;
610
611    if (avpkt->size < 4)
612        return AVERROR_INVALIDDATA;
613
614    bytestream2_init(gb, avpkt->data, avpkt->size);
615
616    if ((ret = ff_reget_buffer(avctx, frame, 0)) < 0)
617        return ret;
618
619    chunk = bytestream2_get_be32(gb);
620    switch (chunk) {
621    case MKBETAG('P', 'A', 'L', '8'):
622        for (int y = 0; y < frame->height; y++)
623            memset(frame->data[0] + y * frame->linesize[0], 0, frame->width * s->bpp);
624        if (avctx->pix_fmt == AV_PIX_FMT_PAL8)
625            memset(frame->data[1], 0, AVPALETTE_SIZE);
626        return decode_pal8(avctx, s->pal);
627    case MKBETAG('M', 'A', 'D', '1'):
628        if (avctx->pix_fmt == AV_PIX_FMT_PAL8)
629            ret = decode_mad1(avctx, frame);
630        else
631            ret = decode_mad1_24(avctx, frame);
632        break;
633    case MKBETAG('A', 'V', 'C', 'F'):
634        if (avctx->pix_fmt == AV_PIX_FMT_PAL8) {
635            s->key = 1;
636            ret = decode_avcf(avctx, frame);
637            break;
638        }
639    case MKBETAG('A', 'L', 'C', 'D'):
640        if (avctx->pix_fmt == AV_PIX_FMT_PAL8) {
641            s->key = 0;
642            ret = decode_alcd(avctx, frame);
643            break;
644        }
645    case MKBETAG('R', 'L', 'E', 'F'):
646        if (avctx->pix_fmt == AV_PIX_FMT_PAL8) {
647            s->key = 1;
648            ret = decode_rle(avctx, frame);
649            break;
650        }
651    case MKBETAG('R', 'L', 'E', 'D'):
652        if (avctx->pix_fmt == AV_PIX_FMT_PAL8) {
653            s->key = 0;
654            ret = decode_rle(avctx, frame);
655            break;
656        }
657    default:
658        av_log(avctx, AV_LOG_DEBUG, "unknown chunk 0x%X\n", chunk);
659        break;
660    }
661
662    if (ret < 0)
663        return ret;
664
665    if (avctx->pix_fmt == AV_PIX_FMT_PAL8)
666        memcpy(frame->data[1], s->pal, AVPALETTE_SIZE);
667
668    if ((ret = av_frame_ref(rframe, s->frame)) < 0)
669        return ret;
670
671    frame->pict_type = s->key ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P;
672    frame->key_frame = s->key;
673    *got_frame = 1;
674
675    return avpkt->size;
676}
677
678static av_cold int decode_init(AVCodecContext *avctx)
679{
680    ArgoContext *s = avctx->priv_data;
681
682    switch (avctx->bits_per_coded_sample) {
683    case  8: s->bpp = 1;
684             avctx->pix_fmt = AV_PIX_FMT_PAL8; break;
685    case 24: s->bpp = 4;
686             avctx->pix_fmt = AV_PIX_FMT_BGR0; break;
687    default: avpriv_request_sample(s, "depth == %u", avctx->bits_per_coded_sample);
688             return AVERROR_PATCHWELCOME;
689    }
690
691    if (avctx->width % 2 || avctx->height % 2) {
692        avpriv_request_sample(s, "Odd dimensions\n");
693        return AVERROR_PATCHWELCOME;
694    }
695
696    s->frame = av_frame_alloc();
697    if (!s->frame)
698        return AVERROR(ENOMEM);
699
700    for (int n = 0, i = -4; i < 4; i++) {
701        for (int j = -14; j < 2; j++) {
702            s->mv0[n][0] = j;
703            s->mv0[n++][1] = i;
704        }
705    }
706
707    for (int n = 0, i = -5; i <= 1; i += 2) {
708        int j = -5;
709
710        while (j <= 1) {
711            s->mv1[n][0] = j;
712            s->mv1[n++][1] = i;
713            j += 2;
714        }
715    }
716
717    return 0;
718}
719
720static void decode_flush(AVCodecContext *avctx)
721{
722    ArgoContext *s = avctx->priv_data;
723
724    av_frame_unref(s->frame);
725}
726
727static av_cold int decode_close(AVCodecContext *avctx)
728{
729    ArgoContext *s = avctx->priv_data;
730
731    av_frame_free(&s->frame);
732
733    return 0;
734}
735
736const FFCodec ff_argo_decoder = {
737    .p.name         = "argo",
738    .p.long_name    = NULL_IF_CONFIG_SMALL("Argonaut Games Video"),
739    .p.type         = AVMEDIA_TYPE_VIDEO,
740    .p.id           = AV_CODEC_ID_ARGO,
741    .priv_data_size = sizeof(ArgoContext),
742    .init           = decode_init,
743    FF_CODEC_DECODE_CB(decode_frame),
744    .flush          = decode_flush,
745    .close          = decode_close,
746    .p.capabilities = AV_CODEC_CAP_DR1,
747    .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
748};
749