Sfoglia il codice sorgente

obs-ffmpeg: Update NVENC to new presets

(This commit also modifies the UI)
jp9000 3 anni fa
parent
commit
d7c7180a8c

+ 60 - 2
UI/obs-app.cpp

@@ -2805,6 +2805,64 @@ static void convert_14_2_encoder_setting(const char *encoder, const char *file)
 	obs_data_item_release(&cbr_item);
 	obs_data_item_release(&cbr_item);
 }
 }
 
 
+static void convert_28_1_encoder_setting(const char *encoder, const char *file)
+{
+	OBSDataAutoRelease data =
+		obs_data_create_from_json_file_safe(file, "bak");
+	bool modified = false;
+
+	if (astrcmpi(encoder, "jim_nvenc") == 0 ||
+	    astrcmpi(encoder, "jim_hevc_nvenc") == 0 ||
+	    astrcmpi(encoder, "ffmpeg_nvenc") == 0 ||
+	    astrcmpi(encoder, "ffmpeg_hevc_nvenc") == 0) {
+
+		if (obs_data_has_user_value(data, "preset") &&
+		    !obs_data_has_user_value(data, "preset2")) {
+			const char *preset =
+				obs_data_get_string(data, "preset");
+
+			if (astrcmpi(preset, "hq") == 0) {
+				obs_data_set_string(data, "preset2", "p6");
+				obs_data_set_string(data, "tune", "hq");
+				obs_data_set_string(data, "multipass", "qres");
+
+			} else if (astrcmpi(preset, "mq") == 0) {
+				obs_data_set_string(data, "preset2", "p4");
+				obs_data_set_string(data, "tune", "hq");
+				obs_data_set_string(data, "multipass", "qres");
+
+			} else if (astrcmpi(preset, "hp") == 0) {
+				obs_data_set_string(data, "preset2", "p1");
+				obs_data_set_string(data, "tune", "hq");
+				obs_data_set_string(data, "multipass",
+						    "disabled");
+
+			} else if (astrcmpi(preset, "ll") == 0) {
+				obs_data_set_string(data, "preset2", "p3");
+				obs_data_set_string(data, "tune", "ll");
+				obs_data_set_string(data, "multipass",
+						    "disabled");
+
+			} else if (astrcmpi(preset, "llhq") == 0) {
+				obs_data_set_string(data, "preset2", "p4");
+				obs_data_set_string(data, "tune", "ll");
+				obs_data_set_string(data, "multipass", "qres");
+
+			} else if (astrcmpi(preset, "llhp") == 0) {
+				obs_data_set_string(data, "preset2", "p2");
+				obs_data_set_string(data, "tune", "ll");
+				obs_data_set_string(data, "multipass",
+						    "disabled");
+			}
+
+			modified = true;
+		}
+	}
+
+	if (modified)
+		obs_data_save_json_safe(data, file, "tmp", "bak");
+}
+
 static void upgrade_settings(void)
 static void upgrade_settings(void)
 {
 {
 	char path[512];
 	char path[512];
@@ -2852,13 +2910,13 @@ static void upgrade_settings(void)
 				strcat(path, "/");
 				strcat(path, "/");
 				strcat(path, ent->d_name);
 				strcat(path, ent->d_name);
 				strcat(path, "/recordEncoder.json");
 				strcat(path, "/recordEncoder.json");
-				convert_14_2_encoder_setting(rEnc, path);
+				convert_28_1_encoder_setting(rEnc, path);
 
 
 				path[pathlen] = 0;
 				path[pathlen] = 0;
 				strcat(path, "/");
 				strcat(path, "/");
 				strcat(path, ent->d_name);
 				strcat(path, ent->d_name);
 				strcat(path, "/streamEncoder.json");
 				strcat(path, "/streamEncoder.json");
-				convert_14_2_encoder_setting(sEnc, path);
+				convert_28_1_encoder_setting(sEnc, path);
 			}
 			}
 
 
 			path[pathlen] = 0;
 			path[pathlen] = 0;

+ 0 - 2
UI/window-basic-main-outputs.cpp

@@ -671,7 +671,6 @@ void SimpleOutput::UpdateRecordingSettings_nvenc(int cqp)
 	OBSDataAutoRelease settings = obs_data_create();
 	OBSDataAutoRelease settings = obs_data_create();
 	obs_data_set_string(settings, "rate_control", "CQP");
 	obs_data_set_string(settings, "rate_control", "CQP");
 	obs_data_set_string(settings, "profile", "high");
 	obs_data_set_string(settings, "profile", "high");
-	obs_data_set_string(settings, "preset", "hq");
 	obs_data_set_int(settings, "cqp", cqp);
 	obs_data_set_int(settings, "cqp", cqp);
 
 
 	obs_encoder_update(videoRecording, settings);
 	obs_encoder_update(videoRecording, settings);
