Mercurial > libavcodec.hg
annotate gifdec.c @ 12483:0159a19bfff7 libavcodec
aacdec: Rework channel mapping compatibility hacks.
For a PCE based configuration map the channels solely based on tags.
For an indexed configuration map the channels solely based on position.
This works with all known exotic samples including al17, elem_id0, bad_concat,
and lfe_is_sce.
author | alexc |
---|---|
date | Fri, 10 Sep 2010 18:01:48 +0000 |
parents | ffb3668ff7af |
children |
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 | |
12372
914f484bb476
Remove use of the deprecated function avcodec_check_dimensions(), use
stefano
parents:
11560
diff
changeset
|
25 #include "libavcore/imgutils.h" |
4054 | 26 #include "avcodec.h" |
27 #include "bytestream.h" | |
4080
f426c81afc9e
LZW decoder as separate module plus TIFF LZW support
kostya
parents:
4060
diff
changeset
|
28 #include "lzw.h" |
4054 | 29 |
30 #define GCE_DISPOSAL_NONE 0 | |
31 #define GCE_DISPOSAL_INPLACE 1 | |
32 #define GCE_DISPOSAL_BACKGROUND 2 | |
33 #define GCE_DISPOSAL_RESTORE 3 | |
34 | |
35 typedef struct GifState { | |
4058 | 36 AVFrame picture; |
4054 | 37 int screen_width; |
38 int screen_height; | |
39 int bits_per_pixel; | |
40 int background_color_index; | |
41 int transparent_color_index; | |
42 int color_resolution; | |
4058 | 43 uint32_t *image_palette; |
4054 | 44 |
45 /* after the frame is displayed, the disposal method is used */ | |
46 int gce_disposal; | |
47 /* delay during which the frame is shown */ | |
48 int gce_delay; | |
49 | |
50 /* LZW compatible decoder */ | |
6218 | 51 const uint8_t *bytestream; |
52 const uint8_t *bytestream_end; | |
4080
f426c81afc9e
LZW decoder as separate module plus TIFF LZW support
kostya
parents:
4060
diff
changeset
|
53 LZWState *lzw; |
4054 | 54 |
55 /* aux buffers */ | |
56 uint8_t global_palette[256 * 3]; | |
57 uint8_t local_palette[256 * 3]; | |
4652 | 58 |
59 AVCodecContext* avctx; | |
4054 | 60 } GifState; |
61 | |
62 static const uint8_t gif87a_sig[6] = "GIF87a"; | |
63 static const uint8_t gif89a_sig[6] = "GIF89a"; | |
64 | |
65 static int gif_read_image(GifState *s) | |
66 { | |
67 int left, top, width, height, bits_per_pixel, code_size, flags; | |
4057 | 68 int is_interleaved, has_local_palette, y, pass, y1, linesize, n, i; |
4144 | 69 uint8_t *ptr, *spal, *palette, *ptr1; |
4054 | 70 |
71 left = bytestream_get_le16(&s->bytestream); | |
72 top = bytestream_get_le16(&s->bytestream); | |
73 width = bytestream_get_le16(&s->bytestream); | |
74 height = bytestream_get_le16(&s->bytestream); | |
75 flags = bytestream_get_byte(&s->bytestream); | |
76 is_interleaved = flags & 0x40; | |
77 has_local_palette = flags & 0x80; | |
78 bits_per_pixel = (flags & 0x07) + 1; | |
79 #ifdef DEBUG | |
4652 | 80 dprintf(s->avctx, "gif: image x=%d y=%d w=%d h=%d\n", left, top, width, height); |
4054 | 81 #endif |
82 | |
83 if (has_local_palette) { | |
84 bytestream_get_buffer(&s->bytestream, s->local_palette, 3 * (1 << bits_per_pixel)); | |
85 palette = s->local_palette; | |
86 } else { | |
87 palette = s->global_palette; | |
88 bits_per_pixel = s->bits_per_pixel; | |
89 } | |
90 | |
91 /* verify that all the image is inside the screen dimensions */ | |
92 if (left + width > s->screen_width || | |
93 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
|
94 return AVERROR(EINVAL); |
4054 | 95 |
96 /* build the palette */ | |
4060 | 97 n = (1 << bits_per_pixel); |
98 spal = palette; | |
99 for(i = 0; i < n; i++) { | |
5089 | 100 s->image_palette[i] = (0xff << 24) | AV_RB24(spal); |
4060 | 101 spal += 3; |
102 } | |
103 for(; i < 256; i++) | |
104 s->image_palette[i] = (0xff << 24); | |
105 /* handle transparency */ | |
106 if (s->transparent_color_index >= 0) | |
107 s->image_palette[s->transparent_color_index] = 0; | |
4054 | 108 |
109 /* now get the image data */ | |
110 code_size = bytestream_get_byte(&s->bytestream); | |
4729 | 111 ff_lzw_decode_init(s->lzw, code_size, s->bytestream, |
112 s->bytestream_end - s->bytestream, FF_LZW_GIF); | |
4054 | 113 |
114 /* read all the image */ | |
4058 | 115 linesize = s->picture.linesize[0]; |
4143 | 116 ptr1 = s->picture.data[0] + top * linesize + left; |
4054 | 117 ptr = ptr1; |
118 pass = 0; | |
119 y1 = 0; | |
120 for (y = 0; y < height; y++) { | |
4080
f426c81afc9e
LZW decoder as separate module plus TIFF LZW support
kostya
parents:
4060
diff
changeset
|
121 ff_lzw_decode(s->lzw, ptr, width); |
4054 | 122 if (is_interleaved) { |
123 switch(pass) { | |
124 default: | |
125 case 0: | |
126 case 1: | |
127 y1 += 8; | |
128 ptr += linesize * 8; | |
129 if (y1 >= height) { | |
6462
745a4216b352
fix interlaced decoding, original patch from reimar
bcoudurier
parents:
6218
diff
changeset
|
130 y1 = pass ? 2 : 4; |
745a4216b352
fix interlaced decoding, original patch from reimar
bcoudurier
parents:
6218
diff
changeset
|
131 ptr = ptr1 + linesize * y1; |
4054 | 132 pass++; |
133 } | |
134 break; | |
135 case 2: | |
136 y1 += 4; | |
137 ptr += linesize * 4; | |
138 if (y1 >= height) { | |
139 y1 = 1; | |
140 ptr = ptr1 + linesize; | |
141 pass++; | |
142 } | |
143 break; | |
144 case 3: | |
145 y1 += 2; | |
146 ptr += linesize * 2; | |
147 break; | |
148 } | |
149 } else { | |
150 ptr += linesize; | |
151 } | |
152 } | |
153 /* 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
|
154 ff_lzw_decode_tail(s->lzw); |
f426c81afc9e
LZW decoder as separate module plus TIFF LZW support
kostya
parents:
4060
diff
changeset
|
155 s->bytestream = ff_lzw_cur_ptr(s->lzw); |
4054 | 156 return 0; |
157 } | |
158 | |
159 static int gif_read_extension(GifState *s) | |
160 { | |
161 int ext_code, ext_len, i, gce_flags, gce_transparent_index; | |
162 | |
163 /* extension */ | |
164 ext_code = bytestream_get_byte(&s->bytestream); | |
165 ext_len = bytestream_get_byte(&s->bytestream); | |
166 #ifdef DEBUG | |
4652 | 167 dprintf(s->avctx, "gif: ext_code=0x%x len=%d\n", ext_code, ext_len); |
4054 | 168 #endif |
169 switch(ext_code) { | |
170 case 0xf9: | |
171 if (ext_len != 4) | |
172 goto discard_ext; | |
173 s->transparent_color_index = -1; | |
174 gce_flags = bytestream_get_byte(&s->bytestream); | |
175 s->gce_delay = bytestream_get_le16(&s->bytestream); | |
176 gce_transparent_index = bytestream_get_byte(&s->bytestream); | |
177 if (gce_flags & 0x01) | |
178 s->transparent_color_index = gce_transparent_index; | |
179 else | |
180 s->transparent_color_index = -1; | |
181 s->gce_disposal = (gce_flags >> 2) & 0x7; | |
182 #ifdef DEBUG | |
4652 | 183 dprintf(s->avctx, "gif: gce_flags=%x delay=%d tcolor=%d disposal=%d\n", |
4054 | 184 gce_flags, s->gce_delay, |
185 s->transparent_color_index, s->gce_disposal); | |
186 #endif | |
187 ext_len = bytestream_get_byte(&s->bytestream); | |
188 break; | |
189 } | |
190 | |
191 /* NOTE: many extension blocks can come after */ | |
192 discard_ext: | |
193 while (ext_len != 0) { | |
194 for (i = 0; i < ext_len; i++) | |
195 bytestream_get_byte(&s->bytestream); | |
196 ext_len = bytestream_get_byte(&s->bytestream); | |
197 #ifdef DEBUG | |
4652 | 198 dprintf(s->avctx, "gif: ext_len1=%d\n", ext_len); |
4054 | 199 #endif |
200 } | |
201 return 0; | |
202 } | |
203 | |
204 static int gif_read_header1(GifState *s) | |
205 { | |
206 uint8_t sig[6]; | |
4057 | 207 int v, n; |
4054 | 208 int has_global_palette; |
209 | |
4718 | 210 if (s->bytestream_end < s->bytestream + 13) |
211 return -1; | |
212 | |
4054 | 213 /* read gif signature */ |
214 bytestream_get_buffer(&s->bytestream, sig, 6); | |
215 if (memcmp(sig, gif87a_sig, 6) != 0 && | |
216 memcmp(sig, gif89a_sig, 6) != 0) | |
217 return -1; | |
218 | |
219 /* read screen header */ | |
220 s->transparent_color_index = -1; | |
221 s->screen_width = bytestream_get_le16(&s->bytestream); | |
222 s->screen_height = bytestream_get_le16(&s->bytestream); | |
223 if( (unsigned)s->screen_width > 32767 | |
224 || (unsigned)s->screen_height > 32767){ | |
225 av_log(NULL, AV_LOG_ERROR, "picture size too large\n"); | |
226 return -1; | |
227 } | |
228 | |
229 v = bytestream_get_byte(&s->bytestream); | |
230 s->color_resolution = ((v & 0x70) >> 4) + 1; | |
231 has_global_palette = (v & 0x80); | |
232 s->bits_per_pixel = (v & 0x07) + 1; | |
233 s->background_color_index = bytestream_get_byte(&s->bytestream); | |
234 bytestream_get_byte(&s->bytestream); /* ignored */ | |
235 #ifdef DEBUG | |
4652 | 236 dprintf(s->avctx, "gif: screen_w=%d screen_h=%d bpp=%d global_palette=%d\n", |
4054 | 237 s->screen_width, s->screen_height, s->bits_per_pixel, |
238 has_global_palette); | |
239 #endif | |
240 if (has_global_palette) { | |
241 n = 1 << s->bits_per_pixel; | |
4718 | 242 if (s->bytestream_end < s->bytestream + n * 3) |
243 return -1; | |
4054 | 244 bytestream_get_buffer(&s->bytestream, s->global_palette, n * 3); |
245 } | |
246 return 0; | |
247 } | |
248 | |
249 static int gif_parse_next_image(GifState *s) | |
250 { | |
4718 | 251 while (s->bytestream < s->bytestream_end) { |
4717 | 252 int code = bytestream_get_byte(&s->bytestream); |
4054 | 253 #ifdef DEBUG |
4652 | 254 dprintf(s->avctx, "gif: code=%02x '%c'\n", code, code); |
4054 | 255 #endif |
256 switch (code) { | |
257 case ',': | |
4874
f06463413858
simplify, patch by Mark Cox, melbournemark plus ffmpeg minus devel gmail com
bcoudurier
parents:
4868
diff
changeset
|
258 return gif_read_image(s); |
4054 | 259 case '!': |
260 if (gif_read_extension(s) < 0) | |
261 return -1; | |
262 break; | |
4874
f06463413858
simplify, patch by Mark Cox, melbournemark plus ffmpeg minus devel gmail com
bcoudurier
parents:
4868
diff
changeset
|
263 case ';': |
f06463413858
simplify, patch by Mark Cox, melbournemark plus ffmpeg minus devel gmail com
bcoudurier
parents:
4868
diff
changeset
|
264 /* end of image */ |
4054 | 265 default: |
4868 | 266 /* error or erroneous EOF */ |
4717 | 267 return -1; |
4054 | 268 } |
269 } | |
4720
7775ba23c931
return error if loop has ended before decoding image
bcoudurier
parents:
4719
diff
changeset
|
270 return -1; |
4054 | 271 } |
272 | |
6517
48759bfbd073
Apply 'cold' attribute to init/uninit functions in libavcodec
zuxy
parents:
6462
diff
changeset
|
273 static av_cold int gif_decode_init(AVCodecContext *avctx) |
4054 | 274 { |
275 GifState *s = avctx->priv_data; | |
276 | |
4652 | 277 s->avctx = avctx; |
278 | |
4058 | 279 avcodec_get_frame_defaults(&s->picture); |
280 avctx->coded_frame= &s->picture; | |
281 s->picture.data[0] = NULL; | |
4080
f426c81afc9e
LZW decoder as separate module plus TIFF LZW support
kostya
parents:
4060
diff
changeset
|
282 ff_lzw_decode_open(&s->lzw); |
4054 | 283 return 0; |
284 } | |
285 | |
9355
54bc8a2727b0
Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents:
8629
diff
changeset
|
286 static int gif_decode_frame(AVCodecContext *avctx, void *data, int *data_size, AVPacket *avpkt) |
4054 | 287 { |
9355
54bc8a2727b0
Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents:
8629
diff
changeset
|
288 const uint8_t *buf = avpkt->data; |
54bc8a2727b0
Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents:
8629
diff
changeset
|
289 int buf_size = avpkt->size; |
4054 | 290 GifState *s = avctx->priv_data; |
291 AVFrame *picture = data; | |
292 int ret; | |
293 | |
294 s->bytestream = buf; | |
4718 | 295 s->bytestream_end = buf + buf_size; |
4054 | 296 if (gif_read_header1(s) < 0) |
297 return -1; | |
298 | |
299 avctx->pix_fmt = PIX_FMT_PAL8; | |
12462
ffb3668ff7af
Use new imgutils.h API names, fix deprecation warnings.
stefano
parents:
12372
diff
changeset
|
300 if (av_image_check_size(s->screen_width, s->screen_height, 0, avctx)) |
4058 | 301 return -1; |
302 avcodec_set_dimensions(avctx, s->screen_width, s->screen_height); | |
4054 | 303 |
4058 | 304 if (s->picture.data[0]) |
305 avctx->release_buffer(avctx, &s->picture); | |
306 if (avctx->get_buffer(avctx, &s->picture) < 0) { | |
307 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); | |
308 return -1; | |
309 } | |
310 s->image_palette = (uint32_t *)s->picture.data[1]; | |
4054 | 311 ret = gif_parse_next_image(s); |
312 if (ret < 0) | |
313 return ret; | |
314 | |
4058 | 315 *picture = s->picture; |
316 *data_size = sizeof(AVPicture); | |
4719 | 317 return s->bytestream - buf; |
4058 | 318 } |
4054 | 319 |
6517
48759bfbd073
Apply 'cold' attribute to init/uninit functions in libavcodec
zuxy
parents:
6462
diff
changeset
|
320 static av_cold int gif_decode_close(AVCodecContext *avctx) |
4058 | 321 { |
322 GifState *s = avctx->priv_data; | |
323 | |
4080
f426c81afc9e
LZW decoder as separate module plus TIFF LZW support
kostya
parents:
4060
diff
changeset
|
324 ff_lzw_decode_close(&s->lzw); |
4058 | 325 if(s->picture.data[0]) |
326 avctx->release_buffer(avctx, &s->picture); | |
4054 | 327 return 0; |
328 } | |
329 | |
330 AVCodec gif_decoder = { | |
331 "gif", | |
11560
8a4984c5cacc
Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents:
9734
diff
changeset
|
332 AVMEDIA_TYPE_VIDEO, |
4054 | 333 CODEC_ID_GIF, |
334 sizeof(GifState), | |
335 gif_decode_init, | |
336 NULL, | |
4058 | 337 gif_decode_close, |
4054 | 338 gif_decode_frame, |
9734 | 339 CODEC_CAP_DR1, |
7040
e943e1409077
Make AVCodec long_names definition conditional depending on CONFIG_SMALL.
stefano
parents:
6712
diff
changeset
|
340 .long_name = NULL_IF_CONFIG_SMALL("GIF (Graphics Interchange Format)"), |
4054 | 341 }; |