diff --git a/plugins/obs-ffmpeg/obs-ffmpeg-nvenc.c b/plugins/obs-ffmpeg/obs-ffmpeg-nvenc.c index c27d61c64..6a29d3a32 100644 --- a/plugins/obs-ffmpeg/obs-ffmpeg-nvenc.c +++ b/plugins/obs-ffmpeg/obs-ffmpeg-nvenc.c @@ -39,6 +39,10 @@ struct nvenc_encoder { DARRAY(uint8_t) sei; }; +#ifdef __linux__ +extern bool ubuntu_20_04_nvenc_fallback; +#endif + #define ENCODER_NAME_H264 "NVIDIA NVENC H.264 (FFmpeg)" static const char *h264_nvenc_getname(void *unused) { @@ -122,6 +126,12 @@ static bool nvenc_update(struct nvenc_encoder *enc, obs_data_t *settings, rc = "CBR"; } +#ifdef __linux__ + bool use_old_nvenc = ubuntu_20_04_nvenc_fallback; +#else +#define use_old_nvenc false +#endif + info.format = voi->format; info.colorspace = voi->colorspace; info.range = voi->range; @@ -131,8 +141,8 @@ static bool nvenc_update(struct nvenc_encoder *enc, obs_data_t *settings, av_opt_set_int(enc->ffve.context->priv_data, "cbr", false, 0); av_opt_set(enc->ffve.context->priv_data, "profile", profile, 0); - if (obs_data_has_user_value(settings, "preset") && - !obs_data_has_user_value(settings, "preset2")) { + if (use_old_nvenc || (obs_data_has_user_value(settings, "preset") && + !obs_data_has_user_value(settings, "preset2"))) { if (astrcmpi(preset, "mq") == 0) { preset = "hq"; @@ -471,6 +481,12 @@ obs_properties_t *nvenc_properties_internal(enum codec_type codec, bool ffmpeg) obs_properties_t *props = obs_properties_create(); obs_property_t *p; +#ifdef __linux__ + bool use_old_nvenc = ubuntu_20_04_nvenc_fallback; +#else +#define use_old_nvenc false +#endif + p = obs_properties_add_list(props, "rate_control", obs_module_text("RateControl"), OBS_COMBO_TYPE_LIST, @@ -499,46 +515,60 @@ obs_properties_t *nvenc_properties_internal(enum codec_type codec, bool ffmpeg) 10, 1); obs_property_int_set_suffix(p, " s"); - p = obs_properties_add_list(props, "preset2", obs_module_text("Preset"), + p = obs_properties_add_list(props, use_old_nvenc ? "preset" : "preset2", + obs_module_text("Preset"), OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_STRING); #define add_preset(val) \ obs_property_list_add_string(p, obs_module_text("NVENC.Preset2." val), \ val) - add_preset("p1"); - add_preset("p2"); - add_preset("p3"); - add_preset("p4"); - add_preset("p5"); - add_preset("p6"); - add_preset("p7"); + if (use_old_nvenc) { + add_preset("mq"); + add_preset("hq"); + add_preset("default"); + add_preset("hp"); + add_preset("ll"); + add_preset("llhq"); + add_preset("llhp"); + } else { + add_preset("p1"); + add_preset("p2"); + add_preset("p3"); + add_preset("p4"); + add_preset("p5"); + add_preset("p6"); + add_preset("p7"); + } #undef add_preset - p = obs_properties_add_list(props, "tune", obs_module_text("Tuning"), - OBS_COMBO_TYPE_LIST, - OBS_COMBO_FORMAT_STRING); + if (!use_old_nvenc) { + 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"); + 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); + 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"); + add_multipass("disabled"); + add_multipass("qres"); + add_multipass("fullres"); #undef add_multipass + } p = obs_properties_add_list(props, "profile", obs_module_text("Profile"), diff --git a/plugins/obs-ffmpeg/obs-ffmpeg.c b/plugins/obs-ffmpeg/obs-ffmpeg.c index 053422d9e..90e105f09 100644 --- a/plugins/obs-ffmpeg/obs-ffmpeg.c +++ b/plugins/obs-ffmpeg/obs-ffmpeg.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -8,7 +9,6 @@ #ifdef _WIN32 #include -#include #include #include "jim-nvenc.h" @@ -231,6 +231,58 @@ extern bool load_nvenc_lib(void); extern uint32_t get_nvenc_ver(); #endif +/* please remove this annoying garbage and the associated garbage in + * obs-ffmpeg-nvenc.c when ubuntu 20.04 is finally gone for good. */ + +#ifdef __linux__ +bool ubuntu_20_04_nvenc_fallback = false; + +static void do_nvenc_check_for_ubuntu_20_04(void) +{ + FILE *fp; + char *line = NULL; + size_t linecap = 0; + struct dstr distro; + struct dstr version; + + fp = fopen("/etc/os-release", "r"); + if (!fp) { + return; + } + + dstr_init_copy(&distro, "Unknown"); + dstr_init_copy(&version, "Unknown"); + + while (getline(&line, &linecap, fp) != -1) { + if (!strncmp(line, "NAME", 4)) { + char *start = strchr(line, '='); + if (!start || *(++start) == '\0') + continue; + dstr_copy(&distro, start); + dstr_resize(&distro, distro.len - 1); + } + + if (!strncmp(line, "VERSION_ID", 10)) { + char *start = strchr(line, '='); + if (!start || *(++start) == '\0') + continue; + dstr_copy(&version, start); + dstr_resize(&version, version.len - 1); + } + } + + if (dstr_cmpi(&distro, "ubuntu") == 0 && + dstr_cmp(&version, "20.04") == 0) { + ubuntu_20_04_nvenc_fallback = true; + } + + fclose(fp); + dstr_free(&version); + dstr_free(&distro); + free(line); +} +#endif + static bool nvenc_codec_exists(const char *name, const char *fallback) { const AVCodec *nvenc = avcodec_find_encoder_by_name(name); @@ -338,6 +390,12 @@ bool obs_module_load(void) bool av1 = false; if (nvenc_supported(&h264, &hevc, &av1)) { blog(LOG_INFO, "NVENC supported"); + +#ifdef __linux__ + /* why are we here? just to suffer? */ + do_nvenc_check_for_ubuntu_20_04(); +#endif + #ifdef _WIN32 if (get_win_ver_int() > 0x0601) { jim_nvenc_load(h264, hevc, av1);