~ubuntu-branches/ubuntu/feisty/avidemux/feisty

« back to all changes in this revision

Viewing changes to avidemux/ADM_lavcodec/flicvideo.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel T Chen
  • Date: 2006-12-15 17:13:20 UTC
  • mfrom: (1.1.6 upstream)
  • Revision ID: james.westby@ubuntu.com-20061215171320-w79pvpehxx2fr217
Tags: 1:2.3.0-0.0ubuntu1
* Merge from debian-multimedia.org, remaining Ubuntu change:
  - desktop file,
  - no support for ccache and make -j.
* Closes Ubuntu: #69614.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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/RGB555/RGB565 and maybe one day RGB24
 
30
 * colorspace data, depending on the FLC. 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
#include <unistd.h>
 
41
 
 
42
#include "common.h"
 
43
#include "avcodec.h"
 
44
#include "bswap.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
#define CHECK_PIXEL_PTR(n) \
 
64
    if (pixel_ptr + n > pixel_limit) { \
 
65
        av_log (s->avctx, AV_LOG_INFO, "Problem: pixel_ptr >= pixel_limit (%d >= %d)\n", \
 
66
        pixel_ptr + n, pixel_limit); \
 
67
        return -1; \
 
68
    } \
 
69
 
 
70
typedef struct FlicDecodeContext {
 
71
    AVCodecContext *avctx;
 
72
    AVFrame frame;
 
73
 
 
74
    unsigned int palette[256];
 
75
    int new_palette;
 
76
    int fli_type;  /* either 0xAF11 or 0xAF12, affects palette resolution */
 
77
} FlicDecodeContext;
 
78
 
 
79
static int flic_decode_init(AVCodecContext *avctx)
 
80
{
 
81
    FlicDecodeContext *s = (FlicDecodeContext *)avctx->priv_data;
 
82
    unsigned char *fli_header = (unsigned char *)avctx->extradata;
 
83
    int depth;
 
84
 
 
85
    s->avctx = avctx;
 
86
    avctx->has_b_frames = 0;
 
87
 
 
88
    s->fli_type = LE_16(&fli_header[4]); /* Might be overridden if a Magic Carpet FLC */
 
89
    depth       = LE_16(&fli_header[12]);
 
90
 
 
91
    if (depth == 0) {
 
92
      depth = 8; /* Some FLC generators set depth to zero, when they mean 8Bpp. Fix up here */
 
93
    }
 
94
 
 
95
    if (s->avctx->extradata_size == 12) {
 
96
        /* special case for magic carpet FLIs */
 
97
        s->fli_type = FLC_MAGIC_CARPET_SYNTHETIC_TYPE_CODE;
 
98
    } else if (s->avctx->extradata_size != 128) {
 
99
        av_log(avctx, AV_LOG_ERROR, "Expected extradata of 12 or 128 bytes\n");
 
100
        return -1;
 
101
    }
 
102
 
 
103
    if ((s->fli_type == FLC_FLX_TYPE_CODE) && (depth == 16)) {
 
104
        depth = 15; /* Original Autodesk FLX's say the depth is 16Bpp when it is really 15Bpp */
 
105
    }
 
106
 
 
107
    switch (depth) {
 
108
        case 8  : avctx->pix_fmt = PIX_FMT_PAL8; break;
 
109
        case 15 : avctx->pix_fmt = PIX_FMT_RGB555; break;
 
110
        case 16 : avctx->pix_fmt = PIX_FMT_RGB565; break;
 
111
        case 24 : avctx->pix_fmt = PIX_FMT_BGR24; /* Supposedly BGR, but havent any files to test with */
 
112
                  av_log(avctx, AV_LOG_ERROR, "24Bpp FLC/FLX is unsupported due to no test files.\n");
 
113
                  return -1;
 
114
                  break;
 
115
        default :
 
116
                  av_log(avctx, AV_LOG_ERROR, "Unkown FLC/FLX depth of %d Bpp is unsupported.\n",depth);
 
117
                  return -1;
 
118
    }
 
119
 
 
120
    s->frame.data[0] = NULL;
 
121
    s->new_palette = 0;
 
122
 
 
123
    return 0;
 
124
}
 
