summaryrefslogtreecommitdiff
path: root/libavformat/gifdec.c
diff options
context:
space:
mode:
authorMichael Niedermayer <michaelni@gmx.at>2013-01-21 18:52:01 +0100
committerMichael Niedermayer <michaelni@gmx.at>2013-01-25 17:25:16 +0100
commit13aca070ab83afbd9026b298ead38f9ea88f6a92 (patch)
tree403e18b24e84a4dc11c1abf0c4cca198309fdd9c /libavformat/gifdec.c
parent40b4468f6231d46cac2c7d1cac7613a77faf8e8e (diff)
gifdec: resync support
This allows decoding gifs that have junk at the begin and also allows byte wise seeking Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'libavformat/gifdec.c')
-rw-r--r--libavformat/gifdec.c32
1 files 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;
}
}