GCC Code Coverage Report
Directory: ../../../ffmpeg/ Exec Total Coverage
File: src/libavcodec/flicvideo.c Lines: 186 603 30.8 %
Date: 2019-11-18 18:00:01 Branches: 110 409 26.9 %

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 <stdio.h>
38
#include <stdlib.h>
39
#include <string.h>
40
41
#include "libavutil/intreadwrite.h"
42
#include "avcodec.h"
43
#include "bytestream.h"
44
#include "internal.h"
45
#include "mathops.h"
46
47
#define FLI_256_COLOR 4
48
#define FLI_DELTA     7
49
#define FLI_COLOR     11
50
#define FLI_LC        12
51
#define FLI_BLACK     13
52
#define FLI_BRUN      15
53
#define FLI_COPY      16
54
#define FLI_MINI      18
55
#define FLI_DTA_BRUN  25
56
#define FLI_DTA_COPY  26
57
#define FLI_DTA_LC    27
58
59
#define FLI_TYPE_CODE     (0xAF11)
60
#define FLC_FLX_TYPE_CODE (0xAF12)
61
#define FLC_DTA_TYPE_CODE (0xAF44) /* Marks an "Extended FLC" comes from Dave's Targa Animator (DTA) */
62
#define FLC_MAGIC_CARPET_SYNTHETIC_TYPE_CODE (0xAF13)
63
64
#define CHECK_PIXEL_PTR(n) \
65
    if (pixel_ptr + n > pixel_limit) { \
66
        av_log (s->avctx, AV_LOG_ERROR, "Invalid pixel_ptr = %d > pixel_limit = %d\n", \
67
        pixel_ptr + n, pixel_limit); \
68
        return AVERROR_INVALIDDATA; \
69
    } \
70
71
typedef struct FlicDecodeContext {
72
    AVCodecContext *avctx;
73
    AVFrame *frame;
74
75
    unsigned int palette[256];
76
    int new_palette;
77
    int fli_type;  /* either 0xAF11 or 0xAF12, affects palette resolution */
78
} FlicDecodeContext;
79
80
8
static av_cold int flic_decode_init(AVCodecContext *avctx)
81
{
82
8
    FlicDecodeContext *s = avctx->priv_data;
83
8
    unsigned char *fli_header = (unsigned char *)avctx->extradata;
84
    int depth;
85
86
8
    if (avctx->extradata_size != 0 &&
87
8
        avctx->extradata_size != 12 &&
88
6
        avctx->extradata_size != 128 &&
89
        avctx->extradata_size != 256 &&
90
        avctx->extradata_size != 904 &&
91
        avctx->extradata_size != 1024) {
92
        av_log(avctx, AV_LOG_ERROR, "Unexpected extradata size %d\n", avctx->extradata_size);
93
        return AVERROR_INVALIDDATA;
94
    }
95
96
8
    s->avctx = avctx;
97
98
8
    if (s->avctx->extradata_size == 12) {
99
        /* special case for magic carpet FLIs */
100
2
        s->fli_type = FLC_MAGIC_CARPET_SYNTHETIC_TYPE_CODE;
101
2
        depth = 8;
102
6
    } else if (avctx->extradata_size == 1024) {
103
        uint8_t *ptr = avctx->extradata;
104
        int i;
105
106
        for (i = 0; i < 256; i++) {
107
            s->palette[i] = AV_RL32(ptr);
108
            ptr += 4;
109
        }
110
        depth = 8;
111
        /* FLI in MOV, see e.g. FFmpeg trac issue #626 */
112
6
    } else if (avctx->extradata_size == 0 ||
113
6
               avctx->extradata_size == 256 ||
114
        /* see FFmpeg ticket #1234 */
115
6
               avctx->extradata_size == 904) {
116
        s->fli_type = FLI_TYPE_CODE;
117
        depth = 8;
118
    } else {
119
6
        s->fli_type = AV_RL16(&fli_header[4]);
120
6
        depth = AV_RL16(&fli_header[12]);
121
    }
122
123
8
    if (depth == 0) {
124
        depth = 8; /* Some FLC generators set depth to zero, when they mean 8Bpp. Fix up here */
125
    }
126
127

8
    if ((s->fli_type == FLC_FLX_TYPE_CODE) && (depth == 16)) {
128
        depth = 15; /* Original Autodesk FLX's say the depth is 16Bpp when it is really 15Bpp */
129
    }
130
131

8
    switch (depth) {
132
8
        case 8  : avctx->pix_fmt = AV_PIX_FMT_PAL8; break;
133
        case 15 : avctx->pix_fmt = AV_PIX_FMT_RGB555; break;
134
        case 16 : avctx->pix_fmt = AV_PIX_FMT_RGB565; break;
135
        case 24 : avctx->pix_fmt = AV_PIX_FMT_BGR24; break;
136
        default :
137
                  av_log(avctx, AV_LOG_ERROR, "Unknown FLC/FLX depth of %d Bpp is unsupported.\n",depth);
138
                  return AVERROR_INVALIDDATA;
139
    }
140
141
8
    s->frame = av_frame_alloc();
142
8
    if (!s->frame)
143
        return AVERROR(ENOMEM);
144
145
8
    s->new_palette = 0;
146
147
8
    return 0;
148
}
149
150
501
static int flic_decode_frame_8BPP(AVCodecContext *avctx,
151
                                  void *data, int *got_frame,
152
                                  const uint8_t *buf, int buf_size)