125
 
 
126
static int flic_decode_frame_8BPP(AVCodecContext *avctx,
 
127
                                  void *data, int *data_size,
 
128
                                  uint8_t *buf, int buf_size)
 
129
{
 
130
    FlicDecodeContext *s = (FlicDecodeContext *)avctx->priv_data;
 
131
 
 
132
    int stream_ptr = 0;
 
133
    int stream_ptr_after_color_chunk;
 
134
    int pixel_ptr;
 
135
    int palette_ptr;
 
136
    unsigned char palette_idx1;
 
137
    unsigned char palette_idx2;
 
138
 
 
139
    unsigned int frame_size;
 
140
    int num_chunks;
 
141
 
 
142
    unsigned int chunk_size;
 
143
    int chunk_type;
 
144
 
 
145
    int i, j;
 
146
 
 
147
    int color_packets;
 
148
    int color_changes;
 
149
    int color_shift;
 
150
    unsigned char r, g, b;
 
151
 
 
152
    int lines;
 
153
    int compressed_lines;
 
154
    int starting_line;
 
155
    signed short line_packets;
 
156
    int y_ptr;
 
157
    signed char byte_run;
 
158
    int pixel_skip;
 
159
    int pixel_countdown;
 
160
    unsigned char *pixels;
 
161
    int pixel_limit;
 
162
 
 
163
    s->frame.reference = 1;
 
164
    s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE;
 
165
    if (avctx->reget_buffer(avctx, &s->frame) < 0) {
 
166
        av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
 
167
        return -1;
 
168
    }
 
169
 
 
170
    pixels = s->frame.data[0];
 
171
    pixel_limit = s->avctx->height * s->frame.linesize[0];
 
172
 
 
173
    frame_size = LE_32(&buf[stream_ptr]);
 
174
    stream_ptr += 6;  /* skip the magic number */
 
175
    num_chunks = LE_16(&buf[stream_ptr]);
 
176
    stream_ptr += 10;  /* skip padding */
 
177
 
 
178
    frame_size -= 16;
 
179
 
 
180
    /* iterate through the chunks */
 
181
    while ((frame_size > 0) && (num_chunks > 0)) {
 
182
        chunk_size = LE_32(&buf[stream_ptr]);
 
183
        stream_ptr += 4;
 
184
        chunk_type = LE_16(&buf[stream_ptr]);
 
185
        stream_ptr += 2;
 
186
 
 
187
        switch (chunk_type) {
 
188
        case FLI_256_COLOR:
 
189
        case FLI_COLOR:
 
190
            stream_ptr_after_color_chunk = stream_ptr + chunk_size - 6;
 
191
            s->new_palette = 1;
 
192
 
 
193
            /* check special case: If this file is from the Magic Carpet
 
194
             * game and uses 6-bit colors even though it reports 256-color
 
195
             * chunks in a 0xAF12-type file (fli_type is set to 0xAF13 during
 
196
             * initialization) */
 
197
            if ((chunk_type == FLI_256_COLOR) && (s->fli_type != FLC_MAGIC_CARPET_SYNTHETIC_TYPE_CODE))
 
198
                color_shift = 0;
 
199
            else
 
200
                color_shift = 2;
 
201
            /* set up the palette */
 
202
            color_packets = LE_16(&buf[stream_ptr]);
 
203
            stream_ptr += 2;
 
204
            palette_ptr = 0;
 
205
            for (i = 0; i < color_packets; i++) {
 
206
                /* first byte is how many colors to skip */
 
207
                palette_ptr += buf[stream_ptr++];
 
208
 
 
209
                /* next byte indicates how many entries to change */
 
210
                color_changes = buf[stream_ptr++];
 
211
 
 
212
                /* if there are 0 color changes, there are actually 256 */
 
213
                if (color_changes == 0)
 
214
                    color_changes = 256;
 
215
 
 
216
                for (j = 0; j < color_changes; j++) {
 
217
 
 
218
                    /* wrap around, for good measure */
 
219
                    if ((unsigned)palette_ptr >= 256)
 
220
                        palette_ptr = 0;
 
221
 
 
222
                    r = buf[stream_ptr++] << color_shift;
 
223
                    g = buf[stream_ptr++] << color_shift;
 
224
                    b = buf[stream_ptr++] << color_shift;
 
225
                    s->palette[palette_ptr++] = (r << 16) | (g << 8) | b;
 
226
                }
 
227
            }
 
228
 
 
229
            /* color chunks sometimes have weird 16-bit alignment issues;
 
230
             * therefore, take the hardline approach and set the stream_ptr
 
231
             * to the value calculated w.r.t. the size specified by the color
 
232
             * chunk header */
 
233
            stream_ptr = stream_ptr_after_color_chunk;
 
234
 
 
235
            break;
 
236
 
 
237
        case FLI_DELTA:
 
238
            y_ptr = 0;
 
239
            compressed_lines = LE_16(&buf[stream_ptr]);
 
240
            stream_ptr += 2;
 
241
            while (compressed_lines > 0) {
 
242
                line_packets = LE_16(&buf[stream_ptr]);
 
243
                stream_ptr += 2;
 
244
                if (line_packets < 0) {
 
245
                    line_packets = -line_packets;
 
246
                    y_ptr += line_packets * s->frame.linesize[0];
 
247
                } else {
 
248
                    compressed_lines--;
 
249
                    pixel_ptr = y_ptr;
 
250
                    pixel_countdown = s->avctx->width;
 
251
                    for (i = 0; i < line_packets; i++) {
 
252
                        /* account for the skip bytes */
 
253
                        pixel_skip = buf[stream_ptr++];
 
254
                        pixel_ptr += pixel_skip;
 
255
                        pixel_countdown -= pixel_skip;
 
256
                        byte_run = buf[stream_ptr++];
 
257
                        if (byte_run < 0) {
 
258
                            byte_run = -byte_run;
 
259
                            palette_idx1 = buf[stream_ptr++];
 
260
                            palette_idx2 = buf[stream_ptr++];
 
261
                            CHECK_PIXEL_PTR(byte_run);
 
262
                            for (j = 0; j < byte_run; j++, pixel_countdown -= 2) {
 
263
                                pixels[pixel_ptr++] = palette_idx1;
 
264
                                pixels[pixel_ptr++] = palette_idx2;
 
265
                            }
 
266
                        } else {
 
267
                            CHECK_PIXEL_PTR(byte_run * 2);
 
268
                            for (j = 0; j < byte_run * 2; j++, pixel_countdown--) {
 
269
                                palette_idx1 = buf[stream_ptr++];
 
270
                                pixels[pixel_ptr++] = palette_idx1;
 
271
                            }
 
272
                        }
 
273
                    }
 
274
 
 
275
                    y_ptr += s->frame.linesize[0];
 
276
                }
 
277
            }
 
278
            break;
 
279
 
 
280
        case FLI_LC:
 
281
            /* line compressed */
 
282
            starting_line = LE_16(&buf[stream_ptr]);
 
283
            stream_ptr += 2;
 
284
            y_ptr = 0;
 
285
            y_ptr += starting_line * s->frame.linesize[0];
 
286
 
 
287
            compressed_lines = LE_16(&buf[stream_ptr]);
 
288
            stream_ptr += 2;
 
289
            while (compressed_lines > 0) {
 
290
                pixel_ptr = y_ptr;
 
291
                pixel_countdown = s->avctx->width;
 
292
                line_packets = buf[stream_ptr++];
 
293
                if (line_packets > 0) {
 
294
                    for (i = 0; i < line_packets; i++) {
 
295
                        /* account for the skip bytes */
 
296
                        pixel_skip = buf[stream_ptr++];
 
297
                        pixel_ptr += pixel_skip;
 
298
                        pixel_countdown -= pixel_skip;
 
299
                        byte_run = buf[stream_ptr++];
 
300
                        if (byte_run > 0) {
 
301
                            CHECK_PIXEL_PTR(byte_run);
 
302
                            for (j = 0; j < byte_run; j++, pixel_countdown--) {
 
303
                                palette_idx1 = buf[stream_ptr++];
 
304
                                pixels[pixel_ptr++] = palette_idx1;
 
305
                            }
 
306
                        } else {
 
307
                            byte_run = -byte_run;
 
308
                            palette_idx1 = buf[stream_ptr++];
 
309
                            CHECK_PIXEL_PTR(byte_run);
 
310
                            for (j = 0; j < byte_run; j++, pixel_countdown--) {
 
311
                                pixels[pixel_ptr++] = palette_idx1;
 
312
                            }
 
313
                        }
 
314
                    }
 
315
                }
 
316
 
 
317
                y_ptr += s->frame.linesize[0];
 
318
                compressed_lines--;
 
319
            }
 
320
            break;
 
321
 
 
322
        case FLI_BLACK:
 
323
            /* set the whole frame to color 0 (which is usually black) */
 
324
            memset(pixels, 0,
 
325
                s->frame.linesize[0] * s->avctx->height);
 
326
            break;
 
327
 
 
328
        case FLI_BRUN:
 
329
            /* Byte run compression: This chunk type only occurs in the first
 
330
             * FLI frame and it will update the entire frame. */
 
331
            y_ptr = 0;
 
332
            for (lines = 0; lines < s->avctx->height; lines++) {
 
333
                pixel_ptr = y_ptr;
 
334
                /* disregard the line packets; instead, iterate through all
 
335
                 * pixels on a row */
 
336
                stream_ptr++;
 
337
                pixel_countdown = s->avctx->width;
 
338
                while (pixel_countdown > 0) {
 
339
                    byte_run = buf[stream_ptr++];
 
340
                    if (byte_run > 0) {
 
341
                        palette_idx1 = buf[stream_ptr++];
 
342
                        CHECK_PIXEL_PTR(byte_run);
 
343
                        for (j = 0; j < byte_run; j++) {
 
344
                            pixels[pixel_ptr++] = palette_idx1;
 
345
                            pixel_countdown--;
 
346
                            if (pixel_countdown < 0)
 
347
                                av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d)\n",
 
348
                                       pixel_countdown);
 
349
                        }
 
350
                    } else {  /* copy bytes if byte_run < 0 */
 
351
                        byte_run = -byte_run;
 
352
                        CHECK_PIXEL_PTR(byte_run);
 
353
                        for (j = 0; j < byte_run; j++) {
 
354
                            palette_idx1 = buf[stream_ptr++];
 
355
                            pixels[pixel_ptr++] = palette_idx1;
 
356
                            pixel_countdown--;
 
357
                            if (pixel_countdown < 0)
 
358
                                av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d)\n",
 
359
                                       pixel_countdown);
 
360
                        }
 
361
                    }
 
362
                }
 
