コード例 #1
0
ファイル: gifdec.c プロジェクト: aronlu/FFmpeg
static int gif_read_ext(AVFormatContext *s)
{
    GIFDemuxContext *gdc = s->priv_data;
    AVIOContext *pb = s->pb;
    int sb_size, ext_label = avio_r8(pb);
    int ret;

    if (ext_label == GIF_GCE_EXT_LABEL) {
        if ((sb_size = avio_r8(pb)) < 4) {
            av_log(s, AV_LOG_FATAL, "Graphic Control Extension block's size less than 4.\n");
            return AVERROR_INVALIDDATA;
        }

        /* skip packed fields */
        if ((ret = avio_skip(pb, 1)) < 0)
            return ret;

        gdc->delay = avio_rl16(pb);

        if (gdc->delay < gdc->min_delay)
            gdc->delay = gdc->default_delay;

        /* skip the rest of the Graphic Control Extension block */
        if ((ret = avio_skip(pb, sb_size - 3)) < 0 )
            return ret;
    }

    if ((ret = gif_skip_subblocks(pb)) < 0)
        return ret;

    return 0;
}
コード例 #2
0
ファイル: gifdec.c プロジェクト: markjreed/vice-emu
static int gif_read_ext(AVFormatContext *s)
{
    GIFDemuxContext *gdc = s->priv_data;
    AVIOContext *pb = s->pb;
    int sb_size, ext_label = avio_r8(pb);
    int ret;

    if (ext_label == GIF_GCE_EXT_LABEL) {
        if ((sb_size = avio_r8(pb)) < 4) {
            av_log(s, AV_LOG_FATAL, "Graphic Control Extension block's size less than 4.\n");
            return AVERROR_INVALIDDATA;
        }

        /* skip packed fields */
        if ((ret = avio_skip(pb, 1)) < 0)
            return ret;

        gdc->delay = avio_rl16(pb);

        if (gdc->delay < gdc->min_delay)
            gdc->delay = gdc->default_delay;

        /* 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 data[256];

        sb_size = avio_r8(pb);
        ret = avio_read(pb, data, sb_size);
        if (ret < 0 || !sb_size)
            return ret;

        if (sb_size == strlen(NETSCAPE_EXT_STR)) {
            sb_size = avio_r8(pb);
            ret = avio_read(pb, data, sb_size);
            if (ret < 0 || !sb_size)
                return ret;

            if (sb_size == 3 && data[0] == 1) {
                gdc->total_iter = AV_RL16(data+1);

                if (gdc->total_iter == 0)
                    gdc->total_iter = -1;
            }
        }
    }

    if ((ret = gif_skip_subblocks(pb)) < 0)
        return ret;

    return 0;
}
コード例 #3
0
ファイル: gifdec.c プロジェクト: markjreed/vice-emu
static int gif_read_packet(AVFormatContext *s, AVPacket *pkt)
{
    GIFDemuxContext *gdc = s->priv_data;
    AVIOContext *pb = s->pb;
    int packed_fields, block_label, ct_size,
        keyframe, frame_parsed = 0, ret;
    int64_t frame_start = avio_tell(pb), frame_end;
    unsigned char buf[6];

    if ((ret = avio_read(pb, buf, 6)) == 6) {
        keyframe = memcmp(buf, gif87a_sig, 6) == 0 ||
                   memcmp(buf, gif89a_sig, 6) == 0;
    } else if (ret < 0) {
        return ret;
    } else {
        keyframe = 0;
    }

    if (keyframe) {
parse_keyframe:
        /* skip 2 bytes of width and 2 of height */
        if ((ret = avio_skip(pb, 4)) < 0)
            return ret;

        packed_fields = avio_r8(pb);

        /* skip 1 byte of Background Color Index and 1 byte of Pixel Aspect Ratio */
        if ((ret = avio_skip(pb, 2)) < 0)
            return ret;

        /* global color table presence */
        if (packed_fields & 0x80) {
            ct_size = 3 * (1 << ((packed_fields & 0x07) + 1));

            if ((ret = avio_skip(pb, ct_size)) < 0)
                return ret;
        }
    } else {
        avio_seek(pb, -ret, SEEK_CUR);
        ret = AVERROR_EOF;
    }

    while (GIF_TRAILER != (block_label = avio_r8(pb)) && !avio_feof(pb)) {
        if (block_label == GIF_EXTENSION_INTRODUCER) {
            if ((ret = gif_read_ext (s)) < 0 )
                goto resync;
        } else if (block_label == GIF_IMAGE_SEPARATOR) {
            /* skip to last byte of Image Descriptor header */
            if ((ret = avio_skip(pb, 8)) < 0)
                return ret;

            packed_fields = avio_r8(pb);

            /* local color table presence */
            if (packed_fields & 0x80) {
                ct_size = 3 * (1 << ((packed_fields & 0x07) + 1));

                if ((ret = avio_skip(pb, ct_size)) < 0)
                    return ret;
            }

            /* read LZW Minimum Code Size */
            if (avio_r8(pb) < 1) {
                av_log(s, AV_LOG_ERROR, "lzw minimum code size must be >= 1\n");
                goto resync;
            }

            if ((ret = gif_skip_subblocks(pb)) < 0)
                goto resync;

            frame_end = avio_tell(pb);

            if (avio_seek(pb, frame_start, SEEK_SET) != frame_start)
                return AVERROR(EIO);

            ret = av_get_packet(pb, pkt, frame_end - frame_start);
            if (ret < 0)
                return ret;

            if (keyframe)
                pkt->flags |= AV_PKT_FLAG_KEY;

            pkt->stream_index = 0;
            pkt->duration = gdc->delay;

            /* Graphic Control Extension's scope is single frame.
             * Remove its influence. */
            gdc->delay = gdc->default_delay;
            frame_parsed = 1;

            break;
        } else {
            av_log(s, AV_LOG_ERROR, "invalid block label\n");
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;
        }
    }

    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 || avio_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;
}