FFmpeg
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
gifdec.c
Go to the documentation of this file.
1 /*
2  * GIF demuxer
3  * Copyright (c) 2012 Vitaliy E Sugrobov
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
22 /**
23  * @file
24  * GIF demuxer.
25  */
26 
27 #include "avformat.h"
28 #include "libavutil/intreadwrite.h"
29 #include "libavutil/opt.h"
30 #include "internal.h"
31 #include "libavcodec/gif.h"
32 
33 typedef struct GIFDemuxContext {
34  const AVClass *class;
35  /**
36  * Time span in hundredths of second before
37  * the next frame should be drawn on screen.
38  */
39  int delay;
40  /**
41  * Minimum allowed delay between frames in hundredths of
42  * second. Values below this threshold considered to be
43  * invalid and set to value of default_delay.
44  */
45  int min_delay;
48 
49 /**
50  * Major web browsers display gifs at ~10-15fps when rate
51  * is not explicitly set or have too low values. We assume default rate to be 10.
52  * Default delay = 100hundredths of second / 10fps = 10hos per frame.
53  */
54 #define GIF_DEFAULT_DELAY 10
55 /**
56  * By default delay values less than this threshold considered to be invalid.
57  */
58 #define GIF_MIN_DELAY 2
59 
60 static int gif_probe(AVProbeData *p)
61 {
62  /* check magick */
63  if (memcmp(p->buf, gif87a_sig, 6) && memcmp(p->buf, gif89a_sig, 6))
64  return 0;
65 
66  /* width or height contains zero? */
67  if (!AV_RL16(&p->buf[6]) || !AV_RL16(&p->buf[8]))
68  return 0;
69 
70  return AVPROBE_SCORE_MAX;
71 }
72 
73 static int resync(AVIOContext *pb)
74 {
75  int i;
76  for (i = 0; i < 6; i++) {
77  int b = avio_r8(pb);
78  if (b != gif87a_sig[i] && b != gif89a_sig[i])
79  i = -(b != 'G');
80  if (url_feof(pb))
81  return AVERROR_EOF;
82  }
83  return 0;
84 }
85 
87 {
88  GIFDemuxContext *gdc = s->priv_data;
89  AVIOContext *pb = s->pb;
90  AVStream *st;
91  int width, height, ret;
92 
93  if ((ret = resync(pb)) < 0)
94  return ret;
95 
96  gdc->delay = gdc->default_delay;
97  width = avio_rl16(pb);
98  height = avio_rl16(pb);
99 
100  if (width == 0 || height == 0)
101  return AVERROR_INVALIDDATA;
102 
103  st = avformat_new_stream(s, NULL);
104  if (!st)
105  return AVERROR(ENOMEM);
106 
107  /* GIF format operates with time in "hundredths of second",
108  * therefore timebase is 1/100 */
109  avpriv_set_pts_info(st, 64, 1, 100);
112  st->codec->width = width;
113  st->codec->height = height;
114 
115  /* jump to start because gif decoder needs header data too */
116  if (avio_seek(pb, 0, SEEK_SET) != 0)
117  return AVERROR(EIO);
118 
119  return 0;
120 }
121 
123 {
124  int sb_size, ret = 0;
125 
126  while (0x00 != (sb_size = avio_r8(pb))) {
127  if ((ret = avio_skip(pb, sb_size)) < 0)
128  return ret;
129  }
130 
131  return ret;
132 }
133 
135 {
136  GIFDemuxContext *gdc = s->priv_data;
137  AVIOContext *pb = s->pb;
138  int sb_size, ext_label = avio_r8(pb);
139  int ret;
140 
141  if (ext_label == GIF_GCE_EXT_LABEL) {
142  if ((sb_size = avio_r8(pb)) < 4) {
143  av_log(s, AV_LOG_FATAL, "Graphic Control Extension block's size less than 4.\n");
144  return AVERROR_INVALIDDATA;
145  }
146 
147  /* skip packed fields */
148  if ((ret = avio_skip(pb, 1)) < 0)
149  return ret;
150 
151  gdc->delay = avio_rl16(pb);
152 
153  if (gdc->delay < gdc->min_delay)
154  gdc->delay = gdc->default_delay;
155 
156  /* skip the rest of the Graphic Control Extension block */
157  if ((ret = avio_skip(pb, sb_size - 3)) < 0 )
158  return ret;
159  }
160 
161  if ((ret = gif_skip_subblocks(pb)) < 0)
162  return ret;
163 
164  return 0;
165 }
166 
168 {
169  GIFDemuxContext *gdc = s->priv_data;
170  AVIOContext *pb = s->pb;
171  int packed_fields, block_label, ct_size,
172  keyframe, frame_parsed = 0, ret;
173  int64_t frame_start = avio_tell(pb), frame_end;
174  unsigned char buf[6];
175 
176  if ((ret = avio_read(pb, buf, 6)) == 6) {
177  keyframe = memcmp(buf, gif87a_sig, 6) == 0 ||
178  memcmp(buf, gif89a_sig, 6) == 0;
179  } else if (ret < 0) {
180  return ret;
181  } else {
182  keyframe = 0;
183  }
184 
185  if (keyframe) {
186 parse_keyframe:
187  /* skip 2 bytes of width and 2 of height */
188  if ((ret = avio_skip(pb, 4)) < 0)
189  return ret;
190 
191  packed_fields = avio_r8(pb);
192 
193  /* skip 1 byte of Background Color Index and 1 byte of Pixel Aspect Ratio */
194  if ((ret = avio_skip(pb, 2)) < 0)
195  return ret;
196 
197  /* global color table presence */
198  if (packed_fields & 0x80) {
199  ct_size = 3 * (1 << ((packed_fields & 0x07) + 1));
200 
201  if ((ret = avio_skip(pb, ct_size)) < 0)
202  return ret;
203  }
204  } else {
205  avio_seek(pb, -ret, SEEK_CUR);
206  ret = AVERROR_EOF;
207  }
208 
209  while (GIF_TRAILER != (block_label = avio_r8(pb)) && !url_feof(pb)) {
210  if (block_label == GIF_EXTENSION_INTRODUCER) {
211  if ((ret = gif_read_ext (s)) < 0 )
212  goto resync;
213  } else if (block_label == GIF_IMAGE_SEPARATOR) {
214  /* skip to last byte of Image Descriptor header */
215  if ((ret = avio_skip(pb, 8)) < 0)
216  return ret;
217 
218  packed_fields = avio_r8(pb);
219 
220  /* local color table presence */
221  if (packed_fields & 0x80) {
222  ct_size = 3 * (1 << ((packed_fields & 0x07) + 1));
223 
224  if ((ret = avio_skip(pb, ct_size)) < 0)
225  return ret;
226  }
227 
228  /* read LZW Minimum Code Size */
229  if (avio_r8(pb) < 1) {
230  av_log(s, AV_LOG_ERROR, "lzw minimum code size must be >= 1\n");
231  goto resync;
232  }
233 
234  if ((ret = gif_skip_subblocks(pb)) < 0)
235  goto resync;
236 
237  frame_end = avio_tell(pb);
238 
239  if (avio_seek(pb, frame_start, SEEK_SET) != frame_start)
240  return AVERROR(EIO);
241 
242  ret = av_get_packet(pb, pkt, frame_end - frame_start);
243  if (ret < 0)
244  return ret;
245 
246  if (keyframe)
247  pkt->flags |= AV_PKT_FLAG_KEY;
248 
249  pkt->stream_index = 0;
250  pkt->duration = gdc->delay;
251 
252  /* Graphic Control Extension's scope is single frame.
253  * Remove its influence. */
254  gdc->delay = gdc->default_delay;
255  frame_parsed = 1;
256 
257  break;
258  } else {
259  av_log(s, AV_LOG_ERROR, "invalid block label\n");
260 resync:
261  if (!keyframe)
262  avio_seek(pb, frame_start, SEEK_SET);
263  if ((ret = resync(pb)) < 0)
264  return ret;
265  frame_start = avio_tell(pb) - 6;
266  keyframe = 1;
267  goto parse_keyframe;
268  }
269  }
270 
271  if (ret >= 0 && !frame_parsed) {
272  /* This might happen when there is no image block
273  * between extension blocks and GIF_TRAILER or EOF */
274  return AVERROR_EOF;
275  } else
276  return ret;
277 }
278 
279 static const AVOption options[] = {
280  { "min_delay" , "minimum valid delay between frames (in hundredths of second)", offsetof(GIFDemuxContext, min_delay) , AV_OPT_TYPE_INT, {.i64 = GIF_MIN_DELAY} , 0, 100 * 60, AV_OPT_FLAG_DECODING_PARAM },
281  { "default_delay", "default delay between frames (in hundredths of second)" , offsetof(GIFDemuxContext, default_delay), AV_OPT_TYPE_INT, {.i64 = GIF_DEFAULT_DELAY}, 0, 100 * 60, AV_OPT_FLAG_DECODING_PARAM },
282  { NULL },
283 };
284 
285 static const AVClass demuxer_class = {
286  .class_name = "GIF demuxer",
287  .item_name = av_default_item_name,
288  .option = options,
289  .version = LIBAVUTIL_VERSION_INT,
290  .category = AV_CLASS_CATEGORY_DEMUXER,
291 };
292 
294  .name = "gif",
295  .long_name = NULL_IF_CONFIG_SMALL("CompuServe Graphics Interchange Format (GIF)"),
296  .priv_data_size = sizeof(GIFDemuxContext),
301  .priv_class = &demuxer_class,
302 };