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