FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/flicvideo.c
Date: 2026-10-30 17:37:53
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 539163 static inline int check_pixel_ptr(ptrdiff_t ptr, int n,
64 ptrdiff_t limit, int direction)
65 {
66
3/6
✓ Branch 0 taken 539163 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 539163 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 539163 times.
539163 if (( direction && ptr + n > limit) ||
67 ✗ (!direction && ptr + n < limit))
68 ✗ return AVERROR_INVALIDDATA;
69 539163 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 503 static int flic_decode_frame_8BPP(AVCodecContext *avctx,
359 AVFrame *rframe, int *got_frame,
360 const uint8_t *buf, int buf_size)
361 {
362 503 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 503 bytestream2_init(&g2, buf, buf_size);
395
396
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 503 times.
503 if ((ret = ff_reget_buffer(avctx, s->frame, 0)) < 0)
397 ✗ return ret;
398
399 503 direction = s->frame->linesize[0] > 0;
400 503 pixels = s->frame->data[0];
401 503 pixel_limit = s->avctx->height * s->frame->linesize[0];
402
2/4
✓ Branch 0 taken 503 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 503 times.
503 if (buf_size < 16 || buf_size > INT_MAX - (3 * 256 + AV_INPUT_BUFFER_PADDING_SIZE))
403 ✗ return AVERROR_INVALIDDATA;
404 503 frame_size = bytestream2_get_le32(&g2);
405
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 503 times.
503 if (frame_size > buf_size)
406 ✗ frame_size = buf_size;
407 503 bytestream2_skip(&g2, 2); /* skip the magic number */
408 503 num_chunks = bytestream2_get_le16(&g2);
409 503 bytestream2_skip(&g2, 8); /* skip padding */
410
411
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 503 times.
503 if (frame_size < 16)
412 ✗ return AVERROR_INVALIDDATA;
413
414 503 frame_size -= 16;
415
416 /* iterate through the chunks */
417
4/6
✓ Branch 0 taken 526 times.
✓ Branch 1 taken 503 times.
✓ Branch 2 taken 526 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 526 times.
✗ Branch 5 not taken.
1555 while ((frame_size >= 6) && (num_chunks > 0) &&
418 526 bytestream2_get_bytes_left(&g2) >= 4) {
419 int stream_ptr_after_chunk;
420 526 chunk_size = bytestream2_get_le32(&g2);
421
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 526 times.
526 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 526 stream_ptr_after_chunk = bytestream2_tell(&g2) - 4 + chunk_size;
427
428 526 chunk_type = bytestream2_get_le16(&g2);
429
430
4/8
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 67 times.
✓ Branch 2 taken 413 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
526 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 413 case FLI_LC:
537 /* line compressed */
538 413 starting_line = bytestream2_get_le16(&g2);
539
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 413 times.
413 if (starting_line >= s->avctx->height)
540 ✗ return AVERROR_INVALIDDATA;
541 413 y_ptr = 0;
542 413 y_ptr += starting_line * s->frame->linesize[0];
543
544 413 compressed_lines = bytestream2_get_le16(&g2);
545
2/2
✓ Branch 0 taken 53577 times.
✓ Branch 1 taken 413 times.
53990 while (compressed_lines > 0) {
546 53577 pixel_ptr = y_ptr;
547
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 53577 times.
53577 CHECK_PIXEL_PTR(0);
548 53577 pixel_countdown = s->avctx->width;
549
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 53577 times.
53577 if (bytestream2_tell(&g2) + 1 > stream_ptr_after_chunk)
550 ✗ break;
551 53577 line_packets = bytestream2_get_byte(&g2);
552
2/2
✓ Branch 0 taken 48539 times.
✓ Branch 1 taken 5038 times.
53577 if (line_packets > 0) {
553
2/2
✓ Branch 0 taken 321857 times.
✓ Branch 1 taken 48539 times.
370396 for (i = 0; i < line_packets; i++) {
554 /* account for the skip bytes */
555
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 321857 times.
321857 if (bytestream2_tell(&g2) + 1 > stream_ptr_after_chunk)
556 ✗ break;
557 321857 pixel_skip = bytestream2_get_byte(&g2);
558 321857 pixel_ptr += pixel_skip;
559 321857 pixel_countdown -= pixel_skip;
560 321857 byte_run = sign_extend(bytestream2_get_byte(&g2),8);
561
2/2
✓ Branch 0 taken 236371 times.
✓ Branch 1 taken 85486 times.
321857 if (byte_run > 0) {
562
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 236371 times.
236371 CHECK_PIXEL_PTR(byte_run);
563
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 236371 times.
236371 if (bytestream2_tell(&g2) + byte_run > stream_ptr_after_chunk)
564 ✗ break;
565
2/2
✓ Branch 0 taken 1367845 times.
✓ Branch 1 taken 236371 times.
1604216 for (j = 0; j < byte_run; j++, pixel_countdown--) {
566 1367845 pixels[pixel_ptr++] = bytestream2_get_byte(&g2);
567 }
568
1/2
✓ Branch 0 taken 85486 times.
✗ Branch 1 not taken.
85486 } else if (byte_run < 0) {
569 85486 byte_run = -byte_run;
570 85486 palette_idx1 = bytestream2_get_byte(&g2);
571
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 85486 times.
85486 CHECK_PIXEL_PTR(byte_run);
572
2/2
✓ Branch 0 taken 542784 times.
✓ Branch 1 taken 85486 times.
628270 for (j = 0; j < byte_run; j++, pixel_countdown--) {
573 542784 pixels[pixel_ptr++] = palette_idx1;
574 }
575 }
576 }
577 }
578
579 53577 y_ptr += s->frame->linesize[0];
580 53577 compressed_lines--;
581 }
582 413 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 526 times.
✗ Branch 2 not taken.
526 if (stream_ptr_after_chunk - bytestream2_tell(&g2) >= 0) {
665 526 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 526 frame_size -= chunk_size;
672 526 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 503 times.
503 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 503 memcpy(s->frame->data[1], s->palette, AVPALETTE_SIZE);
684
2/2
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 461 times.
503 if (s->new_palette) {
685 42 s->new_palette = 0;
686 }
687
688
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 503 times.
503 if ((ret = av_frame_ref(rframe, s->frame)) < 0)
689 ✗ return ret;
690
691 503 *got_frame = 1;
692
693 503 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++ ^ HAVE_BIGENDIAN] = 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++ ^ HAVE_BIGENDIAN] = 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 ✗ y_ptr += s->frame->linesize[0];
875 }
876 ✗ break;
877
878 ✗ case FLI_DTA_BRUN:
879 ✗ y_ptr = 0;
880 ✗ for (lines = 0; lines < s->avctx->height; lines++) {
881 ✗ pixel_ptr = y_ptr;
882 /* disregard the line packets; instead, iterate through all
883 * pixels on a row */
884 ✗ bytestream2_skip(&g2, 1);
885 ✗ pixel_countdown = s->avctx->width; /* Width is in pixels, not bytes */
886
887 ✗ while (pixel_countdown > 0) {
888 ✗ if (bytestream2_tell(&g2) + 1 > stream_ptr_after_chunk)
889 ✗ break;
890 ✗ byte_run = sign_extend(bytestream2_get_byte(&g2), 8);
891 ✗ if (byte_run > 0) {
892 ✗ pixel = bytestream2_get_le16(&g2);
893 ✗ CHECK_PIXEL_PTR(2 * byte_run);
894 ✗ for (j = 0; j < byte_run; j++) {
895 ✗ *((signed short*)(&pixels[pixel_ptr])) = pixel;
896 ✗ pixel_ptr += 2;
897 ✗ pixel_countdown--;
898 ✗ if (pixel_countdown < 0)
899 ✗ av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d)\n",
900 pixel_countdown);
901 }
902 } else { /* copy pixels if byte_run < 0 */
903 ✗ byte_run = -byte_run;
904 ✗ if (bytestream2_tell(&g2) + 2 * byte_run > stream_ptr_after_chunk)
905 ✗ break;
906 ✗ CHECK_PIXEL_PTR(2 * byte_run);
907 ✗ for (j = 0; j < byte_run; j++) {
908 ✗ *((signed short*)(&pixels[pixel_ptr])) = bytestream2_get_le16(&g2);
909 ✗ pixel_ptr += 2;
910 ✗ pixel_countdown--;
911 ✗ if (pixel_countdown < 0)
912 ✗ av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d)\n",
913 pixel_countdown);
914 }
915 }
916 }
917
918 ✗ y_ptr += s->frame->linesize[0];
919 }
920 ✗ break;
921
922 ✗ case FLI_COPY:
923 case FLI_DTA_COPY:
924 /* copy the chunk (uncompressed frame) */
925 ✗ if (chunk_size - 6 > (unsigned int)(FFALIGN(s->avctx->width, 2) * s->avctx->height)*2) {
926 ✗ av_log(avctx, AV_LOG_ERROR, "In chunk FLI_COPY : source data (%d bytes) " \
927 "bigger than image, skipping chunk\n", chunk_size - 6);
928 ✗ bytestream2_skip(&g2, chunk_size - 6);
929 } else {
930
931 ✗ if (bytestream2_get_bytes_left(&g2) < 2 * s->avctx->width * s->avctx->height )
932 ✗ return AVERROR_INVALIDDATA;
933 ✗ for (y_ptr = 0; check_pixel_ptr(y_ptr, 2*s->avctx->width, pixel_limit, direction) == 0;
934 ✗ y_ptr += s->frame->linesize[0]) {
935
936 ✗ pixel_countdown = s->avctx->width;
937 ✗ pixel_ptr = 0;
938 ✗ while (pixel_countdown > 0) {
939 ✗ *((signed short*)(&pixels[y_ptr + pixel_ptr])) = bytestream2_get_le16(&g2);
940 ✗ pixel_ptr += 2;
941 ✗ pixel_countdown--;
942 }
943 ✗ if (s->avctx->width & 1)
944 ✗ bytestream2_skip(&g2, 2);
945 }
946 }
947 ✗ break;
948
949 ✗ case FLI_MINI:
950 /* some sort of a thumbnail? disregard this chunk... */
951 ✗ bytestream2_skip(&g2, chunk_size - 6);
952 ✗ break;
953
954 ✗ default:
955 ✗ av_log(avctx, AV_LOG_ERROR, "Unrecognized chunk type: %d\n", chunk_type);
956 ✗ break;
957 }
958
959 ✗ if (stream_ptr_after_chunk - bytestream2_tell(&g2) >= 0) {
960 ✗ bytestream2_skip(&g2, stream_ptr_after_chunk - bytestream2_tell(&g2));
961 } else {
962 ✗ av_log(avctx, AV_LOG_ERROR, "Chunk overread\n");
963 ✗ break;
964 }
965
966 ✗ frame_size -= chunk_size;
967 ✗ num_chunks--;
968 }
969
970 /* by the end of the chunk, the stream ptr should equal the frame
971 * size (minus 1, possibly); if it doesn't, issue a warning */
972 ✗ if ((bytestream2_get_bytes_left(&g2) != 0) && (bytestream2_get_bytes_left(&g2) != 1))
973 ✗ av_log(avctx, AV_LOG_ERROR, "Processed FLI chunk where chunk size = %d " \
974 "and final chunk ptr = %d\n", buf_size, bytestream2_tell(&g2));
975
976 ✗ if ((ret = av_frame_ref(rframe, s->frame)) < 0)
977 ✗ return ret;
978
979 ✗ *got_frame = 1;
980
981 ✗ return buf_size;
982 }
983
984 ✗ static int flic_decode_frame_24BPP(AVCodecContext *avctx,
985 AVFrame *rframe, int *got_frame,
986 const uint8_t *buf, int buf_size)
987 {
988 ✗ FlicDecodeContext *s = avctx->priv_data;
989
990 GetByteContext g2;
991 ptrdiff_t pixel_ptr;
992 unsigned char palette_idx1;
993
994 unsigned int frame_size;
995 int num_chunks;
996
997 unsigned int chunk_size;
998 int chunk_type;
999
1000 int i, j, ret, direction;
1001
1002 int lines;
1003 int compressed_lines;
1004 int line_packets;
1005 ptrdiff_t y_ptr;
1006 int byte_run;
1007 int pixel_skip;
1008 int pixel_countdown;
1009 unsigned char *pixels;
1010 int pixel;
1011 ptrdiff_t pixel_limit;
1012
1013 ✗ bytestream2_init(&g2, buf, buf_size);
1014
1015 ✗ if ((ret = ff_reget_buffer(avctx, s->frame, 0)) < 0)
1016 ✗ return ret;
1017
1018 ✗ direction = s->frame->linesize[0] > 0;
1019 ✗ pixels = s->frame->data[0];
1020 ✗ pixel_limit = s->avctx->height * s->frame->linesize[0];
1021
1022 ✗ frame_size = bytestream2_get_le32(&g2);
1023 ✗ bytestream2_skip(&g2, 2); /* skip the magic number */
1024 ✗ num_chunks = bytestream2_get_le16(&g2);
1025 ✗ bytestream2_skip(&g2, 8); /* skip padding */
1026 ✗ if (frame_size > buf_size)
1027 ✗ frame_size = buf_size;
1028
1029 ✗ if (frame_size < 16)
1030 ✗ return AVERROR_INVALIDDATA;
1031 ✗ frame_size -= 16;
1032
1033 /* iterate through the chunks */
1034 ✗ while ((frame_size > 0) && (num_chunks > 0) &&
1035 ✗ bytestream2_get_bytes_left(&g2) >= 4) {
1036 int stream_ptr_after_chunk;
1037 ✗ chunk_size = bytestream2_get_le32(&g2);
1038 ✗ if (chunk_size > frame_size) {
1039 ✗ av_log(avctx, AV_LOG_WARNING,
1040 "Invalid chunk_size = %u > frame_size = %u\n", chunk_size, frame_size);
1041 ✗ chunk_size = frame_size;
1042 }
1043 ✗ stream_ptr_after_chunk = bytestream2_tell(&g2) - 4 + chunk_size;
1044
1045 ✗ chunk_type = bytestream2_get_le16(&g2);
1046
1047
1048 ✗ switch (chunk_type) {
1049 ✗ case FLI_256_COLOR:
1050 case FLI_COLOR:
1051 /* For some reason, it seems that non-palettized flics do
1052 * include one of these chunks in their first frame.
1053 * Why I do not know, it seems rather extraneous. */
1054 ff_dlog(avctx,
1055 "Unexpected Palette chunk %d in non-palettized FLC\n",
1056 chunk_type);
1057 ✗ bytestream2_skip(&g2, chunk_size - 6);
1058 ✗ break;
1059
1060 ✗ case FLI_DELTA:
1061 case FLI_DTA_LC:
1062 ✗ y_ptr = 0;
1063 ✗ compressed_lines = bytestream2_get_le16(&g2);
1064 ✗ while (compressed_lines > 0) {
1065 ✗ if (bytestream2_tell(&g2) + 2 > stream_ptr_after_chunk)
1066 ✗ break;
1067 ✗ CHECK_Y_PTR()
1068 ✗ line_packets = sign_extend(bytestream2_get_le16(&g2), 16);
1069 ✗ if (line_packets < 0) {
1070 ✗ line_packets = -line_packets;
1071 ✗ if (line_packets > s->avctx->height)
1072 ✗ return AVERROR_INVALIDDATA;
1073 ✗ y_ptr += line_packets * s->frame->linesize[0];
1074 } else {
1075 ✗ compressed_lines--;
1076 ✗ pixel_ptr = y_ptr;
1077 ✗ CHECK_PIXEL_PTR(0);
1078 ✗ pixel_countdown = s->avctx->width;
1079 ✗ for (i = 0; i < line_packets; i++) {
1080 /* account for the skip bytes */
1081 ✗ if (bytestream2_tell(&g2) + 2 > stream_ptr_after_chunk)
1082 ✗ break;
1083 ✗ pixel_skip = bytestream2_get_byte(&g2);
1084 ✗ pixel_ptr += (pixel_skip*3); /* Pixel is 3 bytes wide */
1085 ✗ pixel_countdown -= pixel_skip;
1086 ✗ byte_run = sign_extend(bytestream2_get_byte(&g2), 8);
1087 ✗ if (byte_run < 0) {
1088 ✗ byte_run = -byte_run;
1089 ✗ pixel = bytestream2_get_le24(&g2);
1090 ✗ CHECK_PIXEL_PTR(3 * byte_run);
1091 ✗ for (j = 0; j < byte_run; j++, pixel_countdown -= 1) {
1092 ✗ AV_WL24(&pixels[pixel_ptr], pixel);
1093 ✗ pixel_ptr += 3;
1094 }
1095 } else {
1096 ✗ if (bytestream2_tell(&g2) + 2*byte_run > stream_ptr_after_chunk)
1097 ✗ break;
1098 ✗ CHECK_PIXEL_PTR(3 * byte_run);
1099 ✗ for (j = 0; j < byte_run; j++, pixel_countdown--) {
1100 ✗ pixel = bytestream2_get_le24(&g2);
1101 ✗ AV_WL24(&pixels[pixel_ptr], pixel);
1102 ✗ pixel_ptr += 3;
1103 }
1104 }
1105 }
1106
1107 ✗ y_ptr += s->frame->linesize[0];
1108 }
1109 }
1110 ✗ break;
1111
1112 ✗ case FLI_LC:
1113 ✗ av_log(avctx, AV_LOG_ERROR, "Unexpected FLI_LC chunk in non-palettized FLC\n");
1114 ✗ bytestream2_skip(&g2, chunk_size - 6);
1115 ✗ break;
1116
1117 ✗ case FLI_BLACK:
1118 /* set the whole frame to 0x00 which is black for 24 bit mode. */
1119 ✗ for (int y = 0; y < s->avctx->height; y++)
1120 ✗ memset(pixels + y * s->frame->linesize[0], 0, s->avctx->width * 3);
1121 ✗ break;
1122
1123 ✗ case FLI_BRUN:
1124 ✗ y_ptr = 0;
1125 ✗ for (lines = 0; lines < s->avctx->height; lines++) {
1126 ✗ pixel_ptr = y_ptr;
1127 /* disregard the line packets; instead, iterate through all
1128 * pixels on a row */
1129 ✗ bytestream2_skip(&g2, 1);
1130 ✗ pixel_countdown = (s->avctx->width * 3);
1131
1132 ✗ while (pixel_countdown > 0) {
1133 ✗ if (bytestream2_tell(&g2) + 1 > stream_ptr_after_chunk)
1134 ✗ break;
1135 ✗ byte_run = sign_extend(bytestream2_get_byte(&g2), 8);
1136 ✗ if (byte_run > 0) {
1137 ✗ palette_idx1 = bytestream2_get_byte(&g2);
1138 ✗ CHECK_PIXEL_PTR(byte_run);
1139 ✗ for (j = 0; j < byte_run; j++) {
1140 ✗ pixels[pixel_ptr++] = palette_idx1;
1141 ✗ pixel_countdown--;
1142 ✗ if (pixel_countdown < 0)
1143 ✗ av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d) (linea%d)\n",
1144 pixel_countdown, lines);
1145 }
1146 } else { /* copy bytes if byte_run < 0 */
1147 ✗ byte_run = -byte_run;
1148 ✗ if (bytestream2_tell(&g2) + byte_run > stream_ptr_after_chunk)
1149 ✗ break;
1150 ✗ CHECK_PIXEL_PTR(byte_run);
1151 ✗ for (j = 0; j < byte_run; j++) {
1152 ✗ palette_idx1 = bytestream2_get_byte(&g2);
1153 ✗ pixels[pixel_ptr++] = palette_idx1;
1154 ✗ pixel_countdown--;
1155 ✗ if (pixel_countdown < 0)
1156 ✗ av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d) at line %d\n",
1157 pixel_countdown, lines);
1158 }
1159 }
1160 }
1161
1162 ✗ y_ptr += s->frame->linesize[0];
1163 }
1164 ✗ break;
1165
1166 ✗ case FLI_DTA_BRUN:
1167 ✗ y_ptr = 0;
1168 ✗ for (lines = 0; lines < s->avctx->height; lines++) {
1169 ✗ pixel_ptr = y_ptr;
1170 /* disregard the line packets; instead, iterate through all
1171 * pixels on a row */
1172 ✗ bytestream2_skip(&g2, 1);
1173 ✗ pixel_countdown = s->avctx->width; /* Width is in pixels, not bytes */
1174
1175 ✗ while (pixel_countdown > 0) {
1176 ✗ if (bytestream2_tell(&g2) + 1 > stream_ptr_after_chunk)
1177 ✗ break;
1178 ✗ byte_run = sign_extend(bytestream2_get_byte(&g2), 8);
1179 ✗ if (byte_run > 0) {
1180 ✗ pixel = bytestream2_get_le24(&g2);
1181 ✗ CHECK_PIXEL_PTR(3 * byte_run);
1182 ✗ for (j = 0; j < byte_run; j++) {
1183 ✗ AV_WL24(pixels + pixel_ptr, pixel);
1184 ✗ pixel_ptr += 3;
1185 ✗ pixel_countdown--;
1186 ✗ if (pixel_countdown < 0)
1187 ✗ av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d)\n",
1188 pixel_countdown);
1189 }
1190 } else { /* copy pixels if byte_run < 0 */
1191 ✗ byte_run = -byte_run;
1192 ✗ if (bytestream2_tell(&g2) + 3 * byte_run > stream_ptr_after_chunk)
1193 ✗ break;
1194 ✗ CHECK_PIXEL_PTR(3 * byte_run);
1195 ✗ for (j = 0; j < byte_run; j++) {
1196 ✗ pixel = bytestream2_get_le24(&g2);
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 }
1205 }
1206
1207 ✗ y_ptr += s->frame->linesize[0];
1208 }
1209 ✗ break;
1210
1211 ✗ case FLI_COPY:
1212 case FLI_DTA_COPY:
1213 /* copy the chunk (uncompressed frame) */
1214 ✗ if (chunk_size - 6 > (unsigned int)(FFALIGN(s->avctx->width, 2) * s->avctx->height)*3) {
1215 ✗ av_log(avctx, AV_LOG_ERROR, "In chunk FLI_COPY : source data (%d bytes) " \
1216 "bigger than image, skipping chunk\n", chunk_size - 6);
1217 ✗ bytestream2_skip(&g2, chunk_size - 6);
1218 } else {
1219 ✗ for (y_ptr = 0; check_pixel_ptr(y_ptr, 3*s->avctx->width, pixel_limit, direction) == 0;
1220 ✗ y_ptr += s->frame->linesize[0]) {
1221
1222 ✗ bytestream2_get_buffer(&g2, pixels + y_ptr, 3*s->avctx->width);
1223 ✗ if (s->avctx->width & 1)
1224 ✗ bytestream2_skip(&g2, 3);
1225 }
1226 }
1227 ✗ break;
1228
1229 ✗ case FLI_MINI:
1230 /* some sort of a thumbnail? disregard this chunk... */
1231 ✗ bytestream2_skip(&g2, chunk_size - 6);
1232 ✗ break;
1233
1234 ✗ default:
1235 ✗ av_log(avctx, AV_LOG_ERROR, "Unrecognized chunk type: %d\n", chunk_type);
1236 ✗ break;
1237 }
1238
1239 ✗ if (stream_ptr_after_chunk - bytestream2_tell(&g2) >= 0) {
1240 ✗ bytestream2_skip(&g2, stream_ptr_after_chunk - bytestream2_tell(&g2));
1241 } else {
1242 ✗ av_log(avctx, AV_LOG_ERROR, "Chunk overread\n");
1243 ✗ break;
1244 }
1245
1246 ✗ frame_size -= chunk_size;
1247 ✗ num_chunks--;
1248 }
1249
1250 /* by the end of the chunk, the stream ptr should equal the frame
1251 * size (minus 1, possibly); if it doesn't, issue a warning */
1252 ✗ if ((bytestream2_get_bytes_left(&g2) != 0) && (bytestream2_get_bytes_left(&g2) != 1))
1253 ✗ av_log(avctx, AV_LOG_ERROR, "Processed FLI chunk where chunk size = %d " \
1254 "and final chunk ptr = %d\n", buf_size, bytestream2_tell(&g2));
1255
1256 ✗ if ((ret = av_frame_ref(rframe, s->frame)) < 0)
1257 ✗ return ret;
1258
1259 ✗ *got_frame = 1;
1260
1261 ✗ return buf_size;
1262 }
1263
1264 503 static int flic_decode_frame(AVCodecContext *avctx, AVFrame *frame,
1265 int *got_frame, AVPacket *avpkt)
1266 {
1267 503 const uint8_t *buf = avpkt->data;
1268 503 int buf_size = avpkt->size;
1269
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 503 times.
503 if (avctx->pix_fmt == AV_PIX_FMT_MONOBLACK) {
1270 ✗ return flic_decode_frame_1BPP(avctx, frame, got_frame,
1271 buf, buf_size);
1272
1/2
✓ Branch 0 taken 503 times.
✗ Branch 1 not taken.
503 } else if (avctx->pix_fmt == AV_PIX_FMT_PAL8) {
1273 503 return flic_decode_frame_8BPP(avctx, frame, got_frame,
1274 buf, buf_size);
1275 ✗ } else if ((avctx->pix_fmt == AV_PIX_FMT_RGB555) ||
1276 ✗ (avctx->pix_fmt == AV_PIX_FMT_RGB565)) {
1277 ✗ return flic_decode_frame_15_16BPP(avctx, frame, got_frame,
1278 buf, buf_size);
1279 ✗ } else if (avctx->pix_fmt == AV_PIX_FMT_BGR24) {
1280 ✗ return flic_decode_frame_24BPP(avctx, frame, got_frame,
1281 buf, buf_size);
1282 }
1283
1284 /* Should not get here, ever as the pix_fmt is processed */
1285 /* in flic_decode_init and the above if should deal with */
1286 /* the finite set of possibilities allowable by here. */
1287 /* But in case we do, just error out. */
1288 ✗ av_log(avctx, AV_LOG_ERROR, "Unknown FLC format, my science cannot explain how this happened.\n");
1289 ✗ return AVERROR_BUG;
1290 }
1291
1292
1293 8 static av_cold int flic_decode_end(AVCodecContext *avctx)
1294 {
1295 8 FlicDecodeContext *s = avctx->priv_data;
1296
1297 8 av_frame_free(&s->frame);
1298
1299 8 return 0;
1300 }
1301
1302 const FFCodec ff_flic_decoder = {
1303 .p.name = "flic",
1304 CODEC_LONG_NAME("Autodesk Animator Flic video"),
1305 .p.type = AVMEDIA_TYPE_VIDEO,
1306 .p.id = AV_CODEC_ID_FLIC,
1307 .priv_data_size = sizeof(FlicDecodeContext),
1308 .init = flic_decode_init,
1309 .close = flic_decode_end,
1310 FF_CODEC_DECODE_CB(flic_decode_frame),
1311 .p.capabilities = AV_CODEC_CAP_DR1,
1312 };
1313