363
 
 
364
                y_ptr += s->frame.linesize[0];
 
365
            }
 
366
            break;
 
367
 
 
368
        case FLI_COPY:
 
369
            /* copy the chunk (uncompressed frame) */
 
370
            if (chunk_size - 6 > s->avctx->width * s->avctx->height) {
 
371
                av_log(avctx, AV_LOG_ERROR, "In chunk FLI_COPY : source data (%d bytes) " \
 
372
                       "bigger than image, skipping chunk\n", chunk_size - 6);
 
373
                stream_ptr += chunk_size - 6;
 
374
            } else {
 
375
                for (y_ptr = 0; y_ptr < s->frame.linesize[0] * s->avctx->height;
 
376
                     y_ptr += s->frame.linesize[0]) {
 
377
                    memcpy(&pixels[y_ptr], &buf[stream_ptr],
 
378
                        s->avctx->width);
 
379
                    stream_ptr += s->avctx->width;
 
380
                }
 
381
            }
 
382
            break;
 
383
 
 
384
        case FLI_MINI:
 
385
            /* some sort of a thumbnail? disregard this chunk... */
 
386
            stream_ptr += chunk_size - 6;
 
387
            break;
 
388
 
 
389
        default:
 
390
            av_log(avctx, AV_LOG_ERROR, "Unrecognized chunk type: %d\n", chunk_type);
 
