47 #define FLI_256_COLOR 4 55 #define FLI_DTA_BRUN 25 56 #define FLI_DTA_COPY 26 59 #define FLI_TYPE_CODE (0xAF11) 60 #define FLC_FLX_TYPE_CODE (0xAF12) 61 #define FLC_DTA_TYPE_CODE (0xAF44) 62 #define FLC_MAGIC_CARPET_SYNTHETIC_TYPE_CODE (0xAF13) 64 #define CHECK_PIXEL_PTR(n) \ 65 if (pixel_ptr + n > pixel_limit) { \ 66 av_log (s->avctx, AV_LOG_ERROR, "Invalid pixel_ptr = %d > pixel_limit = %d\n", \ 67 pixel_ptr + n, pixel_limit); \ 68 return AVERROR_INVALIDDATA; \ 83 unsigned char *fli_header = (
unsigned char *)avctx->
extradata;
106 for (i = 0; i < 256; i++) {
120 depth =
AV_RL16(&fli_header[12]);
137 av_log(avctx,
AV_LOG_ERROR,
"Unknown FLC/FLX depth of %d Bpp is unsupported.\n",depth);
151 void *
data,
int *got_frame,
152 const uint8_t *buf,
int buf_size)
159 unsigned char palette_idx1;
160 unsigned char palette_idx2;
165 unsigned int chunk_size;
173 unsigned char r,
g,
b;
176 int compressed_lines;
183 unsigned char *pixels;
184 unsigned int pixel_limit;
195 frame_size = bytestream2_get_le32(&g2);
196 if (frame_size > buf_size)
197 frame_size = buf_size;
199 num_chunks = bytestream2_get_le16(&g2);
208 while ((frame_size >= 6) && (num_chunks > 0) &&
210 int stream_ptr_after_chunk;
211 chunk_size = bytestream2_get_le32(&g2);
212 if (chunk_size > frame_size) {
214 "Invalid chunk_size = %u > frame_size = %u\n", chunk_size, frame_size);
219 chunk_type = bytestream2_get_le16(&g2);
221 switch (chunk_type) {
233 color_packets = bytestream2_get_le16(&g2);
235 for (i = 0; i < color_packets; i++) {
237 palette_ptr += bytestream2_get_byte(&g2);
240 color_changes = bytestream2_get_byte(&g2);
243 if (color_changes == 0)
249 for (j = 0; j < color_changes; j++) {
253 if ((
unsigned)palette_ptr >= 256)
256 r = bytestream2_get_byte(&g2) << color_shift;
257 g = bytestream2_get_byte(&g2) << color_shift;
258 b = bytestream2_get_byte(&g2) << color_shift;
259 entry = 0xFF
U << 24 | r << 16 | g << 8 |
b;
260 if (color_shift == 2)
261 entry |= entry >> 6 & 0x30303;
262 if (s->
palette[palette_ptr] != entry)
264 s->
palette[palette_ptr++] = entry;
271 compressed_lines = bytestream2_get_le16(&g2);
272 while (compressed_lines > 0) {
275 if (y_ptr > pixel_limit)
277 line_packets =
sign_extend(bytestream2_get_le16(&g2), 16);
278 if ((line_packets & 0xC000) == 0xC000) {
280 line_packets = -line_packets;
284 }
else if ((line_packets & 0xC000) == 0x4000) {
286 }
else if ((line_packets & 0xC000) == 0x8000) {
290 pixels[pixel_ptr] = line_packets & 0xff;
296 for (i = 0; i < line_packets; i++) {
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);
305 byte_run = -byte_run;
306 palette_idx1 = bytestream2_get_byte(&g2);
307 palette_idx2 = bytestream2_get_byte(&g2);
309 for (j = 0; j < byte_run; j++, pixel_countdown -= 2) {
310 pixels[pixel_ptr++] = palette_idx1;
311 pixels[pixel_ptr++] = palette_idx2;
317 for (j = 0; j < byte_run * 2; j++, pixel_countdown--) {
318 pixels[pixel_ptr++] = bytestream2_get_byte(&g2);
330 starting_line = bytestream2_get_le16(&g2);
336 compressed_lines = bytestream2_get_le16(&g2);
337 while (compressed_lines > 0) {
343 line_packets = bytestream2_get_byte(&g2);
344 if (line_packets > 0) {
345 for (i = 0; i < line_packets; i++) {
349 pixel_skip = bytestream2_get_byte(&g2);
350 pixel_ptr += pixel_skip;
351 pixel_countdown -= pixel_skip;
352 byte_run =
sign_extend(bytestream2_get_byte(&g2),8);
357 for (j = 0; j < byte_run; j++, pixel_countdown--) {
358 pixels[pixel_ptr++] = bytestream2_get_byte(&g2);
360 }
else if (byte_run < 0) {
361 byte_run = -byte_run;
362 palette_idx1 = bytestream2_get_byte(&g2);
364 for (j = 0; j < byte_run; j++, pixel_countdown--) {
365 pixels[pixel_ptr++] = palette_idx1;
386 for (lines = 0; lines < s->
avctx->
height; lines++) {
392 while (pixel_countdown > 0) {
395 byte_run =
sign_extend(bytestream2_get_byte(&g2), 8);
402 palette_idx1 = bytestream2_get_byte(&g2);
404 for (j = 0; j < byte_run; j++) {
405 pixels[pixel_ptr++] = palette_idx1;
407 if (pixel_countdown < 0)
409 pixel_countdown, lines);
412 byte_run = -byte_run;
416 for (j = 0; j < byte_run; j++) {
417 pixels[pixel_ptr++] = bytestream2_get_byte(&g2);
419 if (pixel_countdown < 0)
421 pixel_countdown, lines);
434 "has incorrect size, skipping chunk\n", chunk_size - 6);
463 frame_size -= chunk_size;
471 "and final chunk ptr = %d\n", buf_size,
490 void *
data,
int *got_frame,
491 const uint8_t *buf,
int buf_size)
499 unsigned char palette_idx1;
504 unsigned int chunk_size;
510 int compressed_lines;
516 unsigned char *pixels;
518 unsigned int pixel_limit;
528 frame_size = bytestream2_get_le32(&g2);
530 num_chunks = bytestream2_get_le16(&g2);
532 if (frame_size > buf_size)
533 frame_size = buf_size;
540 while ((frame_size > 0) && (num_chunks > 0) &&
542 int stream_ptr_after_chunk;
543 chunk_size = bytestream2_get_le32(&g2);
544 if (chunk_size > frame_size) {
546 "Invalid chunk_size = %u > frame_size = %u\n", chunk_size, frame_size);
551 chunk_type = bytestream2_get_le16(&g2);
554 switch (chunk_type) {
561 "Unexpected Palette chunk %d in non-palettized FLC\n",
569 compressed_lines = bytestream2_get_le16(&g2);
570 while (compressed_lines > 0) {
573 if (y_ptr > pixel_limit)
575 line_packets =
sign_extend(bytestream2_get_le16(&g2), 16);
576 if (line_packets < 0) {
577 line_packets = -line_packets;
586 for (i = 0; i < line_packets; i++) {
590 pixel_skip = bytestream2_get_byte(&g2);
591 pixel_ptr += (pixel_skip*2);
592 pixel_countdown -= pixel_skip;
593 byte_run =
sign_extend(bytestream2_get_byte(&g2), 8);
595 byte_run = -byte_run;
596 pixel = bytestream2_get_le16(&g2);
598 for (j = 0; j < byte_run; j++, pixel_countdown -= 2) {
599 *((
signed short*)(&pixels[pixel_ptr])) = pixel;
606 for (j = 0; j < byte_run; j++, pixel_countdown--) {
607 *((
signed short*)(&pixels[pixel_ptr])) = bytestream2_get_le16(&g2);
625 memset(pixels, 0x0000,
631 for (lines = 0; lines < s->
avctx->
height; lines++) {
638 while (pixel_countdown > 0) {
641 byte_run =
sign_extend(bytestream2_get_byte(&g2), 8);
643 palette_idx1 = bytestream2_get_byte(&g2);
645 for (j = 0; j < byte_run; j++) {
646 pixels[pixel_ptr++] = palette_idx1;
648 if (pixel_countdown < 0)
650 pixel_countdown, lines);
653 byte_run = -byte_run;
657 for (j = 0; j < byte_run; j++) {
658 palette_idx1 = bytestream2_get_byte(&g2);
659 pixels[pixel_ptr++] = palette_idx1;
661 if (pixel_countdown < 0)
663 pixel_countdown, lines);
676 while (pixel_countdown > 0) {
677 *((
signed short*)(&pixels[pixel_ptr])) =
AV_RL16(&buf[pixel_ptr]);
687 for (lines = 0; lines < s->
avctx->
height; lines++) {
694 while (pixel_countdown > 0) {
697 byte_run =
sign_extend(bytestream2_get_byte(&g2), 8);
699 pixel = bytestream2_get_le16(&g2);
701 for (j = 0; j < byte_run; j++) {
702 *((
signed short*)(&pixels[pixel_ptr])) = pixel;
705 if (pixel_countdown < 0)
710 byte_run = -byte_run;
714 for (j = 0; j < byte_run; j++) {
715 *((
signed short*)(&pixels[pixel_ptr])) = bytestream2_get_le16(&g2);
718 if (pixel_countdown < 0)
734 "bigger than image, skipping chunk\n", chunk_size - 6);
743 while (pixel_countdown > 0) {
744 *((
signed short*)(&pixels[y_ptr + pixel_ptr])) = bytestream2_get_le16(&g2);
771 frame_size -= chunk_size;
790 void *
data,
int *got_frame,
791 const uint8_t *buf,
int buf_size)
797 unsigned char palette_idx1;
802 unsigned int chunk_size;
808 int compressed_lines;
814 unsigned char *pixels;
816 unsigned int pixel_limit;
826 frame_size = bytestream2_get_le32(&g2);
828 num_chunks = bytestream2_get_le16(&g2);
830 if (frame_size > buf_size)
831 frame_size = buf_size;
838 while ((frame_size > 0) && (num_chunks > 0) &&
840 int stream_ptr_after_chunk;
841 chunk_size = bytestream2_get_le32(&g2);
842 if (chunk_size > frame_size) {
844 "Invalid chunk_size = %u > frame_size = %u\n", chunk_size, frame_size);
849 chunk_type = bytestream2_get_le16(&g2);
852 switch (chunk_type) {
859 "Unexpected Palette chunk %d in non-palettized FLC\n",
867 compressed_lines = bytestream2_get_le16(&g2);
868 while (compressed_lines > 0) {
871 if (y_ptr > pixel_limit)
873 line_packets =
sign_extend(bytestream2_get_le16(&g2), 16);
874 if (line_packets < 0) {
875 line_packets = -line_packets;
884 for (i = 0; i < line_packets; i++) {
888 pixel_skip = bytestream2_get_byte(&g2);
889 pixel_ptr += (pixel_skip*3);
890 pixel_countdown -= pixel_skip;
891 byte_run =
sign_extend(bytestream2_get_byte(&g2), 8);
893 byte_run = -byte_run;
894 pixel = bytestream2_get_le24(&g2);
896 for (j = 0; j < byte_run; j++, pixel_countdown -= 1) {
897 AV_WL24(&pixels[pixel_ptr], pixel);
904 for (j = 0; j < byte_run; j++, pixel_countdown--) {
905 pixel = bytestream2_get_le24(&g2);
906 AV_WL24(&pixels[pixel_ptr], pixel);
930 for (lines = 0; lines < s->
avctx->
height; lines++) {
937 while (pixel_countdown > 0) {
940 byte_run =
sign_extend(bytestream2_get_byte(&g2), 8);
942 palette_idx1 = bytestream2_get_byte(&g2);
944 for (j = 0; j < byte_run; j++) {
945 pixels[pixel_ptr++] = palette_idx1;
947 if (pixel_countdown < 0)
949 pixel_countdown, lines);
952 byte_run = -byte_run;
956 for (j = 0; j < byte_run; j++) {
957 palette_idx1 = bytestream2_get_byte(&g2);
958 pixels[pixel_ptr++] = palette_idx1;
960 if (pixel_countdown < 0)
962 pixel_countdown, lines);
973 for (lines = 0; lines < s->
avctx->
height; lines++) {
980 while (pixel_countdown > 0) {
983 byte_run =
sign_extend(bytestream2_get_byte(&g2), 8);
985 pixel = bytestream2_get_le24(&g2);
987 for (j = 0; j < byte_run; j++) {
988 AV_WL24(pixels + pixel_ptr, pixel);
991 if (pixel_countdown < 0)
996 byte_run = -byte_run;
1000 for (j = 0; j < byte_run; j++) {
1001 pixel = bytestream2_get_le24(&g2);
1002 AV_WL24(pixels + pixel_ptr, pixel);
1005 if (pixel_countdown < 0)
1021 "bigger than image, skipping chunk\n", chunk_size - 6);
1051 frame_size -= chunk_size;
1070 void *
data,
int *got_frame,
1074 int buf_size = avpkt->
size;
1091 av_log(avctx,
AV_LOG_ERROR,
"Unknown FLC format, my science cannot explain how this happened.\n");
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
This structure describes decoded (raw) audio or video data.
ptrdiff_t const GLvoid * data
#define AV_LOG_WARNING
Something somehow does not look correct.
#define CHECK_PIXEL_PTR(n)
static av_cold int init(AVCodecContext *avctx)
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
static av_always_inline void bytestream2_init(GetByteContext *g, const uint8_t *buf, int buf_size)
static int flic_decode_frame_15_16BPP(AVCodecContext *avctx, void *data, int *got_frame, const uint8_t *buf, int buf_size)
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_WL32 unsigned int_TMPL AV_WL24 unsigned int_TMPL AV_RL16
static void decode(AVCodecContext *dec_ctx, AVPacket *pkt, AVFrame *frame, FILE *outfile)
static int flic_decode_frame_8BPP(AVCodecContext *avctx, void *data, int *got_frame, const uint8_t *buf, int buf_size)
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
8 bits with AV_PIX_FMT_RGB32 palette
int av_frame_ref(AVFrame *dst, const AVFrame *src)
Set up a new reference to the data described by the source frame.
uint8_t * extradata
some codecs need / can use extradata like Huffman tables.
static av_always_inline int bytestream2_get_bytes_left(GetByteContext *g)
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
static int flic_decode_frame_24BPP(AVCodecContext *avctx, void *data, int *got_frame, const uint8_t *buf, int buf_size)
static av_always_inline void bytestream2_skip(GetByteContext *g, unsigned int size)
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
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...
static av_always_inline unsigned int bytestream2_get_buffer(GetByteContext *g, uint8_t *dst, unsigned int size)
#define FLC_MAGIC_CARPET_SYNTHETIC_TYPE_CODE
const char * name
Name of the codec implementation.
int width
picture width / height.
#define FLC_FLX_TYPE_CODE
packed RGB 8:8:8, 24bpp, BGRBGR...
static av_always_inline int bytestream2_tell(GetByteContext *g)
Libavcodec external API header.
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
main external API structure.
#define AVERROR_BUG
Internal bug, also see AVERROR_BUG2.
static int flic_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt)
static av_cold int flic_decode_end(AVCodecContext *avctx)
int palette_has_changed
Tell user application that palette has changed from previous frame.
static av_const int sign_extend(int val, unsigned bits)
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
common internal api header.
#define AV_PIX_FMT_RGB555
#define AV_INPUT_BUFFER_PADDING_SIZE
Required number of additionally allocated bytes at the end of the input bitstream for decoding...
unsigned int palette[256]
#define AV_PIX_FMT_RGB565
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
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_RL32
This structure stores compressed data.
static av_cold int flic_decode_init(AVCodecContext *avctx)
#define AV_CODEC_CAP_DR1
Codec uses get_buffer() or get_encode_buffer() for allocating buffers and supports custom allocators...