summaryrefslogtreecommitdiff
path: root/libavformat
diff options
context:
space:
mode:
Diffstat (limited to 'libavformat')
-rw-r--r--libavformat/gif.c38
1 files changed, 33 insertions, 5 deletions
diff --git a/libavformat/gif.c b/libavformat/gif.c
index 6b03d0a6e8..ef1ea7582d 100644
--- a/libavformat/gif.c
+++ b/libavformat/gif.c
@@ -68,7 +68,8 @@ static int gif_image_write_header(AVIOContext *pb, int width, int height,
typedef struct {
AVClass *class; /** Class for private options. */
int loop;
- int64_t prev_pts;
+ AVPacket *prev_pkt;
+ int duration;
} GIFContext;
static int gif_write_header(AVFormatContext *s)
@@ -103,13 +104,33 @@ static int gif_write_header(AVFormatContext *s)
return 0;
}
+/* TODO: move below */
+static int flush_packet(AVFormatContext *s, AVPacket *pkt);
+
static int gif_write_packet(AVFormatContext *s, AVPacket *pkt)
{
GIFContext *gif = s->priv_data;
- int size, duration;
+
+ if (!gif->prev_pkt) {
+ gif->prev_pkt = av_malloc(sizeof(*gif->prev_pkt));
+ if (!gif->prev_pkt)
+ return AVERROR(ENOMEM);
+ return av_copy_packet(gif->prev_pkt, pkt);
+ }
+ return flush_packet(s, pkt);
+}
+
+static int flush_packet(AVFormatContext *s, AVPacket *new)
+{
+ GIFContext *gif = s->priv_data;
+ int size;
AVIOContext *pb = s->pb;
uint8_t flags = 0x4, transparent_color_index = 0x1f;
const uint32_t *palette;
+ AVPacket *pkt = gif->prev_pkt;
+
+ if (!pkt)
+ return 0;
/* Mark one colour as transparent if the input palette contains at least
* one colour that is more than 50% transparent. */
@@ -132,27 +153,34 @@ static int gif_write_packet(AVFormatContext *s, AVPacket *pkt)
flags |= 0x1; /* Transparent Color Flag */
}
- duration = pkt->pts == AV_NOPTS_VALUE ? 0 : av_clip_uint16(pkt->pts - gif->prev_pts);
- gif->prev_pts = pkt->pts;
+ if (new && new->pts != AV_NOPTS_VALUE)
+ gif->duration = av_clip_uint16(new->pts - gif->prev_pkt->pts);
/* graphic control extension block */
avio_w8(pb, 0x21);
avio_w8(pb, 0xf9);
avio_w8(pb, 0x04); /* block size */
avio_w8(pb, flags);
- avio_wl16(pb, duration);
+ avio_wl16(pb, gif->duration);
avio_w8(pb, transparent_color_index);
avio_w8(pb, 0x00);
avio_write(pb, pkt->data, pkt->size);
+ av_free_packet(gif->prev_pkt);
+ if (new)
+ av_copy_packet(gif->prev_pkt, new);
+
return 0;
}
static int gif_write_trailer(AVFormatContext *s)
{
+ GIFContext *gif = s->priv_data;
AVIOContext *pb = s->pb;
+ flush_packet(s, NULL);
+ av_freep(&gif->prev_pkt);
avio_w8(pb, 0x3b);
return 0;