Mercurial > libavcodec.hg
annotate anm.c @ 11913:80916e795581 libavcodec
Bump micro version, add changelog entry for DTS-ES extension decoding support
author | mstorsjo |
---|---|
date | Tue, 22 Jun 2010 09:22:21 +0000 |
parents | 7dd2a45249a9 |
children |
rev | line source |
---|---|
10835 | 1 /* |
2 * Deluxe Paint Animation decoder | |
3 * Copyright (c) 2009 Peter Ross | |
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 /** | |
11644
7dd2a45249a9
Remove explicit filename from Doxygen @file commands.
diego
parents:
11560
diff
changeset
|
23 * @file |
10835 | 24 * Deluxe Paint Animation decoder |
25 */ | |
26 | |
27 #include "avcodec.h" | |
28 #include "bytestream.h" | |
29 | |
30 typedef struct AnmContext { | |
31 AVFrame frame; | |
32 int x; ///< x coordinate position | |
33 } AnmContext; | |
34 | |
35 static av_cold int decode_init(AVCodecContext *avctx) | |
36 { | |
37 AnmContext *s = avctx->priv_data; | |
38 const uint8_t *buf; | |
39 int i; | |
40 | |
41 avctx->pix_fmt = PIX_FMT_PAL8; | |
42 | |
43 if (avctx->extradata_size != 16*8 + 4*256) | |
44 return -1; | |
45 | |
46 s->frame.reference = 1; | |
47 if (avctx->get_buffer(avctx, &s->frame) < 0) { | |
48 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); | |
49 return -1; | |
50 } | |
51 | |
52 buf = avctx->extradata + 16*8; | |
53 for (i = 0; i < 256; i++) | |
54 ((uint32_t*)s->frame.data[1])[i] = bytestream_get_le32(&buf); | |
55 | |
56 return 0; | |
57 } | |
58 | |
59 /** | |
60 * Perform decode operation | |
61 * @param dst, dst_end Destination image buffer | |
62 * @param buf, buf_end Source buffer (optional, see below) | |
63 * @param pixel Fill color (optional, see below) | |
64 * @param count Pixel count | |
65 * @param x Pointer to x-axis counter | |
66 * @param width Image width | |
67 * @param linesize Destination image buffer linesize | |
68 * @return non-zero if destination buffer is exhausted | |
69 * | |
70 * a copy operation is achieved when 'buf' is set | |
71 * a fill operation is acheived when 'buf' is null and pixel is >= 0 | |
72 * a skip operation is acheived when 'buf' is null and pixel is < 0 | |
73 */ | |
74 static inline int op(uint8_t **dst, const uint8_t *dst_end, | |
75 const uint8_t **buf, const uint8_t *buf_end, | |
76 int pixel, int count, | |
77 int *x, int width, int linesize) | |
78 { | |
79 int remaining = width - *x; | |
80 while(count > 0) { | |
81 int striplen = FFMIN(count, remaining); | |
82 if (buf) { | |
83 striplen = FFMIN(striplen, buf_end - *buf); | |
84 memcpy(*dst, *buf, striplen); | |
85 *buf += striplen; | |
86 } else if (pixel >= 0) | |
87 memset(*dst, pixel, striplen); | |
88 *dst += striplen; | |
89 remaining -= striplen; | |
90 count -= striplen; | |
91 if (remaining <= 0) { | |
92 *dst += linesize - width; | |
93 remaining = width; | |
94 } | |
95 if (linesize > 0) { | |
96 if (*dst >= dst_end) goto exhausted; | |
97 } else { | |
98 if (*dst <= dst_end) goto exhausted; | |
99 } | |
100 } | |
101 *x = width - remaining; | |
102 return 0; | |
103 | |
104 exhausted: | |
105 *x = width - remaining; | |
106 return 1; | |
107 } | |
108 | |
109 static int decode_frame(AVCodecContext *avctx, | |
110 void *data, int *data_size, | |
111 AVPacket *avpkt) | |
112 { | |
113 AnmContext *s = avctx->priv_data; | |
114 const uint8_t *buf = avpkt->data; | |
115 const int buf_size = avpkt->size; | |
116 const uint8_t *buf_end = buf + buf_size; | |
117 uint8_t *dst, *dst_end; | |
118 int count; | |
119 | |
120 if(avctx->reget_buffer(avctx, &s->frame) < 0){ | |
121 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); | |
122 return -1; | |
123 } | |
124 dst = s->frame.data[0]; | |
125 dst_end = s->frame.data[0] + s->frame.linesize[0]*avctx->height; | |
126 | |
127 if (buf[0] != 0x42) { | |
128 av_log_ask_for_sample(avctx, "unknown record type\n"); | |
129 return buf_size; | |
130 } | |
131 if (buf[1]) { | |
132 av_log_ask_for_sample(avctx, "padding bytes not supported\n"); | |
133 return buf_size; | |
134 } | |
135 buf += 4; | |
136 | |
137 s->x = 0; | |
138 do { | |
139 /* if statements are ordered by probability */ | |
140 #define OP(buf, pixel, count) \ | |
141 op(&dst, dst_end, (buf), buf_end, (pixel), (count), &s->x, avctx->width, s->frame.linesize[0]) | |
142 | |
143 int type = bytestream_get_byte(&buf); | |
144 count = type & 0x7F; | |
145 type >>= 7; | |
146 if (count) { | |
147 if (OP(type ? NULL : &buf, -1, count)) break; | |
148 } else if (!type) { | |
149 int pixel; | |
150 count = bytestream_get_byte(&buf); /* count==0 gives nop */ | |
151 pixel = bytestream_get_byte(&buf); | |
152 if (OP(NULL, pixel, count)) break; | |
153 } else { | |
154 int pixel; | |
155 type = bytestream_get_le16(&buf); | |
156 count = type & 0x3FFF; | |
157 type >>= 14; | |
158 if (!count) { | |
159 if (type == 0) | |
160 break; // stop | |
161 if (type == 2) { | |
162 av_log_ask_for_sample(avctx, "unknown opcode"); | |
163 return AVERROR_INVALIDDATA; | |
164 } | |
165 continue; | |
166 } | |
167 pixel = type == 3 ? bytestream_get_byte(&buf) : -1; | |
168 if (type == 1) count += 0x4000; | |
169 if (OP(type == 2 ? &buf : NULL, pixel, count)) break; | |
170 } | |
171 } while (buf + 1 < buf_end); | |
172 | |
173 *data_size = sizeof(AVFrame); | |
174 *(AVFrame*)data = s->frame; | |
175 return buf_size; | |
176 } | |
177 | |
178 static av_cold int decode_end(AVCodecContext *avctx) | |
179 { | |
180 AnmContext *s = avctx->priv_data; | |
181 if (s->frame.data[0]) | |
182 avctx->release_buffer(avctx, &s->frame); | |
183 return 0; | |
184 } | |
185 | |
186 AVCodec anm_decoder = { | |
187 "anm", | |
11560
8a4984c5cacc
Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents:
10835
diff
changeset
|
188 AVMEDIA_TYPE_VIDEO, |
10835 | 189 CODEC_ID_ANM, |
190 sizeof(AnmContext), | |
191 decode_init, | |
192 NULL, | |
193 decode_end, | |
194 decode_frame, | |
195 CODEC_CAP_DR1, | |
196 .long_name = NULL_IF_CONFIG_SMALL("Deluxe Paint Animation"), | |
197 }; |