1
0
Эх сурвалжийг харах

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.
Ryan Foster 2 жил өмнө
parent
commit
46e17a1160

+ 32 - 4
plugins/obs-ffmpeg/obs-ffmpeg-av1.c

@@ -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"