lavu/bprint: add append buffer function
[ffmpeg.git] / libavformat / gifdec.c
index 6cf36c1..e05dc41 100644 (file)
@@ -44,6 +44,13 @@ typedef struct GIFDemuxContext {
      */
     int min_delay;
     int default_delay;
+
+    /**
+     * loop options
+     */
+    int total_iter;
+    int iter_count;
+    int ignore_loop;
 } GIFDemuxContext;
 
 /**
@@ -156,6 +163,17 @@ static int gif_read_ext(AVFormatContext *s)
         /* skip the rest of the Graphic Control Extension block */
         if ((ret = avio_skip(pb, sb_size - 3)) < 0 )
             return ret;
+    } else if (ext_label == GIF_APP_EXT_LABEL) {
+        uint8_t netscape_ext[sizeof(NETSCAPE_EXT_STR)-1 + 2];
+
+        if ((sb_size = avio_r8(pb)) != strlen(NETSCAPE_EXT_STR))
+            return 0;
+        ret = avio_read(pb, netscape_ext, sizeof(netscape_ext));
+        if (ret < sizeof(netscape_ext))
+            return ret;
+        gdc->total_iter = avio_rl16(pb);
+        if (gdc->total_iter == 0)
+            gdc->total_iter = -1;
     }
 
     if ((ret = gif_skip_subblocks(pb)) < 0)
@@ -268,10 +286,13 @@ resync:
         }
     }
 
-    if (ret >= 0 && !frame_parsed) {
+    if ((ret >= 0 && !frame_parsed) || ret == AVERROR_EOF) {
         /* This might happen when there is no image block
          * between extension blocks and GIF_TRAILER or EOF */
-        return  AVERROR_EOF;
+        if (!gdc->ignore_loop && (block_label == GIF_TRAILER || url_feof(pb))
+            && (gdc->total_iter < 0 || ++gdc->iter_count < gdc->total_iter))
+            return avio_seek(pb, 0, SEEK_SET);
+        return AVERROR_EOF;
     } else
         return ret;
 }
@@ -279,6 +300,7 @@ resync:
 static const AVOption options[] = {
     { "min_delay"    , "minimum valid delay between frames (in hundredths of second)", offsetof(GIFDemuxContext, min_delay)    , AV_OPT_TYPE_INT, {.i64 = GIF_MIN_DELAY}    , 0, 100 * 60, AV_OPT_FLAG_DECODING_PARAM },
     { "default_delay", "default delay between frames (in hundredths of second)"      , offsetof(GIFDemuxContext, default_delay), AV_OPT_TYPE_INT, {.i64 = GIF_DEFAULT_DELAY}, 0, 100 * 60, AV_OPT_FLAG_DECODING_PARAM },
+    { "ignore_loop"  , "ignore loop setting (netscape extension)"                    , offsetof(GIFDemuxContext, ignore_loop)  , AV_OPT_TYPE_INT, {.i64 = 1}                , 0,        1, AV_OPT_FLAG_DECODING_PARAM },
     { NULL },
 };