2 * Deluxe Paint Animation decoder
3 * Copyright (c) 2009 Peter Ross
5 * This file is part of Libav.
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.
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.
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
24 * Deluxe Paint Animation decoder
28 #include "bytestream.h"
30 typedef struct AnmContext
{
32 int palette
[AVPALETTE_COUNT
];
34 int x
; ///< x coordinate position
37 static av_cold
int decode_init(AVCodecContext
*avctx
)
39 AnmContext
*s
= avctx
->priv_data
;
42 avctx
->pix_fmt
= AV_PIX_FMT_PAL8
;
44 s
->frame
.reference
= 1;
45 bytestream2_init(&s
->gb
, avctx
->extradata
, avctx
->extradata_size
);
46 if (bytestream2_get_bytes_left(&s
->gb
) < 16 * 8 + 4 * 256)
47 return AVERROR_INVALIDDATA
;
49 bytestream2_skipu(&s
->gb
, 16 * 8);
50 for (i
= 0; i
< 256; i
++)
51 s
->palette
[i
] = bytestream2_get_le32u(&s
->gb
);
57 * Perform decode operation
58 * @param dst pointer to destination image buffer
59 * @param dst_end pointer to end of destination image buffer
60 * @param gb GetByteContext (optional, see below)
61 * @param pixel Fill color (optional, see below)
62 * @param count Pixel count
63 * @param x Pointer to x-axis counter
64 * @param width Image width
65 * @param linesize Destination image buffer linesize
66 * @return non-zero if destination buffer is exhausted
68 * a copy operation is achieved when 'gb' is set
69 * a fill operation is achieved when 'gb' is null and pixel is >= 0
70 * a skip operation is achieved when 'gb' is null and pixel is < 0
72 static inline int op(uint8_t **dst
, const uint8_t *dst_end
,
75 int *x
, int width
, int linesize
)
77 int remaining
= width
- *x
;
79 int striplen
= FFMIN(count
, remaining
);
81 if (bytestream2_get_bytes_left(gb
) < striplen
)
83 bytestream2_get_bufferu(gb
, *dst
, striplen
);
84 } else if (pixel
>= 0)
85 memset(*dst
, pixel
, striplen
);
87 remaining
-= striplen
;
90 *dst
+= linesize
- width
;
94 if (*dst
>= dst_end
) goto exhausted
;
96 if (*dst
<= dst_end
) goto exhausted
;
99 *x
= width
- remaining
;
103 *x
= width
- remaining
;
107 static int decode_frame(AVCodecContext
*avctx
,
108 void *data
, int *got_frame
,
111 AnmContext
*s
= avctx
->priv_data
;
112 const int buf_size
= avpkt
->size
;
113 uint8_t *dst
, *dst_end
;
116 if ((ret
= avctx
->reget_buffer(avctx
, &s
->frame
)) < 0){
117 av_log(avctx
, AV_LOG_ERROR
, "get_buffer() failed\n");
120 dst
= s
->frame
.data
[0];
121 dst_end
= s
->frame
.data
[0] + s
->frame
.linesize
[0]*avctx
->height
;
123 bytestream2_init(&s
->gb
, avpkt
->data
, buf_size
);
125 if (bytestream2_get_byte(&s
->gb
) != 0x42) {
126 av_log_ask_for_sample(avctx
, "unknown record type\n");
129 if (bytestream2_get_byte(&s
->gb
)) {
130 av_log_ask_for_sample(avctx
, "padding bytes not supported\n");
133 bytestream2_skip(&s
->gb
, 2);
137 /* if statements are ordered by probability */
138 #define OP(gb, pixel, count) \
139 op(&dst, dst_end, (gb), (pixel), (count), &s->x, avctx->width, s->frame.linesize[0])
141 int type
= bytestream2_get_byte(&s
->gb
);
145 if (OP(type
? NULL
: &s
->gb
, -1, count
)) break;
148 count
= bytestream2_get_byte(&s
->gb
); /* count==0 gives nop */
149 pixel
= bytestream2_get_byte(&s
->gb
);
150 if (OP(NULL
, pixel
, count
)) break;
153 type
= bytestream2_get_le16(&s
->gb
);
154 count
= type
& 0x3FFF;
160 av_log_ask_for_sample(avctx
, "unknown opcode");
161 return AVERROR_PATCHWELCOME
;
165 pixel
= type
== 3 ? bytestream2_get_byte(&s
->gb
) : -1;
166 if (type
== 1) count
+= 0x4000;
167 if (OP(type
== 2 ? &s
->gb
: NULL
, pixel
, count
)) break;
169 } while (bytestream2_get_bytes_left(&s
->gb
) > 0);
171 memcpy(s
->frame
.data
[1], s
->palette
, AVPALETTE_SIZE
);
174 *(AVFrame
*)data
= s
->frame
;
178 static av_cold
int decode_end(AVCodecContext
*avctx
)
180 AnmContext
*s
= avctx
->priv_data
;
181 if (s
->frame
.data
[0])
182 avctx
->release_buffer(avctx
, &s
->frame
);
186 AVCodec ff_anm_decoder
= {
188 .type
= AVMEDIA_TYPE_VIDEO
,
189 .id
= AV_CODEC_ID_ANM
,
190 .priv_data_size
= sizeof(AnmContext
),
193 .decode
= decode_frame
,
194 .capabilities
= CODEC_CAP_DR1
,
195 .long_name
= NULL_IF_CONFIG_SMALL("Deluxe Paint Animation"),