ffmpeg / libavcodec / flicvideo.c @ 5509bffa
History | View | Annotate | Download (27.4 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., 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 |
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 |
}; |