153
{
154
501
    FlicDecodeContext *s = avctx->priv_data;
155
156
    GetByteContext g2;
157
    int pixel_ptr;
158
    int palette_ptr;
159
    unsigned char palette_idx1;
160
    unsigned char palette_idx2;
161
162
    unsigned int frame_size;
163
    int num_chunks;
164
165
    unsigned int chunk_size;
166
    int chunk_type;
167
168
    int i, j, ret;
169
170
    int color_packets;
171
    int color_changes;
172
    int color_shift;
173
    unsigned char r, g, b;
174
175
    int lines;
176
    int compressed_lines;
177
    int starting_line;
178
    int line_packets;
179
    int y_ptr;
180
    int byte_run;
181
    int pixel_skip;
182
    int pixel_countdown;
183
    unsigned char *pixels;
184
    unsigned int pixel_limit;
185
186
501
    bytestream2_init(&g2, buf, buf_size);
187
188
501
    if ((ret = ff_reget_buffer(avctx, s->frame, 0)) < 0)
189
        return ret;
190
191
501
    pixels = s->frame->data[0];
192
501
    pixel_limit = s->avctx->height * s->frame->linesize[0];
193

501
    if (buf_size < 16 || buf_size > INT_MAX - (3 * 256 + AV_INPUT_BUFFER_PADDING_SIZE))
194
        return AVERROR_INVALIDDATA;
195
501
    frame_size = bytestream2_get_le32(&g2);
196
501
    if (frame_size > buf_size)
197
        frame_size = buf_size;
198
501
    bytestream2_skip(&g2, 2); /* skip the magic number */
199
501
    num_chunks = bytestream2_get_le16(&g2);
200
501
    bytestream2_skip(&g2, 8);  /* skip padding */
201
202
501
    if (frame_size < 16)
203
        return AVERROR_INVALIDDATA;
204
205
501
    frame_size -= 16;
206
207
    /* iterate through the chunks */
208

1549
    while ((frame_size >= 6) && (num_chunks > 0) &&
209
524
            bytestream2_get_bytes_left(&g2) >= 4) {
210
        int stream_ptr_after_chunk;
211
524
        chunk_size = bytestream2_get_le32(&g2);
212
524
        if (chunk_size > frame_size) {
213
            av_log(avctx, AV_LOG_WARNING,
214
                   "Invalid chunk_size = %u > frame_size = %u\n", chunk_size, frame_size);
215
            chunk_size = frame_size;
216
        }
217
524
        stream_ptr_after_chunk = bytestream2_tell(&g2) - 4 + chunk_size;
218
219
524
        chunk_type = bytestream2_get_le16(&g2);
220
221


524
        switch (chunk_type) {
222
42
        case FLI_256_COLOR:
223
        case FLI_COLOR:
224
            /* check special case: If this file is from the Magic Carpet
225
             * game and uses 6-bit colors even though it reports 256-color
226
             * chunks in a 0xAF12-type file (fli_type is set to 0xAF13 during
227
             * initialization) */
228

42
            if ((chunk_type == FLI_256_COLOR) && (s->fli_type != FLC_MAGIC_CARPET_SYNTHETIC_TYPE_CODE))
229
1
                color_shift = 0;
230
            else
231
41
                color_shift = 2;
232
            /* set up the palette */
233
42
            color_packets = bytestream2_get_le16(&g2);
234
42
            palette_ptr = 0;
235
297
            for (i = 0; i < color_packets; i++) {
236
                /* first byte is how many colors to skip */
237
255
                palette_ptr += bytestream2_get_byte(&g2);
238
239
                /* next byte indicates how many entries to change */
240
255
                color_changes = bytestream2_get_byte(&g2);
241
242
                /* if there are 0 color changes, there are actually 256 */
243
255
                if (color_changes == 0)
244
4
                    color_changes = 256;
245
246
255
                if (bytestream2_tell(&g2) + color_changes * 3 > stream_ptr_after_chunk)
247
                    break;
248
249
10643
                for (j = 0; j < color_changes; j++) {
250
                    unsigned int entry;
251
252
                    /* wrap around, for good measure */
253
10388
                    if ((unsigned)palette_ptr >= 256)
254
                        palette_ptr = 0;
255
256
10388
                    r = bytestream2_get_byte(&g2) << color_shift;
257
10388
                    g = bytestream2_get_byte(&g2) << color_shift;
258
10388
                    b = bytestream2_get_byte(&g2) << color_shift;
259
10388
                    entry = 0xFFU << 24 | r << 16 | g << 8 | b;
260
10388
                    if (color_shift == 2)
261
10132
                        entry |= entry >> 6 & 0x30303;
262
10388
                    if (s->palette[palette_ptr] != entry)
263
10388
                        s->new_palette = 1;
264
10388
                    s->palette[palette_ptr++] = entry;
265
                }
266
            }
267
42
            break;
268
269
67
        case FLI_DELTA:
270
67
            y_ptr = 0;
271
67
            compressed_lines = bytestream2_get_le16(&g2);
272
8288
            while (compressed_lines > 0) {
273
8221
                if (bytestream2_tell(&g2) + 2 > stream_ptr_after_chunk)
274
                    break;
275
8221
                if (y_ptr > pixel_limit)
276
                    return AVERROR_INVALIDDATA;
277
8221
                line_packets = sign_extend(bytestream2_get_le16(&g2), 16);
278
8221
                if ((line_packets & 0xC000) == 0xC000) {
279
                    // line skip opcode
280
108
                    line_packets = -line_packets;
281
108
                    if (line_packets > s->avctx->height)
282
                        return AVERROR_INVALIDDATA;
283
108
                    y_ptr += line_packets * s->frame->linesize[0];
284
8113
                } else if ((line_packets & 0xC000) == 0x4000) {
285
                    av_log(avctx, AV_LOG_ERROR, "Undefined opcode (%x) in DELTA_FLI\n", line_packets);
286
8113
                } else if ((line_packets & 0xC000) == 0x8000) {
287
                    // "last byte" opcode
288
                    pixel_ptr= y_ptr + s->frame->linesize[0] - 1;
289
                    CHECK_PIXEL_PTR(0);
290
                    pixels[pixel_ptr] = line_packets & 0xff;
291
                } else {
292
8113
                    compressed_lines--;
293
8113
                    pixel_ptr = y_ptr;
294
8113
                    CHECK_PIXEL_PTR(0);
295
8113
                    pixel_countdown = s->avctx->width;
296
132721
                    for (i = 0; i < line_packets; i++) {
297
124608
                        if (bytestream2_tell(&g2) + 2 > stream_ptr_after_chunk)
298
                            break;
299
                        /* account for the skip bytes */
300
124608
                        pixel_skip = bytestream2_get_byte(&g2);
301
124608
                        pixel_ptr += pixel_skip;
302
124608
                        pixel_countdown -= pixel_skip;
303
124608
                        byte_run = sign_extend(bytestream2_get_byte(&g2), 8);
304
124608
                        if (byte_run < 0) {
305
37508
                            byte_run = -byte_run;
306
37508
                            palette_idx1 = bytestream2_get_byte(&g2);
307
37508
                            palette_idx2 = bytestream2_get_byte(&g2);
308
37508
                            CHECK_PIXEL_PTR(byte_run * 2);
309
220003
                            for (j = 0; j < byte_run; j++, pixel_countdown -= 2) {
310
182495
                                pixels[pixel_ptr++] = palette_idx1;
311
182495
                                pixels[pixel_ptr++] = palette_idx2;
312
                            }
313
                        } else {
314
87100
                            CHECK_PIXEL_PTR(byte_run * 2);
315
87100
                            if (bytestream2_tell(&g2) + byte_run * 2 > stream_ptr_after_chunk)
316
                                break;
317
906386
                            for (j = 0; j < byte_run * 2; j++, pixel_countdown--) {
318
819286
                                pixels[pixel_ptr++] = bytestream2_get_byte(&g2);
319
                            }
320
                        }
321
                    }
322
323
8113
                    y_ptr += s->frame->linesize[0];
324
                }
325
            }
326
67
            break;
327
328
411
        case FLI_LC:
329
            /* line compressed */
330
411
            starting_line = bytestream2_get_le16(&g2);
331
411
            if (starting_line >= s->avctx->height)
332
                return AVERROR_INVALIDDATA;
333
411
            y_ptr = 0;
334
411
            y_ptr += starting_line * s->frame->linesize[0];
335
336
411
            compressed_lines = bytestream2_get_le16(&g2);
337
53677
            while (compressed_lines > 0) {
338
53266
                pixel_ptr = y_ptr;
339
53266
                CHECK_PIXEL_PTR(0);
340
53266
                pixel_countdown = s->avctx->width;
341
53266
                if (bytestream2_tell(&g2) + 1 > stream_ptr_after_chunk)
342
                    break;
343
53266
                line_packets = bytestream2_get_byte(&g2);
344
53266
                if (line_packets > 0) {
345
369126
                    for (i = 0; i < line_packets; i++) {
346
                        /* account for the skip bytes */
347
320826
                        if (bytestream2_tell(&g2) + 1 > stream_ptr_after_chunk)
348
                            break;
349
320826
                        pixel_skip = bytestream2_get_byte(&g2);
350
320826
                        pixel_ptr += pixel_skip;
351
320826
                        pixel_countdown -= pixel_skip;
352
320826
                        byte_run = sign_extend(bytestream2_get_byte(&g2),8);
353
320826
                        if (byte_run > 0) {
354
235604
                            CHECK_PIXEL_PTR(byte_run);
355
235604
                            if (bytestream2_tell(&g2) + byte_run > stream_ptr_after_chunk)
356
                                break;
357
1600390
                            for (j = 0; j < byte_run; j++, pixel_countdown--) {
358
1364786
                                pixels[pixel_ptr++] = bytestream2_get_byte(&g2);
359
                            }
360
85222
                        } else if (byte_run < 0) {
361
85222
                            byte_run = -byte_run;
362
85222
                            palette_idx1 = bytestream2_get_byte(&g2);
363
85222
                            CHECK_PIXEL_PTR(byte_run);
364
625612
                            for (j = 0; j < byte_run; j++, pixel_countdown--) {
365
540390
                                pixels[pixel_ptr++] = palette_idx1;
366
                            }
367
                        }
368
                    }
369
                }
370
371
53266
                y_ptr += s->frame->linesize[0];
372
53266
                compressed_lines--;
373
            }
374
411
            break;
375
376
        case FLI_BLACK:
377
            /* set the whole frame to color 0 (which is usually black) */
378
            memset(pixels, 0,
379
                s->frame->linesize[0] * s->avctx->height);
380
            break;
381
382
4
        case FLI_BRUN:
383
            /* Byte run compression: This chunk type only occurs in the first
384
             * FLI frame and it will update the entire frame. */
385
4
            y_ptr = 0;
386
1084
            for (lines = 0; lines < s->avctx->height; lines++) {
387
1080
                pixel_ptr = y_ptr;
388
                /* disregard the line packets; instead, iterate through all
389
                 * pixels on a row */
390
1080
                 bytestream2_skip(&g2, 1);
391
1080
                pixel_countdown = s->avctx->width;
392
23867
                while (pixel_countdown > 0) {
393
22787
                    if (bytestream2_tell(&g2) + 1 > stream_ptr_after_chunk)
394
                        break;
395
22787
                    byte_run = sign_extend(bytestream2_get_byte(&g2), 8);
396
22787
                    if (!byte_run) {
397
                        av_log(avctx, AV_LOG_ERROR, "Invalid byte run value.\n");
398
                        return AVERROR_INVALIDDATA;
399
                    }
400
401
22787
                    if (byte_run > 0) {
402
14467
                        palette_idx1 = bytestream2_get_byte(&g2);
403
14467
                        CHECK_PIXEL_PTR(byte_run);
404
492515
                        for (j = 0; j < byte_run; j++) {
405
478048
                            pixels[pixel_ptr++] = palette_idx1;
406
478048
                            pixel_countdown--;
407
478048
                            if (pixel_countdown < 0)
408
                                av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d) at line %d\n",
409
                                       pixel_countdown, lines);
410
                        }
411
                    } else {  /* copy bytes if byte_run < 0 */
412
8320
                        byte_run = -byte_run;
413
8320
                        CHECK_PIXEL_PTR(byte_run);
414
8320
                        if (bytestream2_tell(&g2) + byte_run > stream_ptr_after_chunk)
415
                            break;
416
29472
                        for (j = 0; j < byte_run; j++) {
417
21152
                            pixels[pixel_ptr++] = bytestream2_get_byte(&g2);
418
21152
                            pixel_countdown--;
419
21152
                            if (pixel_countdown < 0)
420
                                av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d) at line %d\n",
421
                                       pixel_countdown, lines);
422
                        }
423
                    }
424
                }