391
            break;
 
392
        }
 
393
 
 
394
        frame_size -= chunk_size;
 
395
        num_chunks--;
 
396
    }
 
397
 
 
398
    /* by the end of the chunk, the stream ptr should equal the frame
 
399
     * size (minus 1, possibly); if it doesn't, issue a warning */
 
400
    if ((stream_ptr != buf_size) && (stream_ptr != buf_size - 1))
 
401
        av_log(avctx, AV_LOG_ERROR, "Processed FLI chunk where chunk size = %d " \
 
402
               "and final chunk ptr = %d\n", buf_size, stream_ptr);
 
403
 
 
404
    /* make the palette available on the way out */
 
405
//    if (s->new_palette) {
 
406
    if (1) {
 
407
        memcpy(s->frame.data[1], s->palette, AVPALETTE_SIZE);
 
408
        s->frame.palette_has_changed = 1;
 
409
        s->new_palette = 0;
 
410
    }
 
411
 
 
412
    *data_size=sizeof(AVFrame);
 
413
    *(AVFrame*)data = s->frame;
 
414
 
 
415
    return buf_size;
 
416
}
 
417
 
 
418
static int flic_decode_frame_15_16BPP(AVCodecContext *avctx,
 
419
                                      void *data, int *data_size,
 
420
                                      uint8_t *buf, int buf_size)
 
