LCOV - code coverage report
Current view: top level - libavcodec - sunrast.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 74 126 58.7 %
Date: 2017-12-12 11:08:38 Functions: 1 1 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Sun Rasterfile (.sun/.ras/im{1,8,24}/.sunras) image decoder
       3             :  * Copyright (c) 2007, 2008 Ivo van Poorten
       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             : #include "libavutil/common.h"
      23             : #include "libavutil/intreadwrite.h"
      24             : #include "libavutil/imgutils.h"
      25             : #include "avcodec.h"
      26             : #include "internal.h"
      27             : #include "sunrast.h"
      28             : 
      29          28 : static int sunrast_decode_frame(AVCodecContext *avctx, void *data,
      30             :                                 int *got_frame, AVPacket *avpkt)
      31             : {
      32          28 :     const uint8_t *buf       = avpkt->data;
      33          28 :     const uint8_t *buf_end   = avpkt->data + avpkt->size;
      34          28 :     AVFrame * const p        = data;
      35             :     unsigned int w, h, depth, type, maptype, maplength, stride, x, y, len, alen;
      36          28 :     uint8_t *ptr, *ptr2 = NULL;
      37          28 :     const uint8_t *bufstart = buf;
      38             :     int ret;
      39             : 
      40          28 :     if (avpkt->size < 32)
      41           0 :         return AVERROR_INVALIDDATA;
      42             : 
      43          28 :     if (AV_RB32(buf) != RAS_MAGIC) {
      44           0 :         av_log(avctx, AV_LOG_ERROR, "this is not sunras encoded data\n");
      45           0 :         return AVERROR_INVALIDDATA;
      46             :     }
      47             : 
      48          28 :     w         = AV_RB32(buf + 4);
      49          28 :     h         = AV_RB32(buf + 8);
      50          28 :     depth     = AV_RB32(buf + 12);
      51          28 :     type      = AV_RB32(buf + 20);
      52          28 :     maptype   = AV_RB32(buf + 24);
      53          28 :     maplength = AV_RB32(buf + 28);
      54          28 :     buf      += 32;
      55             : 
      56          28 :     if (type == RT_EXPERIMENTAL) {
      57           0 :         avpriv_request_sample(avctx, "TIFF/IFF/EXPERIMENTAL (compression) type");
      58           0 :         return AVERROR_PATCHWELCOME;
      59             :     }
      60          28 :     if (type > RT_FORMAT_IFF) {
      61           0 :         av_log(avctx, AV_LOG_ERROR, "invalid (compression) type\n");
      62           0 :         return AVERROR_INVALIDDATA;
      63             :     }
      64          28 :     if (maptype == RMT_RAW) {
      65           0 :         avpriv_request_sample(avctx, "Unknown colormap type");
      66           0 :         return AVERROR_PATCHWELCOME;
      67             :     }
      68          28 :     if (maptype > RMT_RAW) {
      69           0 :         av_log(avctx, AV_LOG_ERROR, "invalid colormap type\n");
      70           0 :         return AVERROR_INVALIDDATA;
      71             :     }
      72             : 
      73          28 :     if (type == RT_FORMAT_TIFF || type == RT_FORMAT_IFF) {
      74           0 :         av_log(avctx, AV_LOG_ERROR, "unsupported (compression) type\n");
      75           0 :         return -1;
      76             :     }
      77             : 
      78          28 :     switch (depth) {
      79           4 :         case 1:
      80           4 :             avctx->pix_fmt = maplength ? AV_PIX_FMT_PAL8 : AV_PIX_FMT_MONOWHITE;
      81           4 :             break;
      82           0 :         case 4:
      83           0 :             avctx->pix_fmt = maplength ? AV_PIX_FMT_PAL8 : AV_PIX_FMT_NONE;
      84           0 :             break;
      85           6 :         case 8:
      86           6 :             avctx->pix_fmt = maplength ? AV_PIX_FMT_PAL8 : AV_PIX_FMT_GRAY8;
      87           6 :             break;
      88          18 :         case 24:
      89          18 :             avctx->pix_fmt = (type == RT_FORMAT_RGB) ? AV_PIX_FMT_RGB24 : AV_PIX_FMT_BGR24;
      90          18 :             break;
      91           0 :         case 32:
      92           0 :             avctx->pix_fmt = (type == RT_FORMAT_RGB) ? AV_PIX_FMT_0RGB : AV_PIX_FMT_0BGR;
      93           0 :             break;
      94           0 :         default:
      95           0 :             av_log(avctx, AV_LOG_ERROR, "invalid depth\n");
      96           0 :             return AVERROR_INVALIDDATA;
      97             :     }
      98             : 
      99          28 :     ret = ff_set_dimensions(avctx, w, h);
     100          28 :     if (ret < 0)
     101           0 :         return ret;
     102             : 
     103          28 :     if ((ret = ff_get_buffer(avctx, p, 0)) < 0)
     104           0 :         return ret;
     105             : 
     106          28 :     p->pict_type = AV_PICTURE_TYPE_I;
     107             : 
     108          28 :     if (buf_end - buf < maplength)
     109           0 :         return AVERROR_INVALIDDATA;
     110             : 
     111          28 :     if (depth > 8 && maplength) {
     112           0 :         av_log(avctx, AV_LOG_WARNING, "useless colormap found or file is corrupted, trying to recover\n");
     113             : 
     114          28 :     } else if (maplength) {
     115           4 :         unsigned int len = maplength / 3;
     116             : 
     117           4 :         if (maplength % 3 || maplength > 768) {
     118           0 :             av_log(avctx, AV_LOG_WARNING, "invalid colormap length\n");
     119           0 :             return AVERROR_INVALIDDATA;
     120             :         }
     121             : 
     122           4 :         ptr = p->data[1];
     123        1028 :         for (x = 0; x < len; x++, ptr += 4)
     124        1024 :             *(uint32_t *)ptr = (0xFFU<<24) + (buf[x]<<16) + (buf[len+x]<<8) + buf[len+len+x];
     125             :     }
     126             : 
     127          28 :     buf += maplength;
     128             : 
     129          28 :     if (maplength && depth < 8) {
     130           0 :         ptr = ptr2 = av_malloc_array((w + 15), h);
     131           0 :         if (!ptr)
     132           0 :             return AVERROR(ENOMEM);
     133           0 :         stride = (w + 15 >> 3) * depth;
     134             :     } else {
     135          28 :     ptr    = p->data[0];
     136          28 :     stride = p->linesize[0];
     137             :     }
     138             : 
     139             :     /* scanlines are aligned on 16 bit boundaries */
     140          28 :     len  = (depth * w + 7) >> 3;
     141          28 :     alen = len + (len & 1);
     142             : 
     143          28 :     if (type == RT_BYTE_ENCODED) {
     144             :         int value, run;
     145          20 :         uint8_t *end = ptr + h * stride;
     146             : 
     147          20 :         x = 0;
     148     6339790 :         while (ptr != end && buf < buf_end) {
     149     6339750 :             run = 1;
     150     6339750 :             if (buf_end - buf < 1)
     151           0 :                 return AVERROR_INVALIDDATA;
     152             : 
     153     6339750 :             if ((value = *buf++) == RLE_TRIGGER) {
     154       37867 :                 run = *buf++ + 1;
     155       37867 :                 if (run != 1)
     156       27727 :                     value = *buf++;
     157             :             }
     158    19099960 :             while (run--) {
     159     6420480 :                 if (x < len)
     160     6420480 :                     ptr[x] = value;
     161     6420480 :                 if (++x >= alen) {
     162        7104 :                     x = 0;
     163        7104 :                     ptr += stride;
     164        7104 :                     if (ptr == end)
     165          20 :                         break;
     166             :                 }
     167             :             }
     168             :         }
     169             :     } else {
     170        4616 :         for (y = 0; y < h; y++) {
     171        4608 :             if (buf_end - buf < alen)
     172           0 :                 break;
     173        4608 :             memcpy(ptr, buf, len);
     174        4608 :             ptr += stride;
     175        4608 :             buf += alen;
     176             :         }
     177             :     }
     178          28 :     if (avctx->pix_fmt == AV_PIX_FMT_PAL8 && depth < 8) {
     179           0 :         uint8_t *ptr_free = ptr2;
     180           0 :         ptr = p->data[0];
     181           0 :         for (y=0; y<h; y++) {
     182           0 :             for (x = 0; x < (w + 7 >> 3) * depth; x++) {
     183           0 :                 if (depth == 1) {
     184           0 :                     ptr[8*x]   = ptr2[x] >> 7;
     185           0 :                     ptr[8*x+1] = ptr2[x] >> 6 & 1;
     186           0 :                     ptr[8*x+2] = ptr2[x] >> 5 & 1;
     187           0 :                     ptr[8*x+3] = ptr2[x] >> 4 & 1;
     188           0 :                     ptr[8*x+4] = ptr2[x] >> 3 & 1;
     189           0 :                     ptr[8*x+5] = ptr2[x] >> 2 & 1;
     190           0 :                     ptr[8*x+6] = ptr2[x] >> 1 & 1;
     191           0 :                     ptr[8*x+7] = ptr2[x]      & 1;
     192             :                 } else {
     193           0 :                     ptr[2*x]   = ptr2[x] >> 4;
     194           0 :                     ptr[2*x+1] = ptr2[x] & 0xF;
     195             :                 }
     196             :             }
     197           0 :             ptr  += p->linesize[0];
     198           0 :             ptr2 += (w + 15 >> 3) * depth;
     199             :         }
     200           0 :         av_freep(&ptr_free);
     201             :     }
     202             : 
     203          28 :     *got_frame = 1;
     204             : 
     205          28 :     return buf - bufstart;
     206             : }
     207             : 
     208             : AVCodec ff_sunrast_decoder = {
     209             :     .name           = "sunrast",
     210             :     .long_name      = NULL_IF_CONFIG_SMALL("Sun Rasterfile image"),
     211             :     .type           = AVMEDIA_TYPE_VIDEO,
     212             :     .id             = AV_CODEC_ID_SUNRAST,
     213             :     .decode         = sunrast_decode_frame,
     214             :     .capabilities   = AV_CODEC_CAP_DR1,
     215             : };

Generated by: LCOV version 1.13