LCOV - code coverage report
Current view: top level - libavcodec - gifdec.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 200 266 75.2 %
Date: 2017-12-15 11:05:35 Functions: 11 11 100.0 %

          Line data    Source code
       1             : /*
       2             :  * GIF decoder
       3             :  * Copyright (c) 2003 Fabrice Bellard
       4             :  * Copyright (c) 2006 Baptiste Coudurier
       5             :  * Copyright (c) 2012 Vitaliy E Sugrobov
       6             :  *
       7             :  * This file is part of FFmpeg.
       8             :  *
       9             :  * FFmpeg is free software; you can redistribute it and/or
      10             :  * modify it under the terms of the GNU Lesser General Public
      11             :  * License as published by the Free Software Foundation; either
      12             :  * version 2.1 of the License, or (at your option) any later version.
      13             :  *
      14             :  * FFmpeg is distributed in the hope that it will be useful,
      15             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      17             :  * Lesser General Public License for more details.
      18             :  *
      19             :  * You should have received a copy of the GNU Lesser General Public
      20             :  * License along with FFmpeg; if not, write to the Free Software
      21             :  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
      22             :  */
      23             : 
      24             : #include "libavutil/imgutils.h"
      25             : #include "libavutil/opt.h"
      26             : #include "avcodec.h"
      27             : #include "bytestream.h"
      28             : #include "internal.h"
      29             : #include "lzw.h"
      30             : #include "gif.h"
      31             : 
      32             : /* This value is intentionally set to "transparent white" color.
      33             :  * It is much better to have white background instead of black
      34             :  * when gif image converted to format which not support transparency.
      35             :  */
      36             : #define GIF_TRANSPARENT_COLOR    0x00ffffff
      37             : 
      38             : typedef struct GifState {
      39             :     const AVClass *class;
      40             :     AVFrame *frame;
      41             :     int screen_width;
      42             :     int screen_height;
      43             :     int has_global_palette;
      44             :     int bits_per_pixel;
      45             :     uint32_t bg_color;
      46             :     int background_color_index;
      47             :     int transparent_color_index;
      48             :     int color_resolution;
      49             :     /* intermediate buffer for storing color indices
      50             :      * obtained from lzw-encoded data stream */
      51             :     uint8_t *idx_line;
      52             :     int idx_line_size;
      53             : 
      54             :     /* after the frame is displayed, the disposal method is used */
      55             :     int gce_prev_disposal;
      56             :     int gce_disposal;
      57             :     /* rectangle describing area that must be disposed */
      58             :     int gce_l, gce_t, gce_w, gce_h;
      59             :     /* depending on disposal method we store either part of the image
      60             :      * drawn on the canvas or background color that
      61             :      * should be used upon disposal */
      62             :     uint32_t * stored_img;
      63             :     int stored_img_size;
      64             :     int stored_bg_color;
      65             : 
      66             :     GetByteContext gb;
      67             :     LZWState *lzw;
      68             : 
      69             :     /* aux buffers */
      70             :     uint32_t global_palette[256];
      71             :     uint32_t local_palette[256];
      72             : 
      73             :     AVCodecContext *avctx;
      74             :     int keyframe;
      75             :     int keyframe_ok;
      76             :     int trans_color;    /**< color value that is used instead of transparent color */
      77             : } GifState;
      78             : 
      79        1219 : static void gif_read_palette(GifState *s, uint32_t *pal, int nb)
      80             : {
      81             :     int i;
      82             : 
      83      300547 :     for (i = 0; i < nb; i++, pal++)
      84      299328 :         *pal = (0xffu << 24) | bytestream2_get_be24u(&s->gb);
      85        1219 : }
      86             : 
      87          13 : static void gif_fill(AVFrame *picture, uint32_t color)
      88             : {
      89          13 :     uint32_t *p = (uint32_t *)picture->data[0];
      90          13 :     uint32_t *p_end = p + (picture->linesize[0] / sizeof(uint32_t)) * picture->height;
      91             : 
      92      726141 :     for (; p < p_end; p++)
      93      726128 :         *p = color;
      94          13 : }
      95             : 
      96           6 : static void gif_fill_rect(AVFrame *picture, uint32_t color, int l, int t, int w, int h)
      97             : {
      98           6 :     const int linesize = picture->linesize[0] / sizeof(uint32_t);
      99           6 :     const uint32_t *py = (uint32_t *)picture->data[0] + t * linesize;
     100           6 :     const uint32_t *pr, *pb = py + h * linesize;
     101             :     uint32_t *px;
     102             : 
     103         222 :     for (; py < pb; py += linesize) {
     104         216 :         px = (uint32_t *)py + l;
     105         216 :         pr = px + w;
     106             : 
     107       15768 :         for (; px < pr; px++)
     108       15552 :             *px = color;
     109             :     }
     110           6 : }
     111             : 
     112           3 : static void gif_copy_img_rect(const uint32_t *src, uint32_t *dst,
     113             :                               int linesize, int l, int t, int w, int h)
     114             : {
     115           3 :     const int y_start = t * linesize;
     116             :     const uint32_t *src_px,
     117           3 :                    *src_py = src + y_start,
     118           3 :                    *dst_py = dst + y_start;
     119           3 :     const uint32_t *src_pb = src_py + h * linesize;
     120             :     uint32_t *dst_px;
     121             : 
     122         183 :     for (; src_py < src_pb; src_py += linesize, dst_py += linesize) {
     123         180 :         src_px = src_py + l;
     124         180 :         dst_px = (uint32_t *)dst_py + l;
     125             : 
     126         180 :         memcpy(dst_px, src_px, w * sizeof(uint32_t));
     127             :     }
     128           3 : }
     129             : 
     130        1294 : static int gif_read_image(GifState *s, AVFrame *frame)
     131             : {
     132             :     int left, top, width, height, bits_per_pixel, code_size, flags, pw;
     133             :     int is_interleaved, has_local_palette, y, pass, y1, linesize, pal_size, lzwed_len;
     134             :     uint32_t *ptr, *pal, *px, *pr, *ptr1;
     135             :     int ret;
     136             :     uint8_t *idx;
     137             : 
     138             :     /* At least 9 bytes of Image Descriptor. */
     139        1294 :     if (bytestream2_get_bytes_left(&s->gb) < 9)
     140           0 :         return AVERROR_INVALIDDATA;
     141             : 
     142        1294 :     left   = bytestream2_get_le16u(&s->gb);
     143        1294 :     top    = bytestream2_get_le16u(&s->gb);
     144        1294 :     width  = bytestream2_get_le16u(&s->gb);
     145        1294 :     height = bytestream2_get_le16u(&s->gb);
     146        1294 :     flags  = bytestream2_get_byteu(&s->gb);
     147        1294 :     is_interleaved = flags & 0x40;
     148        1294 :     has_local_palette = flags & 0x80;
     149        1294 :     bits_per_pixel = (flags & 0x07) + 1;
     150             : 
     151             :     ff_dlog(s->avctx, "image x=%d y=%d w=%d h=%d\n", left, top, width, height);
     152             : 
     153        1294 :     if (has_local_palette) {
     154        1213 :         pal_size = 1 << bits_per_pixel;
     155             : 
     156        1213 :         if (bytestream2_get_bytes_left(&s->gb) < pal_size * 3)
     157           0 :             return AVERROR_INVALIDDATA;
     158             : 
     159        1213 :         gif_read_palette(s, s->local_palette, pal_size);
     160        1213 :         pal = s->local_palette;
     161             :     } else {
     162          81 :         if (!s->has_global_palette) {
     163           0 :             av_log(s->avctx, AV_LOG_ERROR, "picture doesn't have either global or local palette.\n");
     164           0 :             return AVERROR_INVALIDDATA;
     165             :         }
     166             : 
     167          81 :         pal = s->global_palette;
     168             :     }
     169             : 
     170        1294 :     if (s->keyframe) {
     171          13 :         if (s->transparent_color_index == -1 && s->has_global_palette) {
     172             :             /* transparency wasn't set before the first frame, fill with background color */
     173           5 :             gif_fill(frame, s->bg_color);
     174             :         } else {
     175             :             /* otherwise fill with transparent color.
     176             :              * this is necessary since by default picture filled with 0x80808080. */
     177           8 :             gif_fill(frame, s->trans_color);
     178             :         }
     179             :     }
     180             : 
     181             :     /* verify that all the image is inside the screen dimensions */
     182        1294 :     if (!width || width > s->screen_width || left >= s->screen_width) {
     183           0 :         av_log(s->avctx, AV_LOG_ERROR, "Invalid image width.\n");
     184           0 :         return AVERROR_INVALIDDATA;
     185             :     }
     186        1294 :     if (!height || height > s->screen_height || top >= s->screen_height) {
     187           0 :         av_log(s->avctx, AV_LOG_ERROR, "Invalid image height.\n");
     188           0 :         return AVERROR_INVALIDDATA;
     189             :     }
     190        1294 :     if (left + width > s->screen_width) {
     191             :         /* width must be kept around to avoid lzw vs line desync */
     192           0 :         pw = s->screen_width - left;
     193           0 :         av_log(s->avctx, AV_LOG_WARNING, "Image too wide by %d, truncating.\n",
     194           0 :                left + width - s->screen_width);
     195             :     } else {
     196        1294 :         pw = width;
     197             :     }
     198        1294 :     if (top + height > s->screen_height) {
     199             :         /* we don't care about the extra invisible lines */
     200           0 :         av_log(s->avctx, AV_LOG_WARNING, "Image too high by %d, truncating.\n",
     201           0 :                top + height - s->screen_height);
     202           0 :         height = s->screen_height - top;
     203             :     }
     204             : 
     205             :     /* process disposal method */
     206        1294 :     if (s->gce_prev_disposal == GCE_DISPOSAL_BACKGROUND) {
     207           6 :         gif_fill_rect(frame, s->stored_bg_color, s->gce_l, s->gce_t, s->gce_w, s->gce_h);
     208        1288 :     } else if (s->gce_prev_disposal == GCE_DISPOSAL_RESTORE) {
     209           2 :         gif_copy_img_rect(s->stored_img, (uint32_t *)frame->data[0],
     210           1 :             frame->linesize[0] / sizeof(uint32_t), s->gce_l, s->gce_t, s->gce_w, s->gce_h);
     211             :     }
     212             : 
     213        1294 :     s->gce_prev_disposal = s->gce_disposal;
     214             : 
     215        1294 :     if (s->gce_disposal != GCE_DISPOSAL_NONE) {
     216        1293 :         s->gce_l = left;  s->gce_t = top;
     217        1293 :         s->gce_w = pw;    s->gce_h = height;
     218             : 
     219        1293 :         if (s->gce_disposal == GCE_DISPOSAL_BACKGROUND) {
     220           8 :             if (s->transparent_color_index >= 0)
     221           8 :                 s->stored_bg_color = s->trans_color;
     222             :             else
     223           0 :                 s->stored_bg_color = s->bg_color;
     224        1285 :         } else if (s->gce_disposal == GCE_DISPOSAL_RESTORE) {
     225           2 :             av_fast_malloc(&s->stored_img, &s->stored_img_size, frame->linesize[0] * frame->height);
     226           2 :             if (!s->stored_img)
     227           0 :                 return AVERROR(ENOMEM);
     228             : 
     229           2 :             gif_copy_img_rect((uint32_t *)frame->data[0], s->stored_img,
     230           2 :                 frame->linesize[0] / sizeof(uint32_t), left, top, pw, height);
     231             :         }
     232             :     }
     233             : 
     234             :     /* Expect at least 2 bytes: 1 for lzw code size and 1 for block size. */
     235        1294 :     if (bytestream2_get_bytes_left(&s->gb) < 2)
     236           0 :         return AVERROR_INVALIDDATA;
     237             : 
     238             :     /* now get the image data */
     239        1294 :     code_size = bytestream2_get_byteu(&s->gb);
     240        1294 :     if ((ret = ff_lzw_decode_init(s->lzw, code_size, s->gb.buffer,
     241        1294 :                                   bytestream2_get_bytes_left(&s->gb), FF_LZW_GIF)) < 0) {
     242           0 :         av_log(s->avctx, AV_LOG_ERROR, "LZW init failed\n");
     243           0 :         return ret;
     244             :     }
     245             : 
     246             :     /* read all the image */
     247        1294 :     linesize = frame->linesize[0] / sizeof(uint32_t);
     248        1294 :     ptr1 = (uint32_t *)frame->data[0] + top * linesize + left;
     249        1294 :     ptr = ptr1;
     250        1294 :     pass = 0;
     251        1294 :     y1 = 0;
     252       39267 :     for (y = 0; y < height; y++) {
     253       37973 :         int count = ff_lzw_decode(s->lzw, s->idx_line, width);
     254       37973 :         if (count != width) {
     255           0 :             if (count)
     256           0 :                 av_log(s->avctx, AV_LOG_ERROR, "LZW decode failed\n");
     257           0 :             goto decode_tail;
     258             :         }
     259             : 
     260       37973 :         pr = ptr + pw;
     261             : 
     262     5366572 :         for (px = ptr, idx = s->idx_line; px < pr; px++, idx++) {
     263     5328599 :             if (*idx != s->transparent_color_index)
     264     3988325 :                 *px = pal[*idx];
     265             :         }
     266             : 
     267       37973 :         if (is_interleaved) {
     268           0 :             switch(pass) {
     269           0 :             default:
     270             :             case 0:
     271             :             case 1:
     272           0 :                 y1 += 8;
     273           0 :                 ptr += linesize * 8;
     274           0 :                 break;
     275           0 :             case 2:
     276           0 :                 y1 += 4;
     277           0 :                 ptr += linesize * 4;
     278           0 :                 break;
     279           0 :             case 3:
     280           0 :                 y1 += 2;
     281           0 :                 ptr += linesize * 2;
     282           0 :                 break;
     283             :             }
     284           0 :             while (y1 >= height) {
     285           0 :                 y1  = 4 >> pass;
     286           0 :                 ptr = ptr1 + linesize * y1;
     287           0 :                 pass++;
     288             :             }
     289             :         } else {
     290       37973 :             ptr += linesize;
     291             :         }
     292             :     }
     293             : 
     294        1294 :  decode_tail:
     295             :     /* read the garbage data until end marker is found */
     296        1294 :     lzwed_len = ff_lzw_decode_tail(s->lzw);
     297        1294 :     bytestream2_skipu(&s->gb, lzwed_len);
     298             : 
     299             :     /* Graphic Control Extension's scope is single frame.
     300             :      * Remove its influence. */
     301        1294 :     s->transparent_color_index = -1;
     302        1294 :     s->gce_disposal = GCE_DISPOSAL_NONE;
     303             : 
     304        1294 :     return 0;
     305             : }
     306             : 
     307        1303 : static int gif_read_extension(GifState *s)
     308             : {
     309             :     int ext_code, ext_len, gce_flags, gce_transparent_index;
     310             : 
     311             :     /* There must be at least 2 bytes:
     312             :      * 1 for extension label and 1 for extension length. */
     313        1303 :     if (bytestream2_get_bytes_left(&s->gb) < 2)
     314           0 :         return AVERROR_INVALIDDATA;
     315             : 
     316        1303 :     ext_code = bytestream2_get_byteu(&s->gb);
     317        1303 :     ext_len  = bytestream2_get_byteu(&s->gb);
     318             : 
     319             :     ff_dlog(s->avctx, "ext_code=0x%x len=%d\n", ext_code, ext_len);
     320             : 
     321        1303 :     switch(ext_code) {
     322        1294 :     case GIF_GCE_EXT_LABEL:
     323        1294 :         if (ext_len != 4)
     324           0 :             goto discard_ext;
     325             : 
     326             :         /* We need at least 5 bytes more: 4 is for extension body
     327             :          * and 1 for next block size. */
     328        1294 :         if (bytestream2_get_bytes_left(&s->gb) < 5)
     329           0 :             return AVERROR_INVALIDDATA;
     330             : 
     331        1294 :         gce_flags    = bytestream2_get_byteu(&s->gb);
     332        1294 :         bytestream2_skipu(&s->gb, 2);    // delay during which the frame is shown
     333        1294 :         gce_transparent_index = bytestream2_get_byteu(&s->gb);
     334        1294 :         if (gce_flags & 0x01)
     335          46 :             s->transparent_color_index = gce_transparent_index;
     336             :         else
     337        1248 :             s->transparent_color_index = -1;
     338        1294 :         s->gce_disposal = (gce_flags >> 2) & 0x7;
     339             : 
     340             :         ff_dlog(s->avctx, "gce_flags=%x tcolor=%d disposal=%d\n",
     341             :                gce_flags,
     342             :                s->transparent_color_index, s->gce_disposal);
     343             : 
     344        1294 :         if (s->gce_disposal > 3) {
     345           0 :             s->gce_disposal = GCE_DISPOSAL_NONE;
     346             :             ff_dlog(s->avctx, "invalid value in gce_disposal (%d). Using default value of 0.\n", ext_len);
     347             :         }
     348             : 
     349        1294 :         ext_len = bytestream2_get_byteu(&s->gb);
     350        1294 :         break;
     351             :     }
     352             : 
     353             :     /* NOTE: many extension blocks can come after */
     354        1303 :  discard_ext:
     355        2633 :     while (ext_len) {
     356             :         /* There must be at least ext_len bytes and 1 for next block size byte. */
     357          27 :         if (bytestream2_get_bytes_left(&s->gb) < ext_len + 1)
     358           0 :             return AVERROR_INVALIDDATA;
     359             : 
     360          27 :         bytestream2_skipu(&s->gb, ext_len);
     361          27 :         ext_len = bytestream2_get_byteu(&s->gb);
     362             : 
     363             :         ff_dlog(s->avctx, "ext_len1=%d\n", ext_len);
     364             :     }
     365        1303 :     return 0;
     366             : }
     367             : 
     368          13 : static int gif_read_header1(GifState *s)
     369             : {
     370             :     uint8_t sig[6];
     371             :     int v, n;
     372             :     int background_color_index;
     373             : 
     374          13 :     if (bytestream2_get_bytes_left(&s->gb) < 13)
     375           0 :         return AVERROR_INVALIDDATA;
     376             : 
     377             :     /* read gif signature */
     378          13 :     bytestream2_get_bufferu(&s->gb, sig, 6);
     379          26 :     if (memcmp(sig, gif87a_sig, 6) &&
     380          13 :         memcmp(sig, gif89a_sig, 6))
     381           0 :         return AVERROR_INVALIDDATA;
     382             : 
     383             :     /* read screen header */
     384          13 :     s->transparent_color_index = -1;
     385          13 :     s->screen_width  = bytestream2_get_le16u(&s->gb);
     386          13 :     s->screen_height = bytestream2_get_le16u(&s->gb);
     387             : 
     388          13 :     v = bytestream2_get_byteu(&s->gb);
     389          13 :     s->color_resolution = ((v & 0x70) >> 4) + 1;
     390          13 :     s->has_global_palette = (v & 0x80);
     391          13 :     s->bits_per_pixel = (v & 0x07) + 1;
     392          13 :     background_color_index = bytestream2_get_byteu(&s->gb);
     393          13 :     n = bytestream2_get_byteu(&s->gb);
     394          13 :     if (n) {
     395           0 :         s->avctx->sample_aspect_ratio.num = n + 15;
     396           0 :         s->avctx->sample_aspect_ratio.den = 64;
     397             :     }
     398             : 
     399             :     ff_dlog(s->avctx, "screen_w=%d screen_h=%d bpp=%d global_palette=%d\n",
     400             :            s->screen_width, s->screen_height, s->bits_per_pixel,
     401             :            s->has_global_palette);
     402             : 
     403          13 :     if (s->has_global_palette) {
     404           6 :         s->background_color_index = background_color_index;
     405           6 :         n = 1 << s->bits_per_pixel;
     406           6 :         if (bytestream2_get_bytes_left(&s->gb) < n * 3)
     407           0 :             return AVERROR_INVALIDDATA;
     408             : 
     409           6 :         gif_read_palette(s, s->global_palette, n);
     410           6 :         s->bg_color = s->global_palette[s->background_color_index];
     411             :     } else
     412           7 :         s->background_color_index = -1;
     413             : 
     414          13 :     return 0;
     415             : }
     416             : 
     417        1294 : static int gif_parse_next_image(GifState *s, AVFrame *frame)
     418             : {
     419        3891 :     while (bytestream2_get_bytes_left(&s->gb) > 0) {
     420        2597 :         int code = bytestream2_get_byte(&s->gb);
     421             :         int ret;
     422             : 
     423        2597 :         av_log(s->avctx, AV_LOG_DEBUG, "code=%02x '%c'\n", code, code);
     424             : 
     425        2597 :         switch (code) {
     426        1294 :         case GIF_IMAGE_SEPARATOR:
     427        1294 :             return gif_read_image(s, frame);
     428        1303 :         case GIF_EXTENSION_INTRODUCER:
     429        1303 :             if ((ret = gif_read_extension(s)) < 0)
     430           0 :                 return ret;
     431        1303 :             break;
     432           0 :         case GIF_TRAILER:
     433             :             /* end of image */
     434           0 :             return AVERROR_EOF;
     435           0 :         default:
     436             :             /* erroneous block label */
     437           0 :             return AVERROR_INVALIDDATA;
     438             :         }
     439             :     }
     440           0 :     return AVERROR_EOF;
     441             : }
     442             : 
     443          28 : static av_cold int gif_decode_init(AVCodecContext *avctx)
     444             : {
     445          28 :     GifState *s = avctx->priv_data;
     446             : 
     447          28 :     s->avctx = avctx;
     448             : 
     449          28 :     avctx->pix_fmt = AV_PIX_FMT_RGB32;
     450          28 :     s->frame = av_frame_alloc();
     451          28 :     if (!s->frame)
     452           0 :         return AVERROR(ENOMEM);
     453          28 :     ff_lzw_decode_open(&s->lzw);
     454          28 :     return 0;
     455             : }
     456             : 
     457        1294 : static int gif_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt)
     458             : {
     459        1294 :     GifState *s = avctx->priv_data;
     460             :     int ret;
     461             : 
     462        1294 :     bytestream2_init(&s->gb, avpkt->data, avpkt->size);
     463             : 
     464        1294 :     s->frame->pts     = avpkt->pts;
     465             : #if FF_API_PKT_PTS
     466             : FF_DISABLE_DEPRECATION_WARNINGS
     467        1294 :     s->frame->pkt_pts = avpkt->pts;
     468             : FF_ENABLE_DEPRECATION_WARNINGS
     469             : #endif
     470        1294 :     s->frame->pkt_dts = avpkt->dts;
     471        1294 :     s->frame->pkt_duration = avpkt->duration;
     472             : 
     473        1294 :     if (avpkt->size >= 6) {
     474        2588 :         s->keyframe = memcmp(avpkt->data, gif87a_sig, 6) == 0 ||
     475        1294 :                       memcmp(avpkt->data, gif89a_sig, 6) == 0;
     476             :     } else {
     477           0 :         s->keyframe = 0;
     478             :     }
     479             : 
     480        1294 :     if (s->keyframe) {
     481          13 :         s->keyframe_ok = 0;
     482          13 :         s->gce_prev_disposal = GCE_DISPOSAL_NONE;
     483          13 :         if ((ret = gif_read_header1(s)) < 0)
     484           0 :             return ret;
     485             : 
     486          13 :         if ((ret = ff_set_dimensions(avctx, s->screen_width, s->screen_height)) < 0)
     487           0 :             return ret;
     488             : 
     489          13 :         av_frame_unref(s->frame);
     490          13 :         if ((ret = ff_get_buffer(avctx, s->frame, 0)) < 0)
     491           0 :             return ret;
     492             : 
     493          13 :         av_fast_malloc(&s->idx_line, &s->idx_line_size, s->screen_width);
     494          13 :         if (!s->idx_line)
     495           0 :             return AVERROR(ENOMEM);
     496             : 
     497          13 :         s->frame->pict_type = AV_PICTURE_TYPE_I;
     498          13 :         s->frame->key_frame = 1;
     499          13 :         s->keyframe_ok = 1;
     500             :     } else {
     501        1281 :         if (!s->keyframe_ok) {
     502           0 :             av_log(avctx, AV_LOG_ERROR, "cannot decode frame without keyframe\n");
     503           0 :             return AVERROR_INVALIDDATA;
     504             :         }
     505             : 
     506        1281 :         if ((ret = ff_reget_buffer(avctx, s->frame)) < 0)
     507           0 :             return ret;
     508             : 
     509        1281 :         s->frame->pict_type = AV_PICTURE_TYPE_P;
     510        1281 :         s->frame->key_frame = 0;
     511             :     }
     512             : 
     513        1294 :     ret = gif_parse_next_image(s, s->frame);
     514        1294 :     if (ret < 0)
     515           0 :         return ret;
     516             : 
     517        1294 :     if ((ret = av_frame_ref(data, s->frame)) < 0)
     518           0 :         return ret;
     519        1294 :     *got_frame = 1;
     520             : 
     521        1294 :     return bytestream2_tell(&s->gb);
     522             : }
     523             : 
     524          28 : static av_cold int gif_decode_close(AVCodecContext *avctx)
     525             : {
     526          28 :     GifState *s = avctx->priv_data;
     527             : 
     528          28 :     ff_lzw_decode_close(&s->lzw);
     529          28 :     av_frame_free(&s->frame);
     530          28 :     av_freep(&s->idx_line);
     531          28 :     av_freep(&s->stored_img);
     532             : 
     533          28 :     return 0;
     534             : }
     535             : 
     536             : static const AVOption options[] = {
     537             :     { "trans_color", "color value (ARGB) that is used instead of transparent color",
     538             :       offsetof(GifState, trans_color), AV_OPT_TYPE_INT,
     539             :       {.i64 = GIF_TRANSPARENT_COLOR}, 0, 0xffffffff,
     540             :       AV_OPT_FLAG_DECODING_PARAM|AV_OPT_FLAG_VIDEO_PARAM },
     541             :     { NULL },
     542             : };
     543             : 
     544             : static const AVClass decoder_class = {
     545             :     .class_name = "gif decoder",
     546             :     .item_name  = av_default_item_name,
     547             :     .option     = options,
     548             :     .version    = LIBAVUTIL_VERSION_INT,
     549             :     .category   = AV_CLASS_CATEGORY_DECODER,
     550             : };
     551             : 
     552             : AVCodec ff_gif_decoder = {
     553             :     .name           = "gif",
     554             :     .long_name      = NULL_IF_CONFIG_SMALL("GIF (Graphics Interchange Format)"),
     555             :     .type           = AVMEDIA_TYPE_VIDEO,
     556             :     .id             = AV_CODEC_ID_GIF,
     557             :     .priv_data_size = sizeof(GifState),
     558             :     .init           = gif_decode_init,
     559             :     .close          = gif_decode_close,
     560             :     .decode         = gif_decode_frame,
     561             :     .capabilities   = AV_CODEC_CAP_DR1,
     562             :     .priv_class     = &decoder_class,
     563             : };

Generated by: LCOV version 1.13