421
{
 
422
    /* Note, the only difference between the 15Bpp and 16Bpp */
 
423
    /* Format is the pixel format, the packets are processed the same. */
 
424
    FlicDecodeContext *s = (FlicDecodeContext *)avctx->priv_data;
 
425
 
 
426
    int stream_ptr = 0;
 
427
    int pixel_ptr;
 
428
    unsigned char palette_idx1;
 
429
 
 
430
    unsigned int frame_size;
 
431
    int num_chunks;
 
432
 
 
433
    unsigned int chunk_size;
 
434
    int chunk_type;
 
435
 
 
436
    int i, j;
 
437
 
 
438
    int lines;
 
439
    int compressed_lines;
 
440
    signed short line_packets;
 
441
    int y_ptr;
 
442
    signed char byte_run;
 
443
    int pixel_skip;
 
444
    int pixel_countdown;
 
445
    unsigned char *pixels;
 
446
    int pixel;
 
447
    int pixel_limit;
 
448
 
 
449
    s->frame.reference = 1;
 
450
    s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE;
 
451
    if (avctx->reget_buffer(avctx, &s->frame) < 0) {
 
452
        av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
 
453
        return -1;
 
454
    }
 
455
 
 
456
    pixels = s->frame.data[0];
 
457
    pixel_limit = s->avctx->height * s->frame.linesize[0];
 
458
 
 
459
    frame_size = LE_32(&buf[stream_ptr]);
 
460
    stream_ptr += 6;  /* skip the magic number */
 
461
    num_chunks = LE_16(&buf[stream_ptr]);
 
462
    stream_ptr += 10;  /* skip padding */
 
463
 
 
464
    frame_size -= 16;
 
465
 
 
466
    /* iterate through the chunks */
 
467
    while ((frame_size > 0) && (num_chunks > 0)) {
 
468
        chunk_size = LE_32(&buf[stream_ptr]);
 
469
        stream_ptr += 4;
 
470
        chunk_type = LE_16(&buf[stream_ptr]);
 
471
        stream_ptr += 2;
 
472
 
 
473
        switch (chunk_type) {
 
474
        case FLI_256_COLOR:
 
475
        case FLI_COLOR:
 
476
            /* For some reason, it seems that non-paletised flics do include one of these */
 
477
            /* chunks in their first frame.  Why i do not know, it seems rather extraneous */
 
478
/*            av_log(avctx, AV_LOG_ERROR, "Unexpected Palette chunk %d in non-paletised FLC\n",chunk_type);*/
 
479
            stream_ptr = stream_ptr + chunk_size - 6;
 
480
            break;
 
481
 
 
482
        case FLI_DELTA:
 
483
        case FLI_DTA_LC:
 
484
            y_ptr = 0;
 
485
            compressed_lines = LE_16(&buf[stream_ptr]);
 
486
            stream_ptr += 2;
 
487
            while (compressed_lines > 0) {
 
488
                line_packets = LE_16(&buf[stream_ptr]);
 
489
                stream_ptr += 2;
 
490
                if (line_packets < 0) {
 
491
                    line_packets = -line_packets;
 
492
                    y_ptr += line_packets * s->frame.linesize[0];
 
493
                } else {
 
494
                    compressed_lines--;
 
495
                    pixel_ptr = y_ptr;
 
496
                    pixel_countdown = s->avctx->width;
 
497
                    for (i = 0; i < line_packets; i++) {
 
498
                        /* account for the skip bytes */
 
499
                        pixel_skip = buf[stream_ptr++];
 
500
                        pixel_ptr += (pixel_skip*2); /* Pixel is 2 bytes wide */
 
501
                        pixel_countdown -= pixel_skip;
 
502
                        byte_run = buf[stream_ptr++];
 
503
                        if (byte_run < 0) {
 
504
                            byte_run = -byte_run;
 
505
                            pixel    = LE_16(&buf[stream_ptr]);
 
506
                            stream_ptr += 2;
 
507
                            CHECK_PIXEL_PTR(byte_run);
 
508
                            for (j = 0; j < byte_run; j++, pixel_countdown -= 2) {
 
509
                                *((signed short*)(&pixels[pixel_ptr])) = pixel;
 
510
                                pixel_ptr += 2;
 
511
                            }
 
512
                        } else {
 
513
                            CHECK_PIXEL_PTR(byte_run);
 
514
                            for (j = 0; j < byte_run; j++, pixel_countdown--) {
 
515
                                *((signed short*)(&pixels[pixel_ptr])) = LE_16(&buf[stream_ptr]);
 
516
                                stream_ptr += 2;
 
517
                                pixel_ptr += 2;
 
518
                            }
 
519
                        }
 
520
                    }
 
521
 
 
522
                    y_ptr += s->frame.linesize[0];
 
523
                }
 
524
            }
 
525
            break;
 
526
 
 
527
        case FLI_LC:
 
528
            av_log(avctx, AV_LOG_ERROR, "Unexpected FLI_LC chunk in non-paletised FLC\n");
 
529
            stream_ptr = stream_ptr + chunk_size - 6;
 
530
            break;
 
531
 
 
532
        case FLI_BLACK:
 
533
            /* set the whole frame to 0x0000 which is balck in both 15Bpp and 16Bpp modes. */
 
534
            memset(pixels, 0x0000,
 
535
                   s->frame.linesize[0] * s->avctx->height * 2);
 
536
            break;
 
537
 
 
538
        case FLI_BRUN:
 
539
            y_ptr = 0;
 
540
            for (lines = 0; lines < s->avctx->height; lines++) {
 
541
                pixel_ptr = y_ptr;
 
542
                /* disregard the line packets; instead, iterate through all
 
543
                 * pixels on a row */
 
544
                stream_ptr++;
 
545
                pixel_countdown = (s->avctx->width * 2);
 
546
 
 
547
                while (pixel_countdown > 0) {
 
548
                    byte_run = buf[stream_ptr++];
 
549
                    if (byte_run > 0) {
 
550
                        palette_idx1 = buf[stream_ptr++];
 
551
                        CHECK_PIXEL_PTR(byte_run);
 
552
                        for (j = 0; j < byte_run; j++) {
 
553
                            pixels[pixel_ptr++] = palette_idx1;
 
554
                            pixel_countdown--;
 
555
                            if (pixel_countdown < 0)
 
556
                                av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d)\n",
 
557
                                       pixel_countdown);
 
558
                        }
 
559
                    } else {  /* copy bytes if byte_run < 0 */
 
560
                        byte_run = -byte_run;
 
561
                        CHECK_PIXEL_PTR(byte_run);
 
562
                        for (j = 0; j < byte_run; j++) {
 
563
                            palette_idx1 = buf[stream_ptr++];
 
564
                            pixels[pixel_ptr++] = palette_idx1;
 
565
                            pixel_countdown--;
 
566
                            if (pixel_countdown < 0)
 
567
                                av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d)\n",
 
568
                                       pixel_countdown);
 
569
                        }
 
570
                    }
 
571
                }
 
