Mercurial > libavcodec.hg
annotate gifdec.c @ 7983:47f50599b368 libavcodec
x264 has removed the b-rdo and bime options, and instead integrated
them into the subme number to attempt to reduce the number of
unnecessary options. subme now scales up to 9.
Patch by Jason Garett-Glaser %darkshikari A gmail P com%
author | gpoirier |
---|---|
date | Thu, 02 Oct 2008 19:05:35 +0000 |
parents | e943e1409077 |
children | 04423b2f6e0b |
rev | line source |
---|---|
4054 | 1 /* |
2 * GIF decoder | |
3 * Copyright (c) 2003 Fabrice Bellard. | |
4 * Copyright (c) 2006 Baptiste Coudurier. | |
5 * | |
6 * This file is part of FFmpeg. | |
7 * | |
8 * FFmpeg is free software; you can redistribute it and/or | |
9 * modify it under the terms of the GNU Lesser General Public | |
10 * License as published by the Free Software Foundation; either | |
11 * version 2.1 of the License, or (at your option) any later version. | |
12 * | |
13 * FFmpeg is distributed in the hope that it will be useful, | |
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
16 * Lesser General Public License for more details. | |
17 * | |
18 * You should have received a copy of the GNU Lesser General Public | |
19 * License along with FFmpeg; if not, write to the Free Software | |
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
21 */ | |
22 | |
23 //#define DEBUG | |
24 | |
25 #include "avcodec.h" | |
26 #include "bytestream.h" | |
4080
f426c81afc9e
LZW decoder as separate module plus TIFF LZW support
kostya
parents:
4060
diff
changeset
|
27 #include "lzw.h" |
4054 | 28 |
29 #define GCE_DISPOSAL_NONE 0 | |
30 #define GCE_DISPOSAL_INPLACE 1 | |
31 #define GCE_DISPOSAL_BACKGROUND 2 | |
32 #define GCE_DISPOSAL_RESTORE 3 | |
33 | |
34 typedef struct GifState { | |
4058 | 35 AVFrame picture; |
4054 | 36 int screen_width; |
37 int screen_height; | |
38 int bits_per_pixel; | |
39 int background_color_index; | |
40 int transparent_color_index; | |
41 int color_resolution; | |
4058 | 42 uint32_t *image_palette; |
4054 | 43 |
44 /* after the frame is displayed, the disposal method is used */ | |
45 int gce_disposal; | |
46 /* delay during which the frame is shown */ | |
47 int gce_delay; | |
48 | |
49 /* LZW compatible decoder */ | |
6218 | 50 const uint8_t *bytestream; |
51 const uint8_t *bytestream_end; | |
4080
f426c81afc9e
LZW decoder as separate module plus TIFF LZW support
kostya
parents:
4060
diff
changeset
|
52 LZWState *lzw; |
4054 | 53 |
54 /* aux buffers */ | |
55 uint8_t global_palette[256 * 3]; | |
56 uint8_t local_palette[256 * 3]; | |
4652 | 57 |
58 AVCodecContext* avctx; | |
4054 | 59 } GifState; |
60 | |
61 static const uint8_t gif87a_sig[6] = "GIF87a"; | |
62 static const uint8_t gif89a_sig[6] = "GIF89a"; | |
63 | |
64 static int gif_read_image(GifState *s) | |
65 { | |
66 int left, top, width, height, bits_per_pixel, code_size, flags; | |
4057 | 67 int is_interleaved, has_local_palette, y, pass, y1, linesize, n, i; |
4144 | 68 uint8_t *ptr, *spal, *palette, *ptr1; |
4054 | 69 |
70 left = bytestream_get_le16(&s->bytestream); | |
71 top = bytestream_get_le16(&s->bytestream); | |
72 width = bytestream_get_le16(&s->bytestream); | |
73 height = bytestream_get_le16(&s->bytestream); | |
74 flags = bytestream_get_byte(&s->bytestream); | |
75 is_interleaved = flags & 0x40; | |
76 has_local_palette = flags & 0x80; | |
77 bits_per_pixel = (flags & 0x07) + 1; | |
78 #ifdef DEBUG | |
4652 | 79 dprintf(s->avctx, "gif: image x=%d y=%d w=%d h=%d\n", left, top, width, height); |
4054 | 80 #endif |
81 | |
82 if (has_local_palette) { | |
83 bytestream_get_buffer(&s->bytestream, s->local_palette, 3 * (1 << bits_per_pixel)); | |
84 palette = s->local_palette; | |
85 } else { | |
86 palette = s->global_palette; | |
87 bits_per_pixel = s->bits_per_pixel; | |
88 } | |
89 | |
90 /* verify that all the image is inside the screen dimensions */ | |
91 if (left + width > s->screen_width || | |
92 top + height > s->screen_height) | |
4520
9bf957e669f0
This fixes error handling for BeOS, removing the need for some ifdefs.
mmu_man
parents:
4144
diff
changeset
|
93 return AVERROR(EINVAL); |
4054 | 94 |
95 /* build the palette */ | |
4060 | 96 n = (1 << bits_per_pixel); |
97 spal = palette; | |
98 for(i = 0; i < n; i++) { | |
5089 | 99 s->image_palette[i] = (0xff << 24) | AV_RB24(spal); |
4060 | 100 spal += 3; |
101 } | |
102 for(; i < 256; i++) | |
103 s->image_palette[i] = (0xff << 24); | |
104 /* handle transparency */ | |
105 if (s->transparent_color_index >= 0) | |
106 s->image_palette[s->transparent_color_index] = 0; | |
4054 | 107 |
108 /* now get the image data */ | |
109 code_size = bytestream_get_byte(&s->bytestream); | |
4729 | 110 ff_lzw_decode_init(s->lzw, code_size, s->bytestream, |
111 s->bytestream_end - s->bytestream, FF_LZW_GIF); | |
4054 | 112 |
113 /* read all the image */ | |
4058 | 114 linesize = s->picture.linesize[0]; |
4143 | 115 ptr1 = s->picture.data[0] + top * linesize + left; |
4054 | 116 ptr = ptr1; |
117 pass = 0; | |
118 y1 = 0; | |
119 for (y = 0; y < height; y++) { | |
4080
f426c81afc9e
LZW decoder as separate module plus TIFF LZW support
kostya
parents:
4060
diff
changeset
|
120 ff_lzw_decode(s->lzw, ptr, width); |
4054 | 121 if (is_interleaved) { |
122 switch(pass) { | |
123 default: | |
124 case 0: | |
125 case 1: | |
126 y1 += 8; | |
127 ptr += linesize * 8; | |
128 if (y1 >= height) { | |
6462
745a4216b352
fix interlaced decoding, original patch from reimar
bcoudurier
parents:
6218
diff
changeset
|
129 y1 = pass ? 2 : 4; |
745a4216b352
fix interlaced decoding, original patch from reimar
bcoudurier
parents:
6218
diff
changeset
|
130 ptr = ptr1 + linesize * y1; |
4054 | 131 pass++; |
132 } | |
133 break; | |
134 case 2: | |
135 y1 += 4; | |
136 ptr += linesize * 4; | |
137 if (y1 >= height) { | |
138 y1 = 1; | |
139 ptr = ptr1 + linesize; | |
140 pass++; | |
141 } | |
142 break; | |
143 case 3: | |
144 y1 += 2; | |
145 ptr += linesize * 2; | |
146 break; | |
147 } | |
148 } else { | |
149 ptr += linesize; | |
150 } | |
151 } | |
152 /* read the garbage data until end marker is found */ | |
4080
f426c81afc9e
LZW decoder as separate module plus TIFF LZW support
kostya
parents:
4060
diff
changeset
|
153 ff_lzw_decode_tail(s->lzw); |
f426c81afc9e
LZW decoder as separate module plus TIFF LZW support
kostya
parents:
4060
diff
changeset
|
154 s->bytestream = ff_lzw_cur_ptr(s->lzw); |
4054 | 155 return 0; |
156 } | |
157 | |
158 static int gif_read_extension(GifState *s) | |
159 { | |
160 int ext_code, ext_len, i, gce_flags, gce_transparent_index; | |
161 | |
162 /* extension */ | |
163 ext_code = bytestream_get_byte(&s->bytestream); | |
164 ext_len = bytestream_get_byte(&s->bytestream); | |
165 #ifdef DEBUG | |
4652 | 166 dprintf(s->avctx, "gif: ext_code=0x%x len=%d\n", ext_code, ext_len); |
4054 | 167 #endif |
168 switch(ext_code) { | |
169 case 0xf9: | |
170 if (ext_len != 4) | |
171 goto discard_ext; | |
172 s->transparent_color_index = -1; | |
173 gce_flags = bytestream_get_byte(&s->bytestream); | |
174 s->gce_delay = bytestream_get_le16(&s->bytestream); | |
175 gce_transparent_index = bytestream_get_byte(&s->bytestream); | |
176 if (gce_flags & 0x01) | |
177 s->transparent_color_index = gce_transparent_index; | |
178 else | |
179 s->transparent_color_index = -1; | |
180 s->gce_disposal = (gce_flags >> 2) & 0x7; | |
181 #ifdef DEBUG | |
4652 | 182 dprintf(s->avctx, "gif: gce_flags=%x delay=%d tcolor=%d disposal=%d\n", |
4054 | 183 gce_flags, s->gce_delay, |
184 s->transparent_color_index, s->gce_disposal); | |
185 #endif | |
186 ext_len = bytestream_get_byte(&s->bytestream); | |
187 break; | |
188 } | |
189 | |
190 /* NOTE: many extension blocks can come after */ | |
191 discard_ext: | |
192 while (ext_len != 0) { | |
193 for (i = 0; i < ext_len; i++) | |
194 bytestream_get_byte(&s->bytestream); | |
195 ext_len = bytestream_get_byte(&s->bytestream); | |
196 #ifdef DEBUG | |
4652 | 197 dprintf(s->avctx, "gif: ext_len1=%d\n", ext_len); |
4054 | 198 #endif |
199 } | |
200 return 0; | |
201 } | |
202 | |
203 static int gif_read_header1(GifState *s) | |
204 { | |
205 uint8_t sig[6]; | |
4057 | 206 int v, n; |
4054 | 207 int has_global_palette; |
208 | |
4718 | 209 if (s->bytestream_end < s->bytestream + 13) |
210 return -1; | |
211 | |
4054 | 212 /* read gif signature */ |
213 bytestream_get_buffer(&s->bytestream, sig, 6); | |
214 if (memcmp(sig, gif87a_sig, 6) != 0 && | |
215 memcmp(sig, gif89a_sig, 6) != 0) | |
216 return -1; | |
217 | |
218 /* read screen header */ | |
219 s->transparent_color_index = -1; | |
220 s->screen_width = bytestream_get_le16(&s->bytestream); | |
221 s->screen_height = bytestream_get_le16(&s->bytestream); | |
222 if( (unsigned)s->screen_width > 32767 | |
223 || (unsigned)s->screen_height > 32767){ | |
224 av_log(NULL, AV_LOG_ERROR, "picture size too large\n"); | |
225 return -1; | |
226 } | |
227 | |
228 v = bytestream_get_byte(&s->bytestream); | |
229 s->color_resolution = ((v & 0x70) >> 4) + 1; | |
230 has_global_palette = (v & 0x80); | |
231 s->bits_per_pixel = (v & 0x07) + 1; | |
232 s->background_color_index = bytestream_get_byte(&s->bytestream); | |
233 bytestream_get_byte(&s->bytestream); /* ignored */ | |
234 #ifdef DEBUG | |
4652 | 235 dprintf(s->avctx, "gif: screen_w=%d screen_h=%d bpp=%d global_palette=%d\n", |
4054 | 236 s->screen_width, s->screen_height, s->bits_per_pixel, |
237 has_global_palette); | |
238 #endif | |
239 if (has_global_palette) { | |
240 n = 1 << s->bits_per_pixel; | |
4718 | 241 if (s->bytestream_end < s->bytestream + n * 3) |
242 return -1; | |
4054 | 243 bytestream_get_buffer(&s->bytestream, s->global_palette, n * 3); |
244 } | |
245 return 0; | |
246 } | |
247 | |
248 static int gif_parse_next_image(GifState *s) | |
249 { | |
4718 | 250 while (s->bytestream < s->bytestream_end) { |
4717 | 251 int code = bytestream_get_byte(&s->bytestream); |
4054 | 252 #ifdef DEBUG |
4652 | 253 dprintf(s->avctx, "gif: code=%02x '%c'\n", code, code); |
4054 | 254 #endif |
255 switch (code) { | |
256 case ',': | |
4874
f06463413858
simplify, patch by Mark Cox, melbournemark plus ffmpeg minus devel gmail com
bcoudurier
parents:
4868
diff
changeset
|
257 return gif_read_image(s); |
4054 | 258 case '!': |
259 if (gif_read_extension(s) < 0) | |
260 return -1; | |
261 break; | |
4874
f06463413858
simplify, patch by Mark Cox, melbournemark plus ffmpeg minus devel gmail com
bcoudurier
parents:
4868
diff
changeset
|
262 case ';': |
f06463413858
simplify, patch by Mark Cox, melbournemark plus ffmpeg minus devel gmail com
bcoudurier
parents:
4868
diff
changeset
|
263 /* end of image */ |
4054 | 264 default: |
4868 | 265 /* error or erroneous EOF */ |
4717 | 266 return -1; |
4054 | 267 } |
268 } | |
4720
7775ba23c931
return error if loop has ended before decoding image
bcoudurier
parents:
4719
diff
changeset
|
269 return -1; |
4054 | 270 } |
271 | |
6517
48759bfbd073
Apply 'cold' attribute to init/uninit functions in libavcodec
zuxy
parents:
6462
diff
changeset
|
272 static av_cold int gif_decode_init(AVCodecContext *avctx) |
4054 | 273 { |
274 GifState *s = avctx->priv_data; | |
275 | |
4652 | 276 s->avctx = avctx; |
277 | |
4058 | 278 avcodec_get_frame_defaults(&s->picture); |
279 avctx->coded_frame= &s->picture; | |
280 s->picture.data[0] = NULL; | |
4080
f426c81afc9e
LZW decoder as separate module plus TIFF LZW support
kostya
parents:
4060
diff
changeset
|
281 ff_lzw_decode_open(&s->lzw); |
4054 | 282 return 0; |
283 } | |
284 | |
6218 | 285 static int gif_decode_frame(AVCodecContext *avctx, void *data, int *data_size, const uint8_t *buf, int buf_size) |
4054 | 286 { |
287 GifState *s = avctx->priv_data; | |
288 AVFrame *picture = data; | |
289 int ret; | |
290 | |
291 s->bytestream = buf; | |
4718 | 292 s->bytestream_end = buf + buf_size; |
4054 | 293 if (gif_read_header1(s) < 0) |
294 return -1; | |
295 | |
296 avctx->pix_fmt = PIX_FMT_PAL8; | |
4058 | 297 if (avcodec_check_dimensions(avctx, s->screen_width, s->screen_height)) |
298 return -1; | |
299 avcodec_set_dimensions(avctx, s->screen_width, s->screen_height); | |
4054 | 300 |
4058 | 301 if (s->picture.data[0]) |
302 avctx->release_buffer(avctx, &s->picture); | |
303 if (avctx->get_buffer(avctx, &s->picture) < 0) { | |
304 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); | |
305 return -1; | |
306 } | |
307 s->image_palette = (uint32_t *)s->picture.data[1]; | |
4054 | 308 ret = gif_parse_next_image(s); |
309 if (ret < 0) | |
310 return ret; | |
311 | |
4058 | 312 *picture = s->picture; |
313 *data_size = sizeof(AVPicture); | |
4719 | 314 return s->bytestream - buf; |
4058 | 315 } |
4054 | 316 |
6517
48759bfbd073
Apply 'cold' attribute to init/uninit functions in libavcodec
zuxy
parents:
6462
diff
changeset
|
317 static av_cold int gif_decode_close(AVCodecContext *avctx) |
4058 | 318 { |
319 GifState *s = avctx->priv_data; | |
320 | |
4080
f426c81afc9e
LZW decoder as separate module plus TIFF LZW support
kostya
parents:
4060
diff
changeset
|
321 ff_lzw_decode_close(&s->lzw); |
4058 | 322 if(s->picture.data[0]) |
323 avctx->release_buffer(avctx, &s->picture); | |
4054 | 324 return 0; |
325 } | |
326 | |
327 AVCodec gif_decoder = { | |
328 "gif", | |
329 CODEC_TYPE_VIDEO, | |
330 CODEC_ID_GIF, | |
331 sizeof(GifState), | |
332 gif_decode_init, | |
333 NULL, | |
4058 | 334 gif_decode_close, |
4054 | 335 gif_decode_frame, |
7040
e943e1409077
Make AVCodec long_names definition conditional depending on CONFIG_SMALL.
stefano
parents:
6712
diff
changeset
|
336 .long_name = NULL_IF_CONFIG_SMALL("GIF (Graphics Interchange Format)"), |
4054 | 337 }; |