LCOV - code coverage report
Current view: top level - libavutil - imgutils.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 208 344 60.5 %
Date: 2018-05-20 11:54:08 Functions: 17 21 81.0 %

          Line data    Source code
       1             : /*
       2             :  * This file is part of FFmpeg.
       3             :  *
       4             :  * FFmpeg is free software; you can redistribute it and/or
       5             :  * modify it under the terms of the GNU Lesser General Public
       6             :  * License as published by the Free Software Foundation; either
       7             :  * version 2.1 of the License, or (at your option) any later version.
       8             :  *
       9             :  * FFmpeg is distributed in the hope that it will be useful,
      10             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      12             :  * Lesser General Public License for more details.
      13             :  *
      14             :  * You should have received a copy of the GNU Lesser General Public
      15             :  * License along with FFmpeg; if not, write to the Free Software
      16             :  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
      17             :  */
      18             : 
      19             : /**
      20             :  * @file
      21             :  * misc image utilities
      22             :  */
      23             : 
      24             : #include "avassert.h"
      25             : #include "common.h"
      26             : #include "imgutils.h"
      27             : #include "imgutils_internal.h"
      28             : #include "internal.h"
      29             : #include "intreadwrite.h"
      30             : #include "log.h"
      31             : #include "mathematics.h"
      32             : #include "pixdesc.h"
      33             : #include "rational.h"
      34             : 
      35      334244 : void av_image_fill_max_pixsteps(int max_pixsteps[4], int max_pixstep_comps[4],
      36             :                                 const AVPixFmtDescriptor *pixdesc)
      37             : {
      38             :     int i;
      39      334244 :     memset(max_pixsteps, 0, 4*sizeof(max_pixsteps[0]));
      40      334244 :     if (max_pixstep_comps)
      41      333779 :         memset(max_pixstep_comps, 0, 4*sizeof(max_pixstep_comps[0]));
      42             : 
      43     1671220 :     for (i = 0; i < 4; i++) {
      44     1336976 :         const AVComponentDescriptor *comp = &(pixdesc->comp[i]);
      45     1336976 :         if (comp->step > max_pixsteps[comp->plane]) {
      46      901215 :             max_pixsteps[comp->plane] = comp->step;
      47      901215 :             if (max_pixstep_comps)
      48      900078 :                 max_pixstep_comps[comp->plane] = i;
      49             :         }
      50             :     }
      51      334244 : }
      52             : 
      53             : static inline
      54     1237826 : int image_get_linesize(int width, int plane,
      55             :                        int max_step, int max_step_comp,
      56             :                        const AVPixFmtDescriptor *desc)
      57             : {
      58             :     int s, shifted_w, linesize;
      59             : 
      60     1237826 :     if (!desc)
      61           0 :         return AVERROR(EINVAL);
      62             : 
      63     1237826 :     if (width < 0)
      64           0 :         return AVERROR(EINVAL);
      65     1237826 :     s = (max_step_comp == 1 || max_step_comp == 2) ? desc->log2_chroma_w : 0;
      66     1237826 :     shifted_w = ((width + (1 << s) - 1)) >> s;
      67     1237826 :     if (shifted_w && max_step > INT_MAX / shifted_w)
      68           0 :         return AVERROR(EINVAL);
      69     1237826 :     linesize = max_step * shifted_w;
      70             : 
      71     1237826 :     if (desc->flags & AV_PIX_FMT_FLAG_BITSTREAM)
      72        6533 :         linesize = (linesize + 7) >> 3;
      73     1237826 :     return linesize;
      74             : }
      75             : 
      76      705949 : int av_image_get_linesize(enum AVPixelFormat pix_fmt, int width, int plane)
      77             : {
      78      705949 :     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
      79             :     int max_step     [4];       /* max pixel step for each plane */
      80             :     int max_step_comp[4];       /* the component for each plane which has the max pixel step */
      81             : 
      82      705949 :     if (!desc || desc->flags & AV_PIX_FMT_FLAG_HWACCEL)
      83      673519 :         return AVERROR(EINVAL);
      84             : 
      85       32430 :     av_image_fill_max_pixsteps(max_step, max_step_comp, desc);
      86       32430 :     return image_get_linesize(width, plane, max_step[plane], max_step_comp[plane], desc);
      87             : }
      88             : 
      89      301349 : int av_image_fill_linesizes(int linesizes[4], enum AVPixelFormat pix_fmt, int width)
      90             : {
      91             :     int i, ret;
      92      301349 :     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
      93             :     int max_step     [4];       /* max pixel step for each plane */
      94             :     int max_step_comp[4];       /* the component for each plane which has the max pixel step */
      95             : 
      96      301349 :     memset(linesizes, 0, 4*sizeof(linesizes[0]));
      97             : 
      98      301349 :     if (!desc || desc->flags & AV_PIX_FMT_FLAG_HWACCEL)
      99           0 :         return AVERROR(EINVAL);
     100             : 
     101      301349 :     av_image_fill_max_pixsteps(max_step, max_step_comp, desc);
     102     1506745 :     for (i = 0; i < 4; i++) {
     103     1205396 :         if ((ret = image_get_linesize(width, i, max_step[i], max_step_comp[i], desc)) < 0)
     104           0 :             return ret;
     105     1205396 :         linesizes[i] = ret;
     106             :     }
     107             : 
     108      301349 :     return 0;
     109             : }
     110             : 
     111      205722 : int av_image_fill_pointers(uint8_t *data[4], enum AVPixelFormat pix_fmt, int height,
     112             :                            uint8_t *ptr, const int linesizes[4])
     113             : {
     114      205722 :     int i, total_size, size[4] = { 0 }, has_plane[4] = { 0 };
     115             : 
     116      205722 :     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
     117      205722 :     memset(data     , 0, sizeof(data[0])*4);
     118             : 
     119      205722 :     if (!desc || desc->flags & AV_PIX_FMT_FLAG_HWACCEL)
     120           0 :         return AVERROR(EINVAL);
     121             : 
     122      205722 :     data[0] = ptr;
     123      205722 :     if (linesizes[0] > (INT_MAX - 1024) / height)
     124           0 :         return AVERROR(EINVAL);
     125      205722 :     size[0] = linesizes[0] * height;
     126             : 
     127      410350 :     if (desc->flags & AV_PIX_FMT_FLAG_PAL ||
     128      204628 :         desc->flags & FF_PSEUDOPAL) {
     129        1150 :         data[1] = ptr + size[0]; /* palette is stored here as 256 32 bits words */
     130        1150 :         return size[0] + 256 * 4;
     131             :     }
     132             : 
     133     1022860 :     for (i = 0; i < 4; i++)
     134      818288 :         has_plane[desc->comp[i].plane] = 1;
     135             : 
     136      204572 :     total_size = size[0];
     137      555701 :     for (i = 1; i < 4 && has_plane[i]; i++) {
     138      351129 :         int h, s = (i == 1 || i == 2) ? desc->log2_chroma_h : 0;
     139      351129 :         data[i] = data[i-1] + size[i-1];
     140      351129 :         h = (height + (1 << s) - 1) >> s;
     141      351129 :         if (linesizes[i] > INT_MAX / h)
     142           0 :             return AVERROR(EINVAL);
     143      351129 :         size[i] = h * linesizes[i];
     144      351129 :         if (total_size > INT_MAX - size[i])
     145           0 :             return AVERROR(EINVAL);
     146      351129 :         total_size += size[i];
     147             :     }
     148             : 
     149      204572 :     return total_size;
     150             : }
     151             : 
     152        6206 : int avpriv_set_systematic_pal2(uint32_t pal[256], enum AVPixelFormat pix_fmt)
     153             : {
     154             :     int i;
     155             : 
     156     1031998 :     for (i = 0; i < 256; i++) {
     157             :         int r, g, b;
     158             : 
     159     1027991 :         switch (pix_fmt) {
     160      123136 :         case AV_PIX_FMT_RGB8:
     161      123136 :             r = (i>>5    )*36;
     162      123136 :             g = ((i>>2)&7)*36;
     163      123136 :             b = (i&3     )*85;
     164      123136 :             break;
     165      254976 :         case AV_PIX_FMT_BGR8:
     166      254976 :             b = (i>>6    )*85;
     167      254976 :             g = ((i>>3)&7)*36;
     168      254976 :             r = (i&7     )*36;
     169      254976 :             break;
     170      109312 :         case AV_PIX_FMT_RGB4_BYTE:
     171      109312 :             r = (i>>3    )*255;
     172      109312 :             g = ((i>>1)&3)*85;
     173      109312 :             b = (i&1     )*255;
     174      109312 :             break;
     175       99328 :         case AV_PIX_FMT_BGR4_BYTE:
     176       99328 :             b = (i>>3    )*255;
     177       99328 :             g = ((i>>1)&3)*85;
     178       99328 :             r = (i&1     )*255;
     179       99328 :             break;
     180      439040 :         case AV_PIX_FMT_GRAY8:
     181      439040 :             r = b = g = i;
     182      439040 :             break;
     183        2199 :         default:
     184        2199 :             return AVERROR(EINVAL);
     185             :         }
     186     1025792 :         pal[i] = b + (g << 8) + (r << 16) + (0xFFU << 24);
     187             :     }
     188             : 
     189        4007 :     return 0;
     190             : }
     191             : 
     192          45 : int av_image_alloc(uint8_t *pointers[4], int linesizes[4],
     193             :                    int w, int h, enum AVPixelFormat pix_fmt, int align)
     194             : {
     195          45 :     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
     196             :     int i, ret;
     197             :     uint8_t *buf;
     198             : 
     199          45 :     if (!desc)
     200           0 :         return AVERROR(EINVAL);
     201             : 
     202          45 :     if ((ret = av_image_check_size(w, h, 0, NULL)) < 0)
     203           0 :         return ret;
     204          45 :     if ((ret = av_image_fill_linesizes(linesizes, pix_fmt, align>7 ? FFALIGN(w, 8) : w)) < 0)
     205           0 :         return ret;
     206             : 
     207         225 :     for (i = 0; i < 4; i++)
     208         180 :         linesizes[i] = FFALIGN(linesizes[i], align);
     209             : 
     210          45 :     if ((ret = av_image_fill_pointers(pointers, pix_fmt, h, NULL, linesizes)) < 0)
     211           0 :         return ret;
     212          45 :     buf = av_malloc(ret + align);
     213          45 :     if (!buf)
     214           0 :         return AVERROR(ENOMEM);
     215          45 :     if ((ret = av_image_fill_pointers(pointers, pix_fmt, h, buf, linesizes)) < 0) {
     216           0 :         av_free(buf);
     217           0 :         return ret;
     218             :     }
     219          45 :     if (desc->flags & AV_PIX_FMT_FLAG_PAL || (desc->flags & FF_PSEUDOPAL && pointers[1])) {
     220           1 :         avpriv_set_systematic_pal2((uint32_t*)pointers[1], pix_fmt);
     221           1 :         if (align < 4) {
     222           0 :             av_log(NULL, AV_LOG_ERROR, "Formats with a palette require a minimum alignment of 4\n");
     223           0 :             return AVERROR(EINVAL);
     224             :         }
     225             :     }
     226             : 
     227          90 :     if ((desc->flags & AV_PIX_FMT_FLAG_PAL ||
     228          47 :          desc->flags & FF_PSEUDOPAL) && pointers[1] &&
     229           1 :         pointers[1] - pointers[0] > linesizes[0] * h) {
     230             :         /* zero-initialize the padding before the palette */
     231           0 :         memset(pointers[0] + linesizes[0] * h, 0,
     232           0 :                pointers[1] - pointers[0] - linesizes[0] * h);
     233             :     }
     234             : 
     235          45 :     return ret;
     236             : }
     237             : 
     238             : typedef struct ImgUtils {
     239             :     const AVClass *class;
     240             :     int   log_offset;
     241             :     void *log_ctx;
     242             : } ImgUtils;
     243             : 
     244             : static const AVClass imgutils_class = {
     245             :     .class_name                = "IMGUTILS",
     246             :     .item_name                 = av_default_item_name,
     247             :     .option                    = NULL,
     248             :     .version                   = LIBAVUTIL_VERSION_INT,
     249             :     .log_level_offset_offset   = offsetof(ImgUtils, log_offset),
     250             :     .parent_log_context_offset = offsetof(ImgUtils, log_ctx),
     251             : };
     252             : 
     253      695210 : int av_image_check_size2(unsigned int w, unsigned int h, int64_t max_pixels, enum AVPixelFormat pix_fmt, int log_offset, void *log_ctx)
     254             : {
     255      695210 :     ImgUtils imgutils = {
     256             :         .class      = &imgutils_class,
     257             :         .log_offset = log_offset,
     258             :         .log_ctx    = log_ctx,
     259             :     };
     260      695210 :     int64_t stride = av_image_get_linesize(pix_fmt, w, 0);
     261      695210 :     if (stride <= 0)
     262      673519 :         stride = 8LL*w;
     263      695210 :     stride += 128*8;
     264             : 
     265      695210 :     if ((int)w<=0 || (int)h<=0 || stride >= INT_MAX || stride*(uint64_t)(h+128) >= INT_MAX) {
     266        2159 :         av_log(&imgutils, AV_LOG_ERROR, "Picture size %ux%u is invalid\n", w, h);
     267        2159 :         return AVERROR(EINVAL);
     268             :     }
     269             : 
     270      693051 :     if (max_pixels < INT64_MAX) {
     271      240162 :         if (w*(int64_t)h > max_pixels) {
     272           0 :             av_log(&imgutils, AV_LOG_ERROR,
     273             :                     "Picture size %ux%u exceeds specified max pixel count %"PRId64", see the documentation if you wish to increase it\n",
     274             :                     w, h, max_pixels);
     275           0 :             return AVERROR(EINVAL);
     276             :         }
     277             :     }
     278             : 
     279      693051 :     return 0;
     280             : }
     281             : 
     282      433368 : int av_image_check_size(unsigned int w, unsigned int h, int log_offset, void *log_ctx)
     283             : {
     284      433368 :     return av_image_check_size2(w, h, INT64_MAX, AV_PIX_FMT_NONE, log_offset, log_ctx);
     285             : }
     286             : 
     287      116516 : int av_image_check_sar(unsigned int w, unsigned int h, AVRational sar)
     288             : {
     289             :     int64_t scaled_dim;
     290             : 
     291      116516 :     if (sar.den <= 0 || sar.num < 0)
     292           5 :         return AVERROR(EINVAL);
     293             : 
     294      116511 :     if (!sar.num || sar.num == sar.den)
     295      111205 :         return 0;
     296             : 
     297        5306 :     if (sar.num < sar.den)
     298        1365 :         scaled_dim = av_rescale_rnd(w, sar.num, sar.den, AV_ROUND_ZERO);
     299             :     else
     300        3941 :         scaled_dim = av_rescale_rnd(h, sar.den, sar.num, AV_ROUND_ZERO);
     301             : 
     302        5306 :     if (scaled_dim > 0)
     303        5297 :         return 0;
     304             : 
     305           9 :     return AVERROR(EINVAL);
     306             : }
     307             : 
     308       20309 : static void image_copy_plane(uint8_t       *dst, ptrdiff_t dst_linesize,
     309             :                              const uint8_t *src, ptrdiff_t src_linesize,
     310             :                              ptrdiff_t bytewidth, int height)
     311             : {
     312       20309 :     if (!dst || !src)
     313           0 :         return;
     314       20309 :     av_assert0(abs(src_linesize) >= bytewidth);
     315       20309 :     av_assert0(abs(dst_linesize) >= bytewidth);
     316     4028184 :     for (;height > 0; height--) {
     317     4007875 :         memcpy(dst, src, bytewidth);
     318     4007875 :         dst += dst_linesize;
     319     4007875 :         src += src_linesize;
     320             :     }
     321             : }
     322             : 
     323           0 : static void image_copy_plane_uc_from(uint8_t       *dst, ptrdiff_t dst_linesize,
     324             :                                      const uint8_t *src, ptrdiff_t src_linesize,
     325             :                                      ptrdiff_t bytewidth, int height)
     326             : {
     327           0 :     int ret = -1;
     328             : 
     329             : #if ARCH_X86
     330           0 :     ret = ff_image_copy_plane_uc_from_x86(dst, dst_linesize, src, src_linesize,
     331             :                                           bytewidth, height);
     332             : #endif
     333             : 
     334           0 :     if (ret < 0)
     335           0 :         image_copy_plane(dst, dst_linesize, src, src_linesize, bytewidth, height);
     336           0 : }
     337             : 
     338        9350 : void av_image_copy_plane(uint8_t       *dst, int dst_linesize,
     339             :                          const uint8_t *src, int src_linesize,
     340             :                          int bytewidth, int height)
     341             : {
     342        9350 :     image_copy_plane(dst, dst_linesize, src, src_linesize, bytewidth, height);
     343        9350 : }
     344             : 
     345        4677 : static void image_copy(uint8_t *dst_data[4], const ptrdiff_t dst_linesizes[4],
     346             :                        const uint8_t *src_data[4], const ptrdiff_t src_linesizes[4],
     347             :                        enum AVPixelFormat pix_fmt, int width, int height,
     348             :                        void (*copy_plane)(uint8_t *, ptrdiff_t, const uint8_t *,
     349             :                                           ptrdiff_t, ptrdiff_t, int))
     350             : {
     351        4677 :     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
     352             : 
     353        4677 :     if (!desc || desc->flags & AV_PIX_FMT_FLAG_HWACCEL)
     354           0 :         return;
     355             : 
     356        9145 :     if (desc->flags & AV_PIX_FMT_FLAG_PAL ||
     357        4468 :         desc->flags & FF_PSEUDOPAL) {
     358         272 :         copy_plane(dst_data[0], dst_linesizes[0],
     359             :                    src_data[0], src_linesizes[0],
     360             :                    width, height);
     361             :         /* copy the palette */
     362         544 :         if ((desc->flags & AV_PIX_FMT_FLAG_PAL) || (dst_data[1] && src_data[1]))
     363         272 :             memcpy(dst_data[1], src_data[1], 4*256);
     364             :     } else {
     365        4405 :         int i, planes_nb = 0;
     366             : 
     367       18283 :         for (i = 0; i < desc->nb_components; i++)
     368       13878 :             planes_nb = FFMAX(planes_nb, desc->comp[i].plane + 1);
     369             : 
     370       15092 :         for (i = 0; i < planes_nb; i++) {
     371       10687 :             int h = height;
     372       10687 :             ptrdiff_t bwidth = av_image_get_linesize(pix_fmt, width, i);
     373       10687 :             if (bwidth < 0) {
     374           0 :                 av_log(NULL, AV_LOG_ERROR, "av_image_get_linesize failed\n");
     375           0 :                 return;
     376             :             }
     377       10687 :             if (i == 1 || i == 2) {
     378        6096 :                 h = AV_CEIL_RSHIFT(height, desc->log2_chroma_h);
     379             :             }
     380       21374 :             copy_plane(dst_data[i], dst_linesizes[i],
     381       21374 :                        src_data[i], src_linesizes[i],
     382             :                        bwidth, h);
     383             :         }
     384             :     }
     385             : }
     386             : 
     387        4677 : void av_image_copy(uint8_t *dst_data[4], int dst_linesizes[4],
     388             :                    const uint8_t *src_data[4], const int src_linesizes[4],
     389             :                    enum AVPixelFormat pix_fmt, int width, int height)
     390             : {
     391             :     ptrdiff_t dst_linesizes1[4], src_linesizes1[4];
     392             :     int i;
     393             : 
     394       23385 :     for (i = 0; i < 4; i++) {
     395       18708 :         dst_linesizes1[i] = dst_linesizes[i];
     396       18708 :         src_linesizes1[i] = src_linesizes[i];
     397             :     }
     398             : 
     399        4677 :     image_copy(dst_data, dst_linesizes1, src_data, src_linesizes1, pix_fmt,
     400             :                width, height, image_copy_plane);
     401        4677 : }
     402             : 
     403           0 : void av_image_copy_uc_from(uint8_t *dst_data[4], const ptrdiff_t dst_linesizes[4],
     404             :                            const uint8_t *src_data[4], const ptrdiff_t src_linesizes[4],
     405             :                            enum AVPixelFormat pix_fmt, int width, int height)
     406             : {
     407           0 :     image_copy(dst_data, dst_linesizes, src_data, src_linesizes, pix_fmt,
     408             :                width, height, image_copy_plane_uc_from);
     409           0 : }
     410             : 
     411      197641 : int av_image_fill_arrays(uint8_t *dst_data[4], int dst_linesize[4],
     412             :                          const uint8_t *src, enum AVPixelFormat pix_fmt,
     413             :                          int width, int height, int align)
     414             : {
     415             :     int ret, i;
     416             : 
     417      197641 :     ret = av_image_check_size(width, height, 0, NULL);
     418      197641 :     if (ret < 0)
     419           0 :         return ret;
     420             : 
     421      197641 :     ret = av_image_fill_linesizes(dst_linesize, pix_fmt, width);
     422      197641 :     if (ret < 0)
     423           0 :         return ret;
     424             : 
     425      988205 :     for (i = 0; i < 4; i++)
     426      790564 :         dst_linesize[i] = FFALIGN(dst_linesize[i], align);
     427             : 
     428      197641 :     return av_image_fill_pointers(dst_data, pix_fmt, height, (uint8_t *)src, dst_linesize);
     429             : }
     430             : 
     431      179784 : int av_image_get_buffer_size(enum AVPixelFormat pix_fmt,
     432             :                              int width, int height, int align)
     433             : {
     434             :     uint8_t *data[4];
     435             :     int linesize[4];
     436             :     int ret;
     437      179784 :     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
     438      179784 :     if (!desc)
     439           0 :         return AVERROR(EINVAL);
     440             : 
     441      179784 :     ret = av_image_check_size(width, height, 0, NULL);
     442      179784 :     if (ret < 0)
     443           0 :         return ret;
     444             : 
     445             :     // do not include palette for these pseudo-paletted formats
     446      179784 :     if (desc->flags & FF_PSEUDOPAL)
     447        2210 :         return FFALIGN(width, align) * height;
     448             : 
     449      177574 :     return av_image_fill_arrays(data, linesize, NULL, pix_fmt,
     450             :                                 width, height, align);
     451             : }
     452             : 
     453       77155 : int av_image_copy_to_buffer(uint8_t *dst, int dst_size,
     454             :                             const uint8_t * const src_data[4],
     455             :                             const int src_linesize[4],
     456             :                             enum AVPixelFormat pix_fmt,
     457             :                             int width, int height, int align)
     458             : {
     459       77155 :     int i, j, nb_planes = 0, linesize[4];
     460       77155 :     int size = av_image_get_buffer_size(pix_fmt, width, height, align);
     461       77155 :     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
     462             :     int ret;
     463             : 
     464       77155 :     if (size > dst_size || size < 0 || !desc)
     465           0 :         return AVERROR(EINVAL);
     466             : 
     467      308853 :     for (i = 0; i < desc->nb_components; i++)
     468      231698 :         nb_planes = FFMAX(desc->comp[i].plane, nb_planes);
     469             : 
     470       77155 :     nb_planes++;
     471             : 
     472       77155 :     ret = av_image_fill_linesizes(linesize, pix_fmt, width);
     473       77155 :     av_assert0(ret >= 0); // was checked previously
     474             : 
     475      285481 :     for (i = 0; i < nb_planes; i++) {
     476      208326 :         int h, shift = (i == 1 || i == 2) ? desc->log2_chroma_h : 0;
     477      208326 :         const uint8_t *src = src_data[i];
     478      208326 :         h = (height + (1 << shift) - 1) >> shift;
     479             : 
     480    46027866 :         for (j = 0; j < h; j++) {
     481    45819540 :             memcpy(dst, src, linesize[i]);
     482    45819540 :             dst += FFALIGN(linesize[i], align);
     483    45819540 :             src += src_linesize[i];
     484             :         }
     485             :     }
     486             : 
     487       77155 :     if (desc->flags & AV_PIX_FMT_FLAG_PAL) {
     488         286 :         uint32_t *d32 = (uint32_t *)dst;
     489             : 
     490       73502 :         for (i = 0; i<256; i++)
     491       73216 :             AV_WL32(d32 + i, AV_RN32(src_data[1] + 4*i));
     492             :     }
     493             : 
     494       77155 :     return size;
     495             : }
     496             : 
     497             : // Fill dst[0..dst_size] with the bytes in clear[0..clear_size]. The clear
     498             : // bytes are repeated until dst_size is reached. If dst_size is unaligned (i.e.
     499             : // dst_size%clear_size!=0), the remaining data will be filled with the beginning
     500             : // of the clear data only.
     501           0 : static void memset_bytes(uint8_t *dst, size_t dst_size, uint8_t *clear,
     502             :                          size_t clear_size)
     503             : {
     504           0 :     size_t pos = 0;
     505           0 :     int same = 1;
     506             :     int i;
     507             : 
     508           0 :     if (!clear_size)
     509           0 :         return;
     510             : 
     511             :     // Reduce to memset() if possible.
     512           0 :     for (i = 0; i < clear_size; i++) {
     513           0 :         if (clear[i] != clear[0]) {
     514           0 :             same = 0;
     515           0 :             break;
     516             :         }
     517             :     }
     518           0 :     if (same)
     519           0 :         clear_size = 1;
     520             : 
     521           0 :     if (clear_size == 1) {
     522           0 :         memset(dst, clear[0], dst_size);
     523           0 :         dst_size = 0;
     524           0 :     } else if (clear_size == 2) {
     525           0 :         uint16_t val = AV_RN16(clear);
     526           0 :         for (; dst_size >= 2; dst_size -= 2) {
     527           0 :             AV_WN16(dst, val);
     528           0 :             dst += 2;
     529             :         }
     530           0 :     } else if (clear_size == 4) {
     531           0 :         uint32_t val = AV_RN32(clear);
     532           0 :         for (; dst_size >= 4; dst_size -= 4) {
     533           0 :             AV_WN32(dst, val);
     534           0 :             dst += 4;
     535             :         }
     536           0 :     } else if (clear_size == 8) {
     537           0 :         uint32_t val = AV_RN64(clear);
     538           0 :         for (; dst_size >= 8; dst_size -= 8) {
     539           0 :             AV_WN64(dst, val);
     540           0 :             dst += 8;
     541             :         }
     542             :     }
     543             : 
     544           0 :     for (; dst_size; dst_size--)
     545           0 :         *dst++ = clear[pos++ % clear_size];
     546             : }
     547             : 
     548             : // Maximum size in bytes of a plane element (usually a pixel, or multiple pixels
     549             : // if it's a subsampled packed format).
     550             : #define MAX_BLOCK_SIZE 32
     551             : 
     552           0 : int av_image_fill_black(uint8_t *dst_data[4], const ptrdiff_t dst_linesize[4],
     553             :                         enum AVPixelFormat pix_fmt, enum AVColorRange range,
     554             :                         int width, int height)
     555             : {
     556           0 :     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
     557           0 :     int nb_planes = av_pix_fmt_count_planes(pix_fmt);
     558             :     // A pixel or a group of pixels on each plane, with a value that represents black.
     559             :     // Consider e.g. AV_PIX_FMT_UYVY422 for non-trivial cases.
     560           0 :     uint8_t clear_block[4][MAX_BLOCK_SIZE] = {{0}}; // clear padding with 0
     561           0 :     int clear_block_size[4] = {0};
     562           0 :     ptrdiff_t plane_line_bytes[4] = {0};
     563             :     int rgb, limited;
     564             :     int plane, c;
     565             : 
     566           0 :     if (!desc || nb_planes < 1 || nb_planes > 4 || desc->flags & AV_PIX_FMT_FLAG_HWACCEL)
     567           0 :         return AVERROR(EINVAL);
     568             : 
     569           0 :     rgb = !!(desc->flags & AV_PIX_FMT_FLAG_RGB);
     570           0 :     limited = !rgb && range != AVCOL_RANGE_JPEG;
     571             : 
     572           0 :     if (desc->flags & AV_PIX_FMT_FLAG_BITSTREAM) {
     573           0 :         ptrdiff_t bytewidth = av_image_get_linesize(pix_fmt, width, 0);
     574             :         uint8_t *data;
     575           0 :         int mono = pix_fmt == AV_PIX_FMT_MONOWHITE || pix_fmt == AV_PIX_FMT_MONOBLACK;
     576           0 :         int fill = pix_fmt == AV_PIX_FMT_MONOWHITE ? 0xFF : 0;
     577           0 :         if (nb_planes != 1 || !(rgb || mono) || bytewidth < 1)
     578           0 :             return AVERROR(EINVAL);
     579             : 
     580           0 :         if (!dst_data)
     581           0 :             return 0;
     582             : 
     583           0 :         data = dst_data[0];
     584             : 
     585             :         // (Bitstream + alpha will be handled incorrectly - it'll remain transparent.)
     586           0 :         for (;height > 0; height--) {
     587           0 :             memset(data, fill, bytewidth);
     588           0 :             data += dst_linesize[0];
     589             :         }
     590           0 :         return 0;
     591             :     }
     592             : 
     593           0 :     for (c = 0; c < desc->nb_components; c++) {
     594           0 :         const AVComponentDescriptor comp = desc->comp[c];
     595             : 
     596             :         // We try to operate on entire non-subsampled pixel groups (for
     597             :         // AV_PIX_FMT_UYVY422 this would mean two consecutive pixels).
     598           0 :         clear_block_size[comp.plane] = FFMAX(clear_block_size[comp.plane], comp.step);
     599             : 
     600           0 :         if (clear_block_size[comp.plane] > MAX_BLOCK_SIZE)
     601           0 :             return AVERROR(EINVAL);
     602             :     }
     603             : 
     604             :     // Create a byte array for clearing 1 pixel (sometimes several pixels).
     605           0 :     for (c = 0; c < desc->nb_components; c++) {
     606           0 :         const AVComponentDescriptor comp = desc->comp[c];
     607             :         // (Multiple pixels happen e.g. with AV_PIX_FMT_UYVY422.)
     608           0 :         int w = clear_block_size[comp.plane] / comp.step;
     609             :         uint8_t *c_data[4];
     610           0 :         const int c_linesize[4] = {0};
     611             :         uint16_t src_array[MAX_BLOCK_SIZE];
     612           0 :         uint16_t src = 0;
     613             :         int x;
     614             : 
     615           0 :         if (comp.depth > 16)
     616           0 :             return AVERROR(EINVAL);
     617           0 :         if (!rgb && comp.depth < 8)
     618           0 :             return AVERROR(EINVAL);
     619           0 :         if (w < 1)
     620           0 :             return AVERROR(EINVAL);
     621             : 
     622           0 :         if (c == 0 && limited) {
     623           0 :             src = 16 << (comp.depth - 8);
     624           0 :         } else if ((c == 1 || c == 2) && !rgb) {
     625           0 :             src = 128 << (comp.depth - 8);
     626           0 :         } else if (c == 3) {
     627             :             // (Assume even limited YUV uses full range alpha.)
     628           0 :             src = (1 << comp.depth) - 1;
     629             :         }
     630             : 
     631           0 :         for (x = 0; x < w; x++)
     632           0 :             src_array[x] = src;
     633             : 
     634           0 :         for (x = 0; x < 4; x++)
     635           0 :             c_data[x] = &clear_block[x][0];
     636             : 
     637           0 :         av_write_image_line(src_array, c_data, c_linesize, desc, 0, 0, c, w);
     638             :     }
     639             : 
     640           0 :     for (plane = 0; plane < nb_planes; plane++) {
     641           0 :         plane_line_bytes[plane] = av_image_get_linesize(pix_fmt, width, plane);
     642           0 :         if (plane_line_bytes[plane] < 0)
     643           0 :             return AVERROR(EINVAL);
     644             :     }
     645             : 
     646           0 :     if (!dst_data)
     647           0 :         return 0;
     648             : 
     649           0 :     for (plane = 0; plane < nb_planes; plane++) {
     650           0 :         size_t bytewidth = plane_line_bytes[plane];
     651           0 :         uint8_t *data = dst_data[plane];
     652           0 :         int chroma_div = plane == 1 || plane == 2 ? desc->log2_chroma_h : 0;
     653           0 :         int plane_h = ((height + ( 1 << chroma_div) - 1)) >> chroma_div;
     654             : 
     655           0 :         for (; plane_h > 0; plane_h--) {
     656           0 :             memset_bytes(data, bytewidth, &clear_block[plane][0], clear_block_size[plane]);
     657           0 :             data += dst_linesize[plane];
     658             :         }
     659             :     }
     660             : 
     661           0 :     return 0;
     662             : }

Generated by: LCOV version 1.13