Skip to content

Commit

Permalink
vcomp/lavc: check MJPEG params validity
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
MartinPulec committed Aug 13, 2024
1 parent 39dd39c commit 5655d97
Showing 1 changed file with 39 additions and 1 deletion.
40 changes: 39 additions & 1 deletion src/video_compress/libavcodec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<const char *>(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<int>(codec_ctx->priv_data, "async_depth", 1);
Expand Down

0 comments on commit 5655d97

Please sign in to comment.