comparison gif.c @ 790:80aec794c2ed libavformat

Animated GIF looping patch by (Todd Kirby // ffmpeg.php gmail com)
author michael
date Sat, 18 Jun 2005 01:52:24 +0000
parents af4e24d6310c
children feca73904e67
comparison
equal deleted inserted replaced
789:411b75055a43 790:80aec794c2ed
41 #include "bitstream.h" 41 #include "bitstream.h"
42 42
43 /* bitstream minipacket size */ 43 /* bitstream minipacket size */
44 #define GIF_CHUNKS 100 44 #define GIF_CHUNKS 100
45 45
46 /* slows down the decoding (and some browsers doesn't like it) */ 46 /* slows down the decoding (and some browsers don't like it) */
47 /* #define GIF_ADD_APP_HEADER */ 47 /* update on the 'some browsers don't like it issue from above: this was probably due to missing 'Data Sub-block Terminator' (byte 19) in the app_header */
48 #define GIF_ADD_APP_HEADER // required to enable looping of animated gif
48 49
49 typedef struct { 50 typedef struct {
50 unsigned char r; 51 unsigned char r;
51 unsigned char g; 52 unsigned char g;
52 unsigned char b; 53 unsigned char b;
167 168
168 /* !RevPutBitContext */ 169 /* !RevPutBitContext */
169 170
170 /* GIF header */ 171 /* GIF header */
171 static int gif_image_write_header(ByteIOContext *pb, 172 static int gif_image_write_header(ByteIOContext *pb,
172 int width, int height, uint32_t *palette) 173 int width, int height, int loop_count,
174 uint32_t *palette)
173 { 175 {
174 int i; 176 int i;
175 unsigned int v; 177 unsigned int v;
176 178
177 put_tag(pb, "GIF"); 179 put_tag(pb, "GIF");
195 put_byte(pb, (v >> 8) & 0xff); 197 put_byte(pb, (v >> 8) & 0xff);
196 put_byte(pb, (v) & 0xff); 198 put_byte(pb, (v) & 0xff);
197 } 199 }
198 } 200 }
199 201
202 /* update: this is the 'NETSCAPE EXTENSION' that allows for looped animated gif
203 see http://members.aol.com/royalef/gifabout.htm#net-extension
204
205 byte 1 : 33 (hex 0x21) GIF Extension code
206 byte 2 : 255 (hex 0xFF) Application Extension Label
207 byte 3 : 11 (hex (0x0B) Length of Application Block
208 (eleven bytes of data to follow)
209 bytes 4 to 11 : "NETSCAPE"
210 bytes 12 to 14 : "2.0"
211 byte 15 : 3 (hex 0x03) Length of Data Sub-Block
212 (three bytes of data to follow)
213 byte 16 : 1 (hex 0x01)
214 bytes 17 to 18 : 0 to 65535, an unsigned integer in
215 lo-hi byte format. This indicate the
216 number of iterations the loop should
217 be executed.
218 bytes 19 : 0 (hex 0x00) a Data Sub-block Terminator
219 */
220
200 /* application extension header */ 221 /* application extension header */
201 /* XXX: not really sure what to put in here... */
202 #ifdef GIF_ADD_APP_HEADER 222 #ifdef GIF_ADD_APP_HEADER
223 if (loop_count >= 0 && loop_count <= 65535) {
203 put_byte(pb, 0x21); 224 put_byte(pb, 0x21);
204 put_byte(pb, 0xff); 225 put_byte(pb, 0xff);
205 put_byte(pb, 0x0b); 226 put_byte(pb, 0x0b);
206 put_tag(pb, "NETSCAPE2.0"); 227 put_tag(pb, "NETSCAPE2.0"); // bytes 4 to 14
207 put_byte(pb, 0x03); 228 put_byte(pb, 0x03); // byte 15
208 put_byte(pb, 0x01); 229 put_byte(pb, 0x01); // byte 16
209 put_byte(pb, 0x00); 230 put_le16(pb, (uint16_t)loop_count);
210 put_byte(pb, 0x00); 231 put_byte(pb, 0x00); // byte 19
232 }
211 #endif 233 #endif
212 return 0; 234 return 0;
213 } 235 }
214 236
215 /* this is maybe slow, but allows for extensions */ 237 /* this is maybe slow, but allows for extensions */
292 static int gif_write_header(AVFormatContext *s) 314 static int gif_write_header(AVFormatContext *s)
293 { 315 {
294 GIFContext *gif = s->priv_data; 316 GIFContext *gif = s->priv_data;
295 ByteIOContext *pb = &s->pb; 317 ByteIOContext *pb = &s->pb;
296 AVCodecContext *enc, *video_enc; 318 AVCodecContext *enc, *video_enc;
297 int i, width, height/*, rate*/; 319 int i, width, height, loop_count /*, rate*/;
298 320
299 /* XXX: do we reject audio streams or just ignore them ? 321 /* XXX: do we reject audio streams or just ignore them ?
300 if(s->nb_streams > 1) 322 if(s->nb_streams > 1)
301 return -1; 323 return -1;
302 */ 324 */
314 av_free(gif); 336 av_free(gif);
315 return -1; 337 return -1;
316 } else { 338 } else {
317 width = video_enc->width; 339 width = video_enc->width;
318 height = video_enc->height; 340 height = video_enc->height;
341 loop_count = s->loop_output;
319 // rate = video_enc->time_base.den; 342 // rate = video_enc->time_base.den;
320 } 343 }
321 344
322 /* XXX: is it allowed ? seems to work so far... */ 345 /* XXX: is it allowed ? seems to work so far... */
323 video_enc->pix_fmt = PIX_FMT_RGB24; 346 video_enc->pix_fmt = PIX_FMT_RGB24;
324 347
325 gif_image_write_header(pb, width, height, NULL); 348 gif_image_write_header(pb, width, height, loop_count, NULL);
326 349
327 put_flush_packet(&s->pb); 350 put_flush_packet(&s->pb);
328 return 0; 351 return 0;
329 } 352 }
330 353
382 } 405 }
383 406
384 /* better than nothing gif image writer */ 407 /* better than nothing gif image writer */
385 int gif_write(ByteIOContext *pb, AVImageInfo *info) 408 int gif_write(ByteIOContext *pb, AVImageInfo *info)
386 { 409 {
387 gif_image_write_header(pb, info->width, info->height, 410 gif_image_write_header(pb, info->width, info->height, AVFMT_NOOUTPUTLOOP,
388 (uint32_t *)info->pict.data[1]); 411 (uint32_t *)info->pict.data[1]);
389 gif_image_write_image(pb, 0, 0, info->width, info->height, 412 gif_image_write_image(pb, 0, 0, info->width, info->height,
390 info->pict.data[0], info->pict.linesize[0], 413 info->pict.data[0], info->pict.linesize[0],
391 PIX_FMT_PAL8); 414 PIX_FMT_PAL8);
392 put_byte(pb, 0x3b); 415 put_byte(pb, 0x3b);