[FFmpeg-devel] [PATCH] lavf/gifdec: add loop support.

Paul B Mahol onemda at gmail.com
Fri Apr 19 01:50:01 CEST 2013


On 4/18/13, Clement Boesch <ubitux at gmail.com> wrote:
> ---
> Still missing FATE update (need to add -ignore_loop to them), but I'm
> waiting for review on the patch to rework the tests.

I would prefer that default is to not loop at all.

> ---
>  libavcodec/gif.h     |  2 ++
>  libavformat/gifdec.c | 24 +++++++++++++++++++++++-
>  2 files changed, 25 insertions(+), 1 deletion(-)
>
> diff --git a/libavcodec/gif.h b/libavcodec/gif.h
> index b557534..b4cf665 100644
> --- a/libavcodec/gif.h
> +++ b/libavcodec/gif.h
> @@ -43,5 +43,7 @@ static const uint8_t gif89a_sig[6] = "GIF89a";
>  #define GIF_EXTENSION_INTRODUCER    0x21
>  #define GIF_IMAGE_SEPARATOR         0x2c
>  #define GIF_GCE_EXT_LABEL           0xf9
> +#define GIF_APP_EXT_LABEL           0xff

Nice!

> +#define NETSCAPE_EXT_STR            "NETSCAPE2.0"
>
>  #endif /* AVCODEC_GIFDEFS_H */
> diff --git a/libavformat/gifdec.c b/libavformat/gifdec.c
> index 1122849..0028734 100644
> --- a/libavformat/gifdec.c
> +++ b/libavformat/gifdec.c
> @@ -44,6 +44,13 @@ typedef struct GIFDemuxContext {
>       */
>      int min_delay;
>      int default_delay;
> +
> +    /**
> +     * loop options
> +     */
> +    int total_iter;
> +    int iter_count;
> +    int ignore_loop;
>  } GIFDemuxContext;
>
>  /**
> @@ -156,6 +163,17 @@ static int gif_read_ext(AVFormatContext *s)
>          /* 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 netscape_ext[sizeof(NETSCAPE_EXT_STR)-1 + 2];
> +
> +        if ((sb_size = avio_r8(pb)) != strlen(NETSCAPE_EXT_STR))
> +            return 0;
> +        ret = avio_read(pb, netscape_ext, sizeof(netscape_ext));
> +        if (ret < sizeof(netscape_ext))
> +            return ret;
> +        gdc->total_iter = avio_rl16(pb);
> +        if (gdc->total_iter == 0)
> +            gdc->total_iter = -1;
>      }
>
>      if ((ret = gif_skip_subblocks(pb)) < 0)
> @@ -268,9 +286,12 @@ resync:
>          }
>      }
>
> -    if (ret >= 0 && !frame_parsed) {
> +    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 ||
> url_feof(pb))
> +            && (gdc->total_iter < 0 || ++gdc->iter_count <
> gdc->total_iter))
> +            return avio_seek(pb, 0, SEEK_SET);

Is it ok too loop on partial file?

>          return AVERROR_EOF;
>      } else
>          return ret;
> @@ -279,6 +300,7 @@ resync:
>  static const AVOption options[] = {
>      { "min_delay"    , "minimum valid delay between frames (in hundredths
> of second)", offsetof(GIFDemuxContext, min_delay)    , AV_OPT_TYPE_INT,
> {.i64 = GIF_MIN_DELAY}    , 0, 100 * 60, AV_OPT_FLAG_DECODING_PARAM },
>      { "default_delay", "default delay between frames (in hundredths of
> second)"      , offsetof(GIFDemuxContext, default_delay), AV_OPT_TYPE_INT,
> {.i64 = GIF_DEFAULT_DELAY}, 0, 100 * 60, AV_OPT_FLAG_DECODING_PARAM },
> +    { "ignore_loop"  , "ignore loop setting (netscape extension)"
>          , offsetof(GIFDemuxContext, ignore_loop)  , AV_OPT_TYPE_INT, {.i64
> = 0}                , 0,        1, AV_OPT_FLAG_DECODING_PARAM },
>      { NULL },
>  };
>
> --
> 1.8.2.1

rest looks fine


More information about the ffmpeg-devel mailing list