On 19/03/16 22:48, Vittorio Giovara wrote:
> From: Vitaliy E Sugrobov <[email protected]>
>
> This demuxer is capable of extracting multiple frames from gif file.
> In conjunction with gif decoder it implements support for reading
> animated gifs.
>
> Signed-off-by: Vitaliy E Sugrobov <[email protected]>
> Signed-off-by: Vittorio Giovara <[email protected]>
> ---
> Changelog | 1 +
> doc/general.texi | 2 +-
> libavformat/Makefile | 1 +
> libavformat/allformats.c | 2 +-
> libavformat/gifdec.c | 318
> +++++++++++++++++++++++++++++++++++++++++++++++
> 5 files changed, 322 insertions(+), 2 deletions(-)
> create mode 100644 libavformat/gifdec.c
>
> diff --git a/Changelog b/Changelog
> index ca9c9b4..71fe9e2 100644
> --- a/Changelog
> +++ b/Changelog
> @@ -52,6 +52,7 @@ version <next>:
> - G.723.1 muxer and encoder
> - compressed SWF
> - G.729 raw demuxer
> +- GIF demuxer
>
>
> version 11:
> diff --git a/doc/general.texi b/doc/general.texi
> index 15e4a66..5f01c50 100644
> --- a/doc/general.texi
> +++ b/doc/general.texi
> @@ -282,7 +282,7 @@ library:
> @item framecrc testing format @tab X @tab
> @item FunCom ISS @tab @tab X
> @tab Audio format used in various games from FunCom like The Longest
> Journey.
> -@item GIF Animation @tab X @tab
> +@item GIF Animation @tab X @tab X
> @item GXF @tab X @tab X
> @tab General eXchange Format SMPTE 360M, used by Thomson Grass Valley
> playout servers.
> diff --git a/libavformat/Makefile b/libavformat/Makefile
> index 891a20f..5cd8f8f 100644
> --- a/libavformat/Makefile
> +++ b/libavformat/Makefile
> @@ -135,6 +135,7 @@ OBJS-$(CONFIG_FOURXM_DEMUXER) += 4xm.o
> OBJS-$(CONFIG_FRAMECRC_MUXER) += framecrcenc.o framehash.o
> OBJS-$(CONFIG_FRAMEMD5_MUXER) += md5enc.o framehash.o
> OBJS-$(CONFIG_GIF_MUXER) += gif.o
> +OBJS-$(CONFIG_GIF_DEMUXER) += gifdec.o
> OBJS-$(CONFIG_GSM_DEMUXER) += gsmdec.o
> OBJS-$(CONFIG_GXF_DEMUXER) += gxf.o
> OBJS-$(CONFIG_GXF_MUXER) += gxfenc.o audiointerleave.o
> diff --git a/libavformat/allformats.c b/libavformat/allformats.c
> index 0f49756..1056d7b 100644
> --- a/libavformat/allformats.c
> +++ b/libavformat/allformats.c
> @@ -106,7 +106,7 @@ void av_register_all(void)
> REGISTER_MUXDEMUX(G722, g722);
> REGISTER_MUXDEMUX(G723_1, g723_1);
> REGISTER_DEMUXER (G729, g729);
> - REGISTER_MUXER (GIF, gif);
> + REGISTER_MUXDEMUX(GIF, gif);
> REGISTER_DEMUXER (GSM, gsm);
> REGISTER_MUXDEMUX(GXF, gxf);
> REGISTER_MUXDEMUX(H261, h261);
> diff --git a/libavformat/gifdec.c b/libavformat/gifdec.c
> new file mode 100644
> index 0000000..cc46716
> --- /dev/null
> +++ b/libavformat/gifdec.c
> @@ -0,0 +1,318 @@
> +/*
> + * GIF demuxer
> + * Copyright (c) 2012 Vitaliy E Sugrobov
> + *
> + * This file is part of Libav.
> + *
> + * Libav is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2.1 of the License, or (at your option) any later version.
> + *
> + * Libav is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with Libav; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
> USA
> + */
> +
> +/**
> + * @file
> + * GIF demuxer.
> + *
> + * There are two options available to user: default_delay and min_delay.
> + *
> + * These options are for protection from too rapid gif animations.
> + * In practice it is standard approach to slow down rendering of this
> + * kind of gifs. If you try to play gif with delay between frames of one
> + * hundredth of second (100fps) using one of major web browsers, you get
> + * significantly slower playback, around 10 fps. This is because browser
> + * detects that delay value is less than some threshold (usually 2 hundredths
> + * of second) and reset it to default value (usually 10 hundredths of second,
> + * which corresponds to 10fps). Manipulating these options, user can achieve
> + * the same effect during conversion to some video format. Otherwise user
> + * can set them to not protect from rapid animations at all.
> + *
> + * The other case when these options necessary is for gif images encoded
> + * according to gif87a standard since prior to gif89a there was no delay
> + * information included in file.
> + */
> +
> +#include "libavutil/intreadwrite.h"
> +#include "libavutil/opt.h"
> +
> +#include "avformat.h"
> +#include "internal.h"
> +
> +#define GIF_SIG_87A "GIF87a"
> +#define GIF_SIG_89A "GIF89a"
> +
> +#define GIF_TRAILER 0x3b
> +#define GIF_EXTENSION_INTRODUCER 0x21
> +#define GIF_IMAGE_SEPARATOR 0x2c
> +#define GIF_GCE_EXT_LABEL 0xf9
> +
> +typedef struct GIFDemuxContext {
> + const AVClass *class;
> + uint32_t width;
> + uint32_t height;
> +
> + /**
> + * Time span in hundredths of second before
> + * the next frame should be drawn on screen.
> + */
> + int delay;
> +
> + /**
> + * Minimum allowed delay between frames in hundredths of
> + * second. Values below this threshold considered to be
> + * invalid and set to value of default_delay.
> + */
> + int min_delay;
> + int default_delay;
> + int total_duration; ///< In hundredths of second.
> +} GIFDemuxContext;
> +
> +/**
> + * Major web browsers display gifs at ~10-15fps when rate is not explicitly
> + * set or have too low values. We assume default rate to be 10.
> + * Default delay = 100hundredths of second / 10fps = 10hos per frame.
> + */
> +#define GIF_DEFAULT_DELAY 10
> +
> +/**
> + * By default delay values less than this threshold considered to be invalid.
> + */
> +#define GIF_MIN_DELAY 2
> +
> +static int gif_probe(AVProbeData *p)
> +{
Check that the buf is at least 8 bytes here.
> + /* check magick */
> + if (memcmp(p->buf, GIF_SIG_87A, 6) && memcmp(p->buf, GIF_SIG_89A, 6))
> + return 0;
> +
> + /* width or height contains zero? */
> + if (!AV_RL16(&p->buf[6]) || !AV_RL16(&p->buf[8]))
> + return 0;
> +
> + return AVPROBE_SCORE_MAX;
> +}
> +
> +static int gif_read_header(AVFormatContext *s)
> +{
> + GIFDemuxContext *gdc = s->priv_data;
> + AVIOContext *pb = s->pb;
> + AVStream *st;
> + int ret;
> +
> + /* skip 6-byte magick */
> + if ((ret = avio_skip(pb, 6)) < 0)
> + return ret;
> +
> + gdc->delay = gdc->default_delay;
> + gdc->width = avio_rl16(pb);
> + gdc->height = avio_rl16(pb);
> +
> + if (gdc->width == 0 || gdc->height == 0)
> + return AVERROR_INVALIDDATA;
> +
> + st = avformat_new_stream(s, NULL);
> + if (!st)
> + return AVERROR(ENOMEM);
> +
> + /* GIF format operates with time in "hundredths of second",
> + * therefore timebase is 1/100 */
> + avpriv_set_pts_info(st, 64, 1, 100);
> + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
> + st->codecpar->codec_id = AV_CODEC_ID_GIF;
> + st->codecpar->width = gdc->width;
> + st->codecpar->height = gdc->height;
check dimensions maybe?
> +
> + /* jump to start because gif decoder needs header data too */
> + return avio_seek(pb, 0, SEEK_SET);
> +}
> +
> +static int gif_skip_subblocks(AVIOContext *pb)
> +{
> + int sb_size, ret = 0;
> +
> + while ((sb_size = avio_r8(pb)) > 0) {
> + if ((ret = avio_skip(pb, sb_size)) < 0)
> + return ret;
> + }
> +
> + return ret;
> +}
> +
> +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)
> + return gif_skip_subblocks(pb);
> +
> + if ((sb_size = avio_r8(pb)) < 4) {
> + av_log(s, AV_LOG_FATAL,
AV_LOG_ERROR
> + "Graphic Control Extension block's size less than 4.\n");
> + return AVERROR_INVALIDDATA;
> + }
> +
The rest seems good.
lu
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel