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-12-14 19:11:59 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      329036 : void av_image_fill_max_pixsteps(int max_pixsteps[4], int max_pixstep_comps[4],
      36             :                                 const AVPixFmtDescriptor *pixdesc)
      37             : {
      38             :     int i;
      39      329036 :     memset(max_pixsteps, 0, 4*sizeof(max_pixsteps[0]));
      40      329036 :     if (max_pixstep_comps)
      41      328691 :         memset(max_pixstep_comps, 0, 4*sizeof(max_pixstep_comps[0]));
      42             : 
      43     1645180 :     for (i = 0; i < 4; i++) {
      44     1316144 :         const AVComponentDescriptor *comp = &(pixdesc->comp[i]);
      45     1316144 :         if (comp->step > max_pixsteps[comp->plane]) {
      46      887990 :             max_pixsteps[comp->plane] = comp->step;
      47      887990 :             if (max_pixstep_comps)
      48      887118 :                 max_pixstep_comps[comp->plane] = i;
      49             :         }
      50             :     }
      51      329036 : }
      52             : 
      53             : static inline
      54     1220969 : 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     1220969 :     if (!desc)
      61           0 :         return AVERROR(EINVAL);
      62             : 
      63     1220969 :     if (width < 0)
      64           0 :         return AVERROR(EINVAL);
      65     1220969 :     s = (max_step_comp == 1 || max_step_comp == 2) ? desc->log2_chroma_w : 0;
      66     1220969 :     shifted_w = ((width + (1 << s) - 1)) >> s;
      67     1220969 :     if (shifted_w && max_step > INT_MAX / shifted_w)
      68           0 :         return AVERROR(EINVAL);
      69     1220969 :     linesize = max_step * shifted_w;
      70             : 
      71     1220969 :     if (desc->flags & AV_PIX_FMT_FLAG_BITSTREAM)
      72        6481 :         linesize = (linesize + 7) >> 3;
      73     1220969 :     return linesize;
      74             : }
      75             : 
      76      699923 : int av_image_get_linesize(enum AVPixelFormat pix_fmt, int width, int plane)
      77             : {
      78      699923 :     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      699923 :     if (!desc || desc->flags & AV_PIX_FMT_FLAG_HWACCEL)
      83      668658 :         return AVERROR(EINVAL);
      84             : 
      85       31265 :     av_image_fill_max_pixsteps(max_step, max_step_comp, desc);
      86       31265 :     return image_get_linesize(width, plane, max_step[plane], max_step_comp[plane], desc);
      87             : }
      88             : 
      89      297426 : int av_image_fill_linesizes(int linesizes[4], enum AVPixelFormat pix_fmt, int width)
      90             : {
      91             :     int i, ret;
      92      297426 :     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      297426 :     memset(linesizes, 0, 4*sizeof(linesizes[0]));
      97             : 
      98      297426 :     if (!desc || desc->flags & AV_PIX_FMT_FLAG_HWACCEL)
      99           0 :         return AVERROR(EINVAL);
     100             : 
     101      297426 :     av_image_fill_max_pixsteps(max_step, max_step_comp, desc);
     102     1487130 :     for (i = 0; i < 4; i++) {
     103     1189704 :         if ((ret = image_get_linesize(width, i, max_step[i], max_step_comp[i], desc)) < 0)
     104           0 :             return ret;
     105     1189704 :         linesizes[i] = ret;
     106             :     }
     107             : 
     108      297426 :     return 0;
     109             : }
     110             : 
     111      204365 : 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      204365 :     int i, total_size, size[4] = { 0 }, has_plane[4] = { 0 };
     115             : 
     116      204365 :     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
     117      204365 :     memset(data     , 0, sizeof(data[0])*4);
     118             : 
     119      204365 :     if (!desc || desc->flags & AV_PIX_FMT_FLAG_HWACCEL)
     120           0 :         return AVERROR(EINVAL);
     121             : 
     122      204365 :     data[0] = ptr;
     123      204365 :     if (linesizes[0] > (INT_MAX - 1024) / height)
     124           0 :         return AVERROR(EINVAL);
     125      204365 :     size[0] = linesizes[0] * height;
     126             : 
     127      407636 :     if (desc->flags & AV_PIX_FMT_FLAG_PAL ||
     128      203271 :         desc->flags & AV_PIX_FMT_FLAG_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     1016075 :     for (i = 0; i < 4; i++)
     134      812860 :         has_plane[desc->comp[i].plane] = 1;
     135             : 
     136      203215 :     total_size = size[0];
     137      551976 :     for (i = 1; i < 4 && has_plane[i]; i++) {
     138      348761 :         int h, s = (i == 1 || i == 2) ? desc->log2_chroma_h : 0;
     139      348761 :         data[i] = data[i-1] + size[i-1];
     140      348761 :         h = (height + (1 << s) - 1) >> s;
     141      348761 :         if (linesizes[i] > INT_MAX / h)
     142           0 :             return AVERROR(EINVAL);
     143      348761 :         size[i] = h * linesizes[i];
     144      348761 :         if (total_size > INT_MAX - size[i])
     145           0 :             return AVERROR(EINVAL);
     146      348761 :         total_size += size[i];
     147             :     }
     148             : 
     149      203215 :     return total_size;
     150             : }
     151             : 
     152        6085 : int avpriv_set_systematic_pal2(uint32_t pal[256], enum AVPixelFormat pix_fmt)
     153             : {
     154             :     int i;
     155             : 
     156     1017541 :     for (i = 0; i < 256; i++) {
     157             :         int r, g, b;
     158             : 
     159     1013590 :         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      434432 :         case AV_PIX_FMT_GRAY8:
     181      434432 :             r = b = g = i;
     182      434432 :             break;
     183        2134 :         default:
     184        2134 :             return AVERROR(EINVAL);
     185             :         }
     186     1011456 :         pal[i] = b + (g << 8) + (r << 16) + (0xFFU << 24);
     187             :     }
     188             : 
     189        3951 :     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             :     .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      689213 : 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      689213 :     ImgUtils imgutils = {
     256             :         .class      = &imgutils_class,
     257             :         .log_offset = log_offset,
     258             :         .log_ctx    = log_ctx,
     259             :     };
     260      689213 :     int64_t stride = av_image_get_linesize(pix_fmt, w, 0);
     261      689213 :     if (stride <= 0)
     262      668658 :         stride = 8LL*w;
     263      689213 :     stride += 128*8;
     264             : 
     265      689213 :     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      687054 :     if (max_pixels < INT64_MAX) {
     271      237332 :         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      687054 :     return 0;
     280             : }
     281             : 
     282      431329 : int av_image_check_size(unsigned int w, unsigned int h, int log_offset, void *log_ctx)
     283             : {
     284      431329 :     return av_image_check_size2(w, h, INT64_MAX, AV_PIX_FMT_NONE, log_offset, log_ctx);
     285             : }
     286             : 
     287      131192 : int av_image_check_sar(unsigned int w, unsigned int h, AVRational sar)
     288             : {
     289             :     int64_t scaled_dim;
     290             : 
     291      131192 :     if (sar.den <= 0 || sar.num < 0)
     292           5 :         return AVERROR(EINVAL);
     293             : 
     294      131187 :     if (!sar.num || sar.num == sar.den)
     295      125925 :         return 0;
     296             : 
     297        5262 :     if (sar.num < sar.den)
     298        1306 :         scaled_dim = av_rescale_rnd(w, sar.num, sar.den, AV_ROUND_ZERO);
     299             :     else
     300        3956 :         scaled_dim = av_rescale_rnd(h, sar.den, sar.num, AV_ROUND_ZERO);
     301             : 
     302        5262 :     if (scaled_dim > 0)
     303        5253 :         return 0;
     304             : 
     305           9 :     return AVERROR(EINVAL);
     306             : }
     307             : 
     308       20288 : 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       20288 :     if (!dst || !src)
     313           0 :         return;
     314       20288 :     av_assert0(abs(src_linesize) >= bytewidth);
     315       20288 :     av_assert0(abs(dst_linesize) >= bytewidth);
     316     4024515 :     for (;height > 0; height--) {
     317     4004227 :         memcpy(dst, src, bytewidth);
     318     4004227 :         dst += dst_linesize;
     319     4004227 :         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        4668 : 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        4668 :     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
     352             : 
     353        4668 :     if (!desc || desc->flags & AV_PIX_FMT_FLAG_HWACCEL)
     354           0 :         return;
     355             : 
     356        9127 :     if (desc->flags & AV_PIX_FMT_FLAG_PAL ||
     357        4459 :         desc->flags & AV_PIX_FMT_FLAG_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         272 :         memcpy(dst_data[1], src_data[1], 4*256);
     363             :     } else {
     364        4396 :         int i, planes_nb = 0;
     365             : 
     366       18251 :         for (i = 0; i < desc->nb_components; i++)
     367       13855 :             planes_nb = FFMAX(planes_nb, desc->comp[i].plane + 1);
     368             : 
     369       15062 :         for (i = 0; i < planes_nb; i++) {
     370       10666 :             int h = height;
     371       10666 :             ptrdiff_t bwidth = av_image_get_linesize(pix_fmt, width, i);
     372       10666 :             if (bwidth < 0) {
     373           0 :                 av_log(NULL, AV_LOG_ERROR, "av_image_get_linesize failed\n");
     374           0 :                 return;
     375             :             }
     376       10666 :             if (i == 1 || i == 2) {
     377        6084 :                 h = AV_CEIL_RSHIFT(height, desc->log2_chroma_h);
     378             :             }
     379       21332 :             copy_plane(dst_data[i], dst_linesizes[i],
     380       21332 :                        src_data[i], src_linesizes[i],
     381             :                        bwidth, h);
     382             :         }
     383             :     }
     384             : }
     385             : 
     386        4668 : void av_image_copy(uint8_t *dst_data[4], int dst_linesizes[4],
     387             :                    const uint8_t *src_data[4], const int src_linesizes[4],
     388             :                    enum AVPixelFormat pix_fmt, int width, int height)
     389             : {
     390             :     ptrdiff_t dst_linesizes1[4], src_linesizes1[4];
     391             :     int i;
     392             : 
     393       23340 :     for (i = 0; i < 4; i++) {
     394       18672 :         dst_linesizes1[i] = dst_linesizes[i];
     395       18672 :         src_linesizes1[i] = src_linesizes[i];
     396             :     }
     397             : 
     398        4668 :     image_copy(dst_data, dst_linesizes1, src_data, src_linesizes1, pix_fmt,
     399             :                width, height, image_copy_plane);
     400        4668 : }
     401             : 
     402           0 : void av_image_copy_uc_from(uint8_t *dst_data[4], const ptrdiff_t dst_linesizes[4],
     403             :                            const uint8_t *src_data[4], const ptrdiff_t src_linesizes[4],
     404             :                            enum AVPixelFormat pix_fmt, int width, int height)
     405             : {
     406           0 :     image_copy(dst_data, dst_linesizes, src_data, src_linesizes, pix_fmt,
     407             :                width, height, image_copy_plane_uc_from);
     408           0 : }
     409             : 
     410      196633 : int av_image_fill_arrays(uint8_t *dst_data[4], int dst_linesize[4],
     411             :                          const uint8_t *src, enum AVPixelFormat pix_fmt,
     412             :                          int width, int height, int align)
     413             : {
     414             :     int ret, i;
     415             : 
     416      196633 :     ret = av_image_check_size(width, height, 0, NULL);
     417      196633 :     if (ret < 0)
     418           0 :         return ret;
     419             : 
     420      196633 :     ret = av_image_fill_linesizes(dst_linesize, pix_fmt, width);
     421      196633 :     if (ret < 0)
     422           0 :         return ret;
     423             : 
     424      983165 :     for (i = 0; i < 4; i++)
     425      786532 :         dst_linesize[i] = FFALIGN(dst_linesize[i], align);
     426             : 
     427      196633 :     return av_image_fill_pointers(dst_data, pix_fmt, height, (uint8_t *)src, dst_linesize);
     428             : }
     429             : 
     430      178764 : int av_image_get_buffer_size(enum AVPixelFormat pix_fmt,
     431             :                              int width, int height, int align)
     432             : {
     433             :     uint8_t *data[4];
     434             :     int linesize[4];
     435             :     int ret;
     436      178764 :     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
     437      178764 :     if (!desc)
     438           0 :         return AVERROR(EINVAL);
     439             : 
     440      178764 :     ret = av_image_check_size(width, height, 0, NULL);
     441      178764 :     if (ret < 0)
     442           0 :         return ret;
     443             : 
     444             :     // do not include palette for these pseudo-paletted formats
     445      178764 :     if (desc->flags & AV_PIX_FMT_FLAG_PSEUDOPAL)
     446        2198 :         return FFALIGN(width, align) * height;
     447             : 
     448      176566 :     return av_image_fill_arrays(data, linesize, NULL, pix_fmt,
     449             :                                 width, height, align);
     450             : }
     451             : 
     452       76645 : int av_image_copy_to_buffer(uint8_t *dst, int dst_size,
     453             :                             const uint8_t * const src_data[4],
     454             :                             const int src_linesize[4],
     455             :                             enum AVPixelFormat pix_fmt,
     456             :                             int width, int height, int align)
     457             : {
     458       76645 :     int i, j, nb_planes = 0, linesize[4];
     459       76645 :     int size = av_image_get_buffer_size(pix_fmt, width, height, align);
     460       76645 :     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
     461             :     int ret;
     462             : 
     463       76645 :     if (size > dst_size || size < 0 || !desc)
     464           0 :         return AVERROR(EINVAL);
     465             : 
     466      306873 :     for (i = 0; i < desc->nb_components; i++)
     467      230228 :         nb_planes = FFMAX(desc->comp[i].plane, nb_planes);
     468             : 
     469       76645 :     nb_planes++;
     470             : 
     471       76645 :     ret = av_image_fill_linesizes(linesize, pix_fmt, width);
     472       76645 :     av_assert0(ret >= 0); // was checked previously
     473             : 
     474      283620 :     for (i = 0; i < nb_planes; i++) {
     475      206975 :         int h, shift = (i == 1 || i == 2) ? desc->log2_chroma_h : 0;
     476      206975 :         const uint8_t *src = src_data[i];
     477      206975 :         h = (height + (1 << shift) - 1) >> shift;
     478             : 
     479    45735451 :         for (j = 0; j < h; j++) {
     480    45528476 :             memcpy(dst, src, linesize[i]);
     481    45528476 :             dst += FFALIGN(linesize[i], align);
     482    45528476 :             src += src_linesize[i];
     483             :         }
     484             :     }
     485             : 
     486       76645 :     if (desc->flags & AV_PIX_FMT_FLAG_PAL) {
     487         286 :         uint32_t *d32 = (uint32_t *)dst;
     488             : 
     489       73502 :         for (i = 0; i<256; i++)
     490       73216 :             AV_WL32(d32 + i, AV_RN32(src_data[1] + 4*i));
     491             :     }
     492             : 
     493       76645 :     return size;
     494             : }
     495             : 
     496             : // Fill dst[0..dst_size] with the bytes in clear[0..clear_size]. The clear
     497             : // bytes are repeated until dst_size is reached. If dst_size is unaligned (i.e.
     498             : // dst_size%clear_size!=0), the remaining data will be filled with the beginning
     499             : // of the clear data only.
     500           0 : static void memset_bytes(uint8_t *dst, size_t dst_size, uint8_t *clear,
     501             :                          size_t clear_size)
     502             : {
     503           0 :     size_t pos = 0;
     504           0 :     int same = 1;
     505             :     int i;
     506             : 
     507           0 :     if (!clear_size)
     508           0 :         return;
     509             : 
     510             :     // Reduce to memset() if possible.
     511           0 :     for (i = 0; i < clear_size; i++) {
     512           0 :         if (clear[i] != clear[0]) {
     513           0 :             same = 0;
     514           0 :             break;
     515             :         }
     516             :     }
     517           0 :     if (same)
     518           0 :         clear_size = 1;
     519             : 
     520           0 :     if (clear_size == 1) {
     521           0 :         memset(dst, clear[0], dst_size);
     522           0 :         dst_size = 0;
     523           0 :     } else if (clear_size == 2) {
     524           0 :         uint16_t val = AV_RN16(clear);
     525           0 :         for (; dst_size >= 2; dst_size -= 2) {
     526           0 :             AV_WN16(dst, val);
     527           0 :             dst += 2;
     528             :         }
     529           0 :     } else if (clear_size == 4) {
     530           0 :         uint32_t val = AV_RN32(clear);
     531           0 :         for (; dst_size >= 4; dst_size -= 4) {
     532           0 :             AV_WN32(dst, val);
     533           0 :             dst += 4;
     534             :         }
     535           0 :     } else if (clear_size == 8) {
     536           0 :         uint32_t val = AV_RN64(clear);
     537           0 :         for (; dst_size >= 8; dst_size -= 8) {
     538           0 :             AV_WN64(dst, val);
     539           0 :             dst += 8;
     540             :         }
     541             :     }
     542             : 
     543           0 :     for (; dst_size; dst_size--)
     544           0 :         *dst++ = clear[pos++ % clear_size];
     545             : }
     546             : 
     547             : // Maximum size in bytes of a plane element (usually a pixel, or multiple pixels
     548             : // if it's a subsampled packed format).
     549             : #define MAX_BLOCK_SIZE 32
     550             : 
     551           0 : int av_image_fill_black(uint8_t *dst_data[4], const ptrdiff_t dst_linesize[4],
     552             :                         enum AVPixelFormat pix_fmt, enum AVColorRange range,
     553             :                         int width, int height)
     554             : {
     555           0 :     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
     556           0 :     int nb_planes = av_pix_fmt_count_planes(pix_fmt);
     557             :     // A pixel or a group of pixels on each plane, with a value that represents black.
     558             :     // Consider e.g. AV_PIX_FMT_UYVY422 for non-trivial cases.
     559           0 :     uint8_t clear_block[4][MAX_BLOCK_SIZE] = {{0}}; // clear padding with 0
     560           0 :     int clear_block_size[4] = {0};
     561           0 :     ptrdiff_t plane_line_bytes[4] = {0};
     562             :     int rgb, limited;
     563             :     int plane, c;
     564             : 
     565           0 :     if (!desc || nb_planes < 1 || nb_planes > 4 || desc->flags & AV_PIX_FMT_FLAG_HWACCEL)
     566           0 :         return AVERROR(EINVAL);
     567             : 
     568           0 :     rgb = !!(desc->flags & AV_PIX_FMT_FLAG_RGB);
     569           0 :     limited = !rgb && range != AVCOL_RANGE_JPEG;
     570             : 
     571           0 :     if (desc->flags & AV_PIX_FMT_FLAG_BITSTREAM) {
     572           0 :         ptrdiff_t bytewidth = av_image_get_linesize(pix_fmt, width, 0);
     573             :         uint8_t *data;
     574           0 :         int mono = pix_fmt == AV_PIX_FMT_MONOWHITE || pix_fmt == AV_PIX_FMT_MONOBLACK;
     575           0 :         int fill = pix_fmt == AV_PIX_FMT_MONOWHITE ? 0xFF : 0;
     576           0 :         if (nb_planes != 1 || !(rgb || mono) || bytewidth < 1)
     577           0 :             return AVERROR(EINVAL);
     578             : 
     579           0 :         if (!dst_data)
     580           0 :             return 0;
     581             : 
     582           0 :         data = dst_data[0];
     583             : 
     584             :         // (Bitstream + alpha will be handled incorrectly - it'll remain transparent.)
     585           0 :         for (;height > 0; height--) {
     586           0 :             memset(data, fill, bytewidth);
     587           0 :             data += dst_linesize[0];
     588             :         }
     589           0 :         return 0;
     590             :     }
     591             : 
     592           0 :     for (c = 0; c < desc->nb_components; c++) {
     593           0 :         const AVComponentDescriptor comp = desc->comp[c];
     594             : 
     595             :         // We try to operate on entire non-subsampled pixel groups (for
     596             :         // AV_PIX_FMT_UYVY422 this would mean two consecutive pixels).
     597           0 :         clear_block_size[comp.plane] = FFMAX(clear_block_size[comp.plane], comp.step);
     598             : 
     599           0 :         if (clear_block_size[comp.plane] > MAX_BLOCK_SIZE)
     600           0 :             return AVERROR(EINVAL);
     601             :     }
     602             : 
     603             :     // Create a byte array for clearing 1 pixel (sometimes several pixels).
     604           0 :     for (c = 0; c < desc->nb_components; c++) {
     605           0 :         const AVComponentDescriptor comp = desc->comp[c];
     606             :         // (Multiple pixels happen e.g. with AV_PIX_FMT_UYVY422.)
     607           0 :         int w = clear_block_size[comp.plane] / comp.step;
     608             :         uint8_t *c_data[4];
     609           0 :         const int c_linesize[4] = {0};
     610             :         uint16_t src_array[MAX_BLOCK_SIZE];
     611           0 :         uint16_t src = 0;
     612             :         int x;
     613             : 
     614           0 :         if (comp.depth > 16)
     615           0 :             return AVERROR(EINVAL);
     616           0 :         if (!rgb && comp.depth < 8)
     617           0 :             return AVERROR(EINVAL);
     618           0 :         if (w < 1)
     619           0 :             return AVERROR(EINVAL);
     620             : 
     621           0 :         if (c == 0 && limited) {
     622           0 :             src = 16 << (comp.depth - 8);
     623           0 :         } else if ((c == 1 || c == 2) && !rgb) {
     624           0 :             src = 128 << (comp.depth - 8);
     625           0 :         } else if (c == 3) {
     626             :             // (Assume even limited YUV uses full range alpha.)
     627           0 :             src = (1 << comp.depth) - 1;
     628             :         }
     629             : 
     630           0 :         for (x = 0; x < w; x++)
     631           0 :             src_array[x] = src;
     632             : 
     633           0 :         for (x = 0; x < 4; x++)
     634           0 :             c_data[x] = &clear_block[x][0];
     635             : 
     636           0 :         av_write_image_line(src_array, c_data, c_linesize, desc, 0, 0, c, w);
     637             :     }
     638             : 
     639           0 :     for (plane = 0; plane < nb_planes; plane++) {
     640           0 :         plane_line_bytes[plane] = av_image_get_linesize(pix_fmt, width, plane);
     641           0 :         if (plane_line_bytes[plane] < 0)
     642           0 :             return AVERROR(EINVAL);
     643             :     }
     644             : 
     645           0 :     if (!dst_data)
     646           0 :         return 0;
     647             : 
     648           0 :     for (plane = 0; plane < nb_planes; plane++) {
     649           0 :         size_t bytewidth = plane_line_bytes[plane];
     650           0 :         uint8_t *data = dst_data[plane];
     651           0 :         int chroma_div = plane == 1 || plane == 2 ? desc->log2_chroma_h : 0;
     652           0 :         int plane_h = ((height + ( 1 << chroma_div) - 1)) >> chroma_div;
     653             : 
     654           0 :         for (; plane_h > 0; plane_h--) {
     655           0 :             memset_bytes(data, bytewidth, &clear_block[plane][0], clear_block_size[plane]);
     656           0 :             data += dst_linesize[plane];
     657             :         }
     658             :     }
     659             : 
     660           0 :     return 0;
     661             : }

Generated by: LCOV version 1.13