2 * Deluxe Paint Animation decoder
3 * Copyright (c) 2009 Peter Ross
5 * This file is part of FFmpeg.
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.
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.
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
24 * Deluxe Paint Animation decoder
28 #include "bytestream.h"
31 typedef struct AnmContext
{
33 int palette
[AVPALETTE_COUNT
];
35 int x
; ///< x coordinate position
38 static av_cold
int decode_init(AVCodecContext
*avctx
)
40 AnmContext
*s
= avctx
->priv_data
;
43 avctx
->pix_fmt
= AV_PIX_FMT_PAL8
;
45 s
->frame
= av_frame_alloc();
47 return AVERROR(ENOMEM
);
49 bytestream2_init(&s
->gb
, avctx
->extradata
, avctx
->extradata_size
);
50 if (bytestream2_get_bytes_left(&s
->gb
) < 16 * 8 + 4 * 256) {
51 av_frame_free(&s
->frame
);
52 return AVERROR_INVALIDDATA
;
55 bytestream2_skipu(&s
->gb
, 16 * 8);
56 for (i
= 0; i
< 256; i
++)
57 s
->palette
[i
] = bytestream2_get_le32u(&s
->gb
);
63 * Perform decode operation
64 * @param dst pointer to destination image buffer
65 * @param dst_end pointer to end of destination image buffer
66 * @param gb GetByteContext (optional, see below)
67 * @param pixel Fill color (optional, see below)
68 * @param count Pixel count
69 * @param x Pointer to x-axis counter
70 * @param width Image width
71 * @param linesize Destination image buffer linesize
72 * @return non-zero if destination buffer is exhausted
74 * a copy operation is achieved when 'gb' is set
75 * a fill operation is achieved when 'gb' is null and pixel is >= 0
76 * a skip operation is achieved when 'gb' is null and pixel is < 0
78 static inline int op(uint8_t **dst
, const uint8_t *dst_end
,
81 int *x
, int width
, int linesize
)
83 int remaining
= width
- *x
;
85 int striplen
= FFMIN(count
, remaining
);
87 if (bytestream2_get_bytes_left(gb
) < striplen
)
89 bytestream2_get_bufferu(gb
, *dst
, striplen
);
90 } else if (pixel
>= 0)
91 memset(*dst
, pixel
, striplen
);
93 remaining
-= striplen
;
96 *dst
+= linesize
- width
;
100 if (*dst
>= dst_end
) goto exhausted
;
102 if (*dst
<= dst_end
) goto exhausted
;
105 *x
= width
- remaining
;
109 *x
= width
- remaining
;
113 static int decode_frame(AVCodecContext
*avctx
,
114 void *data
, int *got_frame
,
117 AnmContext
*s
= avctx
->priv_data
;
118 const int buf_size
= avpkt
->size
;
119 uint8_t *dst
, *dst_end
;
122 if ((ret
= ff_reget_buffer(avctx
, s
->frame
)) < 0)
124 dst
= s
->frame
->data
[0];
125 dst_end
= s
->frame
->data
[0] + s
->frame
->linesize
[0]*avctx
->height
;
127 bytestream2_init(&s
->gb
, avpkt
->data
, buf_size
);
129 if (bytestream2_get_byte(&s
->gb
) != 0x42) {
130 avpriv_request_sample(avctx
, "Unknown record type");
131 return AVERROR_INVALIDDATA
;
133 if (bytestream2_get_byte(&s
->gb
)) {
134 avpriv_request_sample(avctx
, "Padding bytes");
135 return AVERROR_PATCHWELCOME
;
137 bytestream2_skip(&s
->gb
, 2);
141 /* if statements are ordered by probability */
142 #define OP(gb, pixel, count) \
143 op(&dst, dst_end, (gb), (pixel), (count), &s->x, avctx->width, s->frame->linesize[0])
145 int type
= bytestream2_get_byte(&s
->gb
);
149 if (OP(type
? NULL
: &s
->gb
, -1, count
)) break;
152 count
= bytestream2_get_byte(&s
->gb
); /* count==0 gives nop */
153 pixel
= bytestream2_get_byte(&s
->gb
);
154 if (OP(NULL
, pixel
, count
)) break;
157 type
= bytestream2_get_le16(&s
->gb
);
158 count
= type
& 0x3FFF;
164 avpriv_request_sample(avctx
, "Unknown opcode");
165 return AVERROR_PATCHWELCOME
;
169 pixel
= type
== 3 ? bytestream2_get_byte(&s
->gb
) : -1;
170 if (type
== 1) count
+= 0x4000;
171 if (OP(type
== 2 ? &s
->gb
: NULL
, pixel
, count
)) break;
173 } while (bytestream2_get_bytes_left(&s
->gb
) > 0);
175 memcpy(s
->frame
->data
[1], s
->palette
, AVPALETTE_SIZE
);
178 if ((ret
= av_frame_ref(data
, s
->frame
)) < 0)
184 static av_cold
int decode_end(AVCodecContext
*avctx
)
186 AnmContext
*s
= avctx
->priv_data
;
188 av_frame_free(&s
->frame
);
192 AVCodec ff_anm_decoder
= {
194 .long_name
= NULL_IF_CONFIG_SMALL("Deluxe Paint Animation"),
195 .type
= AVMEDIA_TYPE_VIDEO
,
196 .id
= AV_CODEC_ID_ANM
,
197 .priv_data_size
= sizeof(AnmContext
),
200 .decode
= decode_frame
,
201 .capabilities
= CODEC_CAP_DR1
,