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 "lzw.h"
00047 
00048 
00049 
00050 #define BITSTREAM_WRITER_LE
00051 
00052 #include "put_bits.h"
00053 
00054 typedef struct {
00055     AVFrame picture;
00056     LZWState *lzw;
00057     uint8_t *buf;
00058 } GIFContext;
00059 
00060 
00061 static int gif_image_write_header(AVCodecContext *avctx,
00062                                   uint8_t **bytestream, uint32_t *palette)
00063 {
00064     int i;
00065     unsigned int v, smallest_alpha = 0xFF, alpha_component = 0;
00066 
00067     bytestream_put_buffer(bytestream, "GIF", 3);
00068     bytestream_put_buffer(bytestream, "89a", 3);
00069     bytestream_put_le16(bytestream, avctx->width);
00070     bytestream_put_le16(bytestream, avctx->height);
00071 
00072     bytestream_put_byte(bytestream, 0xf7); 
00073     bytestream_put_byte(bytestream, 0x1f); 
00074     bytestream_put_byte(bytestream, 0); 
00075 
00076     
00077     for(i=0;i<256;i++) {
00078         v = palette[i];
00079         bytestream_put_be24(bytestream, v);
00080         if (v >> 24 < smallest_alpha) {
00081             smallest_alpha = v >> 24;
00082             alpha_component = i;
00083         }
00084     }
00085 
00086     if (smallest_alpha < 128) {
00087         bytestream_put_byte(bytestream, 0x21); 
00088         bytestream_put_byte(bytestream, 0xf9); 
00089         bytestream_put_byte(bytestream, 0x04); 
00090         bytestream_put_byte(bytestream, 0x01); 
00091         bytestream_put_le16(bytestream, 0x00); 
00092         bytestream_put_byte(bytestream, alpha_component);
00093         bytestream_put_byte(bytestream, 0x00);
00094     }
00095 
00096     return 0;
00097 }
00098 
00099 static int gif_image_write_image(AVCodecContext *avctx,
00100                                  uint8_t **bytestream, uint8_t *end,
00101                                  const uint8_t *buf, int linesize)
00102 {
00103     GIFContext *s = avctx->priv_data;
00104     int len = 0, height;
00105     const uint8_t *ptr;
00106     
00107 
00108     bytestream_put_byte(bytestream, 0x2c);
00109     bytestream_put_le16(bytestream, 0);
00110     bytestream_put_le16(bytestream, 0);
00111     bytestream_put_le16(bytestream, avctx->width);
00112     bytestream_put_le16(bytestream, avctx->height);
00113     bytestream_put_byte(bytestream, 0x00); 
00114     
00115 
00116     bytestream_put_byte(bytestream, 0x08);
00117 
00118     ff_lzw_encode_init(s->lzw, s->buf, avctx->width*avctx->height,
00119                        12, FF_LZW_GIF, put_bits);
00120 
00121     ptr = buf;
00122     for (height = avctx->height; height--;) {
00123         len += ff_lzw_encode(s->lzw, ptr, avctx->width);
00124         ptr += linesize;
00125     }
00126     len += ff_lzw_encode_flush(s->lzw, flush_put_bits);
00127 
00128     ptr = s->buf;
00129     while (len > 0) {
00130         int size = FFMIN(255, len);
00131         bytestream_put_byte(bytestream, size);
00132         if (end - *bytestream < size)
00133             return -1;
00134         bytestream_put_buffer(bytestream, ptr, size);
00135         ptr += size;
00136         len -= size;
00137     }
00138     bytestream_put_byte(bytestream, 0x00); 
00139     bytestream_put_byte(bytestream, 0x3b);
00140     return 0;
00141 }
00142 
00143 static av_cold int gif_encode_init(AVCodecContext *avctx)
00144 {
00145     GIFContext *s = avctx->priv_data;
00146 
00147     avctx->coded_frame = &s->picture;
00148     s->lzw = av_mallocz(ff_lzw_encode_state_size);
00149     if (!s->lzw)
00150         return AVERROR(ENOMEM);
00151     s->buf = av_malloc(avctx->width*avctx->height*2);
00152     if (!s->buf)
00153          return AVERROR(ENOMEM);
00154     return 0;
00155 }
00156 
00157 
00158 static int gif_encode_frame(AVCodecContext *avctx, unsigned char *outbuf, int buf_size, void *data)
00159 {
00160     GIFContext *s = avctx->priv_data;
00161     AVFrame *pict = data;
00162     AVFrame *const p = (AVFrame *)&s->picture;
00163     uint8_t *outbuf_ptr = outbuf;
00164     uint8_t *end = outbuf + buf_size;
00165 
00166     *p = *pict;
00167     p->pict_type = AV_PICTURE_TYPE_I;
00168     p->key_frame = 1;
00169     gif_image_write_header(avctx, &outbuf_ptr, (uint32_t *)pict->data[1]);
00170     gif_image_write_image(avctx, &outbuf_ptr, end, pict->data[0], pict->linesize[0]);
00171     return outbuf_ptr - outbuf;
00172 }
00173 
00174 static int gif_encode_close(AVCodecContext *avctx)
00175 {
00176     GIFContext *s = avctx->priv_data;
00177 
00178     av_freep(&s->lzw);
00179     av_freep(&s->buf);
00180     return 0;
00181 }
00182 
00183 AVCodec ff_gif_encoder = {
00184     .name           = "gif",
00185     .type           = AVMEDIA_TYPE_VIDEO,
00186     .id             = CODEC_ID_GIF,
00187     .priv_data_size = sizeof(GIFContext),
00188     .init           = gif_encode_init,
00189     .encode         = gif_encode_frame,
00190     .close          = gif_encode_close,
00191     .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},
00192     .long_name= NULL_IF_CONFIG_SMALL("GIF (Graphics Interchange Format)"),
00193 };