425
426
1080
                y_ptr += s->frame->linesize[0];
427
            }
428
4
            break;
429
430
        case FLI_COPY:
431
            /* copy the chunk (uncompressed frame) */
432
            if (chunk_size - 6 != FFALIGN(s->avctx->width, 4) * s->avctx->height) {
433
                av_log(avctx, AV_LOG_ERROR, "In chunk FLI_COPY : source data (%d bytes) " \
434
                       "has incorrect size, skipping chunk\n", chunk_size - 6);
435
                bytestream2_skip(&g2, chunk_size - 6);
436
            } else {
437
                for (y_ptr = 0; y_ptr < s->frame->linesize[0] * s->avctx->height;
438
                     y_ptr += s->frame->linesize[0]) {
439
                    bytestream2_get_buffer(&g2, &pixels[y_ptr],
440
                                           s->avctx->width);
441
                    if (s->avctx->width & 3)
442
                        bytestream2_skip(&g2, 4 - (s->avctx->width & 3));
443
                }
444
            }
445
            break;
446
447
        case FLI_MINI:
448
            /* some sort of a thumbnail? disregard this chunk... */
449
            break;
450
451
        default:
452
            av_log(avctx, AV_LOG_ERROR, "Unrecognized chunk type: %d\n", chunk_type);
