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