@@ -683,7 +682,6 @@ void SimpleOutput::UpdateRecordingSettings_nvenc_hevc(int cqp)
 	OBSDataAutoRelease settings = obs_data_create();
 	OBSDataAutoRelease settings = obs_data_create();
 	obs_data_set_string(settings, "rate_control", "CQP");
 	obs_data_set_string(settings, "rate_control", "CQP");
 	obs_data_set_string(settings, "profile", "main");
 	obs_data_set_string(settings, "profile", "main");
-	obs_data_set_string(settings, "preset", "hq");
 	obs_data_set_int(settings, "cqp", cqp);
 	obs_data_set_int(settings, "cqp", cqp);
 
 
 	obs_encoder_update(videoRecording, settings);
 	obs_encoder_update(videoRecording, settings);

+ 15 - 8
plugins/obs-ffmpeg/data/locale/en-US.ini

@@ -6,6 +6,7 @@ FFmpegOpts.ToolTip.Source="Allows you to set FFmpeg options. This only accepts o
 Bitrate="Bitrate"
 Bitrate="Bitrate"
 MaxBitrate="Max Bitrate"
 MaxBitrate="Max Bitrate"
 Preset="Preset"
 Preset="Preset"
+Tuning="Tuning"
 Profile="Profile"
 Profile="Profile"
 RateControl="Rate Control"
 RateControl="Rate Control"
 KeyframeIntervalSec="Keyframe Interval (0=auto)"
 KeyframeIntervalSec="Keyframe Interval (0=auto)"
@@ -20,14 +21,6 @@ BFrames="Max B-frames"
 VAAPI.Codec="VAAPI Codec"
 VAAPI.Codec="VAAPI Codec"
 VAAPI.Device="VAAPI Device"
 VAAPI.Device="VAAPI Device"
 
 
-NVENC.Use2Pass="Use Two-Pass Encoding"
-NVENC.Preset.default="Performance"
-NVENC.Preset.hq="Quality"
-NVENC.Preset.hp="Max Performance"
-NVENC.Preset.mq="Max Quality"
-NVENC.Preset.ll="Low-Latency"
-NVENC.Preset.llhq="Low-Latency Quality"
-NVENC.Preset.llhp="Low-Latency Performance"
 NVENC.LookAhead="Look-ahead"
 NVENC.LookAhead="Look-ahead"
 NVENC.LookAhead.ToolTip="Enables dynamic B-frames.\n\nIf disabled, the encoder will always use the number of B-frames specified in the 'Max B-frames' setting.\n\nIf enabled, it will increase visual quality by only using however many B-frames are necessary, up to the maximum,\nat the cost of increased GPU utilization."
 NVENC.LookAhead.ToolTip="Enables dynamic B-frames.\n\nIf disabled, the encoder will always use the number of B-frames specified in the 'Max B-frames' setting.\n\nIf enabled, it will increase visual quality by only using however many B-frames are necessary, up to the maximum,\nat the cost of increased GPU utilization."
 NVENC.PsychoVisualTuning="Psycho Visual Tuning"
 NVENC.PsychoVisualTuning="Psycho Visual Tuning"
@@ -37,6 +30,20 @@ NVENC.8bitUnsupportedHdr="OBS does not support 8-bit output of Rec. 2100."
 NVENC.I010Unsupported="NVENC does not support I010. Use P010 instead."
 NVENC.I010Unsupported="NVENC does not support I010. Use P010 instead."
 NVENC.10bitUnsupported="Cannot perform 10-bit encode on this encoder."
 NVENC.10bitUnsupported="Cannot perform 10-bit encode on this encoder."
 NVENC.TooManyBFrames="Max B-frames setting (%d) is more than encoder supports (%d)."
 NVENC.TooManyBFrames="Max B-frames setting (%d) is more than encoder supports (%d)."
+NVENC.Preset2.p1="P1: Fastest (Lowest Quality)"
+NVENC.Preset2.p2="P2: Faster (Lower Quality)"
+NVENC.Preset2.p3="P3: Fast (Low Quality)"
+NVENC.Preset2.p4="P4: Medium (Default)"
+NVENC.Preset2.p5="P5: Slow (Good Quality)"
+NVENC.Preset2.p6="P6: Slower (Better Quality)"
+NVENC.Preset2.p7="P7: Slowest (Best Quality)"
+NVENC.Tuning.hq="High Quality"
+NVENC.Tuning.ll="Low Latency"
+NVENC.Tuning.ull="Ultra Low Latency"
+NVENC.Multipass="Multipass Mode"
+NVENC.Multipass.disabled="Single Pass"
+NVENC.Multipass.qres="Two Passes (Quarter Resolution)"
+NVENC.Multipass.fullres="Two Passes (Full Resolution)"
 
 
 AMF.Preset.speed="Speed"
 AMF.Preset.speed="Speed"
 AMF.Preset.balanced="Balanced"
 AMF.Preset.balanced="Balanced"

