79a87dde99e8a8d47e5719e5584277bdb7d89002
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 return AVERROR_INVALIDDATA
;
53 bytestream2_skipu(&s
->gb
, 16 * 8);
54 for (i
= 0; i
< 256; i
++)
55 s
->palette
[i
] = bytestream2_get_le32u(&s
->gb
);
61 * Perform decode operation
62 * @param dst pointer to destination image buffer
63 * @param dst_end pointer to end of destination image buffer
64 * @param gb GetByteContext (optional, see below)
65 * @param pixel Fill color (optional, see below)
66 * @param count Pixel count
67 * @param x Pointer to x-axis counter
68 * @param width Image width
69 * @param linesize Destination image buffer linesize
70 * @return non-zero if destination buffer is exhausted
72 * a copy operation is achieved when 'gb' is set
73 * a fill operation is achieved when 'gb' is null and pixel is >= 0
74 * a skip operation is achieved when 'gb' is null and pixel is < 0
76 static inline int op(uint8_t **dst
, const uint8_t *dst_end
,
79 int *x
, int width
, int linesize
)
81 int remaining
= width
- *x
;
83 int striplen
= FFMIN(count
, remaining
);
85 if (bytestream2_get_bytes_left(gb
) < striplen
)
87 bytestream2_get_bufferu(gb
, *dst
, striplen
);
88 } else if (pixel
>= 0)
89 memset(*dst
, pixel
, striplen
);
91 remaining
-= striplen
;
94 *dst
+= linesize
- width
;
98 if (*dst
>= dst_end
) goto exhausted
;
100 if (*dst
<= dst_end
) goto exhausted
;
103 *x
= width
- remaining
;
107 *x
= width
- remaining
;
111 static int decode_frame(AVCodecContext
*avctx
,
112 void *data
, int *got_frame
,
115 AnmContext
*s
= avctx
->priv_data
;
116 const int buf_size
= avpkt
->size
;
117 uint8_t *dst
, *dst_end
;
120 if ((ret
= ff_reget_buffer(avctx
, s
->frame
)) < 0)
122 dst
= s
->frame
->data
[0];
123 dst_end
= s
->frame
->data
[0] + s
->frame
->linesize
[0]*avctx
->height
;
125 bytestream2_init(&s
->gb
, avpkt
->data
, buf_size
);
127 if (bytestream2_get_byte(&s
->gb
) != 0x42) {
128 avpriv_request_sample(avctx
, "Unknown record type");
129 return AVERROR_INVALIDDATA
;
131 if (bytestream2_get_byte(&s
->gb
)) {
132 avpriv_request_sample(avctx
, "Padding bytes");
133 return AVERROR_PATCHWELCOME
;
135 bytestream2_skip(&s
->gb
, 2);
139 /* if statements are ordered by probability */
140 #define OP(gb, pixel, count) \
141 op(&dst, dst_end, (gb), (pixel), (count), &s->x, avctx->width, s->frame->linesize[0])
143 int type
= bytestream2_get_byte(&s
->gb
);
147 if (OP(type
? NULL
: &s
->gb
, -1, count
)) break;
150 count
= bytestream2_get_byte(&s
->gb
); /* count==0 gives nop */
151 pixel
= bytestream2_get_byte(&s
->gb
);
152 if (OP(NULL
, pixel
, count
)) break;
155 type
= bytestream2_get_le16(&s
->gb
);
156 count
= type
& 0x3FFF;
162 avpriv_request_sample(avctx
, "Unknown opcode");
163 return AVERROR_PATCHWELCOME
;
167 pixel
= type
== 3 ? bytestream2_get_byte(&s
->gb
) : -1;
168 if (type
== 1) count
+= 0x4000;
169 if (OP(type
== 2 ? &s
->gb
: NULL
, pixel
, count
)) break;
171 } while (bytestream2_get_bytes_left(&s
->gb
) > 0);
173 memcpy(s
->frame
->data
[1], s
->palette
, AVPALETTE_SIZE
);
176 if ((ret
= av_frame_ref(data
, s
->frame
)) < 0)
182 static av_cold
int decode_end(AVCodecContext
*avctx
)
184 AnmContext
*s
= avctx
->priv_data
;
186 av_frame_free(&s
->frame
);
190 AVCodec ff_anm_decoder
= {
192 .long_name
= NULL_IF_CONFIG_SMALL("Deluxe Paint Animation"),
193 .type
= AVMEDIA_TYPE_VIDEO
,
194 .id
= AV_CODEC_ID_ANM
,
195 .priv_data_size
= sizeof(AnmContext
),
198 .decode
= decode_frame
,
199 .capabilities
= CODEC_CAP_DR1
,