LCOV - code coverage report
Current view: top level - libavcodec - anm.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 71 86 82.6 %
Date: 2017-12-10 21:22:29 Functions: 4 4 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Deluxe Paint Animation decoder
       3             :  * Copyright (c) 2009 Peter Ross
       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             :  * Deluxe Paint Animation decoder
      25             :  */
      26             : 
      27             : #include "avcodec.h"
      28             : #include "bytestream.h"
      29             : #include "internal.h"
      30             : 
      31             : typedef struct AnmContext {
      32             :     AVFrame *frame;
      33             :     int palette[AVPALETTE_COUNT];
      34             :     GetByteContext gb;
      35             :     int x;  ///< x coordinate position
      36             : } AnmContext;
      37             : 
      38           2 : static av_cold int decode_init(AVCodecContext *avctx)
      39             : {
      40           2 :     AnmContext *s = avctx->priv_data;
      41             :     int i;
      42             : 
      43           2 :     avctx->pix_fmt = AV_PIX_FMT_PAL8;
      44             : 
      45           2 :     s->frame = av_frame_alloc();
      46           2 :     if (!s->frame)
      47           0 :         return AVERROR(ENOMEM);
      48             : 
      49           2 :     bytestream2_init(&s->gb, avctx->extradata, avctx->extradata_size);
      50           2 :     if (bytestream2_get_bytes_left(&s->gb) < 16 * 8 + 4 * 256) {
      51           0 :         av_frame_free(&s->frame);
      52           0 :         return AVERROR_INVALIDDATA;
      53             :     }
      54             : 
      55           2 :     bytestream2_skipu(&s->gb, 16 * 8);
      56         514 :     for (i = 0; i < 256; i++)
      57         512 :         s->palette[i] = bytestream2_get_le32u(&s->gb);
      58             : 
      59           2 :     return 0;
      60             : }
      61             : 
      62             : /**
      63             :  * Perform decode operation
      64             :  * @param dst     pointer to destination image buffer
      65             :  * @param dst_end pointer to end of destination image buffer
      66             :  * @param gb GetByteContext (optional, see below)
      67             :  * @param pixel Fill color (optional, see below)
      68             :  * @param count Pixel count
      69             :  * @param x Pointer to x-axis counter
      70             :  * @param width Image width
      71             :  * @param linesize Destination image buffer linesize
      72             :  * @return non-zero if destination buffer is exhausted
      73             :  *
      74             :  * a copy operation is achieved when 'gb' is set
      75             :  * a fill operation is achieved when 'gb' is null and pixel is >= 0
      76             :  * a skip operation is achieved when 'gb' is null and pixel is < 0
      77             :  */
      78      107093 : static inline int op(uint8_t **dst, const uint8_t *dst_end,
      79             :                      GetByteContext *gb,
      80             :                      int pixel, int count,
      81             :                      int *x, int width, int linesize)
      82             : {
      83      107093 :     int remaining = width - *x;
      84      338814 :     while(count > 0) {
      85      124635 :         int striplen = FFMIN(count, remaining);
      86      124635 :         if (gb) {
      87       43244 :             if (bytestream2_get_bytes_left(gb) < striplen)
      88           0 :                 goto exhausted;
      89       43244 :             bytestream2_get_bufferu(gb, *dst, striplen);
      90       81391 :         } else if (pixel >= 0)
      91       29042 :             memset(*dst, pixel, striplen);
      92      124635 :         *dst      += striplen;
      93      124635 :         remaining -= striplen;
      94      124635 :         count     -= striplen;
      95      124635 :         if (remaining <= 0) {
      96       18753 :             *dst      += linesize - width;
      97       18753 :             remaining  = width;
      98             :         }
      99      124635 :         if (linesize > 0) {
     100      124635 :             if (*dst >= dst_end) goto exhausted;
     101             :         } else {
     102           0 :             if (*dst <= dst_end) goto exhausted;
     103             :         }
     104             :     }
     105      107086 :     *x = width - remaining;
     106      107086 :     return 0;
     107             : 
     108           7 : exhausted:
     109           7 :     *x = width - remaining;
     110           7 :     return 1;
     111             : }
     112             : 
     113         123 : static int decode_frame(AVCodecContext *avctx,
     114             :                         void *data, int *got_frame,
     115             :                         AVPacket *avpkt)
     116             : {
     117         123 :     AnmContext *s = avctx->priv_data;
     118         123 :     const int buf_size = avpkt->size;
     119             :     uint8_t *dst, *dst_end;
     120             :     int count, ret;
     121             : 
     122         123 :     if ((ret = ff_reget_buffer(avctx, s->frame)) < 0)
     123           0 :         return ret;
     124         123 :     dst     = s->frame->data[0];
     125         123 :     dst_end = s->frame->data[0] + s->frame->linesize[0]*avctx->height;
     126             : 
     127         123 :     bytestream2_init(&s->gb, avpkt->data, buf_size);
     128             : 
     129         123 :     if (bytestream2_get_byte(&s->gb) != 0x42) {
     130           0 :         avpriv_request_sample(avctx, "Unknown record type");
     131           0 :         return AVERROR_INVALIDDATA;
     132             :     }
     133         123 :     if (bytestream2_get_byte(&s->gb)) {
     134           0 :         avpriv_request_sample(avctx, "Padding bytes");
     135           0 :         return AVERROR_PATCHWELCOME;
     136             :     }
     137         123 :     bytestream2_skip(&s->gb, 2);
     138             : 
     139         123 :     s->x = 0;
     140             :     do {
     141             :         /* if statements are ordered by probability */
     142             : #define OP(gb, pixel, count) \
     143             :     op(&dst, dst_end, (gb), (pixel), (count), &s->x, avctx->width, s->frame->linesize[0])
     144             : 
     145      107209 :         int type = bytestream2_get_byte(&s->gb);
     146      107209 :         count = type & 0x7F;
     147      107209 :         type >>= 7;
     148      107209 :         if (count) {
     149       74301 :             if (OP(type ? NULL : &s->gb, -1, count)) break;
     150       32908 :         } else if (!type) {
     151             :             int pixel;
     152       28842 :             count = bytestream2_get_byte(&s->gb);  /* count==0 gives nop */
     153       28842 :             pixel = bytestream2_get_byte(&s->gb);
     154       28842 :             if (OP(NULL, pixel, count)) break;
     155             :         } else {
     156             :             int pixel;
     157        4066 :             type = bytestream2_get_le16(&s->gb);
     158        4066 :             count = type & 0x3FFF;
     159        4066 :             type >>= 14;
     160        4066 :             if (!count) {
     161         116 :                 if (type == 0)
     162         116 :                     break; // stop
     163           0 :                 if (type == 2) {
     164           0 :                     avpriv_request_sample(avctx, "Unknown opcode");
     165           0 :                     return AVERROR_PATCHWELCOME;
     166             :                 }
     167           0 :                 continue;
     168             :             }
     169        3950 :             pixel = type == 3 ? bytestream2_get_byte(&s->gb) : -1;
     170        3950 :             if (type == 1) count += 0x4000;
     171        3950 :             if (OP(type == 2 ? &s->gb : NULL, pixel, count)) break;
     172             :         }
     173      107086 :     } while (bytestream2_get_bytes_left(&s->gb) > 0);
     174             : 
     175         123 :     memcpy(s->frame->data[1], s->palette, AVPALETTE_SIZE);
     176             : 
     177         123 :     *got_frame = 1;
     178         123 :     if ((ret = av_frame_ref(data, s->frame)) < 0)
     179           0 :         return ret;
     180             : 
     181         123 :     return buf_size;
     182             : }
     183             : 
     184           2 : static av_cold int decode_end(AVCodecContext *avctx)
     185             : {
     186           2 :     AnmContext *s = avctx->priv_data;
     187             : 
     188           2 :     av_frame_free(&s->frame);
     189           2 :     return 0;
     190             : }
     191             : 
     192             : AVCodec ff_anm_decoder = {
     193             :     .name           = "anm",
     194             :     .long_name      = NULL_IF_CONFIG_SMALL("Deluxe Paint Animation"),
     195             :     .type           = AVMEDIA_TYPE_VIDEO,
     196             :     .id             = AV_CODEC_ID_ANM,
     197             :     .priv_data_size = sizeof(AnmContext),
     198             :     .init           = decode_init,
     199             :     .close          = decode_end,
     200             :     .decode         = decode_frame,
     201             :     .capabilities   = AV_CODEC_CAP_DR1,
     202             :     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
     203             : };

Generated by: LCOV version 1.13