453
            break;
454
        }
455
456
524
        if (stream_ptr_after_chunk - bytestream2_tell(&g2) >= 0) {
457
524
            bytestream2_skip(&g2, stream_ptr_after_chunk - bytestream2_tell(&g2));
458
        } else {
459
            av_log(avctx, AV_LOG_ERROR, "Chunk overread\n");
460
            break;
461
        }
462
463
524
        frame_size -= chunk_size;
464
524
        num_chunks--;
465
    }
466
467
    /* by the end of the chunk, the stream ptr should equal the frame
468
     * size (minus 1 or 2, possibly); if it doesn't, issue a warning */
469
501
    if (bytestream2_get_bytes_left(&g2) > 2)
470
        av_log(avctx, AV_LOG_ERROR, "Processed FLI chunk where chunk size = %d " \
471
               "and final chunk ptr = %d\n", buf_size,
472
               buf_size - bytestream2_get_bytes_left(&g2));
473
474
    /* make the palette available on the way out */
475
501
    memcpy(s->frame->data[1], s->palette, AVPALETTE_SIZE);
476
501
    if (s->new_palette) {
477
42
        s->frame->palette_has_changed = 1;
478
42
        s->new_palette = 0;
479
    }
480
481
501
    if ((ret = av_frame_ref(data, s->frame)) < 0)
482
        return ret;
483
484
501
    *got_frame = 1;
485
486
501
    return buf_size;
487
}
488
489
static int flic_decode_frame_15_16BPP(AVCodecContext *avctx,
490
                                      void *data, int *got_frame,
491
                                      const uint8_t *buf, int buf_size)
