[FFmpeg-cvslog] avformat/gifdec: export duration, nb_frames and comment

Paul B Mahol git at videolan.org
Thu Dec 13 20:32:19 EET 2018


ffmpeg | branch: master | Paul B Mahol <onemda at gmail.com> | Thu Dec 13 18:37:27 2018 +0100| [0aa5a7b2e98ee3c6453a9c038b6f612125538d52] | committer: Paul B Mahol

avformat/gifdec: export duration, nb_frames and comment

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

 libavcodec/gif.h     |  1 +
 libavformat/gifdec.c | 85 +++++++++++++++++++++++++++++++++++++++++++---------
 2 files changed, 72 insertions(+), 14 deletions(-)

diff --git a/libavcodec/gif.h b/libavcodec/gif.h
index 9f35778857..7fb61495bc 100644
--- a/libavcodec/gif.h
+++ b/libavcodec/gif.h
@@ -43,6 +43,7 @@ static const uint8_t gif89a_sig[6] = "GIF89a";
 #define GIF_EXTENSION_INTRODUCER    0x21
 #define GIF_IMAGE_SEPARATOR         0x2c
 #define GIF_GCE_EXT_LABEL           0xf9
+#define GIF_COM_EXT_LABEL           0xfe
 #define GIF_APP_EXT_LABEL           0xff
 #define NETSCAPE_EXT_STR            "NETSCAPE2.0"
 
diff --git a/libavformat/gifdec.c b/libavformat/gifdec.c
index 1f3ac8d8d9..7dc67ba875 100644
--- a/libavformat/gifdec.c
+++ b/libavformat/gifdec.c
@@ -25,6 +25,7 @@
  */
 
 #include "avformat.h"
+#include "libavutil/bprint.h"
 #include "libavutil/intreadwrite.h"
 #include "libavutil/opt.h"
 #include "internal.h"
@@ -94,12 +95,25 @@ static int resync(AVIOContext *pb)
     return 0;
 }
 
+static int gif_skip_subblocks(AVIOContext *pb)
+{
+    int sb_size, ret = 0;
+
+    while (0x00 != (sb_size = avio_r8(pb))) {
+        if ((ret = avio_skip(pb, sb_size)) < 0)
+            return ret;
+    }
+
+    return ret;
+}
+
 static int gif_read_header(AVFormatContext *s)
 {
     GIFDemuxContext *gdc = s->priv_data;
     AVIOContext     *pb  = s->pb;
     AVStream        *st;
-    int width, height, ret, n;
+    int type, width, height, ret, n, flags;
+    int64_t nb_frames = 0, duration = 0;
 
     if ((ret = resync(pb)) < 0)
         return ret;
@@ -107,7 +121,8 @@ static int gif_read_header(AVFormatContext *s)
     gdc->delay  = gdc->default_delay;
     width  = avio_rl16(pb);
     height = avio_rl16(pb);
-    avio_skip(pb, 2);
+    flags = avio_r8(pb);
+    avio_skip(pb, 1);
     n      = avio_r8(pb);
 
     if (width == 0 || height == 0)
@@ -117,6 +132,57 @@ static int gif_read_header(AVFormatContext *s)
     if (!st)
         return AVERROR(ENOMEM);
 
+    if (flags & 0x80)
+        avio_skip(pb, 3 * (1 << ((flags & 0x07) + 1)));
+
+    while ((type = avio_r8(pb)) != GIF_TRAILER) {
+        if (avio_feof(pb))
+            break;
+        if (type == GIF_EXTENSION_INTRODUCER) {
+            int subtype = avio_r8(pb);
+            if (subtype == GIF_COM_EXT_LABEL) {
+                AVBPrint bp;
+                int block_size;
+
+                av_bprint_init(&bp, 0, -1);
+                while ((block_size = avio_r8(pb)) != 0) {
+                    avio_read_to_bprint(pb, &bp, block_size);
+                }
+                av_dict_set(&s->metadata, "comment", bp.str, 0);
+                av_bprint_finalize(&bp, NULL);
+            } else if (subtype == GIF_GCE_EXT_LABEL) {
+                int block_size = avio_r8(pb);
+
+                if (block_size == 4) {
+                    int delay;
+
+                    avio_skip(pb, 1);
+                    delay = avio_rl16(pb);
+                    if (delay < gdc->min_delay)
+                        delay = gdc->default_delay;
+                    delay = FFMIN(delay, gdc->max_delay);
+                    duration += delay;
+                    avio_skip(pb, 1);
+                } else {
+                    avio_skip(pb, block_size);
+                }
+                gif_skip_subblocks(pb);
+            } else {
+                gif_skip_subblocks(pb);
+            }
+        } else if (type == GIF_IMAGE_SEPARATOR) {
+            avio_skip(pb, 8);
+            flags = avio_r8(pb);
+            if (flags & 0x80)
+                avio_skip(pb, 3 * (1 << ((flags & 0x07) + 1)));
+            avio_skip(pb, 1);
+            gif_skip_subblocks(pb);
+            nb_frames++;
+        } else {
+            break;
+        }
+    }
+
     /* GIF format operates with time in "hundredths of second",
      * therefore timebase is 1/100 */
     avpriv_set_pts_info(st, 64, 1, 100);
@@ -124,6 +190,9 @@ static int gif_read_header(AVFormatContext *s)
     st->codecpar->codec_id   = AV_CODEC_ID_GIF;
     st->codecpar->width      = width;
     st->codecpar->height     = height;
+    st->start_time           = 0;
+    st->duration             = duration;
+    st->nb_frames            = nb_frames;
     if (n) {
         st->codecpar->sample_aspect_ratio.num = n + 15;
         st->codecpar->sample_aspect_ratio.den = 64;
@@ -136,18 +205,6 @@ static int gif_read_header(AVFormatContext *s)
     return 0;
 }
 
-static int gif_skip_subblocks(AVIOContext *pb)
-{
-    int sb_size, ret = 0;
-
-    while (0x00 != (sb_size = avio_r8(pb))) {
-        if ((ret = avio_skip(pb, sb_size)) < 0)
-            return ret;
-    }
-
-    return ret;
-}
-
 static int gif_read_ext(AVFormatContext *s)
 {
     GIFDemuxContext *gdc = s->priv_data;



More information about the ffmpeg-cvslog mailing list