diff options
Diffstat (limited to 'libavutil/imgutils.c')
-rw-r--r-- | libavutil/imgutils.c | 82 |
1 files changed, 50 insertions, 32 deletions
diff --git a/libavutil/imgutils.c b/libavutil/imgutils.c index 948a6f7..a8bc18d 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 ((unsigned)pix_fmt >= AV_PIX_FMT_NB || desc->flags & AV_PIX_FMT_FLAG_HWACCEL) return AVERROR(EINVAL); - if (desc->flags & AV_PIX_FMT_FLAG_BITSTREAM) - return (width * (desc->comp[0].step_minus1+1) + 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_minus1+1)) - return AVERROR(EINVAL); - linesizes[0] = (width * (desc->comp[0].step_minus1+1) + 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++) @@ -235,7 +245,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 +268,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,8 +302,12 @@ 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= -((-height)>>desc->log2_chroma_h); + h = FF_CEIL_RSHIFT(height, desc->log2_chroma_h); } av_image_copy_plane(dst_data[i], dst_linesizes[i], src_data[i], src_linesizes[i], @@ -317,7 +333,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 +344,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 +389,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; } |