FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/flicvideo.c
Date: 2025-04-25 22:50:00
Exec Total Coverage
Lines: 190 725 26.2%
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 42 s->new_palette = 0;
686 }
687
688
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 510 times.
510 if ((ret = av_frame_ref(rframe, s->frame)) < 0)
689 return ret;
690
691 510 *got_frame = 1;
692
693 510 return buf_size;
694 }
695
696 static int flic_decode_frame_15_16BPP(AVCodecContext *avctx,
697 AVFrame *rframe, int *got_frame,
698 const uint8_t *buf, int buf_size)
699 {
700 /* Note, the only difference between the 15Bpp and 16Bpp */
701 /* Format is the pixel format, the packets are processed the same. */
702 FlicDecodeContext *s = avctx->priv_data;
703
704 GetByteContext g2;
705 ptrdiff_t pixel_ptr;
706 unsigned char palette_idx1;
707
708 unsigned int frame_size;
709 int num_chunks;
710
711 unsigned int chunk_size;
712 int chunk_type;
713
714 int i, j, ret, direction;
715
716 int lines;
717 int compressed_lines;
718 int line_packets;
719 ptrdiff_t y_ptr;
720 int byte_run;
721 int pixel_skip;
722 int pixel_countdown;
723 unsigned char *pixels;
724 int pixel;
725 ptrdiff_t pixel_limit;
726
727 bytestream2_init(&g2, buf, buf_size);
728
729 if ((ret = ff_reget_buffer(avctx, s->frame, 0)) < 0)
730 return ret;
731
732 direction = s->frame->linesize[0] > 0;
733 pixels = s->frame->data[0];
734 pixel_limit = s->avctx->height * s->frame->linesize[0];
735
736 frame_size = bytestream2_get_le32(&g2);
737 bytestream2_skip(&g2, 2); /* skip the magic number */
738 num_chunks = bytestream2_get_le16(&g2);
739 bytestream2_skip(&g2, 8); /* skip padding */
740 if (frame_size > buf_size)
741 frame_size = buf_size;
742
743 if (frame_size < 16)
744 return AVERROR_INVALIDDATA;
745 frame_size -= 16;
746
747 /* iterate through the chunks */
748 while ((frame_size > 0) && (num_chunks > 0) &&
749 bytestream2_get_bytes_left(&g2) >= 4) {
750 int stream_ptr_after_chunk;
751 chunk_size = bytestream2_get_le32(&g2);
752 if (chunk_size > frame_size) {
753 av_log(avctx, AV_LOG_WARNING,
754 "Invalid chunk_size = %u > frame_size = %u\n", chunk_size, frame_size);
755 chunk_size = frame_size;
756 }
757 stream_ptr_after_chunk = bytestream2_tell(&g2) - 4 + chunk_size;
758
759 chunk_type = bytestream2_get_le16(&g2);
760
761
762 switch (chunk_type) {
763 case FLI_256_COLOR:
764 case FLI_COLOR:
765 /* For some reason, it seems that non-palettized flics do
766 * include one of these chunks in their first frame.
767 * Why I do not know, it seems rather extraneous. */
768 ff_dlog(avctx,
769 "Unexpected Palette chunk %d in non-palettized FLC\n",
770 chunk_type);
771 bytestream2_skip(&g2, chunk_size - 6);
772 break;
773
774 case FLI_DELTA:
775 case FLI_DTA_LC:
776 y_ptr = 0;
777 compressed_lines = bytestream2_get_le16(&g2);
778 while (compressed_lines > 0) {
779 if (bytestream2_tell(&g2) + 2 > stream_ptr_after_chunk)
780 break;
781 CHECK_Y_PTR()
782 line_packets = sign_extend(bytestream2_get_le16(&g2), 16);
783 if (line_packets < 0) {
784 line_packets = -line_packets;
785 if (line_packets > s->avctx->height)
786 return AVERROR_INVALIDDATA;
787 y_ptr += line_packets * s->frame->linesize[0];
788 } else {
789 compressed_lines--;
790 pixel_ptr = y_ptr;
791 CHECK_PIXEL_PTR(0);
792 pixel_countdown = s->avctx->width;
793 for (i = 0; i < line_packets; i++) {
794 /* account for the skip bytes */
795 if (bytestream2_tell(&g2) + 2 > stream_ptr_after_chunk)
796 break;
797 pixel_skip = bytestream2_get_byte(&g2);
798 pixel_ptr += (pixel_skip*2); /* Pixel is 2 bytes wide */
799 pixel_countdown -= pixel_skip;
800 byte_run = sign_extend(bytestream2_get_byte(&g2), 8);
801 if (byte_run < 0) {
802 byte_run = -byte_run;
803 pixel = bytestream2_get_le16(&g2);
804 CHECK_PIXEL_PTR(2 * byte_run);
805 for (j = 0; j < byte_run; j++, pixel_countdown -= 2) {
806 *((signed short*)(&pixels[pixel_ptr])) = pixel;
807 pixel_ptr += 2;
808 }
809 } else {
810 if (bytestream2_tell(&g2) + 2*byte_run > stream_ptr_after_chunk)
811 break;
812 CHECK_PIXEL_PTR(2 * byte_run);
813 for (j = 0; j < byte_run; j++, pixel_countdown--) {
814 *((signed short*)(&pixels[pixel_ptr])) = bytestream2_get_le16(&g2);
815 pixel_ptr += 2;
816 }
817 }
818 }
819
820 y_ptr += s->frame->linesize[0];
821 }
822 }
823 break;
824
825 case FLI_LC:
826 av_log(avctx, AV_LOG_ERROR, "Unexpected FLI_LC chunk in non-palettized FLC\n");
827 bytestream2_skip(&g2, chunk_size - 6);
828 break;
829
830 case FLI_BLACK:
831 /* set the whole frame to 0x0000 which is black in both 15Bpp and 16Bpp modes. */
832 for (int y = 0; y < s->avctx->height; y++)
833 memset(pixels + y * s->frame->linesize[0], 0, s->avctx->width * 2);
834 break;
835
836 case FLI_BRUN:
837 y_ptr = 0;
838 for (lines = 0; lines < s->avctx->height; lines++) {
839 pixel_ptr = y_ptr;
840 /* disregard the line packets; instead, iterate through all
841 * pixels on a row */
842 bytestream2_skip(&g2, 1);
843 pixel_countdown = (s->avctx->width * 2);
844
845 while (pixel_countdown > 0) {
846 if (bytestream2_tell(&g2) + 1 > stream_ptr_after_chunk)
847 break;
848 byte_run = sign_extend(bytestream2_get_byte(&g2), 8);
849 if (byte_run > 0) {
850 palette_idx1 = bytestream2_get_byte(&g2);
851 CHECK_PIXEL_PTR(byte_run);
852 for (j = 0; j < byte_run; j++) {
853 pixels[pixel_ptr++] = palette_idx1;
854 pixel_countdown--;
855 if (pixel_countdown < 0)
856 av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d) (linea%d)\n",
857 pixel_countdown, lines);
858 }
859 } else { /* copy bytes if byte_run < 0 */
860 byte_run = -byte_run;
861 if (bytestream2_tell(&g2) + byte_run > stream_ptr_after_chunk)
862 break;
863 CHECK_PIXEL_PTR(byte_run);
864 for (j = 0; j < byte_run; j++) {
865 palette_idx1 = bytestream2_get_byte(&g2);
866 pixels[pixel_ptr++] = palette_idx1;
867 pixel_countdown--;
868 if (pixel_countdown < 0)
869 av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d) at line %d\n",
870 pixel_countdown, lines);
871 }
872 }
873 }
874
875 /* Now FLX is strange, in that it is "byte" as opposed to "pixel" run length compressed.
876 * This does not give us any good opportunity to perform word endian conversion
877 * during decompression. So if it is required (i.e., this is not a LE target, we do
878 * a second pass over the line here, swapping the bytes.
879 */
880 #if HAVE_BIGENDIAN
881 pixel_ptr = y_ptr;
882 pixel_countdown = s->avctx->width;
883 while (pixel_countdown > 0) {
884 *((signed short*)(&pixels[pixel_ptr])) = AV_RL16(&buf[pixel_ptr]);
885 pixel_ptr += 2;
886 }
887 #endif
888 y_ptr += s->frame->linesize[0];
889 }
890 break;
891
892 case FLI_DTA_BRUN:
893 y_ptr = 0;
894 for (lines = 0; lines < s->avctx->height; lines++) {
895 pixel_ptr = y_ptr;
896 /* disregard the line packets; instead, iterate through all
897 * pixels on a row */
898 bytestream2_skip(&g2, 1);
899 pixel_countdown = s->avctx->width; /* Width is in pixels, not bytes */
900
901 while (pixel_countdown > 0) {
902 if (bytestream2_tell(&g2) + 1 > stream_ptr_after_chunk)
903 break;
904 byte_run = sign_extend(bytestream2_get_byte(&g2), 8);
905 if (byte_run > 0) {
906 pixel = bytestream2_get_le16(&g2);
907 CHECK_PIXEL_PTR(2 * byte_run);
908 for (j = 0; j < byte_run; j++) {
909 *((signed short*)(&pixels[pixel_ptr])) = pixel;
910 pixel_ptr += 2;
911 pixel_countdown--;
912 if (pixel_countdown < 0)
913 av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d)\n",
914 pixel_countdown);
915 }
916 } else { /* copy pixels if byte_run < 0 */
917 byte_run = -byte_run;
918 if (bytestream2_tell(&g2) + 2 * byte_run > stream_ptr_after_chunk)
919 break;
920 CHECK_PIXEL_PTR(2 * byte_run);
921 for (j = 0; j < byte_run; j++) {
922 *((signed short*)(&pixels[pixel_ptr])) = bytestream2_get_le16(&g2);
923 pixel_ptr += 2;
924 pixel_countdown--;
925 if (pixel_countdown < 0)
926 av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d)\n",
927 pixel_countdown);
928 }
929 }
930 }
931
932 y_ptr += s->frame->linesize[0];
933 }
934 break;
935
936 case FLI_COPY:
937 case FLI_DTA_COPY:
938 /* copy the chunk (uncompressed frame) */
939 if (chunk_size - 6 > (unsigned int)(FFALIGN(s->avctx->width, 2) * s->avctx->height)*2) {
940 av_log(avctx, AV_LOG_ERROR, "In chunk FLI_COPY : source data (%d bytes) " \
941 "bigger than image, skipping chunk\n", chunk_size - 6);
942 bytestream2_skip(&g2, chunk_size - 6);
943 } else {
944
945 if (bytestream2_get_bytes_left(&g2) < 2 * s->avctx->width * s->avctx->height )
946 return AVERROR_INVALIDDATA;
947 for (y_ptr = 0; check_pixel_ptr(y_ptr, 2*s->avctx->width, pixel_limit, direction) == 0;
948 y_ptr += s->frame->linesize[0]) {
949
950 pixel_countdown = s->avctx->width;
951 pixel_ptr = 0;
952 while (pixel_countdown > 0) {
953 *((signed short*)(&pixels[y_ptr + pixel_ptr])) = bytestream2_get_le16(&g2);
954 pixel_ptr += 2;
955 pixel_countdown--;
956 }
957 if (s->avctx->width & 1)
958 bytestream2_skip(&g2, 2);
959 }
960 }
961 break;
962
963 case FLI_MINI:
964 /* some sort of a thumbnail? disregard this chunk... */
965 bytestream2_skip(&g2, chunk_size - 6);
966 break;
967
968 default:
969 av_log(avctx, AV_LOG_ERROR, "Unrecognized chunk type: %d\n", chunk_type);
970 break;
971 }
972
973 if (stream_ptr_after_chunk - bytestream2_tell(&g2) >= 0) {
974 bytestream2_skip(&g2, stream_ptr_after_chunk - bytestream2_tell(&g2));
975 } else {
976 av_log(avctx, AV_LOG_ERROR, "Chunk overread\n");
977 break;
978 }
979
980 frame_size -= chunk_size;
981 num_chunks--;
982 }
983
984 /* by the end of the chunk, the stream ptr should equal the frame
985 * size (minus 1, possibly); if it doesn't, issue a warning */
986 if ((bytestream2_get_bytes_left(&g2) != 0) && (bytestream2_get_bytes_left(&g2) != 1))
987 av_log(avctx, AV_LOG_ERROR, "Processed FLI chunk where chunk size = %d " \
988 "and final chunk ptr = %d\n", buf_size, bytestream2_tell(&g2));
989
990 if ((ret = av_frame_ref(rframe, s->frame)) < 0)
991 return ret;
992
993 *got_frame = 1;
994
995 return buf_size;
996 }
997
998 static int flic_decode_frame_24BPP(AVCodecContext *avctx,
999 AVFrame *rframe, int *got_frame,
1000 const uint8_t *buf, int buf_size)
1001 {
1002 FlicDecodeContext *s = avctx->priv_data;
1003
1004 GetByteContext g2;
1005 ptrdiff_t pixel_ptr;
1006 unsigned char palette_idx1;
1007
1008 unsigned int frame_size;
1009 int num_chunks;
1010
1011 unsigned int chunk_size;
1012 int chunk_type;
1013
1014 int i, j, ret, direction;
1015
1016 int lines;
1017 int compressed_lines;
1018 int line_packets;
1019 ptrdiff_t y_ptr;
1020 int byte_run;
1021 int pixel_skip;
1022 int pixel_countdown;
1023 unsigned char *pixels;
1024 int pixel;
1025 ptrdiff_t pixel_limit;
1026
1027 bytestream2_init(&g2, buf, buf_size);
1028
1029 if ((ret = ff_reget_buffer(avctx, s->frame, 0)) < 0)
1030 return ret;
1031
1032 direction = s->frame->linesize[0] > 0;
1033 pixels = s->frame->data[0];
1034 pixel_limit = s->avctx->height * s->frame->linesize[0];
1035
1036 frame_size = bytestream2_get_le32(&g2);
1037 bytestream2_skip(&g2, 2); /* skip the magic number */
1038 num_chunks = bytestream2_get_le16(&g2);
1039 bytestream2_skip(&g2, 8); /* skip padding */
1040 if (frame_size > buf_size)
1041 frame_size = buf_size;
1042
1043 if (frame_size < 16)
1044 return AVERROR_INVALIDDATA;
1045 frame_size -= 16;
1046
1047 /* iterate through the chunks */
1048 while ((frame_size > 0) && (num_chunks > 0) &&
1049 bytestream2_get_bytes_left(&g2) >= 4) {
1050 int stream_ptr_after_chunk;
1051 chunk_size = bytestream2_get_le32(&g2);
1052 if (chunk_size > frame_size) {
1053 av_log(avctx, AV_LOG_WARNING,
1054 "Invalid chunk_size = %u > frame_size = %u\n", chunk_size, frame_size);
1055 chunk_size = frame_size;
1056 }
1057 stream_ptr_after_chunk = bytestream2_tell(&g2) - 4 + chunk_size;
1058
1059 chunk_type = bytestream2_get_le16(&g2);
1060
1061
1062 switch (chunk_type) {
1063 case FLI_256_COLOR:
1064 case FLI_COLOR:
1065 /* For some reason, it seems that non-palettized flics do
1066 * include one of these chunks in their first frame.
1067 * Why I do not know, it seems rather extraneous. */
1068 ff_dlog(avctx,
1069 "Unexpected Palette chunk %d in non-palettized FLC\n",
1070 chunk_type);
1071 bytestream2_skip(&g2, chunk_size - 6);
1072 break;
1073
1074 case FLI_DELTA:
1075 case FLI_DTA_LC:
1076 y_ptr = 0;
1077 compressed_lines = bytestream2_get_le16(&g2);
1078 while (compressed_lines > 0) {
1079 if (bytestream2_tell(&g2) + 2 > stream_ptr_after_chunk)
1080 break;
1081 CHECK_Y_PTR()
1082 line_packets = sign_extend(bytestream2_get_le16(&g2), 16);
1083 if (line_packets < 0) {
1084 line_packets = -line_packets;
1085 if (line_packets > s->avctx->height)
1086 return AVERROR_INVALIDDATA;
1087 y_ptr += line_packets * s->frame->linesize[0];
1088 } else {
1089 compressed_lines--;
1090 pixel_ptr = y_ptr;
1091 CHECK_PIXEL_PTR(0);
1092 pixel_countdown = s->avctx->width;
1093 for (i = 0; i < line_packets; i++) {
1094 /* account for the skip bytes */
1095 if (bytestream2_tell(&g2) + 2 > stream_ptr_after_chunk)
1096 break;
1097 pixel_skip = bytestream2_get_byte(&g2);
1098 pixel_ptr += (pixel_skip*3); /* Pixel is 3 bytes wide */
1099 pixel_countdown -= pixel_skip;
1100 byte_run = sign_extend(bytestream2_get_byte(&g2), 8);
1101 if (byte_run < 0) {
1102 byte_run = -byte_run;
1103 pixel = bytestream2_get_le24(&g2);
1104 CHECK_PIXEL_PTR(3 * byte_run);
1105 for (j = 0; j < byte_run; j++, pixel_countdown -= 1) {
1106 AV_WL24(&pixels[pixel_ptr], pixel);
1107 pixel_ptr += 3;
1108 }
1109 } else {
1110 if (bytestream2_tell(&g2) + 2*byte_run > stream_ptr_after_chunk)
1111 break;
1112 CHECK_PIXEL_PTR(3 * byte_run);
1113 for (j = 0; j < byte_run; j++, pixel_countdown--) {
1114 pixel = bytestream2_get_le24(&g2);
1115 AV_WL24(&pixels[pixel_ptr], pixel);
1116 pixel_ptr += 3;
1117 }
1118 }
1119 }
1120
1121 y_ptr += s->frame->linesize[0];
1122 }
1123 }
1124 break;
1125
1126 case FLI_LC:
1127 av_log(avctx, AV_LOG_ERROR, "Unexpected FLI_LC chunk in non-palettized FLC\n");
1128 bytestream2_skip(&g2, chunk_size - 6);
1129 break;
1130
1131 case FLI_BLACK:
1132 /* set the whole frame to 0x00 which is black for 24 bit mode. */
1133 for (int y = 0; y < s->avctx->height; y++)
1134 memset(pixels + y * s->frame->linesize[0], 0, s->avctx->width * 3);
1135 break;
1136
1137 case FLI_BRUN:
1138 y_ptr = 0;
1139 for (lines = 0; lines < s->avctx->height; lines++) {
1140 pixel_ptr = y_ptr;
1141 /* disregard the line packets; instead, iterate through all
1142 * pixels on a row */
1143 bytestream2_skip(&g2, 1);
1144 pixel_countdown = (s->avctx->width * 3);
1145
1146 while (pixel_countdown > 0) {
1147 if (bytestream2_tell(&g2) + 1 > stream_ptr_after_chunk)
1148 break;
1149 byte_run = sign_extend(bytestream2_get_byte(&g2), 8);
1150 if (byte_run > 0) {
1151 palette_idx1 = bytestream2_get_byte(&g2);
1152 CHECK_PIXEL_PTR(byte_run);
1153 for (j = 0; j < byte_run; j++) {
1154 pixels[pixel_ptr++] = palette_idx1;
1155 pixel_countdown--;
1156 if (pixel_countdown < 0)
1157 av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d) (linea%d)\n",
1158 pixel_countdown, lines);
1159 }
1160 } else { /* copy bytes if byte_run < 0 */
1161 byte_run = -byte_run;
1162 if (bytestream2_tell(&g2) + byte_run > stream_ptr_after_chunk)
1163 break;
1164 CHECK_PIXEL_PTR(byte_run);
1165 for (j = 0; j < byte_run; j++) {
1166 palette_idx1 = bytestream2_get_byte(&g2);
1167 pixels[pixel_ptr++] = palette_idx1;
1168 pixel_countdown--;
1169 if (pixel_countdown < 0)
1170 av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d) at line %d\n",
1171 pixel_countdown, lines);
1172 }
1173 }
1174 }
1175
1176 y_ptr += s->frame->linesize[0];
1177 }
1178 break;
1179
1180 case FLI_DTA_BRUN:
1181 y_ptr = 0;
1182 for (lines = 0; lines < s->avctx->height; lines++) {
1183 pixel_ptr = y_ptr;
1184 /* disregard the line packets; instead, iterate through all
1185 * pixels on a row */
1186 bytestream2_skip(&g2, 1);
1187 pixel_countdown = s->avctx->width; /* Width is in pixels, not bytes */
1188
1189 while (pixel_countdown > 0) {
1190 if (bytestream2_tell(&g2) + 1 > stream_ptr_after_chunk)
1191 break;
1192 byte_run = sign_extend(bytestream2_get_byte(&g2), 8);
1193 if (byte_run > 0) {
1194 pixel = bytestream2_get_le24(&g2);
1195 CHECK_PIXEL_PTR(3 * byte_run);
1196 for (j = 0; j < byte_run; j++) {
1197 AV_WL24(pixels + pixel_ptr, pixel);
1198 pixel_ptr += 3;
1199 pixel_countdown--;
1200 if (pixel_countdown < 0)
1201 av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d)\n",
1202 pixel_countdown);
1203 }
1204 } else { /* copy pixels if byte_run < 0 */
1205 byte_run = -byte_run;
1206 if (bytestream2_tell(&g2) + 3 * byte_run > stream_ptr_after_chunk)
1207 break;
1208 CHECK_PIXEL_PTR(3 * byte_run);
1209 for (j = 0; j < byte_run; j++) {
1210 pixel = bytestream2_get_le24(&g2);
1211 AV_WL24(pixels + pixel_ptr, pixel);
1212 pixel_ptr += 3;
1213 pixel_countdown--;
1214 if (pixel_countdown < 0)
1215 av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d)\n",
1216 pixel_countdown);
1217 }
1218 }
1219 }
1220
1221 y_ptr += s->frame->linesize[0];
1222 }
1223 break;
1224
1225 case FLI_COPY:
1226 case FLI_DTA_COPY:
1227 /* copy the chunk (uncompressed frame) */
1228 if (chunk_size - 6 > (unsigned int)(FFALIGN(s->avctx->width, 2) * s->avctx->height)*3) {
1229 av_log(avctx, AV_LOG_ERROR, "In chunk FLI_COPY : source data (%d bytes) " \
1230 "bigger than image, skipping chunk\n", chunk_size - 6);
1231 bytestream2_skip(&g2, chunk_size - 6);
1232 } else {
1233 for (y_ptr = 0; check_pixel_ptr(y_ptr, 3*s->avctx->width, pixel_limit, direction) == 0;
1234 y_ptr += s->frame->linesize[0]) {
1235
1236 bytestream2_get_buffer(&g2, pixels + y_ptr, 3*s->avctx->width);
1237 if (s->avctx->width & 1)
1238 bytestream2_skip(&g2, 3);
1239 }
1240 }
1241 break;
1242
1243 case FLI_MINI:
1244 /* some sort of a thumbnail? disregard this chunk... */
1245 bytestream2_skip(&g2, chunk_size - 6);
1246 break;
1247
1248 default:
1249 av_log(avctx, AV_LOG_ERROR, "Unrecognized chunk type: %d\n", chunk_type);
1250 break;
1251 }
1252
1253 if (stream_ptr_after_chunk - bytestream2_tell(&g2) >= 0) {
1254 bytestream2_skip(&g2, stream_ptr_after_chunk - bytestream2_tell(&g2));
1255 } else {
1256 av_log(avctx, AV_LOG_ERROR, "Chunk overread\n");
1257 break;
1258 }
1259
1260 frame_size -= chunk_size;
1261 num_chunks--;
1262 }
1263
1264 /* by the end of the chunk, the stream ptr should equal the frame
1265 * size (minus 1, possibly); if it doesn't, issue a warning */
1266 if ((bytestream2_get_bytes_left(&g2) != 0) && (bytestream2_get_bytes_left(&g2) != 1))
1267 av_log(avctx, AV_LOG_ERROR, "Processed FLI chunk where chunk size = %d " \
1268 "and final chunk ptr = %d\n", buf_size, bytestream2_tell(&g2));
1269
1270 if ((ret = av_frame_ref(rframe, s->frame)) < 0)
1271 return ret;
1272
1273 *got_frame = 1;
1274
1275 return buf_size;
1276 }
1277
1278 510 static int flic_decode_frame(AVCodecContext *avctx, AVFrame *frame,
1279 int *got_frame, AVPacket *avpkt)
1280 {
1281 510 const uint8_t *buf = avpkt->data;
1282 510 int buf_size = avpkt->size;
1283
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 510 times.
510 if (avctx->pix_fmt == AV_PIX_FMT_MONOBLACK) {
1284 return flic_decode_frame_1BPP(avctx, frame, got_frame,
1285 buf, buf_size);
1286
1/2
✓ Branch 0 taken 510 times.
✗ Branch 1 not taken.
510 } else if (avctx->pix_fmt == AV_PIX_FMT_PAL8) {
1287 510 return flic_decode_frame_8BPP(avctx, frame, got_frame,
1288 buf, buf_size);
1289 } else if ((avctx->pix_fmt == AV_PIX_FMT_RGB555) ||
1290 (avctx->pix_fmt == AV_PIX_FMT_RGB565)) {
1291 return flic_decode_frame_15_16BPP(avctx, frame, got_frame,
1292 buf, buf_size);
1293 } else if (avctx->pix_fmt == AV_PIX_FMT_BGR24) {
1294 return flic_decode_frame_24BPP(avctx, frame, got_frame,
1295 buf, buf_size);
1296 }
1297
1298 /* Should not get here, ever as the pix_fmt is processed */
1299 /* in flic_decode_init and the above if should deal with */
1300 /* the finite set of possibilities allowable by here. */
1301 /* But in case we do, just error out. */
1302 av_log(avctx, AV_LOG_ERROR, "Unknown FLC format, my science cannot explain how this happened.\n");
1303 return AVERROR_BUG;
1304 }
1305
1306
1307 8 static av_cold int flic_decode_end(AVCodecContext *avctx)
1308 {
1309 8 FlicDecodeContext *s = avctx->priv_data;
1310
1311 8 av_frame_free(&s->frame);
1312
1313 8 return 0;
1314 }
1315
1316 const FFCodec ff_flic_decoder = {
1317 .p.name = "flic",
1318 CODEC_LONG_NAME("Autodesk Animator Flic video"),
1319 .p.type = AVMEDIA_TYPE_VIDEO,
1320 .p.id = AV_CODEC_ID_FLIC,
1321 .priv_data_size = sizeof(FlicDecodeContext),
1322 .init = flic_decode_init,
1323 .close = flic_decode_end,
1324 FF_CODEC_DECODE_CB(flic_decode_frame),
1325 .p.capabilities = AV_CODEC_CAP_DR1,
1326 };
1327