diff --git a/plugins/mac-videotoolbox/data/locale/en-US.ini b/plugins/mac-videotoolbox/data/locale/en-US.ini index 267cf523f..e12c23393 100644 --- a/plugins/mac-videotoolbox/data/locale/en-US.ini +++ b/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)" diff --git a/plugins/mac-videotoolbox/encoder.c b/plugins/mac-videotoolbox/encoder.c index 41eb760e4..47b07ebae 100644 --- a/plugins/mac-videotoolbox/encoder.c +++ b/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);