From 13aca070ab83afbd9026b298ead38f9ea88f6a92 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Mon, 21 Jan 2013 18:52:01 +0100 Subject: [PATCH] gifdec: resync support This allows decoding gifs that have junk at the begin and also allows byte wise seeking Signed-off-by: Michael Niedermayer --- libavformat/gifdec.c | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/libavformat/gifdec.c b/libavformat/gifdec.c index 4f4ce2ca95..d43a537682 100644 --- a/libavformat/gifdec.c +++ b/libavformat/gifdec.c @@ -70,6 +70,19 @@ static int gif_probe(AVProbeData *p) return AVPROBE_SCORE_MAX; } +static int resync(AVIOContext *pb) +{ + int i; + for (i = 0; i < 6; i++) { + int b = avio_r8(pb); + if (b != gif87a_sig[i] && b != gif89a_sig[i]) + i = -(b != 'G'); + if (url_feof(pb)) + return AVERROR_EOF; + } + return 0; +} + static int gif_read_header(AVFormatContext *s) { GIFDemuxContext *gdc = s->priv_data; @@ -77,8 +90,7 @@ static int gif_read_header(AVFormatContext *s) AVStream *st; int width, height, ret; - /* skip 6-byte magick */ - if ((ret = avio_skip(pb, 6)) < 0) + if ((ret = resync(pb)) < 0) return ret; gdc->delay = gdc->default_delay; @@ -171,6 +183,7 @@ static int gif_read_packet(AVFormatContext *s, AVPacket *pkt) } if (keyframe) { +parse_keyframe: /* skip 2 bytes of width and 2 of height */ if ((ret = avio_skip(pb, 4)) < 0) return ret; @@ -196,7 +209,7 @@ static int gif_read_packet(AVFormatContext *s, AVPacket *pkt) while (GIF_TRAILER != (block_label = avio_r8(pb)) && !url_feof(pb)) { if (block_label == GIF_EXTENSION_INTRODUCER) { if ((ret = gif_read_ext (s)) < 0 ) - return ret; + goto resync; } else if (block_label == GIF_IMAGE_SEPARATOR) { /* skip to last byte of Image Descriptor header */ if ((ret = avio_skip(pb, 8)) < 0) @@ -215,11 +228,11 @@ static int gif_read_packet(AVFormatContext *s, AVPacket *pkt) /* read LZW Minimum Code Size */ if (avio_r8(pb) < 1) { av_log(s, AV_LOG_ERROR, "lzw minimum code size must be >= 1\n"); - return AVERROR_INVALIDDATA; + goto resync; } if ((ret = gif_skip_subblocks(pb)) < 0) - return ret; + goto resync; frame_end = avio_tell(pb); @@ -244,7 +257,14 @@ static int gif_read_packet(AVFormatContext *s, AVPacket *pkt) break; } else { av_log(s, AV_LOG_ERROR, "invalid block label\n"); - return AVERROR_INVALIDDATA; +resync: + if (!keyframe) + avio_seek(pb, frame_start, SEEK_SET); + if ((ret = resync(pb)) < 0) + return ret; + frame_start = avio_tell(pb) - 6; + keyframe = 1; + goto parse_keyframe; } }