00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044 #include "avcodec.h"
00045 #include "bytestream.h"
00046 #include "bitstream.h"
00047
00048
00049 #define GIF_CHUNKS 100
00050
00051
00052
00053 #define GIF_ADD_APP_HEADER // required to enable looping of animated gif
00054
00055 typedef struct {
00056 unsigned char r;
00057 unsigned char g;
00058 unsigned char b;
00059 } rgb_triplet;
00060
00061
00062
00063
00064
00065
00066
00067
00068 static const rgb_triplet gif_clut[216] = {
00069 { 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x33 }, { 0x00, 0x00, 0x66 }, { 0x00, 0x00, 0x99 }, { 0x00, 0x00, 0xcc }, { 0x00, 0x00, 0xff },
00070 { 0x00, 0x33, 0x00 }, { 0x00, 0x33, 0x33 }, { 0x00, 0x33, 0x66 }, { 0x00, 0x33, 0x99 }, { 0x00, 0x33, 0xcc }, { 0x00, 0x33, 0xff },
00071 { 0x00, 0x66, 0x00 }, { 0x00, 0x66, 0x33 }, { 0x00, 0x66, 0x66 }, { 0x00, 0x66, 0x99 }, { 0x00, 0x66, 0xcc }, { 0x00, 0x66, 0xff },
00072 { 0x00, 0x99, 0x00 }, { 0x00, 0x99, 0x33 }, { 0x00, 0x99, 0x66 }, { 0x00, 0x99, 0x99 }, { 0x00, 0x99, 0xcc }, { 0x00, 0x99, 0xff },
00073 { 0x00, 0xcc, 0x00 }, { 0x00, 0xcc, 0x33 }, { 0x00, 0xcc, 0x66 }, { 0x00, 0xcc, 0x99 }, { 0x00, 0xcc, 0xcc }, { 0x00, 0xcc, 0xff },
00074 { 0x00, 0xff, 0x00 }, { 0x00, 0xff, 0x33 }, { 0x00, 0xff, 0x66 }, { 0x00, 0xff, 0x99 }, { 0x00, 0xff, 0xcc }, { 0x00, 0xff, 0xff },
00075 { 0x33, 0x00, 0x00 }, { 0x33, 0x00, 0x33 }, { 0x33, 0x00, 0x66 }, { 0x33, 0x00, 0x99 }, { 0x33, 0x00, 0xcc }, { 0x33, 0x00, 0xff },
00076 { 0x33, 0x33, 0x00 }, { 0x33, 0x33, 0x33 }, { 0x33, 0x33, 0x66 }, { 0x33, 0x33, 0x99 }, { 0x33, 0x33, 0xcc }, { 0x33, 0x33, 0xff },
00077 { 0x33, 0x66, 0x00 }, { 0x33, 0x66, 0x33 }, { 0x33, 0x66, 0x66 }, { 0x33, 0x66, 0x99 }, { 0x33, 0x66, 0xcc }, { 0x33, 0x66, 0xff },
00078 { 0x33, 0x99, 0x00 }, { 0x33, 0x99, 0x33 }, { 0x33, 0x99, 0x66 }, { 0x33, 0x99, 0x99 }, { 0x33, 0x99, 0xcc }, { 0x33, 0x99, 0xff },
00079 { 0x33, 0xcc, 0x00 }, { 0x33, 0xcc, 0x33 }, { 0x33, 0xcc, 0x66 }, { 0x33, 0xcc, 0x99 }, { 0x33, 0xcc, 0xcc }, { 0x33, 0xcc, 0xff },
00080 { 0x33, 0xff, 0x00 }, { 0x33, 0xff, 0x33 }, { 0x33, 0xff, 0x66 }, { 0x33, 0xff, 0x99 }, { 0x33, 0xff, 0xcc }, { 0x33, 0xff, 0xff },
00081 { 0x66, 0x00, 0x00 }, { 0x66, 0x00, 0x33 }, { 0x66, 0x00, 0x66 }, { 0x66, 0x00, 0x99 }, { 0x66, 0x00, 0xcc }, { 0x66, 0x00, 0xff },
00082 { 0x66, 0x33, 0x00 }, { 0x66, 0x33, 0x33 }, { 0x66, 0x33, 0x66 }, { 0x66, 0x33, 0x99 }, { 0x66, 0x33, 0xcc }, { 0x66, 0x33, 0xff },
00083 { 0x66, 0x66, 0x00 }, { 0x66, 0x66, 0x33 }, { 0x66, 0x66, 0x66 }, { 0x66, 0x66, 0x99 }, { 0x66, 0x66, 0xcc }, { 0x66, 0x66, 0xff },
00084 { 0x66, 0x99, 0x00 }, { 0x66, 0x99, 0x33 }, { 0x66, 0x99, 0x66 }, { 0x66, 0x99, 0x99 }, { 0x66, 0x99, 0xcc }, { 0x66, 0x99, 0xff },
00085 { 0x66, 0xcc, 0x00 }, { 0x66, 0xcc, 0x33 }, { 0x66, 0xcc, 0x66 }, { 0x66, 0xcc, 0x99 }, { 0x66, 0xcc, 0xcc }, { 0x66, 0xcc, 0xff },
00086 { 0x66, 0xff, 0x00 }, { 0x66, 0xff, 0x33 }, { 0x66, 0xff, 0x66 }, { 0x66, 0xff, 0x99 }, { 0x66, 0xff, 0xcc }, { 0x66, 0xff, 0xff },
00087 { 0x99, 0x00, 0x00 }, { 0x99, 0x00, 0x33 }, { 0x99, 0x00, 0x66 }, { 0x99, 0x00, 0x99 }, { 0x99, 0x00, 0xcc }, { 0x99, 0x00, 0xff },
00088 { 0x99, 0x33, 0x00 }, { 0x99, 0x33, 0x33 }, { 0x99, 0x33, 0x66 }, { 0x99, 0x33, 0x99 }, { 0x99, 0x33, 0xcc }, { 0x99, 0x33, 0xff },
00089 { 0x99, 0x66, 0x00 }, { 0x99, 0x66, 0x33 }, { 0x99, 0x66, 0x66 }, { 0x99, 0x66, 0x99 }, { 0x99, 0x66, 0xcc }, { 0x99, 0x66, 0xff },
00090 { 0x99, 0x99, 0x00 }, { 0x99, 0x99, 0x33 }, { 0x99, 0x99, 0x66 }, { 0x99, 0x99, 0x99 }, { 0x99, 0x99, 0xcc }, { 0x99, 0x99, 0xff },
00091 { 0x99, 0xcc, 0x00 }, { 0x99, 0xcc, 0x33 }, { 0x99, 0xcc, 0x66 }, { 0x99, 0xcc, 0x99 }, { 0x99, 0xcc, 0xcc }, { 0x99, 0xcc, 0xff },
00092 { 0x99, 0xff, 0x00 }, { 0x99, 0xff, 0x33 }, { 0x99, 0xff, 0x66 }, { 0x99, 0xff, 0x99 }, { 0x99, 0xff, 0xcc }, { 0x99, 0xff, 0xff },
00093 { 0xcc, 0x00, 0x00 }, { 0xcc, 0x00, 0x33 }, { 0xcc, 0x00, 0x66 }, { 0xcc, 0x00, 0x99 }, { 0xcc, 0x00, 0xcc }, { 0xcc, 0x00, 0xff },
00094 { 0xcc, 0x33, 0x00 }, { 0xcc, 0x33, 0x33 }, { 0xcc, 0x33, 0x66 }, { 0xcc, 0x33, 0x99 }, { 0xcc, 0x33, 0xcc }, { 0xcc, 0x33, 0xff },
00095 { 0xcc, 0x66, 0x00 }, { 0xcc, 0x66, 0x33 }, { 0xcc, 0x66, 0x66 }, { 0xcc, 0x66, 0x99 }, { 0xcc, 0x66, 0xcc }, { 0xcc, 0x66, 0xff },
00096 { 0xcc, 0x99, 0x00 }, { 0xcc, 0x99, 0x33 }, { 0xcc, 0x99, 0x66 }, { 0xcc, 0x99, 0x99 }, { 0xcc, 0x99, 0xcc }, { 0xcc, 0x99, 0xff },
00097 { 0xcc, 0xcc, 0x00 }, { 0xcc, 0xcc, 0x33 }, { 0xcc, 0xcc, 0x66 }, { 0xcc, 0xcc, 0x99 }, { 0xcc, 0xcc, 0xcc }, { 0xcc, 0xcc, 0xff },
00098 { 0xcc, 0xff, 0x00 }, { 0xcc, 0xff, 0x33 }, { 0xcc, 0xff, 0x66 }, { 0xcc, 0xff, 0x99 }, { 0xcc, 0xff, 0xcc }, { 0xcc, 0xff, 0xff },
00099 { 0xff, 0x00, 0x00 }, { 0xff, 0x00, 0x33 }, { 0xff, 0x00, 0x66 }, { 0xff, 0x00, 0x99 }, { 0xff, 0x00, 0xcc }, { 0xff, 0x00, 0xff },
00100 { 0xff, 0x33, 0x00 }, { 0xff, 0x33, 0x33 }, { 0xff, 0x33, 0x66 }, { 0xff, 0x33, 0x99 }, { 0xff, 0x33, 0xcc }, { 0xff, 0x33, 0xff },
00101 { 0xff, 0x66, 0x00 }, { 0xff, 0x66, 0x33 }, { 0xff, 0x66, 0x66 }, { 0xff, 0x66, 0x99 }, { 0xff, 0x66, 0xcc }, { 0xff, 0x66, 0xff },
00102 { 0xff, 0x99, 0x00 }, { 0xff, 0x99, 0x33 }, { 0xff, 0x99, 0x66 }, { 0xff, 0x99, 0x99 }, { 0xff, 0x99, 0xcc }, { 0xff, 0x99, 0xff },
00103 { 0xff, 0xcc, 0x00 }, { 0xff, 0xcc, 0x33 }, { 0xff, 0xcc, 0x66 }, { 0xff, 0xcc, 0x99 }, { 0xff, 0xcc, 0xcc }, { 0xff, 0xcc, 0xff },
00104 { 0xff, 0xff, 0x00 }, { 0xff, 0xff, 0x33 }, { 0xff, 0xff, 0x66 }, { 0xff, 0xff, 0x99 }, { 0xff, 0xff, 0xcc }, { 0xff, 0xff, 0xff },
00105 };
00106
00107
00108
00109
00110
00111
00112 #ifdef ALT_BITSTREAM_WRITER
00113 # error no ALT_BITSTREAM_WRITER support for now
00114 #endif
00115
00116 static void gif_put_bits_rev(PutBitContext *s, int n, unsigned int value)
00117 {
00118 unsigned int bit_buf;
00119 int bit_cnt;
00120
00121
00122 assert(n == 32 || value < (1U << n));
00123
00124 bit_buf = s->bit_buf;
00125 bit_cnt = 32 - s->bit_left;
00126
00127
00128
00129 if (n < (32-bit_cnt)) {
00130 bit_buf |= value << (bit_cnt);
00131 bit_cnt+=n;
00132 } else {
00133 bit_buf |= value << (bit_cnt);
00134
00135 bytestream_put_le32(&s->buf_ptr, bit_buf);
00136
00137
00138 if (s->buf_ptr >= s->buf_end)
00139 abort();
00140
00141 bit_cnt=bit_cnt + n - 32;
00142 if (bit_cnt == 0) {
00143 bit_buf = 0;
00144 } else {
00145 bit_buf = value >> (n - bit_cnt);
00146 }
00147 }
00148
00149 s->bit_buf = bit_buf;
00150 s->bit_left = 32 - bit_cnt;
00151 }
00152
00153
00154 static void gif_flush_put_bits_rev(PutBitContext *s)
00155 {
00156 while (s->bit_left < 32) {
00157
00158 *s->buf_ptr++=s->bit_buf & 0xff;
00159 s->bit_buf>>=8;
00160 s->bit_left+=8;
00161 }
00162
00163 s->bit_left=32;
00164 s->bit_buf=0;
00165 }
00166
00167
00168
00169
00170 static int gif_image_write_header(uint8_t **bytestream,
00171 int width, int height, int loop_count,
00172 uint32_t *palette)
00173 {
00174 int i;
00175 unsigned int v;
00176
00177 bytestream_put_buffer(bytestream, "GIF", 3);
00178 bytestream_put_buffer(bytestream, "89a", 3);
00179 bytestream_put_le16(bytestream, width);
00180 bytestream_put_le16(bytestream, height);
00181
00182 bytestream_put_byte(bytestream, 0xf7);
00183 bytestream_put_byte(bytestream, 0x1f);
00184 bytestream_put_byte(bytestream, 0);
00185
00186
00187 if (!palette) {
00188 bytestream_put_buffer(bytestream, (const unsigned char *)gif_clut, 216*3);
00189 for(i=0;i<((256-216)*3);i++)
00190 bytestream_put_byte(bytestream, 0);
00191 } else {
00192 for(i=0;i<256;i++) {
00193 v = palette[i];
00194 bytestream_put_be24(bytestream, v);
00195 }
00196 }
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218 #ifdef GIF_ADD_APP_HEADER
00219 if (loop_count >= 0 && loop_count <= 65535) {
00220 bytestream_put_byte(bytestream, 0x21);
00221 bytestream_put_byte(bytestream, 0xff);
00222 bytestream_put_byte(bytestream, 0x0b);
00223 bytestream_put_buffer(bytestream, "NETSCAPE2.0", 11);
00224 bytestream_put_byte(bytestream, 0x03);
00225 bytestream_put_byte(bytestream, 0x01);
00226 bytestream_put_le16(bytestream, (uint16_t)loop_count);
00227 bytestream_put_byte(bytestream, 0x00);
00228 }
00229 #endif
00230 return 0;
00231 }
00232
00233
00234 static inline unsigned char gif_clut_index(uint8_t r, uint8_t g, uint8_t b)
00235 {
00236 return ((((r)/47)%6)*6*6+(((g)/47)%6)*6+(((b)/47)%6));
00237 }
00238
00239
00240 static int gif_image_write_image(uint8_t **bytestream,
00241 int x1, int y1, int width, int height,
00242 const uint8_t *buf, int linesize, int pix_fmt)
00243 {
00244 PutBitContext p;
00245 uint8_t buffer[200];
00246 int i, left, w, v;
00247 const uint8_t *ptr;
00248
00249
00250 bytestream_put_byte(bytestream, 0x2c);
00251 bytestream_put_le16(bytestream, x1);
00252 bytestream_put_le16(bytestream, y1);
00253 bytestream_put_le16(bytestream, width);
00254 bytestream_put_le16(bytestream, height);
00255 bytestream_put_byte(bytestream, 0x00);
00256
00257
00258 bytestream_put_byte(bytestream, 0x08);
00259
00260 left= width * height;
00261
00262 init_put_bits(&p, buffer, 130);
00263
00264
00265
00266
00267
00268 ptr = buf;
00269 w = width;
00270 while(left>0) {
00271
00272 gif_put_bits_rev(&p, 9, 0x0100);
00273
00274 for(i=(left<GIF_CHUNKS)?left:GIF_CHUNKS;i;i--) {
00275 if (pix_fmt == PIX_FMT_RGB24) {
00276 v = gif_clut_index(ptr[0], ptr[1], ptr[2]);
00277 ptr+=3;
00278 } else {
00279 v = *ptr++;
00280 }
00281 gif_put_bits_rev(&p, 9, v);
00282 if (--w == 0) {
00283 w = width;
00284 buf += linesize;
00285 ptr = buf;
00286 }
00287 }
00288
00289 if(left<=GIF_CHUNKS) {
00290 gif_put_bits_rev(&p, 9, 0x101);
00291 gif_flush_put_bits_rev(&p);
00292 }
00293 if(pbBufPtr(&p) - p.buf > 0) {
00294 bytestream_put_byte(bytestream, pbBufPtr(&p) - p.buf);
00295 bytestream_put_buffer(bytestream, p.buf, pbBufPtr(&p) - p.buf);
00296 p.buf_ptr = p.buf;
00297 }
00298 left-=GIF_CHUNKS;
00299 }
00300 bytestream_put_byte(bytestream, 0x00);
00301 bytestream_put_byte(bytestream, 0x3b);
00302 return 0;
00303 }
00304
00305 typedef struct {
00306 int64_t time, file_time;
00307 uint8_t buffer[100];
00308 AVFrame picture;
00309 } GIFContext;
00310
00311 static int gif_encode_init(AVCodecContext *avctx)
00312 {
00313 GIFContext *s = avctx->priv_data;
00314
00315 avctx->coded_frame = &s->picture;
00316 return 0;
00317 }
00318
00319
00320 static int gif_encode_frame(AVCodecContext *avctx, unsigned char *outbuf, int buf_size, void *data)
00321 {
00322 GIFContext *s = avctx->priv_data;
00323 AVFrame *pict = data;
00324 AVFrame *const p = (AVFrame *)&s->picture;
00325 uint8_t *outbuf_ptr = outbuf;
00326
00327 *p = *pict;
00328 p->pict_type = FF_I_TYPE;
00329 p->key_frame = 1;
00330 gif_image_write_header(&outbuf_ptr, avctx->width, avctx->height, -1, (uint32_t *)pict->data[1]);
00331 gif_image_write_image(&outbuf_ptr, 0, 0, avctx->width, avctx->height, pict->data[0], pict->linesize[0], PIX_FMT_PAL8);
00332 return outbuf_ptr - outbuf;
00333 }
00334
00335 AVCodec gif_encoder = {
00336 "gif",
00337 CODEC_TYPE_VIDEO,
00338 CODEC_ID_GIF,
00339 sizeof(GIFContext),
00340 gif_encode_init,
00341 gif_encode_frame,
00342 NULL,
00343 .pix_fmts= (enum PixelFormat[]){PIX_FMT_PAL8, -1},
00344 };