Mercurial > libavcodec.hg
annotate gif.c @ 11034:fd5921186064 libavcodec
Make the fast loop filter path work with unavailable left MBs.
This prevents the issue with having to switch between slow and
fast code paths in each row.
0.5% faster loopfilter for cathedral
author | michael |
---|---|
date | Thu, 28 Jan 2010 02:15:25 +0000 |
parents | e15eb76d9e47 |
children | 8a4984c5cacc |
rev | line source |
---|---|
4125 | 1 /* |
2 * GIF encoder. | |
8629
04423b2f6e0b
cosmetics: Remove pointless period after copyright statement non-sentences.
diego
parents:
8591
diff
changeset
|
3 * Copyright (c) 2000 Fabrice Bellard |
04423b2f6e0b
cosmetics: Remove pointless period after copyright statement non-sentences.
diego
parents:
8591
diff
changeset
|
4 * Copyright (c) 2002 Francois Revol |
04423b2f6e0b
cosmetics: Remove pointless period after copyright statement non-sentences.
diego
parents:
8591
diff
changeset
|
5 * Copyright (c) 2006 Baptiste Coudurier |
4125 | 6 * |
7 * This file is part of FFmpeg. | |
8 * | |
9 * FFmpeg is free software; you can redistribute it and/or | |
10 * modify it under the terms of the GNU Lesser General Public | |
11 * License as published by the Free Software Foundation; either | |
12 * version 2.1 of the License, or (at your option) any later version. | |
13 * | |
14 * FFmpeg is distributed in the hope that it will be useful, | |
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
17 * Lesser General Public License for more details. | |
18 * | |
19 * You should have received a copy of the GNU Lesser General Public | |
20 * License along with FFmpeg; if not, write to the Free Software | |
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
22 */ | |
23 | |
24 /* | |
25 * First version by Francois Revol revol@free.fr | |
26 * | |
27 * Features and limitations: | |
28 * - currently no compression is performed, | |
29 * in fact the size of the data is 9/8 the size of the image in 8bpp | |
30 * - uses only a global standard palette | |
31 * - tested with IE 5.0, Opera for BeOS, NetPositive (BeOS), and Mozilla (BeOS). | |
32 * | |
33 * Reference documents: | |
34 * http://www.goice.co.jp/member/mo/formats/gif.html | |
35 * http://astronomy.swin.edu.au/pbourke/dataformats/gif/ | |
36 * http://www.dcs.ed.ac.uk/home/mxr/gfx/2d/GIF89a.txt | |
37 * | |
38 * this url claims to have an LZW algorithm not covered by Unisys patent: | |
39 * http://www.msg.net/utility/whirlgif/gifencod.html | |
40 * could help reduce the size of the files _a lot_... | |
41 * some sites mentions an RLE type compression also. | |
42 */ | |
43 | |
44 #include "avcodec.h" | |
45 #include "bytestream.h" | |
10634 | 46 #include "lzw.h" |
8591 | 47 |
48 /* The GIF format uses reversed order for bitstreams... */ | |
49 /* at least they don't use PDP_ENDIAN :) */ | |
50 #define BITSTREAM_WRITER_LE | |
51 | |
9411
4cb7c65fc775
Split bitstream.h, put the bitstream writer stuff in the new file
stefano
parents:
8775
diff
changeset
|
52 #include "put_bits.h" |
4125 | 53 |
10626 | 54 typedef struct { |
55 AVFrame picture; | |
10634 | 56 LZWState *lzw; |
57 uint8_t *buf; | |
10626 | 58 } GIFContext; |
59 | |
4125 | 60 /* GIF header */ |
10629
f164bb900d0b
pass avctx as argument instead of width and height
bcoudurier
parents:
10628
diff
changeset
|
61 static int gif_image_write_header(AVCodecContext *avctx, |
f164bb900d0b
pass avctx as argument instead of width and height
bcoudurier
parents:
10628
diff
changeset
|
62 uint8_t **bytestream, uint32_t *palette) |
4125 | 63 { |
64 int i; | |
65 unsigned int v; | |
66 | |
67 bytestream_put_buffer(bytestream, "GIF", 3); | |
68 bytestream_put_buffer(bytestream, "89a", 3); | |
10629
f164bb900d0b
pass avctx as argument instead of width and height
bcoudurier
parents:
10628
diff
changeset
|
69 bytestream_put_le16(bytestream, avctx->width); |
f164bb900d0b
pass avctx as argument instead of width and height
bcoudurier
parents:
10628
diff
changeset
|
70 bytestream_put_le16(bytestream, avctx->height); |
4125 | 71 |
72 bytestream_put_byte(bytestream, 0xf7); /* flags: global clut, 256 entries */ | |
73 bytestream_put_byte(bytestream, 0x1f); /* background color index */ | |
74 bytestream_put_byte(bytestream, 0); /* aspect ratio */ | |
75 | |
76 /* the global palette */ | |
8774
0a8166d20fd3
remove dead rgb24 code, gif encoder now directly takes palette, patch by Daniel Verkamp, daniel at drv dot nu
bcoudurier
parents:
8773
diff
changeset
|
77 for(i=0;i<256;i++) { |
0a8166d20fd3
remove dead rgb24 code, gif encoder now directly takes palette, patch by Daniel Verkamp, daniel at drv dot nu
bcoudurier
parents:
8773
diff
changeset
|
78 v = palette[i]; |
0a8166d20fd3
remove dead rgb24 code, gif encoder now directly takes palette, patch by Daniel Verkamp, daniel at drv dot nu
bcoudurier
parents:
8773
diff
changeset
|
79 bytestream_put_be24(bytestream, v); |
4125 | 80 } |
81 | |
82 return 0; | |
83 } | |
84 | |
10634 | 85 static int gif_image_write_image(AVCodecContext *avctx, |
86 uint8_t **bytestream, uint8_t *end, | |
10628 | 87 const uint8_t *buf, int linesize) |
4125 | 88 { |
10634 | 89 GIFContext *s = avctx->priv_data; |
90 int len, height; | |
4125 | 91 const uint8_t *ptr; |
92 /* image block */ | |
93 | |
94 bytestream_put_byte(bytestream, 0x2c); | |
10627 | 95 bytestream_put_le16(bytestream, 0); |
96 bytestream_put_le16(bytestream, 0); | |
10629
f164bb900d0b
pass avctx as argument instead of width and height
bcoudurier
parents:
10628
diff
changeset
|
97 bytestream_put_le16(bytestream, avctx->width); |
f164bb900d0b
pass avctx as argument instead of width and height
bcoudurier
parents:
10628
diff
changeset
|
98 bytestream_put_le16(bytestream, avctx->height); |
4125 | 99 bytestream_put_byte(bytestream, 0x00); /* flags */ |
100 /* no local clut */ | |
101 | |
102 bytestream_put_byte(bytestream, 0x08); | |
103 | |
10634 | 104 ff_lzw_encode_init(s->lzw, s->buf, avctx->width*avctx->height, |
105 12, FF_LZW_GIF, put_bits); | |
4125 | 106 |
107 ptr = buf; | |
10634 | 108 for (height = avctx->height; height--;) { |
109 len += ff_lzw_encode(s->lzw, ptr, avctx->width); | |
110 ptr += linesize; | |
111 } | |
112 len += ff_lzw_encode_flush(s->lzw, flush_put_bits); | |
4125 | 113 |
10634 | 114 ptr = s->buf; |
115 while (len > 0) { | |
116 int size = FFMIN(255, len); | |
117 bytestream_put_byte(bytestream, size); | |
118 if (end - *bytestream < size) | |
119 return -1; | |
120 bytestream_put_buffer(bytestream, ptr, size); | |
121 ptr += size; | |
122 len -= size; | |
4125 | 123 } |
124 bytestream_put_byte(bytestream, 0x00); /* end of image block */ | |
125 bytestream_put_byte(bytestream, 0x3b); | |
126 return 0; | |
127 } | |
128 | |
6517
48759bfbd073
Apply 'cold' attribute to init/uninit functions in libavcodec
zuxy
parents:
6152
diff
changeset
|
129 static av_cold int gif_encode_init(AVCodecContext *avctx) |
4125 | 130 { |
131 GIFContext *s = avctx->priv_data; | |
132 | |
133 avctx->coded_frame = &s->picture; | |
10634 | 134 s->lzw = av_mallocz(ff_lzw_encode_state_size); |
135 if (!s->lzw) | |
136 return AVERROR_NOMEM; | |
137 s->buf = av_malloc(avctx->width*avctx->height*2); | |
138 if (!s->buf) | |
139 return AVERROR_NOMEM; | |
4125 | 140 return 0; |
141 } | |
142 | |
143 /* better than nothing gif encoder */ | |
144 static int gif_encode_frame(AVCodecContext *avctx, unsigned char *outbuf, int buf_size, void *data) | |
145 { | |
146 GIFContext *s = avctx->priv_data; | |
147 AVFrame *pict = data; | |
148 AVFrame *const p = (AVFrame *)&s->picture; | |
149 uint8_t *outbuf_ptr = outbuf; | |
10634 | 150 uint8_t *end = outbuf + buf_size; |
4125 | 151 |
152 *p = *pict; | |
153 p->pict_type = FF_I_TYPE; | |
154 p->key_frame = 1; | |
10629
f164bb900d0b
pass avctx as argument instead of width and height
bcoudurier
parents:
10628
diff
changeset
|
155 gif_image_write_header(avctx, &outbuf_ptr, (uint32_t *)pict->data[1]); |
10634 | 156 gif_image_write_image(avctx, &outbuf_ptr, end, pict->data[0], pict->linesize[0]); |
4125 | 157 return outbuf_ptr - outbuf; |
158 } | |
159 | |
10634 | 160 static int gif_encode_close(AVCodecContext *avctx) |
161 { | |
162 GIFContext *s = avctx->priv_data; | |
163 | |
164 av_freep(&s->lzw); | |
165 av_freep(&s->buf); | |
166 return 0; | |
167 } | |
168 | |
4125 | 169 AVCodec gif_encoder = { |
170 "gif", | |
171 CODEC_TYPE_VIDEO, | |
172 CODEC_ID_GIF, | |
173 sizeof(GIFContext), | |
174 gif_encode_init, | |
175 gif_encode_frame, | |
10634 | 176 gif_encode_close, |
10146
38cfe222e1a4
Mark all pix_fmts and supported_framerates compound literals as const.
reimar
parents:
9431
diff
changeset
|
177 .pix_fmts= (const enum PixelFormat[]){PIX_FMT_RGB8, PIX_FMT_BGR8, PIX_FMT_RGB4_BYTE, PIX_FMT_BGR4_BYTE, PIX_FMT_GRAY8, PIX_FMT_PAL8, PIX_FMT_NONE}, |
7040
e943e1409077
Make AVCodec long_names definition conditional depending on CONFIG_SMALL.
stefano
parents:
6788
diff
changeset
|
178 .long_name= NULL_IF_CONFIG_SMALL("GIF (Graphics Interchange Format)"), |
4125 | 179 }; |