Statistics
| Branch: | Revision:

ffmpeg / libavcodec / flicvideo.c @ e40f5d3c

History | View | Annotate | Download (13.7 KB)

1
/*
2
 * FLI/FLC Animation Video Decoder
3
 * Copyright (C) 2003, 2004 the ffmpeg project
4
 *
5
 * This library is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU Lesser General Public
7
 * License as published by the Free Software Foundation; either
8
 * version 2 of the License, or (at your option) any later version.
9
 *
10
 * This library is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
 * Lesser General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU Lesser General Public
16
 * License along with this library; if not, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
 *
19
 */
20

    
21
/**
22
 * @file flic.c
23
 * Autodesk Animator FLI/FLC Video Decoder
24
 * by Mike Melanson (melanson@pcisys.net)
25
 * for more information on the .fli/.flc file format and all of its many
26
 * variations, visit:
27
 *   http://www.compuphase.com/flic.htm
28
 *
29
 * This decoder outputs PAL8 colorspace data. To use this decoder, be
30
 * sure that your demuxer sends the FLI file header to the decoder via
31
 * the extradata chunk in AVCodecContext. The chunk should be 128 bytes
32
 * large. The only exception is for FLI files from the game "Magic Carpet",
33
 * in which the header is only 12 bytes.
34
 */
35

    
36
#include <stdio.h>
37
#include <stdlib.h>
38
#include <string.h>
39
#include <unistd.h>
40

    
41
#include "common.h"
42
#include "avcodec.h"
43
#include "bswap.h"
44

    
45
#define FLI_256_COLOR 4
46
#define FLI_DELTA     7
47
#define FLI_COLOR     11
48
#define FLI_LC        12
49
#define FLI_BLACK     13
50
#define FLI_BRUN      15
51
#define FLI_COPY      16
52
#define FLI_MINI      18
53

    
54
#define LE_16(x)  ((((uint8_t*)(x))[1] << 8) | ((uint8_t*)(x))[0])
55
#define LE_32(x)  ((((uint8_t*)(x))[3] << 24) | \
56
                   (((uint8_t*)(x))[2] << 16) | \
57
                   (((uint8_t*)(x))[1] << 8) | \
58
                    ((uint8_t*)(x))[0])
59

    
60
typedef struct FlicDecodeContext {
61
    AVCodecContext *avctx;
62
    AVFrame frame;
63

    
64
    unsigned int palette[256];
65
    int new_palette;
66
    int fli_type;  /* either 0xAF11 or 0xAF12, affects palette resolution */
67
} FlicDecodeContext;
68

    
69
static int flic_decode_init(AVCodecContext *avctx)
70
{
71
    FlicDecodeContext *s = (FlicDecodeContext *)avctx->priv_data;
72
    unsigned char *fli_header = (unsigned char *)avctx->extradata;
73

    
74
    s->avctx = avctx;
75
    avctx->pix_fmt = PIX_FMT_PAL8;
76
    avctx->has_b_frames = 0;
77

    
78
    if (s->avctx->extradata_size == 12) {
79
        /* special case for magic carpet FLIs */
80
        s->fli_type = 0xAF13;
81
    } else if (s->avctx->extradata_size == 128) {
82
        s->fli_type = LE_16(&fli_header[4]);
83
    } else {
84
        av_log(avctx, AV_LOG_ERROR, "Expected extradata of 12 or 128 bytes\n");
85
        return -1;
86
    }
87

    
88
    s->frame.data[0] = NULL;
89
    s->new_palette = 0;
90

    
91
    return 0;
92
}
93

    
94
static int flic_decode_frame(AVCodecContext *avctx,
95
                             void *data, int *data_size,
96
                             uint8_t *buf, int buf_size)
