FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/argo.c
Date: 2024-04-19 17:50:32
Exec Total Coverage
Lines: 0 473 0.0%
Functions: 0 10 0.0%
Branches: 0 284 0.0%

Line Branch Exec Source
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 <string.h>
23
24 #include "libavutil/internal.h"
25 #include "libavutil/intreadwrite.h"
26
27 #include "avcodec.h"
28 #include "bytestream.h"
29 #include "codec_internal.h"
30 #include "decode.h"
31
32 typedef struct ArgoContext {
33 GetByteContext gb;
34
35 int bpp;
36 int key;
37 int mv0[128][2];
38 int mv1[16][2];
39 uint32_t pal[256];
40 AVFrame *frame;
41 } ArgoContext;
42
43 static int decode_pal8(AVCodecContext *avctx, uint32_t *pal)
44 {
45 ArgoContext *s = avctx->priv_data;
46 GetByteContext *gb = &s->gb;
47 int start, count;
48
49 start = bytestream2_get_le16(gb);
50 count = bytestream2_get_le16(gb);
51
52 if (start + count > 256)
53 return AVERROR_INVALIDDATA;
54
55 if (bytestream2_get_bytes_left(gb) < 3 * count)
56 return AVERROR_INVALIDDATA;
57
58 for (int i = 0; i < count; i++)
59 pal[start + i] = (0xFFU << 24) | bytestream2_get_be24u(gb);
60
61 return 0;
62 }
63
64 static int decode_avcf(AVCodecContext *avctx, AVFrame *frame)
65 {
66 ArgoContext *s = avctx->priv_data;
67 GetByteContext *gb = &s->gb;
68 const int l = frame->linesize[0];
69 const uint8_t *map = gb->buffer;
70 uint8_t *dst = frame->data[0];
71
72 if (bytestream2_get_bytes_left(gb) < 1024 + (frame->width / 2) * (frame->height / 2))
73 return AVERROR_INVALIDDATA;
74
75 bytestream2_skipu(gb, 1024);
76 for (int y = 0; y < frame->height; y += 2) {
77 for (int x = 0; x < frame->width; x += 2) {
78 int index = bytestream2_get_byteu(gb);
79 const uint8_t *block = map + index * 4;
80
81 dst[x+0] = block[0];
82 dst[x+1] = block[1];
83 dst[x+l] = block[2];
84 dst[x+l+1] = block[3];
85 }
86
87 dst += frame->linesize[0] * 2;
88 }
89
90 return 0;
91 }
92
93 static int decode_alcd(AVCodecContext *avctx, AVFrame *frame)
94 {
95 ArgoContext *s = avctx->priv_data;
96 GetByteContext *gb = &s->gb;
97 GetByteContext sb;
98 const int l = frame->linesize[0];
99 const uint8_t *map = gb->buffer;
100 uint8_t *dst = frame->data[0];
101 uint8_t codes = 0;
102 int count = 0;
103
104 if (bytestream2_get_bytes_left(gb) < 1024 + (((frame->width / 2) * (frame->height / 2) + 7) >> 3))
105 return AVERROR_INVALIDDATA;
106
107 bytestream2_skipu(gb, 1024);
108 sb = *gb;
109 bytestream2_skipu(gb, ((frame->width / 2) * (frame->height / 2) + 7) >> 3);
110
111 for (int y = 0; y < frame->height; y += 2) {
112 for (int x = 0; x < frame->width; x += 2) {
113 const uint8_t *block;
114 int index;
115
116 if (count == 0) {
117 codes = bytestream2_get_byteu(&sb);
118 count = 8;
119 }
120
121 if (codes & 0x80) {
122 index = bytestream2_get_byte(gb);
123 block = map + index * 4;
124
125 dst[x+0] = block[0];
126 dst[x+1] = block[1];
127 dst[x+l] = block[2];
128 dst[x+l+1] = block[3];
129 }
130
131 codes <<= 1;
132 count--;
133 }
134
135 dst += frame->linesize[0] * 2;
136 }
137
138 return 0;
139 }
140
141 static int decode_mad1(AVCodecContext *avctx, AVFrame *frame)
142 {
143 ArgoContext *s = avctx->priv_data;
144 GetByteContext *gb = &s->gb;
145 const int w = frame->width;
146 const int h = frame->height;
147 const int l = frame->linesize[0];
148
149 while (bytestream2_get_bytes_left(gb) > 0) {
150 int size, type, pos, dy;
151 uint8_t *dst;
152
153 type = bytestream2_get_byte(gb);
154 if (type == 0xFF)
155 break;
156
157 switch (type) {
158 case 8:
159 dst = frame->data[0];
160 for (int y = 0; y < h; y += 8) {
161 for (int x = 0; x < w; x += 8) {
162 int fill = bytestream2_get_byte(gb);
163 uint8_t *ddst = dst + x;
164
165 for (int by = 0; by < 8; by++) {
166 memset(ddst, fill, 8);
167 ddst += l;
168 }
169 }
170
171 dst += 8 * l;
172 }
173 break;
174 case 7:
175 while (bytestream2_get_bytes_left(gb) > 0) {
176 int bsize = bytestream2_get_byte(gb);
177 uint8_t *src;
178 int count;
179
180 if (!bsize)
181 break;
182
183 count = bytestream2_get_be16(gb);
184 while (count > 0) {
185 int mvx, mvy, a, b, c, mx, my;
186 int bsize_w, bsize_h;
187
188 bsize_w = bsize_h = bsize;
189 if (bytestream2_get_bytes_left(gb) < 4)
190 return AVERROR_INVALIDDATA;
191 mvx = bytestream2_get_byte(gb) * bsize;
192 mvy = bytestream2_get_byte(gb) * bsize;
193 a = bytestream2_get_byte(gb);
194 b = bytestream2_get_byte(gb);
195 c = ((a & 0x3F) << 8) + b;
196 mx = mvx + (c & 0x7F) - 64;
197 my = mvy + (c >> 7) - 64;
198
199 if (mvy < 0 || mvy >= h)
200 return AVERROR_INVALIDDATA;
201
202 if (mvx < 0 || mvx >= w)
203 return AVERROR_INVALIDDATA;
204
205 if (my < 0 || my >= h)
206 return AVERROR_INVALIDDATA;
207
208 if (mx < 0 || mx >= w)
209 return AVERROR_INVALIDDATA;
210
211 dst = frame->data[0] + mvx + l * mvy;
212 src = frame->data[0] + mx + l * my;
213
214 bsize_w = FFMIN3(bsize_w, w - mvx, w - mx);
215 bsize_h = FFMIN3(bsize_h, h - mvy, h - my);
216
217 if (mvy >= my && (mvy != my || mvx >= mx)) {
218 src += (bsize_h - 1) * l;
219 dst += (bsize_h - 1) * l;
220 for (int by = 0; by < bsize_h; by++) {
221 memmove(dst, src, bsize_w);
222 src -= l;
223 dst -= l;
224 }
225 } else {
226 for (int by = 0; by < bsize_h; by++) {
227 memmove(dst, src, bsize_w);
228 src += l;
229 dst += l;
230 }
231 }
232
233 count--;
234 }
235 }
236 break;
237 case 6:
238 dst = frame->data[0];
239 if (bytestream2_get_bytes_left(gb) < w * h)
240 return AVERROR_INVALIDDATA;
241 for (int y = 0; y < h; y++) {
242 bytestream2_get_bufferu(gb, dst, w);
243 dst += l;
244 }
245 break;
246 case 5:
247 dst = frame->data[0];
248 for (int y = 0; y < h; y += 2) {
249 for (int x = 0; x < w; x += 2) {
250 int fill = bytestream2_get_byte(gb);
251 uint8_t *ddst = dst + x;
252
253 fill = (fill << 8) | fill;
254 for (int by = 0; by < 2; by++) {
255 AV_WN16(ddst, fill);
256
257 ddst += l;
258 }
259 }
260
261 dst += 2 * l;
262 }
263 break;
264 case 3:
265 size = bytestream2_get_le16(gb);
266 if (size > 0) {
267 int x = bytestream2_get_byte(gb) * 4;
268 int y = bytestream2_get_byte(gb) * 4;
269 int count = bytestream2_get_byte(gb);
270 int fill = bytestream2_get_byte(gb);
271
272 av_log(avctx, AV_LOG_DEBUG, "%d %d %d %d\n", x, y, count, fill);
273 for (int i = 0; i < count; i++)
274 ;
275 return AVERROR_PATCHWELCOME;
276 }
277 break;
278 case 2:
279 dst = frame->data[0];
280 pos = 0;
281 dy = 0;
282 while (bytestream2_get_bytes_left(gb) > 0) {
283 int count = bytestream2_get_byteu(gb);
284 int skip = count & 0x3F;
285
286 count = count >> 6;
287 if (skip == 0x3F) {
288 pos += 0x3E;
289 while (pos >= w) {
290 pos -= w;
291 dst += l;
292 dy++;
293 if (dy >= h)
294 return 0;
295 }
296 } else {
297 pos += skip;
298 while (pos >= w) {
299 pos -= w;
300 dst += l;
301 dy++;
302 if (dy >= h)
303 return 0;
304 }
305 while (count >= 0) {
306 int bits = bytestream2_get_byte(gb);
307
308 for (int i = 0; i < 4; i++) {
309 switch (bits & 3) {
310 case 0:
311 break;
312 case 1:
313 if (dy < 1 && !pos)
314 return AVERROR_INVALIDDATA;
315 else
316 dst[pos] = pos ? dst[pos - 1] : dst[-l + w - 1];
317 break;
318 case 2:
319 if (dy < 1)
320 return AVERROR_INVALIDDATA;
321 dst[pos] = dst[pos - l];
322 break;
323 case 3:
324 dst[pos] = bytestream2_get_byte(gb);
325 break;
326 }
327
328 pos++;
329 if (pos >= w) {
330 pos -= w;
331 dst += l;
332 dy++;
333 if (dy >= h)
334 return 0;
335 }
336 bits >>= 2;
337 }
338 count--;
339 }
340 }
341 }
342 break;
343 default:
344 return AVERROR_INVALIDDATA;
345 }
346 }
347
348 return 0;
349 }
350
351 static int decode_mad1_24(AVCodecContext *avctx, AVFrame *frame)
352 {
353 ArgoContext *s = avctx->priv_data;
354 GetByteContext *gb = &s->gb;
355 const int w = frame->width;
356 const int h = frame->height;
357 const int l = frame->linesize[0] / 4;
358
359 while (bytestream2_get_bytes_left(gb) > 0) {
360 int osize, type, pos, dy, di, bcode, value, v14;
361 const uint8_t *bits;
362 uint32_t *dst;
363
364 type = bytestream2_get_byte(gb);
365 if (type == 0xFF)
366 return 0;
367
368 switch (type) {
369 case 8:
370 dst = (uint32_t *)frame->data[0];
371 for (int y = 0; y + 12 <= h; y += 12) {
372 for (int x = 0; x + 12 <= w; x += 12) {
373 int fill = bytestream2_get_be24(gb);
374 uint32_t *dstp = dst + x;
375
376 for (int by = 0; by < 12; by++) {
377 for (int bx = 0; bx < 12; bx++)
378 dstp[bx] = fill;
379
380 dstp += l;
381 }
382 }
383
384 dst += 12 * l;
385 }
386 break;
387 case 7:
388 while (bytestream2_get_bytes_left(gb) > 0) {
389 int bsize = bytestream2_get_byte(gb);
390 uint32_t *src;
391 int count;
392
393 if (!bsize)
394 break;
395
396 count = bytestream2_get_be16(gb);
397 while (count > 0) {
398 int mvx, mvy, a, b, c, mx, my;
399 int bsize_w, bsize_h;
400
401 bsize_w = bsize_h = bsize;
402 if (bytestream2_get_bytes_left(gb) < 4)
403 return AVERROR_INVALIDDATA;
404 mvx = bytestream2_get_byte(gb) * bsize;
405 mvy = bytestream2_get_byte(gb) * bsize;
406 a = bytestream2_get_byte(gb);
407 b = bytestream2_get_byte(gb);
408 c = ((a & 0x3F) << 8) + b;
409 mx = mvx + (c & 0x7F) - 64;
410 my = mvy + (c >> 7) - 64;
411
412 if (mvy < 0 || mvy >= h)
413 return AVERROR_INVALIDDATA;
414
415 if (mvx < 0 || mvx >= w)
416 return AVERROR_INVALIDDATA;
417
418 if (my < 0 || my >= h)
419 return AVERROR_INVALIDDATA;
420
421 if (mx < 0 || mx >= w)
422 return AVERROR_INVALIDDATA;
423
424 dst = (uint32_t *)frame->data[0] + mvx + l * mvy;
425 src = (uint32_t *)frame->data[0] + mx + l * my;
426
427 bsize_w = FFMIN3(bsize_w, w - mvx, w - mx);
428 bsize_h = FFMIN3(bsize_h, h - mvy, h - my);
429
430 if (mvy >= my && (mvy != my || mvx >= mx)) {
431 src += (bsize_h - 1) * l;
432 dst += (bsize_h - 1) * l;
433 for (int by = 0; by < bsize_h; by++) {
434 memmove(dst, src, bsize_w * 4);
435 src -= l;
436 dst -= l;
437 }
438 } else {
439 for (int by = 0; by < bsize_h; by++) {
440 memmove(dst, src, bsize_w * 4);
441 src += l;
442 dst += l;
443 }
444 }
445
446 count--;
447 }
448 }
449 break;
450 case 12:
451 osize = ((h + 3) / 4) * ((w + 3) / 4) + 7;
452 bits = gb->buffer;
453 di = 0;
454 bcode = v14 = 0;
455 if (bytestream2_get_bytes_left(gb) < osize >> 3)
456 return AVERROR_INVALIDDATA;
457 bytestream2_skip(gb, osize >> 3);
458 for (int x = 0; x < w; x += 4) {
459 for (int y = 0; y < h; y += 4) {
460 int astate = 0;
461
462 if (bits[di >> 3] & (1 << (di & 7))) {
463 int codes = bytestream2_get_byte(gb);
464
465 for (int count = 0; count < 4; count++) {
466 uint32_t *src = (uint32_t *)frame->data[0];
467 size_t src_size = l * (h - 1) + (w - 1);
468 int nv, v, code = codes & 3;
469
470 pos = x;
471 dy = y + count;
472 dst = (uint32_t *)frame->data[0] + pos + dy * l;
473 if (code & 1)
474 bcode = bytestream2_get_byte(gb);
475 if (code == 3) {
476 for (int j = 0; j < 4; j++) {
477 switch (bcode & 3) {
478 case 0:
479 break;
480 case 1:
481 if (dy < 1 && !pos)
482 return AVERROR_INVALIDDATA;
483 dst[0] = dst[-1];
484 break;
485 case 2:
486 if (dy < 1)
487 return AVERROR_INVALIDDATA;
488 dst[0] = dst[-l];
489 break;
490 case 3:
491 if (astate) {
492 nv = value >> 4;
493 } else {
494 value = bytestream2_get_byte(gb);
495 nv = value & 0xF;
496 }
497 astate ^= 1;
498 dst[0] = src[av_clip(l * (dy + s->mv1[nv][1]) + pos +
499 s->mv1[nv][0], 0, src_size)];
500 break;
501 }
502
503 bcode >>= 2;
504 dst++;
505 pos++;
506 }
507 } else if (code) {
508 if (code == 1)
509 v14 = bcode;
510 else
511 bcode = v14;
512 for (int j = 0; j < 4; j++) {
513 switch (bcode & 3) {
514 case 0:
515 break;
516 case 1:
517 if (dy < 1 && !pos)
518 return AVERROR_INVALIDDATA;
519 dst[0] = dst[-1];
520 break;
521 case 2:
522 if (dy < 1)
523 return AVERROR_INVALIDDATA;
524 dst[0] = dst[-l];
525 break;
526 case 3:
527 v = bytestream2_get_byte(gb);
528 if (v < 128) {
529 dst[0] = src[av_clip(l * (dy + s->mv0[v][1]) + pos +
530 s->mv0[v][0], 0, src_size)];
531 } else {
532 dst[0] = ((v & 0x7F) << 17) | bytestream2_get_be16(gb);
533 }
534 break;
535 }
536
537 bcode >>= 2;
538 dst++;
539 pos++;
540 }
541 }
542
543 codes >>= 2;
544 }
545 }
546
547 di++;
548 }
549 }
550 break;
551 default:
552 return AVERROR_INVALIDDATA;
553 }
554 }
555
556 return AVERROR_INVALIDDATA;
557 }
558
559 static int decode_rle(AVCodecContext *avctx, AVFrame *frame)
560 {
561 ArgoContext *s = avctx->priv_data;
562 GetByteContext *gb = &s->gb;
563 const int w = frame->width;
564 const int h = frame->height;
565 const int l = frame->linesize[0];
566 uint8_t *dst = frame->data[0];
567 int pos = 0, y = 0;
568
569 while (bytestream2_get_bytes_left(gb) > 0) {
570 int count = bytestream2_get_byte(gb);
571 int pixel = bytestream2_get_byte(gb);
572
573 if (!count) {
574 pos += pixel;
575 while (pos >= w) {
576 pos -= w;
577 y++;
578 if (y >= h)
579 return 0;
580 }
581 } else {
582 while (count > 0) {
583 dst[pos + y * l] = pixel;
584 count--;
585 pos++;
586 if (pos >= w) {
587 pos = 0;
588 y++;
589 if (y >= h)
590 return 0;
591 }
592 }
593 }
594 }
595
596 return 0;
597 }
598
599 static int decode_frame(AVCodecContext *avctx, AVFrame *rframe,
600 int *got_frame, AVPacket *avpkt)
601 {
602 ArgoContext *s = avctx->priv_data;
603 GetByteContext *gb = &s->gb;
604 AVFrame *frame = s->frame;
605 uint32_t chunk;
606 int ret;
607
608 if (avpkt->size < 4)
609 return AVERROR_INVALIDDATA;
610
611 bytestream2_init(gb, avpkt->data, avpkt->size);
612
613 if ((ret = ff_reget_buffer(avctx, frame, 0)) < 0)
614 return ret;
615
616 chunk = bytestream2_get_be32(gb);
617 switch (chunk) {
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);
627 else
628 ret = decode_mad1_24(avctx, frame);
629 break;
630 case MKBETAG('A', 'V', 'C', 'F'):
631 if (avctx->pix_fmt == AV_PIX_FMT_PAL8) {
632 s->key = 1;
633 ret = decode_avcf(avctx, frame);
634 break;
635 }
636 case MKBETAG('A', 'L', 'C', 'D'):
637 if (avctx->pix_fmt == AV_PIX_FMT_PAL8) {
638 s->key = 0;
639 ret = decode_alcd(avctx, frame);
640 break;
641 }
642 case MKBETAG('R', 'L', 'E', 'F'):
643 if (avctx->pix_fmt == AV_PIX_FMT_PAL8) {
644 s->key = 1;
645 ret = decode_rle(avctx, frame);
646 break;
647 }
648 case MKBETAG('R', 'L', 'E', 'D'):
649 if (avctx->pix_fmt == AV_PIX_FMT_PAL8) {
650 s->key = 0;
651 ret = decode_rle(avctx, frame);
652 break;
653 }
654 default:
655 av_log(avctx, AV_LOG_DEBUG, "unknown chunk 0x%X\n", chunk);
656 break;
657 }
658
659 if (ret < 0)
660 return ret;
661
662 if (avctx->pix_fmt == AV_PIX_FMT_PAL8)
663 memcpy(frame->data[1], s->pal, AVPALETTE_SIZE);
664
665 if ((ret = av_frame_ref(rframe, s->frame)) < 0)
666 return ret;
667
668 frame->pict_type = s->key ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P;
669 if (s->key)
670 frame->flags |= AV_FRAME_FLAG_KEY;
671 else
672 frame->flags &= ~AV_FRAME_FLAG_KEY;
673 *got_frame = 1;
674
675 return avpkt->size;
676 }
677
678 static 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
720 static void decode_flush(AVCodecContext *avctx)
721 {
722 ArgoContext *s = avctx->priv_data;
723
724 av_frame_unref(s->frame);
725 }
726
727 static 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
736 const FFCodec ff_argo_decoder = {
737 .p.name = "argo",
738 CODEC_LONG_NAME("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_CLEANUP,
748 };
749