From 5655d9754fffe63e216bd8296c1ffd0647eaaf3b Mon Sep 17 00:00:00 2001 From: Martin Pulec Date: Tue, 13 Aug 2024 12:12:04 +0200 Subject: [PATCH] vcomp/lavc: check MJPEG params validity MJPEG does produce wrong JPEGs[^1] if either slices or threads == 1 and the other not (until now also the implicit case, because the values are auto-adjusted). So if either is 1, auto-set the other value to 1 as well. If both are set and either is 1 and the other not, issue at least a warning. [^1]: for the s=1 && t>1, FFmpeg own decoder is capable to decode, but the bitstream is definitely wrong - instead of RST markers there are EOI markers. --- src/video_compress/libavcodec.cpp | 40 ++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/src/video_compress/libavcodec.cpp b/src/video_compress/libavcodec.cpp index e606623c9..aa6d605ba 100644 --- a/src/video_compress/libavcodec.cpp +++ b/src/video_compress/libavcodec.cpp @@ -1636,10 +1636,48 @@ static void setparam_default(AVCodecContext *codec_ctx, struct setparam_param * } } -static void setparam_jpeg(AVCodecContext *codec_ctx, struct setparam_param * /* param */) +/// check and possibly fix incorrect slices and threads combination for MJPEG +static void +mjpeg_adjust_param(struct setparam_param *param) +{ + char warn[STR_LEN]; + warn[0] = '\0'; + if (param->slices == 1) { + if (param->thread_mode.empty()) { + snprintf_ch(warn, "MJPEG requested slice=1, " + "setting thread count=1"); + param->thread_mode = "1"; + } else if (strtol(param->thread_mode.c_str(), nullptr, 10) != + 1) { + snprintf_ch(warn, "slice=1 with thread count!=1 not " + "recommended"); + } + } else if (strtol(param->thread_mode.c_str(), nullptr, 10) == 1) { + if (param->slices == -1) { + snprintf_ch(warn, "MJPEG requested threads=1, " + "setting slices=1"); + param->slices = 1; + } else if (param->slices > 1) { + snprintf_ch(warn, "slice>1 with thread count=1 not " + "recommended"); + } + } + + if (strlen(warn) == 0) { + return; + } + MSG(WARNING, + "%s. If seems that FFmpeg JPEG encoder requires " + "both slice and threads to be 1, if any of it " + "is or the JPEG is broken.\n", + warn); +} + +static void setparam_jpeg(AVCodecContext *codec_ctx, struct setparam_param *param) { if (strcmp(codec_ctx->codec->name, "mjpeg") == 0) { check_av_opt_set(codec_ctx->priv_data, "huffman", "default", "Huffman tables"); + mjpeg_adjust_param(param); } if (strcmp(codec_ctx->codec->name, "mjpeg_qsv") == 0) { check_av_opt_set(codec_ctx->priv_data, "async_depth", 1);