+ 99 - 45
plugins/obs-ffmpeg/jim-nvenc.c

@@ -10,9 +10,6 @@
 #include <d3d11_1.h>
 #include <d3d11_1.h>
 #include <obs-hevc.h>
 #include <obs-hevc.h>
 
 
-/* TODO: Use new preset scheme */
-#pragma warning(disable : 4996)
-
 /* ========================================================================= */
 /* ========================================================================= */
 
 
 #define EXTRA_BUFFERS 5
 #define EXTRA_BUFFERS 5
@@ -329,7 +326,8 @@ static bool init_session(struct nvenc_data *enc)
 
 
 static void initialize_params(NV_ENC_INITIALIZE_PARAMS *params,
 static void initialize_params(NV_ENC_INITIALIZE_PARAMS *params,
 			      const GUID *nv_encode, const GUID *nv_preset,
 			      const GUID *nv_encode, const GUID *nv_preset,
-			      uint32_t width, uint32_t height, uint32_t fps_num,
+			      NV_ENC_TUNING_INFO nv_tuning, uint32_t width,
+			      uint32_t height, uint32_t fps_num,
 			      uint32_t fps_den, NV_ENC_CONFIG *config)
 			      uint32_t fps_den, NV_ENC_CONFIG *config)
 {
 {
 	int darWidth, darHeight;
 	int darWidth, darHeight;
@@ -348,6 +346,48 @@ static void initialize_params(NV_ENC_INITIALIZE_PARAMS *params,
 	params->enableEncodeAsync = 0;
 	params->enableEncodeAsync = 0;
 	params->enablePTD = 1;
 	params->enablePTD = 1;
 	params->encodeConfig = config;
 	params->encodeConfig = config;
+	params->tuningInfo = nv_tuning;
+}
+
+static inline GUID get_nv_preset2(const char *preset2)
+{
+	if (astrcmpi(preset2, "p1") == 0) {
+		return NV_ENC_PRESET_P1_GUID;
+	} else if (astrcmpi(preset2, "p2") == 0) {
+		return NV_ENC_PRESET_P2_GUID;
+	} else if (astrcmpi(preset2, "p3") == 0) {
+		return NV_ENC_PRESET_P3_GUID;
+	} else if (astrcmpi(preset2, "p4") == 0) {
+		return NV_ENC_PRESET_P4_GUID;
+	} else if (astrcmpi(preset2, "p6") == 0) {
+		return NV_ENC_PRESET_P6_GUID;
+	} else if (astrcmpi(preset2, "p7") == 0) {
+		return NV_ENC_PRESET_P7_GUID;
+	} else {
+		return NV_ENC_PRESET_P5_GUID;
+	}
+}
+
+static inline NV_ENC_TUNING_INFO get_nv_tuning(const char *tuning)
+{
+	if (astrcmpi(tuning, "ll") == 0) {
+		return NV_ENC_TUNING_INFO_LOW_LATENCY;
+	} else if (astrcmpi(tuning, "ull") == 0) {
+		return NV_ENC_TUNING_INFO_ULTRA_LOW_LATENCY;
+	} else {
+		return NV_ENC_TUNING_INFO_HIGH_QUALITY;
+	}
+}
+
+static inline NV_ENC_MULTI_PASS get_nv_multipass(const char *multipass)
+{
+	if (astrcmpi(multipass, "qres") == 0) {
+		return NV_ENC_TWO_PASS_QUARTER_RESOLUTION;
+	} else if (astrcmpi(multipass, "fullres") == 0) {
+		return NV_ENC_TWO_PASS_FULL_RESOLUTION;
+	} else {
+		return NV_ENC_MULTI_PASS_DISABLED;
+	}
 }
 }
 
 
 static bool init_encoder_base(struct nvenc_data *enc, obs_data_t *settings,
 static bool init_encoder_base(struct nvenc_data *enc, obs_data_t *settings,
@@ -359,6 +399,9 @@ static bool init_encoder_base(struct nvenc_data *enc, obs_data_t *settings,
 	int cqp = (int)obs_data_get_int(settings, "cqp");
 	int cqp = (int)obs_data_get_int(settings, "cqp");
 	int keyint_sec = (int)obs_data_get_int(settings, "keyint_sec");
 	int keyint_sec = (int)obs_data_get_int(settings, "keyint_sec");
 	const char *preset = obs_data_get_string(settings, "preset");
 	const char *preset = obs_data_get_string(settings, "preset");
+	const char *preset2 = obs_data_get_string(settings, "preset2");
+	const char *tuning = obs_data_get_string(settings, "tune");
+	const char *multipass = obs_data_get_string(settings, "multipass");
 	const char *profile = obs_data_get_string(settings, "profile");
 	const char *profile = obs_data_get_string(settings, "profile");
 	bool lookahead = obs_data_get_bool(settings, "lookahead");
 	bool lookahead = obs_data_get_bool(settings, "lookahead");
 	bool vbr = astrcmpi(rc, "VBR") == 0;
 	bool vbr = astrcmpi(rc, "VBR") == 0;
@@ -373,34 +416,42 @@ static bool init_encoder_base(struct nvenc_data *enc, obs_data_t *settings,
 	/* -------------------------- */
 	/* -------------------------- */
 	/* get preset                 */
 	/* get preset                 */
 
 
-	GUID nv_preset = NV_ENC_PRESET_DEFAULT_GUID;
-	bool twopass = false;
-	bool hp = false;
-	bool ll = false;
-
-	if (astrcmpi(preset, "hq") == 0) {
-		nv_preset = NV_ENC_PRESET_HQ_GUID;
-
-	} else if (astrcmpi(preset, "mq") == 0) {
-		nv_preset = NV_ENC_PRESET_HQ_GUID;
-		twopass = true;
-
-	} else if (astrcmpi(preset, "hp") == 0) {
-		nv_preset = NV_ENC_PRESET_HP_GUID;
-		hp = true;
-
-	} else if (astrcmpi(preset, "ll") == 0) {
-		nv_preset = NV_ENC_PRESET_LOW_LATENCY_DEFAULT_GUID;
-		ll = true;
-
-	} else if (astrcmpi(preset, "llhq") == 0) {
-		nv_preset = NV_ENC_PRESET_LOW_LATENCY_HQ_GUID;
-		ll = true;
-
-	} else if (astrcmpi(preset, "llhp") == 0) {
-		nv_preset = NV_ENC_PRESET_LOW_LATENCY_HP_GUID;
-		hp = true;
-		ll = true;
+	GUID nv_preset = get_nv_preset2(preset2);
+	NV_ENC_TUNING_INFO nv_tuning = get_nv_tuning(tuning);
+	NV_ENC_MULTI_PASS nv_multipass = get_nv_multipass(multipass);
+
+	if (obs_data_has_user_value(settings, "preset") &&
+	    !obs_data_has_user_value(settings, "preset2")) {
+		if (astrcmpi(preset, "hq") == 0) {
+			nv_preset = NV_ENC_PRESET_P5_GUID;
+			nv_tuning = NV_ENC_TUNING_INFO_HIGH_QUALITY;
+			nv_multipass = NV_ENC_TWO_PASS_QUARTER_RESOLUTION;
+
+		} else if (astrcmpi(preset, "mq") == 0) {
+			nv_preset = NV_ENC_PRESET_P4_GUID;
+			nv_tuning = NV_ENC_TUNING_INFO_HIGH_QUALITY;
+			nv_multipass = NV_ENC_TWO_PASS_QUARTER_RESOLUTION;
+
+		} else if (astrcmpi(preset, "hp") == 0) {
+			nv_preset = NV_ENC_PRESET_P1_GUID;
+			nv_tuning = NV_ENC_TUNING_INFO_HIGH_QUALITY;
+			nv_multipass = NV_ENC_MULTI_PASS_DISABLED;
+
+		} else if (astrcmpi(preset, "ll") == 0) {
+			nv_preset = NV_ENC_PRESET_P3_GUID;
+			nv_tuning = NV_ENC_TUNING_INFO_LOW_LATENCY;
+			nv_multipass = NV_ENC_MULTI_PASS_DISABLED;
+
+		} else if (astrcmpi(preset, "llhq") == 0) {
+			nv_preset = NV_ENC_PRESET_P4_GUID;
+			nv_tuning = NV_ENC_TUNING_INFO_LOW_LATENCY;
+			nv_multipass = NV_ENC_TWO_PASS_QUARTER_RESOLUTION;
+
+		} else if (astrcmpi(preset, "llhp") == 0) {
+			nv_preset = NV_ENC_PRESET_P2_GUID;
+			nv_tuning = NV_ENC_TUNING_INFO_LOW_LATENCY;
+			nv_multipass = NV_ENC_MULTI_PASS_DISABLED;
+		}
 	}
 	}
 
 
 	const bool rc_lossless = astrcmpi(rc, "lossless") == 0;
 	const bool rc_lossless = astrcmpi(rc, "lossless") == 0;
@@ -409,10 +460,13 @@ static bool init_encoder_base(struct nvenc_data *enc, obs_data_t *settings,
 		*lossless =
 		*lossless =
 			nv_get_cap(enc, NV_ENC_CAPS_SUPPORT_LOSSLESS_ENCODE);
 			nv_get_cap(enc, NV_ENC_CAPS_SUPPORT_LOSSLESS_ENCODE);
 		if (*lossless) {
 		if (*lossless) {
-			nv_preset = hp ? NV_ENC_PRESET_LOSSLESS_HP_GUID
-				       : NV_ENC_PRESET_LOSSLESS_DEFAULT_GUID;
+			nv_tuning = NV_ENC_TUNING_INFO_LOSSLESS;
+			nv_multipass = NV_ENC_MULTI_PASS_DISABLED;
 		} else {
 		} else {
 			warn("lossless encode is not supported, ignoring");
 			warn("lossless encode is not supported, ignoring");
+			nv_preset = NV_ENC_PRESET_P5_GUID;
+			nv_tuning = NV_ENC_TUNING_INFO_HIGH_QUALITY;
+			nv_multipass = NV_ENC_TWO_PASS_QUARTER_RESOLUTION;
 		}
 		}
 	}
 	}
 
 
@@ -422,8 +476,9 @@ static bool init_encoder_base(struct nvenc_data *enc, obs_data_t *settings,
 	NV_ENC_PRESET_CONFIG preset_config = {NV_ENC_PRESET_CONFIG_VER,
 	NV_ENC_PRESET_CONFIG preset_config = {NV_ENC_PRESET_CONFIG_VER,
 					      {NV_ENC_CONFIG_VER}};
 					      {NV_ENC_CONFIG_VER}};
 
 
-	err = nv.nvEncGetEncodePresetConfig(enc->session, enc->codec_guid,
-					    nv_preset, &preset_config);
+	err = nv.nvEncGetEncodePresetConfigEx(enc->session, enc->codec_guid,
+					      nv_preset, nv_tuning,
+					      &preset_config);
 	if (nv_failed(enc->encoder, err, __FUNCTION__,
 	if (nv_failed(enc->encoder, err, __FUNCTION__,
 		      "nvEncGetEncodePresetConfig")) {
 		      "nvEncGetEncodePresetConfig")) {
 		return false;
 		return false;
@@ -439,7 +494,7 @@ static bool init_encoder_base(struct nvenc_data *enc, obs_data_t *settings,
 
 
 	NV_ENC_CONFIG *config = &enc->config;
 	NV_ENC_CONFIG *config = &enc->config;
 
 
-	initialize_params(&enc->params, &enc->codec_guid, &nv_preset,
+	initialize_params(&enc->params, &enc->codec_guid, &nv_preset, nv_tuning,
 			  voi->width, voi->height, voi->fps_num, voi->fps_den,
 			  voi->width, voi->height, voi->fps_num, voi->fps_den,
 			  &enc->config);
 			  &enc->config);
 
 
@@ -500,8 +555,7 @@ static bool init_encoder_base(struct nvenc_data *enc, obs_data_t *settings,
 		nv_get_cap(enc, NV_ENC_CAPS_SUPPORT_DYN_BITRATE_CHANGE) &&
 		nv_get_cap(enc, NV_ENC_CAPS_SUPPORT_DYN_BITRATE_CHANGE) &&
 		!lookahead;
 		!lookahead;
 
 
-	config->rcParams.rateControlMode = twopass ? NV_ENC_PARAMS_RC_VBR_HQ
-						   : NV_ENC_PARAMS_RC_VBR;
+	config->rcParams.rateControlMode = NV_ENC_PARAMS_RC_VBR;
 
 
 	if (astrcmpi(rc, "cqp") == 0 || rc_lossless) {
 	if (astrcmpi(rc, "cqp") == 0 || rc_lossless) {
 		if (*lossless)
 		if (*lossless)
@@ -517,14 +571,13 @@ static bool init_encoder_base(struct nvenc_data *enc, obs_data_t *settings,
 		max_bitrate = 0;
 		max_bitrate = 0;
 
 
 	} else if (astrcmpi(rc, "vbr") != 0) { /* CBR by default */
 	} else if (astrcmpi(rc, "vbr") != 0) { /* CBR by default */
-		config->rcParams.rateControlMode =
-			twopass ? NV_ENC_PARAMS_RC_2_PASS_QUALITY
-				: NV_ENC_PARAMS_RC_CBR;
+		config->rcParams.rateControlMode = NV_ENC_PARAMS_RC_CBR;
 	}
 	}
 
 
 	config->rcParams.averageBitRate = bitrate * 1000;
 	config->rcParams.averageBitRate = bitrate * 1000;
 	config->rcParams.maxBitRate = vbr ? max_bitrate * 1000 : bitrate * 1000;
 	config->rcParams.maxBitRate = vbr ? max_bitrate * 1000 : bitrate * 1000;
 	config->rcParams.vbvBufferSize = bitrate * 1000;
 	config->rcParams.vbvBufferSize = bitrate * 1000;
+	config->rcParams.multiPass = nv_multipass;
 
 
 	/* -------------------------- */
 	/* -------------------------- */
 	/* initialize                 */
 	/* initialize                 */
@@ -536,15 +589,16 @@ static bool init_encoder_base(struct nvenc_data *enc, obs_data_t *settings,
 	     "\tcqp:          %d\n"
 	     "\tcqp:          %d\n"
 	     "\tkeyint:       %d\n"
 	     "\tkeyint:       %d\n"
 	     "\tpreset:       %s\n"
 	     "\tpreset:       %s\n"
+	     "\ttuning:       %s\n"
+	     "\tmultipass:    %s\n"
 	     "\tprofile:      %s\n"
 	     "\tprofile:      %s\n"
 	     "\twidth:        %d\n"
 	     "\twidth:        %d\n"
 	     "\theight:       %d\n"
 	     "\theight:       %d\n"
-	     "\t2-pass:       %s\n"
 	     "\tb-frames:     %d\n"
 	     "\tb-frames:     %d\n"
 	     "\tlookahead:    %s\n"
 	     "\tlookahead:    %s\n"
 	     "\tpsycho_aq:    %s\n",
 	     "\tpsycho_aq:    %s\n",
-	     get_codec_name(enc->codec), rc, bitrate, cqp, gop_size, preset,
-	     profile, enc->cx, enc->cy, twopass ? "true" : "false", bf,
+	     get_codec_name(enc->codec), rc, bitrate, cqp, gop_size, preset2,
+	     tuning, multipass, profile, enc->cx, enc->cy, bf,
 	     lookahead ? "true" : "false", psycho_aq ? "true" : "false");
 	     lookahead ? "true" : "false", psycho_aq ? "true" : "false");
 
 
 	return true;
 	return true;

+ 69 - 39
plugins/obs-ffmpeg/obs-ffmpeg-nvenc.c

@@ -100,6 +100,9 @@ static bool nvenc_update(struct nvenc_encoder *enc, obs_data_t *settings,
 	int cqp = (int)obs_data_get_int(settings, "cqp");
 	int cqp = (int)obs_data_get_int(settings, "cqp");
 	int keyint_sec = (int)obs_data_get_int(settings, "keyint_sec");
 	int keyint_sec = (int)obs_data_get_int(settings, "keyint_sec");
 	const char *preset = obs_data_get_string(settings, "preset");
 	const char *preset = obs_data_get_string(settings, "preset");
+	const char *preset2 = obs_data_get_string(settings, "preset2");
+	const char *tuning = obs_data_get_string(settings, "tune");
+	const char *multipass = obs_data_get_string(settings, "multipass");
 	const char *profile = obs_data_get_string(settings, "profile");
 	const char *profile = obs_data_get_string(settings, "profile");
 	int gpu = (int)obs_data_get_int(settings, "gpu");
 	int gpu = (int)obs_data_get_int(settings, "gpu");
 	bool cbr_override = obs_data_get_bool(settings, "cbr");
 	bool cbr_override = obs_data_get_bool(settings, "cbr");
@@ -123,17 +126,24 @@ static bool nvenc_update(struct nvenc_encoder *enc, obs_data_t *settings,
 	info.colorspace = voi->colorspace;
 	info.colorspace = voi->colorspace;
 	info.range = voi->range;
 	info.range = voi->range;
 
 
-	bool twopass = false;
-
-	if (astrcmpi(preset, "mq") == 0) {
-		twopass = true;
-		preset = "hq";
-	}
-
 	nvenc_video_info(enc, &info);
 	nvenc_video_info(enc, &info);
+
 	av_opt_set_int(enc->ffve.context->priv_data, "cbr", false, 0);
 	av_opt_set_int(enc->ffve.context->priv_data, "cbr", false, 0);
 	av_opt_set(enc->ffve.context->priv_data, "profile", profile, 0);
 	av_opt_set(enc->ffve.context->priv_data, "profile", profile, 0);
-	av_opt_set(enc->ffve.context->priv_data, "preset", preset, 0);
+
+	if (obs_data_has_user_value(settings, "preset") &&
+	    !obs_data_has_user_value(settings, "preset2")) {
+
+		if (astrcmpi(preset, "mq") == 0) {
+			preset = "hq";
+		}
+		av_opt_set(enc->ffve.context->priv_data, "preset", preset, 0);
+	} else {
+		av_opt_set(enc->ffve.context->priv_data, "preset", preset2, 0);
+		av_opt_set(enc->ffve.context->priv_data, "tune", tuning, 0);
+		av_opt_set(enc->ffve.context->priv_data, "multipass", multipass,
+			   0);
+	}
 
 
 	if (astrcmpi(rc, "cqp") == 0) {
 	if (astrcmpi(rc, "cqp") == 0) {
 		bitrate = 0;
 		bitrate = 0;
@@ -143,11 +153,9 @@ static bool nvenc_update(struct nvenc_encoder *enc, obs_data_t *settings,
 		bitrate = 0;
 		bitrate = 0;
 		cqp = 0;
 		cqp = 0;
 
 
-		bool hp = (astrcmpi(preset, "hp") == 0 ||
-			   astrcmpi(preset, "llhp") == 0);
-
-		av_opt_set(enc->ffve.context->priv_data, "preset",
-			   hp ? "losslesshp" : "lossless", 0);
+		av_opt_set(enc->ffve.context->priv_data, "tune", "lossless", 0);
+		av_opt_set(enc->ffve.context->priv_data, "multipass",
+			   "disabled", 0);
 
 
 	} else if (astrcmpi(rc, "vbr") != 0) { /* CBR by default */
 	} else if (astrcmpi(rc, "vbr") != 0) { /* CBR by default */
 		av_opt_set_int(enc->ffve.context->priv_data, "cbr", true, 0);
 		av_opt_set_int(enc->ffve.context->priv_data, "cbr", true, 0);
@@ -158,7 +166,6 @@ static bool nvenc_update(struct nvenc_encoder *enc, obs_data_t *settings,
 	}
 	}
 
 
 	av_opt_set(enc->ffve.context->priv_data, "level", "auto", 0);
 	av_opt_set(enc->ffve.context->priv_data, "level", "auto", 0);
-	av_opt_set_int(enc->ffve.context->priv_data, "2pass", twopass, 0);
 	av_opt_set_int(enc->ffve.context->priv_data, "gpu", gpu, 0);
 	av_opt_set_int(enc->ffve.context->priv_data, "gpu", gpu, 0);
 
 
 	set_psycho_aq(enc, psycho_aq);
 	set_psycho_aq(enc, psycho_aq);
@@ -176,17 +183,17 @@ static bool nvenc_update(struct nvenc_encoder *enc, obs_data_t *settings,
 	     "\tcqp:          %d\n"
 	     "\tcqp:          %d\n"
 	     "\tkeyint:       %d\n"
 	     "\tkeyint:       %d\n"
 	     "\tpreset:       %s\n"
 	     "\tpreset:       %s\n"
+	     "\ttuning:       %s\n"
+	     "\tmultipass:    %s\n"
 	     "\tprofile:      %s\n"
 	     "\tprofile:      %s\n"
 	     "\twidth:        %d\n"
 	     "\twidth:        %d\n"
 	     "\theight:       %d\n"
 	     "\theight:       %d\n"
-	     "\t2-pass:       %s\n"
 	     "\tb-frames:     %d\n"
 	     "\tb-frames:     %d\n"
 	     "\tpsycho-aq:    %d\n"
 	     "\tpsycho-aq:    %d\n"
 	     "\tGPU:          %d\n",
 	     "\tGPU:          %d\n",
 	     enc->ffve.enc_name, rc, bitrate, cqp, enc->ffve.context->gop_size,
 	     enc->ffve.enc_name, rc, bitrate, cqp, enc->ffve.context->gop_size,
-	     preset, profile, enc->ffve.context->width, enc->ffve.height,
-	     twopass ? "true" : "false", enc->ffve.context->max_b_frames,
-	     psycho_aq, gpu);
+	     preset2, tuning, multipass, profile, enc->ffve.context->width,
+	     enc->ffve.height, enc->ffve.context->max_b_frames, psycho_aq, gpu);
 
 
 	return ffmpeg_video_encoder_init_codec(&enc->ffve);
 	return ffmpeg_video_encoder_init_codec(&enc->ffve);
 }
 }
@@ -405,7 +412,9 @@ void h264_nvenc_defaults(obs_data_t *settings)
 	obs_data_set_default_int(settings, "keyint_sec", 0);
 	obs_data_set_default_int(settings, "keyint_sec", 0);
 	obs_data_set_default_int(settings, "cqp", 20);
 	obs_data_set_default_int(settings, "cqp", 20);
 	obs_data_set_default_string(settings, "rate_control", "CBR");
 	obs_data_set_default_string(settings, "rate_control", "CBR");
-	obs_data_set_default_string(settings, "preset", "hq");
+	obs_data_set_default_string(settings, "preset2", "p6");
+	obs_data_set_default_string(settings, "multipass", "qres");
+	obs_data_set_default_string(settings, "tune", "hq");
 	obs_data_set_default_string(settings, "profile", "high");
 	obs_data_set_default_string(settings, "profile", "high");
 	obs_data_set_default_bool(settings, "psycho_aq", true);
 	obs_data_set_default_bool(settings, "psycho_aq", true);
 	obs_data_set_default_int(settings, "gpu", 0);
 	obs_data_set_default_int(settings, "gpu", 0);
@@ -421,7 +430,8 @@ void hevc_nvenc_defaults(obs_data_t *settings)
 	obs_data_set_default_int(settings, "keyint_sec", 0);
 	obs_data_set_default_int(settings, "keyint_sec", 0);
 	obs_data_set_default_int(settings, "cqp", 20);
 	obs_data_set_default_int(settings, "cqp", 20);
 	obs_data_set_default_string(settings, "rate_control", "CBR");
 	obs_data_set_default_string(settings, "rate_control", "CBR");
-	obs_data_set_default_string(settings, "preset", "hq");
+	obs_data_set_default_string(settings, "preset2", "p6");
+	obs_data_set_default_string(settings, "tune", "hq");
 	obs_data_set_default_string(settings, "profile", "main");
 	obs_data_set_default_string(settings, "profile", "main");
 	obs_data_set_default_bool(settings, "psycho_aq", true);
 	obs_data_set_default_bool(settings, "psycho_aq", true);
 	obs_data_set_default_int(settings, "gpu", 0);
 	obs_data_set_default_int(settings, "gpu", 0);
@@ -437,7 +447,6 @@ static bool rate_control_modified(obs_properties_t *ppts, obs_property_t *p,
 	bool cqp = astrcmpi(rc, "CQP") == 0;
 	bool cqp = astrcmpi(rc, "CQP") == 0;
 	bool vbr = astrcmpi(rc, "VBR") == 0;
 	bool vbr = astrcmpi(rc, "VBR") == 0;
 	bool lossless = astrcmpi(rc, "lossless") == 0;
 	bool lossless = astrcmpi(rc, "lossless") == 0;
-	size_t count;
 
 
 	p = obs_properties_get(ppts, "bitrate");
 	p = obs_properties_get(ppts, "bitrate");
 	obs_property_set_visible(p, !cqp && !lossless);
 	obs_property_set_visible(p, !cqp && !lossless);
@@ -445,14 +454,10 @@ static bool rate_control_modified(obs_properties_t *ppts, obs_property_t *p,
 	obs_property_set_visible(p, vbr);
 	obs_property_set_visible(p, vbr);
 	p = obs_properties_get(ppts, "cqp");
 	p = obs_properties_get(ppts, "cqp");
 	obs_property_set_visible(p, cqp);
 	obs_property_set_visible(p, cqp);
-
-	p = obs_properties_get(ppts, "preset");
-	count = obs_property_list_item_count(p);
-
-	for (size_t i = 0; i < count; i++) {
-		bool compatible = (i == 0 || i == 3);
-		obs_property_list_item_disable(p, i, lossless && !compatible);
-	}
+	p = obs_properties_get(ppts, "preset2");
+	obs_property_set_visible(p, !lossless);
+	p = obs_properties_get(ppts, "tune");
+	obs_property_set_visible(p, !lossless);
 
 
 	return true;
 	return true;
 }
 }
@@ -490,22 +495,47 @@ obs_properties_t *nvenc_properties_internal(bool hevc, bool ffmpeg)
 				   10, 1);
 				   10, 1);
 	obs_property_int_set_suffix(p, " s");
 	obs_property_int_set_suffix(p, " s");
 
 
-	p = obs_properties_add_list(props, "preset", obs_module_text("Preset"),
+	p = obs_properties_add_list(props, "preset2", obs_module_text("Preset"),
 				    OBS_COMBO_TYPE_LIST,
 				    OBS_COMBO_TYPE_LIST,
 				    OBS_COMBO_FORMAT_STRING);
 				    OBS_COMBO_FORMAT_STRING);
 
 
-#define add_preset(val)                                                       \
-	obs_property_list_add_string(p, obs_module_text("NVENC.Preset." val), \
+#define add_preset(val)                                                        \
+	obs_property_list_add_string(p, obs_module_text("NVENC.Preset2." val), \
 				     val)
 				     val)
-	add_preset("mq");
-	add_preset("hq");
-	add_preset("default");
-	add_preset("hp");
-	add_preset("ll");
-	add_preset("llhq");
-	add_preset("llhp");
+	add_preset("p1");
+	add_preset("p2");
+	add_preset("p3");
+	add_preset("p4");
+	add_preset("p5");
+	add_preset("p6");
+	add_preset("p7");
 #undef add_preset
 #undef add_preset
 
 
+	p = obs_properties_add_list(props, "tune", obs_module_text("Tuning"),
+				    OBS_COMBO_TYPE_LIST,
+				    OBS_COMBO_FORMAT_STRING);
+
+#define add_tune(val)                                                         \
+	obs_property_list_add_string(p, obs_module_text("NVENC.Tuning." val), \
+				     val)
+	add_tune("hq");
+	add_tune("ll");
+	add_tune("ull");
+#undef add_tune
+
+	p = obs_properties_add_list(props, "multipass",
+				    obs_module_text("NVENC.Multipass"),
+				    OBS_COMBO_TYPE_LIST,
+				    OBS_COMBO_FORMAT_STRING);
+
+#define add_multipass(val)            \
+	obs_property_list_add_string( \
+		p, obs_module_text("NVENC.Multipass." val), val)
+	add_multipass("disabled");
+	add_multipass("qres");
+	add_multipass("fullres");
+#undef add_multipass
+
 	p = obs_properties_add_list(props, "profile",
 	p = obs_properties_add_list(props, "profile",
 				    obs_module_text("Profile"),
 				    obs_module_text("Profile"),
 				    OBS_COMBO_TYPE_LIST,
 				    OBS_COMBO_TYPE_LIST,