LCOV - code coverage report
Current view: top level - libavformat - gifdec.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 109 147 74.1 %
Date: 2017-12-12 11:08:38 Functions: 6 6 100.0 %

          Line data    Source code
       1             : /*
       2             :  * GIF demuxer
       3             :  * Copyright (c) 2012 Vitaliy E Sugrobov
       4             :  *
       5             :  * This file is part of FFmpeg.
       6             :  *
       7             :  * FFmpeg is free software; you can redistribute it and/or
       8             :  * modify it under the terms of the GNU Lesser General Public
       9             :  * License as published by the Free Software Foundation; either
      10             :  * version 2.1 of the License, or (at your option) any later version.
      11             :  *
      12             :  * FFmpeg is distributed in the hope that it will be useful,
      13             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15             :  * Lesser General Public License for more details.
      16             :  *
      17             :  * You should have received a copy of the GNU Lesser General Public
      18             :  * License along with FFmpeg; if not, write to the Free Software
      19             :  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
      20             :  */
      21             : 
      22             : /**
      23             :  * @file
      24             :  * GIF demuxer.
      25             :  */
      26             : 
      27             : #include "avformat.h"
      28             : #include "libavutil/intreadwrite.h"
      29             : #include "libavutil/opt.h"
      30             : #include "internal.h"
      31             : #include "libavcodec/gif.h"
      32             : 
      33             : typedef struct GIFDemuxContext {
      34             :     const AVClass *class;
      35             :     /**
      36             :      * Time span in hundredths of second before
      37             :      * the next frame should be drawn on screen.
      38             :      */
      39             :     int delay;
      40             :     /**
      41             :      * Minimum allowed delay between frames in hundredths of
      42             :      * second. Values below this threshold considered to be
      43             :      * invalid and set to value of default_delay.
      44             :      */
      45             :     int min_delay;
      46             :     int max_delay;
      47             :     int default_delay;
      48             : 
      49             :     /**
      50             :      * loop options
      51             :      */
      52             :     int total_iter;
      53             :     int iter_count;
      54             :     int ignore_loop;
      55             : 
      56             :     int nb_frames;
      57             :     int last_duration;
      58             : } GIFDemuxContext;
      59             : 
      60             : /**
      61             :  * Major web browsers display gifs at ~10-15fps when rate
      62             :  * is not explicitly set or have too low values. We assume default rate to be 10.
      63             :  * Default delay = 100hundredths of second / 10fps = 10hos per frame.
      64             :  */
      65             : #define GIF_DEFAULT_DELAY   10
      66             : /**
      67             :  * By default delay values less than this threshold considered to be invalid.
      68             :  */
      69             : #define GIF_MIN_DELAY       2
      70             : 
      71        6130 : static int gif_probe(AVProbeData *p)
      72             : {
      73             :     /* check magick */
      74        6130 :     if (memcmp(p->buf, gif87a_sig, 6) && memcmp(p->buf, gif89a_sig, 6))
      75        6115 :         return 0;
      76             : 
      77             :     /* width or height contains zero? */
      78          15 :     if (!AV_RL16(&p->buf[6]) || !AV_RL16(&p->buf[8]))
      79           0 :         return 0;
      80             : 
      81          15 :     return AVPROBE_SCORE_MAX;
      82             : }
      83             : 
      84          15 : static int resync(AVIOContext *pb)
      85             : {
      86             :     int i;
      87         105 :     for (i = 0; i < 6; i++) {
      88          90 :         int b = avio_r8(pb);
      89          90 :         if (b != gif87a_sig[i] && b != gif89a_sig[i])
      90           0 :             i = -(b != 'G');
      91          90 :         if (avio_feof(pb))
      92           0 :             return AVERROR_EOF;
      93             :     }
      94          15 :     return 0;
      95             : }
      96             : 
      97          15 : static int gif_read_header(AVFormatContext *s)
      98             : {
      99          15 :     GIFDemuxContext *gdc = s->priv_data;
     100          15 :     AVIOContext     *pb  = s->pb;
     101             :     AVStream        *st;
     102             :     int width, height, ret;
     103             : 
     104          15 :     if ((ret = resync(pb)) < 0)
     105           0 :         return ret;
     106             : 
     107          15 :     gdc->delay  = gdc->default_delay;
     108          15 :     width  = avio_rl16(pb);
     109          15 :     height = avio_rl16(pb);
     110             : 
     111          15 :     if (width == 0 || height == 0)
     112           0 :         return AVERROR_INVALIDDATA;
     113             : 
     114          15 :     st = avformat_new_stream(s, NULL);
     115          15 :     if (!st)
     116           0 :         return AVERROR(ENOMEM);
     117             : 
     118             :     /* GIF format operates with time in "hundredths of second",
     119             :      * therefore timebase is 1/100 */
     120          15 :     avpriv_set_pts_info(st, 64, 1, 100);
     121          15 :     st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
     122          15 :     st->codecpar->codec_id   = AV_CODEC_ID_GIF;
     123          15 :     st->codecpar->width      = width;
     124          15 :     st->codecpar->height     = height;
     125             : 
     126             :     /* jump to start because gif decoder needs header data too */
     127          15 :     if (avio_seek(pb, 0, SEEK_SET) != 0)
     128           0 :         return AVERROR(EIO);
     129             : 
     130          15 :     return 0;
     131             : }
     132             : 
     133        3690 : static int gif_skip_subblocks(AVIOContext *pb)
     134             : {
     135        3690 :     int sb_size, ret = 0;
     136             : 
     137      176043 :     while (0x00 != (sb_size = avio_r8(pb))) {
     138      168663 :         if ((ret = avio_skip(pb, sb_size)) < 0)
     139           0 :             return ret;
     140             :     }
     141             : 
     142        3690 :     return ret;
     143             : }
     144             : 
     145        1868 : static int gif_read_ext(AVFormatContext *s)
     146             : {
     147        1868 :     GIFDemuxContext *gdc = s->priv_data;
     148        1868 :     AVIOContext *pb = s->pb;
     149        1868 :     int sb_size, ext_label = avio_r8(pb);
     150             :     int ret;
     151             : 
     152        1868 :     if (ext_label == GIF_GCE_EXT_LABEL) {
     153        1822 :         if ((sb_size = avio_r8(pb)) < 4) {
     154           0 :             av_log(s, AV_LOG_FATAL, "Graphic Control Extension block's size less than 4.\n");
     155           0 :             return AVERROR_INVALIDDATA;
     156             :         }
     157             : 
     158             :         /* skip packed fields */
     159        1822 :         if ((ret = avio_skip(pb, 1)) < 0)
     160           0 :             return ret;
     161             : 
     162        1822 :         gdc->delay = avio_rl16(pb);
     163             : 
     164        1822 :         if (gdc->delay < gdc->min_delay)
     165        1212 :             gdc->delay = gdc->default_delay;
     166        1822 :         gdc->delay = FFMIN(gdc->delay, gdc->max_delay);
     167             : 
     168             :         /* skip the rest of the Graphic Control Extension block */
     169        1822 :         if ((ret = avio_skip(pb, sb_size - 3)) < 0 )
     170           0 :             return ret;
     171          46 :     } else if (ext_label == GIF_APP_EXT_LABEL) {
     172             :         uint8_t data[256];
     173             : 
     174          44 :         sb_size = avio_r8(pb);
     175          44 :         ret = avio_read(pb, data, sb_size);
     176          44 :         if (ret < 0 || !sb_size)
     177           0 :             return ret;
     178             : 
     179          44 :         if (sb_size == strlen(NETSCAPE_EXT_STR)) {
     180          44 :             sb_size = avio_r8(pb);
     181          44 :             ret = avio_read(pb, data, sb_size);
     182          44 :             if (ret < 0 || !sb_size)
     183           0 :                 return ret;
     184             : 
     185          44 :             if (sb_size == 3 && data[0] == 1) {
     186          43 :                 gdc->total_iter = AV_RL16(data+1);
     187             : 
     188          43 :                 if (gdc->total_iter == 0)
     189          43 :                     gdc->total_iter = -1;
     190             :             }
     191             :         }
     192             :     }
     193             : 
     194        1868 :     if ((ret = gif_skip_subblocks(pb)) < 0)
     195           0 :         return ret;
     196             : 
     197        1868 :     return 0;
     198             : }
     199             : 
     200        1862 : static int gif_read_packet(AVFormatContext *s, AVPacket *pkt)
     201             : {
     202        1862 :     GIFDemuxContext *gdc = s->priv_data;
     203        1862 :     AVIOContext *pb = s->pb;
     204             :     int packed_fields, block_label, ct_size,
     205        1862 :         keyframe, frame_parsed = 0, ret;
     206        1862 :     int64_t frame_start = avio_tell(pb), frame_end;
     207             :     unsigned char buf[6];
     208             : 
     209        1862 :     if ((ret = avio_read(pb, buf, 6)) == 6) {
     210        3644 :         keyframe = memcmp(buf, gif87a_sig, 6) == 0 ||
     211        1822 :                    memcmp(buf, gif89a_sig, 6) == 0;
     212          40 :     } else if (ret < 0) {
     213           7 :         return ret;
     214             :     } else {
     215          33 :         keyframe = 0;
     216             :     }
     217             : 
     218        1855 :     if (keyframe) {
     219          50 : parse_keyframe:
     220             :         /* skip 2 bytes of width and 2 of height */
     221          50 :         if ((ret = avio_skip(pb, 4)) < 0)
     222           0 :             return ret;
     223             : 
     224          50 :         packed_fields = avio_r8(pb);
     225             : 
     226             :         /* skip 1 byte of Background Color Index and 1 byte of Pixel Aspect Ratio */
     227          50 :         if ((ret = avio_skip(pb, 2)) < 0)
     228           0 :             return ret;
     229             : 
     230             :         /* global color table presence */
     231          50 :         if (packed_fields & 0x80) {
     232          43 :             ct_size = 3 * (1 << ((packed_fields & 0x07) + 1));
     233             : 
     234          43 :             if ((ret = avio_skip(pb, ct_size)) < 0)
     235           0 :                 return ret;
     236             :         }
     237             :     } else {
     238        1805 :         avio_seek(pb, -ret, SEEK_CUR);
     239        1805 :         ret = AVERROR_EOF;
     240             :     }
     241             : 
     242        5578 :     while (GIF_TRAILER != (block_label = avio_r8(pb)) && !avio_feof(pb)) {
     243        3690 :         if (block_label == GIF_EXTENSION_INTRODUCER) {
     244        1868 :             if ((ret = gif_read_ext (s)) < 0 )
     245           0 :                 goto resync;
     246        1822 :         } else if (block_label == GIF_IMAGE_SEPARATOR) {
     247             :             /* skip to last byte of Image Descriptor header */
     248        1822 :             if ((ret = avio_skip(pb, 8)) < 0)
     249           0 :                 return ret;
     250             : 
     251        1822 :             packed_fields = avio_r8(pb);
     252             : 
     253             :             /* local color table presence */
     254        1822 :             if (packed_fields & 0x80) {
     255        1213 :                 ct_size = 3 * (1 << ((packed_fields & 0x07) + 1));
     256             : 
     257        1213 :                 if ((ret = avio_skip(pb, ct_size)) < 0)
     258           0 :                     return ret;
     259             :             }
     260             : 
     261             :             /* read LZW Minimum Code Size */
     262        1822 :             if (avio_r8(pb) < 1) {
     263           0 :                 av_log(s, AV_LOG_ERROR, "lzw minimum code size must be >= 1\n");
     264           0 :                 goto resync;
     265             :             }
     266             : 
     267        1822 :             if ((ret = gif_skip_subblocks(pb)) < 0)
     268           0 :                 goto resync;
     269             : 
     270        1822 :             frame_end = avio_tell(pb);
     271             : 
     272        1822 :             if (avio_seek(pb, frame_start, SEEK_SET) != frame_start)
     273           0 :                 return AVERROR(EIO);
     274             : 
     275        1822 :             ret = av_get_packet(pb, pkt, frame_end - frame_start);
     276        1822 :             if (ret < 0)
     277           0 :                 return ret;
     278             : 
     279        1822 :             if (keyframe)
     280          50 :                 pkt->flags |= AV_PKT_FLAG_KEY;
     281             : 
     282        1822 :             pkt->stream_index = 0;
     283        1822 :             pkt->duration = gdc->delay;
     284             : 
     285        1822 :             gdc->nb_frames ++;
     286        1822 :             gdc->last_duration = pkt->duration;
     287             : 
     288             :             /* Graphic Control Extension's scope is single frame.
     289             :              * Remove its influence. */
     290        1822 :             gdc->delay = gdc->default_delay;
     291        1822 :             frame_parsed = 1;
     292             : 
     293        1822 :             break;
     294             :         } else {
     295           0 :             av_log(s, AV_LOG_ERROR, "invalid block label\n");
     296           0 : resync:
     297           0 :             if (!keyframe)
     298           0 :                 avio_seek(pb, frame_start, SEEK_SET);
     299           0 :             if ((ret = resync(pb)) < 0)
     300           0 :                 return ret;
     301           0 :             frame_start = avio_tell(pb) - 6;
     302           0 :             keyframe = 1;
     303           0 :             goto parse_keyframe;
     304             :         }
     305             :     }
     306             : 
     307        1855 :     if ((ret >= 0 && !frame_parsed) || ret == AVERROR_EOF) {
     308          33 :         if (gdc->nb_frames == 1) {
     309           0 :             s->streams[0]->r_frame_rate = (AVRational) {100, gdc->last_duration};
     310             :         }
     311             :         /* This might happen when there is no image block
     312             :          * between extension blocks and GIF_TRAILER or EOF */
     313          33 :         if (!gdc->ignore_loop && (block_label == GIF_TRAILER || avio_feof(pb))
     314           0 :             && (gdc->total_iter < 0 || ++gdc->iter_count < gdc->total_iter))
     315           0 :             return avio_seek(pb, 0, SEEK_SET);
     316          33 :         return AVERROR_EOF;
     317             :     } else
     318        1822 :         return ret;
     319             : }
     320             : 
     321             : static const AVOption options[] = {
     322             :     { "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 },
     323             :     { "max_gif_delay", "maximum valid delay between frames (in hundredths of seconds)", offsetof(GIFDemuxContext, max_delay)   , AV_OPT_TYPE_INT, {.i64 = 65535}            , 0, 65535   , AV_OPT_FLAG_DECODING_PARAM },
     324             :     { "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 },
     325             :     { "ignore_loop"  , "ignore loop setting (netscape extension)"                    , offsetof(GIFDemuxContext, ignore_loop)  , AV_OPT_TYPE_BOOL,{.i64 = 1}                , 0,        1, AV_OPT_FLAG_DECODING_PARAM },
     326             :     { NULL },
     327             : };
     328             : 
     329             : static const AVClass demuxer_class = {
     330             :     .class_name = "GIF demuxer",
     331             :     .item_name  = av_default_item_name,
     332             :     .option     = options,
     333             :     .version    = LIBAVUTIL_VERSION_INT,
     334             :     .category   = AV_CLASS_CATEGORY_DEMUXER,
     335             : };
     336             : 
     337             : AVInputFormat ff_gif_demuxer = {
     338             :     .name           = "gif",
     339             :     .long_name      = NULL_IF_CONFIG_SMALL("CompuServe Graphics Interchange Format (GIF)"),
     340             :     .priv_data_size = sizeof(GIFDemuxContext),
     341             :     .read_probe     = gif_probe,
     342             :     .read_header    = gif_read_header,
     343             :     .read_packet    = gif_read_packet,
     344             :     .flags          = AVFMT_GENERIC_INDEX,
     345             :     .priv_class     = &demuxer_class,
     346             : };

Generated by: LCOV version 1.13