Просмотр исходного кода

mac-videotoolbox: Add CRF support on Apple silicon

Co-Authored-By: Sebastian Beckmann <[email protected]>
AuroraWright 3 лет назад
Родитель
Сommit
84c7d87a7f
2 измененных файлов с 40 добавлено и 10 удалено
  1. 1 0
      plugins/mac-videotoolbox/data/locale/en-US.ini
  2. 39 10
      plugins/mac-videotoolbox/encoder.c

+ 1 - 0
plugins/mac-videotoolbox/data/locale/en-US.ini

@@ -2,6 +2,7 @@ VTH264EncHW="Apple VT H264 Hardware Encoder"
 VTH264EncSW="Apple VT H264 Software Encoder"
 VTEncoder="VideoToolbox Encoder"
 Bitrate="Bitrate"
+Quality="Quality"
 UseMaxBitrate="Limit bitrate"
 MaxBitrate="Maximum bitrate"
 MaxBitrateWindow="Maximum bitrate window (seconds)"

+ 39 - 10
plugins/mac-videotoolbox/encoder.c

@@ -37,6 +37,7 @@ struct vt_encoder {
 	uint32_t fps_den;
 	const char *rate_control;
 	uint32_t bitrate;
+	float quality;
 	bool limit_bitrate;
 	uint32_t rc_max_bitrate;
 	float rc_max_bitrate_window;
@@ -147,8 +148,8 @@ static OSStatus session_set_prop(VTCompressionSessionRef session,
 
 static OSStatus session_set_bitrate(VTCompressionSessionRef session,
 				    const char *rate_control, int new_bitrate,
-				    bool limit_bitrate, int max_bitrate,
-				    float max_bitrate_window)
+				    float quality, bool limit_bitrate,
+				    int max_bitrate, float max_bitrate_window)
 {
 	OSStatus code;
 
@@ -174,6 +175,10 @@ static OSStatus session_set_bitrate(VTCompressionSessionRef session,
 			session, kVTCompressionPropertyKey_AverageBitRate,
 			new_bitrate * 1000));
 		can_limit_bitrate = true;
+	} else if (strcmp(rate_control, "CRF") == 0) {
+		SESSION_CHECK(session_set_prop_float(
+			session, kVTCompressionPropertyKey_Quality, quality));
+		can_limit_bitrate = true;
 	} else {
 		VT_LOG(LOG_ERROR,
 		       "Selected rate control method is not supported: %s",
@@ -355,9 +360,10 @@ static bool create_encoder(struct vt_encoder *enc)
 	STATUS_CHECK(session_set_prop(s, kVTCompressionPropertyKey_ProfileLevel,
 				      obs_to_vt_profile(enc->profile)));
 
-	STATUS_CHECK(session_set_bitrate(
-		s, enc->rate_control, enc->bitrate, enc->limit_bitrate,
-		enc->rc_max_bitrate, enc->rc_max_bitrate_window));
+	STATUS_CHECK(session_set_bitrate(s, enc->rate_control, enc->bitrate,
+					 enc->quality, enc->limit_bitrate,
+					 enc->rc_max_bitrate,
+					 enc->rc_max_bitrate_window));
 
 	STATUS_CHECK(session_set_colorspace(s, enc->colorspace));
 
@@ -398,6 +404,7 @@ static void dump_encoder_info(struct vt_encoder *enc)
 		"\tvt_encoder_id          %s\n"
 		"\trate_control:          %s\n"
 		"\tbitrate:               %d (kbps)\n"
+		"\tquality:               %f\n"
 		"\tfps_num:               %d\n"
 		"\tfps_den:               %d\n"
 		"\twidth:                 %d\n"
@@ -409,8 +416,8 @@ static void dump_encoder_info(struct vt_encoder *enc)
 		"\thw_enc:                %s\n"
 		"\tprofile:               %s\n",
 		enc->vt_encoder_id, enc->rate_control, enc->bitrate,
-		enc->fps_num, enc->fps_den, enc->width, enc->height,
-		enc->keyint, enc->limit_bitrate ? "on" : "off",
+		enc->quality, enc->fps_num, enc->fps_den, enc->width,
+		enc->height, enc->keyint, enc->limit_bitrate ? "on" : "off",
 		enc->rc_max_bitrate, enc->rc_max_bitrate_window,
 		enc->hw_enc ? "on" : "off",
 		(enc->profile != NULL && !!strlen(enc->profile)) ? enc->profile
@@ -464,6 +471,7 @@ static void update_params(struct vt_encoder *enc, obs_data_t *settings)
 	enc->keyint = (uint32_t)obs_data_get_int(settings, "keyint_sec");
 	enc->rate_control = obs_data_get_string(settings, "rate_control");
 	enc->bitrate = (uint32_t)obs_data_get_int(settings, "bitrate");
+	enc->quality = ((float)obs_data_get_int(settings, "quality")) / 100;
 	enc->profile = obs_data_get_string(settings, "profile");
 	enc->limit_bitrate = obs_data_get_bool(settings, "limit_bitrate");
 	enc->rc_max_bitrate = obs_data_get_int(settings, "max_bitrate");
@@ -486,7 +494,8 @@ static bool vt_update(void *data, obs_data_t *settings)
 		return true;
 
 	OSStatus code = session_set_bitrate(enc->session, enc->rate_control,
-					    enc->bitrate, enc->limit_bitrate,
+					    enc->bitrate, enc->quality,
+					    enc->limit_bitrate,
 					    enc->rc_max_bitrate,
 					    enc->rc_max_bitrate_window);
 	if (code != noErr)
@@ -854,6 +863,7 @@ static const char *vt_getname(void *data)
 
 #define TEXT_VT_ENCODER obs_module_text("VTEncoder")
 #define TEXT_BITRATE obs_module_text("Bitrate")
+#define TEXT_QUALITY obs_module_text("Quality")
 #define TEXT_USE_MAX_BITRATE obs_module_text("UseMaxBitrate")
 #define TEXT_MAX_BITRATE obs_module_text("MaxBitrate")
 #define TEXT_MAX_BITRATE_WINDOW obs_module_text("MaxBitrateWindow")
@@ -868,15 +878,22 @@ static bool rate_control_limit_bitrate_modified(obs_properties_t *ppts,
 						obs_property_t *p,
 						obs_data_t *settings)
 {
+	bool has_bitrate = true;
 	bool can_limit_bitrate = true;
 	bool use_limit_bitrate = obs_data_get_bool(settings, "limit_bitrate");
 	const char *rate_control =
 		obs_data_get_string(settings, "rate_control");
 
-	if (strcmp(rate_control, "CBR") == 0)
+	if (strcmp(rate_control, "CBR") == 0) {
 		can_limit_bitrate = false;
-	else if (strcmp(rate_control, "ABR") == 0)
+		has_bitrate = true;
+	} else if (strcmp(rate_control, "CRF") == 0) {
+		can_limit_bitrate = true;
+		has_bitrate = false;
+	} else if (strcmp(rate_control, "ABR") == 0) {
 		can_limit_bitrate = true;
+		has_bitrate = true;
+	}
 
 	p = obs_properties_get(ppts, "limit_bitrate");
 	obs_property_set_visible(p, can_limit_bitrate);
@@ -884,6 +901,11 @@ static bool rate_control_limit_bitrate_modified(obs_properties_t *ppts,
 	obs_property_set_visible(p, can_limit_bitrate && use_limit_bitrate);
 	p = obs_properties_get(ppts, "max_bitrate_window");
 	obs_property_set_visible(p, can_limit_bitrate && use_limit_bitrate);
+
+	p = obs_properties_get(ppts, "bitrate");
+	obs_property_set_visible(p, has_bitrate);
+	p = obs_properties_get(ppts, "quality");
+	obs_property_set_visible(p, !has_bitrate);
 	return true;
 }
 
@@ -904,12 +926,18 @@ static obs_properties_t *vt_properties(void *unused)
 #endif
 			obs_property_list_add_string(p, "CBR", "CBR");
 	obs_property_list_add_string(p, "ABR", "ABR");
+#ifndef __aarch64__
+	if (os_get_emulation_status() == true)
+#endif
+		obs_property_list_add_string(p, "CRF", "CRF");
 	obs_property_set_modified_callback(p,
 					   rate_control_limit_bitrate_modified);
 
 	p = obs_properties_add_int(props, "bitrate", TEXT_BITRATE, 50, 10000000,
 				   50);
 	obs_property_int_set_suffix(p, " Kbps");
+	obs_properties_add_int_slider(props, "quality", TEXT_QUALITY, 0, 100,
+				      1);
 
 	p = obs_properties_add_bool(props, "limit_bitrate",
 				    TEXT_USE_MAX_BITRATE);
@@ -948,6 +976,7 @@ static void vt_defaults(obs_data_t *settings)
 			obs_data_set_default_string(settings, "rate_control",
 						    "CBR");
 	obs_data_set_default_int(settings, "bitrate", 2500);
+	obs_data_set_default_int(settings, "quality", 60);
 	obs_data_set_default_bool(settings, "limit_bitrate", false);
 	obs_data_set_default_int(settings, "max_bitrate", 2500);
 	obs_data_set_default_double(settings, "max_bitrate_window", 1.5f);