0
0
mirror of https://github.com/obsproject/obs-studio.git synced 2024-09-19 20:32:15 +02:00

obs-ffmpeg: Fix FFmpeg NVENC presets on Ubuntu 20.04

Ubuntu 20.04 and 22.04 both have the same FFmpeg versions, but FFmpeg on
20.04 was built with version 9 of NVENC headers, whereas 22.04 was built
with 11.

Unfortunately, that means we have to revert back to the old presets when
Ubuntu 20.04 is detected. The way this detection is done is a bit hacky,
but it's the only way to preserve startup performance. Otherwise we'd
have to write yet another startup subprocess test program to detect
whether the FFmpeg being used was built with older or newer NVENC, which
is both slow to start up and annoying to write. So instead, just get the
distro name/version strings and detect Ubuntu 20.04 that way.
This commit is contained in:
Jim 2022-10-25 21:51:08 -07:00
parent 4cc06ebdaa
commit dd26fe4f8a
2 changed files with 112 additions and 24 deletions

View File

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

View File

@ -1,3 +1,4 @@
#include <util/dstr.h>
#include <obs-module.h>
#include <util/platform.h>
#include <libavutil/avutil.h>
@ -8,7 +9,6 @@
#ifdef _WIN32
#include <dxgi.h>
#include <util/dstr.h>
#include <util/windows/win-version.h>
#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);