LCOV - code coverage report
Current view: top level - libavcodec - pnm.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 94 122 77.0 %
Date: 2017-12-15 18:13:28 Functions: 3 3 100.0 %

          Line data    Source code
       1             : /*
       2             :  * PNM image format
       3             :  * Copyright (c) 2002, 2003 Fabrice Bellard
       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 <stdlib.h>
      23             : #include <string.h>
      24             : 
      25             : #include "libavutil/imgutils.h"
      26             : #include "avcodec.h"
      27             : #include "internal.h"
      28             : #include "pnm.h"
      29             : 
      30      301263 : static inline int pnm_space(int c)
      31             : {
      32      301263 :     return c == ' ' || c == '\n' || c == '\r' || c == '\t';
      33             : }
      34             : 
      35       63046 : static void pnm_get(PNMContext *sc, char *str, int buf_size)
      36             : {
      37             :     char *s;
      38             :     int c;
      39             : 
      40             :     /* skip spaces and comments */
      41      126142 :     while (sc->bytestream < sc->bytestream_end) {
      42       63087 :         c = *sc->bytestream++;
      43       63087 :         if (c == '#')  {
      44        2300 :             while (c != '\n' && sc->bytestream < sc->bytestream_end) {
      45        2200 :                 c = *sc->bytestream++;
      46             :             }
      47       63037 :         } else if (!pnm_space(c)) {
      48       63037 :             break;
      49             :         }
      50             :     }
      51             : 
      52       63046 :     s = str;
      53      301281 :     while (sc->bytestream < sc->bytestream_end && !pnm_space(c)) {
      54      175189 :         if ((s - str)  < buf_size - 1)
      55      175189 :             *s++ = c;
      56      175189 :         c = *sc->bytestream++;
      57             :     }
      58       63046 :     *s = '\0';
      59       63046 : }
      60             : 
      61       15695 : int ff_pnm_decode_header(AVCodecContext *avctx, PNMContext * const s)
      62             : {
      63             :     char buf1[32], tuple_type[32];
      64             :     int h, w, depth, maxval;
      65             :     int ret;
      66             : 
      67       15695 :     pnm_get(s, buf1, sizeof(buf1));
      68       15695 :     if(buf1[0] != 'P')
      69           9 :         return AVERROR_INVALIDDATA;
      70       15686 :     s->type= buf1[1]-'0';
      71             : 
      72       15686 :     if (s->type==1 || s->type==4) {
      73         379 :         avctx->pix_fmt = AV_PIX_FMT_MONOWHITE;
      74       15307 :     } else if (s->type==2 || s->type==5) {
      75       23644 :         if (avctx->codec_id == AV_CODEC_ID_PGMYUV)
      76       10227 :             avctx->pix_fmt = AV_PIX_FMT_YUV420P;
      77             :         else
      78        1595 :             avctx->pix_fmt = AV_PIX_FMT_GRAY8;
      79        3485 :     } else if (s->type==3 || s->type==6) {
      80        3401 :         avctx->pix_fmt = AV_PIX_FMT_RGB24;
      81          84 :     } else if (s->type==7) {
      82          84 :         w      = -1;
      83          84 :         h      = -1;
      84          84 :         maxval = -1;
      85          84 :         depth  = -1;
      86          84 :         tuple_type[0] = '\0';
      87             :         for (;;) {
      88         924 :             pnm_get(s, buf1, sizeof(buf1));
      89         504 :             if (!strcmp(buf1, "WIDTH")) {
      90          84 :                 pnm_get(s, buf1, sizeof(buf1));
      91          84 :                 w = strtol(buf1, NULL, 10);
      92         420 :             } else if (!strcmp(buf1, "HEIGHT")) {
      93          84 :                 pnm_get(s, buf1, sizeof(buf1));
      94          84 :                 h = strtol(buf1, NULL, 10);
      95         336 :             } else if (!strcmp(buf1, "DEPTH")) {
      96          84 :                 pnm_get(s, buf1, sizeof(buf1));
      97          84 :                 depth = strtol(buf1, NULL, 10);
      98         252 :             } else if (!strcmp(buf1, "MAXVAL")) {
      99          84 :                 pnm_get(s, buf1, sizeof(buf1));
     100          84 :                 maxval = strtol(buf1, NULL, 10);
     101         252 :             } else if (!strcmp(buf1, "TUPLTYPE") ||
     102             :                        /* libavcodec used to write invalid files */
     103          84 :                        !strcmp(buf1, "TUPLETYPE")) {
     104          84 :                 pnm_get(s, tuple_type, sizeof(tuple_type));
     105          84 :             } else if (!strcmp(buf1, "ENDHDR")) {
     106          84 :                 break;
     107             :             } else {
     108           0 :                 return AVERROR_INVALIDDATA;
     109             :             }
     110             :         }
     111             :         /* check that all tags are present */
     112         168 :         if (w <= 0 || h <= 0 || maxval <= 0 || maxval > UINT16_MAX || depth <= 0 || tuple_type[0] == '\0' ||
     113         168 :             av_image_check_size(w, h, 0, avctx) || s->bytestream >= s->bytestream_end)
     114           0 :             return AVERROR_INVALIDDATA;
     115             : 
     116          84 :         ret = ff_set_dimensions(avctx, w, h);
     117          84 :         if (ret < 0)
     118           0 :             return ret;
     119          84 :         s->maxval     = maxval;
     120          84 :         if (depth == 1) {
     121          42 :             if (maxval == 1) {
     122          14 :                 avctx->pix_fmt = AV_PIX_FMT_MONOBLACK;
     123          28 :             } else if (maxval < 256) {
     124          14 :                 avctx->pix_fmt = AV_PIX_FMT_GRAY8;
     125             :             } else {
     126          14 :                 avctx->pix_fmt = AV_PIX_FMT_GRAY16;
     127             :             }
     128          42 :         } else if (depth == 2) {
     129           0 :             if (maxval < 256) {
     130           0 :                 avctx->pix_fmt = AV_PIX_FMT_GRAY8A;
     131             :             } else {
     132           0 :                 avctx->pix_fmt = AV_PIX_FMT_YA16;
     133             :             }
     134          42 :         } else if (depth == 3) {
     135          28 :             if (maxval < 256) {
     136          14 :                 avctx->pix_fmt = AV_PIX_FMT_RGB24;
     137             :             } else {
     138          14 :                 avctx->pix_fmt = AV_PIX_FMT_RGB48;
     139             :             }
     140          14 :         } else if (depth == 4) {
     141          14 :             if (maxval < 256) {
     142          14 :                 avctx->pix_fmt = AV_PIX_FMT_RGBA;
     143             :             } else {
     144           0 :                 avctx->pix_fmt = AV_PIX_FMT_RGBA64;
     145             :             }
     146             :         } else {
     147           0 :             return AVERROR_INVALIDDATA;
     148             :         }
     149          84 :         return 0;
     150             :     } else {
     151           0 :         return AVERROR_INVALIDDATA;
     152             :     }
     153       15602 :     pnm_get(s, buf1, sizeof(buf1));
     154       15602 :     w = atoi(buf1);
     155       15602 :     pnm_get(s, buf1, sizeof(buf1));
     156       15602 :     h = atoi(buf1);
     157       15602 :     if(w <= 0 || h <= 0 || av_image_check_size(w, h, 0, avctx) || s->bytestream >= s->bytestream_end)
     158           0 :         return AVERROR_INVALIDDATA;
     159             : 
     160       15602 :     ret = ff_set_dimensions(avctx, w, h);
     161       15602 :     if (ret < 0)
     162           0 :         return ret;
     163             : 
     164       15602 :     if (avctx->pix_fmt != AV_PIX_FMT_MONOWHITE && avctx->pix_fmt != AV_PIX_FMT_MONOBLACK) {
     165       15223 :         pnm_get(s, buf1, sizeof(buf1));
     166       15223 :         s->maxval = atoi(buf1);
     167       15223 :         if (s->maxval <= 0 || s->maxval > UINT16_MAX) {
     168           0 :             av_log(avctx, AV_LOG_ERROR, "Invalid maxval: %d\n", s->maxval);
     169           0 :             s->maxval = 255;
     170             :         }
     171       30446 :         if (s->maxval >= 256) {
     172           0 :             if (avctx->pix_fmt == AV_PIX_FMT_GRAY8) {
     173           0 :                 avctx->pix_fmt = AV_PIX_FMT_GRAY16;
     174           0 :             } else if (avctx->pix_fmt == AV_PIX_FMT_RGB24) {
     175           0 :                 avctx->pix_fmt = AV_PIX_FMT_RGB48;
     176           0 :             } else if (avctx->pix_fmt == AV_PIX_FMT_YUV420P && s->maxval < 65536) {
     177           0 :                 if (s->maxval < 512)
     178           0 :                     avctx->pix_fmt = AV_PIX_FMT_YUV420P9;
     179           0 :                 else if (s->maxval < 1024)
     180           0 :                     avctx->pix_fmt = AV_PIX_FMT_YUV420P10;
     181             :                 else
     182           0 :                     avctx->pix_fmt = AV_PIX_FMT_YUV420P16;
     183             :             } else {
     184           0 :                 av_log(avctx, AV_LOG_ERROR, "Unsupported pixel format\n");
     185           0 :                 avctx->pix_fmt = AV_PIX_FMT_NONE;
     186           0 :                 return AVERROR_INVALIDDATA;
     187             :             }
     188             :         }
     189             :     }else
     190         379 :         s->maxval=1;
     191             :     /* more check if YUV420 */
     192       15602 :     if (av_pix_fmt_desc_get(avctx->pix_fmt)->flags & AV_PIX_FMT_FLAG_PLANAR) {
     193       10227 :         if ((avctx->width & 1) != 0)
     194           0 :             return AVERROR_INVALIDDATA;
     195       10227 :         h = (avctx->height * 2);
     196       10227 :         if ((h % 3) != 0)
     197           0 :             return AVERROR_INVALIDDATA;
     198       10227 :         h /= 3;
     199       10227 :         avctx->height = h;
     200             :     }
     201       15602 :     return 0;
     202             : }

Generated by: LCOV version 1.13