492
{
493
    /* Note, the only difference between the 15Bpp and 16Bpp */
494
    /* Format is the pixel format, the packets are processed the same. */
495
    FlicDecodeContext *s = avctx->priv_data;
496
497
    GetByteContext g2;
498
    int pixel_ptr;
499
    unsigned char palette_idx1;
500
501
    unsigned int frame_size;
502
    int num_chunks;
503
504
    unsigned int chunk_size;
505
    int chunk_type;
506
507
    int i, j, ret;
508
509
    int lines;
510
    int compressed_lines;
511
    int line_packets;
512
    int y_ptr;
513
    int byte_run;
514
    int pixel_skip;
515
    int pixel_countdown;
516
    unsigned char *pixels;
517
    int pixel;
518
    unsigned int pixel_limit;
519
520
    bytestream2_init(&g2, buf, buf_size);
521
522
    if ((ret = ff_reget_buffer(avctx, s->frame, 0)) < 0)
523
        return ret;
524
525
    pixels = s->frame->data[0];
526
    pixel_limit = s->avctx->height * s->frame->linesize[0];
527
528
    frame_size = bytestream2_get_le32(&g2);
529
    bytestream2_skip(&g2, 2);  /* skip the magic number */
530
    num_chunks = bytestream2_get_le16(&g2);
531
    bytestream2_skip(&g2, 8);  /* skip padding */
532
    if (frame_size > buf_size)
533
        frame_size = buf_size;
534
535
    if (frame_size < 16)
536
        return AVERROR_INVALIDDATA;
537
    frame_size -= 16;
538
539
    /* iterate through the chunks */
540
    while ((frame_size > 0) && (num_chunks > 0) &&
541
            bytestream2_get_bytes_left(&g2) >= 4) {
542
        int stream_ptr_after_chunk;
543
        chunk_size = bytestream2_get_le32(&g2);
544
        if (chunk_size > frame_size) {
545
            av_log(avctx, AV_LOG_WARNING,
546
                   "Invalid chunk_size = %u > frame_size = %u\n", chunk_size, frame_size);
547
            chunk_size = frame_size;
548
        }
549
        stream_ptr_after_chunk = bytestream2_tell(&g2) - 4 + chunk_size;
550
551
        chunk_type = bytestream2_get_le16(&g2);
552
553
554
        switch (chunk_type) {
555
        case FLI_256_COLOR:
556
        case FLI_COLOR:
557
            /* For some reason, it seems that non-palettized flics do
558
             * include one of these chunks in their first frame.
559
             * Why I do not know, it seems rather extraneous. */
560
            ff_dlog(avctx,
561
                    "Unexpected Palette chunk %d in non-palettized FLC\n",
562
                    chunk_type);
563
            bytestream2_skip(&g2, chunk_size - 6);
564
            break;
565
566
        case FLI_DELTA:
567
        case FLI_DTA_LC:
568
            y_ptr = 0;
569
            compressed_lines = bytestream2_get_le16(&g2);
570
            while (compressed_lines > 0) {
571
                if (bytestream2_tell(&g2) + 2 > stream_ptr_after_chunk)
572
                    break;
573
                if (y_ptr > pixel_limit)
574
                    return AVERROR_INVALIDDATA;
575
                line_packets = sign_extend(bytestream2_get_le16(&g2), 16);
576
                if (line_packets < 0) {
577
                    line_packets = -line_packets;
578
                    if (line_packets > s->avctx->height)
579
                        return AVERROR_INVALIDDATA;
580
                    y_ptr += line_packets * s->frame->linesize[0];
581
                } else {
582
                    compressed_lines--;
583
                    pixel_ptr = y_ptr;
584
                    CHECK_PIXEL_PTR(0);
585
                    pixel_countdown = s->avctx->width;
586
                    for (i = 0; i < line_packets; i++) {
587
                        /* account for the skip bytes */
588
                        if (bytestream2_tell(&g2) + 2 > stream_ptr_after_chunk)
589
                            break;
590
                        pixel_skip = bytestream2_get_byte(&g2);
591
                        pixel_ptr += (pixel_skip*2); /* Pixel is 2 bytes wide */
592
                        pixel_countdown -= pixel_skip;
593
                        byte_run = sign_extend(bytestream2_get_byte(&g2), 8);
594
                        if (byte_run < 0) {
595
                            byte_run = -byte_run;
596
                            pixel    = bytestream2_get_le16(&g2);
597
                            CHECK_PIXEL_PTR(2 * byte_run);
598
                            for (j = 0; j < byte_run; j++, pixel_countdown -= 2) {
599
                                *((signed short*)(&pixels[pixel_ptr])) = pixel;
600
                                pixel_ptr += 2;
601
                            }
602
                        } else {
603
                            if (bytestream2_tell(&g2) + 2*byte_run > stream_ptr_after_chunk)
604
                                break;
605
                            CHECK_PIXEL_PTR(2 * byte_run);
606
                            for (j = 0; j < byte_run; j++, pixel_countdown--) {
607
                                *((signed short*)(&pixels[pixel_ptr])) = bytestream2_get_le16(&g2);
608
                                pixel_ptr += 2;
609
                            }
610
                        }
611
                    }
612
613
                    y_ptr += s->frame->linesize[0];
614
                }
615
            }
616
            break;
617
618
        case FLI_LC:
619
            av_log(avctx, AV_LOG_ERROR, "Unexpected FLI_LC chunk in non-palettized FLC\n");
620
            bytestream2_skip(&g2, chunk_size - 6);
621
            break;
622
623
        case FLI_BLACK:
624
            /* set the whole frame to 0x0000 which is black in both 15Bpp and 16Bpp modes. */
625
            memset(pixels, 0x0000,
626
                   s->frame->linesize[0] * s->avctx->height);
627
            break;
628
629
        case FLI_BRUN:
630
            y_ptr = 0;
631
            for (lines = 0; lines < s->avctx->height; lines++) {
632
                pixel_ptr = y_ptr;
633
                /* disregard the line packets; instead, iterate through all
634
                 * pixels on a row */
635
                bytestream2_skip(&g2, 1);
636
                pixel_countdown = (s->avctx->width * 2);
637
638
                while (pixel_countdown > 0) {
639
                    if (bytestream2_tell(&g2) + 1 > stream_ptr_after_chunk)
640
                        break;
641
                    byte_run = sign_extend(bytestream2_get_byte(&g2), 8);
642
                    if (byte_run > 0) {
643
                        palette_idx1 = bytestream2_get_byte(&g2);
644
                        CHECK_PIXEL_PTR(byte_run);
645
                        for (j = 0; j < byte_run; j++) {
646
                            pixels[pixel_ptr++] = palette_idx1;
647
                            pixel_countdown--;
648
                            if (pixel_countdown < 0)
649
                                av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d) (linea%d)\n",
650
                                       pixel_countdown, lines);
651
                        }
652
                    } else {  /* copy bytes if byte_run < 0 */
653
                        byte_run = -byte_run;
654
                        if (bytestream2_tell(&g2) + byte_run > stream_ptr_after_chunk)
655
                            break;
656
                        CHECK_PIXEL_PTR(byte_run);
657
                        for (j = 0; j < byte_run; j++) {
658
                            palette_idx1 = bytestream2_get_byte(&g2);
659
                            pixels[pixel_ptr++] = palette_idx1;
660
                            pixel_countdown--;
661
                            if (pixel_countdown < 0)
662
                                av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d) at line %d\n",
663
                                       pixel_countdown, lines);
664
                        }
665
                    }
666
                }
667
668
                /* Now FLX is strange, in that it is "byte" as opposed to "pixel" run length compressed.
669
                 * This does not give us any good opportunity to perform word endian conversion
670
                 * during decompression. So if it is required (i.e., this is not a LE target, we do
671
                 * a second pass over the line here, swapping the bytes.
672
                 */
673
#if HAVE_BIGENDIAN
674
                pixel_ptr = y_ptr;
675
                pixel_countdown = s->avctx->width;
676
                while (pixel_countdown > 0) {
677
                    *((signed short*)(&pixels[pixel_ptr])) = AV_RL16(&buf[pixel_ptr]);
678
                    pixel_ptr += 2;
679
                }
680
#endif
681
                y_ptr += s->frame->linesize[0];
682
            }
683
            break;
684
685
        case FLI_DTA_BRUN:
686
            y_ptr = 0;
