0
0
mirror of https://github.com/obsproject/obs-studio.git synced 2024-09-20 13:08:50 +02:00

mac-videotoolbox: Add CRF support on Apple silicon

Co-Authored-By: Sebastian Beckmann <beckmann.sebastian@outlook.de>
This commit is contained in:
AuroraWright 2022-06-22 18:02:05 +02:00 committed by Sebastian Beckmann
parent 9e0d7b3123
commit 84c7d87a7f
2 changed files with 40 additions and 10 deletions

View File

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

View File

@ -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);