diff --git a/doc/codecs.texi b/doc/codecs.texi index ca7c52317b6483322fa703fdc1d6a6ce4df4d38d..9a3a56d7dc38f704a42dfb162ef3c549f235a39d 100644 --- a/doc/codecs.texi +++ b/doc/codecs.texi @@ -1272,6 +1272,10 @@ ffprobe -dump_separator " " -i ~/videos/matrixbench_mpeg2.mpg @end example +@item max_pixels @var{integer} (@emph{decoding/encoding,video}) +Maximum number of pixels per image. This value can be used to avoid out of +memory failures due to large images. + @end table @c man end CODEC OPTIONS diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 7ac2adaf66a486a79f8ee9636ccbbb60c3ab48a5..02234aee67263b5d32d989f75bddee72552d54e6 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -3570,6 +3570,14 @@ typedef struct AVCodecContext { */ int trailing_padding; + /** + * The number of pixels per image to maximally accept. + * + * - decoding: set by user + * - encoding: set by user + */ + int64_t max_pixels; + } AVCodecContext; AVRational av_codec_get_pkt_timebase (const AVCodecContext *avctx); diff --git a/libavcodec/options_table.h b/libavcodec/options_table.h index ee798599530305395242aa7c9259d84655f1a6e6..3fe792594f7605f5771bd8e162ab0bd720f1e15f 100644 --- a/libavcodec/options_table.h +++ b/libavcodec/options_table.h @@ -570,6 +570,7 @@ static const AVOption avcodec_options[] = { {"codec_whitelist", "List of decoders that are allowed to be used", OFFSET(codec_whitelist), AV_OPT_TYPE_STRING, { .str = NULL }, CHAR_MIN, CHAR_MAX, A|V|S|D }, {"pixel_format", "set pixel format", OFFSET(pix_fmt), AV_OPT_TYPE_PIXEL_FMT, {.i64=AV_PIX_FMT_NONE}, -1, INT_MAX, 0 }, {"video_size", "set video size", OFFSET(width), AV_OPT_TYPE_IMAGE_SIZE, {.str=NULL}, 0, INT_MAX, 0 }, +{"max_pixels", "Maximum number of pixels", OFFSET(max_pixels), AV_OPT_TYPE_INT64, {.i64 = INT_MAX }, 0, INT_MAX, A|V|S|D|E }, {NULL}, }; diff --git a/libavcodec/utils.c b/libavcodec/utils.c index 89a12c68a24f3f60aee90710bb0629713151cf57..44ecc09c96191b44d1068610c9dac4ac18981ca6 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -209,7 +209,7 @@ void avcodec_set_dimensions(AVCodecContext *s, int width, int height) int ff_set_dimensions(AVCodecContext *s, int width, int height) { - int ret = av_image_check_size(width, height, 0, s); + int ret = av_image_check_size2(width, height, s->max_pixels, AV_PIX_FMT_NONE, 0, s); if (ret < 0) width = height = 0; @@ -904,7 +904,7 @@ static int get_buffer_internal(AVCodecContext *avctx, AVFrame *frame, int flags) int ret; if (avctx->codec_type == AVMEDIA_TYPE_VIDEO) { - if ((ret = av_image_check_size(avctx->width, avctx->height, 0, avctx)) < 0 || avctx->pix_fmt<0) { + if ((ret = av_image_check_size2(avctx->width, avctx->height, avctx->max_pixels, AV_PIX_FMT_NONE, 0, avctx)) < 0 || avctx->pix_fmt<0) { av_log(avctx, AV_LOG_ERROR, "video_get_buffer: image parameters invalid\n"); return AVERROR(EINVAL); } @@ -1338,8 +1338,8 @@ int attribute_align_arg avcodec_open2(AVCodecContext *avctx, const AVCodec *code } if ((avctx->coded_width || avctx->coded_height || avctx->width || avctx->height) - && ( av_image_check_size(avctx->coded_width, avctx->coded_height, 0, avctx) < 0 - || av_image_check_size(avctx->width, avctx->height, 0, avctx) < 0)) { + && ( av_image_check_size2(avctx->coded_width, avctx->coded_height, avctx->max_pixels, AV_PIX_FMT_NONE, 0, avctx) < 0 + || av_image_check_size2(avctx->width, avctx->height, avctx->max_pixels, AV_PIX_FMT_NONE, 0, avctx) < 0)) { av_log(avctx, AV_LOG_WARNING, "Ignoring invalid width/height values\n"); ff_set_dimensions(avctx, 0, 0); } @@ -1982,7 +1982,7 @@ int attribute_align_arg avcodec_encode_video2(AVCodecContext *avctx, return 0; } - if (av_image_check_size(avctx->width, avctx->height, 0, avctx)) + if (av_image_check_size2(avctx->width, avctx->height, avctx->max_pixels, AV_PIX_FMT_NONE, 0, avctx)) return AVERROR(EINVAL); if (frame && frame->format == AV_PIX_FMT_NONE) @@ -2233,7 +2233,7 @@ int attribute_align_arg avcodec_decode_video2(AVCodecContext *avctx, AVFrame *pi } *got_picture_ptr = 0; - if ((avctx->coded_width || avctx->coded_height) && av_image_check_size(avctx->coded_width, avctx->coded_height, 0, avctx)) + if ((avctx->coded_width || avctx->coded_height) && av_image_check_size2(avctx->coded_width, avctx->coded_height, avctx->max_pixels, AV_PIX_FMT_NONE, 0, avctx)) return AVERROR(EINVAL); avctx->internal->pkt = avpkt; diff --git a/tests/ref/fate/api-mjpeg-codec-param b/tests/ref/fate/api-mjpeg-codec-param index c67d1b1ab04ae4027470f9723f8bf3bdceecd2ee..08313adab3e67cef75a632a4098c97ebae57e765 100644 --- a/tests/ref/fate/api-mjpeg-codec-param +++ b/tests/ref/fate/api-mjpeg-codec-param @@ -155,6 +155,7 @@ stream=0, decode=0 codec_whitelist= pixel_format=yuvj422p video_size=400x225 + max_pixels=2147483647 stream=0, decode=1 b=0 ab=0 @@ -312,3 +313,4 @@ stream=0, decode=1 codec_whitelist= pixel_format=yuvj422p video_size=400x225 + max_pixels=2147483647 diff --git a/tests/ref/fate/api-png-codec-param b/tests/ref/fate/api-png-codec-param index bd534418947e69551850b1b479e57dc47c2e2389..7a9a92146114fe6b0552eeca0ae0b67e3405be70 100644 --- a/tests/ref/fate/api-png-codec-param +++ b/tests/ref/fate/api-png-codec-param @@ -155,6 +155,7 @@ stream=0, decode=0 codec_whitelist= pixel_format=rgba video_size=128x128 + max_pixels=2147483647 stream=0, decode=1 b=0 ab=0 @@ -312,3 +313,4 @@ stream=0, decode=1 codec_whitelist= pixel_format=rgba video_size=128x128 + max_pixels=2147483647