diff options
Diffstat (limited to 'libavutil/imgutils.c')
-rw-r--r-- | libavutil/imgutils.c | 102 |
1 files changed, 69 insertions, 33 deletions
diff --git a/libavutil/imgutils.c b/libavutil/imgutils.c index 6c581396a3..3320664702 100644 --- a/libavutil/imgutils.c +++ b/libavutil/imgutils.c @@ -1,18 +1,18 @@ /* - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -21,6 +21,7 @@ * misc image utilities */ +#include "avassert.h" #include "common.h" #include "imgutils.h" #include "internal.h" @@ -48,27 +49,45 @@ void av_image_fill_max_pixsteps(int max_pixsteps[4], int max_pixstep_comps[4], } } +static inline +int image_get_linesize(int width, int plane, + int max_step, int max_step_comp, + const AVPixFmtDescriptor *desc) +{ + int s, shifted_w, linesize; + + if (!desc) + return AVERROR(EINVAL); + + if (width < 0) + return AVERROR(EINVAL); + s = (max_step_comp == 1 || max_step_comp == 2) ? desc->log2_chroma_w : 0; + shifted_w = ((width + (1 << s) - 1)) >> s; + if (shifted_w && max_step > INT_MAX / shifted_w) + return AVERROR(EINVAL); + linesize = max_step * shifted_w; + + if (desc->flags & AV_PIX_FMT_FLAG_BITSTREAM) + linesize = (linesize + 7) >> 3; + return linesize; +} + int av_image_get_linesize(enum AVPixelFormat pix_fmt, int width, int plane) { const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); int max_step [4]; /* max pixel step for each plane */ int max_step_comp[4]; /* the component for each plane which has the max pixel step */ - int s; - if (!desc) + if (!desc || desc->flags & AV_PIX_FMT_FLAG_HWACCEL) return AVERROR(EINVAL); - if (desc->flags & AV_PIX_FMT_FLAG_BITSTREAM) - return (width * desc->comp[0].step + 7) >> 3; - av_image_fill_max_pixsteps(max_step, max_step_comp, desc); - s = (max_step_comp[plane] == 1 || max_step_comp[plane] == 2) ? desc->log2_chroma_w : 0; - return max_step[plane] * (((width + (1 << s) - 1)) >> s); + return image_get_linesize(width, plane, max_step[plane], max_step_comp[plane], desc); } int av_image_fill_linesizes(int linesizes[4], enum AVPixelFormat pix_fmt, int width) { - int i; + int i, ret; const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); int max_step [4]; /* max pixel step for each plane */ int max_step_comp[4]; /* the component for each plane which has the max pixel step */ @@ -78,20 +97,11 @@ int av_image_fill_linesizes(int linesizes[4], enum AVPixelFormat pix_fmt, int wi if (!desc || desc->flags & AV_PIX_FMT_FLAG_HWACCEL) return AVERROR(EINVAL); - if (desc->flags & AV_PIX_FMT_FLAG_BITSTREAM) { - if (width > (INT_MAX - 7) / desc->comp[0].step) - return AVERROR(EINVAL); - linesizes[0] = (width * desc->comp[0].step + 7) >> 3; - return 0; - } - av_image_fill_max_pixsteps(max_step, max_step_comp, desc); for (i = 0; i < 4; i++) { - int s = (max_step_comp[i] == 1 || max_step_comp[i] == 2) ? desc->log2_chroma_w : 0; - int shifted_w = ((width + (1 << s) - 1)) >> s; - if (max_step[i] > INT_MAX / shifted_w) - return AVERROR(EINVAL); - linesizes[i] = max_step[i] * shifted_w; + if ((ret = image_get_linesize(width, i, max_step[i], max_step_comp[i], desc)) < 0) + return ret; + linesizes[i] = ret; } return 0; @@ -191,7 +201,7 @@ int av_image_alloc(uint8_t *pointers[4], int linesizes[4], if ((ret = av_image_check_size(w, h, 0, NULL)) < 0) return ret; - if ((ret = av_image_fill_linesizes(linesizes, pix_fmt, w)) < 0) + if ((ret = av_image_fill_linesizes(linesizes, pix_fmt, align>7 ? FFALIGN(w, 8) : w)) < 0) return ret; for (i = 0; i < 4; i++) @@ -209,6 +219,14 @@ int av_image_alloc(uint8_t *pointers[4], int linesizes[4], if (desc->flags & AV_PIX_FMT_FLAG_PAL || desc->flags & AV_PIX_FMT_FLAG_PSEUDOPAL) avpriv_set_systematic_pal2((uint32_t*)pointers[1], pix_fmt); + if ((desc->flags & AV_PIX_FMT_FLAG_PAL || + desc->flags & AV_PIX_FMT_FLAG_PSEUDOPAL) && + pointers[1] - pointers[0] > linesizes[0] * h) { + /* zero-initialize the padding before the palette */ + memset(pointers[0] + linesizes[0] * h, 0, + pointers[1] - pointers[0] - linesizes[0] * h); + } + return ret; } @@ -218,11 +236,21 @@ typedef struct ImgUtils { void *log_ctx; } ImgUtils; -static const AVClass imgutils_class = { "IMGUTILS", av_default_item_name, NULL, LIBAVUTIL_VERSION_INT, offsetof(ImgUtils, log_offset), offsetof(ImgUtils, log_ctx) }; +static const AVClass imgutils_class = { + .class_name = "IMGUTILS", + .item_name = av_default_item_name, + .version = LIBAVUTIL_VERSION_INT, + .log_level_offset_offset = offsetof(ImgUtils, log_offset), + .parent_log_context_offset = offsetof(ImgUtils, log_ctx), +}; int av_image_check_size(unsigned int w, unsigned int h, int log_offset, void *log_ctx) { - ImgUtils imgutils = { &imgutils_class, log_offset, log_ctx }; + ImgUtils imgutils = { + .class = &imgutils_class, + .log_offset = log_offset, + .log_ctx = log_ctx, + }; if ((int)w>0 && (int)h>0 && (w+128)*(uint64_t)(h+128) < INT_MAX/8) return 0; @@ -235,7 +263,7 @@ int av_image_check_sar(unsigned int w, unsigned int h, AVRational sar) { int64_t scaled_dim; - if (!sar.den) + if (sar.den <= 0 || sar.num < 0) return AVERROR(EINVAL); if (!sar.num || sar.num == sar.den) @@ -258,6 +286,8 @@ void av_image_copy_plane(uint8_t *dst, int dst_linesize, { if (!dst || !src) return; + av_assert0(abs(src_linesize) >= bytewidth); + av_assert0(abs(dst_linesize) >= bytewidth); for (;height > 0; height--) { memcpy(dst, src, bytewidth); dst += dst_linesize; @@ -290,6 +320,10 @@ void av_image_copy(uint8_t *dst_data[4], int dst_linesizes[4], for (i = 0; i < planes_nb; i++) { int h = height; int bwidth = av_image_get_linesize(pix_fmt, width, i); + if (bwidth < 0) { + av_log(NULL, AV_LOG_ERROR, "av_image_get_linesize failed\n"); + return; + } if (i == 1 || i == 2) { h = AV_CEIL_RSHIFT(height, desc->log2_chroma_h); } @@ -317,7 +351,7 @@ int av_image_fill_arrays(uint8_t *dst_data[4], int dst_linesize[4], for (i = 0; i < 4; i++) dst_linesize[i] = FFALIGN(dst_linesize[i], align); - return av_image_fill_pointers(dst_data, pix_fmt, height, src, dst_linesize); + return av_image_fill_pointers(dst_data, pix_fmt, height, (uint8_t *)src, dst_linesize); } int av_image_get_buffer_size(enum AVPixelFormat pix_fmt, @@ -328,7 +362,7 @@ int av_image_get_buffer_size(enum AVPixelFormat pix_fmt, int ret; const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); if (!desc) - return AVERROR_BUG; + return AVERROR(EINVAL); ret = av_image_check_size(width, height, 0, NULL); if (ret < 0) @@ -373,9 +407,11 @@ int av_image_copy_to_buffer(uint8_t *dst, int dst_size, } } - if (desc->flags & AV_PIX_FMT_FLAG_PAL) - memcpy((unsigned char *)(((size_t)dst + 3) & ~3), - src_data[1], 256 * 4); + if (desc->flags & AV_PIX_FMT_FLAG_PAL) { + uint32_t *d32 = (uint32_t *)(((size_t)dst + 3) & ~3); + for (i = 0; i<256; i++) + AV_WL32(d32 + i, AV_RN32(src_data[1] + 4*i)); + } return size; } |