obs-ffmpeg: Fix SVT-AV1 rate control mode selection

In updated versions of FFmpeg (5.1.x) and SVT-AV1 (1.2.0/1.3.0), the
rate contol mode selection mechanism has changed, causing CBR to throw
an "Invalid Parameter" error and the encoder will fail to start. This
appears to be caused by us specifying rc_max_rate, which will also fail
on FFmpeg CLI. Adjust how we manage rate control methods, appropriately
version-gated, to work with both our current dependency versions and the
versions that we'd like to use.
This commit is contained in:
Ryan Foster
2022-11-19 15:44:12 -08:00
committed by Jim
parent c7f4c78a69
commit 46e17a1160
+32 -4
View File
@@ -66,6 +66,7 @@ static bool av1_update(struct av1_encoder *enc, obs_data_t *settings)
int cqp = (int)obs_data_get_int(settings, "cqp");
int keyint_sec = (int)obs_data_get_int(settings, "keyint_sec");
int preset = (int)obs_data_get_int(settings, "preset");
AVDictionary *svtav1_opts = NULL;
video_t *video = obs_encoder_video(enc->ffve.encoder);
const struct video_output_info *voi = video_output_get_info(video);
@@ -94,31 +95,58 @@ static bool av1_update(struct av1_encoder *enc, obs_data_t *settings)
av_opt_set_int(enc->ffve.context->priv_data, "row-mt", 1, 0);
}
if (enc->svtav1)
if (enc->svtav1) {
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(59, 37, 100)
av_dict_set_int(&svtav1_opts, "rc", 1, 0);
#else
av_opt_set(enc->ffve.context->priv_data, "rc", "vbr", 0);
#endif
}
if (astrcmpi(rc, "cqp") == 0) {
bitrate = 0;
enc->ffve.context->global_quality = cqp;
if (enc->svtav1)
if (enc->svtav1) {
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(59, 37, 100)
av_dict_set_int(&svtav1_opts, "rc", 0, 0);
av_opt_set_int(enc->ffve.context->priv_data, "qp", cqp,
0);
#else
av_opt_set(enc->ffve.context->priv_data, "rc", "cqp",
0);
#endif
}
} else if (astrcmpi(rc, "vbr") != 0) { /* CBR by default */
const int64_t rate = bitrate * INT64_C(1000);
enc->ffve.context->rc_max_rate = rate;
enc->ffve.context->rc_min_rate = rate;
cqp = 0;
if (enc->svtav1)
if (enc->svtav1) {
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(59, 37, 100)
av_dict_set_int(&svtav1_opts, "rc", 2, 0);
av_dict_set_int(&svtav1_opts, "pred-struct", 1, 0);
av_dict_set_int(&svtav1_opts, "bias-pct", 0, 0);
av_dict_set_int(&svtav1_opts, "tbr", rate, 0);
#else
enc->ffve.context->rc_max_rate = rate;
av_opt_set(enc->ffve.context->priv_data, "rc", "cvbr",
0);
#endif
} else {
enc->ffve.context->rc_max_rate = rate;
}
}
if (enc->svtav1) {
av_opt_set_dict_val(enc->ffve.context->priv_data, "svtav1_opts",
svtav1_opts, 0);
}
const char *ffmpeg_opts = obs_data_get_string(settings, "ffmpeg_opts");
ffmpeg_video_encoder_update(&enc->ffve, bitrate, keyint_sec, voi, &info,
ffmpeg_opts);
av_dict_free(&svtav1_opts);
info("settings:\n"
"\tencoder: %s\n"