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 if (avctx->width > 65535 || avctx->height > 65535) {
00149 av_log(avctx, AV_LOG_ERROR, "GIF does not support resolutions above 65535x65535\n");
00150 return -1;
00151 }
00152
00153 avctx->coded_frame = &s->picture;
00154 s->lzw = av_mallocz(ff_lzw_encode_state_size);
00155 if (!s->lzw)
00156 return AVERROR(ENOMEM);
00157 s->buf = av_malloc(avctx->width*avctx->height*2);
00158 if (!s->buf)
00159 return AVERROR(ENOMEM);
00160 return 0;
00161 }
00162
00163
00164 static int gif_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
00165 const AVFrame *pict, int *got_packet)
00166 {
00167 GIFContext *s = avctx->priv_data;
00168 AVFrame *const p = &s->picture;
00169 uint8_t *outbuf_ptr, *end;
00170 int ret;
00171
00172 if ((ret = ff_alloc_packet2(avctx, pkt, avctx->width*avctx->height*7/5 + FF_MIN_BUFFER_SIZE)) < 0)
00173 return ret;
00174 outbuf_ptr = pkt->data;
00175 end = pkt->data + pkt->size;
00176
00177 *p = *pict;
00178 p->pict_type = AV_PICTURE_TYPE_I;
00179 p->key_frame = 1;
00180 gif_image_write_header(avctx, &outbuf_ptr, (uint32_t *)pict->data[1]);
00181 gif_image_write_image(avctx, &outbuf_ptr, end, pict->data[0], pict->linesize[0]);
00182
00183 pkt->size = outbuf_ptr - pkt->data;
00184 pkt->flags |= AV_PKT_FLAG_KEY;
00185 *got_packet = 1;
00186
00187 return 0;
00188 }
00189
00190 static int gif_encode_close(AVCodecContext *avctx)
00191 {
00192 GIFContext *s = avctx->priv_data;
00193
00194 av_freep(&s->lzw);
00195 av_freep(&s->buf);
00196 return 0;
00197 }
00198
00199 AVCodec ff_gif_encoder = {
00200 .name = "gif",
00201 .type = AVMEDIA_TYPE_VIDEO,
00202 .id = AV_CODEC_ID_GIF,
00203 .priv_data_size = sizeof(GIFContext),
00204 .init = gif_encode_init,
00205 .encode2 = gif_encode_frame,
00206 .close = gif_encode_close,
00207 .pix_fmts = (const enum PixelFormat[]){
00208 PIX_FMT_RGB8, PIX_FMT_BGR8, PIX_FMT_RGB4_BYTE, PIX_FMT_BGR4_BYTE,
00209 PIX_FMT_GRAY8, PIX_FMT_PAL8, PIX_FMT_NONE
00210 },
00211 .long_name = NULL_IF_CONFIG_SMALL("GIF (Graphics Interchange Format)"),
00212 };