Mercurial > libavcodec.hg
annotate gif.c @ 12340:2d15f62f4f8a libavcodec
VP8: move zeroing of luma DC block into the WHT
Lets us do the zeroing in asm instead of C.
Also makes it consistent with the way the regular iDCT code does it.
author | darkshikari |
---|---|
date | Mon, 02 Aug 2010 20:18:09 +0000 |
parents | 998691d7f8f5 |
children |
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) | |
11581
998691d7f8f5
Replace all remaining occurrences of AVERROR_NOMEM with
stefano
parents:
11560
diff
changeset
|
136 return AVERROR(ENOMEM); |
10634 | 137 s->buf = av_malloc(avctx->width*avctx->height*2); |
138 if (!s->buf) | |
11581
998691d7f8f5
Replace all remaining occurrences of AVERROR_NOMEM with
stefano
parents:
11560
diff
changeset
|
139 return AVERROR(ENOMEM); |
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", | |
11560
8a4984c5cacc
Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents:
10634
diff
changeset
|
171 AVMEDIA_TYPE_VIDEO, |
4125 | 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 }; |