Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  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 "internal.h"
  28. #include "intreadwrite.h"
  29. #include "log.h"
  30. #include "pixdesc.h"
  31.  
  32. void av_image_fill_max_pixsteps(int max_pixsteps[4], int max_pixstep_comps[4],
  33.                                 const AVPixFmtDescriptor *pixdesc)
  34. {
  35.     int i;
  36.     memset(max_pixsteps, 0, 4*sizeof(max_pixsteps[0]));
  37.     if (max_pixstep_comps)
  38.         memset(max_pixstep_comps, 0, 4*sizeof(max_pixstep_comps[0]));
  39.  
  40.     for (i = 0; i < 4; i++) {
  41.         const AVComponentDescriptor *comp = &(pixdesc->comp[i]);
  42.         if ((comp->step_minus1+1) > max_pixsteps[comp->plane]) {
  43.             max_pixsteps[comp->plane] = comp->step_minus1+1;
  44.             if (max_pixstep_comps)
  45.                 max_pixstep_comps[comp->plane] = i;
  46.         }
  47.     }
  48. }
  49.  
  50. static inline
  51. int image_get_linesize(int width, int plane,
  52.                        int max_step, int max_step_comp,
  53.                        const AVPixFmtDescriptor *desc)
  54. {
  55.     int s, shifted_w, linesize;
  56.  
  57.     if (!desc)
  58.         return AVERROR(EINVAL);
  59.  
  60.     if (width < 0)
  61.         return AVERROR(EINVAL);
  62.     s = (max_step_comp == 1 || max_step_comp == 2) ? desc->log2_chroma_w : 0;
  63.     shifted_w = ((width + (1 << s) - 1)) >> s;
  64.     if (shifted_w && max_step > INT_MAX / shifted_w)
  65.         return AVERROR(EINVAL);
  66.     linesize = max_step * shifted_w;
  67.  
  68.     if (desc->flags & AV_PIX_FMT_FLAG_BITSTREAM)
  69.         linesize = (linesize + 7) >> 3;
  70.     return linesize;
  71. }
  72.  
  73. int av_image_get_linesize(enum AVPixelFormat pix_fmt, int width, int plane)
  74. {
  75.     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
  76.     int max_step     [4];       /* max pixel step for each plane */
  77.     int max_step_comp[4];       /* the component for each plane which has the max pixel step */
  78.  
  79.     if ((unsigned)pix_fmt >= AV_PIX_FMT_NB || desc->flags & AV_PIX_FMT_FLAG_HWACCEL)
  80.         return AVERROR(EINVAL);
  81.  
  82.     av_image_fill_max_pixsteps(max_step, max_step_comp, desc);
  83.     return image_get_linesize(width, plane, max_step[plane], max_step_comp[plane], desc);
  84. }
  85.  
  86. int av_image_fill_linesizes(int linesizes[4], enum AVPixelFormat pix_fmt, int width)
  87. {
  88.     int i, ret;
  89.     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
  90.     int max_step     [4];       /* max pixel step for each plane */
  91.     int max_step_comp[4];       /* the component for each plane which has the max pixel step */
  92.  
  93.     memset(linesizes, 0, 4*sizeof(linesizes[0]));
  94.  
  95.     if (!desc || desc->flags & AV_PIX_FMT_FLAG_HWACCEL)
  96.         return AVERROR(EINVAL);
  97.  
  98.     av_image_fill_max_pixsteps(max_step, max_step_comp, desc);
  99.     for (i = 0; i < 4; i++) {
  100.         if ((ret = image_get_linesize(width, i, max_step[i], max_step_comp[i], desc)) < 0)
  101.             return ret;
  102.         linesizes[i] = ret;
  103.     }
  104.  
  105.     return 0;
  106. }
  107.  
  108. int av_image_fill_pointers(uint8_t *data[4], enum AVPixelFormat pix_fmt, int height,
  109.                            uint8_t *ptr, const int linesizes[4])
  110. {
  111.     int i, total_size, size[4] = { 0 }, has_plane[4] = { 0 };
  112.  
  113.     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
  114.     memset(data     , 0, sizeof(data[0])*4);
  115.  
  116.     if (!desc || desc->flags & AV_PIX_FMT_FLAG_HWACCEL)
  117.         return AVERROR(EINVAL);
  118.  
  119.     data[0] = ptr;
  120.     if (linesizes[0] > (INT_MAX - 1024) / height)
  121.         return AVERROR(EINVAL);
  122.     size[0] = linesizes[0] * height;
  123.  
  124.     if (desc->flags & AV_PIX_FMT_FLAG_PAL ||
  125.         desc->flags & AV_PIX_FMT_FLAG_PSEUDOPAL) {
  126.         size[0] = (size[0] + 3) & ~3;
  127.         data[1] = ptr + size[0]; /* palette is stored here as 256 32 bits words */
  128.         return size[0] + 256 * 4;
  129.     }
  130.  
  131.     for (i = 0; i < 4; i++)
  132.         has_plane[desc->comp[i].plane] = 1;
  133.  
  134.     total_size = size[0];
  135.     for (i = 1; i < 4 && has_plane[i]; i++) {
  136.         int h, s = (i == 1 || i == 2) ? desc->log2_chroma_h : 0;
  137.         data[i] = data[i-1] + size[i-1];
  138.         h = (height + (1 << s) - 1) >> s;
  139.         if (linesizes[i] > INT_MAX / h)
  140.             return AVERROR(EINVAL);
  141.         size[i] = h * linesizes[i];
  142.         if (total_size > INT_MAX - size[i])
  143.             return AVERROR(EINVAL);
  144.         total_size += size[i];
  145.     }
  146.  
  147.     return total_size;
  148. }
  149.  
  150. int avpriv_set_systematic_pal2(uint32_t pal[256], enum AVPixelFormat pix_fmt)
  151. {
  152.     int i;
  153.  
  154.     for (i = 0; i < 256; i++) {
  155.         int r, g, b;
  156.  
  157.         switch (pix_fmt) {
  158.         case AV_PIX_FMT_RGB8:
  159.             r = (i>>5    )*36;
  160.             g = ((i>>2)&7)*36;
  161.             b = (i&3     )*85;
  162.             break;
  163.         case AV_PIX_FMT_BGR8:
  164.             b = (i>>6    )*85;
  165.             g = ((i>>3)&7)*36;
  166.             r = (i&7     )*36;
  167.             break;
  168.         case AV_PIX_FMT_RGB4_BYTE:
  169.             r = (i>>3    )*255;
  170.             g = ((i>>1)&3)*85;
  171.             b = (i&1     )*255;
  172.             break;
  173.         case AV_PIX_FMT_BGR4_BYTE:
  174.             b = (i>>3    )*255;
  175.             g = ((i>>1)&3)*85;
  176.             r = (i&1     )*255;
  177.             break;
  178.         case AV_PIX_FMT_GRAY8:
  179.             r = b = g = i;
  180.             break;
  181.         default:
  182.             return AVERROR(EINVAL);
  183.         }
  184.         pal[i] = b + (g<<8) + (r<<16) + (0xFFU<<24);
  185.     }
  186.  
  187.     return 0;
  188. }
  189.  
  190. int av_image_alloc(uint8_t *pointers[4], int linesizes[4],
  191.                    int w, int h, enum AVPixelFormat pix_fmt, int align)
  192. {
  193.     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
  194.     int i, ret;
  195.     uint8_t *buf;
  196.  
  197.     if (!desc)
  198.         return AVERROR(EINVAL);
  199.  
  200.     if ((ret = av_image_check_size(w, h, 0, NULL)) < 0)
  201.         return ret;
  202.     if ((ret = av_image_fill_linesizes(linesizes, pix_fmt, align>7 ? FFALIGN(w, 8) : w)) < 0)
  203.         return ret;
  204.  
  205.     for (i = 0; i < 4; i++)
  206.         linesizes[i] = FFALIGN(linesizes[i], align);
  207.  
  208.     if ((ret = av_image_fill_pointers(pointers, pix_fmt, h, NULL, linesizes)) < 0)
  209.         return ret;
  210.     buf = av_malloc(ret + align);
  211.     if (!buf)
  212.         return AVERROR(ENOMEM);
  213.     if ((ret = av_image_fill_pointers(pointers, pix_fmt, h, buf, linesizes)) < 0) {
  214.         av_free(buf);
  215.         return ret;
  216.     }
  217.     if (desc->flags & AV_PIX_FMT_FLAG_PAL || desc->flags & AV_PIX_FMT_FLAG_PSEUDOPAL)
  218.         avpriv_set_systematic_pal2((uint32_t*)pointers[1], pix_fmt);
  219.  
  220.     return ret;
  221. }
  222.  
  223. typedef struct ImgUtils {
  224.     const AVClass *class;
  225.     int   log_offset;
  226.     void *log_ctx;
  227. } ImgUtils;
  228.  
  229. static const AVClass imgutils_class = { "IMGUTILS", av_default_item_name, NULL, LIBAVUTIL_VERSION_INT, offsetof(ImgUtils, log_offset), offsetof(ImgUtils, log_ctx) };
  230.  
  231. int av_image_check_size(unsigned int w, unsigned int h, int log_offset, void *log_ctx)
  232. {
  233.     ImgUtils imgutils = { &imgutils_class, log_offset, log_ctx };
  234.  
  235.     if ((int)w>0 && (int)h>0 && (w+128)*(uint64_t)(h+128) < INT_MAX/8)
  236.         return 0;
  237.  
  238.     av_log(&imgutils, AV_LOG_ERROR, "Picture size %ux%u is invalid\n", w, h);
  239.     return AVERROR(EINVAL);
  240. }
  241.  
  242. void av_image_copy_plane(uint8_t       *dst, int dst_linesize,
  243.                          const uint8_t *src, int src_linesize,
  244.                          int bytewidth, int height)
  245. {
  246.     if (!dst || !src)
  247.         return;
  248.     av_assert0(abs(src_linesize) >= bytewidth);
  249.     av_assert0(abs(dst_linesize) >= bytewidth);
  250.     for (;height > 0; height--) {
  251.         memcpy(dst, src, bytewidth);
  252.         dst += dst_linesize;
  253.         src += src_linesize;
  254.     }
  255. }
  256.  
  257. void av_image_copy(uint8_t *dst_data[4], int dst_linesizes[4],
  258.                    const uint8_t *src_data[4], const int src_linesizes[4],
  259.                    enum AVPixelFormat pix_fmt, int width, int height)
  260. {
  261.     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
  262.  
  263.     if (!desc || desc->flags & AV_PIX_FMT_FLAG_HWACCEL)
  264.         return;
  265.  
  266.     if (desc->flags & AV_PIX_FMT_FLAG_PAL ||
  267.         desc->flags & AV_PIX_FMT_FLAG_PSEUDOPAL) {
  268.         av_image_copy_plane(dst_data[0], dst_linesizes[0],
  269.                             src_data[0], src_linesizes[0],
  270.                             width, height);
  271.         /* copy the palette */
  272.         memcpy(dst_data[1], src_data[1], 4*256);
  273.     } else {
  274.         int i, planes_nb = 0;
  275.  
  276.         for (i = 0; i < desc->nb_components; i++)
  277.             planes_nb = FFMAX(planes_nb, desc->comp[i].plane + 1);
  278.  
  279.         for (i = 0; i < planes_nb; i++) {
  280.             int h = height;
  281.             int bwidth = av_image_get_linesize(pix_fmt, width, i);
  282.             if (bwidth < 0) {
  283.                 av_log(NULL, AV_LOG_ERROR, "av_image_get_linesize failed\n");
  284.                 return;
  285.             }
  286.             if (i == 1 || i == 2) {
  287.                 h = FF_CEIL_RSHIFT(height, desc->log2_chroma_h);
  288.             }
  289.             av_image_copy_plane(dst_data[i], dst_linesizes[i],
  290.                                 src_data[i], src_linesizes[i],
  291.                                 bwidth, h);
  292.         }
  293.     }
  294. }
  295.  
  296. int av_image_fill_arrays(uint8_t *dst_data[4], int dst_linesize[4],
  297.                          const uint8_t *src,
  298.                          enum AVPixelFormat pix_fmt, int width, int height, int align)
  299. {
  300.     int ret, i;
  301.  
  302.     if ((ret = av_image_check_size(width, height, 0, NULL)) < 0)
  303.         return ret;
  304.  
  305.     if ((ret = av_image_fill_linesizes(dst_linesize, pix_fmt, width)) < 0)
  306.         return ret;
  307.  
  308.     for (i = 0; i < 4; i++)
  309.         dst_linesize[i] = FFALIGN(dst_linesize[i], align);
  310.  
  311.     if ((ret = av_image_fill_pointers(dst_data, pix_fmt, width, NULL, dst_linesize)) < 0)
  312.         return ret;
  313.  
  314.     return av_image_fill_pointers(dst_data, pix_fmt, height, (uint8_t *)src, dst_linesize);
  315. }
  316.  
  317. int av_image_get_buffer_size(enum AVPixelFormat pix_fmt, int width, int height, int align)
  318. {
  319.     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
  320.     uint8_t *data[4];
  321.     int linesize[4];
  322.  
  323.     if (!desc)
  324.         return AVERROR(EINVAL);
  325.     if (av_image_check_size(width, height, 0, NULL) < 0)
  326.         return AVERROR(EINVAL);
  327.     if (desc->flags & AV_PIX_FMT_FLAG_PSEUDOPAL)
  328.         // do not include palette for these pseudo-paletted formats
  329.         return width * height;
  330.     return av_image_fill_arrays(data, linesize, NULL, pix_fmt, width, height, align);
  331. }
  332.  
  333. int av_image_copy_to_buffer(uint8_t *dst, int dst_size,
  334.                             const uint8_t * const src_data[4], const int src_linesize[4],
  335.                             enum AVPixelFormat pix_fmt, int width, int height, int align)
  336. {
  337.     int i, j, nb_planes = 0, linesize[4];
  338.     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
  339.     int size = av_image_get_buffer_size(pix_fmt, width, height, align);
  340.  
  341.     if (size > dst_size || size < 0)
  342.         return AVERROR(EINVAL);
  343.  
  344.     for (i = 0; i < desc->nb_components; i++)
  345.         nb_planes = FFMAX(desc->comp[i].plane, nb_planes);
  346.     nb_planes++;
  347.  
  348.     av_image_fill_linesizes(linesize, pix_fmt, width);
  349.     for (i = 0; i < nb_planes; i++) {
  350.         int h, shift = (i == 1 || i == 2) ? desc->log2_chroma_h : 0;
  351.         const uint8_t *src = src_data[i];
  352.         h = (height + (1 << shift) - 1) >> shift;
  353.  
  354.         for (j = 0; j < h; j++) {
  355.             memcpy(dst, src, linesize[i]);
  356.             dst += FFALIGN(linesize[i], align);
  357.             src += src_linesize[i];
  358.         }
  359.     }
  360.  
  361.     if (desc->flags & AV_PIX_FMT_FLAG_PAL) {
  362.         uint32_t *d32 = (uint32_t *)(((size_t)dst + 3) & ~3);
  363.         for (i = 0; i<256; i++)
  364.             AV_WL32(d32 + i, AV_RN32(src_data[1] + 4*i));
  365.     }
  366.  
  367.     return size;
  368. }
  369.