LCOV - code coverage report
Current view: top level - libavutil - imgutils.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 207 343 60.3 %
Date: 2017-10-20 23:03:07 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      305858 : void av_image_fill_max_pixsteps(int max_pixsteps[4], int max_pixstep_comps[4],
      36             :                                 const AVPixFmtDescriptor *pixdesc)
      37             : {
      38             :     int i;
      39      305858 :     memset(max_pixsteps, 0, 4*sizeof(max_pixsteps[0]));
      40      305858 :     if (max_pixstep_comps)
      41      305513 :         memset(max_pixstep_comps, 0, 4*sizeof(max_pixstep_comps[0]));
      42             : 
      43     1529290 :     for (i = 0; i < 4; i++) {
      44     1223432 :         const AVComponentDescriptor *comp = &(pixdesc->comp[i]);
      45     1223432 :         if (comp->step > max_pixsteps[comp->plane]) {
      46      827675 :             max_pixsteps[comp->plane] = comp->step;
      47      827675 :             if (max_pixstep_comps)
      48      826803 :                 max_pixstep_comps[comp->plane] = i;
      49             :         }
      50             :     }
      51      305858 : }
      52             : 
      53             : static inline
      54     1189922 : 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     1189922 :     if (!desc)
      61           0 :         return AVERROR(EINVAL);
      62             : 
      63     1189922 :     if (width < 0)
      64           0 :         return AVERROR(EINVAL);
      65     1189922 :     s = (max_step_comp == 1 || max_step_comp == 2) ? desc->log2_chroma_w : 0;
      66     1189922 :     shifted_w = ((width + (1 << s) - 1)) >> s;
      67     1189922 :     if (shifted_w && max_step > INT_MAX / shifted_w)
      68           0 :         return AVERROR(EINVAL);
      69     1189922 :     linesize = max_step * shifted_w;
      70             : 
      71     1189922 :     if (desc->flags & AV_PIX_FMT_FLAG_BITSTREAM)
      72        6320 :         linesize = (linesize + 7) >> 3;
      73     1189922 :     return linesize;
      74             : }
      75             : 
      76      677026 : int av_image_get_linesize(enum AVPixelFormat pix_fmt, int width, int plane)
      77             : {
      78      677026 :     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      677026 :     if (!desc || desc->flags & AV_PIX_FMT_FLAG_HWACCEL)
      83      666316 :         return AVERROR(EINVAL);
      84             : 
      85       10710 :     av_image_fill_max_pixsteps(max_step, max_step_comp, desc);
      86       10710 :     return image_get_linesize(width, plane, max_step[plane], max_step_comp[plane], desc);
      87             : }
      88             : 
      89      294803 : int av_image_fill_linesizes(int linesizes[4], enum AVPixelFormat pix_fmt, int width)
      90             : {
      91             :     int i, ret;
      92      294803 :     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      294803 :     memset(linesizes, 0, 4*sizeof(linesizes[0]));
      97             : 
      98      294803 :     if (!desc || desc->flags & AV_PIX_FMT_FLAG_HWACCEL)
      99           0 :         return AVERROR(EINVAL);
     100             : 
     101      294803 :     av_image_fill_max_pixsteps(max_step, max_step_comp, desc);
     102     1474015 :     for (i = 0; i < 4; i++) {
     103     1179212 :         if ((ret = image_get_linesize(width, i, max_step[i], max_step_comp[i], desc)) < 0)
     104           0 :             return ret;
     105     1179212 :         linesizes[i] = ret;
     106             :     }
     107             : 
     108      294803 :     return 0;
     109             : }
     110             : 
     111      202512 : 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      202512 :     int i, total_size, size[4] = { 0 }, has_plane[4] = { 0 };
     115             : 
     116      202512 :     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
     117      202512 :     memset(data     , 0, sizeof(data[0])*4);
     118             : 
     119      202512 :     if (!desc || desc->flags & AV_PIX_FMT_FLAG_HWACCEL)
     120           0 :         return AVERROR(EINVAL);
     121             : 
     122      202512 :     data[0] = ptr;
     123      202512 :     if (linesizes[0] > (INT_MAX - 1024) / height)
     124           0 :         return AVERROR(EINVAL);
     125      202512 :     size[0] = linesizes[0] * height;
     126             : 
     127      403930 :     if (desc->flags & AV_PIX_FMT_FLAG_PAL ||
     128      201418 :         desc->flags & AV_PIX_FMT_FLAG_PSEUDOPAL) {
     129        1148 :         data[1] = ptr + size[0]; /* palette is stored here as 256 32 bits words */
     130        1148 :         return size[0] + 256 * 4;
     131             :     }
     132             : 
     133     1006820 :     for (i = 0; i < 4; i++)
     134      805456 :         has_plane[desc->comp[i].plane] = 1;
     135             : 
     136      201364 :     total_size = size[0];
     137      546586 :     for (i = 1; i < 4 && has_plane[i]; i++) {
     138      345222 :         int h, s = (i == 1 || i == 2) ? desc->log2_chroma_h : 0;
     139      345222 :         data[i] = data[i-1] + size[i-1];
     140      345222 :         h = (height + (1 << s) - 1) >> s;
     141      345222 :         if (linesizes[i] > INT_MAX / h)
     142           0 :             return AVERROR(EINVAL);
     143      345222 :         size[i] = h * linesizes[i];
     144      345222 :         if (total_size > INT_MAX - size[i])
     145           0 :             return AVERROR(EINVAL);
     146      345222 :         total_size += size[i];
     147             :     }
     148             : 
     149      201364 :     return total_size;
     150             : }
     151             : 
     152        6083 : int avpriv_set_systematic_pal2(uint32_t pal[256], enum AVPixelFormat pix_fmt)
     153             : {
     154             :     int i;
     155             : 
     156     1017027 :     for (i = 0; i < 256; i++) {
     157             :         int r, g, b;
     158             : 
     159     1013078 :         switch (pix_fmt) {
     160      119040 :         case AV_PIX_FMT_RGB8:
     161      119040 :             r = (i>>5    )*36;
     162      119040 :             g = ((i>>2)&7)*36;
     163      119040 :             b = (i&3     )*85;
     164      119040 :             break;
     165      254208 :         case AV_PIX_FMT_BGR8:
     166      254208 :             b = (i>>6    )*85;
     167      254208 :             g = ((i>>3)&7)*36;
     168      254208 :             r = (i&7     )*36;
     169      254208 :             break;
     170      105216 :         case AV_PIX_FMT_RGB4_BYTE:
     171      105216 :             r = (i>>3    )*255;
     172      105216 :             g = ((i>>1)&3)*85;
     173      105216 :             b = (i&1     )*255;
     174      105216 :             break;
     175       98560 :         case AV_PIX_FMT_BGR4_BYTE:
     176       98560 :             b = (i>>3    )*255;
     177       98560 :             g = ((i>>1)&3)*85;
     178       98560 :             r = (i&1     )*255;
     179       98560 :             break;
     180      433920 :         case AV_PIX_FMT_GRAY8:
     181      433920 :             r = b = g = i;
     182      433920 :             break;
     183        2134 :         default:
     184        2134 :             return AVERROR(EINVAL);
     185             :         }
     186     1010944 :         pal[i] = b + (g << 8) + (r << 16) + (0xFFU << 24);
     187             :     }
     188             : 
     189        3949 :     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 & AV_PIX_FMT_FLAG_PSEUDOPAL) {
     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          46 :          desc->flags & AV_PIX_FMT_FLAG_PSEUDOPAL) &&
     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             :     .version    = LIBAVUTIL_VERSION_INT,
     248             :     .log_level_offset_offset   = offsetof(ImgUtils, log_offset),
     249             :     .parent_log_context_offset = offsetof(ImgUtils, log_ctx),
     250             : };
     251             : 
     252      666319 : 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)
     253             : {
     254      666319 :     ImgUtils imgutils = {
     255             :         .class      = &imgutils_class,
     256             :         .log_offset = log_offset,
     257             :         .log_ctx    = log_ctx,
     258             :     };
     259      666319 :     int64_t stride = av_image_get_linesize(pix_fmt, w, 0);
     260      666319 :     if (stride <= 0)
     261      666316 :         stride = 8LL*w;
     262      666319 :     stride += 128*8;
     263             : 
     264      666319 :     if ((int)w<=0 || (int)h<=0 || stride >= INT_MAX || stride*(uint64_t)(h+128) >= INT_MAX) {
     265        2159 :         av_log(&imgutils, AV_LOG_ERROR, "Picture size %ux%u is invalid\n", w, h);
     266        2159 :         return AVERROR(EINVAL);
     267             :     }
     268             : 
     269      664160 :     if (max_pixels < INT64_MAX) {
     270      235043 :         if (w*(int64_t)h > max_pixels) {
     271           0 :             av_log(&imgutils, AV_LOG_ERROR,
     272             :                     "Picture size %ux%u exceeds specified max pixel count %"PRId64", see the documentation if you wish to increase it\n",
     273             :                     w, h, max_pixels);
     274           0 :             return AVERROR(EINVAL);
     275             :         }
     276             :     }
     277             : 
     278      664160 :     return 0;
     279             : }
     280             : 
     281      431276 : int av_image_check_size(unsigned int w, unsigned int h, int log_offset, void *log_ctx)
     282             : {
     283      431276 :     return av_image_check_size2(w, h, INT64_MAX, AV_PIX_FMT_NONE, log_offset, log_ctx);
     284             : }
     285             : 
     286      129640 : int av_image_check_sar(unsigned int w, unsigned int h, AVRational sar)
     287             : {
     288             :     int64_t scaled_dim;
     289             : 
     290      129640 :     if (sar.den <= 0 || sar.num < 0)
     291           5 :         return AVERROR(EINVAL);
     292             : 
     293      129635 :     if (!sar.num || sar.num == sar.den)
     294      124803 :         return 0;
     295             : 
     296        4832 :     if (sar.num < sar.den)
     297         877 :         scaled_dim = av_rescale_rnd(w, sar.num, sar.den, AV_ROUND_ZERO);
     298             :     else
     299        3955 :         scaled_dim = av_rescale_rnd(h, sar.den, sar.num, AV_ROUND_ZERO);
     300             : 
     301        4832 :     if (scaled_dim > 0)
     302        4823 :         return 0;
     303             : 
     304           9 :     return AVERROR(EINVAL);
     305             : }
     306             : 
     307       20126 : static void image_copy_plane(uint8_t       *dst, ptrdiff_t dst_linesize,
     308             :                              const uint8_t *src, ptrdiff_t src_linesize,
     309             :                              ptrdiff_t bytewidth, int height)
     310             : {
     311       20126 :     if (!dst || !src)
     312           0 :         return;
     313       20126 :     av_assert0(abs(src_linesize) >= bytewidth);
     314       20126 :     av_assert0(abs(dst_linesize) >= bytewidth);
     315     3979233 :     for (;height > 0; height--) {
     316     3959107 :         memcpy(dst, src, bytewidth);
     317     3959107 :         dst += dst_linesize;
     318     3959107 :         src += src_linesize;
     319             :     }
     320             : }
     321             : 
     322           0 : static void image_copy_plane_uc_from(uint8_t       *dst, ptrdiff_t dst_linesize,
     323             :                                      const uint8_t *src, ptrdiff_t src_linesize,
     324             :                                      ptrdiff_t bytewidth, int height)
     325             : {
     326           0 :     int ret = -1;
     327             : 
     328             : #if ARCH_X86
     329           0 :     ret = ff_image_copy_plane_uc_from_x86(dst, dst_linesize, src, src_linesize,
     330             :                                           bytewidth, height);
     331             : #endif
     332             : 
     333           0 :     if (ret < 0)
     334           0 :         image_copy_plane(dst, dst_linesize, src, src_linesize, bytewidth, height);
     335           0 : }
     336             : 
     337        9191 : void av_image_copy_plane(uint8_t       *dst, int dst_linesize,
     338             :                          const uint8_t *src, int src_linesize,
     339             :                          int bytewidth, int height)
     340             : {
     341        9191 :     image_copy_plane(dst, dst_linesize, src, src_linesize, bytewidth, height);
     342        9191 : }
     343             : 
     344        4667 : static void image_copy(uint8_t *dst_data[4], const ptrdiff_t dst_linesizes[4],
     345             :                        const uint8_t *src_data[4], const ptrdiff_t src_linesizes[4],
     346             :                        enum AVPixelFormat pix_fmt, int width, int height,
     347             :                        void (*copy_plane)(uint8_t *, ptrdiff_t, const uint8_t *,
     348             :                                           ptrdiff_t, ptrdiff_t, int))
     349             : {
     350        4667 :     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
     351             : 
     352        4667 :     if (!desc || desc->flags & AV_PIX_FMT_FLAG_HWACCEL)
     353           0 :         return;
     354             : 
     355        9125 :     if (desc->flags & AV_PIX_FMT_FLAG_PAL ||
     356        4458 :         desc->flags & AV_PIX_FMT_FLAG_PSEUDOPAL) {
     357         272 :         copy_plane(dst_data[0], dst_linesizes[0],
     358             :                    src_data[0], src_linesizes[0],
     359             :                    width, height);
     360             :         /* copy the palette */
     361         272 :         memcpy(dst_data[1], src_data[1], 4*256);
     362             :     } else {
     363        4395 :         int i, planes_nb = 0;
     364             : 
     365       18247 :         for (i = 0; i < desc->nb_components; i++)
     366       13852 :             planes_nb = FFMAX(planes_nb, desc->comp[i].plane + 1);
     367             : 
     368       15058 :         for (i = 0; i < planes_nb; i++) {
     369       10663 :             int h = height;
     370       10663 :             ptrdiff_t bwidth = av_image_get_linesize(pix_fmt, width, i);
     371       10663 :             if (bwidth < 0) {
     372           0 :                 av_log(NULL, AV_LOG_ERROR, "av_image_get_linesize failed\n");
     373           0 :                 return;
     374             :             }
     375       10663 :             if (i == 1 || i == 2) {
     376        6082 :                 h = AV_CEIL_RSHIFT(height, desc->log2_chroma_h);
     377             :             }
     378       21326 :             copy_plane(dst_data[i], dst_linesizes[i],
     379       21326 :                        src_data[i], src_linesizes[i],
     380             :                        bwidth, h);
     381             :         }
     382             :     }
     383             : }
     384             : 
     385        4667 : void av_image_copy(uint8_t *dst_data[4], int dst_linesizes[4],
     386             :                    const uint8_t *src_data[4], const int src_linesizes[4],
     387             :                    enum AVPixelFormat pix_fmt, int width, int height)
     388             : {
     389             :     ptrdiff_t dst_linesizes1[4], src_linesizes1[4];
     390             :     int i;
     391             : 
     392       23335 :     for (i = 0; i < 4; i++) {
     393       18668 :         dst_linesizes1[i] = dst_linesizes[i];
     394       18668 :         src_linesizes1[i] = src_linesizes[i];
     395             :     }
     396             : 
     397        4667 :     image_copy(dst_data, dst_linesizes1, src_data, src_linesizes1, pix_fmt,
     398             :                width, height, image_copy_plane);
     399        4667 : }
     400             : 
     401           0 : void av_image_copy_uc_from(uint8_t *dst_data[4], const ptrdiff_t dst_linesizes[4],
     402             :                            const uint8_t *src_data[4], const ptrdiff_t src_linesizes[4],
     403             :                            enum AVPixelFormat pix_fmt, int width, int height)
     404             : {
     405           0 :     image_copy(dst_data, dst_linesizes, src_data, src_linesizes, pix_fmt,
     406             :                width, height, image_copy_plane_uc_from);
     407           0 : }
     408             : 
     409      194821 : int av_image_fill_arrays(uint8_t *dst_data[4], int dst_linesize[4],
     410             :                          const uint8_t *src, enum AVPixelFormat pix_fmt,
     411             :                          int width, int height, int align)
     412             : {
     413             :     int ret, i;
     414             : 
     415      194821 :     ret = av_image_check_size(width, height, 0, NULL);
     416      194821 :     if (ret < 0)
     417           0 :         return ret;
     418             : 
     419      194821 :     ret = av_image_fill_linesizes(dst_linesize, pix_fmt, width);
     420      194821 :     if (ret < 0)
     421           0 :         return ret;
     422             : 
     423      974105 :     for (i = 0; i < 4; i++)
     424      779284 :         dst_linesize[i] = FFALIGN(dst_linesize[i], align);
     425             : 
     426      194821 :     return av_image_fill_pointers(dst_data, pix_fmt, height, (uint8_t *)src, dst_linesize);
     427             : }
     428             : 
     429      177089 : int av_image_get_buffer_size(enum AVPixelFormat pix_fmt,
     430             :                              int width, int height, int align)
     431             : {
     432             :     uint8_t *data[4];
     433             :     int linesize[4];
     434             :     int ret;
     435      177089 :     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
     436      177089 :     if (!desc)
     437           0 :         return AVERROR(EINVAL);
     438             : 
     439      177089 :     ret = av_image_check_size(width, height, 0, NULL);
     440      177089 :     if (ret < 0)
     441           0 :         return ret;
     442             : 
     443             :     // do not include palette for these pseudo-paletted formats
     444      177089 :     if (desc->flags & AV_PIX_FMT_FLAG_PSEUDOPAL)
     445        2194 :         return FFALIGN(width, align) * height;
     446             : 
     447      174895 :     return av_image_fill_arrays(data, linesize, NULL, pix_fmt,
     448             :                                 width, height, align);
     449             : }
     450             : 
     451       75878 : int av_image_copy_to_buffer(uint8_t *dst, int dst_size,
     452             :                             const uint8_t * const src_data[4],
     453             :                             const int src_linesize[4],
     454             :                             enum AVPixelFormat pix_fmt,
     455             :                             int width, int height, int align)
     456             : {
     457       75878 :     int i, j, nb_planes = 0, linesize[4];
     458       75878 :     int size = av_image_get_buffer_size(pix_fmt, width, height, align);
     459       75878 :     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
     460             :     int ret;
     461             : 
     462       75878 :     if (size > dst_size || size < 0 || !desc)
     463           0 :         return AVERROR(EINVAL);
     464             : 
     465      303805 :     for (i = 0; i < desc->nb_components; i++)
     466      227927 :         nb_planes = FFMAX(desc->comp[i].plane, nb_planes);
     467             : 
     468       75878 :     nb_planes++;
     469             : 
     470       75878 :     ret = av_image_fill_linesizes(linesize, pix_fmt, width);
     471       75878 :     av_assert0(ret >= 0); // was checked previously
     472             : 
     473      280631 :     for (i = 0; i < nb_planes; i++) {
     474      204753 :         int h, shift = (i == 1 || i == 2) ? desc->log2_chroma_h : 0;
     475      204753 :         const uint8_t *src = src_data[i];
     476      204753 :         h = (height + (1 << shift) - 1) >> shift;
     477             : 
     478    44978535 :         for (j = 0; j < h; j++) {
     479    44773782 :             memcpy(dst, src, linesize[i]);
     480    44773782 :             dst += FFALIGN(linesize[i], align);
     481    44773782 :             src += src_linesize[i];
     482             :         }
     483             :     }
     484             : 
     485       75878 :     if (desc->flags & AV_PIX_FMT_FLAG_PAL) {
     486         286 :         uint32_t *d32 = (uint32_t *)dst;
     487             : 
     488       73502 :         for (i = 0; i<256; i++)
     489       73216 :             AV_WL32(d32 + i, AV_RN32(src_data[1] + 4*i));
     490             :     }
     491             : 
     492       75878 :     return size;
     493             : }
     494             : 
     495             : // Fill dst[0..dst_size] with the bytes in clear[0..clear_size]. The clear
     496             : // bytes are repeated until dst_size is reached. If dst_size is unaligned (i.e.
     497             : // dst_size%clear_size!=0), the remaining data will be filled with the beginning
     498             : // of the clear data only.
     499           0 : static void memset_bytes(uint8_t *dst, size_t dst_size, uint8_t *clear,
     500             :                          size_t clear_size)
     501             : {
     502           0 :     size_t pos = 0;
     503           0 :     int same = 1;
     504             :     int i;
     505             : 
     506           0 :     if (!clear_size)
     507           0 :         return;
     508             : 
     509             :     // Reduce to memset() if possible.
     510           0 :     for (i = 0; i < clear_size; i++) {
     511           0 :         if (clear[i] != clear[0]) {
     512           0 :             same = 0;
     513           0 :             break;
     514             :         }
     515             :     }
     516           0 :     if (same)
     517           0 :         clear_size = 1;
     518             : 
     519           0 :     if (clear_size == 1) {
     520           0 :         memset(dst, clear[0], dst_size);
     521           0 :         dst_size = 0;
     522           0 :     } else if (clear_size == 2) {
     523           0 :         uint16_t val = AV_RN16(clear);
     524           0 :         for (; dst_size >= 2; dst_size -= 2) {
     525           0 :             AV_WN16(dst, val);
     526           0 :             dst += 2;
     527             :         }
     528           0 :     } else if (clear_size == 4) {
     529           0 :         uint32_t val = AV_RN32(clear);
     530           0 :         for (; dst_size >= 4; dst_size -= 4) {
     531           0 :             AV_WN32(dst, val);
     532           0 :             dst += 4;
     533             :         }
     534           0 :     } else if (clear_size == 8) {
     535           0 :         uint32_t val = AV_RN64(clear);
     536           0 :         for (; dst_size >= 8; dst_size -= 8) {
     537           0 :             AV_WN64(dst, val);
     538           0 :             dst += 8;
     539             :         }
     540             :     }
     541             : 
     542           0 :     for (; dst_size; dst_size--)
     543           0 :         *dst++ = clear[pos++ % clear_size];
     544             : }
     545             : 
     546             : // Maximum size in bytes of a plane element (usually a pixel, or multiple pixels
     547             : // if it's a subsampled packed format).
     548             : #define MAX_BLOCK_SIZE 32
     549             : 
     550           0 : int av_image_fill_black(uint8_t *dst_data[4], const ptrdiff_t dst_linesize[4],
     551             :                         enum AVPixelFormat pix_fmt, enum AVColorRange range,
     552             :                         int width, int height)
     553             : {
     554           0 :     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
     555           0 :     int nb_planes = av_pix_fmt_count_planes(pix_fmt);
     556             :     // A pixel or a group of pixels on each plane, with a value that represents black.
     557             :     // Consider e.g. AV_PIX_FMT_UYVY422 for non-trivial cases.
     558           0 :     uint8_t clear_block[4][MAX_BLOCK_SIZE] = {{0}}; // clear padding with 0
     559           0 :     int clear_block_size[4] = {0};
     560           0 :     ptrdiff_t plane_line_bytes[4] = {0};
     561             :     int rgb, limited;
     562             :     int plane, c;
     563             : 
     564           0 :     if (!desc || nb_planes < 1 || nb_planes > 4 || desc->flags & AV_PIX_FMT_FLAG_HWACCEL)
     565           0 :         return AVERROR(EINVAL);
     566             : 
     567           0 :     rgb = !!(desc->flags & AV_PIX_FMT_FLAG_RGB);
     568           0 :     limited = !rgb && range != AVCOL_RANGE_JPEG;
     569             : 
     570           0 :     if (desc->flags & AV_PIX_FMT_FLAG_BITSTREAM) {
     571           0 :         ptrdiff_t bytewidth = av_image_get_linesize(pix_fmt, width, 0);
     572             :         uint8_t *data;
     573           0 :         int mono = pix_fmt == AV_PIX_FMT_MONOWHITE || pix_fmt == AV_PIX_FMT_MONOBLACK;
     574           0 :         int fill = pix_fmt == AV_PIX_FMT_MONOWHITE ? 0xFF : 0;
     575           0 :         if (nb_planes != 1 || !(rgb || mono) || bytewidth < 1)
     576           0 :             return AVERROR(EINVAL);
     577             : 
     578           0 :         if (!dst_data)
     579           0 :             return 0;
     580             : 
     581           0 :         data = dst_data[0];
     582             : 
     583             :         // (Bitstream + alpha will be handled incorrectly - it'll remain transparent.)
     584           0 :         for (;height > 0; height--) {
     585           0 :             memset(data, fill, bytewidth);
     586           0 :             data += dst_linesize[0];
     587             :         }
     588           0 :         return 0;
     589             :     }
     590             : 
     591           0 :     for (c = 0; c < desc->nb_components; c++) {
     592           0 :         const AVComponentDescriptor comp = desc->comp[c];
     593             : 
     594             :         // We try to operate on entire non-subsampled pixel groups (for
     595             :         // AV_PIX_FMT_UYVY422 this would mean two consecutive pixels).
     596           0 :         clear_block_size[comp.plane] = FFMAX(clear_block_size[comp.plane], comp.step);
     597             : 
     598           0 :         if (clear_block_size[comp.plane] > MAX_BLOCK_SIZE)
     599           0 :             return AVERROR(EINVAL);
     600             :     }
     601             : 
     602             :     // Create a byte array for clearing 1 pixel (sometimes several pixels).
     603           0 :     for (c = 0; c < desc->nb_components; c++) {
     604           0 :         const AVComponentDescriptor comp = desc->comp[c];
     605             :         // (Multiple pixels happen e.g. with AV_PIX_FMT_UYVY422.)
     606           0 :         int w = clear_block_size[comp.plane] / comp.step;
     607             :         uint8_t *c_data[4];
     608           0 :         const int c_linesize[4] = {0};
     609             :         uint16_t src_array[MAX_BLOCK_SIZE];
     610           0 :         uint16_t src = 0;
     611             :         int x;
     612             : 
     613           0 :         if (comp.depth > 16)
     614           0 :             return AVERROR(EINVAL);
     615           0 :         if (!rgb && comp.depth < 8)
     616           0 :             return AVERROR(EINVAL);
     617           0 :         if (w < 1)
     618           0 :             return AVERROR(EINVAL);
     619             : 
     620           0 :         if (c == 0 && limited) {
     621           0 :             src = 16 << (comp.depth - 8);
     622           0 :         } else if ((c == 1 || c == 2) && !rgb) {
     623           0 :             src = 128 << (comp.depth - 8);
     624           0 :         } else if (c == 3) {
     625             :             // (Assume even limited YUV uses full range alpha.)
     626           0 :             src = (1 << comp.depth) - 1;
     627             :         }
     628             : 
     629           0 :         for (x = 0; x < w; x++)
     630           0 :             src_array[x] = src;
     631             : 
     632           0 :         for (x = 0; x < 4; x++)
     633           0 :             c_data[x] = &clear_block[x][0];
     634             : 
     635           0 :         av_write_image_line(src_array, c_data, c_linesize, desc, 0, 0, c, w);
     636             :     }
     637             : 
     638           0 :     for (plane = 0; plane < nb_planes; plane++) {
     639           0 :         plane_line_bytes[plane] = av_image_get_linesize(pix_fmt, width, plane);
     640           0 :         if (plane_line_bytes[plane] < 0)
     641           0 :             return AVERROR(EINVAL);
     642             :     }
     643             : 
     644           0 :     if (!dst_data)
     645           0 :         return 0;
     646             : 
     647           0 :     for (plane = 0; plane < nb_planes; plane++) {
     648           0 :         size_t bytewidth = plane_line_bytes[plane];
     649           0 :         uint8_t *data = dst_data[plane];
     650           0 :         int chroma_div = plane == 1 || plane == 2 ? desc->log2_chroma_h : 0;
     651           0 :         int plane_h = ((height + ( 1 << chroma_div) - 1)) >> chroma_div;
     652             : 
     653           0 :         for (; plane_h > 0; plane_h--) {
     654           0 :             memset_bytes(data, bytewidth, &clear_block[plane][0], clear_block_size[plane]);
     655           0 :             data += dst_linesize[plane];
     656             :         }
     657             :     }
     658             : 
     659           0 :     return 0;
     660             : }

Generated by: LCOV version 1.13