summaryrefslogtreecommitdiff
path: root/ffmpeg/libavformat/gifdec.c
diff options
context:
space:
mode:
Diffstat (limited to 'ffmpeg/libavformat/gifdec.c')
-rw-r--r--ffmpeg/libavformat/gifdec.c34
1 files changed, 33 insertions, 1 deletions
diff --git a/ffmpeg/libavformat/gifdec.c b/ffmpeg/libavformat/gifdec.c
index 1122849..2981bca 100644
--- a/ffmpeg/libavformat/gifdec.c
+++ b/ffmpeg/libavformat/gifdec.c
@@ -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,27 @@ 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 data[256];
+
+ sb_size = avio_r8(pb);
+ ret = avio_read(pb, data, sb_size);
+ if (ret < 0 || !sb_size)
+ return ret;
+
+ if (sb_size == strlen(NETSCAPE_EXT_STR)) {
+ sb_size = avio_r8(pb);
+ ret = avio_read(pb, data, sb_size);
+ if (ret < 0 || !sb_size)
+ return ret;
+
+ if (sb_size == 3 && data[0] == 1) {
+ gdc->total_iter = AV_RL16(data+1);
+
+ if (gdc->total_iter == 0)
+ gdc->total_iter = -1;
+ }
+ }
}
if ((ret = gif_skip_subblocks(pb)) < 0)
@@ -268,9 +296,12 @@ 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 */
+ 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 +310,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 },
};