From e7e243b2ee08313c0fb6a75c1c8c62c78af00d8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20B=C5=93sch?= Date: Thu, 18 Apr 2013 03:35:20 +0200 Subject: [PATCH] gif: use only one graphic control extension block per image. --- libavcodec/gif.c | 29 ++++++----------------------- libavformat/gif.c | 28 ++++++++++++++++++++++++++-- 2 files changed, 32 insertions(+), 25 deletions(-) diff --git a/libavcodec/gif.c b/libavcodec/gif.c index b35cfd1..0df302e 100644 --- a/libavcodec/gif.c +++ b/libavcodec/gif.c @@ -56,28 +56,6 @@ static int gif_image_write_image(AVCodecContext *avctx, int x_start = 0, y_start = 0; const uint8_t *ptr; - /* Mark one colour as transparent if the input palette contains at least - * one colour that is more than 50% transparent. */ - if (palette) { - unsigned i, smallest_alpha = 0xFF, alpha_component = 0; - for (i = 0; i < AVPALETTE_COUNT; i++) { - const uint32_t v = palette[i]; - if (v >> 24 < smallest_alpha) { - smallest_alpha = v >> 24; - alpha_component = i; - } - } - if (smallest_alpha < 128) { - bytestream_put_byte(bytestream, 0x21); /* Extension Introducer */ - bytestream_put_byte(bytestream, 0xf9); /* Graphic Control Label */ - bytestream_put_byte(bytestream, 0x04); /* block length */ - bytestream_put_byte(bytestream, 0x01); /* Transparent Color Flag */ - bytestream_put_le16(bytestream, 0x00); /* no delay */ - bytestream_put_byte(bytestream, alpha_component); - bytestream_put_byte(bytestream, 0x00); - } - } - /* Crop image */ // TODO support with palette change if (s->last_frame && !palette) { @@ -210,8 +188,13 @@ static int gif_encode_frame(AVCodecContext *avctx, AVPacket *pkt, p->pict_type = AV_PICTURE_TYPE_I; p->key_frame = 1; - if (avctx->pix_fmt == AV_PIX_FMT_PAL8) + if (avctx->pix_fmt == AV_PIX_FMT_PAL8) { + uint8_t *pal_exdata = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE, AVPALETTE_SIZE); + if (!pal_exdata) + return AVERROR(ENOMEM); + memcpy(pal_exdata, p->data[1], AVPALETTE_SIZE); palette = (uint32_t*)p->data[1]; + } gif_image_write_image(avctx, &outbuf_ptr, end, palette, pict->data[0], pict->linesize[0]); if (!s->last_frame) { diff --git a/libavformat/gif.c b/libavformat/gif.c index 3d86f23..f26d537 100644 --- a/libavformat/gif.c +++ b/libavformat/gif.c @@ -102,15 +102,39 @@ static int gif_write_header(AVFormatContext *s) static int gif_write_packet(AVFormatContext *s, AVPacket *pkt) { + int size; AVCodecContext *enc = s->streams[pkt->stream_index]->codec; AVIOContext *pb = s->pb; int jiffies; + uint8_t flags = 0x4, transparent_color_index = 0x1f; + const uint32_t *palette; + + /* Mark one colour as transparent if the input palette contains at least + * one colour that is more than 50% transparent. */ + palette = (uint32_t*)av_packet_get_side_data(pkt, AV_PKT_DATA_PALETTE, &size); + if (palette && size != AVPALETTE_SIZE) { + av_log(s, AV_LOG_ERROR, "Invalid palette extradata\n"); + return AVERROR_INVALIDDATA; + } + if (palette) { + unsigned i, smallest_alpha = 0xff; + + for (i = 0; i < AVPALETTE_COUNT; i++) { + const uint32_t v = palette[i]; + if (v >> 24 < smallest_alpha) { + smallest_alpha = v >> 24; + transparent_color_index = i; + } + } + if (smallest_alpha < 128) + flags |= 0x1; /* Transparent Color Flag */ + } /* graphic control extension block */ avio_w8(pb, 0x21); avio_w8(pb, 0xf9); avio_w8(pb, 0x04); /* block size */ - avio_w8(pb, 0x04); /* flags */ + avio_w8(pb, flags); /* 1 jiffy is 1/70 s */ /* the delay_time field indicates the number of jiffies - 1 */ @@ -121,7 +145,7 @@ static int gif_write_packet(AVFormatContext *s, AVPacket *pkt) avio_wl16(pb, jiffies); - avio_w8(pb, 0x1f); /* transparent color index */ + avio_w8(pb, transparent_color_index); avio_w8(pb, 0x00); avio_write(pb, pkt->data, pkt->size); -- 1.8.2.1