2 * Argonaut Games Video decoder
3 * Copyright (c) 2020 Paul B Mahol
5 * This file is part of FFmpeg.
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.
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.
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
26 #include "libavutil/imgutils.h"
27 #include "libavutil/internal.h"
28 #include "libavutil/intreadwrite.h"
29 #include "libavutil/mem.h"
32 #include "bytestream.h"
35 typedef struct ArgoContext {
46 static int decode_pal8(AVCodecContext *avctx, uint32_t *pal)
48 ArgoContext *s = avctx->priv_data;
49 GetByteContext *gb = &s->gb;
52 start = bytestream2_get_le16(gb);
53 count = bytestream2_get_le16(gb);
55 if (start + count > 256)
56 return AVERROR_INVALIDDATA;
58 if (bytestream2_get_bytes_left(gb) < 3 * count)
59 return AVERROR_INVALIDDATA;
61 for (int i = 0; i < count; i++)
62 pal[start + i] = (0xFF << 24U) | bytestream2_get_be24u(gb);
67 static int decode_avcf(AVCodecContext *avctx, AVFrame *frame)
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];
75 if (bytestream2_get_bytes_left(gb) < 1024 + (frame->width / 2) * (frame->height / 2))
76 return AVERROR_INVALIDDATA;
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;
87 dst[x+l+1] = block[3];
90 dst += frame->linesize[0] * 2;
96 static int decode_alcd(AVCodecContext *avctx, AVFrame *frame)
98 ArgoContext *s = avctx->priv_data;
99 GetByteContext *gb = &s->gb;
101 const int l = frame->linesize[0];
102 const uint8_t *map = gb->buffer;
103 uint8_t *dst = frame->data[0];
107 if (bytestream2_get_bytes_left(gb) < 1024 + (((frame->width / 2) * (frame->height / 2) + 7) >> 3))
108 return AVERROR_INVALIDDATA;
110 bytestream2_skipu(gb, 1024);
112 bytestream2_skipu(gb, ((frame->width / 2) * (frame->height / 2) + 7) >> 3);
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;
120 codes = bytestream2_get_byteu(&sb);
125 index = bytestream2_get_byte(gb);
126 block = map + index * 4;
131 dst[x+l+1] = block[3];
138 dst += frame->linesize[0] * 2;
144 static int decode_mad1(AVCodecContext *avctx, AVFrame *frame)
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];
152 while (bytestream2_get_bytes_left(gb) > 0) {
153 int size, type, pos, dy;
156 type = bytestream2_get_byte(gb);
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;
168 for (int by = 0; by < 8; by++) {
169 memset(ddst, fill, 8);
178 while (bytestream2_get_bytes_left(gb) > 0) {
179 int bsize = bytestream2_get_byte(gb);
186 count = bytestream2_get_be16(gb);
188 int mvx, mvy, a, b, c, mx, my;
189 int bsize_w, bsize_h;
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;
202 if (mvy < 0 || mvy >= h)
203 return AVERROR_INVALIDDATA;
205 if (mvx < 0 || mvx >= w)
206 return AVERROR_INVALIDDATA;
208 if (my < 0 || my >= h)
209 return AVERROR_INVALIDDATA;
211 if (mx < 0 || mx >= w)
212 return AVERROR_INVALIDDATA;
214 dst = frame->data[0] + mvx + l * mvy;
215 src = frame->data[0] + mx + l * my;
217 bsize_w = FFMIN3(bsize_w, w - mvx, w - mx);
218 bsize_h = FFMIN3(bsize_h, h - mvy, h - my);
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);
229 for (int by = 0; by < bsize_h; by++) {
230 memmove(dst, src, bsize_w);
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);
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;
256 fill = (fill << 8) | fill;
257 for (int by = 0; by < 2; by++) {
268 size = bytestream2_get_le16(gb);
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);
275 av_log(avctx, AV_LOG_DEBUG, "%d %d %d %d\n", x, y, count, fill);
276 for (int i = 0; i < count; i++)
278 return AVERROR_PATCHWELCOME;
282 dst = frame->data[0];
285 while (bytestream2_get_bytes_left(gb) > 0) {
286 int count = bytestream2_get_byteu(gb);
287 int skip = count & 0x3F;
309 int bits = bytestream2_get_byte(gb);
311 for (int i = 0; i < 4; i++) {
317 return AVERROR_INVALIDDATA;
319 dst[pos] = pos ? dst[pos - 1] : dst[-l + w - 1];
323 return AVERROR_INVALIDDATA;
324 dst[pos] = dst[pos - l];
327 dst[pos] = bytestream2_get_byte(gb);
347 return AVERROR_INVALIDDATA;
354 static int decode_mad1_24(AVCodecContext *avctx, AVFrame *frame)
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;
362 while (bytestream2_get_bytes_left(gb) > 0) {
363 int osize, type, pos, dy, di, bcode, value, v14;
367 type = bytestream2_get_byte(gb);
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;
379 for (int by = 0; by < 12; by++) {
380 for (int bx = 0; bx < 12; bx++)
391 while (bytestream2_get_bytes_left(gb) > 0) {
392 int bsize = bytestream2_get_byte(gb);
399 count = bytestream2_get_be16(gb);
401 int mvx, mvy, a, b, c, mx, my;
402 int bsize_w, bsize_h;
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;
415 if (mvy < 0 || mvy >= h)
416 return AVERROR_INVALIDDATA;
418 if (mvx < 0 || mvx >= w)
419 return AVERROR_INVALIDDATA;
421 if (my < 0 || my >= h)
422 return AVERROR_INVALIDDATA;
424 if (mx < 0 || mx >= w)
425 return AVERROR_INVALIDDATA;
427 dst = (uint32_t *)frame->data[0] + mvx + l * mvy;
428 src = (uint32_t *)frame->data[0] + mx + l * my;
430 bsize_w = FFMIN3(bsize_w, w - mvx, w - mx);
431 bsize_h = FFMIN3(bsize_h, h - mvy, h - my);
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);
442 for (int by = 0; by < bsize_h; by++) {
443 memmove(dst, src, bsize_w * 4);
454 osize = ((h + 3) / 4) * ((w + 3) / 4) + 7;
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) {
465 if (bits[di >> 3] & (1 << (di & 7))) {
466 int codes = bytestream2_get_byte(gb);
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;
475 dst = (uint32_t *)frame->data[0] + pos + dy * l;
477 bcode = bytestream2_get_byte(gb);
479 for (int j = 0; j < 4; j++) {
485 return AVERROR_INVALIDDATA;
490 return AVERROR_INVALIDDATA;
497 value = bytestream2_get_byte(gb);
501 dst[0] = src[av_clip(l * (dy + s->mv1[nv][1]) + pos +
502 s->mv1[nv][0], 0, src_size)];
515 for (int j = 0; j < 4; j++) {
521 return AVERROR_INVALIDDATA;
526 return AVERROR_INVALIDDATA;
530 v = bytestream2_get_byte(gb);
532 dst[0] = src[av_clip(l * (dy + s->mv0[v][1]) + pos +
533 s->mv0[v][0], 0, src_size)];
535 dst[0] = ((v & 0x7F) << 17) | bytestream2_get_be16(gb);
555 return AVERROR_INVALIDDATA;
559 return AVERROR_INVALIDDATA;
562 static int decode_rle(AVCodecContext *avctx, AVFrame *frame)
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] / 4;
569 uint8_t *dst = frame->data[0];
572 while (bytestream2_get_bytes_left(gb) > 0) {
573 int count = bytestream2_get_byte(gb);
574 int pixel = bytestream2_get_byte(gb);
586 dst[pos + y * l] = pixel;
602 static int decode_frame(AVCodecContext *avctx, void *data,
603 int *got_frame, AVPacket *avpkt)
605 ArgoContext *s = avctx->priv_data;
606 GetByteContext *gb = &s->gb;
607 AVFrame *frame = s->frame;
611 bytestream2_init(gb, avpkt->data, avpkt->size);
613 if ((ret = ff_reget_buffer(avctx, frame, 0)) < 0)
616 chunk = bytestream2_get_be32(gb);
618 case MKBETAG('P', 'A', 'L', '8'):
619 for (int y = 0; y < frame->height; y++)
620 memset(frame->data[0] + y * frame->linesize[0], 0, frame->width * s->bpp);
621 if (avctx->pix_fmt == AV_PIX_FMT_PAL8)
622 memset(frame->data[1], 0, AVPALETTE_SIZE);
623 return decode_pal8(avctx, s->pal);
624 case MKBETAG('M', 'A', 'D', '1'):
625 if (avctx->pix_fmt == AV_PIX_FMT_PAL8)
626 ret = decode_mad1(avctx, frame);
628 ret = decode_mad1_24(avctx, frame);
630 case MKBETAG('A', 'V', 'C', 'F'):
631 if (avctx->pix_fmt == AV_PIX_FMT_PAL8) {
633 ret = decode_avcf(avctx, frame);
636 case MKBETAG('A', 'L', 'C', 'D'):
637 if (avctx->pix_fmt == AV_PIX_FMT_PAL8) {
639 ret = decode_alcd(avctx, frame);
642 case MKBETAG('R', 'L', 'E', 'F'):
643 if (avctx->pix_fmt == AV_PIX_FMT_PAL8) {
645 ret = decode_rle(avctx, frame);
648 case MKBETAG('R', 'L', 'E', 'D'):
649 if (avctx->pix_fmt == AV_PIX_FMT_PAL8) {
651 ret = decode_rle(avctx, frame);
655 av_log(avctx, AV_LOG_DEBUG, "unknown chunk 0x%X\n", chunk);
662 if (avctx->pix_fmt == AV_PIX_FMT_PAL8)
663 memcpy(frame->data[1], s->pal, AVPALETTE_SIZE);
665 if ((ret = av_frame_ref(data, s->frame)) < 0)
668 frame->pict_type = s->key ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P;
669 frame->key_frame = s->key;
675 static av_cold int decode_init(AVCodecContext *avctx)
677 ArgoContext *s = avctx->priv_data;
679 switch (avctx->bits_per_raw_sample) {
681 avctx->pix_fmt = AV_PIX_FMT_PAL8; break;
683 avctx->pix_fmt = AV_PIX_FMT_BGR0; break;
684 default: avpriv_request_sample(s, "depth == %u", avctx->bits_per_raw_sample);
685 return AVERROR_PATCHWELCOME;
688 s->frame = av_frame_alloc();
690 return AVERROR(ENOMEM);
692 for (int n = 0, i = -4; i < 4; i++) {
693 for (int j = -14; j < 2; j++) {
699 for (int n = 0, i = -5; i <= 1; i += 2) {
712 static void decode_flush(AVCodecContext *avctx)
714 ArgoContext *s = avctx->priv_data;
716 av_frame_unref(s->frame);
719 static av_cold int decode_close(AVCodecContext *avctx)
721 ArgoContext *s = avctx->priv_data;
723 av_frame_free(&s->frame);
728 AVCodec ff_argo_decoder = {
730 .long_name = NULL_IF_CONFIG_SMALL("Argonaut Games Video"),
731 .type = AVMEDIA_TYPE_VIDEO,
732 .id = AV_CODEC_ID_ARGO,
733 .priv_data_size = sizeof(ArgoContext),
735 .decode = decode_frame,
736 .flush = decode_flush,
737 .close = decode_close,
738 .capabilities = AV_CODEC_CAP_DR1,
739 .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,