687
            for (lines = 0; lines < s->avctx->height; lines++) {
688
                pixel_ptr = y_ptr;
689
                /* disregard the line packets; instead, iterate through all
690
                 * pixels on a row */
691
                bytestream2_skip(&g2, 1);
692
                pixel_countdown = s->avctx->width; /* Width is in pixels, not bytes */
693
694
                while (pixel_countdown > 0) {
695
                    if (bytestream2_tell(&g2) + 1 > stream_ptr_after_chunk)
696
                        break;
697
                    byte_run = sign_extend(bytestream2_get_byte(&g2), 8);
698
                    if (byte_run > 0) {
699
                        pixel    = bytestream2_get_le16(&g2);
700
                        CHECK_PIXEL_PTR(2 * byte_run);
701
                        for (j = 0; j < byte_run; j++) {
702
                            *((signed short*)(&pixels[pixel_ptr])) = pixel;
703
                            pixel_ptr += 2;
704
                            pixel_countdown--;
705
                            if (pixel_countdown < 0)
706
                                av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d)\n",
707
                                       pixel_countdown);
708
                        }
709
                    } else {  /* copy pixels if byte_run < 0 */
710
                        byte_run = -byte_run;
711
                        if (bytestream2_tell(&g2) + 2 * byte_run > stream_ptr_after_chunk)
712
                            break;
713
                        CHECK_PIXEL_PTR(2 * byte_run);
714
                        for (j = 0; j < byte_run; j++) {
715
                            *((signed short*)(&pixels[pixel_ptr])) = bytestream2_get_le16(&g2);
716
                            pixel_ptr  += 2;
717
                            pixel_countdown--;
718
                            if (pixel_countdown < 0)
719
                                av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d)\n",
720
                                       pixel_countdown);
721
                        }
722
                    }
723
                }
724
725
                y_ptr += s->frame->linesize[0];
726
            }
727
            break;
728
729
        case FLI_COPY:
730
        case FLI_DTA_COPY:
731
            /* copy the chunk (uncompressed frame) */
732
            if (chunk_size - 6 > (unsigned int)(FFALIGN(s->avctx->width, 2) * s->avctx->height)*2) {
733
                av_log(avctx, AV_LOG_ERROR, "In chunk FLI_COPY : source data (%d bytes) " \
734
                       "bigger than image, skipping chunk\n", chunk_size - 6);
735
                bytestream2_skip(&g2, chunk_size - 6);
736
            } else {
737
738
                for (y_ptr = 0; y_ptr < s->frame->linesize[0] * s->avctx->height;
739
                     y_ptr += s->frame->linesize[0]) {
740
741
                    pixel_countdown = s->avctx->width;
742
                    pixel_ptr = 0;
743
                    while (pixel_countdown > 0) {
744
                      *((signed short*)(&pixels[y_ptr + pixel_ptr])) = bytestream2_get_le16(&g2);
745
                      pixel_ptr += 2;
746
                      pixel_countdown--;
747
                    }
748
                    if (s->avctx->width & 1)
749
                        bytestream2_skip(&g2, 2);
750
                }
751
            }
752
            break;
753
754
        case FLI_MINI:
755
            /* some sort of a thumbnail? disregard this chunk... */
756
            bytestream2_skip(&g2, chunk_size - 6);
757
            break;
758
759
        default:
760
            av_log(avctx, AV_LOG_ERROR, "Unrecognized chunk type: %d\n", chunk_type);
761
            break;
762
        }
763
764
        if (stream_ptr_after_chunk - bytestream2_tell(&g2) >= 0) {
765
            bytestream2_skip(&g2, stream_ptr_after_chunk - bytestream2_tell(&g2));
766
        } else {
767
            av_log(avctx, AV_LOG_ERROR, "Chunk overread\n");
768
            break;
769
        }
770
771
        frame_size -= chunk_size;
772
        num_chunks--;
773
    }
774
775
    /* by the end of the chunk, the stream ptr should equal the frame
776
     * size (minus 1, possibly); if it doesn't, issue a warning */
777
    if ((bytestream2_get_bytes_left(&g2) != 0) && (bytestream2_get_bytes_left(&g2) != 1))
778
        av_log(avctx, AV_LOG_ERROR, "Processed FLI chunk where chunk size = %d " \
779
               "and final chunk ptr = %d\n", buf_size, bytestream2_tell(&g2));
780
781
    if ((ret = av_frame_ref(data, s->frame)) < 0)
782
        return ret;
783
784
    *got_frame = 1;
785
786
    return buf_size;
787
}
788
789
static int flic_decode_frame_24BPP(AVCodecContext *avctx,
790
                                   void *data, int *got_frame,
791
                                   const uint8_t *buf, int buf_size)
