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;
 | 
					    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)
 | 
					static int gif_read_header(AVFormatContext *s)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    GIFDemuxContext *gdc = s->priv_data;
 | 
					    GIFDemuxContext *gdc = s->priv_data;
 | 
				
			||||||
@@ -77,8 +90,7 @@ static int gif_read_header(AVFormatContext *s)
 | 
				
			|||||||
    AVStream        *st;
 | 
					    AVStream        *st;
 | 
				
			||||||
    int width, height, ret;
 | 
					    int width, height, ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* skip 6-byte magick */
 | 
					    if ((ret = resync(pb)) < 0)
 | 
				
			||||||
    if ((ret = avio_skip(pb, 6)) < 0)
 | 
					 | 
				
			||||||
        return ret;
 | 
					        return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    gdc->delay  = gdc->default_delay;
 | 
					    gdc->delay  = gdc->default_delay;
 | 
				
			||||||
@@ -171,6 +183,7 @@ static int gif_read_packet(AVFormatContext *s, AVPacket *pkt)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (keyframe) {
 | 
					    if (keyframe) {
 | 
				
			||||||
 | 
					parse_keyframe:
 | 
				
			||||||
        /* skip 2 bytes of width and 2 of height */
 | 
					        /* skip 2 bytes of width and 2 of height */
 | 
				
			||||||
        if ((ret = avio_skip(pb, 4)) < 0)
 | 
					        if ((ret = avio_skip(pb, 4)) < 0)
 | 
				
			||||||
            return ret;
 | 
					            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)) {
 | 
					    while (GIF_TRAILER != (block_label = avio_r8(pb)) && !url_feof(pb)) {
 | 
				
			||||||
        if (block_label == GIF_EXTENSION_INTRODUCER) {
 | 
					        if (block_label == GIF_EXTENSION_INTRODUCER) {
 | 
				
			||||||
            if ((ret = gif_read_ext (s)) < 0 )
 | 
					            if ((ret = gif_read_ext (s)) < 0 )
 | 
				
			||||||
                return ret;
 | 
					                goto resync;
 | 
				
			||||||
        } else if (block_label == GIF_IMAGE_SEPARATOR) {
 | 
					        } else if (block_label == GIF_IMAGE_SEPARATOR) {
 | 
				
			||||||
            /* skip to last byte of Image Descriptor header */
 | 
					            /* skip to last byte of Image Descriptor header */
 | 
				
			||||||
            if ((ret = avio_skip(pb, 8)) < 0)
 | 
					            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 */
 | 
					            /* read LZW Minimum Code Size */
 | 
				
			||||||
            if (avio_r8(pb) < 1) {
 | 
					            if (avio_r8(pb) < 1) {
 | 
				
			||||||
                av_log(s, AV_LOG_ERROR, "lzw minimum code size must be >= 1\n");
 | 
					                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)
 | 
					            if ((ret = gif_skip_subblocks(pb)) < 0)
 | 
				
			||||||
                return ret;
 | 
					                goto resync;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            frame_end = avio_tell(pb);
 | 
					            frame_end = avio_tell(pb);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -244,7 +257,14 @@ static int gif_read_packet(AVFormatContext *s, AVPacket *pkt)
 | 
				
			|||||||
            break;
 | 
					            break;
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            av_log(s, AV_LOG_ERROR, "invalid block label\n");
 | 
					            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