572
 
 
573
                /* Now FLX is strange, in that it is "byte" as opposed to "pixel" run length compressed.
 
574
                 * This doesnt give us any good oportunity to perform word endian conversion
 
575
                 * during decompression. So if its requried (ie, this isnt a LE target, we do
 
576
                 * a second pass over the line here, swapping the bytes.
 
577
                 */
 
578
                pixel = 0xFF00;
 
579
                if (0xFF00 != LE_16(&pixel)) /* Check if its not an LE Target */
 
580
                {
 
581
                  pixel_ptr = y_ptr;
 
582
                  pixel_countdown = s->avctx->width;
 
583
                  while (pixel_countdown > 0) {
 
584
                    *((signed short*)(&pixels[pixel_ptr])) = LE_16(&buf[pixel_ptr]);
 
585
                    pixel_ptr += 2;
 
586
                  }
 
587
                }
 
588
                y_ptr += s->frame.linesize[0];
 
589
            }
 
590
            break;
 
591
 
 
592
        case FLI_DTA_BRUN:
 
593
            y_ptr = 0;
 
594
            for (lines = 0; lines < s->avctx->height; lines++) {
 
595
                pixel_ptr = y_ptr;
 
596
                /* disregard the line packets; instead, iterate through all
 
597
                 * pixels on a row */
 
598
                stream_ptr++;
 
599
                pixel_countdown = s->avctx->width; /* Width is in pixels, not bytes */
 
600
 
 
601
                while (pixel_countdown > 0) {
 
602
                    byte_run = buf[stream_ptr++];
 
603
                    if (byte_run > 0) {
 
604
                        pixel    = LE_16(&buf[stream_ptr]);
 
605
                        stream_ptr += 2;
 
606
                        CHECK_PIXEL_PTR(byte_run);
 
607
                        for (j = 0; j < byte_run; j++) {
 
608
                            *((signed short*)(&pixels[pixel_ptr])) = pixel;
 
609
                            pixel_ptr += 2;
 
610
                            pixel_countdown--;
 
611
                            if (pixel_countdown < 0)
 
612
                                av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d)\n",
 
613
                                       pixel_countdown);
 
614
                        }
 
615
                    } else {  /* copy pixels if byte_run < 0 */
 
616
                        byte_run = -byte_run;
 
617
                        CHECK_PIXEL_PTR(byte_run);
 
618
                        for (j = 0; j < byte_run; j++) {
 
619
                            *((signed short*)(&pixels[pixel_ptr])) = LE_16(&buf[stream_ptr]);
 
620
                            stream_ptr += 2;
 
621
                            pixel_ptr  += 2;
 
622
                            pixel_countdown--;
 
623
                            if (pixel_countdown < 0)
 
624
                                av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d)\n",
 
625
                                       pixel_countdown);
 
