FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/argo.c
Date: 2022-07-04 00:18:54
Exec Total Coverage
Lines: 0 470 0.0%
Branches: 0 282 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 <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
35 typedef 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
46 static 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
67 static 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
96 static 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
144 static 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
354 static 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
562 static 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
602 static 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
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 .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