[FFmpeg-cvslog] lavf/gif: correct the delay after the first frame.

Clément Bœsch git at videolan.org
Fri Apr 19 12:11:24 CEST 2013


ffmpeg | branch: master | Clément Bœsch <ubitux at gmail.com> | Fri Apr 19 04:02:12 2013 +0200| [a7c5b7a6764b5170515183716943a7a463161cfc] | committer: Clément Bœsch

lavf/gif: correct the delay after the first frame.

To define accurately the delay between two frames, it is necessary to
have both available. Before this commit, the first frame had a delay of
0; while in practice the problem is not visible in most situation, it is
problematic with low frame rate and large scene change.

This commit notably fixes output generated with commands such as:

  ffmpeg -i big_buck_bunny_1080p_h264.mov
     -vf "select='gt(scene,0.4)',scale=320:-1,setpts=N/TB"
     -frames:v 5 -y out.gif

Also, to avoid odd loop delays, the N-1 delay is duplicated for the last
frame.

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=a7c5b7a6764b5170515183716943a7a463161cfc
---

 libavformat/gif.c  |   38 +++++++++++++++++++++++++++++++++-----
 tests/ref/lavf/gif |    4 ++--
 2 files changed, 35 insertions(+), 7 deletions(-)

diff --git a/libavformat/gif.c b/libavformat/gif.c
index 6b03d0a..ef1ea75 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;
diff --git a/tests/ref/lavf/gif b/tests/ref/lavf/gif
index f66d05f..531cd1e 100644
--- a/tests/ref/lavf/gif
+++ b/tests/ref/lavf/gif
@@ -1,3 +1,3 @@
-c886d22859c033b2b0fe2d63ffcf8aef *./tests/data/lavf/lavf.gif
+e35f5ea283bbcb249818e0078ec72664 *./tests/data/lavf/lavf.gif
 2011766 ./tests/data/lavf/lavf.gif
-./tests/data/lavf/lavf.gif CRC=0xdca4429c
+./tests/data/lavf/lavf.gif CRC=0x0dc5477c



More information about the ffmpeg-cvslog mailing list