626
                        }
 
627
                    }
 
628
                }
 
629
 
 
630
                y_ptr += s->frame.linesize[0];
 
631
            }
 
632
            break;
 
633
 
 
634
        case FLI_COPY:
 
635
        case FLI_DTA_COPY:
 
636
            /* copy the chunk (uncompressed frame) */
 
637
            if (chunk_size - 6 > (unsigned int)(s->avctx->width * s->avctx->height)*2) {
 
638
                av_log(avctx, AV_LOG_ERROR, "In chunk FLI_COPY : source data (%d bytes) " \
 
639
                       "bigger than image, skipping chunk\n", chunk_size - 6);
 
640
                stream_ptr += chunk_size - 6;
 
641
            } else {
 
642
 
 
643
                for (y_ptr = 0; y_ptr < s->frame.linesize[0] * s->avctx->height;
 
644
                     y_ptr += s->frame.linesize[0]) {
 
645
 
 
646
                    pixel_countdown = s->avctx->width;
 
647
                    pixel_ptr = 0;
 
648
                    while (pixel_countdown > 0) {
 
649
                      *((signed short*)(&pixels[y_ptr + pixel_ptr])) = LE_16(&buf[stream_ptr+pixel_ptr]);
 
650
                      pixel_ptr += 2;
 
651
                      pixel_countdown--;
 
652
                    }
 
653
                    stream_ptr += s->avctx->width*2;
 
654
                }
 
655
            }
 
