Mercurial > libavcodec.hg
annotate gifdec.c @ 12266:48d6738904a9 libavcodec
Fix SPLATB_REG mess. Used to be a if/elseif/elseif/elseif spaghetti, so this
splits it into small optimization-specific macros which are selected for each
DSP function. The advantage of this approach is that the sse4 functions now
use the ssse3 codepath also without needing an explicit sse4 codepath.
author | rbultje |
---|---|
date | Sat, 24 Jul 2010 19:33:05 +0000 |
parents | 8a4984c5cacc |
children | 914f484bb476 |
rev | line source |
---|---|
4054 | 1 /* |
2 * GIF decoder | |
8629
04423b2f6e0b
cosmetics: Remove pointless period after copyright statement non-sentences.
diego
parents:
7040
diff
changeset
|
3 * Copyright (c) 2003 Fabrice Bellard |
04423b2f6e0b
cosmetics: Remove pointless period after copyright statement non-sentences.
diego
parents:
7040
diff
changeset
|
4 * Copyright (c) 2006 Baptiste Coudurier |
4054 | 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 | |
9355
54bc8a2727b0
Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents:
8629
diff
changeset
|
285 static int gif_decode_frame(AVCodecContext *avctx, void *data, int *data_size, AVPacket *avpkt) |
4054 | 286 { |
9355
54bc8a2727b0
Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents:
8629
diff
changeset
|
287 const uint8_t *buf = avpkt->data; |
54bc8a2727b0
Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents:
8629
diff
changeset
|
288 int buf_size = avpkt->size; |
4054 | 289 GifState *s = avctx->priv_data; |
290 AVFrame *picture = data; | |
291 int ret; | |
292 | |
293 s->bytestream = buf; | |
4718 | 294 s->bytestream_end = buf + buf_size; |
4054 | 295 if (gif_read_header1(s) < 0) |
296 return -1; | |
297 | |
298 avctx->pix_fmt = PIX_FMT_PAL8; | |
4058 | 299 if (avcodec_check_dimensions(avctx, s->screen_width, s->screen_height)) |
300 return -1; | |
301 avcodec_set_dimensions(avctx, s->screen_width, s->screen_height); | |
4054 | 302 |
4058 | 303 if (s->picture.data[0]) |
304 avctx->release_buffer(avctx, &s->picture); | |
305 if (avctx->get_buffer(avctx, &s->picture) < 0) { | |
306 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); | |
307 return -1; | |
308 } | |
309 s->image_palette = (uint32_t *)s->picture.data[1]; | |
4054 | 310 ret = gif_parse_next_image(s); |
311 if (ret < 0) | |
312 return ret; | |
313 | |
4058 | 314 *picture = s->picture; |
315 *data_size = sizeof(AVPicture); | |
4719 | 316 return s->bytestream - buf; |
4058 | 317 } |
4054 | 318 |
6517
48759bfbd073
Apply 'cold' attribute to init/uninit functions in libavcodec
zuxy
parents:
6462
diff
changeset
|
319 static av_cold int gif_decode_close(AVCodecContext *avctx) |
4058 | 320 { |
321 GifState *s = avctx->priv_data; | |
322 | |
4080
f426c81afc9e
LZW decoder as separate module plus TIFF LZW support
kostya
parents:
4060
diff
changeset
|
323 ff_lzw_decode_close(&s->lzw); |
4058 | 324 if(s->picture.data[0]) |
325 avctx->release_buffer(avctx, &s->picture); | |
4054 | 326 return 0; |
327 } | |
328 | |
329 AVCodec gif_decoder = { | |
330 "gif", | |
11560
8a4984c5cacc
Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents:
9734
diff
changeset
|
331 AVMEDIA_TYPE_VIDEO, |
4054 | 332 CODEC_ID_GIF, |
333 sizeof(GifState), | |
334 gif_decode_init, | |
335 NULL, | |
4058 | 336 gif_decode_close, |
4054 | 337 gif_decode_frame, |
9734 | 338 CODEC_CAP_DR1, |
7040
e943e1409077
Make AVCodec long_names definition conditional depending on CONFIG_SMALL.
stefano
parents:
6712
diff
changeset
|
339 .long_name = NULL_IF_CONFIG_SMALL("GIF (Graphics Interchange Format)"), |
4054 | 340 }; |