Mercurial > libavformat.hg
comparison gifdec.c @ 887:d70e50f1495f libavformat
COSMETICS: tabs --> spaces, some prettyprinting
author | diego |
---|---|
date | Thu, 22 Dec 2005 01:10:11 +0000 |
parents | da1d5db0ce5c |
children | edbe5c3717f9 |
comparison
equal
deleted
inserted
replaced
886:7ed1351f8c7e | 887:d70e50f1495f |
---|---|
20 | 20 |
21 int gif_write(ByteIOContext *pb, AVImageInfo *info); | 21 int gif_write(ByteIOContext *pb, AVImageInfo *info); |
22 | 22 |
23 //#define DEBUG | 23 //#define DEBUG |
24 | 24 |
25 #define MAXBITS 12 | 25 #define MAXBITS 12 |
26 #define SIZTABLE (1<<MAXBITS) | 26 #define SIZTABLE (1<<MAXBITS) |
27 | 27 |
28 #define GCE_DISPOSAL_NONE 0 | 28 #define GCE_DISPOSAL_NONE 0 |
29 #define GCE_DISPOSAL_INPLACE 1 | 29 #define GCE_DISPOSAL_INPLACE 1 |
30 #define GCE_DISPOSAL_BACKGROUND 2 | 30 #define GCE_DISPOSAL_BACKGROUND 2 |
31 #define GCE_DISPOSAL_RESTORE 3 | 31 #define GCE_DISPOSAL_RESTORE 3 |
52 int eob_reached; | 52 int eob_reached; |
53 uint8_t *pbuf, *ebuf; | 53 uint8_t *pbuf, *ebuf; |
54 int bbits; | 54 int bbits; |
55 unsigned int bbuf; | 55 unsigned int bbuf; |
56 | 56 |
57 int cursize; /* The current code size */ | 57 int cursize; /* The current code size */ |
58 int curmask; | 58 int curmask; |
59 int codesize; | 59 int codesize; |
60 int clear_code; | 60 int clear_code; |
61 int end_code; | 61 int end_code; |
62 int newcodes; /* First available code */ | 62 int newcodes; /* First available code */ |
63 int top_slot; /* Highest code for current size */ | 63 int top_slot; /* Highest code for current size */ |
64 int slot; /* Last read code */ | 64 int slot; /* Last read code */ |
65 int fc, oc; | 65 int fc, oc; |
66 uint8_t *sp; | 66 uint8_t *sp; |
67 uint8_t stack[SIZTABLE]; | 67 uint8_t stack[SIZTABLE]; |
68 uint8_t suffix[SIZTABLE]; | 68 uint8_t suffix[SIZTABLE]; |
69 uint16_t prefix[SIZTABLE]; | 69 uint16_t prefix[SIZTABLE]; |
95 const uint8_t *p, *p_end; | 95 const uint8_t *p, *p_end; |
96 int bits_per_pixel, has_global_palette, ext_code, ext_len; | 96 int bits_per_pixel, has_global_palette, ext_code, ext_len; |
97 int gce_flags, gce_disposal; | 97 int gce_flags, gce_disposal; |
98 | 98 |
99 if (pd->buf_size < 24 || | 99 if (pd->buf_size < 24 || |
100 memcmp(pd->buf, gif89a_sig, 6) != 0) | 100 memcmp(pd->buf, gif89a_sig, 6) != 0) |
101 return 0; | 101 return 0; |
102 p_end = pd->buf + pd->buf_size; | 102 p_end = pd->buf + pd->buf_size; |
103 p = pd->buf + 6; | 103 p = pd->buf + 6; |
104 bits_per_pixel = (p[4] & 0x07) + 1; | 104 bits_per_pixel = (p[4] & 0x07) + 1; |
105 has_global_palette = (p[4] & 0x80); | 105 has_global_palette = (p[4] & 0x80); |
143 } | 143 } |
144 | 144 |
145 static int gif_image_probe(AVProbeData * pd) | 145 static int gif_image_probe(AVProbeData * pd) |
146 { | 146 { |
147 if (pd->buf_size >= 24 && | 147 if (pd->buf_size >= 24 && |
148 (memcmp(pd->buf, gif87a_sig, 6) == 0 || | 148 (memcmp(pd->buf, gif87a_sig, 6) == 0 || |
149 memcmp(pd->buf, gif89a_sig, 6) == 0)) | 149 memcmp(pd->buf, gif89a_sig, 6) == 0)) |
150 return AVPROBE_SCORE_MAX - 1; | 150 return AVPROBE_SCORE_MAX - 1; |
151 else | 151 else |
152 return 0; | 152 return 0; |
153 } | 153 } |
154 | 154 |
155 | 155 |
156 static void GLZWDecodeInit(GifState * s, int csize) | 156 static void GLZWDecodeInit(GifState * s, int csize) |
157 { | 157 { |
196 ptr = s->pbuf; | 196 ptr = s->pbuf; |
197 } | 197 } |
198 s->bbuf |= ptr[0] << s->bbits; | 198 s->bbuf |= ptr[0] << s->bbits; |
199 ptr++; | 199 ptr++; |
200 s->pbuf = ptr; | 200 s->pbuf = ptr; |
201 s->bbits += 8; | 201 s->bbits += 8; |
202 } | 202 } |
203 c = s->bbuf & s->curmask; | 203 c = s->bbuf & s->curmask; |
204 s->bbuf >>= s->cursize; | 204 s->bbuf >>= s->cursize; |
205 s->bbits -= s->cursize; | 205 s->bbits -= s->cursize; |
206 return c; | 206 return c; |
221 sp = s->sp; | 221 sp = s->sp; |
222 oc = s->oc; | 222 oc = s->oc; |
223 fc = s->fc; | 223 fc = s->fc; |
224 | 224 |
225 while (sp > s->stack) { | 225 while (sp > s->stack) { |
226 *buf++ = *(--sp); | 226 *buf++ = *(--sp); |
227 if ((--l) == 0) | 227 if ((--l) == 0) |
228 goto the_end; | 228 goto the_end; |
229 } | 229 } |
230 | 230 |
231 for (;;) { | 231 for (;;) { |
232 c = GetCode(s); | 232 c = GetCode(s); |
233 if (c == s->end_code) { | 233 if (c == s->end_code) { |
234 s->end_code = -1; | 234 s->end_code = -1; |
235 break; | 235 break; |
236 } else if (c == s->clear_code) { | 236 } else if (c == s->clear_code) { |
237 s->cursize = s->codesize + 1; | 237 s->cursize = s->codesize + 1; |
238 s->curmask = mask[s->cursize]; | 238 s->curmask = mask[s->cursize]; |
239 s->slot = s->newcodes; | 239 s->slot = s->newcodes; |
240 s->top_slot = 1 << s->cursize; | 240 s->top_slot = 1 << s->cursize; |
241 while ((c = GetCode(s)) == s->clear_code); | 241 while ((c = GetCode(s)) == s->clear_code); |
242 if (c == s->end_code) { | 242 if (c == s->end_code) { |
243 s->end_code = -1; | 243 s->end_code = -1; |
244 break; | 244 break; |
245 } | 245 } |
246 /* test error */ | 246 /* test error */ |
247 if (c >= s->slot) | 247 if (c >= s->slot) |
248 c = 0; | 248 c = 0; |
249 fc = oc = c; | 249 fc = oc = c; |
250 *buf++ = c; | 250 *buf++ = c; |
251 if ((--l) == 0) | 251 if ((--l) == 0) |
252 break; | 252 break; |
253 } else { | 253 } else { |
254 code = c; | 254 code = c; |
255 if (code >= s->slot) { | 255 if (code >= s->slot) { |
256 *sp++ = fc; | 256 *sp++ = fc; |
257 code = oc; | 257 code = oc; |
258 } | 258 } |
259 while (code >= s->newcodes) { | 259 while (code >= s->newcodes) { |
260 *sp++ = s->suffix[code]; | 260 *sp++ = s->suffix[code]; |
261 code = s->prefix[code]; | 261 code = s->prefix[code]; |
262 } | 262 } |
263 *sp++ = code; | 263 *sp++ = code; |
264 if (s->slot < s->top_slot) { | 264 if (s->slot < s->top_slot) { |
265 s->suffix[s->slot] = fc = code; | 265 s->suffix[s->slot] = fc = code; |
266 s->prefix[s->slot++] = oc; | 266 s->prefix[s->slot++] = oc; |
267 oc = c; | 267 oc = c; |
268 } | 268 } |
269 if (s->slot >= s->top_slot) { | 269 if (s->slot >= s->top_slot) { |
270 if (s->cursize < MAXBITS) { | 270 if (s->cursize < MAXBITS) { |
271 s->top_slot <<= 1; | 271 s->top_slot <<= 1; |
272 s->curmask = mask[++s->cursize]; | 272 s->curmask = mask[++s->cursize]; |
273 } | 273 } |
274 } | 274 } |
275 while (sp > s->stack) { | 275 while (sp > s->stack) { |
276 *buf++ = *(--sp); | 276 *buf++ = *(--sp); |
277 if ((--l) == 0) | 277 if ((--l) == 0) |
278 goto the_end; | 278 goto the_end; |
279 } | 279 } |
280 } | 280 } |
281 } | 281 } |
282 the_end: | 282 the_end: |
283 s->sp = sp; | 283 s->sp = sp; |
284 s->oc = oc; | 284 s->oc = oc; |
285 s->fc = fc; | 285 s->fc = fc; |
304 #ifdef DEBUG | 304 #ifdef DEBUG |
305 printf("gif: image x=%d y=%d w=%d h=%d\n", left, top, width, height); | 305 printf("gif: image x=%d y=%d w=%d h=%d\n", left, top, width, height); |
306 #endif | 306 #endif |
307 | 307 |
308 if (has_local_palette) { | 308 if (has_local_palette) { |
309 get_buffer(f, s->local_palette, 3 * (1 << bits_per_pixel)); | 309 get_buffer(f, s->local_palette, 3 * (1 << bits_per_pixel)); |
310 palette = s->local_palette; | 310 palette = s->local_palette; |
311 } else { | 311 } else { |
312 palette = s->global_palette; | 312 palette = s->global_palette; |
313 bits_per_pixel = s->bits_per_pixel; | 313 bits_per_pixel = s->bits_per_pixel; |
314 } | 314 } |
463 int has_global_palette; | 463 int has_global_palette; |
464 | 464 |
465 /* read gif signature */ | 465 /* read gif signature */ |
466 ret = get_buffer(f, sig, 6); | 466 ret = get_buffer(f, sig, 6); |
467 if (ret != 6) | 467 if (ret != 6) |
468 return -1; | 468 return -1; |
469 if (memcmp(sig, gif87a_sig, 6) != 0 && | 469 if (memcmp(sig, gif87a_sig, 6) != 0 && |
470 memcmp(sig, gif89a_sig, 6) != 0) | 470 memcmp(sig, gif89a_sig, 6) != 0) |
471 return -1; | 471 return -1; |
472 | 472 |
473 /* read screen header */ | 473 /* read screen header */ |
474 s->transparent_color_index = -1; | 474 s->transparent_color_index = -1; |
475 s->screen_width = get_le16(f); | 475 s->screen_width = get_le16(f); |
476 s->screen_height = get_le16(f); | 476 s->screen_height = get_le16(f); |
483 v = get_byte(f); | 483 v = get_byte(f); |
484 s->color_resolution = ((v & 0x70) >> 4) + 1; | 484 s->color_resolution = ((v & 0x70) >> 4) + 1; |
485 has_global_palette = (v & 0x80); | 485 has_global_palette = (v & 0x80); |
486 s->bits_per_pixel = (v & 0x07) + 1; | 486 s->bits_per_pixel = (v & 0x07) + 1; |
487 s->background_color_index = get_byte(f); | 487 s->background_color_index = get_byte(f); |
488 get_byte(f); /* ignored */ | 488 get_byte(f); /* ignored */ |
489 #ifdef DEBUG | 489 #ifdef DEBUG |
490 printf("gif: screen_w=%d screen_h=%d bpp=%d global_palette=%d\n", | 490 printf("gif: screen_w=%d screen_h=%d bpp=%d global_palette=%d\n", |
491 s->screen_width, s->screen_height, s->bits_per_pixel, | 491 s->screen_width, s->screen_height, s->bits_per_pixel, |
492 has_global_palette); | 492 has_global_palette); |
493 #endif | 493 #endif |
494 if (has_global_palette) { | 494 if (has_global_palette) { |
495 n = 1 << s->bits_per_pixel; | 495 n = 1 << s->bits_per_pixel; |
496 get_buffer(f, s->global_palette, n * 3); | 496 get_buffer(f, s->global_palette, n * 3); |
497 } | 497 } |
498 return 0; | 498 return 0; |
499 } | 499 } |
500 | 500 |
501 static int gif_parse_next_image(GifState *s) | 501 static int gif_parse_next_image(GifState *s) |
502 { | 502 { |
503 ByteIOContext *f = s->f; | 503 ByteIOContext *f = s->f; |
504 int ret, code; | 504 int ret, code; |
505 | 505 |
506 for (;;) { | 506 for (;;) { |
507 code = url_fgetc(f); | 507 code = url_fgetc(f); |
508 #ifdef DEBUG | 508 #ifdef DEBUG |
509 printf("gif: code=%02x '%c'\n", code, code); | 509 printf("gif: code=%02x '%c'\n", code, code); |
510 #endif | 510 #endif |
511 switch (code) { | 511 switch (code) { |
512 case ',': | 512 case ',': |
513 if (gif_read_image(s) < 0) | 513 if (gif_read_image(s) < 0) |
514 return AVERROR_IO; | 514 return AVERROR_IO; |
515 ret = 0; | 515 ret = 0; |
516 goto the_end; | 516 goto the_end; |
517 case ';': | 517 case ';': |
518 /* end of image */ | 518 /* end of image */ |
519 ret = AVERROR_IO; | 519 ret = AVERROR_IO; |
520 goto the_end; | 520 goto the_end; |
521 case '!': | 521 case '!': |
522 if (gif_read_extension(s) < 0) | 522 if (gif_read_extension(s) < 0) |
523 return AVERROR_IO; | 523 return AVERROR_IO; |
524 break; | 524 break; |
525 case EOF: | 525 case EOF: |
526 default: | 526 default: |
527 /* error or errneous EOF */ | 527 /* error or errneous EOF */ |
528 ret = AVERROR_IO; | 528 ret = AVERROR_IO; |
529 goto the_end; | 529 goto the_end; |
530 } | 530 } |
531 } | 531 } |
532 the_end: | 532 the_end: |
533 return ret; | 533 return ret; |
534 } | 534 } |
535 | 535 |
536 static int gif_read_header(AVFormatContext * s1, | 536 static int gif_read_header(AVFormatContext * s1, |
537 AVFormatParameters * ap) | 537 AVFormatParameters * ap) |
538 { | 538 { |
539 GifState *s = s1->priv_data; | 539 GifState *s = s1->priv_data; |
540 ByteIOContext *f = &s1->pb; | 540 ByteIOContext *f = &s1->pb; |
541 AVStream *st; | 541 AVStream *st; |
542 | 542 |
551 return -ENOMEM; | 551 return -ENOMEM; |
552 s->pix_fmt = PIX_FMT_RGB24; | 552 s->pix_fmt = PIX_FMT_RGB24; |
553 /* now we are ready: build format streams */ | 553 /* now we are ready: build format streams */ |
554 st = av_new_stream(s1, 0); | 554 st = av_new_stream(s1, 0); |
555 if (!st) | 555 if (!st) |
556 return -1; | 556 return -1; |
557 | 557 |
558 st->codec->codec_type = CODEC_TYPE_VIDEO; | 558 st->codec->codec_type = CODEC_TYPE_VIDEO; |
559 st->codec->codec_id = CODEC_ID_RAWVIDEO; | 559 st->codec->codec_id = CODEC_ID_RAWVIDEO; |
560 st->codec->time_base.den = 5; | 560 st->codec->time_base.den = 5; |
561 st->codec->time_base.num = 1; | 561 st->codec->time_base.num = 1; |
565 st->codec->pix_fmt = PIX_FMT_RGB24; | 565 st->codec->pix_fmt = PIX_FMT_RGB24; |
566 return 0; | 566 return 0; |
567 } | 567 } |
568 | 568 |
569 static int gif_read_packet(AVFormatContext * s1, | 569 static int gif_read_packet(AVFormatContext * s1, |
570 AVPacket * pkt) | 570 AVPacket * pkt) |
571 { | 571 { |
572 GifState *s = s1->priv_data; | 572 GifState *s = s1->priv_data; |
573 int ret; | 573 int ret; |
574 | 574 |
575 ret = gif_parse_next_image(s); | 575 ret = gif_parse_next_image(s); |
576 if (ret < 0) | 576 if (ret < 0) |
577 return ret; | 577 return ret; |
578 | 578 |
579 /* XXX: avoid copying */ | 579 /* XXX: avoid copying */ |
580 if (av_new_packet(pkt, s->screen_width * s->screen_height * 3)) { | 580 if (av_new_packet(pkt, s->screen_width * s->screen_height * 3)) { |
581 return AVERROR_IO; | 581 return AVERROR_IO; |
582 } | 582 } |
583 pkt->stream_index = 0; | 583 pkt->stream_index = 0; |
584 memcpy(pkt->data, s->image_buf, s->screen_width * s->screen_height * 3); | 584 memcpy(pkt->data, s->image_buf, s->screen_width * s->screen_height * 3); |
585 return 0; | 585 return 0; |
586 } | 586 } |