97
{
98
    FlicDecodeContext *s = (FlicDecodeContext *)avctx->priv_data;
99

    
100
    int stream_ptr = 0;
101
    int stream_ptr_after_color_chunk;
102
    int pixel_ptr;
103
    int palette_ptr;
104
    unsigned char palette_idx1;
105
    unsigned char palette_idx2;
106

    
107
    unsigned int frame_size;
108
    int num_chunks;
109

    
110
    unsigned int chunk_size;
111
    int chunk_type;
112

    
113
    int i, j;
114

    
115
    int color_packets;
116
    int color_changes;
117
    int color_shift;
118
    unsigned char r, g, b;
119

    
120
    int lines;
121
    int compressed_lines;
122
    int starting_line;
123
    signed short line_packets;
124
    int y_ptr;
125
    signed char byte_run;
126
    int pixel_skip;
127
    int pixel_countdown;
128
    unsigned char *pixels;
129

    
130
    s->frame.reference = 1;
131
    s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE;
132
    if (avctx->reget_buffer(avctx, &s->frame) < 0) {
133
        av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
134
        return -1;
135
    }
136

    
137
    pixels = s->frame.data[0];
138

    
139
    frame_size = LE_32(&buf[stream_ptr]);
140
    stream_ptr += 6;  /* skip the magic number */
141
    num_chunks = LE_16(&buf[stream_ptr]);
142
    stream_ptr += 10;  /* skip padding */
143

    
144
    frame_size -= 16;
145

    
146
    /* iterate through the chunks */
147
    while ((frame_size > 0) && (num_chunks > 0)) {
148
        chunk_size = LE_32(&buf[stream_ptr]);
149
        stream_ptr += 4;
150
        chunk_type = LE_16(&buf[stream_ptr]);
151
        stream_ptr += 2;
152

    
153
        switch (chunk_type) {
154
        case FLI_256_COLOR:
155
        case FLI_COLOR:
156
            stream_ptr_after_color_chunk = stream_ptr + chunk_size - 6;
157
            s->new_palette = 1;
158

    
159
            /* check special case: If this file is from the Magic Carpet 
160
             * game and uses 6-bit colors even though it reports 256-color 
161
             * chunks in a 0xAF12-type file (fli_type is set to 0xAF13 during
162
             * initialization) */
163
            if ((chunk_type == FLI_256_COLOR) && (s->fli_type != 0xAF13))
164
                color_shift = 0;
165
            else
166
                color_shift = 2;
167
            /* set up the palette */
168
            color_packets = LE_16(&buf[stream_ptr]);
169
            stream_ptr += 2;
170
            palette_ptr = 0;
171
            for (i = 0; i < color_packets; i++) {
172
                /* first byte is how many colors to skip */
173
                palette_ptr += buf[stream_ptr++];
174

    
175
                /* next byte indicates how many entries to change */
176
                color_changes = buf[stream_ptr++];
177

    
178
                /* if there are 0 color changes, there are actually 256 */
179
                if (color_changes == 0)
180
                    color_changes = 256;
181

    
182
                for (j = 0; j < color_changes; j++) {
183

    
184
                    /* wrap around, for good measure */
185
                    if (palette_ptr >= 256)
186
                        palette_ptr = 0;
187

    
188
                    r = buf[stream_ptr++] << color_shift;
189
                    g = buf[stream_ptr++] << color_shift;
190
                    b = buf[stream_ptr++] << color_shift;
191
                    s->palette[palette_ptr++] = (r << 16) | (g << 8) | b;
192
                }
193
            }
194

    
195
            /* color chunks sometimes have weird 16-bit alignment issues;
196
             * therefore, take the hardline approach and set the stream_ptr
197
             * to the value calculated w.r.t. the size specified by the color
198
             * chunk header */
199
            stream_ptr = stream_ptr_after_color_chunk;
200

    
201
            break;
202

    
203
        case FLI_DELTA:
204
            y_ptr = 0;
205
            compressed_lines = LE_16(&buf[stream_ptr]);
206
            stream_ptr += 2;
207
            while (compressed_lines > 0) {
208
                line_packets = LE_16(&buf[stream_ptr]);
209
                stream_ptr += 2;
210
                if (line_packets < 0) {
211
                    line_packets = -line_packets;
212
                    y_ptr += line_packets * s->frame.linesize[0];
213
                } else {
214
                    compressed_lines--;
215
                    pixel_ptr = y_ptr;
216
                    pixel_countdown = s->avctx->width;
217
                    for (i = 0; i < line_packets; i++) {
218
                        /* account for the skip bytes */
219
                        pixel_skip = buf[stream_ptr++];
220
                        pixel_ptr += pixel_skip;
221
                        pixel_countdown -= pixel_skip;
222
                        byte_run = buf[stream_ptr++];
223
                        if (byte_run < 0) {
224
                            byte_run = -byte_run;
225
                            palette_idx1 = buf[stream_ptr++];
226
                            palette_idx2 = buf[stream_ptr++];
227
                            for (j = 0; j < byte_run; j++, pixel_countdown -= 2) {
228
                                pixels[pixel_ptr++] = palette_idx1;
229
                                pixels[pixel_ptr++] = palette_idx2;
230
                            }
231
                        } else {
232
                            for (j = 0; j < byte_run * 2; j++, pixel_countdown--) {
233
                                palette_idx1 = buf[stream_ptr++];
234
                                pixels[pixel_ptr++] = palette_idx1;
235
                            }
236
                        }
237
                    }
238

    
239
                    y_ptr += s->frame.linesize[0];
240
                }
241
            }
242
            break;
243

    
244
        case FLI_LC:
245
            /* line compressed */
246
            starting_line = LE_16(&buf[stream_ptr]);
247
            stream_ptr += 2;
248
            y_ptr = 0;
249
            y_ptr += starting_line * s->frame.linesize[0];
250

    
251
            compressed_lines = LE_16(&buf[stream_ptr]);
252
            stream_ptr += 2;
253
            while (compressed_lines > 0) {
254
                pixel_ptr = y_ptr;
255
                pixel_countdown = s->avctx->width;
256
                line_packets = buf[stream_ptr++];
257
                if (line_packets > 0) {
258
                    for (i = 0; i < line_packets; i++) {
259
                        /* account for the skip bytes */
260
                        pixel_skip = buf[stream_ptr++];
261
                        pixel_ptr += pixel_skip;
262
                        pixel_countdown -= pixel_skip;
263
                        byte_run = buf[stream_ptr++];
264
                        if (byte_run > 0) {
265
                            for (j = 0; j < byte_run; j++, pixel_countdown--) {
266
                                palette_idx1 = buf[stream_ptr++];
267
                                pixels[pixel_ptr++] = palette_idx1;
268
                            }
269
                        } else {
270
                            byte_run = -byte_run;
271
                            palette_idx1 = buf[stream_ptr++];
272
                            for (j = 0; j < byte_run; j++, pixel_countdown--) {
273
                                pixels[pixel_ptr++] = palette_idx1;
274
                            }
275
                        }
276
                    }
277
                }
278

    
279
                y_ptr += s->frame.linesize[0];
280
                compressed_lines--;
281
            }
282
            break;
283

    
284
        case FLI_BLACK:
285
            /* set the whole frame to color 0 (which is usually black) */
286
            memset(pixels, 0,
287
                s->frame.linesize[0] * s->avctx->height);
288
            break;
289

    
290
        case FLI_BRUN:
291
            /* Byte run compression: This chunk type only occurs in the first
292
             * FLI frame and it will update the entire frame. */
293
            y_ptr = 0;
294
            for (lines = 0; lines < s->avctx->height; lines++) {
295
                pixel_ptr = y_ptr;
296
                /* disregard the line packets; instead, iterate through all
297
                 * pixels on a row */
298
                stream_ptr++;
299
                pixel_countdown = s->avctx->width;
300
                while (pixel_countdown > 0) {
301
                    byte_run = buf[stream_ptr++];
302
                    if (byte_run > 0) {
303
                        palette_idx1 = buf[stream_ptr++];
304
                        for (j = 0; j < byte_run; j++) {
305
                            pixels[pixel_ptr++] = palette_idx1;
306
                            pixel_countdown--;
307
                            if (pixel_countdown < 0)
308
                                av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d)\n",
309
                                       pixel_countdown);
310
                        }
311
                    } else {  /* copy bytes if byte_run < 0 */
312
                        byte_run = -byte_run;
313
                        for (j = 0; j < byte_run; j++) {
314
                            palette_idx1 = buf[stream_ptr++];
315
                            pixels[pixel_ptr++] = palette_idx1;
316
                            pixel_countdown--;
317
                            if (pixel_countdown < 0)
318
                                av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d)\n",
319
                                       pixel_countdown);
320
                        }
321
                    }
322
                }
