00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "avformat.h"
00022
00023
00024
00025 #define MAXBITS 12
00026 #define SIZTABLE (1<<MAXBITS)
00027
00028 #define GCE_DISPOSAL_NONE 0
00029 #define GCE_DISPOSAL_INPLACE 1
00030 #define GCE_DISPOSAL_BACKGROUND 2
00031 #define GCE_DISPOSAL_RESTORE 3
00032
00033 typedef struct GifState {
00034 int screen_width;
00035 int screen_height;
00036 int bits_per_pixel;
00037 int background_color_index;
00038 int transparent_color_index;
00039 int color_resolution;
00040 uint8_t *image_buf;
00041 int image_linesize;
00042 uint32_t *image_palette;
00043 int pix_fmt;
00044
00045
00046 int gce_disposal;
00047
00048 int gce_delay;
00049
00050
00051 ByteIOContext *f;
00052 int eob_reached;
00053 uint8_t *pbuf, *ebuf;
00054 int bbits;
00055 unsigned int bbuf;
00056
00057 int cursize;
00058 int curmask;
00059 int codesize;
00060 int clear_code;
00061 int end_code;
00062 int newcodes;
00063 int top_slot;
00064 int slot;
00065 int fc, oc;
00066 uint8_t *sp;
00067 uint8_t stack[SIZTABLE];
00068 uint8_t suffix[SIZTABLE];
00069 uint16_t prefix[SIZTABLE];
00070
00071
00072 uint8_t global_palette[256 * 3];
00073 uint8_t local_palette[256 * 3];
00074 uint8_t buf[256];
00075 } GifState;
00076
00077
00078 static const uint8_t gif87a_sig[6] = "GIF87a";
00079 static const uint8_t gif89a_sig[6] = "GIF89a";
00080
00081 static const uint16_t mask[17] =
00082 {
00083 0x0000, 0x0001, 0x0003, 0x0007,
00084 0x000F, 0x001F, 0x003F, 0x007F,
00085 0x00FF, 0x01FF, 0x03FF, 0x07FF,
00086 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF
00087 };
00088
00089
00090
00091
00092
00093 static int gif_video_probe(AVProbeData * pd)
00094 {
00095 const uint8_t *p, *p_end;
00096 int bits_per_pixel, has_global_palette, ext_code, ext_len;
00097 int gce_flags, gce_disposal;
00098
00099 if (pd->buf_size < 24 ||
00100 memcmp(pd->buf, gif89a_sig, 6) != 0)
00101 return 0;
00102 p_end = pd->buf + pd->buf_size;
00103 p = pd->buf + 6;
00104 bits_per_pixel = (p[4] & 0x07) + 1;
00105 has_global_palette = (p[4] & 0x80);
00106 p += 7;
00107 if (has_global_palette)
00108 p += (1 << bits_per_pixel) * 3;
00109 for(;;) {
00110 if (p >= p_end)
00111 return 0;
00112 if (*p != '!')
00113 break;
00114 p++;
00115 if (p >= p_end)
00116 return 0;
00117 ext_code = *p++;
00118 if (p >= p_end)
00119 return 0;
00120 ext_len = *p++;
00121 if (ext_code == 0xf9) {
00122 if (p >= p_end)
00123 return 0;
00124
00125
00126 gce_flags = *p++;
00127 gce_disposal = (gce_flags >> 2) & 0x7;
00128 if (gce_disposal != 0)
00129 return AVPROBE_SCORE_MAX;
00130 else
00131 return 0;
00132 }
00133 for(;;) {
00134 if (ext_len == 0)
00135 break;
00136 p += ext_len;
00137 if (p >= p_end)
00138 return 0;
00139 ext_len = *p++;
00140 }
00141 }
00142 return 0;
00143 }
00144
00145 static void GLZWDecodeInit(GifState * s, int csize)
00146 {
00147
00148 s->eob_reached = 0;
00149 s->pbuf = s->buf;
00150 s->ebuf = s->buf;
00151 s->bbuf = 0;
00152 s->bbits = 0;
00153
00154
00155 s->codesize = csize;
00156 s->cursize = s->codesize + 1;
00157 s->curmask = mask[s->cursize];
00158 s->top_slot = 1 << s->cursize;
00159 s->clear_code = 1 << s->codesize;
00160 s->end_code = s->clear_code + 1;
00161 s->slot = s->newcodes = s->clear_code + 2;
00162 s->oc = s->fc = 0;
00163 s->sp = s->stack;
00164 }
00165
00166
00167 static inline int GetCode(GifState * s)
00168 {
00169 int c, sizbuf;
00170 uint8_t *ptr;
00171
00172 while (s->bbits < s->cursize) {
00173 ptr = s->pbuf;
00174 if (ptr >= s->ebuf) {
00175 if (!s->eob_reached) {
00176 sizbuf = get_byte(s->f);
00177 s->ebuf = s->buf + sizbuf;
00178 s->pbuf = s->buf;
00179 if (sizbuf > 0) {
00180 get_buffer(s->f, s->buf, sizbuf);
00181 } else {
00182 s->eob_reached = 1;
00183 }
00184 }
00185 ptr = s->pbuf;
00186 }
00187 s->bbuf |= ptr[0] << s->bbits;
00188 ptr++;
00189 s->pbuf = ptr;
00190 s->bbits += 8;
00191 }
00192 c = s->bbuf & s->curmask;
00193 s->bbuf >>= s->cursize;
00194 s->bbits -= s->cursize;
00195 return c;
00196 }
00197
00198
00199
00200
00201 static int GLZWDecode(GifState * s, uint8_t * buf, int len)
00202 {
00203 int l, c, code, oc, fc;
00204 uint8_t *sp;
00205
00206 if (s->end_code < 0)
00207 return 0;
00208
00209 l = len;
00210 sp = s->sp;
00211 oc = s->oc;
00212 fc = s->fc;
00213
00214 while (sp > s->stack) {
00215 *buf++ = *(--sp);
00216 if ((--l) == 0)
00217 goto the_end;
00218 }
00219
00220 for (;;) {
00221 c = GetCode(s);
00222 if (c == s->end_code) {
00223 s->end_code = -1;
00224 break;
00225 } else if (c == s->clear_code) {
00226 s->cursize = s->codesize + 1;
00227 s->curmask = mask[s->cursize];
00228 s->slot = s->newcodes;
00229 s->top_slot = 1 << s->cursize;
00230 while ((c = GetCode(s)) == s->clear_code);
00231 if (c == s->end_code) {
00232 s->end_code = -1;
00233 break;
00234 }
00235
00236 if (c >= s->slot)
00237 c = 0;
00238 fc = oc = c;
00239 *buf++ = c;
00240 if ((--l) == 0)
00241 break;
00242 } else {
00243 code = c;
00244 if (code >= s->slot) {
00245 *sp++ = fc;
00246 code = oc;
00247 }
00248 while (code >= s->newcodes) {
00249 *sp++ = s->suffix[code];
00250 code = s->prefix[code];
00251 }
00252 *sp++ = code;
00253 if (s->slot < s->top_slot) {
00254 s->suffix[s->slot] = fc = code;
00255 s->prefix[s->slot++] = oc;
00256 oc = c;
00257 }
00258 if (s->slot >= s->top_slot) {
00259 if (s->cursize < MAXBITS) {
00260 s->top_slot <<= 1;
00261 s->curmask = mask[++s->cursize];
00262 }
00263 }
00264 while (sp > s->stack) {
00265 *buf++ = *(--sp);
00266 if ((--l) == 0)
00267 goto the_end;
00268 }
00269 }
00270 }
00271 the_end:
00272 s->sp = sp;
00273 s->oc = oc;
00274 s->fc = fc;
00275 return len - l;
00276 }
00277
00278 static int gif_read_image(GifState *s)
00279 {
00280 ByteIOContext *f = s->f;
00281 int left, top, width, height, bits_per_pixel, code_size, flags;
00282 int is_interleaved, has_local_palette, y, x, pass, y1, linesize, n, i;
00283 uint8_t *ptr, *line, *d, *spal, *palette, *sptr, *ptr1;
00284
00285 left = get_le16(f);
00286 top = get_le16(f);
00287 width = get_le16(f);
00288 height = get_le16(f);
00289 flags = get_byte(f);
00290 is_interleaved = flags & 0x40;
00291 has_local_palette = flags & 0x80;
00292 bits_per_pixel = (flags & 0x07) + 1;
00293 #ifdef DEBUG
00294 printf("gif: image x=%d y=%d w=%d h=%d\n", left, top, width, height);
00295 #endif
00296
00297 if (has_local_palette) {
00298 get_buffer(f, s->local_palette, 3 * (1 << bits_per_pixel));
00299 palette = s->local_palette;
00300 } else {
00301 palette = s->global_palette;
00302 bits_per_pixel = s->bits_per_pixel;
00303 }
00304
00305
00306 if (left + width > s->screen_width ||
00307 top + height > s->screen_height)
00308 return AVERROR(EINVAL);
00309
00310
00311 if (s->pix_fmt == PIX_FMT_RGB24) {
00312 line = av_malloc(width);
00313 if (!line)
00314 return AVERROR(ENOMEM);
00315 } else {
00316 n = (1 << bits_per_pixel);
00317 spal = palette;
00318 for(i = 0; i < n; i++) {
00319 s->image_palette[i] = (0xff << 24) |
00320 (spal[0] << 16) | (spal[1] << 8) | (spal[2]);
00321 spal += 3;
00322 }
00323 for(; i < 256; i++)
00324 s->image_palette[i] = (0xff << 24);
00325
00326 if (s->transparent_color_index >= 0)
00327 s->image_palette[s->transparent_color_index] = 0;
00328 line = NULL;
00329 }
00330
00331
00332 s->f = f;
00333 code_size = get_byte(f);
00334 GLZWDecodeInit(s, code_size);
00335
00336
00337 linesize = s->image_linesize;
00338 ptr1 = s->image_buf + top * linesize + (left * 3);
00339 ptr = ptr1;
00340 pass = 0;
00341 y1 = 0;
00342 for (y = 0; y < height; y++) {
00343 if (s->pix_fmt == PIX_FMT_RGB24) {
00344
00345 GLZWDecode(s, line, width);
00346 d = ptr;
00347 sptr = line;
00348 for(x = 0; x < width; x++) {
00349 spal = palette + sptr[0] * 3;
00350 d[0] = spal[0];
00351 d[1] = spal[1];
00352 d[2] = spal[2];
00353 d += 3;
00354 sptr++;
00355 }
00356 } else {
00357 GLZWDecode(s, ptr, width);
00358 }
00359 if (is_interleaved) {
00360 switch(pass) {
00361 default:
00362 case 0:
00363 case 1:
00364 y1 += 8;
00365 ptr += linesize * 8;
00366 if (y1 >= height) {
00367 y1 = 4;
00368 if (pass == 0)
00369 ptr = ptr1 + linesize * 4;
00370 else
00371 ptr = ptr1 + linesize * 2;
00372 pass++;
00373 }
00374 break;
00375 case 2:
00376 y1 += 4;
00377 ptr += linesize * 4;
00378 if (y1 >= height) {
00379 y1 = 1;
00380 ptr = ptr1 + linesize;
00381 pass++;
00382 }
00383 break;
00384 case 3:
00385 y1 += 2;
00386 ptr += linesize * 2;
00387 break;
00388 }
00389 } else {
00390 ptr += linesize;
00391 }
00392 }
00393 av_free(line);
00394
00395
00396 while (!s->eob_reached)
00397 GetCode(s);
00398 return 0;
00399 }
00400
00401 static int gif_read_extension(GifState *s)
00402 {
00403 ByteIOContext *f = s->f;
00404 int ext_code, ext_len, i, gce_flags, gce_transparent_index;
00405
00406
00407 ext_code = get_byte(f);
00408 ext_len = get_byte(f);
00409 #ifdef DEBUG
00410 printf("gif: ext_code=0x%x len=%d\n", ext_code, ext_len);
00411 #endif
00412 switch(ext_code) {
00413 case 0xf9:
00414 if (ext_len != 4)
00415 goto discard_ext;
00416 s->transparent_color_index = -1;
00417 gce_flags = get_byte(f);
00418 s->gce_delay = get_le16(f);
00419 gce_transparent_index = get_byte(f);
00420 if (gce_flags & 0x01)
00421 s->transparent_color_index = gce_transparent_index;
00422 else
00423 s->transparent_color_index = -1;
00424 s->gce_disposal = (gce_flags >> 2) & 0x7;
00425 #ifdef DEBUG
00426 printf("gif: gce_flags=%x delay=%d tcolor=%d disposal=%d\n",
00427 gce_flags, s->gce_delay,
00428 s->transparent_color_index, s->gce_disposal);
00429 #endif
00430 ext_len = get_byte(f);
00431 break;
00432 }
00433
00434
00435 discard_ext:
00436 while (ext_len != 0) {
00437 for (i = 0; i < ext_len; i++)
00438 get_byte(f);
00439 ext_len = get_byte(f);
00440 #ifdef DEBUG
00441 printf("gif: ext_len1=%d\n", ext_len);
00442 #endif
00443 }
00444 return 0;
00445 }
00446
00447 static int gif_read_header1(GifState *s)
00448 {
00449 ByteIOContext *f = s->f;
00450 uint8_t sig[6];
00451 int ret, v, n;
00452 int has_global_palette;
00453
00454
00455 ret = get_buffer(f, sig, 6);
00456 if (ret != 6)
00457 return -1;
00458 if (memcmp(sig, gif87a_sig, 6) != 0 &&
00459 memcmp(sig, gif89a_sig, 6) != 0)
00460 return -1;
00461
00462
00463 s->transparent_color_index = -1;
00464 s->screen_width = get_le16(f);
00465 s->screen_height = get_le16(f);
00466 if( (unsigned)s->screen_width > 32767
00467 || (unsigned)s->screen_height > 32767){
00468 av_log(NULL, AV_LOG_ERROR, "picture size too large\n");
00469 return -1;
00470 }
00471
00472 v = get_byte(f);
00473 s->color_resolution = ((v & 0x70) >> 4) + 1;
00474 has_global_palette = (v & 0x80);
00475 s->bits_per_pixel = (v & 0x07) + 1;
00476 s->background_color_index = get_byte(f);
00477 get_byte(f);
00478 #ifdef DEBUG
00479 printf("gif: screen_w=%d screen_h=%d bpp=%d global_palette=%d\n",
00480 s->screen_width, s->screen_height, s->bits_per_pixel,
00481 has_global_palette);
00482 #endif
00483 if (has_global_palette) {
00484 n = 1 << s->bits_per_pixel;
00485 get_buffer(f, s->global_palette, n * 3);
00486 }
00487 return 0;
00488 }
00489
00490 static int gif_parse_next_image(GifState *s)
00491 {
00492 ByteIOContext *f = s->f;
00493 int ret, code;
00494
00495 for (;;) {
00496 code = url_fgetc(f);
00497 #ifdef DEBUG
00498 printf("gif: code=%02x '%c'\n", code, code);
00499 #endif
00500 switch (code) {
00501 case ',':
00502 if (gif_read_image(s) < 0)
00503 return AVERROR(EIO);
00504 ret = 0;
00505 goto the_end;
00506 case ';':
00507
00508 ret = AVERROR(EIO);
00509 goto the_end;
00510 case '!':
00511 if (gif_read_extension(s) < 0)
00512 return AVERROR(EIO);
00513 break;
00514 case EOF:
00515 default:
00516
00517 ret = AVERROR(EIO);
00518 goto the_end;
00519 }
00520 }
00521 the_end:
00522 return ret;
00523 }
00524
00525 static int gif_read_header(AVFormatContext * s1,
00526 AVFormatParameters * ap)
00527 {
00528 GifState *s = s1->priv_data;
00529 ByteIOContext *f = s1->pb;
00530 AVStream *st;
00531
00532 s->f = f;
00533 if (gif_read_header1(s) < 0)
00534 return -1;
00535
00536
00537 s->image_linesize = s->screen_width * 3;
00538 s->image_buf = av_malloc(s->screen_height * s->image_linesize);
00539 if (!s->image_buf)
00540 return AVERROR(ENOMEM);
00541 s->pix_fmt = PIX_FMT_RGB24;
00542
00543 st = av_new_stream(s1, 0);
00544 if (!st)
00545 return -1;
00546
00547 st->codec->codec_type = CODEC_TYPE_VIDEO;
00548 st->codec->codec_id = CODEC_ID_RAWVIDEO;
00549 st->codec->time_base.den = 5;
00550 st->codec->time_base.num = 1;
00551
00552 st->codec->width = s->screen_width;
00553 st->codec->height = s->screen_height;
00554 st->codec->pix_fmt = PIX_FMT_RGB24;
00555 return 0;
00556 }
00557
00558 static int gif_read_packet(AVFormatContext * s1,
00559 AVPacket * pkt)
00560 {
00561 GifState *s = s1->priv_data;
00562 int ret;
00563
00564 ret = gif_parse_next_image(s);
00565 if (ret < 0)
00566 return ret;
00567
00568
00569 if (av_new_packet(pkt, s->screen_width * s->screen_height * 3)) {
00570 return AVERROR(EIO);
00571 }
00572 pkt->stream_index = 0;
00573 memcpy(pkt->data, s->image_buf, s->screen_width * s->screen_height * 3);
00574 return 0;
00575 }
00576
00577 static int gif_read_close(AVFormatContext *s1)
00578 {
00579 GifState *s = s1->priv_data;
00580 av_free(s->image_buf);
00581 return 0;
00582 }
00583
00584 AVInputFormat gif_demuxer =
00585 {
00586 "gif",
00587 "gif format",
00588 sizeof(GifState),
00589 gif_video_probe,
00590 gif_read_header,
00591 gif_read_packet,
00592 gif_read_close,
00593 };