656
            break;
 
657
 
 
658
        case FLI_MINI:
 
659
            /* some sort of a thumbnail? disregard this chunk... */
 
660
            stream_ptr += chunk_size - 6;
 
661
            break;
 
662
 
 
663
        default:
 
664
            av_log(avctx, AV_LOG_ERROR, "Unrecognized chunk type: %d\n", chunk_type);
 
665
            break;
 
666
        }
 
667
 
 
668
        frame_size -= chunk_size;
 
669
        num_chunks--;
 
670
    }
 
671
 
 
672
    /* by the end of the chunk, the stream ptr should equal the frame
 
673
     * size (minus 1, possibly); if it doesn't, issue a warning */
 
674
    if ((stream_ptr != buf_size) && (stream_ptr != buf_size - 1))
 
675
        av_log(avctx, AV_LOG_ERROR, "Processed FLI chunk where chunk size = %d " \
 
676
               "and final chunk ptr = %d\n", buf_size, stream_ptr);
 
677
 
 
678
 
 
679
    *data_size=sizeof(AVFrame);
 
680
    *(AVFrame*)data = s->frame;
 
681
 
 
682
    return buf_size;
 
683
}
 
684
 
 
685
static int flic_decode_frame_24BPP(AVCodecContext *avctx,
 
686
                                   void *data, int *data_size,
 
687
                                   uint8_t *buf, int buf_size)
 
688
{
 
689
  av_log(avctx, AV_LOG_ERROR, "24Bpp FLC Unsupported due to lack of test files.\n");
 
690
  return -1;
 
691
}
 
692
 
 
693
static int flic_decode_frame(AVCodecContext *avctx,
 
694
                             void *data, int *data_size,
 
695
                             uint8_t *buf, int buf_size)
 
696
{
 
697
    if (avctx->pix_fmt == PIX_FMT_PAL8) {
 
698
      return flic_decode_frame_8BPP(avctx, data, data_size,
 
699
                                    buf, buf_size);
 
700
    }
 
701
    else if ((avctx->pix_fmt == PIX_FMT_RGB555) ||
 
702
             (avctx->pix_fmt == PIX_FMT_RGB565)) {
 
703
      return flic_decode_frame_15_16BPP(avctx, data, data_size,
 
704
                                        buf, buf_size);
 
705
    }
 
706
    else if (avctx->pix_fmt == PIX_FMT_BGR24) {
 
707
      return flic_decode_frame_24BPP(avctx, data, data_size,
 
708
                                     buf, buf_size);
 
709
    }
 
710
 
 
711
    /* Shouldnt get  here, ever as the pix_fmt is processed */
 
712
    /* in flic_decode_init and the above if should deal with */
 
713
    /* the finite set of possibilites allowable by here. */
 
714
    /* but in case we do, just error out. */
 
715
    av_log(avctx, AV_LOG_ERROR, "Unknown Format of FLC. My Science cant explain how this happened\n");
 
716
    return -1;
 
717
}
 
718
 
 
719
 
 
720
static int flic_decode_end(AVCodecContext *avctx)
 
721
{
 
722
    FlicDecodeContext *s = avctx->priv_data;
 
723
 
 
724
    if (s->frame.data[0])
 
725
        avctx->release_buffer(avctx, &s->frame);
 
726
 
 
727
    return 0;
 
728
}
 
729
 
 
730
AVCodec flic_decoder = {
 
731
    "flic",
 
732
    CODEC_TYPE_VIDEO,
 
733
    CODEC_ID_FLIC,
 
734
    sizeof(FlicDecodeContext),
 
735
    flic_decode_init,
 
736
    NULL,
 
737
    flic_decode_end,
 
738
    flic_decode_frame,
 
739
    CODEC_CAP_DR1,
 
740
    NULL,
 
741
    NULL,
 
742
    NULL,
 
743
    NULL
 
744
};