792
{
793
    FlicDecodeContext *s = avctx->priv_data;
794
795
    GetByteContext g2;
796
    int pixel_ptr;
797
    unsigned char palette_idx1;
798
799
    unsigned int frame_size;
800
    int num_chunks;
801
802
    unsigned int chunk_size;
803
    int chunk_type;
804
805
    int i, j, ret;
806
807
    int lines;
808
    int compressed_lines;
809
    int line_packets;
810
    int y_ptr;
811
    int byte_run;
812
    int pixel_skip;
813
    int pixel_countdown;
814
    unsigned char *pixels;
815
    int pixel;
816
    unsigned int pixel_limit;
817
818
    bytestream2_init(&g2, buf, buf_size);
819
820
    if ((ret = ff_reget_buffer(avctx, s->frame, 0)) < 0)
821
        return ret;
822
823
    pixels = s->frame->data[0];
824
    pixel_limit = s->avctx->height * s->frame->linesize[0];
825
826
    frame_size = bytestream2_get_le32(&g2);
827
    bytestream2_skip(&g2, 2);  /* skip the magic number */
828
    num_chunks = bytestream2_get_le16(&g2);
829
    bytestream2_skip(&g2, 8);  /* skip padding */
830
    if (frame_size > buf_size)
831
        frame_size = buf_size;
832
833
    if (frame_size < 16)
834
        return AVERROR_INVALIDDATA;
835
    frame_size -= 16;
836
837
    /* iterate through the chunks */
838
    while ((frame_size > 0) && (num_chunks > 0) &&
839
            bytestream2_get_bytes_left(&g2) >= 4) {
840
        int stream_ptr_after_chunk;
841
        chunk_size = bytestream2_get_le32(&g2);
842
        if (chunk_size > frame_size) {
843
            av_log(avctx, AV_LOG_WARNING,
844
                   "Invalid chunk_size = %u > frame_size = %u\n", chunk_size, frame_size);
845
            chunk_size = frame_size;
846
        }
847
        stream_ptr_after_chunk = bytestream2_tell(&g2) - 4 + chunk_size;
848
849
        chunk_type = bytestream2_get_le16(&g2);
850
851
852
        switch (chunk_type) {
853
        case FLI_256_COLOR:
854
        case FLI_COLOR:
855
            /* For some reason, it seems that non-palettized flics do
856
             * include one of these chunks in their first frame.
857
             * Why I do not know, it seems rather extraneous. */
858
            ff_dlog(avctx,
859
                    "Unexpected Palette chunk %d in non-palettized FLC\n",
860
                    chunk_type);
861
            bytestream2_skip(&g2, chunk_size - 6);
862
            break;
863
864
        case FLI_DELTA:
865
        case FLI_DTA_LC:
866
            y_ptr = 0;
867
            compressed_lines = bytestream2_get_le16(&g2);
868
            while (compressed_lines > 0) {
869
                if (bytestream2_tell(&g2) + 2 > stream_ptr_after_chunk)
870
                    break;
871
                if (y_ptr > pixel_limit)
872
                    return AVERROR_INVALIDDATA;
873
                line_packets = sign_extend(bytestream2_get_le16(&g2), 16);
874
                if (line_packets < 0) {
875
                    line_packets = -line_packets;
876
                    if (line_packets > s->avctx->height)
877
                        return AVERROR_INVALIDDATA;
878
                    y_ptr += line_packets * s->frame->linesize[0];
879
                } else {
880
                    compressed_lines--;
881
                    pixel_ptr = y_ptr;
882
                    CHECK_PIXEL_PTR(0);
883
                    pixel_countdown = s->avctx->width;
884
                    for (i = 0; i < line_packets; i++) {
885
                        /* account for the skip bytes */
886
                        if (bytestream2_tell(&g2) + 2 > stream_ptr_after_chunk)
887
                            break;
888
                        pixel_skip = bytestream2_get_byte(&g2);
889
                        pixel_ptr += (pixel_skip*3); /* Pixel is 3 bytes wide */
890
                        pixel_countdown -= pixel_skip;
891
                        byte_run = sign_extend(bytestream2_get_byte(&g2), 8);
892
                        if (byte_run < 0) {
893
                            byte_run = -byte_run;
894
                            pixel    = bytestream2_get_le24(&g2);
895
                            CHECK_PIXEL_PTR(3 * byte_run);
896
                            for (j = 0; j < byte_run; j++, pixel_countdown -= 1) {
897
                                AV_WL24(&pixels[pixel_ptr], pixel);
898
                                pixel_ptr += 3;
899
                            }
900
                        } else {
901
                            if (bytestream2_tell(&g2) + 2*byte_run > stream_ptr_after_chunk)
902
                                break;
903
                            CHECK_PIXEL_PTR(3 * byte_run);
904
                            for (j = 0; j < byte_run; j++, pixel_countdown--) {
905
                                pixel = bytestream2_get_le24(&g2);
906
                                AV_WL24(&pixels[pixel_ptr], pixel);
907
                                pixel_ptr += 3;
908
                            }
909
                        }
910
                    }
911
912
                    y_ptr += s->frame->linesize[0];
913
                }
914
            }
915
            break;
916
917
        case FLI_LC:
918
            av_log(avctx, AV_LOG_ERROR, "Unexpected FLI_LC chunk in non-palettized FLC\n");
919
            bytestream2_skip(&g2, chunk_size - 6);
920
            break;
921
922
        case FLI_BLACK:
923
            /* set the whole frame to 0x00 which is black for 24 bit mode. */
924
            memset(pixels, 0x00,
925
                   s->frame->linesize[0] * s->avctx->height);
926
            break;
927
928
        case FLI_BRUN:
929
            y_ptr = 0;
930
            for (lines = 0; lines < s->avctx->height; lines++) {
931
                pixel_ptr = y_ptr;
932
                /* disregard the line packets; instead, iterate through all
933
                 * pixels on a row */
934
                bytestream2_skip(&g2, 1);
935
                pixel_countdown = (s->avctx->width * 3);
936
937
                while (pixel_countdown > 0) {
938
                    if (bytestream2_tell(&g2) + 1 > stream_ptr_after_chunk)
939
                        break;
940
                    byte_run = sign_extend(bytestream2_get_byte(&g2), 8);
941
                    if (byte_run > 0) {
942
                        palette_idx1 = bytestream2_get_byte(&g2);
943
                        CHECK_PIXEL_PTR(byte_run);
944
                        for (j = 0; j < byte_run; j++) {
945
                            pixels[pixel_ptr++] = palette_idx1;
946
                            pixel_countdown--;
947
                            if (pixel_countdown < 0)
948
                                av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d) (linea%d)\n",
949
                                       pixel_countdown, lines);
950
                        }
951
                    } else {  /* copy bytes if byte_run < 0 */
952
                        byte_run = -byte_run;
953
                        if (bytestream2_tell(&g2) + byte_run > stream_ptr_after_chunk)
954
                            break;
955
                        CHECK_PIXEL_PTR(byte_run);
956
                        for (j = 0; j < byte_run; j++) {
957
                            palette_idx1 = bytestream2_get_byte(&g2);
958
                            pixels[pixel_ptr++] = palette_idx1;
959
                            pixel_countdown--;
960
                            if (pixel_countdown < 0)
961
                                av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d) at line %d\n",
962
                                       pixel_countdown, lines);
963
                        }
964
                    }
965
                }
966
967
                y_ptr += s->frame->linesize[0];
968
            }
969
            break;
970
971
        case FLI_DTA_BRUN:
972
            y_ptr = 0;