323

    
324
                y_ptr += s->frame.linesize[0];
325
            }
326
            break;
327

    
328
        case FLI_COPY:
329
            /* copy the chunk (uncompressed frame) */
330
            if (chunk_size - 6 > s->avctx->width * s->avctx->height) {
331
                av_log(avctx, AV_LOG_ERROR, "In chunk FLI_COPY : source data (%d bytes) " \
332
                       "bigger than image, skipping chunk\n", chunk_size - 6);
333
                stream_ptr += chunk_size - 6;
334
            } else {
335
                for (y_ptr = 0; y_ptr < s->frame.linesize[0] * s->avctx->height;
336
                     y_ptr += s->frame.linesize[0]) {
337
                    memcpy(&pixels[y_ptr], &buf[stream_ptr],
338
                        s->avctx->width);
339
                    stream_ptr += s->avctx->width;
340
                }
341
            }
342
            break;
343

    
344
        case FLI_MINI:
345
            /* some sort of a thumbnail? disregard this chunk... */
346
            stream_ptr += chunk_size - 6;
347
            break;
348

    
349
        default:
350
            av_log(avctx, AV_LOG_ERROR, "Unrecognized chunk type: %d\n", chunk_type);
351
            break;
352
        }
353

    
354
        frame_size -= chunk_size;
