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