973
            for (lines = 0; lines < s->avctx->height; lines++) {
974
                pixel_ptr = y_ptr;
975
                /* disregard the line packets; instead, iterate through all
976
                 * pixels on a row */
977
                bytestream2_skip(&g2, 1);
978
                pixel_countdown = s->avctx->width; /* Width is in pixels, not bytes */
979
980
                while (pixel_countdown > 0) {
981
                    if (bytestream2_tell(&g2) + 1 > stream_ptr_after_chunk)
982
                        break;
983
                    byte_run = sign_extend(bytestream2_get_byte(&g2), 8);
984
                    if (byte_run > 0) {
985
                        pixel = bytestream2_get_le24(&g2);
986
                        CHECK_PIXEL_PTR(3 * byte_run);
987
                        for (j = 0; j < byte_run; j++) {
988
                            AV_WL24(pixels + pixel_ptr, pixel);
989
                            pixel_ptr += 3;
990
                            pixel_countdown--;
991
                            if (pixel_countdown < 0)
992
                                av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d)\n",
993
                                       pixel_countdown);
994
                        }
995
                    } else {  /* copy pixels if byte_run < 0 */
996
                        byte_run = -byte_run;
997
                        if (bytestream2_tell(&g2) + 3 * byte_run > stream_ptr_after_chunk)
998
                            break;
999
                        CHECK_PIXEL_PTR(3 * byte_run);
1000
                        for (j = 0; j < byte_run; j++) {
1001
                            pixel = bytestream2_get_le24(&g2);
1002
                            AV_WL24(pixels + pixel_ptr, pixel);
1003
                            pixel_ptr  += 3;
1004
                            pixel_countdown--;
1005
                            if (pixel_countdown < 0)
1006
                                av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d)\n",
1007
                                       pixel_countdown);
1008
                        }
1009
                    }
1010
                }
1011
1012
                y_ptr += s->frame->linesize[0];
1013
            }
1014
            break;
1015
1016
        case FLI_COPY:
1017
        case FLI_DTA_COPY:
1018
            /* copy the chunk (uncompressed frame) */
1019
            if (chunk_size - 6 > (unsigned int)(FFALIGN(s->avctx->width, 2) * s->avctx->height)*3) {
1020
                av_log(avctx, AV_LOG_ERROR, "In chunk FLI_COPY : source data (%d bytes) " \
1021
                       "bigger than image, skipping chunk\n", chunk_size - 6);
1022
                bytestream2_skip(&g2, chunk_size - 6);
1023
            } else {
1024
                for (y_ptr = 0; y_ptr < s->frame->linesize[0] * s->avctx->height;
1025
                     y_ptr += s->frame->linesize[0]) {
1026
1027
                    bytestream2_get_buffer(&g2, pixels + y_ptr, 3*s->avctx->width);
1028
                    if (s->avctx->width & 1)
1029
                        bytestream2_skip(&g2, 3);
1030
                }
1031
            }
1032
            break;
1033
1034
        case FLI_MINI:
1035
            /* some sort of a thumbnail? disregard this chunk... */
1036
            bytestream2_skip(&g2, chunk_size - 6);
1037
            break;
1038
1039
        default:
1040
            av_log(avctx, AV_LOG_ERROR, "Unrecognized chunk type: %d\n", chunk_type);
1041
            break;
1042
        }
1043
1044
        if (stream_ptr_after_chunk - bytestream2_tell(&g2) >= 0) {
1045
            bytestream2_skip(&g2, stream_ptr_after_chunk - bytestream2_tell(&g2));
1046
        } else {
1047
            av_log(avctx, AV_LOG_ERROR, "Chunk overread\n");
1048
            break;
1049
        }
1050
1051
        frame_size -= chunk_size;
1052
        num_chunks--;
1053
    }
1054
1055
    /* by the end of the chunk, the stream ptr should equal the frame
1056
     * size (minus 1, possibly); if it doesn't, issue a warning */
1057
    if ((bytestream2_get_bytes_left(&g2) != 0) && (bytestream2_get_bytes_left(&g2) != 1))
1058
        av_log(avctx, AV_LOG_ERROR, "Processed FLI chunk where chunk size = %d " \
1059
               "and final chunk ptr = %d\n", buf_size, bytestream2_tell(&g2));
1060
1061
    if ((ret = av_frame_ref(data, s->frame)) < 0)
1062
        return ret;
1063
1064
    *got_frame = 1;
1065
1066
    return buf_size;
1067
}
1068
1069
501
static int flic_decode_frame(AVCodecContext *avctx,
1070
                             void *data, int *got_frame,
1071
                             AVPacket *avpkt)
1072
{
1073
501
    const uint8_t *buf = avpkt->data;
1074
501
    int buf_size = avpkt->size;
1075
501
    if (avctx->pix_fmt == AV_PIX_FMT_PAL8) {
1076
501
        return flic_decode_frame_8BPP(avctx, data, got_frame,
1077
                                      buf, buf_size);
1078
    } else if ((avctx->pix_fmt == AV_PIX_FMT_RGB555) ||
1079
               (avctx->pix_fmt == AV_PIX_FMT_RGB565)) {
1080
        return flic_decode_frame_15_16BPP(avctx, data, got_frame,
1081
                                          buf, buf_size);
1082
    } else if (avctx->pix_fmt == AV_PIX_FMT_BGR24) {
1083
        return flic_decode_frame_24BPP(avctx, data, got_frame,
1084
                                       buf, buf_size);
1085
    }
1086
1087
    /* Should not get  here, ever as the pix_fmt is processed */
1088
    /* in flic_decode_init and the above if should deal with */
1089
    /* the finite set of possibilities allowable by here. */
1090
    /* But in case we do, just error out. */
1091
    av_log(avctx, AV_LOG_ERROR, "Unknown FLC format, my science cannot explain how this happened.\n");
1092
    return AVERROR_BUG;
1093
}
1094
1095
1096
8
static av_cold int flic_decode_end(AVCodecContext *avctx)
1097
{
1098
8
    FlicDecodeContext *s = avctx->priv_data;
1099
1100
8
    av_frame_free(&s->frame);
1101
1102
8
    return 0;
1103
}
1104
1105
AVCodec ff_flic_decoder = {
1106
    .name           = "flic",
1107
    .long_name      = NULL_IF_CONFIG_SMALL("Autodesk Animator Flic video"),
1108
    .type           = AVMEDIA_TYPE_VIDEO,
1109
    .id             = AV_CODEC_ID_FLIC,
1110
    .priv_data_size = sizeof(FlicDecodeContext),
1111
    .init           = flic_decode_init,
1112
    .close          = flic_decode_end,
1113
    .decode         = flic_decode_frame,
1114
    .capabilities   = AV_CODEC_CAP_DR1,
1115
};