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>
This commit is contained in:
		@@ -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;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user