FFmpeg
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 FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
22 /**
23  * @file
24  * Autodesk Animator FLI/FLC Video Decoder
25  * by Mike Melanson (melanson@pcisys.net)
26  * for more information on the .fli/.flc file format and all of its many
27  * variations, visit:
28  * http://www.compuphase.com/flic.htm
29  *
30  * This decoder outputs PAL8/RGB555/RGB565/BGR24. To use this decoder, be
31  * sure that your demuxer sends the FLI file header to the decoder via
32  * the extradata chunk in AVCodecContext. The chunk should be 128 bytes
33  * large. The only exception is for FLI files from the game "Magic Carpet",
34  * in which the header is only 12 bytes.
35  */
36 
37 #include <string.h>
38 
39 #include "libavutil/intreadwrite.h"
40 #include "avcodec.h"
41 #include "bytestream.h"
42 #include "codec_internal.h"
43 #include "decode.h"
44 #include "mathops.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 static inline int check_pixel_ptr(ptrdiff_t ptr, int n,
64  ptrdiff_t limit, int direction)
65 {
66  if (( direction && ptr + n > limit) ||
67  (!direction && ptr + n < limit))
68  return AVERROR_INVALIDDATA;
69  return 0;
70 }
71 
72 #define CHECK_PIXEL_PTR(n) \
73 { \
74  ret = check_pixel_ptr(pixel_ptr, (n), pixel_limit, direction); \
75  if (ret < 0) \
76  return ret; \
77 }
78 
79 #define CHECK_Y_PTR() \
80 { \
81  ret = check_pixel_ptr(y_ptr, 0, pixel_limit, direction); \
82  if (ret < 0) \
83  return ret; \
84 }
85 
86 typedef struct FlicDecodeContext {
89 
90  unsigned int palette[256];
92  int fli_type; /* either 0xAF11 or 0xAF12, affects palette resolution */
94 
96 {
97  FlicDecodeContext *s = avctx->priv_data;
98  uint8_t *fli_header = avctx->extradata;
99  int depth;
100 
101  if (avctx->extradata_size != 0 &&
102  avctx->extradata_size != 12 &&
103  avctx->extradata_size != 128 &&
104  avctx->extradata_size != 256 &&
105  avctx->extradata_size != 904 &&
106  avctx->extradata_size != 1024) {
107  av_log(avctx, AV_LOG_ERROR, "Unexpected extradata size %d\n", avctx->extradata_size);
108  return AVERROR_INVALIDDATA;
109  }
110 
111  s->avctx = avctx;
112 
113  if (s->avctx->extradata_size == 12) {
114  /* special case for magic carpet FLIs */
116  depth = 8;
117  } else if (avctx->extradata_size == 1024) {
118  uint8_t *ptr = avctx->extradata;
119  int i;
120 
121  for (i = 0; i < 256; i++) {
122  s->palette[i] = AV_RL32(ptr);
123  ptr += 4;
124  }
125  depth = 8;
126  /* FLI in MOV, see e.g. FFmpeg trac issue #626 */
127  } else if (avctx->extradata_size == 0 ||
128  avctx->extradata_size == 256 ||
129  /* see FFmpeg ticket #1234 */
130  avctx->extradata_size == 904) {
131  s->fli_type = FLI_TYPE_CODE;
132  depth = 8;
133  } else {
134  s->fli_type = AV_RL16(&fli_header[4]);
135  depth = AV_RL16(&fli_header[12]);
136  }
137 
138  if (depth == 0) {
139  depth = 8; /* Some FLC generators set depth to zero, when they mean 8Bpp. Fix up here */
140  }
141 
142  if ((s->fli_type == FLC_FLX_TYPE_CODE) && (depth == 16)) {
143  depth = 15; /* Original Autodesk FLX's say the depth is 16Bpp when it is really 15Bpp */
144  }
145 
146  switch (depth) {
147  case 1 : avctx->pix_fmt = AV_PIX_FMT_MONOBLACK; break;
148  case 8 : avctx->pix_fmt = AV_PIX_FMT_PAL8; break;
149  case 15 : avctx->pix_fmt = AV_PIX_FMT_RGB555; break;
150  case 16 : avctx->pix_fmt = AV_PIX_FMT_RGB565; break;
151  case 24 : avctx->pix_fmt = AV_PIX_FMT_BGR24; break;
152  default :
153  av_log(avctx, AV_LOG_ERROR, "Unknown FLC/FLX depth of %d Bpp is unsupported.\n",depth);
154  return AVERROR_INVALIDDATA;
155  }
156 
157  s->frame = av_frame_alloc();
158  if (!s->frame)
159  return AVERROR(ENOMEM);
160 
161  s->new_palette = 0;
162 
163  return 0;
164 }
165 
167  AVFrame *rframe, int *got_frame,
168  const uint8_t *buf, int buf_size)
169 {
170  FlicDecodeContext *s = avctx->priv_data;
171 
172  GetByteContext g2;
173  ptrdiff_t pixel_ptr;
174 
175  unsigned int frame_size;
176  int num_chunks;
177 
178  unsigned int chunk_size;
179  int chunk_type;
180 
181  int i, j, ret, direction;
182 
183  int lines;
184  int compressed_lines;
185  int starting_line;
186  int line_packets;
187  ptrdiff_t y_ptr;
188  int byte_run;
189  int pixel_skip;
190  int pixel_countdown;
191  unsigned char *pixels;
192  ptrdiff_t pixel_limit;
193 
194  bytestream2_init(&g2, buf, buf_size);
195 
196  if ((ret = ff_reget_buffer(avctx, s->frame, 0)) < 0)
197  return ret;
198 
199  direction = s->frame->linesize[0] > 0;
200  pixels = s->frame->data[0];
201  pixel_limit = s->avctx->height * s->frame->linesize[0];
202  if (buf_size < 16 || buf_size > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE)
203  return AVERROR_INVALIDDATA;
204  frame_size = bytestream2_get_le32(&g2);
205  if (frame_size > buf_size)
206  frame_size = buf_size;
207  bytestream2_skip(&g2, 2); /* skip the magic number */
208  num_chunks = bytestream2_get_le16(&g2);
209  bytestream2_skip(&g2, 8); /* skip padding */
210 
211  if (frame_size < 16)
212  return AVERROR_INVALIDDATA;
213 
214  frame_size -= 16;
215 
216  /* iterate through the chunks */
217  while ((frame_size >= 6) && (num_chunks > 0) &&
218  bytestream2_get_bytes_left(&g2) >= 4) {
219  int stream_ptr_after_chunk;
220  chunk_size = bytestream2_get_le32(&g2);
221  if (chunk_size > frame_size) {
222  av_log(avctx, AV_LOG_WARNING,
223  "Invalid chunk_size = %u > frame_size = %u\n", chunk_size, frame_size);
224  chunk_size = frame_size;
225  }
226  stream_ptr_after_chunk = bytestream2_tell(&g2) - 4 + chunk_size;
227 
228  chunk_type = bytestream2_get_le16(&g2);
229 
230  switch (chunk_type) {
231  case FLI_BRUN:
232  /* Byte run compression: This chunk type only occurs in the first
233  * FLI frame and it will update the entire frame. */
234  y_ptr = 0;
235  for (lines = 0; lines < s->avctx->height; lines++) {
236  pixel_ptr = y_ptr;
237  /* disregard the line packets; instead, iterate through all
238  * pixels on a row */
239  bytestream2_skip(&g2, 1);
240  pixel_countdown = (s->avctx->width + 7) >> 3;
241  while (pixel_countdown > 0) {
242  if (bytestream2_tell(&g2) + 1 > stream_ptr_after_chunk)
243  break;
244  byte_run = sign_extend(bytestream2_get_byte(&g2), 8);
245  if (!byte_run) {
246  av_log(avctx, AV_LOG_ERROR, "Invalid byte run value.\n");
247  return AVERROR_INVALIDDATA;
248  }
249 
250  if (byte_run > 0) {
251  int value = bytestream2_get_byte(&g2);
252  CHECK_PIXEL_PTR(byte_run);
253  for (j = 0; j < byte_run; j++) {
254  pixels[pixel_ptr++] = value;
255  pixel_countdown--;
256  if (pixel_countdown < 0)
257  av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d) at line %d\n",
258  pixel_countdown, lines);
259  }
260  } else { /* copy bytes if byte_run < 0 */
261  byte_run = -byte_run;
262  CHECK_PIXEL_PTR(byte_run);
263  if (bytestream2_tell(&g2) + byte_run > stream_ptr_after_chunk)
264  break;
265  for (j = 0; j < byte_run; j++) {
266  pixels[pixel_ptr++] = bytestream2_get_byte(&g2);
267  pixel_countdown--;
268  if (pixel_countdown < 0)
269  av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d) at line %d\n",
270  pixel_countdown, lines);
271  }
272  }
273  }
274 
275  y_ptr += s->frame->linesize[0];
276  }
277  break;
278 
279  case FLI_LC:
280  /* line compressed */
281  starting_line = bytestream2_get_le16(&g2);
282  if (starting_line >= s->avctx->height)
283  return AVERROR_INVALIDDATA;
284  y_ptr = 0;
285  y_ptr += starting_line * s->frame->linesize[0];
286 
287  compressed_lines = bytestream2_get_le16(&g2);
288  while (compressed_lines > 0) {
289  pixel_ptr = y_ptr;
290  CHECK_PIXEL_PTR(0);
291  pixel_countdown = (s->avctx->width + 7) >> 3;
292  if (bytestream2_tell(&g2) + 1 > stream_ptr_after_chunk)
293  break;
294  line_packets = bytestream2_get_byte(&g2);
295  if (line_packets > 0) {
296  for (i = 0; i < line_packets; i++) {
297  /* account for the skip bytes */
298  if (bytestream2_tell(&g2) + 1 > stream_ptr_after_chunk)
299  break;
300  pixel_skip = bytestream2_get_byte(&g2);
301  pixel_ptr += pixel_skip;
302  pixel_countdown -= pixel_skip;
303  byte_run = sign_extend(bytestream2_get_byte(&g2),8);
304  if (byte_run > 0) {
305  CHECK_PIXEL_PTR(byte_run);
306  if (bytestream2_tell(&g2) + byte_run > stream_ptr_after_chunk)
307  break;
308  for (j = 0; j < byte_run; j++, pixel_countdown--) {
309  pixels[pixel_ptr++] = bytestream2_get_byte(&g2);
310  }
311  } else if (byte_run < 0) {
312  int value = bytestream2_get_byte(&g2);
313  byte_run = -byte_run;
314  CHECK_PIXEL_PTR(byte_run);
315  for (j = 0; j < byte_run; j++, pixel_countdown--) {
316  pixels[pixel_ptr++] = value;
317  }
318  }
319  }
320  }
321 
322  y_ptr += s->frame->linesize[0];
323  compressed_lines--;
324  }
325  break;
326 
327  default:
328  av_log(avctx, AV_LOG_ERROR, "Unrecognized chunk type: %d\n", chunk_type);
329  break;
330  }
331 
332  if (stream_ptr_after_chunk - bytestream2_tell(&g2) >= 0) {
333  bytestream2_skip(&g2, stream_ptr_after_chunk - bytestream2_tell(&g2));
334  } else {
335  av_log(avctx, AV_LOG_ERROR, "Chunk overread\n");
336  break;
337  }
338 
339  frame_size -= chunk_size;
340  num_chunks--;
341  }
342 
343  /* by the end of the chunk, the stream ptr should equal the frame
344  * size (minus 1 or 2, possibly); if it doesn't, issue a warning */
345  if (bytestream2_get_bytes_left(&g2) > 2)
346  av_log(avctx, AV_LOG_ERROR, "Processed FLI chunk where chunk size = %d " \
347  "and final chunk ptr = %d\n", buf_size,
348  buf_size - bytestream2_get_bytes_left(&g2));
349 
350  if ((ret = av_frame_ref(rframe, s->frame)) < 0)
351  return ret;
352 
353  *got_frame = 1;
354 
355  return buf_size;
356 }
357 
359  AVFrame *rframe, int *got_frame,
360  const uint8_t *buf, int buf_size)
361 {
362  FlicDecodeContext *s = avctx->priv_data;
363 
364  GetByteContext g2;
365  ptrdiff_t pixel_ptr;
366  int palette_ptr;
367  unsigned char palette_idx1;
368  unsigned char palette_idx2;
369 
370  unsigned int frame_size;
371  int num_chunks;
372 
373  unsigned int chunk_size;
374  int chunk_type;
375 
376  int i, j, ret, direction;
377 
378  int color_packets;
379  int color_changes;
380  int color_shift;
381  unsigned char r, g, b;
382 
383  int lines;
384  int compressed_lines;
385  int starting_line;
386  int line_packets;
387  ptrdiff_t y_ptr;
388  int byte_run;
389  int pixel_skip;
390  int pixel_countdown;
391  unsigned char *pixels;
392  ptrdiff_t pixel_limit;
393 
394  bytestream2_init(&g2, buf, buf_size);
395 
396  if ((ret = ff_reget_buffer(avctx, s->frame, 0)) < 0)
397  return ret;
398 
399  direction = s->frame->linesize[0] > 0;
400  pixels = s->frame->data[0];
401  pixel_limit = s->avctx->height * s->frame->linesize[0];
402  if (buf_size < 16 || buf_size > INT_MAX - (3 * 256 + AV_INPUT_BUFFER_PADDING_SIZE))
403  return AVERROR_INVALIDDATA;
404  frame_size = bytestream2_get_le32(&g2);
405  if (frame_size > buf_size)
406  frame_size = buf_size;
407  bytestream2_skip(&g2, 2); /* skip the magic number */
408  num_chunks = bytestream2_get_le16(&g2);
409  bytestream2_skip(&g2, 8); /* skip padding */
410 
411  if (frame_size < 16)
412  return AVERROR_INVALIDDATA;
413 
414  frame_size -= 16;
415 
416  /* iterate through the chunks */
417  while ((frame_size >= 6) && (num_chunks > 0) &&
418  bytestream2_get_bytes_left(&g2) >= 4) {
419  int stream_ptr_after_chunk;
420  chunk_size = bytestream2_get_le32(&g2);
421  if (chunk_size > frame_size) {
422  av_log(avctx, AV_LOG_WARNING,
423  "Invalid chunk_size = %u > frame_size = %u\n", chunk_size, frame_size);
424  chunk_size = frame_size;
425  }
426  stream_ptr_after_chunk = bytestream2_tell(&g2) - 4 + chunk_size;
427 
428  chunk_type = bytestream2_get_le16(&g2);
429 
430  switch (chunk_type) {
431  case FLI_256_COLOR:
432  case FLI_COLOR:
433  /* check special case: If this file is from the Magic Carpet
434  * game and uses 6-bit colors even though it reports 256-color
435  * chunks in a 0xAF12-type file (fli_type is set to 0xAF13 during
436  * initialization) */
437  if ((chunk_type == FLI_256_COLOR) && (s->fli_type != FLC_MAGIC_CARPET_SYNTHETIC_TYPE_CODE))
438  color_shift = 0;
439  else
440  color_shift = 2;
441  /* set up the palette */
442  color_packets = bytestream2_get_le16(&g2);
443  palette_ptr = 0;
444  for (i = 0; i < color_packets; i++) {
445  /* first byte is how many colors to skip */
446  palette_ptr += bytestream2_get_byte(&g2);
447 
448  /* next byte indicates how many entries to change */
449  color_changes = bytestream2_get_byte(&g2);
450 
451  /* if there are 0 color changes, there are actually 256 */
452  if (color_changes == 0)
453  color_changes = 256;
454 
455  if (bytestream2_tell(&g2) + color_changes * 3 > stream_ptr_after_chunk)
456  break;
457 
458  for (j = 0; j < color_changes; j++) {
459  unsigned int entry;
460 
461  /* wrap around, for good measure */
462  if ((unsigned)palette_ptr >= 256)
463  palette_ptr = 0;
464 
465  r = bytestream2_get_byte(&g2) << color_shift;
466  g = bytestream2_get_byte(&g2) << color_shift;
467  b = bytestream2_get_byte(&g2) << color_shift;
468  entry = 0xFFU << 24 | r << 16 | g << 8 | b;
469  if (color_shift == 2)
470  entry |= entry >> 6 & 0x30303;
471  if (s->palette[palette_ptr] != entry)
472  s->new_palette = 1;
473  s->palette[palette_ptr++] = entry;
474  }
475  }
476  break;
477 
478  case FLI_DELTA:
479  y_ptr = 0;
480  compressed_lines = bytestream2_get_le16(&g2);
481  while (compressed_lines > 0) {
482  if (bytestream2_tell(&g2) + 2 > stream_ptr_after_chunk)
483  break;
484  CHECK_Y_PTR()
485  line_packets = sign_extend(bytestream2_get_le16(&g2), 16);
486  if ((line_packets & 0xC000) == 0xC000) {
487  // line skip opcode
488  line_packets = -line_packets;
489  if (line_packets > s->avctx->height)
490  return AVERROR_INVALIDDATA;
491  y_ptr += line_packets * s->frame->linesize[0];
492  } else if ((line_packets & 0xC000) == 0x4000) {
493  av_log(avctx, AV_LOG_ERROR, "Undefined opcode (%x) in DELTA_FLI\n", line_packets);
494  } else if ((line_packets & 0xC000) == 0x8000) {
495  // "last byte" opcode
496  pixel_ptr= y_ptr + s->frame->linesize[0] - 1;
497  CHECK_PIXEL_PTR(0);
498  pixels[pixel_ptr] = line_packets & 0xff;
499  } else {
500  compressed_lines--;
501  pixel_ptr = y_ptr;
502  CHECK_PIXEL_PTR(0);
503  pixel_countdown = s->avctx->width;
504  for (i = 0; i < line_packets; i++) {
505  if (bytestream2_tell(&g2) + 2 > stream_ptr_after_chunk)
506  break;
507  /* account for the skip bytes */
508  pixel_skip = bytestream2_get_byte(&g2);
509  pixel_ptr += pixel_skip;
510  pixel_countdown -= pixel_skip;
511  byte_run = sign_extend(bytestream2_get_byte(&g2), 8);
512  if (byte_run < 0) {
513  byte_run = -byte_run;
514  palette_idx1 = bytestream2_get_byte(&g2);
515  palette_idx2 = bytestream2_get_byte(&g2);
516  CHECK_PIXEL_PTR(byte_run * 2);
517  for (j = 0; j < byte_run; j++, pixel_countdown -= 2) {
518  pixels[pixel_ptr++] = palette_idx1;
519  pixels[pixel_ptr++] = palette_idx2;
520  }
521  } else {
522  CHECK_PIXEL_PTR(byte_run * 2);
523  if (bytestream2_tell(&g2) + byte_run * 2 > stream_ptr_after_chunk)
524  break;
525  for (j = 0; j < byte_run * 2; j++, pixel_countdown--) {
526  pixels[pixel_ptr++] = bytestream2_get_byte(&g2);
527  }
528  }
529  }
530 
531  y_ptr += s->frame->linesize[0];
532  }
533  }
534  break;
535 
536  case FLI_LC:
537  /* line compressed */
538  starting_line = bytestream2_get_le16(&g2);
539  if (starting_line >= s->avctx->height)
540  return AVERROR_INVALIDDATA;
541  y_ptr = 0;
542  y_ptr += starting_line * s->frame->linesize[0];
543 
544  compressed_lines = bytestream2_get_le16(&g2);
545  while (compressed_lines > 0) {
546  pixel_ptr = y_ptr;
547  CHECK_PIXEL_PTR(0);
548  pixel_countdown = s->avctx->width;
549  if (bytestream2_tell(&g2) + 1 > stream_ptr_after_chunk)
550  break;
551  line_packets = bytestream2_get_byte(&g2);
552  if (line_packets > 0) {
553  for (i = 0; i < line_packets; i++) {
554  /* account for the skip bytes */
555  if (bytestream2_tell(&g2) + 1 > stream_ptr_after_chunk)
556  break;
557  pixel_skip = bytestream2_get_byte(&g2);
558  pixel_ptr += pixel_skip;
559  pixel_countdown -= pixel_skip;
560  byte_run = sign_extend(bytestream2_get_byte(&g2),8);
561  if (byte_run > 0) {
562  CHECK_PIXEL_PTR(byte_run);
563  if (bytestream2_tell(&g2) + byte_run > stream_ptr_after_chunk)
564  break;
565  for (j = 0; j < byte_run; j++, pixel_countdown--) {
566  pixels[pixel_ptr++] = bytestream2_get_byte(&g2);
567  }
568  } else if (byte_run < 0) {
569  byte_run = -byte_run;
570  palette_idx1 = bytestream2_get_byte(&g2);
571  CHECK_PIXEL_PTR(byte_run);
572  for (j = 0; j < byte_run; j++, pixel_countdown--) {
573  pixels[pixel_ptr++] = palette_idx1;
574  }
575  }
576  }
577  }
578 
579  y_ptr += s->frame->linesize[0];
580  compressed_lines--;
581  }
582  break;
583 
584  case FLI_BLACK:
585  /* set the whole frame to color 0 (which is usually black) */
586  for (int y = 0; y < s->avctx->height; y++)
587  memset(pixels + y * s->frame->linesize[0], 0, s->avctx->width);
588  break;
589 
590  case FLI_BRUN:
591  /* Byte run compression: This chunk type only occurs in the first
592  * FLI frame and it will update the entire frame. */
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  bytestream2_skip(&g2, 1);
599  pixel_countdown = s->avctx->width;
600  while (pixel_countdown > 0) {
601  if (bytestream2_tell(&g2) + 1 > stream_ptr_after_chunk)
602  break;
603  byte_run = sign_extend(bytestream2_get_byte(&g2), 8);
604  if (!byte_run) {
605  av_log(avctx, AV_LOG_ERROR, "Invalid byte run value.\n");
606  return AVERROR_INVALIDDATA;
607  }
608 
609  if (byte_run > 0) {
610  palette_idx1 = bytestream2_get_byte(&g2);
611  CHECK_PIXEL_PTR(byte_run);
612  for (j = 0; j < byte_run; j++) {
613  pixels[pixel_ptr++] = palette_idx1;
614  pixel_countdown--;
615  if (pixel_countdown < 0)
616  av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d) at line %d\n",
617  pixel_countdown, lines);
618  }
619  } else { /* copy bytes if byte_run < 0 */
620  byte_run = -byte_run;
621  CHECK_PIXEL_PTR(byte_run);
622  if (bytestream2_tell(&g2) + byte_run > stream_ptr_after_chunk)
623  break;
624  for (j = 0; j < byte_run; j++) {
625  pixels[pixel_ptr++] = bytestream2_get_byte(&g2);
626  pixel_countdown--;
627  if (pixel_countdown < 0)
628  av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d) at line %d\n",
629  pixel_countdown, lines);
630  }
631  }
632  }
633 
634  y_ptr += s->frame->linesize[0];
635  }
636  break;
637 
638  case FLI_COPY:
639  /* copy the chunk (uncompressed frame) */
640  if (chunk_size - 6 != FFALIGN(s->avctx->width, 4) * s->avctx->height) {
641  av_log(avctx, AV_LOG_ERROR, "In chunk FLI_COPY : source data (%d bytes) " \
642  "has incorrect size, skipping chunk\n", chunk_size - 6);
643  bytestream2_skip(&g2, chunk_size - 6);
644  } else {
645  for (y_ptr = 0; check_pixel_ptr(y_ptr, s->avctx->width, pixel_limit, direction) == 0;
646  y_ptr += s->frame->linesize[0]) {
647  bytestream2_get_buffer(&g2, &pixels[y_ptr],
648  s->avctx->width);
649  if (s->avctx->width & 3)
650  bytestream2_skip(&g2, 4 - (s->avctx->width & 3));
651  }
652  }
653  break;
654 
655  case FLI_MINI:
656  /* some sort of a thumbnail? disregard this chunk... */
657  break;
658 
659  default:
660  av_log(avctx, AV_LOG_ERROR, "Unrecognized chunk type: %d\n", chunk_type);
661  break;
662  }
663 
664  if (stream_ptr_after_chunk - bytestream2_tell(&g2) >= 0) {
665  bytestream2_skip(&g2, stream_ptr_after_chunk - bytestream2_tell(&g2));
666  } else {
667  av_log(avctx, AV_LOG_ERROR, "Chunk overread\n");
668  break;
669  }
670 
671  frame_size -= chunk_size;
672  num_chunks--;
673  }
674 
675  /* by the end of the chunk, the stream ptr should equal the frame
676  * size (minus 1 or 2, possibly); if it doesn't, issue a warning */
677  if (bytestream2_get_bytes_left(&g2) > 2)
678  av_log(avctx, AV_LOG_ERROR, "Processed FLI chunk where chunk size = %d " \
679  "and final chunk ptr = %d\n", buf_size,
680  buf_size - bytestream2_get_bytes_left(&g2));
681 
682  /* make the palette available on the way out */
683  memcpy(s->frame->data[1], s->palette, AVPALETTE_SIZE);
684  if (s->new_palette) {
685 #if FF_API_PALETTE_HAS_CHANGED
687  s->frame->palette_has_changed = 1;
689 #endif
690  s->new_palette = 0;
691  }
692 
693  if ((ret = av_frame_ref(rframe, s->frame)) < 0)
694  return ret;
695 
696  *got_frame = 1;
697 
698  return buf_size;
699 }
700 
702  AVFrame *rframe, int *got_frame,
703  const uint8_t *buf, int buf_size)
704 {
705  /* Note, the only difference between the 15Bpp and 16Bpp */
706  /* Format is the pixel format, the packets are processed the same. */
707  FlicDecodeContext *s = avctx->priv_data;
708 
709  GetByteContext g2;
710  ptrdiff_t pixel_ptr;
711  unsigned char palette_idx1;
712 
713  unsigned int frame_size;
714  int num_chunks;
715 
716  unsigned int chunk_size;
717  int chunk_type;
718 
719  int i, j, ret, direction;
720 
721  int lines;
722  int compressed_lines;
723  int line_packets;
724  ptrdiff_t y_ptr;
725  int byte_run;
726  int pixel_skip;
727  int pixel_countdown;
728  unsigned char *pixels;
729  int pixel;
730  ptrdiff_t pixel_limit;
731 
732  bytestream2_init(&g2, buf, buf_size);
733 
734  if ((ret = ff_reget_buffer(avctx, s->frame, 0)) < 0)
735  return ret;
736 
737  direction = s->frame->linesize[0] > 0;
738  pixels = s->frame->data[0];
739  pixel_limit = s->avctx->height * s->frame->linesize[0];
740 
741  frame_size = bytestream2_get_le32(&g2);
742  bytestream2_skip(&g2, 2); /* skip the magic number */
743  num_chunks = bytestream2_get_le16(&g2);
744  bytestream2_skip(&g2, 8); /* skip padding */
745  if (frame_size > buf_size)
746  frame_size = buf_size;
747 
748  if (frame_size < 16)
749  return AVERROR_INVALIDDATA;
750  frame_size -= 16;
751 
752  /* iterate through the chunks */
753  while ((frame_size > 0) && (num_chunks > 0) &&
754  bytestream2_get_bytes_left(&g2) >= 4) {
755  int stream_ptr_after_chunk;
756  chunk_size = bytestream2_get_le32(&g2);
757  if (chunk_size > frame_size) {
758  av_log(avctx, AV_LOG_WARNING,
759  "Invalid chunk_size = %u > frame_size = %u\n", chunk_size, frame_size);
760  chunk_size = frame_size;
761  }
762  stream_ptr_after_chunk = bytestream2_tell(&g2) - 4 + chunk_size;
763 
764  chunk_type = bytestream2_get_le16(&g2);
765 
766 
767  switch (chunk_type) {
768  case FLI_256_COLOR:
769  case FLI_COLOR:
770  /* For some reason, it seems that non-palettized flics do
771  * include one of these chunks in their first frame.
772  * Why I do not know, it seems rather extraneous. */
773  ff_dlog(avctx,
774  "Unexpected Palette chunk %d in non-palettized FLC\n",
775  chunk_type);
776  bytestream2_skip(&g2, chunk_size - 6);
777  break;
778 
779  case FLI_DELTA:
780  case FLI_DTA_LC:
781  y_ptr = 0;
782  compressed_lines = bytestream2_get_le16(&g2);
783  while (compressed_lines > 0) {
784  if (bytestream2_tell(&g2) + 2 > stream_ptr_after_chunk)
785  break;
786  CHECK_Y_PTR()
787  line_packets = sign_extend(bytestream2_get_le16(&g2), 16);
788  if (line_packets < 0) {
789  line_packets = -line_packets;
790  if (line_packets > s->avctx->height)
791  return AVERROR_INVALIDDATA;
792  y_ptr += line_packets * s->frame->linesize[0];
793  } else {
794  compressed_lines--;
795  pixel_ptr = y_ptr;
796  CHECK_PIXEL_PTR(0);
797  pixel_countdown = s->avctx->width;
798  for (i = 0; i < line_packets; i++) {
799  /* account for the skip bytes */
800  if (bytestream2_tell(&g2) + 2 > stream_ptr_after_chunk)
801  break;
802  pixel_skip = bytestream2_get_byte(&g2);
803  pixel_ptr += (pixel_skip*2); /* Pixel is 2 bytes wide */
804  pixel_countdown -= pixel_skip;
805  byte_run = sign_extend(bytestream2_get_byte(&g2), 8);
806  if (byte_run < 0) {
807  byte_run = -byte_run;
808  pixel = bytestream2_get_le16(&g2);
809  CHECK_PIXEL_PTR(2 * byte_run);
810  for (j = 0; j < byte_run; j++, pixel_countdown -= 2) {
811  *((signed short*)(&pixels[pixel_ptr])) = pixel;
812  pixel_ptr += 2;
813  }
814  } else {
815  if (bytestream2_tell(&g2) + 2*byte_run > stream_ptr_after_chunk)
816  break;
817  CHECK_PIXEL_PTR(2 * byte_run);
818  for (j = 0; j < byte_run; j++, pixel_countdown--) {
819  *((signed short*)(&pixels[pixel_ptr])) = bytestream2_get_le16(&g2);
820  pixel_ptr += 2;
821  }
822  }
823  }
824 
825  y_ptr += s->frame->linesize[0];
826  }
827  }
828  break;
829 
830  case FLI_LC:
831  av_log(avctx, AV_LOG_ERROR, "Unexpected FLI_LC chunk in non-palettized FLC\n");
832  bytestream2_skip(&g2, chunk_size - 6);
833  break;
834 
835  case FLI_BLACK:
836  /* set the whole frame to 0x0000 which is black in both 15Bpp and 16Bpp modes. */
837  for (int y = 0; y < s->avctx->height; y++)
838  memset(pixels + y * s->frame->linesize[0], 0, s->avctx->width * 2);
839  break;
840 
841  case FLI_BRUN:
842  y_ptr = 0;
843  for (lines = 0; lines < s->avctx->height; lines++) {
844  pixel_ptr = y_ptr;
845  /* disregard the line packets; instead, iterate through all
846  * pixels on a row */
847  bytestream2_skip(&g2, 1);
848  pixel_countdown = (s->avctx->width * 2);
849 
850  while (pixel_countdown > 0) {
851  if (bytestream2_tell(&g2) + 1 > stream_ptr_after_chunk)
852  break;
853  byte_run = sign_extend(bytestream2_get_byte(&g2), 8);
854  if (byte_run > 0) {
855  palette_idx1 = bytestream2_get_byte(&g2);
856  CHECK_PIXEL_PTR(byte_run);
857  for (j = 0; j < byte_run; j++) {
858  pixels[pixel_ptr++] = palette_idx1;
859  pixel_countdown--;
860  if (pixel_countdown < 0)
861  av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d) (linea%d)\n",
862  pixel_countdown, lines);
863  }
864  } else { /* copy bytes if byte_run < 0 */
865  byte_run = -byte_run;
866  if (bytestream2_tell(&g2) + byte_run > stream_ptr_after_chunk)
867  break;
868  CHECK_PIXEL_PTR(byte_run);
869  for (j = 0; j < byte_run; j++) {
870  palette_idx1 = bytestream2_get_byte(&g2);
871  pixels[pixel_ptr++] = palette_idx1;
872  pixel_countdown--;
873  if (pixel_countdown < 0)
874  av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d) at line %d\n",
875  pixel_countdown, lines);
876  }
877  }
878  }
879 
880  /* Now FLX is strange, in that it is "byte" as opposed to "pixel" run length compressed.
881  * This does not give us any good opportunity to perform word endian conversion
882  * during decompression. So if it is required (i.e., this is not a LE target, we do
883  * a second pass over the line here, swapping the bytes.
884  */
885 #if HAVE_BIGENDIAN
886  pixel_ptr = y_ptr;
887  pixel_countdown = s->avctx->width;
888  while (pixel_countdown > 0) {
889  *((signed short*)(&pixels[pixel_ptr])) = AV_RL16(&buf[pixel_ptr]);
890  pixel_ptr += 2;
891  }
892 #endif
893  y_ptr += s->frame->linesize[0];
894  }
895  break;
896 
897  case FLI_DTA_BRUN:
898  y_ptr = 0;
899  for (lines = 0; lines < s->avctx->height; lines++) {
900  pixel_ptr = y_ptr;
901  /* disregard the line packets; instead, iterate through all
902  * pixels on a row */
903  bytestream2_skip(&g2, 1);
904  pixel_countdown = s->avctx->width; /* Width is in pixels, not bytes */
905 
906  while (pixel_countdown > 0) {
907  if (bytestream2_tell(&g2) + 1 > stream_ptr_after_chunk)
908  break;
909  byte_run = sign_extend(bytestream2_get_byte(&g2), 8);
910  if (byte_run > 0) {
911  pixel = bytestream2_get_le16(&g2);
912  CHECK_PIXEL_PTR(2 * byte_run);
913  for (j = 0; j < byte_run; j++) {
914  *((signed short*)(&pixels[pixel_ptr])) = pixel;
915  pixel_ptr += 2;
916  pixel_countdown--;
917  if (pixel_countdown < 0)
918  av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d)\n",
919  pixel_countdown);
920  }
921  } else { /* copy pixels if byte_run < 0 */
922  byte_run = -byte_run;
923  if (bytestream2_tell(&g2) + 2 * byte_run > stream_ptr_after_chunk)
924  break;
925  CHECK_PIXEL_PTR(2 * byte_run);
926  for (j = 0; j < byte_run; j++) {
927  *((signed short*)(&pixels[pixel_ptr])) = bytestream2_get_le16(&g2);
928  pixel_ptr += 2;
929  pixel_countdown--;
930  if (pixel_countdown < 0)
931  av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d)\n",
932  pixel_countdown);
933  }
934  }
935  }
936 
937  y_ptr += s->frame->linesize[0];
938  }
939  break;
940 
941  case FLI_COPY:
942  case FLI_DTA_COPY:
943  /* copy the chunk (uncompressed frame) */
944  if (chunk_size - 6 > (unsigned int)(FFALIGN(s->avctx->width, 2) * s->avctx->height)*2) {
945  av_log(avctx, AV_LOG_ERROR, "In chunk FLI_COPY : source data (%d bytes) " \
946  "bigger than image, skipping chunk\n", chunk_size - 6);
947  bytestream2_skip(&g2, chunk_size - 6);
948  } else {
949 
950  if (bytestream2_get_bytes_left(&g2) < 2 * s->avctx->width * s->avctx->height )
951  return AVERROR_INVALIDDATA;
952  for (y_ptr = 0; check_pixel_ptr(y_ptr, 2*s->avctx->width, pixel_limit, direction) == 0;
953  y_ptr += s->frame->linesize[0]) {
954 
955  pixel_countdown = s->avctx->width;
956  pixel_ptr = 0;
957  while (pixel_countdown > 0) {
958  *((signed short*)(&pixels[y_ptr + pixel_ptr])) = bytestream2_get_le16(&g2);
959  pixel_ptr += 2;
960  pixel_countdown--;
961  }
962  if (s->avctx->width & 1)
963  bytestream2_skip(&g2, 2);
964  }
965  }
966  break;
967 
968  case FLI_MINI:
969  /* some sort of a thumbnail? disregard this chunk... */
970  bytestream2_skip(&g2, chunk_size - 6);
971  break;
972 
973  default:
974  av_log(avctx, AV_LOG_ERROR, "Unrecognized chunk type: %d\n", chunk_type);
975  break;
976  }
977 
978  if (stream_ptr_after_chunk - bytestream2_tell(&g2) >= 0) {
979  bytestream2_skip(&g2, stream_ptr_after_chunk - bytestream2_tell(&g2));
980  } else {
981  av_log(avctx, AV_LOG_ERROR, "Chunk overread\n");
982  break;
983  }
984 
985  frame_size -= chunk_size;
986  num_chunks--;
987  }
988 
989  /* by the end of the chunk, the stream ptr should equal the frame
990  * size (minus 1, possibly); if it doesn't, issue a warning */
991  if ((bytestream2_get_bytes_left(&g2) != 0) && (bytestream2_get_bytes_left(&g2) != 1))
992  av_log(avctx, AV_LOG_ERROR, "Processed FLI chunk where chunk size = %d " \
993  "and final chunk ptr = %d\n", buf_size, bytestream2_tell(&g2));
994 
995  if ((ret = av_frame_ref(rframe, s->frame)) < 0)
996  return ret;
997 
998  *got_frame = 1;
999 
1000  return buf_size;
1001 }
1002 
1004  AVFrame *rframe, int *got_frame,
1005  const uint8_t *buf, int buf_size)
1006 {
1007  FlicDecodeContext *s = avctx->priv_data;
1008 
1009  GetByteContext g2;
1010  ptrdiff_t pixel_ptr;
1011  unsigned char palette_idx1;
1012 
1013  unsigned int frame_size;
1014  int num_chunks;
1015 
1016  unsigned int chunk_size;
1017  int chunk_type;
1018 
1019  int i, j, ret, direction;
1020 
1021  int lines;
1022  int compressed_lines;
1023  int line_packets;
1024  ptrdiff_t y_ptr;
1025  int byte_run;
1026  int pixel_skip;
1027  int pixel_countdown;
1028  unsigned char *pixels;
1029  int pixel;
1030  ptrdiff_t pixel_limit;
1031 
1032  bytestream2_init(&g2, buf, buf_size);
1033 
1034  if ((ret = ff_reget_buffer(avctx, s->frame, 0)) < 0)
1035  return ret;
1036 
1037  direction = s->frame->linesize[0] > 0;
1038  pixels = s->frame->data[0];
1039  pixel_limit = s->avctx->height * s->frame->linesize[0];
1040 
1041  frame_size = bytestream2_get_le32(&g2);
1042  bytestream2_skip(&g2, 2); /* skip the magic number */
1043  num_chunks = bytestream2_get_le16(&g2);
1044  bytestream2_skip(&g2, 8); /* skip padding */
1045  if (frame_size > buf_size)
1046  frame_size = buf_size;
1047 
1048  if (frame_size < 16)
1049  return AVERROR_INVALIDDATA;
1050  frame_size -= 16;
1051 
1052  /* iterate through the chunks */
1053  while ((frame_size > 0) && (num_chunks > 0) &&
1054  bytestream2_get_bytes_left(&g2) >= 4) {
1055  int stream_ptr_after_chunk;
1056  chunk_size = bytestream2_get_le32(&g2);
1057  if (chunk_size > frame_size) {
1058  av_log(avctx, AV_LOG_WARNING,
1059  "Invalid chunk_size = %u > frame_size = %u\n", chunk_size, frame_size);
1060  chunk_size = frame_size;
1061  }
1062  stream_ptr_after_chunk = bytestream2_tell(&g2) - 4 + chunk_size;
1063 
1064  chunk_type = bytestream2_get_le16(&g2);
1065 
1066 
1067  switch (chunk_type) {
1068  case FLI_256_COLOR:
1069  case FLI_COLOR:
1070  /* For some reason, it seems that non-palettized flics do
1071  * include one of these chunks in their first frame.
1072  * Why I do not know, it seems rather extraneous. */
1073  ff_dlog(avctx,
1074  "Unexpected Palette chunk %d in non-palettized FLC\n",
1075  chunk_type);
1076  bytestream2_skip(&g2, chunk_size - 6);
1077  break;
1078 
1079  case FLI_DELTA:
1080  case FLI_DTA_LC:
1081  y_ptr = 0;
1082  compressed_lines = bytestream2_get_le16(&g2);
1083  while (compressed_lines > 0) {
1084  if (bytestream2_tell(&g2) + 2 > stream_ptr_after_chunk)
1085  break;
1086  CHECK_Y_PTR()
1087  line_packets = sign_extend(bytestream2_get_le16(&g2), 16);
1088  if (line_packets < 0) {
1089  line_packets = -line_packets;
1090  if (line_packets > s->avctx->height)
1091  return AVERROR_INVALIDDATA;
1092  y_ptr += line_packets * s->frame->linesize[0];
1093  } else {
1094  compressed_lines--;
1095  pixel_ptr = y_ptr;
1096  CHECK_PIXEL_PTR(0);
1097  pixel_countdown = s->avctx->width;
1098  for (i = 0; i < line_packets; i++) {
1099  /* account for the skip bytes */
1100  if (bytestream2_tell(&g2) + 2 > stream_ptr_after_chunk)
1101  break;
1102  pixel_skip = bytestream2_get_byte(&g2);
1103  pixel_ptr += (pixel_skip*3); /* Pixel is 3 bytes wide */
1104  pixel_countdown -= pixel_skip;
1105  byte_run = sign_extend(bytestream2_get_byte(&g2), 8);
1106  if (byte_run < 0) {
1107  byte_run = -byte_run;
1108  pixel = bytestream2_get_le24(&g2);
1109  CHECK_PIXEL_PTR(3 * byte_run);
1110  for (j = 0; j < byte_run; j++, pixel_countdown -= 1) {
1111  AV_WL24(&pixels[pixel_ptr], pixel);
1112  pixel_ptr += 3;
1113  }
1114  } else {
1115  if (bytestream2_tell(&g2) + 2*byte_run > stream_ptr_after_chunk)
1116  break;
1117  CHECK_PIXEL_PTR(3 * byte_run);
1118  for (j = 0; j < byte_run; j++, pixel_countdown--) {
1119  pixel = bytestream2_get_le24(&g2);
1120  AV_WL24(&pixels[pixel_ptr], pixel);
1121  pixel_ptr += 3;
1122  }
1123  }
1124  }
1125 
1126  y_ptr += s->frame->linesize[0];
1127  }
1128  }
1129  break;
1130 
1131  case FLI_LC:
1132  av_log(avctx, AV_LOG_ERROR, "Unexpected FLI_LC chunk in non-palettized FLC\n");
1133  bytestream2_skip(&g2, chunk_size - 6);
1134  break;
1135 
1136  case FLI_BLACK:
1137  /* set the whole frame to 0x00 which is black for 24 bit mode. */
1138  for (int y = 0; y < s->avctx->height; y++)
1139  memset(pixels + y * s->frame->linesize[0], 0, s->avctx->width * 3);
1140  break;
1141 
1142  case FLI_BRUN:
1143  y_ptr = 0;
1144  for (lines = 0; lines < s->avctx->height; lines++) {
1145  pixel_ptr = y_ptr;
1146  /* disregard the line packets; instead, iterate through all
1147  * pixels on a row */
1148  bytestream2_skip(&g2, 1);
1149  pixel_countdown = (s->avctx->width * 3);
1150 
1151  while (pixel_countdown > 0) {
1152  if (bytestream2_tell(&g2) + 1 > stream_ptr_after_chunk)
1153  break;
1154  byte_run = sign_extend(bytestream2_get_byte(&g2), 8);
1155  if (byte_run > 0) {
1156  palette_idx1 = bytestream2_get_byte(&g2);
1157  CHECK_PIXEL_PTR(byte_run);
1158  for (j = 0; j < byte_run; j++) {
1159  pixels[pixel_ptr++] = palette_idx1;
1160  pixel_countdown--;
1161  if (pixel_countdown < 0)
1162  av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d) (linea%d)\n",
1163  pixel_countdown, lines);
1164  }
1165  } else { /* copy bytes if byte_run < 0 */
1166  byte_run = -byte_run;
1167  if (bytestream2_tell(&g2) + byte_run > stream_ptr_after_chunk)
1168  break;
1169  CHECK_PIXEL_PTR(byte_run);
1170  for (j = 0; j < byte_run; j++) {
1171  palette_idx1 = bytestream2_get_byte(&g2);
1172  pixels[pixel_ptr++] = palette_idx1;
1173  pixel_countdown--;
1174  if (pixel_countdown < 0)
1175  av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d) at line %d\n",
1176  pixel_countdown, lines);
1177  }
1178  }
1179  }
1180 
1181  y_ptr += s->frame->linesize[0];
1182  }
1183  break;
1184 
1185  case FLI_DTA_BRUN:
1186  y_ptr = 0;
1187  for (lines = 0; lines < s->avctx->height; lines++) {
1188  pixel_ptr = y_ptr;
1189  /* disregard the line packets; instead, iterate through all
1190  * pixels on a row */
1191  bytestream2_skip(&g2, 1);
1192  pixel_countdown = s->avctx->width; /* Width is in pixels, not bytes */
1193 
1194  while (pixel_countdown > 0) {
1195  if (bytestream2_tell(&g2) + 1 > stream_ptr_after_chunk)
1196  break;
1197  byte_run = sign_extend(bytestream2_get_byte(&g2), 8);
1198  if (byte_run > 0) {
1199  pixel = bytestream2_get_le24(&g2);
1200  CHECK_PIXEL_PTR(3 * byte_run);
1201  for (j = 0; j < byte_run; j++) {
1202  AV_WL24(pixels + pixel_ptr, pixel);
1203  pixel_ptr += 3;
1204  pixel_countdown--;
1205  if (pixel_countdown < 0)
1206  av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d)\n",
1207  pixel_countdown);
1208  }
1209  } else { /* copy pixels if byte_run < 0 */
1210  byte_run = -byte_run;
1211  if (bytestream2_tell(&g2) + 3 * byte_run > stream_ptr_after_chunk)
1212  break;
1213  CHECK_PIXEL_PTR(3 * byte_run);
1214  for (j = 0; j < byte_run; j++) {
1215  pixel = bytestream2_get_le24(&g2);
1216  AV_WL24(pixels + pixel_ptr, pixel);
1217  pixel_ptr += 3;
1218  pixel_countdown--;
1219  if (pixel_countdown < 0)
1220  av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d)\n",
1221  pixel_countdown);
1222  }
1223  }
1224  }
1225 
1226  y_ptr += s->frame->linesize[0];
1227  }
1228  break;
1229 
1230  case FLI_COPY:
1231  case FLI_DTA_COPY:
1232  /* copy the chunk (uncompressed frame) */
1233  if (chunk_size - 6 > (unsigned int)(FFALIGN(s->avctx->width, 2) * s->avctx->height)*3) {
1234  av_log(avctx, AV_LOG_ERROR, "In chunk FLI_COPY : source data (%d bytes) " \
1235  "bigger than image, skipping chunk\n", chunk_size - 6);
1236  bytestream2_skip(&g2, chunk_size - 6);
1237  } else {
1238  for (y_ptr = 0; check_pixel_ptr(y_ptr, 3*s->avctx->width, pixel_limit, direction) == 0;
1239  y_ptr += s->frame->linesize[0]) {
1240 
1241  bytestream2_get_buffer(&g2, pixels + y_ptr, 3*s->avctx->width);
1242  if (s->avctx->width & 1)
1243  bytestream2_skip(&g2, 3);
1244  }
1245  }
1246  break;
1247 
1248  case FLI_MINI:
1249  /* some sort of a thumbnail? disregard this chunk... */
1250  bytestream2_skip(&g2, chunk_size - 6);
1251  break;
1252 
1253  default:
1254  av_log(avctx, AV_LOG_ERROR, "Unrecognized chunk type: %d\n", chunk_type);
1255  break;
1256  }
1257 
1258  if (stream_ptr_after_chunk - bytestream2_tell(&g2) >= 0) {
1259  bytestream2_skip(&g2, stream_ptr_after_chunk - bytestream2_tell(&g2));
1260  } else {
1261  av_log(avctx, AV_LOG_ERROR, "Chunk overread\n");
1262  break;
1263  }
1264 
1265  frame_size -= chunk_size;
1266  num_chunks--;
1267  }
1268 
1269  /* by the end of the chunk, the stream ptr should equal the frame
1270  * size (minus 1, possibly); if it doesn't, issue a warning */
1271  if ((bytestream2_get_bytes_left(&g2) != 0) && (bytestream2_get_bytes_left(&g2) != 1))
1272  av_log(avctx, AV_LOG_ERROR, "Processed FLI chunk where chunk size = %d " \
1273  "and final chunk ptr = %d\n", buf_size, bytestream2_tell(&g2));
1274 
1275  if ((ret = av_frame_ref(rframe, s->frame)) < 0)
1276  return ret;
1277 
1278  *got_frame = 1;
1279 
1280  return buf_size;
1281 }
1282 
1284  int *got_frame, AVPacket *avpkt)
1285 {
1286  const uint8_t *buf = avpkt->data;
1287  int buf_size = avpkt->size;
1288  if (avctx->pix_fmt == AV_PIX_FMT_MONOBLACK) {
1289  return flic_decode_frame_1BPP(avctx, frame, got_frame,
1290  buf, buf_size);
1291  } else if (avctx->pix_fmt == AV_PIX_FMT_PAL8) {
1292  return flic_decode_frame_8BPP(avctx, frame, got_frame,
1293  buf, buf_size);
1294  } else if ((avctx->pix_fmt == AV_PIX_FMT_RGB555) ||
1295  (avctx->pix_fmt == AV_PIX_FMT_RGB565)) {
1296  return flic_decode_frame_15_16BPP(avctx, frame, got_frame,
1297  buf, buf_size);
1298  } else if (avctx->pix_fmt == AV_PIX_FMT_BGR24) {
1299  return flic_decode_frame_24BPP(avctx, frame, got_frame,
1300  buf, buf_size);
1301  }
1302 
1303  /* Should not get here, ever as the pix_fmt is processed */
1304  /* in flic_decode_init and the above if should deal with */
1305  /* the finite set of possibilities allowable by here. */
1306  /* But in case we do, just error out. */
1307  av_log(avctx, AV_LOG_ERROR, "Unknown FLC format, my science cannot explain how this happened.\n");
1308  return AVERROR_BUG;
1309 }
1310 
1311 
1313 {
1314  FlicDecodeContext *s = avctx->priv_data;
1315 
1316  av_frame_free(&s->frame);
1317 
1318  return 0;
1319 }
1320 
1322  .p.name = "flic",
1323  CODEC_LONG_NAME("Autodesk Animator Flic video"),
1324  .p.type = AVMEDIA_TYPE_VIDEO,
1325  .p.id = AV_CODEC_ID_FLIC,
1326  .priv_data_size = sizeof(FlicDecodeContext),
1328  .close = flic_decode_end,
1330  .p.capabilities = AV_CODEC_CAP_DR1,
1331 };
FF_ENABLE_DEPRECATION_WARNINGS
#define FF_ENABLE_DEPRECATION_WARNINGS
Definition: internal.h:73
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:186
flic_decode_end
static av_cold int flic_decode_end(AVCodecContext *avctx)
Definition: flicvideo.c:1312
entry
#define entry
Definition: aom_film_grain_template.c:66
FLC_FLX_TYPE_CODE
#define FLC_FLX_TYPE_CODE
Definition: flicvideo.c:59
r
const char * r
Definition: vf_curves.c:126
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
CHECK_Y_PTR
#define CHECK_Y_PTR()
Definition: flicvideo.c:79
GetByteContext
Definition: bytestream.h:33
FLI_BRUN
#define FLI_BRUN
Definition: flicvideo.c:51
FLC_MAGIC_CARPET_SYNTHETIC_TYPE_CODE
#define FLC_MAGIC_CARPET_SYNTHETIC_TYPE_CODE
Definition: flicvideo.c:61
av_frame_free
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:130
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:344
flic_decode_frame_15_16BPP
static int flic_decode_frame_15_16BPP(AVCodecContext *avctx, AVFrame *rframe, int *got_frame, const uint8_t *buf, int buf_size)
Definition: flicvideo.c:701
AVPacket::data
uint8_t * data
Definition: packet.h:522
b
#define b
Definition: input.c:41
AV_CODEC_ID_FLIC
@ AV_CODEC_ID_FLIC
Definition: codec_id.h:102
FLI_COLOR
#define FLI_COLOR
Definition: flicvideo.c:48
FFCodec
Definition: codec_internal.h:127
AV_PIX_FMT_BGR24
@ AV_PIX_FMT_BGR24
packed RGB 8:8:8, 24bpp, BGRBGR...
Definition: pixfmt.h:76
bytestream2_skip
static av_always_inline void bytestream2_skip(GetByteContext *g, unsigned int size)
Definition: bytestream.h:168
FFCodec::p
AVCodec p
The public AVCodec.
Definition: codec_internal.h:131
FlicDecodeContext::fli_type
int fli_type
Definition: flicvideo.c:92
flic_decode_frame_1BPP
static int flic_decode_frame_1BPP(AVCodecContext *avctx, AVFrame *rframe, int *got_frame, const uint8_t *buf, int buf_size)
Definition: flicvideo.c:166
FLI_BLACK
#define FLI_BLACK
Definition: flicvideo.c:50
flic_decode_init
static av_cold int flic_decode_init(AVCodecContext *avctx)
Definition: flicvideo.c:95
av_frame_alloc
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
Definition: frame.c:118
FlicDecodeContext::frame
AVFrame * frame
Definition: flicvideo.c:88
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:180
av_cold
#define av_cold
Definition: attributes.h:90
AVCodecContext::extradata_size
int extradata_size
Definition: avcodec.h:524
FF_CODEC_DECODE_CB
#define FF_CODEC_DECODE_CB(func)
Definition: codec_internal.h:287
intreadwrite.h
s
#define s(width, name)
Definition: cbs_vp9.c:198
g
const char * g
Definition: vf_curves.c:127
frame_size
int frame_size
Definition: mxfenc.c:2422
FLI_TYPE_CODE
#define FLI_TYPE_CODE
Definition: flicvideo.c:58
flic_decode_frame
static int flic_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame, AVPacket *avpkt)
Definition: flicvideo.c:1283
FLI_DTA_BRUN
#define FLI_DTA_BRUN
Definition: flicvideo.c:54
CHECK_PIXEL_PTR
#define CHECK_PIXEL_PTR(n)
Definition: flicvideo.c:72
decode.h
AV_RL16
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_WL32 unsigned int_TMPL AV_WL24 unsigned int_TMPL AV_RL16
Definition: bytestream.h:94
check_pixel_ptr
static int check_pixel_ptr(ptrdiff_t ptr, int n, ptrdiff_t limit, int direction)
Definition: flicvideo.c:63
flic_decode_frame_8BPP
static int flic_decode_frame_8BPP(AVCodecContext *avctx, AVFrame *rframe, int *got_frame, const uint8_t *buf, int buf_size)
Definition: flicvideo.c:358
CODEC_LONG_NAME
#define CODEC_LONG_NAME(str)
Definition: codec_internal.h:272
frame
static AVFrame * frame
Definition: demux_decode.c:54
FLI_DELTA
#define FLI_DELTA
Definition: flicvideo.c:47
pixel
uint8_t pixel
Definition: tiny_ssim.c:41
AV_PIX_FMT_MONOBLACK
@ AV_PIX_FMT_MONOBLACK
Y , 1bpp, 0 is black, 1 is white, in each byte pixels are ordered from the msb to the lsb.
Definition: pixfmt.h:83
AVPALETTE_SIZE
#define AVPALETTE_SIZE
Definition: pixfmt.h:32
AV_WL24
#define AV_WL24(p, d)
Definition: intreadwrite.h:462
mathops.h
bytestream2_get_buffer
static av_always_inline unsigned int bytestream2_get_buffer(GetByteContext *g, uint8_t *dst, unsigned int size)
Definition: bytestream.h:267
bytestream2_get_bytes_left
static av_always_inline int bytestream2_get_bytes_left(GetByteContext *g)
Definition: bytestream.h:158
bytestream2_tell
static av_always_inline int bytestream2_tell(GetByteContext *g)
Definition: bytestream.h:192
ff_dlog
#define ff_dlog(a,...)
Definition: tableprint_vlc.h:28
init
int(* init)(AVBSFContext *ctx)
Definition: dts2pts.c:365
AV_CODEC_CAP_DR1
#define AV_CODEC_CAP_DR1
Codec uses get_buffer() or get_encode_buffer() for allocating buffers and supports custom allocators.
Definition: codec.h:52
AVPacket::size
int size
Definition: packet.h:523
av_frame_ref
int av_frame_ref(AVFrame *dst, const AVFrame *src)
Set up a new reference to the data described by the source frame.
Definition: frame.c:354
codec_internal.h
FLI_MINI
#define FLI_MINI
Definition: flicvideo.c:53
ff_flic_decoder
const FFCodec ff_flic_decoder
Definition: flicvideo.c:1321
FLI_COPY
#define FLI_COPY
Definition: flicvideo.c:52
FLI_LC
#define FLI_LC
Definition: flicvideo.c:49
FlicDecodeContext
Definition: flicvideo.c:86
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:255
FLI_DTA_COPY
#define FLI_DTA_COPY
Definition: flicvideo.c:55
AVCodecContext::extradata
uint8_t * extradata
some codecs need / can use extradata like Huffman tables.
Definition: avcodec.h:523
AV_PIX_FMT_RGB555
#define AV_PIX_FMT_RGB555
Definition: pixfmt.h:466
value
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf default value
Definition: writing_filters.txt:86
AVCodec::name
const char * name
Name of the codec implementation.
Definition: codec.h:194
AVCodecContext::pix_fmt
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition: avcodec.h:657
AV_PIX_FMT_RGB565
#define AV_PIX_FMT_RGB565
Definition: pixfmt.h:465
avcodec.h
limit
static double limit(double x)
Definition: vf_pseudocolor.c:142
AV_PIX_FMT_PAL8
@ AV_PIX_FMT_PAL8
8 bits with AV_PIX_FMT_RGB32 palette
Definition: pixfmt.h:84
ff_reget_buffer
int ff_reget_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
Identical in function to ff_get_buffer(), except it reuses the existing buffer if available.
Definition: decode.c:1678
ret
ret
Definition: filter_design.txt:187
FlicDecodeContext::avctx
AVCodecContext * avctx
Definition: flicvideo.c:87
AV_INPUT_BUFFER_PADDING_SIZE
#define AV_INPUT_BUFFER_PADDING_SIZE
Definition: defs.h:40
AV_RL32
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_RL32
Definition: bytestream.h:92
U
#define U(x)
Definition: vpx_arith.h:37
AVCodecContext
main external API structure.
Definition: avcodec.h:445
FLI_DTA_LC
#define FLI_DTA_LC
Definition: flicvideo.c:56
sign_extend
static av_const int sign_extend(int val, unsigned bits)
Definition: mathops.h:133
FLI_256_COLOR
#define FLI_256_COLOR
Definition: flicvideo.c:46
FF_DISABLE_DEPRECATION_WARNINGS
#define FF_DISABLE_DEPRECATION_WARNINGS
Definition: internal.h:72
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
FFALIGN
#define FFALIGN(x, a)
Definition: macros.h:78
AVPacket
This structure stores compressed data.
Definition: packet.h:499
AVCodecContext::priv_data
void * priv_data
Definition: avcodec.h:472
bytestream.h
bytestream2_init
static av_always_inline void bytestream2_init(GetByteContext *g, const uint8_t *buf, int buf_size)
Definition: bytestream.h:137
AVERROR_BUG
#define AVERROR_BUG
Internal bug, also see AVERROR_BUG2.
Definition: error.h:52
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
AVERROR_INVALIDDATA
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:61
flic_decode_frame_24BPP
static int flic_decode_frame_24BPP(AVCodecContext *avctx, AVFrame *rframe, int *got_frame, const uint8_t *buf, int buf_size)
Definition: flicvideo.c:1003
FlicDecodeContext::palette
unsigned int palette[256]
Definition: flicvideo.c:90
FlicDecodeContext::new_palette
int new_palette
Definition: flicvideo.c:91