FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/flicvideo.c
Date: 2024-04-25 15:36:26
Exec Total Coverage
Lines: 191 726 26.3%
Functions: 5 8 62.5%
Branches: 114 507 22.5%

Line Branch Exec Source
1 /*
2 * FLI/FLC Animation Video Decoder
3 * Copyright (C) 2003, 2004 The FFmpeg project
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 /**
23 * @file
24 * Autodesk Animator FLI/FLC Video Decoder
25 * by Mike Melanson (melanson@pcisys.net)
26 * for more information on the .fli/.flc file format and all of its many
27 * variations, visit:
28 * http://www.compuphase.com/flic.htm
29 *
30 * This decoder outputs PAL8/RGB555/RGB565/BGR24. To use this decoder, be
31 * sure that your demuxer sends the FLI file header to the decoder via
32 * the extradata chunk in AVCodecContext. The chunk should be 128 bytes
33 * large. The only exception is for FLI files from the game "Magic Carpet",
34 * in which the header is only 12 bytes.
35 */
36
37 #include <string.h>
38
39 #include "libavutil/intreadwrite.h"
40 #include "avcodec.h"
41 #include "bytestream.h"
42 #include "codec_internal.h"
43 #include "decode.h"
44 #include "mathops.h"
45
46 #define FLI_256_COLOR 4
47 #define FLI_DELTA 7
48 #define FLI_COLOR 11
49 #define FLI_LC 12
50 #define FLI_BLACK 13
51 #define FLI_BRUN 15
52 #define FLI_COPY 16
53 #define FLI_MINI 18
54 #define FLI_DTA_BRUN 25
55 #define FLI_DTA_COPY 26
56 #define FLI_DTA_LC 27
57
58 #define FLI_TYPE_CODE (0xAF11)
59 #define FLC_FLX_TYPE_CODE (0xAF12)
60 #define FLC_DTA_TYPE_CODE (0xAF44) /* Marks an "Extended FLC" comes from Dave's Targa Animator (DTA) */
61 #define FLC_MAGIC_CARPET_SYNTHETIC_TYPE_CODE (0xAF13)
62
63 541259 static inline int check_pixel_ptr(ptrdiff_t ptr, int n,
64 ptrdiff_t limit, int direction)
65 {
66
3/6
✓ Branch 0 taken 541259 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 541259 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 541259 times.
541259 if (( direction && ptr + n > limit) ||
67 (!direction && ptr + n < limit))
68 return AVERROR_INVALIDDATA;
69 541259 return 0;
70 }
71
72 #define CHECK_PIXEL_PTR(n) \
73 { \
74 ret = check_pixel_ptr(pixel_ptr, (n), pixel_limit, direction); \
75 if (ret < 0) \
76 return ret; \
77 }
78
79 #define CHECK_Y_PTR() \
80 { \
81 ret = check_pixel_ptr(y_ptr, 0, pixel_limit, direction); \
82 if (ret < 0) \
83 return ret; \
84 }
85
86 typedef struct FlicDecodeContext {
87 AVCodecContext *avctx;
88 AVFrame *frame;
89
90 unsigned int palette[256];
91 int new_palette;
92 int fli_type; /* either 0xAF11 or 0xAF12, affects palette resolution */
93 } FlicDecodeContext;
94
95 8 static av_cold int flic_decode_init(AVCodecContext *avctx)
96 {
97 8 FlicDecodeContext *s = avctx->priv_data;
98 8 uint8_t *fli_header = avctx->extradata;
99 int depth;
100
101
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 if (avctx->extradata_size != 0 &&
102
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
8 avctx->extradata_size != 12 &&
103
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 avctx->extradata_size != 128 &&
104 avctx->extradata_size != 256 &&
105 avctx->extradata_size != 904 &&
106 avctx->extradata_size != 1024) {
107 av_log(avctx, AV_LOG_ERROR, "Unexpected extradata size %d\n", avctx->extradata_size);
108 return AVERROR_INVALIDDATA;
109 }
110
111 8 s->avctx = avctx;
112
113
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6 times.
8 if (s->avctx->extradata_size == 12) {
114 /* special case for magic carpet FLIs */
115 2 s->fli_type = FLC_MAGIC_CARPET_SYNTHETIC_TYPE_CODE;
116 2 depth = 8;
117
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 } else if (avctx->extradata_size == 1024) {
118 uint8_t *ptr = avctx->extradata;
119 int i;
120
121 for (i = 0; i < 256; i++) {
122 s->palette[i] = AV_RL32(ptr);
123 ptr += 4;
124 }
125 depth = 8;
126 /* FLI in MOV, see e.g. FFmpeg trac issue #626 */
127
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 } else if (avctx->extradata_size == 0 ||
128
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 avctx->extradata_size == 256 ||
129 /* see FFmpeg ticket #1234 */
130
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 avctx->extradata_size == 904) {
131 s->fli_type = FLI_TYPE_CODE;
132 depth = 8;
133 } else {
134 6 s->fli_type = AV_RL16(&fli_header[4]);
135 6 depth = AV_RL16(&fli_header[12]);
136 }
137
138
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (depth == 0) {
139 depth = 8; /* Some FLC generators set depth to zero, when they mean 8Bpp. Fix up here */
140 }
141
142
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
8 if ((s->fli_type == FLC_FLX_TYPE_CODE) && (depth == 16)) {
143 depth = 15; /* Original Autodesk FLX's say the depth is 16Bpp when it is really 15Bpp */
144 }
145
146
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
8 switch (depth) {
147 case 1 : avctx->pix_fmt = AV_PIX_FMT_MONOBLACK; break;
148 8 case 8 : avctx->pix_fmt = AV_PIX_FMT_PAL8; break;
149 case 15 : avctx->pix_fmt = AV_PIX_FMT_RGB555; break;
150 case 16 : avctx->pix_fmt = AV_PIX_FMT_RGB565; break;
151 case 24 : avctx->pix_fmt = AV_PIX_FMT_BGR24; break;
152 default :
153 av_log(avctx, AV_LOG_ERROR, "Unknown FLC/FLX depth of %d Bpp is unsupported.\n",depth);
154 return AVERROR_INVALIDDATA;
155 }
156
157 8 s->frame = av_frame_alloc();
158
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (!s->frame)
159 return AVERROR(ENOMEM);
160
161 8 s->new_palette = 0;
162
163 8 return 0;
164 }
165
166 static int flic_decode_frame_1BPP(AVCodecContext *avctx,
167 AVFrame *rframe, int *got_frame,
168 const uint8_t *buf, int buf_size)
169 {
170 FlicDecodeContext *s = avctx->priv_data;
171
172 GetByteContext g2;
173 ptrdiff_t pixel_ptr;
174
175 unsigned int frame_size;
176 int num_chunks;
177
178 unsigned int chunk_size;
179 int chunk_type;
180
181 int i, j, ret, direction;
182
183 int lines;
184 int compressed_lines;
185 int starting_line;
186 int line_packets;
187 ptrdiff_t y_ptr;
188 int byte_run;
189 int pixel_skip;
190 int pixel_countdown;
191 unsigned char *pixels;
192 ptrdiff_t pixel_limit;
193
194 bytestream2_init(&g2, buf, buf_size);
195
196 if ((ret = ff_reget_buffer(avctx, s->frame, 0)) < 0)
197 return ret;
198
199 direction = s->frame->linesize[0] > 0;
200 pixels = s->frame->data[0];
201 pixel_limit = s->avctx->height * s->frame->linesize[0];
202 if (buf_size < 16 || buf_size > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE)
203 return AVERROR_INVALIDDATA;
204 frame_size = bytestream2_get_le32(&g2);
205 if (frame_size > buf_size)
206 frame_size = buf_size;
207 bytestream2_skip(&g2, 2); /* skip the magic number */
208 num_chunks = bytestream2_get_le16(&g2);
209 bytestream2_skip(&g2, 8); /* skip padding */
210
211 if (frame_size < 16)
212 return AVERROR_INVALIDDATA;
213
214 frame_size -= 16;
215
216 /* iterate through the chunks */
217 while ((frame_size >= 6) && (num_chunks > 0) &&
218 bytestream2_get_bytes_left(&g2) >= 4) {
219 int stream_ptr_after_chunk;
220 chunk_size = bytestream2_get_le32(&g2);
221 if (chunk_size > frame_size) {
222 av_log(avctx, AV_LOG_WARNING,
223 "Invalid chunk_size = %u > frame_size = %u\n", chunk_size, frame_size);
224 chunk_size = frame_size;
225 }
226 stream_ptr_after_chunk = bytestream2_tell(&g2) - 4 + chunk_size;
227
228 chunk_type = bytestream2_get_le16(&g2);
229
230 switch (chunk_type) {
231 case FLI_BRUN:
232 /* Byte run compression: This chunk type only occurs in the first
233 * FLI frame and it will update the entire frame. */
234 y_ptr = 0;
235 for (lines = 0; lines < s->avctx->height; lines++) {
236 pixel_ptr = y_ptr;
237 /* disregard the line packets; instead, iterate through all
238 * pixels on a row */
239 bytestream2_skip(&g2, 1);
240 pixel_countdown = (s->avctx->width + 7) >> 3;
241 while (pixel_countdown > 0) {
242 if (bytestream2_tell(&g2) + 1 > stream_ptr_after_chunk)
243 break;
244 byte_run = sign_extend(bytestream2_get_byte(&g2), 8);
245 if (!byte_run) {
246 av_log(avctx, AV_LOG_ERROR, "Invalid byte run value.\n");
247 return AVERROR_INVALIDDATA;
248 }
249
250 if (byte_run > 0) {
251 int value = bytestream2_get_byte(&g2);
252 CHECK_PIXEL_PTR(byte_run);
253 for (j = 0; j < byte_run; j++) {
254 pixels[pixel_ptr++] = value;
255 pixel_countdown--;
256 if (pixel_countdown < 0)
257 av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d) at line %d\n",
258 pixel_countdown, lines);
259 }
260 } else { /* copy bytes if byte_run < 0 */
261 byte_run = -byte_run;
262 CHECK_PIXEL_PTR(byte_run);
263 if (bytestream2_tell(&g2) + byte_run > stream_ptr_after_chunk)
264 break;
265 for (j = 0; j < byte_run; j++) {
266 pixels[pixel_ptr++] = bytestream2_get_byte(&g2);
267 pixel_countdown--;
268 if (pixel_countdown < 0)
269 av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d) at line %d\n",
270 pixel_countdown, lines);
271 }
272 }
273 }
274
275 y_ptr += s->frame->linesize[0];
276 }
277 break;
278
279 case FLI_LC:
280 /* line compressed */
281 starting_line = bytestream2_get_le16(&g2);
282 if (starting_line >= s->avctx->height)
283 return AVERROR_INVALIDDATA;
284 y_ptr = 0;
285 y_ptr += starting_line * s->frame->linesize[0];
286
287 compressed_lines = bytestream2_get_le16(&g2);
288 while (compressed_lines > 0) {
289 pixel_ptr = y_ptr;
290 CHECK_PIXEL_PTR(0);
291 pixel_countdown = (s->avctx->width + 7) >> 3;
292 if (bytestream2_tell(&g2) + 1 > stream_ptr_after_chunk)
293 break;
294 line_packets = bytestream2_get_byte(&g2);
295 if (line_packets > 0) {
296 for (i = 0; i < line_packets; i++) {
297 /* account for the skip bytes */
298 if (bytestream2_tell(&g2) + 1 > stream_ptr_after_chunk)
299 break;
300 pixel_skip = bytestream2_get_byte(&g2);
301 pixel_ptr += pixel_skip;
302 pixel_countdown -= pixel_skip;
303 byte_run = sign_extend(bytestream2_get_byte(&g2),8);
304 if (byte_run > 0) {
305 CHECK_PIXEL_PTR(byte_run);
306 if (bytestream2_tell(&g2) + byte_run > stream_ptr_after_chunk)
307 break;
308 for (j = 0; j < byte_run; j++, pixel_countdown--) {
309 pixels[pixel_ptr++] = bytestream2_get_byte(&g2);
310 }
311 } else if (byte_run < 0) {
312 int value = bytestream2_get_byte(&g2);
313 byte_run = -byte_run;
314 CHECK_PIXEL_PTR(byte_run);
315 for (j = 0; j < byte_run; j++, pixel_countdown--) {
316 pixels[pixel_ptr++] = value;
317 }
318 }
319 }
320 }
321
322 y_ptr += s->frame->linesize[0];
323 compressed_lines--;
324 }
325 break;
326
327 default:
328 av_log(avctx, AV_LOG_ERROR, "Unrecognized chunk type: %d\n", chunk_type);
329 break;
330 }
331
332 if (stream_ptr_after_chunk - bytestream2_tell(&g2) >= 0) {
333 bytestream2_skip(&g2, stream_ptr_after_chunk - bytestream2_tell(&g2));
334 } else {
335 av_log(avctx, AV_LOG_ERROR, "Chunk overread\n");
336 break;
337 }
338
339 frame_size -= chunk_size;
340 num_chunks--;
341 }
342
343 /* by the end of the chunk, the stream ptr should equal the frame
344 * size (minus 1 or 2, possibly); if it doesn't, issue a warning */
345 if (bytestream2_get_bytes_left(&g2) > 2)
346 av_log(avctx, AV_LOG_ERROR, "Processed FLI chunk where chunk size = %d " \
347 "and final chunk ptr = %d\n", buf_size,
348 buf_size - bytestream2_get_bytes_left(&g2));
349
350 if ((ret = av_frame_ref(rframe, s->frame)) < 0)
351 return ret;
352
353 *got_frame = 1;
354
355 return buf_size;
356 }
357
358 510 static int flic_decode_frame_8BPP(AVCodecContext *avctx,
359 AVFrame *rframe, int *got_frame,
360 const uint8_t *buf, int buf_size)
361 {
362 510 FlicDecodeContext *s = avctx->priv_data;
363
364 GetByteContext g2;
365 ptrdiff_t pixel_ptr;
366 int palette_ptr;
367 unsigned char palette_idx1;
368 unsigned char palette_idx2;
369
370 unsigned int frame_size;
371 int num_chunks;
372
373 unsigned int chunk_size;
374 int chunk_type;
375
376 int i, j, ret, direction;
377
378 int color_packets;
379 int color_changes;
380 int color_shift;
381 unsigned char r, g, b;
382
383 int lines;
384 int compressed_lines;
385 int starting_line;
386 int line_packets;
387 ptrdiff_t y_ptr;
388 int byte_run;
389 int pixel_skip;
390 int pixel_countdown;
391 unsigned char *pixels;
392 ptrdiff_t pixel_limit;
393
394 510 bytestream2_init(&g2, buf, buf_size);
395
396
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 510 times.
510 if ((ret = ff_reget_buffer(avctx, s->frame, 0)) < 0)
397 return ret;
398
399 510 direction = s->frame->linesize[0] > 0;
400 510 pixels = s->frame->data[0];
401 510 pixel_limit = s->avctx->height * s->frame->linesize[0];
402
2/4
✓ Branch 0 taken 510 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 510 times.
510 if (buf_size < 16 || buf_size > INT_MAX - (3 * 256 + AV_INPUT_BUFFER_PADDING_SIZE))
403 return AVERROR_INVALIDDATA;
404 510 frame_size = bytestream2_get_le32(&g2);
405
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 510 times.
510 if (frame_size > buf_size)
406 frame_size = buf_size;
407 510 bytestream2_skip(&g2, 2); /* skip the magic number */
408 510 num_chunks = bytestream2_get_le16(&g2);
409 510 bytestream2_skip(&g2, 8); /* skip padding */
410
411
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 510 times.
510 if (frame_size < 16)
412 return AVERROR_INVALIDDATA;
413
414 510 frame_size -= 16;
415
416 /* iterate through the chunks */
417
4/6
✓ Branch 0 taken 533 times.
✓ Branch 1 taken 510 times.
✓ Branch 2 taken 533 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 533 times.
✗ Branch 5 not taken.
1576 while ((frame_size >= 6) && (num_chunks > 0) &&
418 533 bytestream2_get_bytes_left(&g2) >= 4) {
419 int stream_ptr_after_chunk;
420 533 chunk_size = bytestream2_get_le32(&g2);
421
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 533 times.
533 if (chunk_size > frame_size) {
422 av_log(avctx, AV_LOG_WARNING,
423 "Invalid chunk_size = %u > frame_size = %u\n", chunk_size, frame_size);
424 chunk_size = frame_size;
425 }
426 533 stream_ptr_after_chunk = bytestream2_tell(&g2) - 4 + chunk_size;
427
428 533 chunk_type = bytestream2_get_le16(&g2);
429
430
4/8
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 67 times.
✓ Branch 2 taken 420 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
533 switch (chunk_type) {
431 42 case FLI_256_COLOR:
432 case FLI_COLOR:
433 /* check special case: If this file is from the Magic Carpet
434 * game and uses 6-bit colors even though it reports 256-color
435 * chunks in a 0xAF12-type file (fli_type is set to 0xAF13 during
436 * initialization) */
437
4/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 40 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1 times.
42 if ((chunk_type == FLI_256_COLOR) && (s->fli_type != FLC_MAGIC_CARPET_SYNTHETIC_TYPE_CODE))
438 1 color_shift = 0;
439 else
440 41 color_shift = 2;
441 /* set up the palette */
442 42 color_packets = bytestream2_get_le16(&g2);
443 42 palette_ptr = 0;
444
2/2
✓ Branch 0 taken 255 times.
✓ Branch 1 taken 42 times.
297 for (i = 0; i < color_packets; i++) {
445 /* first byte is how many colors to skip */
446 255 palette_ptr += bytestream2_get_byte(&g2);
447
448 /* next byte indicates how many entries to change */
449 255 color_changes = bytestream2_get_byte(&g2);
450
451 /* if there are 0 color changes, there are actually 256 */
452
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 251 times.
255 if (color_changes == 0)
453 4 color_changes = 256;
454
455
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 255 times.
255 if (bytestream2_tell(&g2) + color_changes * 3 > stream_ptr_after_chunk)
456 break;
457
458
2/2
✓ Branch 0 taken 10388 times.
✓ Branch 1 taken 255 times.
10643 for (j = 0; j < color_changes; j++) {
459 unsigned int entry;
460
461 /* wrap around, for good measure */
462
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10388 times.
10388 if ((unsigned)palette_ptr >= 256)
463 palette_ptr = 0;
464
465 10388 r = bytestream2_get_byte(&g2) << color_shift;
466 10388 g = bytestream2_get_byte(&g2) << color_shift;
467 10388 b = bytestream2_get_byte(&g2) << color_shift;
468 10388 entry = 0xFFU << 24 | r << 16 | g << 8 | b;
469
2/2
✓ Branch 0 taken 10132 times.
✓ Branch 1 taken 256 times.
10388 if (color_shift == 2)
470 10132 entry |= entry >> 6 & 0x30303;
471
1/2
✓ Branch 0 taken 10388 times.
✗ Branch 1 not taken.
10388 if (s->palette[palette_ptr] != entry)
472 10388 s->new_palette = 1;
473 10388 s->palette[palette_ptr++] = entry;
474 }
475 }
476 42 break;
477
478 67 case FLI_DELTA:
479 67 y_ptr = 0;
480 67 compressed_lines = bytestream2_get_le16(&g2);
481
2/2
✓ Branch 0 taken 8221 times.
✓ Branch 1 taken 67 times.
8288 while (compressed_lines > 0) {
482
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8221 times.
8221 if (bytestream2_tell(&g2) + 2 > stream_ptr_after_chunk)
483 break;
484
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8221 times.
8221 CHECK_Y_PTR()
485 8221 line_packets = sign_extend(bytestream2_get_le16(&g2), 16);
486
2/2
✓ Branch 0 taken 108 times.
✓ Branch 1 taken 8113 times.
8221 if ((line_packets & 0xC000) == 0xC000) {
487 // line skip opcode
488 108 line_packets = -line_packets;
489
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 108 times.
108 if (line_packets > s->avctx->height)
490 return AVERROR_INVALIDDATA;
491 108 y_ptr += line_packets * s->frame->linesize[0];
492
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8113 times.
8113 } else if ((line_packets & 0xC000) == 0x4000) {
493 av_log(avctx, AV_LOG_ERROR, "Undefined opcode (%x) in DELTA_FLI\n", line_packets);
494
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8113 times.
8113 } else if ((line_packets & 0xC000) == 0x8000) {
495 // "last byte" opcode
496 pixel_ptr= y_ptr + s->frame->linesize[0] - 1;
497 CHECK_PIXEL_PTR(0);
498 pixels[pixel_ptr] = line_packets & 0xff;
499 } else {
500 8113 compressed_lines--;
501 8113 pixel_ptr = y_ptr;
502
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8113 times.
8113 CHECK_PIXEL_PTR(0);
503 8113 pixel_countdown = s->avctx->width;
504
2/2
✓ Branch 0 taken 124608 times.
✓ Branch 1 taken 8113 times.
132721 for (i = 0; i < line_packets; i++) {
505
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 124608 times.
124608 if (bytestream2_tell(&g2) + 2 > stream_ptr_after_chunk)
506 break;
507 /* account for the skip bytes */
508 124608 pixel_skip = bytestream2_get_byte(&g2);
509 124608 pixel_ptr += pixel_skip;
510 124608 pixel_countdown -= pixel_skip;
511 124608 byte_run = sign_extend(bytestream2_get_byte(&g2), 8);
512
2/2
✓ Branch 0 taken 37508 times.
✓ Branch 1 taken 87100 times.
124608 if (byte_run < 0) {
513 37508 byte_run = -byte_run;
514 37508 palette_idx1 = bytestream2_get_byte(&g2);
515 37508 palette_idx2 = bytestream2_get_byte(&g2);
516
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 37508 times.
37508 CHECK_PIXEL_PTR(byte_run * 2);
517
2/2
✓ Branch 0 taken 182495 times.
✓ Branch 1 taken 37508 times.
220003 for (j = 0; j < byte_run; j++, pixel_countdown -= 2) {
518 182495 pixels[pixel_ptr++] = palette_idx1;
519 182495 pixels[pixel_ptr++] = palette_idx2;
520 }
521 } else {
522
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 87100 times.
87100 CHECK_PIXEL_PTR(byte_run * 2);
523
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 87100 times.
87100 if (bytestream2_tell(&g2) + byte_run * 2 > stream_ptr_after_chunk)
524 break;
525
2/2
✓ Branch 0 taken 819286 times.
✓ Branch 1 taken 87100 times.
906386 for (j = 0; j < byte_run * 2; j++, pixel_countdown--) {
526 819286 pixels[pixel_ptr++] = bytestream2_get_byte(&g2);
527 }
528 }
529 }
530
531 8113 y_ptr += s->frame->linesize[0];
532 }
533 }
534 67 break;
535
536 420 case FLI_LC:
537 /* line compressed */
538 420 starting_line = bytestream2_get_le16(&g2);
539
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 420 times.
420 if (starting_line >= s->avctx->height)
540 return AVERROR_INVALIDDATA;
541 420 y_ptr = 0;
542 420 y_ptr += starting_line * s->frame->linesize[0];
543
544 420 compressed_lines = bytestream2_get_le16(&g2);
545
2/2
✓ Branch 0 taken 54111 times.
✓ Branch 1 taken 420 times.
54531 while (compressed_lines > 0) {
546 54111 pixel_ptr = y_ptr;
547
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 54111 times.
54111 CHECK_PIXEL_PTR(0);
548 54111 pixel_countdown = s->avctx->width;
549
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 54111 times.
54111 if (bytestream2_tell(&g2) + 1 > stream_ptr_after_chunk)
550 break;
551 54111 line_packets = bytestream2_get_byte(&g2);
552
2/2
✓ Branch 0 taken 48982 times.
✓ Branch 1 taken 5129 times.
54111 if (line_packets > 0) {
553
2/2
✓ Branch 0 taken 323419 times.
✓ Branch 1 taken 48982 times.
372401 for (i = 0; i < line_packets; i++) {
554 /* account for the skip bytes */
555
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 323419 times.
323419 if (bytestream2_tell(&g2) + 1 > stream_ptr_after_chunk)
556 break;
557 323419 pixel_skip = bytestream2_get_byte(&g2);
558 323419 pixel_ptr += pixel_skip;
559 323419 pixel_countdown -= pixel_skip;
560 323419 byte_run = sign_extend(bytestream2_get_byte(&g2),8);
561
2/2
✓ Branch 0 taken 237641 times.
✓ Branch 1 taken 85778 times.
323419 if (byte_run > 0) {
562
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 237641 times.
237641 CHECK_PIXEL_PTR(byte_run);
563
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 237641 times.
237641 if (bytestream2_tell(&g2) + byte_run > stream_ptr_after_chunk)
564 break;
565
2/2
✓ Branch 0 taken 1371847 times.
✓ Branch 1 taken 237641 times.
1609488 for (j = 0; j < byte_run; j++, pixel_countdown--) {
566 1371847 pixels[pixel_ptr++] = bytestream2_get_byte(&g2);
567 }
568
1/2
✓ Branch 0 taken 85778 times.
✗ Branch 1 not taken.
85778 } else if (byte_run < 0) {
569 85778 byte_run = -byte_run;
570 85778 palette_idx1 = bytestream2_get_byte(&g2);
571
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 85778 times.
85778 CHECK_PIXEL_PTR(byte_run);
572
2/2
✓ Branch 0 taken 545540 times.
✓ Branch 1 taken 85778 times.
631318 for (j = 0; j < byte_run; j++, pixel_countdown--) {
573 545540 pixels[pixel_ptr++] = palette_idx1;
574 }
575 }
576 }
577 }
578
579 54111 y_ptr += s->frame->linesize[0];
580 54111 compressed_lines--;
581 }
582 420 break;
583
584 case FLI_BLACK:
585 /* set the whole frame to color 0 (which is usually black) */
586 for (int y = 0; y < s->avctx->height; y++)
587 memset(pixels + y * s->frame->linesize[0], 0, s->avctx->width);
588 break;
589
590 4 case FLI_BRUN:
591 /* Byte run compression: This chunk type only occurs in the first
592 * FLI frame and it will update the entire frame. */
593 4 y_ptr = 0;
594
2/2
✓ Branch 0 taken 1080 times.
✓ Branch 1 taken 4 times.
1084 for (lines = 0; lines < s->avctx->height; lines++) {
595 1080 pixel_ptr = y_ptr;
596 /* disregard the line packets; instead, iterate through all
597 * pixels on a row */
598 1080 bytestream2_skip(&g2, 1);
599 1080 pixel_countdown = s->avctx->width;
600
2/2
✓ Branch 0 taken 22787 times.
✓ Branch 1 taken 1080 times.
23867 while (pixel_countdown > 0) {
601
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 22787 times.
22787 if (bytestream2_tell(&g2) + 1 > stream_ptr_after_chunk)
602 break;
603 22787 byte_run = sign_extend(bytestream2_get_byte(&g2), 8);
604
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22787 times.
22787 if (!byte_run) {
605 av_log(avctx, AV_LOG_ERROR, "Invalid byte run value.\n");
606 return AVERROR_INVALIDDATA;
607 }
608
609
2/2
✓ Branch 0 taken 14467 times.
✓ Branch 1 taken 8320 times.
22787 if (byte_run > 0) {
610 14467 palette_idx1 = bytestream2_get_byte(&g2);
611
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 14467 times.
14467 CHECK_PIXEL_PTR(byte_run);
612
2/2
✓ Branch 0 taken 478048 times.
✓ Branch 1 taken 14467 times.
492515 for (j = 0; j < byte_run; j++) {
613 478048 pixels[pixel_ptr++] = palette_idx1;
614 478048 pixel_countdown--;
615
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 478048 times.
478048 if (pixel_countdown < 0)
616 av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d) at line %d\n",
617 pixel_countdown, lines);
618 }
619 } else { /* copy bytes if byte_run < 0 */
620 8320 byte_run = -byte_run;
621
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8320 times.
8320 CHECK_PIXEL_PTR(byte_run);
622
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8320 times.
8320 if (bytestream2_tell(&g2) + byte_run > stream_ptr_after_chunk)
623 break;
624
2/2
✓ Branch 0 taken 21152 times.
✓ Branch 1 taken 8320 times.
29472 for (j = 0; j < byte_run; j++) {
625 21152 pixels[pixel_ptr++] = bytestream2_get_byte(&g2);
626 21152 pixel_countdown--;
627
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21152 times.
21152 if (pixel_countdown < 0)
628 av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d) at line %d\n",
629 pixel_countdown, lines);
630 }
631 }
632 }
633
634 1080 y_ptr += s->frame->linesize[0];
635 }
636 4 break;
637
638 case FLI_COPY:
639 /* copy the chunk (uncompressed frame) */
640 if (chunk_size - 6 != FFALIGN(s->avctx->width, 4) * s->avctx->height) {
641 av_log(avctx, AV_LOG_ERROR, "In chunk FLI_COPY : source data (%d bytes) " \
642 "has incorrect size, skipping chunk\n", chunk_size - 6);
643 bytestream2_skip(&g2, chunk_size - 6);
644 } else {
645 for (y_ptr = 0; check_pixel_ptr(y_ptr, s->avctx->width, pixel_limit, direction) == 0;
646 y_ptr += s->frame->linesize[0]) {
647 bytestream2_get_buffer(&g2, &pixels[y_ptr],
648 s->avctx->width);
649 if (s->avctx->width & 3)
650 bytestream2_skip(&g2, 4 - (s->avctx->width & 3));
651 }
652 }
653 break;
654
655 case FLI_MINI:
656 /* some sort of a thumbnail? disregard this chunk... */
657 break;
658
659 default:
660 av_log(avctx, AV_LOG_ERROR, "Unrecognized chunk type: %d\n", chunk_type);
661 break;
662 }
663
664
1/2
✓ Branch 1 taken 533 times.
✗ Branch 2 not taken.
533 if (stream_ptr_after_chunk - bytestream2_tell(&g2) >= 0) {
665 533 bytestream2_skip(&g2, stream_ptr_after_chunk - bytestream2_tell(&g2));
666 } else {
667 av_log(avctx, AV_LOG_ERROR, "Chunk overread\n");
668 break;
669 }
670
671 533 frame_size -= chunk_size;
672 533 num_chunks--;
673 }
674
675 /* by the end of the chunk, the stream ptr should equal the frame
676 * size (minus 1 or 2, possibly); if it doesn't, issue a warning */
677
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 510 times.
510 if (bytestream2_get_bytes_left(&g2) > 2)
678 av_log(avctx, AV_LOG_ERROR, "Processed FLI chunk where chunk size = %d " \
679 "and final chunk ptr = %d\n", buf_size,
680 buf_size - bytestream2_get_bytes_left(&g2));
681
682 /* make the palette available on the way out */
683 510 memcpy(s->frame->data[1], s->palette, AVPALETTE_SIZE);
684
2/2
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 468 times.
510 if (s->new_palette) {
685 #if FF_API_PALETTE_HAS_CHANGED
686 FF_DISABLE_DEPRECATION_WARNINGS
687 42 s->frame->palette_has_changed = 1;
688 FF_ENABLE_DEPRECATION_WARNINGS
689 #endif
690 42 s->new_palette = 0;
691 }
692
693
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 510 times.
510 if ((ret = av_frame_ref(rframe, s->frame)) < 0)
694 return ret;
695
696 510 *got_frame = 1;
697
698 510 return buf_size;
699 }
700
701 static int flic_decode_frame_15_16BPP(AVCodecContext *avctx,
702 AVFrame *rframe, int *got_frame,
703 const uint8_t *buf, int buf_size)
704 {
705 /* Note, the only difference between the 15Bpp and 16Bpp */
706 /* Format is the pixel format, the packets are processed the same. */
707 FlicDecodeContext *s = avctx->priv_data;
708
709 GetByteContext g2;
710 ptrdiff_t pixel_ptr;
711 unsigned char palette_idx1;
712
713 unsigned int frame_size;
714 int num_chunks;
715
716 unsigned int chunk_size;
717 int chunk_type;
718
719 int i, j, ret, direction;
720
721 int lines;
722 int compressed_lines;
723 int line_packets;
724 ptrdiff_t y_ptr;
725 int byte_run;
726 int pixel_skip;
727 int pixel_countdown;
728 unsigned char *pixels;
729 int pixel;
730 ptrdiff_t pixel_limit;
731
732 bytestream2_init(&g2, buf, buf_size);
733
734 if ((ret = ff_reget_buffer(avctx, s->frame, 0)) < 0)
735 return ret;
736
737 direction = s->frame->linesize[0] > 0;
738 pixels = s->frame->data[0];
739 pixel_limit = s->avctx->height * s->frame->linesize[0];
740
741 frame_size = bytestream2_get_le32(&g2);
742 bytestream2_skip(&g2, 2); /* skip the magic number */
743 num_chunks = bytestream2_get_le16(&g2);
744 bytestream2_skip(&g2, 8); /* skip padding */
745 if (frame_size > buf_size)
746 frame_size = buf_size;
747
748 if (frame_size < 16)
749 return AVERROR_INVALIDDATA;
750 frame_size -= 16;
751
752 /* iterate through the chunks */
753 while ((frame_size > 0) && (num_chunks > 0) &&
754 bytestream2_get_bytes_left(&g2) >= 4) {
755 int stream_ptr_after_chunk;
756 chunk_size = bytestream2_get_le32(&g2);
757 if (chunk_size > frame_size) {
758 av_log(avctx, AV_LOG_WARNING,
759 "Invalid chunk_size = %u > frame_size = %u\n", chunk_size, frame_size);
760 chunk_size = frame_size;
761 }
762 stream_ptr_after_chunk = bytestream2_tell(&g2) - 4 + chunk_size;
763
764 chunk_type = bytestream2_get_le16(&g2);
765
766
767 switch (chunk_type) {
768 case FLI_256_COLOR:
769 case FLI_COLOR:
770 /* For some reason, it seems that non-palettized flics do
771 * include one of these chunks in their first frame.
772 * Why I do not know, it seems rather extraneous. */
773 ff_dlog(avctx,
774 "Unexpected Palette chunk %d in non-palettized FLC\n",
775 chunk_type);
776 bytestream2_skip(&g2, chunk_size - 6);
777 break;
778
779 case FLI_DELTA:
780 case FLI_DTA_LC:
781 y_ptr = 0;
782 compressed_lines = bytestream2_get_le16(&g2);
783 while (compressed_lines > 0) {
784 if (bytestream2_tell(&g2) + 2 > stream_ptr_after_chunk)
785 break;
786 CHECK_Y_PTR()
787 line_packets = sign_extend(bytestream2_get_le16(&g2), 16);
788 if (line_packets < 0) {
789 line_packets = -line_packets;
790 if (line_packets > s->avctx->height)
791 return AVERROR_INVALIDDATA;
792 y_ptr += line_packets * s->frame->linesize[0];
793 } else {
794 compressed_lines--;
795 pixel_ptr = y_ptr;
796 CHECK_PIXEL_PTR(0);
797 pixel_countdown = s->avctx->width;
798 for (i = 0; i < line_packets; i++) {
799 /* account for the skip bytes */
800 if (bytestream2_tell(&g2) + 2 > stream_ptr_after_chunk)
801 break;
802 pixel_skip = bytestream2_get_byte(&g2);
803 pixel_ptr += (pixel_skip*2); /* Pixel is 2 bytes wide */
804 pixel_countdown -= pixel_skip;
805 byte_run = sign_extend(bytestream2_get_byte(&g2), 8);
806 if (byte_run < 0) {
807 byte_run = -byte_run;
808 pixel = bytestream2_get_le16(&g2);
809 CHECK_PIXEL_PTR(2 * byte_run);
810 for (j = 0; j < byte_run; j++, pixel_countdown -= 2) {
811 *((signed short*)(&pixels[pixel_ptr])) = pixel;
812 pixel_ptr += 2;
813 }
814 } else {
815 if (bytestream2_tell(&g2) + 2*byte_run > stream_ptr_after_chunk)
816 break;
817 CHECK_PIXEL_PTR(2 * byte_run);
818 for (j = 0; j < byte_run; j++, pixel_countdown--) {
819 *((signed short*)(&pixels[pixel_ptr])) = bytestream2_get_le16(&g2);
820 pixel_ptr += 2;
821 }
822 }
823 }
824
825 y_ptr += s->frame->linesize[0];
826 }
827 }
828 break;
829
830 case FLI_LC:
831 av_log(avctx, AV_LOG_ERROR, "Unexpected FLI_LC chunk in non-palettized FLC\n");
832 bytestream2_skip(&g2, chunk_size - 6);
833 break;
834
835 case FLI_BLACK:
836 /* set the whole frame to 0x0000 which is black in both 15Bpp and 16Bpp modes. */
837 for (int y = 0; y < s->avctx->height; y++)
838 memset(pixels + y * s->frame->linesize[0], 0, s->avctx->width * 2);
839 break;
840
841 case FLI_BRUN:
842 y_ptr = 0;
843 for (lines = 0; lines < s->avctx->height; lines++) {
844 pixel_ptr = y_ptr;
845 /* disregard the line packets; instead, iterate through all
846 * pixels on a row */
847 bytestream2_skip(&g2, 1);
848 pixel_countdown = (s->avctx->width * 2);
849
850 while (pixel_countdown > 0) {
851 if (bytestream2_tell(&g2) + 1 > stream_ptr_after_chunk)
852 break;
853 byte_run = sign_extend(bytestream2_get_byte(&g2), 8);
854 if (byte_run > 0) {
855 palette_idx1 = bytestream2_get_byte(&g2);
856 CHECK_PIXEL_PTR(byte_run);
857 for (j = 0; j < byte_run; j++) {
858 pixels[pixel_ptr++] = palette_idx1;
859 pixel_countdown--;
860 if (pixel_countdown < 0)
861 av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d) (linea%d)\n",
862 pixel_countdown, lines);
863 }
864 } else { /* copy bytes if byte_run < 0 */
865 byte_run = -byte_run;
866 if (bytestream2_tell(&g2) + byte_run > stream_ptr_after_chunk)
867 break;
868 CHECK_PIXEL_PTR(byte_run);
869 for (j = 0; j < byte_run; j++) {
870 palette_idx1 = bytestream2_get_byte(&g2);
871 pixels[pixel_ptr++] = palette_idx1;
872 pixel_countdown--;
873 if (pixel_countdown < 0)
874 av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d) at line %d\n",
875 pixel_countdown, lines);
876 }
877 }
878 }
879
880 /* Now FLX is strange, in that it is "byte" as opposed to "pixel" run length compressed.
881 * This does not give us any good opportunity to perform word endian conversion
882 * during decompression. So if it is required (i.e., this is not a LE target, we do
883 * a second pass over the line here, swapping the bytes.
884 */
885 #if HAVE_BIGENDIAN
886 pixel_ptr = y_ptr;
887 pixel_countdown = s->avctx->width;
888 while (pixel_countdown > 0) {
889 *((signed short*)(&pixels[pixel_ptr])) = AV_RL16(&buf[pixel_ptr]);
890 pixel_ptr += 2;
891 }
892 #endif
893 y_ptr += s->frame->linesize[0];
894 }
895 break;
896
897 case FLI_DTA_BRUN:
898 y_ptr = 0;
899 for (lines = 0; lines < s->avctx->height; lines++) {
900 pixel_ptr = y_ptr;
901 /* disregard the line packets; instead, iterate through all
902 * pixels on a row */
903 bytestream2_skip(&g2, 1);
904 pixel_countdown = s->avctx->width; /* Width is in pixels, not bytes */
905
906 while (pixel_countdown > 0) {
907 if (bytestream2_tell(&g2) + 1 > stream_ptr_after_chunk)
908 break;
909 byte_run = sign_extend(bytestream2_get_byte(&g2), 8);
910 if (byte_run > 0) {
911 pixel = bytestream2_get_le16(&g2);
912 CHECK_PIXEL_PTR(2 * byte_run);
913 for (j = 0; j < byte_run; j++) {
914 *((signed short*)(&pixels[pixel_ptr])) = pixel;
915 pixel_ptr += 2;
916 pixel_countdown--;
917 if (pixel_countdown < 0)
918 av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d)\n",
919 pixel_countdown);
920 }
921 } else { /* copy pixels if byte_run < 0 */
922 byte_run = -byte_run;
923 if (bytestream2_tell(&g2) + 2 * byte_run > stream_ptr_after_chunk)
924 break;
925 CHECK_PIXEL_PTR(2 * byte_run);
926 for (j = 0; j < byte_run; j++) {
927 *((signed short*)(&pixels[pixel_ptr])) = bytestream2_get_le16(&g2);
928 pixel_ptr += 2;
929 pixel_countdown--;
930 if (pixel_countdown < 0)
931 av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d)\n",
932 pixel_countdown);
933 }
934 }
935 }
936
937 y_ptr += s->frame->linesize[0];
938 }
939 break;
940
941 case FLI_COPY:
942 case FLI_DTA_COPY:
943 /* copy the chunk (uncompressed frame) */
944 if (chunk_size - 6 > (unsigned int)(FFALIGN(s->avctx->width, 2) * s->avctx->height)*2) {
945 av_log(avctx, AV_LOG_ERROR, "In chunk FLI_COPY : source data (%d bytes) " \
946 "bigger than image, skipping chunk\n", chunk_size - 6);
947 bytestream2_skip(&g2, chunk_size - 6);
948 } else {
949
950 if (bytestream2_get_bytes_left(&g2) < 2 * s->avctx->width * s->avctx->height )
951 return AVERROR_INVALIDDATA;
952 for (y_ptr = 0; check_pixel_ptr(y_ptr, 2*s->avctx->width, pixel_limit, direction) == 0;
953 y_ptr += s->frame->linesize[0]) {
954
955 pixel_countdown = s->avctx->width;
956 pixel_ptr = 0;
957 while (pixel_countdown > 0) {
958 *((signed short*)(&pixels[y_ptr + pixel_ptr])) = bytestream2_get_le16(&g2);
959 pixel_ptr += 2;
960 pixel_countdown--;
961 }
962 if (s->avctx->width & 1)
963 bytestream2_skip(&g2, 2);
964 }
965 }
966 break;
967
968 case FLI_MINI:
969 /* some sort of a thumbnail? disregard this chunk... */
970 bytestream2_skip(&g2, chunk_size - 6);
971 break;
972
973 default:
974 av_log(avctx, AV_LOG_ERROR, "Unrecognized chunk type: %d\n", chunk_type);
975 break;
976 }
977
978 if (stream_ptr_after_chunk - bytestream2_tell(&g2) >= 0) {
979 bytestream2_skip(&g2, stream_ptr_after_chunk - bytestream2_tell(&g2));
980 } else {
981 av_log(avctx, AV_LOG_ERROR, "Chunk overread\n");
982 break;
983 }
984
985 frame_size -= chunk_size;
986 num_chunks--;
987 }
988
989 /* by the end of the chunk, the stream ptr should equal the frame
990 * size (minus 1, possibly); if it doesn't, issue a warning */
991 if ((bytestream2_get_bytes_left(&g2) != 0) && (bytestream2_get_bytes_left(&g2) != 1))
992 av_log(avctx, AV_LOG_ERROR, "Processed FLI chunk where chunk size = %d " \
993 "and final chunk ptr = %d\n", buf_size, bytestream2_tell(&g2));
994
995 if ((ret = av_frame_ref(rframe, s->frame)) < 0)
996 return ret;
997
998 *got_frame = 1;
999
1000 return buf_size;
1001 }
1002
1003 static int flic_decode_frame_24BPP(AVCodecContext *avctx,
1004 AVFrame *rframe, int *got_frame,
1005 const uint8_t *buf, int buf_size)
1006 {
1007 FlicDecodeContext *s = avctx->priv_data;
1008
1009 GetByteContext g2;
1010 ptrdiff_t pixel_ptr;
1011 unsigned char palette_idx1;
1012
1013 unsigned int frame_size;
1014 int num_chunks;
1015
1016 unsigned int chunk_size;
1017 int chunk_type;
1018
1019 int i, j, ret, direction;
1020
1021 int lines;
1022 int compressed_lines;
1023 int line_packets;
1024 ptrdiff_t y_ptr;
1025 int byte_run;
1026 int pixel_skip;
1027 int pixel_countdown;
1028 unsigned char *pixels;
1029 int pixel;
1030 ptrdiff_t pixel_limit;
1031
1032 bytestream2_init(&g2, buf, buf_size);
1033
1034 if ((ret = ff_reget_buffer(avctx, s->frame, 0)) < 0)
1035 return ret;
1036
1037 direction = s->frame->linesize[0] > 0;
1038 pixels = s->frame->data[0];
1039 pixel_limit = s->avctx->height * s->frame->linesize[0];
1040
1041 frame_size = bytestream2_get_le32(&g2);
1042 bytestream2_skip(&g2, 2); /* skip the magic number */
1043 num_chunks = bytestream2_get_le16(&g2);
1044 bytestream2_skip(&g2, 8); /* skip padding */
1045 if (frame_size > buf_size)
1046 frame_size = buf_size;
1047
1048 if (frame_size < 16)
1049 return AVERROR_INVALIDDATA;
1050 frame_size -= 16;
1051
1052 /* iterate through the chunks */
1053 while ((frame_size > 0) && (num_chunks > 0) &&
1054 bytestream2_get_bytes_left(&g2) >= 4) {
1055 int stream_ptr_after_chunk;
1056 chunk_size = bytestream2_get_le32(&g2);
1057 if (chunk_size > frame_size) {
1058 av_log(avctx, AV_LOG_WARNING,
1059 "Invalid chunk_size = %u > frame_size = %u\n", chunk_size, frame_size);
1060 chunk_size = frame_size;
1061 }
1062 stream_ptr_after_chunk = bytestream2_tell(&g2) - 4 + chunk_size;
1063
1064 chunk_type = bytestream2_get_le16(&g2);
1065
1066
1067 switch (chunk_type) {
1068 case FLI_256_COLOR:
1069 case FLI_COLOR:
1070 /* For some reason, it seems that non-palettized flics do
1071 * include one of these chunks in their first frame.
1072 * Why I do not know, it seems rather extraneous. */
1073 ff_dlog(avctx,
1074 "Unexpected Palette chunk %d in non-palettized FLC\n",
1075 chunk_type);
1076 bytestream2_skip(&g2, chunk_size - 6);
1077 break;
1078
1079 case FLI_DELTA:
1080 case FLI_DTA_LC:
1081 y_ptr = 0;
1082 compressed_lines = bytestream2_get_le16(&g2);
1083 while (compressed_lines > 0) {
1084 if (bytestream2_tell(&g2) + 2 > stream_ptr_after_chunk)
1085 break;
1086 CHECK_Y_PTR()
1087 line_packets = sign_extend(bytestream2_get_le16(&g2), 16);
1088 if (line_packets < 0) {
1089 line_packets = -line_packets;
1090 if (line_packets > s->avctx->height)
1091 return AVERROR_INVALIDDATA;
1092 y_ptr += line_packets * s->frame->linesize[0];
1093 } else {
1094 compressed_lines--;
1095 pixel_ptr = y_ptr;
1096 CHECK_PIXEL_PTR(0);
1097 pixel_countdown = s->avctx->width;
1098 for (i = 0; i < line_packets; i++) {
1099 /* account for the skip bytes */
1100 if (bytestream2_tell(&g2) + 2 > stream_ptr_after_chunk)
1101 break;
1102 pixel_skip = bytestream2_get_byte(&g2);
1103 pixel_ptr += (pixel_skip*3); /* Pixel is 3 bytes wide */
1104 pixel_countdown -= pixel_skip;
1105 byte_run = sign_extend(bytestream2_get_byte(&g2), 8);
1106 if (byte_run < 0) {
1107 byte_run = -byte_run;
1108 pixel = bytestream2_get_le24(&g2);
1109 CHECK_PIXEL_PTR(3 * byte_run);
1110 for (j = 0; j < byte_run; j++, pixel_countdown -= 1) {
1111 AV_WL24(&pixels[pixel_ptr], pixel);
1112 pixel_ptr += 3;
1113 }
1114 } else {
1115 if (bytestream2_tell(&g2) + 2*byte_run > stream_ptr_after_chunk)
1116 break;
1117 CHECK_PIXEL_PTR(3 * byte_run);
1118 for (j = 0; j < byte_run; j++, pixel_countdown--) {
1119 pixel = bytestream2_get_le24(&g2);
1120 AV_WL24(&pixels[pixel_ptr], pixel);
1121 pixel_ptr += 3;
1122 }
1123 }
1124 }
1125
1126 y_ptr += s->frame->linesize[0];
1127 }
1128 }
1129 break;
1130
1131 case FLI_LC:
1132 av_log(avctx, AV_LOG_ERROR, "Unexpected FLI_LC chunk in non-palettized FLC\n");
1133 bytestream2_skip(&g2, chunk_size - 6);
1134 break;
1135
1136 case FLI_BLACK:
1137 /* set the whole frame to 0x00 which is black for 24 bit mode. */
1138 for (int y = 0; y < s->avctx->height; y++)
1139 memset(pixels + y * s->frame->linesize[0], 0, s->avctx->width * 3);
1140 break;
1141
1142 case FLI_BRUN:
1143 y_ptr = 0;
1144 for (lines = 0; lines < s->avctx->height; lines++) {
1145 pixel_ptr = y_ptr;
1146 /* disregard the line packets; instead, iterate through all
1147 * pixels on a row */
1148 bytestream2_skip(&g2, 1);
1149 pixel_countdown = (s->avctx->width * 3);
1150
1151 while (pixel_countdown > 0) {
1152 if (bytestream2_tell(&g2) + 1 > stream_ptr_after_chunk)
1153 break;
1154 byte_run = sign_extend(bytestream2_get_byte(&g2), 8);
1155 if (byte_run > 0) {
1156 palette_idx1 = bytestream2_get_byte(&g2);
1157 CHECK_PIXEL_PTR(byte_run);
1158 for (j = 0; j < byte_run; j++) {
1159 pixels[pixel_ptr++] = palette_idx1;
1160 pixel_countdown--;
1161 if (pixel_countdown < 0)
1162 av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d) (linea%d)\n",
1163 pixel_countdown, lines);
1164 }
1165 } else { /* copy bytes if byte_run < 0 */
1166 byte_run = -byte_run;
1167 if (bytestream2_tell(&g2) + byte_run > stream_ptr_after_chunk)
1168 break;
1169 CHECK_PIXEL_PTR(byte_run);
1170 for (j = 0; j < byte_run; j++) {
1171 palette_idx1 = bytestream2_get_byte(&g2);
1172 pixels[pixel_ptr++] = palette_idx1;
1173 pixel_countdown--;
1174 if (pixel_countdown < 0)
1175 av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d) at line %d\n",
1176 pixel_countdown, lines);
1177 }
1178 }
1179 }
1180
1181 y_ptr += s->frame->linesize[0];
1182 }
1183 break;
1184
1185 case FLI_DTA_BRUN:
1186 y_ptr = 0;
1187 for (lines = 0; lines < s->avctx->height; lines++) {
1188 pixel_ptr = y_ptr;
1189 /* disregard the line packets; instead, iterate through all
1190 * pixels on a row */
1191 bytestream2_skip(&g2, 1);
1192 pixel_countdown = s->avctx->width; /* Width is in pixels, not bytes */
1193
1194 while (pixel_countdown > 0) {
1195 if (bytestream2_tell(&g2) + 1 > stream_ptr_after_chunk)
1196 break;
1197 byte_run = sign_extend(bytestream2_get_byte(&g2), 8);
1198 if (byte_run > 0) {
1199 pixel = bytestream2_get_le24(&g2);
1200 CHECK_PIXEL_PTR(3 * byte_run);
1201 for (j = 0; j < byte_run; j++) {
1202 AV_WL24(pixels + pixel_ptr, pixel);
1203 pixel_ptr += 3;
1204 pixel_countdown--;
1205 if (pixel_countdown < 0)
1206 av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d)\n",
1207 pixel_countdown);
1208 }
1209 } else { /* copy pixels if byte_run < 0 */
1210 byte_run = -byte_run;
1211 if (bytestream2_tell(&g2) + 3 * byte_run > stream_ptr_after_chunk)
1212 break;
1213 CHECK_PIXEL_PTR(3 * byte_run);
1214 for (j = 0; j < byte_run; j++) {
1215 pixel = bytestream2_get_le24(&g2);
1216 AV_WL24(pixels + pixel_ptr, pixel);
1217 pixel_ptr += 3;
1218 pixel_countdown--;
1219 if (pixel_countdown < 0)
1220 av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d)\n",
1221 pixel_countdown);
1222 }
1223 }
1224 }
1225
1226 y_ptr += s->frame->linesize[0];
1227 }
1228 break;
1229
1230 case FLI_COPY:
1231 case FLI_DTA_COPY:
1232 /* copy the chunk (uncompressed frame) */
1233 if (chunk_size - 6 > (unsigned int)(FFALIGN(s->avctx->width, 2) * s->avctx->height)*3) {
1234 av_log(avctx, AV_LOG_ERROR, "In chunk FLI_COPY : source data (%d bytes) " \
1235 "bigger than image, skipping chunk\n", chunk_size - 6);
1236 bytestream2_skip(&g2, chunk_size - 6);
1237 } else {
1238 for (y_ptr = 0; check_pixel_ptr(y_ptr, 3*s->avctx->width, pixel_limit, direction) == 0;
1239 y_ptr += s->frame->linesize[0]) {
1240
1241 bytestream2_get_buffer(&g2, pixels + y_ptr, 3*s->avctx->width);
1242 if (s->avctx->width & 1)
1243 bytestream2_skip(&g2, 3);
1244 }
1245 }
1246 break;
1247
1248 case FLI_MINI:
1249 /* some sort of a thumbnail? disregard this chunk... */
1250 bytestream2_skip(&g2, chunk_size - 6);
1251 break;
1252
1253 default:
1254 av_log(avctx, AV_LOG_ERROR, "Unrecognized chunk type: %d\n", chunk_type);
1255 break;
1256 }
1257
1258 if (stream_ptr_after_chunk - bytestream2_tell(&g2) >= 0) {
1259 bytestream2_skip(&g2, stream_ptr_after_chunk - bytestream2_tell(&g2));
1260 } else {
1261 av_log(avctx, AV_LOG_ERROR, "Chunk overread\n");
1262 break;
1263 }
1264
1265 frame_size -= chunk_size;
1266 num_chunks--;
1267 }
1268
1269 /* by the end of the chunk, the stream ptr should equal the frame
1270 * size (minus 1, possibly); if it doesn't, issue a warning */
1271 if ((bytestream2_get_bytes_left(&g2) != 0) && (bytestream2_get_bytes_left(&g2) != 1))
1272 av_log(avctx, AV_LOG_ERROR, "Processed FLI chunk where chunk size = %d " \
1273 "and final chunk ptr = %d\n", buf_size, bytestream2_tell(&g2));
1274
1275 if ((ret = av_frame_ref(rframe, s->frame)) < 0)
1276 return ret;
1277
1278 *got_frame = 1;
1279
1280 return buf_size;
1281 }
1282
1283 510 static int flic_decode_frame(AVCodecContext *avctx, AVFrame *frame,
1284 int *got_frame, AVPacket *avpkt)
1285 {
1286 510 const uint8_t *buf = avpkt->data;
1287 510 int buf_size = avpkt->size;
1288
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 510 times.
510 if (avctx->pix_fmt == AV_PIX_FMT_MONOBLACK) {
1289 return flic_decode_frame_1BPP(avctx, frame, got_frame,
1290 buf, buf_size);
1291
1/2
✓ Branch 0 taken 510 times.
✗ Branch 1 not taken.
510 } else if (avctx->pix_fmt == AV_PIX_FMT_PAL8) {
1292 510 return flic_decode_frame_8BPP(avctx, frame, got_frame,
1293 buf, buf_size);
1294 } else if ((avctx->pix_fmt == AV_PIX_FMT_RGB555) ||
1295 (avctx->pix_fmt == AV_PIX_FMT_RGB565)) {
1296 return flic_decode_frame_15_16BPP(avctx, frame, got_frame,
1297 buf, buf_size);
1298 } else if (avctx->pix_fmt == AV_PIX_FMT_BGR24) {
1299 return flic_decode_frame_24BPP(avctx, frame, got_frame,
1300 buf, buf_size);
1301 }
1302
1303 /* Should not get here, ever as the pix_fmt is processed */
1304 /* in flic_decode_init and the above if should deal with */
1305 /* the finite set of possibilities allowable by here. */
1306 /* But in case we do, just error out. */
1307 av_log(avctx, AV_LOG_ERROR, "Unknown FLC format, my science cannot explain how this happened.\n");
1308 return AVERROR_BUG;
1309 }
1310
1311
1312 8 static av_cold int flic_decode_end(AVCodecContext *avctx)
1313 {
1314 8 FlicDecodeContext *s = avctx->priv_data;
1315
1316 8 av_frame_free(&s->frame);
1317
1318 8 return 0;
1319 }
1320
1321 const FFCodec ff_flic_decoder = {
1322 .p.name = "flic",
1323 CODEC_LONG_NAME("Autodesk Animator Flic video"),
1324 .p.type = AVMEDIA_TYPE_VIDEO,
1325 .p.id = AV_CODEC_ID_FLIC,
1326 .priv_data_size = sizeof(FlicDecodeContext),
1327 .init = flic_decode_init,
1328 .close = flic_decode_end,
1329 FF_CODEC_DECODE_CB(flic_decode_frame),
1330 .p.capabilities = AV_CODEC_CAP_DR1,
1331 };
1332