FFmpeg coverage


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