Skip to main content

FFmpeg Picture size is invalid

·632 words·3 mins
Table of Contents

High-Resolution Image
#

最近遇到了一个问题,FFmpeg 在处理一些分辨率特别大的图片时候会报错,错误如下

[IMGUTILS @ 0x7ffc82f1c7c0] Picture size 14583x29167 is invalid
[png @ 0x5f93fcc46e00] [IMGUTILS @ 0x7ffc82f1c0b0] Picture size 29167x14583 is invalid
[png @ 0x5f93fcc46e00] Invalid image size
[png_pipe @ 0x5f93fcc45ac0] Could not find codec parameters for stream 0 (Video: png, none): unspecified size
Consider increasing the value for the 'analyzeduration' (0) and 'probesize' (5000000) options
Input #0, png_pipe, from 'test.png':
  Duration: N/A, bitrate: N/A
  Stream #0:0: Video: png, none, 25 fps, 25 tbr, 25 tbn

这个图片的文件大小仅有 6Mb,但是分辨率高达 14583x29167。搜了一下这个问题相关的 Solution

FFmpeg 在 avformat_open_input 的时候会调用 av_image_check_size2 进行检测

//  https://github.com/FFmpeg/FFmpeg/blob/b2cba76d4fe55c944bb4277c1c1def8597c1106b/libavutil/imgutils.c#L301-L304
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)
{
    ImgUtils imgutils = {
        .class      = &imgutils_class,
        .log_offset = log_offset,
        .log_ctx    = log_ctx,
    };
    int64_t stride = av_image_get_linesize(pix_fmt, w, 0);
    if (stride <= 0)
        stride = 8LL*w;
    stride += 128*8;

    if (w==0 || h==0 || w > INT32_MAX || h > INT32_MAX || stride >= INT_MAX || stride*(h + 128ULL) >= INT_MAX) {
        av_log(&imgutils, AV_LOG_ERROR, "Picture size %ux%u is invalid\n", w, h);
        return AVERROR(EINVAL);
    }

    if (max_pixels < INT64_MAX) {
        if (w*(int64_t)h > max_pixels) {
            av_log(&imgutils, AV_LOG_ERROR,
                    "Picture size %ux%u exceeds specified max pixel count %"PRId64", see the documentation if you wish to increase it\n",
                    w, h, max_pixels);
            return AVERROR(EINVAL);
        }
    }

    return 0;
}

这里使用的是 INT_MAX,对于 int 被定义为 4 字节的系统来说,值大小为 2147483647。此处是为了防止类似 decompression bomb DOS attack 对系统负载造成影响,这是一个值得去做的限制

各工具内存占用对比
#

这里简单对比几个工具在图片缩放时的内存占用

FFmpeg
#

  • 基于 n7.1 修改源码后
$ pidstat -r 1 -e ./ffmpeg -i test.png -vf "scale=1920:-1" -y output.png -loglevel quiet
Linux 6.12.4-arch1-1 (misaka)   12/22/2024      _x86_64_        (16 CPU)

07:17:29 PM   UID       PID  minflt/s  majflt/s     VSZ     RSS   %MEM  Command
07:17:30 PM  1000    268282   3812.00      0.00 1730960 1687492   5.90  ffmpeg
07:17:31 PM  1000    268282      0.00      0.00 1730960 1687492   5.90  ffmpeg
07:17:32 PM  1000    268282      0.00      0.00 1730960 1687492   5.90  ffmpeg
07:17:33 PM  1000    268282      0.00      0.00 1730960 1687492   5.90  ffmpeg
07:17:34 PM  1000    268282   1137.00      0.00 2215708 1682304   5.88  ffmpeg
07:17:35 PM  1000    268282      0.00      0.00 2215708 1682304   5.88  ffmpeg
07:17:36 PM  1000    268282      0.00      0.00 2215708 1682304   5.88  ffmpeg
07:17:37 PM  1000    268282      0.00      0.00 2215708 1682304   5.88  ffmpeg

Average:     1000    268282    618.62      0.00 1973334 1684898   5.89  ffmpeg

ImageMagick
#

  • ImageMagick 7.1.1-41
$ pidstat -r 1 -e magick test.png -resize 1920x output.png

Linux 6.12.4-arch1-1 (misaka)   12/22/2024      _x86_64_        (16 CPU)

07:34:55 PM   UID       PID  minflt/s  majflt/s     VSZ     RSS   %MEM  Command
07:34:56 PM  1000    339864   9986.00      0.00 11833328 7081340  24.77  magick
07:34:57 PM  1000    339864   2225.00      0.00 11833328 11499132  40.22  magick
07:34:58 PM  1000    339864    271.00      0.00 6848844 6683620  23.37  magick
07:34:59 PM  1000    339864     12.00      0.00 6848844 6684388  23.38  magick
07:35:00 PM  1000    339864     13.00      0.00 6848844 6685284  23.38  magick
07:35:01 PM  1000    339864     21.00      0.00 6848844 6686564  23.39  magick
07:35:02 PM  1000    339864     22.00      0.00 6848844 6687972  23.39  magick
07:35:03 PM  1000    339864     18.00      0.00 6848844 6689124  23.39  magick
07:35:04 PM  1000    339864    464.00      0.00 7255624 6830140  23.89  magick
07:35:05 PM  1000    339864    113.00      0.00 7255624 7061556  24.70  magick

Average:     1000    339864   1314.50      0.00 7927097 7258912  25.39  magick

libvips
#

  • vips-8.16.0
$ pidstat -r 1 -e vips thumbnail test.png output.png 1920

Linux 6.12.4-arch1-1 (misaka)   12/22/2024      _x86_64_        (16 CPU)

07:44:37 PM   UID       PID  minflt/s  majflt/s     VSZ     RSS   %MEM  Command
07:44:38 PM  1000    383594  72104.00      0.00 1380940  337740   1.18  vips
07:44:39 PM  1000    383594  17521.00      0.00 1460056  360072   1.26  vips
07:44:40 PM  1000    383594  23021.00      0.00 1530896  473988   1.66  vips
07:44:41 PM  1000    383594  17532.00      0.00 1595468  555320   1.94  vips
07:44:42 PM  1000    383594  21905.00      0.00 1661004  669348   2.34  vips
07:44:43 PM  1000    383594   9972.00      0.00 1660040  708328   2.48  vips
07:44:44 PM  1000    383594   5987.00      0.00 1660040  732136   2.56  vips
07:44:45 PM  1000    383594   9049.00      0.00 1725576  780520   2.73  vips

Average:     1000    383594  22136.38      0.00 1584252  577182   2.02  vips

可以看到占用最少的 libvips 依然使用了 563Mb。不太建议直接处理这种类型的图片,最好直接前置拦截

Related

WEB 端视频时间轴预览图的实现思路
·293 words·2 mins
FFmpeg 封装字幕
·425 words·2 mins
FFmpeg 视频水印实战
·303 words·2 mins