355
        num_chunks--;
356
    }
357

    
358
    /* by the end of the chunk, the stream ptr should equal the frame
359
     * size (minus 1, possibly); if it doesn't, issue a warning */
360
    if ((stream_ptr != buf_size) && (stream_ptr != buf_size - 1))
361
        av_log(avctx, AV_LOG_ERROR, "Processed FLI chunk where chunk size = %d " \
362
               "and final chunk ptr = %d\n", buf_size, stream_ptr);
363

    
364
    /* make the palette available on the way out */
365
//    if (s->new_palette) {
366
    if (1) {
367
        memcpy(s->frame.data[1], s->palette, AVPALETTE_SIZE);
368
        s->frame.palette_has_changed = 1;
369
        s->new_palette = 0;
370
    }
371

    
372
    *data_size=sizeof(AVFrame);
373
    *(AVFrame*)data = s->frame;
374

    
375
    return buf_size;
376
}
377

    
378
static int flic_decode_end(AVCodecContext *avctx)
379
{
380
    FlicDecodeContext *s = avctx->priv_data;
381

    
382
    if (s->frame.data[0])
383
        avctx->release_buffer(avctx, &s->frame);
384

    
385
    return 0;
386
}
387

    
388
AVCodec flic_decoder = {
389
    "flic",
390
    CODEC_TYPE_VIDEO,
391
    CODEC_ID_FLIC,
392
    sizeof(FlicDecodeContext),
393
    flic_decode_init,
394
    NULL,
395
    flic_decode_end,
396
    flic_decode_frame,
397
    CODEC_CAP_DR1,
398
    NULL
399
};