mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-01-08 13:22:53 +02:00
lavf/gifdec: add loop support.
Loop is ignored by default.
This commit is contained in:
parent
f5ede48fbb
commit
a16c20569d
@ -43,5 +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_APP_EXT_LABEL 0xff
|
||||
#define NETSCAPE_EXT_STR "NETSCAPE2.0"
|
||||
|
||||
#endif /* AVCODEC_GIFDEFS_H */
|
||||
|
@ -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,9 +286,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 +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 },
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user