diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index af7758f..9f6bbad 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -30,6 +30,9 @@ jobs: known_hosts: ${{ secrets.KNOWN_HOSTS }} if_key_exists: replace + - name: Update apt cache + run: apt-get update + - name: Build Package run: ./main.sh diff --git a/debian/changelog b/debian/changelog index a4dc502..e640628 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +obs-studio (29.1.3-100pika1) pikauwu; urgency=low + + Update to 29.1.3 + + -- Kevin Henkel Sat, 04 Feb 2023 12:48:06 +0100 + obs-studio (29.0.2.git2ac3767-99pika1.lunar) lunar; urgency=low Update to lunar diff --git a/debian/control b/debian/control index da4cf8a..b4c13d9 100644 --- a/debian/control +++ b/debian/control @@ -6,7 +6,6 @@ Uploaders: Kevin Henkel Build-Depends: debhelper (>= 9), cdbs, cmake, git, libx11-dev, libgl1-mesa-dev | libgl-dev, libpulse-dev, libxcb-composite0-dev, libxinerama-dev, libv4l-dev, libudev-dev, libfreetype6-dev, libfontconfig-dev, qt6-base-dev, qt6-base-private-dev, libqt6svg6-dev, libx264-dev, libxcb-xinerama0-dev, libxcb-shm0-dev, libavformat-dev, libavcodec-dev, libavutil-dev, libswscale-dev, libswresample-dev, libavdevice-dev, libavfilter-dev, libfdk-aac-dev, libjack-jackd2-dev, libcurl4-openssl-dev, libspeexdsp-dev, libvlc-dev, libasound2-dev, libluajit-5.1-dev, python3-dev, swig, libmbedtls-dev, pkg-config, libxcb-randr0-dev, libxcb-xfixes0-dev, libx11-xcb-dev, libxcb1-dev, libjansson-dev, libnss3-dev, libxtst-dev, libatspi2.0-dev, libatk-bridge2.0-dev, libatk1.0-dev, libgtk2.0-dev, libgtkglext1-dev, libxss-dev, linux-generic, v4l2loopback-dkms, libwayland-dev, libpci-dev, libdrm-dev, libpipewire-0.3-dev, librist-dev, libsrt-openssl-dev, libva-dev, libuuid1, nlohmann-json3-dev, libwebsocketpp-dev, libasio-dev, libffmpeg-amf-dev Homepage: http://obsproject.org - Package: obs-studio Architecture: amd64 Depends: ${shlibs:Depends}, ${misc:Depends}, qt6-wayland, qt6-qpa-plugins, obs-gstreamer-vaapi-plugin, obs-gamecapture-plugin diff --git a/debian/rules b/debian/rules index fbc773b..3e4ddbe 100755 --- a/debian/rules +++ b/debian/rules @@ -7,5 +7,5 @@ AJA_DIR := $(BASE_DIR)/ntv2 %: dh $@ override_dh_auto_configure: - dh_auto_configure -- -DOBS_VERSION_OVERRIDE="29.0.2" -DBUILD_FOR_PPA=ON -DTWITCH_CLIENTID='unla3~mb`xq9`1dhr?1lhhg`65mah0' -DTWITCH_HASH='2D4A98C454B4B0B6' -DRESTREAM_CLIENTID='ml6b16ec(n9?1#9g?m#>9f0,gnkojhhd;oh6' -DRESTREAM_HASH='2DE8E8C514397EE9' -DYOUTUBE_CLIENTID='153066229607$$;a7mw2ig756r?vc ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include ++#include ++ ++using namespace amf; ++ ++struct adapter_caps { ++ bool is_amd = false; ++ bool supports_avc = false; ++ bool supports_hevc = false; ++ bool supports_av1 = false; ++}; ++ ++static AMFFactory *amf_factory = nullptr; ++static std::map adapter_info; ++ ++static bool has_encoder(AMFContextPtr &amf_context, const wchar_t *encoder_name) ++{ ++ AMFComponentPtr encoder; ++ AMF_RESULT res = amf_factory->CreateComponent(amf_context, encoder_name, ++ &encoder); ++ return res == AMF_OK; ++} ++ ++static bool get_adapter_caps(uint32_t adapter_idx) ++{ ++ if (adapter_idx) ++ return false; ++ ++ adapter_caps &caps = adapter_info[adapter_idx]; ++ ++ AMF_RESULT res; ++ AMFContextPtr amf_context; ++ res = amf_factory->CreateContext(&amf_context); ++ if (res != AMF_OK) ++ return true; ++ ++ AMFContext1 *context1 = NULL; ++ res = amf_context->QueryInterface(AMFContext1::IID(), ++ (void **)&context1); ++ if (res != AMF_OK) ++ return false; ++ res = context1->InitVulkan(nullptr); ++ context1->Release(); ++ if (res != AMF_OK) ++ return false; ++ ++ caps.is_amd = true; ++ caps.supports_avc = has_encoder(amf_context, AMFVideoEncoderVCE_AVC); ++ caps.supports_hevc = has_encoder(amf_context, AMFVideoEncoder_HEVC); ++ caps.supports_av1 = has_encoder(amf_context, AMFVideoEncoder_AV1); ++ ++ return true; ++} ++ ++int main(void) ++try { ++ AMF_RESULT res; ++ VkResult vkres; ++ ++ VkApplicationInfo app_info = {}; ++ app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; ++ app_info.pApplicationName = "obs-amf-test"; ++ app_info.apiVersion = VK_API_VERSION_1_2; ++ ++ VkInstanceCreateInfo info = {}; ++ info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; ++ info.pApplicationInfo = &app_info; ++ ++ VkInstance instance; ++ vkres = vkCreateInstance(&info, nullptr, &instance); ++ if (vkres != VK_SUCCESS) ++ throw "Failed to initialize Vulkan"; ++ ++ uint32_t device_count; ++ vkres = vkEnumeratePhysicalDevices(instance, &device_count, nullptr); ++ if (vkres != VK_SUCCESS || !device_count) ++ throw "Failed to enumerate Vulkan devices"; ++ ++ VkPhysicalDevice *devices = new VkPhysicalDevice[device_count]; ++ vkres = vkEnumeratePhysicalDevices(instance, &device_count, devices); ++ if (vkres != VK_SUCCESS) ++ throw "Failed to enumerate Vulkan devices"; ++ ++ VkPhysicalDeviceDriverProperties driver_props = {}; ++ driver_props.sType = ++ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES; ++ VkPhysicalDeviceProperties2 device_props = {}; ++ device_props.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2; ++ device_props.pNext = &driver_props; ++ vkGetPhysicalDeviceProperties2(devices[0], &device_props); ++ ++ if (strcmp(driver_props.driverName, "AMD proprietary driver")) ++ throw "Not running AMD proprietary driver"; ++ ++ vkDestroyInstance(instance, nullptr); ++ ++ /* --------------------------------------------------------- */ ++ /* try initializing amf, I guess */ ++ ++ void *amf_module = dlopen(AMF_DLL_NAMEA, RTLD_LAZY); ++ if (!amf_module) ++ throw "Failed to load AMF lib"; ++ ++ auto init = (AMFInit_Fn)dlsym(amf_module, AMF_INIT_FUNCTION_NAME); ++ if (!init) ++ throw "Failed to get init func"; ++ ++ res = init(AMF_FULL_VERSION, &amf_factory); ++ if (res != AMF_OK) ++ throw "AMFInit failed"; ++ ++ uint32_t idx = 0; ++ while (get_adapter_caps(idx++)) ++ ; ++ ++ for (auto &[idx, caps] : adapter_info) { ++ printf("[%u]\n", idx); ++ printf("is_amd=%s\n", caps.is_amd ? "true" : "false"); ++ printf("supports_avc=%s\n", ++ caps.supports_avc ? "true" : "false"); ++ printf("supports_hevc=%s\n", ++ caps.supports_hevc ? "true" : "false"); ++ printf("supports_av1=%s\n", ++ caps.supports_av1 ? "true" : "false"); ++ } ++ ++ return 0; ++} catch (const char *text) { ++ printf("[error]\nstring=%s\n", text); ++ return 0; ++} +diff --git a/plugins/obs-ffmpeg/obs-ffmpeg.c b/plugins/obs-ffmpeg/obs-ffmpeg.c +index da0b2c2b4..92421c6f3 100644 +--- a/plugins/obs-ffmpeg/obs-ffmpeg.c ++++ b/plugins/obs-ffmpeg/obs-ffmpeg.c +@@ -360,6 +360,9 @@ static bool hevc_vaapi_supported(void) + #ifdef _WIN32 + extern void jim_nvenc_load(bool h264, bool hevc, bool av1); + extern void jim_nvenc_unload(void); ++#endif ++ ++#if defined(_WIN32) || defined(__linux__) + extern void amf_load(void); + extern void amf_unload(void); + #endif +@@ -434,7 +437,7 @@ bool obs_module_load(void) + #endif + } + +-#ifdef _WIN32 ++#if defined(_WIN32) || defined(__linux__) + amf_load(); + #endif + +@@ -475,8 +478,11 @@ void obs_module_unload(void) + obs_ffmpeg_unload_logging(); + #endif + +-#ifdef _WIN32 ++#if defined(_WIN32) || defined(__linux__) + amf_unload(); ++#endif ++ ++#ifdef _WIN32 + jim_nvenc_unload(); + #endif + } +diff --git a/plugins/obs-ffmpeg/texture-amf-opts.hpp b/plugins/obs-ffmpeg/texture-amf-opts.hpp +index b1c37d200..d28e3f77e 100644 +--- a/plugins/obs-ffmpeg/texture-amf-opts.hpp ++++ b/plugins/obs-ffmpeg/texture-amf-opts.hpp +@@ -321,7 +321,7 @@ static void amf_apply_opt(amf_base *enc, obs_option *opt) + val = atoi(opt->value); + } + +- os_utf8_to_wcs(opt->name, 0, wname, _countof(wname)); ++ os_utf8_to_wcs(opt->name, 0, wname, amf_countof(wname)); + if (is_bool) { + bool bool_val = (bool)val; + set_amf_property(enc, wname, bool_val); +diff --git a/plugins/obs-ffmpeg/texture-amf.cpp b/plugins/obs-ffmpeg/texture-amf.cpp +index abd1d6f92..871087710 100644 +--- a/plugins/obs-ffmpeg/texture-amf.cpp ++++ b/plugins/obs-ffmpeg/texture-amf.cpp +@@ -11,6 +11,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -18,6 +19,7 @@ + #include + #include + ++#ifdef _WIN32 + #include + #include + #include +@@ -25,6 +27,8 @@ + #include + #include + #include ++#endif ++ + #include + #include + #include +@@ -55,8 +59,10 @@ struct amf_error { + + struct handle_tex { + uint32_t handle; ++#ifdef _WIN32 + ComPtr tex; + ComPtr km; ++#endif + }; + + struct adapter_caps { +@@ -72,7 +78,7 @@ static std::map caps; + static bool h264_supported = false; + static AMFFactory *amf_factory = nullptr; + static AMFTrace *amf_trace = nullptr; +-static HMODULE amf_module = nullptr; ++static void *amf_module = nullptr; + static uint64_t amf_version = 0; + + /* ========================================================================= */ +@@ -120,9 +126,11 @@ struct amf_base { + virtual void init() = 0; + }; + +-using d3dtex_t = ComPtr; + using buf_t = std::vector; + ++#ifdef _WIN32 ++using d3dtex_t = ComPtr; ++ + struct amf_texencode : amf_base, public AMFSurfaceObserver { + volatile bool destroying = false; + +@@ -159,6 +167,7 @@ struct amf_texencode : amf_base, public AMFSurfaceObserver { + throw amf_error("InitDX11 failed", res); + } + }; ++#endif + + struct amf_fallback : amf_base, public AMFSurfaceObserver { + volatile bool destroying = false; +@@ -186,9 +195,21 @@ struct amf_fallback : amf_base, public AMFSurfaceObserver { + + void init() override + { ++#if defined(_WIN32) + AMF_RESULT res = amf_context->InitDX11(nullptr, AMF_DX11_1); + if (res != AMF_OK) + throw amf_error("InitDX11 failed", res); ++#elif defined(__linux__) ++ AMFContext1 *context1 = NULL; ++ AMF_RESULT res = amf_context->QueryInterface( ++ AMFContext1::IID(), (void **)&context1); ++ if (res != AMF_OK) ++ throw amf_error("CreateContext1 failed", res); ++ res = context1->InitVulkan(nullptr); ++ context1->Release(); ++ if (res != AMF_OK) ++ throw amf_error("InitVulkan failed", res); ++#endif + } + }; + +@@ -230,13 +251,18 @@ static void set_amf_property(amf_base *enc, const wchar_t *name, const T &value) + : (enc->codec == amf_codec_type::HEVC) \ + ? AMF_VIDEO_ENCODER_HEVC_##name \ + : AMF_VIDEO_ENCODER_AV1_##name) ++#define get_opt_name_enum(name) \ ++ ((enc->codec == amf_codec_type::AVC) ? (int)AMF_VIDEO_ENCODER_##name \ ++ : (enc->codec == amf_codec_type::HEVC) \ ++ ? (int)AMF_VIDEO_ENCODER_HEVC_##name \ ++ : (int)AMF_VIDEO_ENCODER_AV1_##name) + #define set_opt(name, value) set_amf_property(enc, get_opt_name(name), value) + #define get_opt(name, value) get_amf_property(enc, get_opt_name(name), value) + #define set_avc_opt(name, value) set_avc_property(enc, name, value) + #define set_hevc_opt(name, value) set_hevc_property(enc, name, value) + #define set_av1_opt(name, value) set_av1_property(enc, name, value) + #define set_enum_opt(name, value) \ +- set_amf_property(enc, get_opt_name(name), get_opt_name(name##_##value)) ++ set_amf_property(enc, get_opt_name(name), get_opt_name_enum(name##_##value)) + #define set_avc_enum(name, value) \ + set_avc_property(enc, name, AMF_VIDEO_ENCODER_##name##_##value) + #define set_hevc_enum(name, value) \ +@@ -247,6 +273,7 @@ static void set_amf_property(amf_base *enc, const wchar_t *name, const T &value) + /* ------------------------------------------------------------------------- */ + /* Implementation */ + ++#ifdef _WIN32 + static HMODULE get_lib(const char *lib) + { + HMODULE mod = GetModuleHandleA(lib); +@@ -393,6 +420,7 @@ static void get_tex_from_handle(amf_texencode *enc, uint32_t handle, + *km_out = km.Detach(); + *tex_out = tex.Detach(); + } ++#endif + + static constexpr amf_int64 macroblock_size = 16; + +@@ -504,7 +532,7 @@ static void convert_to_encoder_packet(amf_base *enc, AMFDataPtr &data, + enc->packet_data = AMFBufferPtr(data); + data->GetProperty(L"PTS", &packet->pts); + +- const wchar_t *get_output_type; ++ const wchar_t *get_output_type = NULL; + switch (enc->codec) { + case amf_codec_type::AVC: + get_output_type = AMF_VIDEO_ENCODER_OUTPUT_DATA_TYPE; +@@ -638,6 +666,7 @@ static void amf_encode_base(amf_base *enc, AMFSurface *amf_surf, + static bool amf_encode_tex(void *data, uint32_t handle, int64_t pts, + uint64_t lock_key, uint64_t *next_key, + encoder_packet *packet, bool *received_packet) ++#ifdef _WIN32 + try { + amf_texencode *enc = (amf_texencode *)data; + ID3D11DeviceContext *context = enc->context; +@@ -714,6 +743,18 @@ try { + *received_packet = false; + return false; + } ++#else ++{ ++ UNUSED_PARAMETER(data); ++ UNUSED_PARAMETER(handle); ++ UNUSED_PARAMETER(pts); ++ UNUSED_PARAMETER(lock_key); ++ UNUSED_PARAMETER(next_key); ++ UNUSED_PARAMETER(packet); ++ UNUSED_PARAMETER(received_packet); ++ return false; ++} ++#endif + + static buf_t alloc_buf(amf_fallback *enc) + { +@@ -1177,6 +1218,7 @@ static const char *amf_avc_get_name(void *) + + static inline int get_avc_preset(amf_base *enc, const char *preset) + { ++ UNUSED_PARAMETER(enc); + if (astrcmpi(preset, "quality") == 0) + return AMF_VIDEO_ENCODER_QUALITY_PRESET_QUALITY; + else if (astrcmpi(preset, "speed") == 0) +@@ -1287,7 +1329,7 @@ static bool amf_avc_init(void *data, obs_data_t *settings) + set_avc_property(enc, B_PIC_PATTERN, bf); + + } else if (bf != 0) { +- warn("B-Frames set to %lld but b-frames are not " ++ warn("B-Frames set to %" PRId64 " but b-frames are not " + "supported by this device", + bf); + bf = 0; +@@ -1332,12 +1374,12 @@ static bool amf_avc_init(void *data, obs_data_t *settings) + + info("settings:\n" + "\trate_control: %s\n" +- "\tbitrate: %d\n" +- "\tcqp: %d\n" ++ "\tbitrate: %" PRId64 "\n" ++ "\tcqp: %" PRId64 "\n" + "\tkeyint: %d\n" + "\tpreset: %s\n" + "\tprofile: %s\n" +- "\tb-frames: %d\n" ++ "\tb-frames: %" PRId64 "\n" + "\twidth: %d\n" + "\theight: %d\n" + "\tparams: %s", +@@ -1407,6 +1449,7 @@ static void amf_avc_create_internal(amf_base *enc, obs_data_t *settings) + + static void *amf_avc_create_texencode(obs_data_t *settings, + obs_encoder_t *encoder) ++#ifdef _WIN32 + try { + check_texture_encode_capability(encoder, amf_codec_type::AVC); + +@@ -1429,6 +1472,12 @@ try { + blog(LOG_ERROR, "[texture-amf-h264] %s: %s", __FUNCTION__, err); + return obs_encoder_create_rerouted(encoder, "h264_fallback_amf"); + } ++#else ++{ ++ UNUSED_PARAMETER(settings); ++ return obs_encoder_create_rerouted(encoder, "h264_fallback_amf"); ++} ++#endif + + static void *amf_avc_create_fallback(obs_data_t *settings, + obs_encoder_t *encoder) +@@ -1521,6 +1570,7 @@ static const char *amf_hevc_get_name(void *) + + static inline int get_hevc_preset(amf_base *enc, const char *preset) + { ++ UNUSED_PARAMETER(enc); + if (astrcmpi(preset, "balanced") == 0) + return AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET_BALANCED; + else if (astrcmpi(preset, "speed") == 0) +@@ -1640,8 +1690,8 @@ static bool amf_hevc_init(void *data, obs_data_t *settings) + + info("settings:\n" + "\trate_control: %s\n" +- "\tbitrate: %d\n" +- "\tcqp: %d\n" ++ "\tbitrate: %" PRId64 "\n" ++ "\tcqp: %" PRId64 "\n" + "\tkeyint: %d\n" + "\tpreset: %s\n" + "\tprofile: %s\n" +@@ -1758,6 +1808,7 @@ static void amf_hevc_create_internal(amf_base *enc, obs_data_t *settings) + + static void *amf_hevc_create_texencode(obs_data_t *settings, + obs_encoder_t *encoder) ++#ifdef _WIN32 + try { + check_texture_encode_capability(encoder, amf_codec_type::HEVC); + +@@ -1780,6 +1831,12 @@ try { + blog(LOG_ERROR, "[texture-amf-h265] %s: %s", __FUNCTION__, err); + return obs_encoder_create_rerouted(encoder, "h265_fallback_amf"); + } ++#else ++{ ++ UNUSED_PARAMETER(settings); ++ return obs_encoder_create_rerouted(encoder, "h265_fallback_amf"); ++} ++#endif + + static void *amf_hevc_create_fallback(obs_data_t *settings, + obs_encoder_t *encoder) +@@ -1868,6 +1925,7 @@ static const char *amf_av1_get_name(void *) + + static inline int get_av1_preset(amf_base *enc, const char *preset) + { ++ UNUSED_PARAMETER(enc); + if (astrcmpi(preset, "highquality") == 0) + return AMF_VIDEO_ENCODER_AV1_QUALITY_PRESET_HIGH_QUALITY; + else if (astrcmpi(preset, "quality") == 0) +@@ -2001,8 +2059,8 @@ static bool amf_av1_init(void *data, obs_data_t *settings) + + info("settings:\n" + "\trate_control: %s\n" +- "\tbitrate: %d\n" +- "\tcqp: %d\n" ++ "\tbitrate: %" PRId64 "\n" ++ "\tcqp: %" PRId64 "\n" + "\tkeyint: %d\n" + "\tpreset: %s\n" + "\tprofile: %s\n" +@@ -2066,6 +2124,7 @@ static void amf_av1_create_internal(amf_base *enc, obs_data_t *settings) + + static void *amf_av1_create_texencode(obs_data_t *settings, + obs_encoder_t *encoder) ++#ifdef _WIN32 + try { + check_texture_encode_capability(encoder, amf_codec_type::AV1); + +@@ -2088,6 +2147,12 @@ try { + blog(LOG_ERROR, "[texture-amf-av1] %s: %s", __FUNCTION__, err); + return obs_encoder_create_rerouted(encoder, "av1_fallback_amf"); + } ++#else ++{ ++ UNUSED_PARAMETER(settings); ++ return obs_encoder_create_rerouted(encoder, "av1_fallback_amf"); ++} ++#endif + + static void *amf_av1_create_fallback(obs_data_t *settings, + obs_encoder_t *encoder) +@@ -2185,9 +2250,16 @@ static bool enum_luids(void *param, uint32_t idx, uint64_t luid) + return true; + } + ++#ifdef _WIN32 ++#define OBS_AMF_TEST "obs-amf-test.exe" ++#else ++#define OBS_AMF_TEST "obs-amf-test" ++#endif ++ + extern "C" void amf_load(void) + try { + AMF_RESULT res; ++#ifdef _WIN32 + HMODULE amf_module_test; + + /* Check if the DLL is present before running the more expensive */ +@@ -2197,16 +2269,24 @@ try { + if (!amf_module_test) + throw "No AMF library"; + FreeLibrary(amf_module_test); ++#else ++ void *amf_module_test = os_dlopen(AMF_DLL_NAMEA); ++ if (!amf_module_test) ++ throw "No AMF library"; ++ os_dlclose(amf_module_test); ++#endif + + /* ----------------------------------- */ + /* Check for supported codecs */ + +- BPtr test_exe = os_get_executable_path_ptr("obs-amf-test.exe"); ++ BPtr test_exe = os_get_executable_path_ptr(OBS_AMF_TEST); + std::stringstream cmd; + std::string caps_str; + + cmd << test_exe; ++#ifdef _WIN32 + enum_graphics_device_luids(enum_luids, &cmd); ++#endif + + os_process_pipe_t *pp = os_process_pipe_create(cmd.str().c_str(), "r"); + if (!pp) +@@ -2266,12 +2346,12 @@ try { + /* ----------------------------------- */ + /* Init AMF */ + +- amf_module = LoadLibraryW(AMF_DLL_NAME); ++ amf_module = os_dlopen(AMF_DLL_NAMEA); + if (!amf_module) + throw "AMF library failed to load"; + + AMFInit_Fn init = +- (AMFInit_Fn)GetProcAddress(amf_module, AMF_INIT_FUNCTION_NAME); ++ (AMFInit_Fn)os_dlsym(amf_module, AMF_INIT_FUNCTION_NAME); + if (!init) + throw "Failed to get AMFInit address"; + +@@ -2283,7 +2363,7 @@ try { + if (res != AMF_OK) + throw amf_error("GetTrace failed", res); + +- AMFQueryVersion_Fn get_ver = (AMFQueryVersion_Fn)GetProcAddress( ++ AMFQueryVersion_Fn get_ver = (AMFQueryVersion_Fn)os_dlsym( + amf_module, AMF_QUERY_VERSION_FUNCTION_NAME); + if (!get_ver) + throw "Failed to get AMFQueryVersion address"; +@@ -2322,7 +2402,7 @@ try { + } catch (const amf_error &err) { + /* doing an error here because it means at least the library has loaded + * successfully, so they probably have AMD at this point */ +- blog(LOG_ERROR, "%s: %s: 0x%lX", __FUNCTION__, err.str, ++ blog(LOG_ERROR, "%s: %s: 0x%uX", __FUNCTION__, err.str, + (uint32_t)err.res); + } + diff --git a/patches/6207.patch b/patches/0001-6207.patch similarity index 99% rename from patches/6207.patch rename to patches/0001-6207.patch index 783cb86..aff32b4 100644 --- a/patches/6207.patch +++ b/patches/0001-6207.patch @@ -2269,3 +2269,4 @@ index 0000000000000..316276df75e54 +void pipewire_audio_capture_load(void); +void pipewire_audio_capture_app_load(void); +/* ------------------------------------------------- */ + diff --git a/patches/amf.patch b/patches/0002-7206.patch similarity index 98% rename from patches/amf.patch rename to patches/0002-7206.patch index 691837b..0a33fca 100644 --- a/patches/amf.patch +++ b/patches/0002-7206.patch @@ -19,7 +19,7 @@ will be detected on startup and the encoders disabled. create mode 100644 plugins/obs-ffmpeg/obs-amf-test/obs-amf-test-linux.cpp diff --git a/plugins/obs-ffmpeg/CMakeLists.txt b/plugins/obs-ffmpeg/CMakeLists.txt -index 3eba00932ab9f..778d93ffba753 100644 +index 3eba00932..778d93ffb 100644 --- a/plugins/obs-ffmpeg/CMakeLists.txt +++ b/plugins/obs-ffmpeg/CMakeLists.txt @@ -108,10 +108,12 @@ if(OS_WINDOWS) @@ -37,7 +37,7 @@ index 3eba00932ab9f..778d93ffba753 100644 endif() diff --git a/plugins/obs-ffmpeg/cmake/legacy.cmake b/plugins/obs-ffmpeg/cmake/legacy.cmake -index 5540676eacba1..78b8c30a10d32 100644 +index 5540676ea..78b8c30a1 100644 --- a/plugins/obs-ffmpeg/cmake/legacy.cmake +++ b/plugins/obs-ffmpeg/cmake/legacy.cmake @@ -106,9 +106,10 @@ if(OS_WINDOWS) @@ -53,7 +53,7 @@ index 5540676eacba1..78b8c30a10d32 100644 endif() diff --git a/plugins/obs-ffmpeg/obs-amf-test/CMakeLists.txt b/plugins/obs-ffmpeg/obs-amf-test/CMakeLists.txt -index e00cef1cf1d8a..07cf1e0fc0e83 100644 +index e00cef1cf..07cf1e0fc 100644 --- a/plugins/obs-ffmpeg/obs-amf-test/CMakeLists.txt +++ b/plugins/obs-ffmpeg/obs-amf-test/CMakeLists.txt @@ -6,8 +6,14 @@ find_package(AMF 1.4.29 REQUIRED) @@ -75,7 +75,7 @@ index e00cef1cf1d8a..07cf1e0fc0e83 100644 diff --git a/plugins/obs-ffmpeg/obs-amf-test/obs-amf-test-linux.cpp b/plugins/obs-ffmpeg/obs-amf-test/obs-amf-test-linux.cpp new file mode 100644 -index 0000000000000..db437d85164f7 +index 000000000..db437d851 --- /dev/null +++ b/plugins/obs-ffmpeg/obs-amf-test/obs-amf-test-linux.cpp @@ -0,0 +1,140 @@ @@ -220,7 +220,7 @@ index 0000000000000..db437d85164f7 + return 0; +} diff --git a/plugins/obs-ffmpeg/obs-ffmpeg.c b/plugins/obs-ffmpeg/obs-ffmpeg.c -index da0b2c2b46f7a..92421c6f34d9a 100644 +index da0b2c2b4..92421c6f3 100644 --- a/plugins/obs-ffmpeg/obs-ffmpeg.c +++ b/plugins/obs-ffmpeg/obs-ffmpeg.c @@ -360,6 +360,9 @@ static bool hevc_vaapi_supported(void) @@ -256,7 +256,7 @@ index da0b2c2b46f7a..92421c6f34d9a 100644 #endif } diff --git a/plugins/obs-ffmpeg/texture-amf-opts.hpp b/plugins/obs-ffmpeg/texture-amf-opts.hpp -index b1c37d200d8b0..d28e3f77e412f 100644 +index b1c37d200..d28e3f77e 100644 --- a/plugins/obs-ffmpeg/texture-amf-opts.hpp +++ b/plugins/obs-ffmpeg/texture-amf-opts.hpp @@ -321,7 +321,7 @@ static void amf_apply_opt(amf_base *enc, obs_option *opt) @@ -269,7 +269,7 @@ index b1c37d200d8b0..d28e3f77e412f 100644 bool bool_val = (bool)val; set_amf_property(enc, wname, bool_val); diff --git a/plugins/obs-ffmpeg/texture-amf.cpp b/plugins/obs-ffmpeg/texture-amf.cpp -index 88914a027f699..fe651f0e13d82 100644 +index 88914a027..fe651f0e1 100644 --- a/plugins/obs-ffmpeg/texture-amf.cpp +++ b/plugins/obs-ffmpeg/texture-amf.cpp @@ -11,6 +11,7 @@ @@ -642,6 +642,8 @@ index 88914a027f699..fe651f0e13d82 100644 (uint32_t)err.res); } +-- +2.40.0 From 33d3c849e8e68f0d479548640202d2e8e7041396 Mon Sep 17 00:00:00 2001 From: Kurt Kartaltepe @@ -658,7 +660,7 @@ frames destined for encoding. 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libobs-opengl/gl-egl-common.c b/libobs-opengl/gl-egl-common.c -index f06cd19019b29..e53f5a27555d4 100644 +index f06cd1901..e53f5a275 100644 --- a/libobs-opengl/gl-egl-common.c +++ b/libobs-opengl/gl-egl-common.c @@ -186,7 +186,7 @@ struct gs_texture *gl_egl_create_texture_from_eglimage( @@ -670,6 +672,8 @@ index f06cd19019b29..e53f5a27555d4 100644 const GLuint gltex = *(GLuint *)gs_texture_get_obj(texture); gl_bind_texture(GL_TEXTURE_2D, gltex); +-- +2.40.0 From de0dd29322328c003944905c89b7da6401159fb5 Mon Sep 17 00:00:00 2001 From: Kurt Kartaltepe @@ -692,7 +696,7 @@ support encode_texture2 10 files changed, 135 insertions(+), 126 deletions(-) diff --git a/libobs-opengl/gl-subsystem.c b/libobs-opengl/gl-subsystem.c -index 0cdd46d08c58d..8499af20e0475 100644 +index 0cdd46d08..8499af20e 100644 --- a/libobs-opengl/gl-subsystem.c +++ b/libobs-opengl/gl-subsystem.c @@ -1519,6 +1519,18 @@ void gs_swapchain_destroy(gs_swapchain_t *swapchain) @@ -715,7 +719,7 @@ index 0cdd46d08c58d..8499af20e0475 100644 { /* TODO */ diff --git a/libobs/graphics/graphics-imports.c b/libobs/graphics/graphics-imports.c -index d6eaccccc71fc..8de5bebb6c6ee 100644 +index d6eaccccc..8de5bebb6 100644 --- a/libobs/graphics/graphics-imports.c +++ b/libobs/graphics/graphics-imports.c @@ -195,6 +195,8 @@ bool load_graphics_imports(struct gs_exports *exports, void *module, @@ -737,7 +741,7 @@ index d6eaccccc71fc..8de5bebb6c6ee 100644 GRAPHICS_IMPORT_OPTIONAL(device_stagesurface_create_p010); GRAPHICS_IMPORT_OPTIONAL(device_register_loss_callbacks); diff --git a/libobs/graphics/graphics-internal.h b/libobs/graphics/graphics-internal.h -index d0ae5b895b39c..268ad36da522d 100644 +index d0ae5b895..268ad36da 100644 --- a/libobs/graphics/graphics-internal.h +++ b/libobs/graphics/graphics-internal.h @@ -273,6 +273,16 @@ struct gs_exports { @@ -775,7 +779,7 @@ index d0ae5b895b39c..268ad36da522d 100644 gs_stagesurf_t *(*device_stagesurface_create_nv12)(gs_device_t *device, uint32_t width, diff --git a/libobs/graphics/graphics.c b/libobs/graphics/graphics.c -index 288fb1db6409c..78a7fc27bccb7 100644 +index 288fb1db6..78a7fc27b 100644 --- a/libobs/graphics/graphics.c +++ b/libobs/graphics/graphics.c @@ -2908,6 +2908,84 @@ void gs_debug_marker_end(void) @@ -949,7 +953,7 @@ index 288fb1db6409c..78a7fc27bccb7 100644 { graphics_t *graphics = thread_graphics; diff --git a/libobs/graphics/graphics.h b/libobs/graphics/graphics.h -index 0f62d5b955062..ee17a65fa3357 100644 +index 0f62d5b95..ee17a65fa 100644 --- a/libobs/graphics/graphics.h +++ b/libobs/graphics/graphics.h @@ -857,6 +857,12 @@ EXPORT bool gs_timer_range_get_data(gs_timer_range_t *range, bool *disjoint, @@ -980,7 +984,7 @@ index 0f62d5b955062..ee17a65fa3357 100644 uint32_t height); EXPORT gs_stagesurf_t *gs_stagesurface_create_p010(uint32_t width, diff --git a/libobs/obs-encoder.h b/libobs/obs-encoder.h -index 6e831af5cf064..c6184bfb595a2 100644 +index 6e831af5c..c6184bfb5 100644 --- a/libobs/obs-encoder.h +++ b/libobs/obs-encoder.h @@ -29,6 +29,9 @@ @@ -994,7 +998,7 @@ index 6e831af5cf064..c6184bfb595a2 100644 #define OBS_ENCODER_CAP_PASS_TEXTURE (1 << 1) #define OBS_ENCODER_CAP_DYN_BITRATE (1 << 2) diff --git a/libobs/obs-internal.h b/libobs/obs-internal.h -index 1ea555c3ac7a3..6e975d065417f 100644 +index 1ea555c3a..6e975d065 100644 --- a/libobs/obs-internal.h +++ b/libobs/obs-internal.h @@ -268,9 +268,9 @@ struct obs_core_video_mix { @@ -1009,7 +1013,7 @@ index 1ea555c3ac7a3..6e975d065417f 100644 gs_texture_t *render_texture; gs_texture_t *output_texture; diff --git a/libobs/obs-video-gpu-encode.c b/libobs/obs-video-gpu-encode.c -index 0dfb11df0508b..0d65a6d173e7a 100644 +index 0dfb11df0..0d65a6d17 100644 --- a/libobs/obs-video-gpu-encode.c +++ b/libobs/obs-video-gpu-encode.c @@ -17,8 +17,11 @@ @@ -1087,7 +1091,7 @@ index 0dfb11df0508b..0d65a6d173e7a 100644 void stop_gpu_encoding_thread(struct obs_core_video_mix *video) diff --git a/libobs/obs-video.c b/libobs/obs-video.c -index 60acaaf6f6536..8918b869d8832 100644 +index 60acaaf6f..8918b869d 100644 --- a/libobs/obs-video.c +++ b/libobs/obs-video.c @@ -427,7 +427,6 @@ stage_output_texture(struct obs_core_video_mix *video, int cur_texture, @@ -1201,7 +1205,7 @@ index 60acaaf6f6536..8918b869d8832 100644 video->was_active = active; } diff --git a/libobs/obs.c b/libobs/obs.c -index 1850ecc7584e5..1e57f25174a34 100644 +index 1850ecc75..1e57f2517 100644 --- a/libobs/obs.c +++ b/libobs/obs.c @@ -179,7 +179,6 @@ static bool obs_init_gpu_conversion(struct obs_core_video_mix *video) @@ -1247,6 +1251,8 @@ index 1850ecc7584e5..1e57f25174a34 100644 } gs_texture_destroy(video->output_texture); +-- +2.40.0 From d9c1a0ce4ae3b7a2465b0f77dd1bc8e8ff74dd21 Mon Sep 17 00:00:00 2001 From: Torge Matthies @@ -1264,7 +1270,7 @@ And use it if non-NULL instead of encode_texture. 5 files changed, 111 insertions(+), 17 deletions(-) diff --git a/libobs/obs-encoder.c b/libobs/obs-encoder.c -index 677b92f7dabd7..83bf911c99484 100644 +index 677b92f7d..83bf911c9 100644 --- a/libobs/obs-encoder.c +++ b/libobs/obs-encoder.c @@ -194,7 +194,7 @@ static void add_connection(struct obs_encoder *encoder) @@ -1303,7 +1309,7 @@ index 677b92f7dabd7..83bf911c99484 100644 get_callback_idx(const struct obs_encoder *encoder, void (*new_packet)(void *param, struct encoder_packet *packet), diff --git a/libobs/obs-encoder.h b/libobs/obs-encoder.h -index c6184bfb595a2..f33e668bfa5d8 100644 +index c6184bfb5..f33e668bf 100644 --- a/libobs/obs-encoder.h +++ b/libobs/obs-encoder.h @@ -105,6 +105,18 @@ struct encoder_frame { @@ -1354,7 +1360,7 @@ index c6184bfb595a2..f33e668bfa5d8 100644 EXPORT void obs_register_encoder_s(const struct obs_encoder_info *info, diff --git a/libobs/obs-internal.h b/libobs/obs-internal.h -index 6e975d065417f..2abfbddee08e8 100644 +index 6e975d065..2abfbddee 100644 --- a/libobs/obs-internal.h +++ b/libobs/obs-internal.h @@ -1259,6 +1259,9 @@ extern struct obs_encoder_info *find_encoder(const char *id); @@ -1368,10 +1374,10 @@ index 6e975d065417f..2abfbddee08e8 100644 void (*new_packet)(void *param, struct encoder_packet *packet), diff --git a/libobs/obs-module.c b/libobs/obs-module.c -index cd7841b6c1960..443c97b2303ac 100644 +index cd7841b6c..443c97b23 100644 --- a/libobs/obs-module.c +++ b/libobs/obs-module.c -@@ -679,16 +679,30 @@ lookup_t *obs_module_load_locale(obs_module_t *module, +@@ -679,16 +679,30 @@ cleanup: da_push_back(dest, &data); \ } while (false) @@ -1424,7 +1430,7 @@ index cd7841b6c1960..443c97b2303ac 100644 CHECK_REQUIRED_VAL_(info, encode, obs_register_encoder); diff --git a/libobs/obs-video-gpu-encode.c b/libobs/obs-video-gpu-encode.c -index 0d65a6d173e7a..394ded9b68bca 100644 +index 0d65a6d17..394ded9b6 100644 --- a/libobs/obs-video-gpu-encode.c +++ b/libobs/obs-video-gpu-encode.c @@ -78,7 +78,7 @@ static void *gpu_encode_thread(void *data) @@ -1474,6 +1480,8 @@ index 0d65a6d173e7a..394ded9b68bca 100644 send_off_encoder_packet(encoder, success, received, &pkt); +-- +2.40.0 From 0475795cdbf7c7bcb90bb373a10bbd5a7ce17a07 Mon Sep 17 00:00:00 2001 From: David Rosca @@ -1494,7 +1502,7 @@ v8: init AMF context with our Vulkan device 3 files changed, 913 insertions(+), 32 deletions(-) diff --git a/plugins/obs-ffmpeg/CMakeLists.txt b/plugins/obs-ffmpeg/CMakeLists.txt -index 778d93ffba753..97376182fbfae 100644 +index 778d93ffb..97376182f 100644 --- a/plugins/obs-ffmpeg/CMakeLists.txt +++ b/plugins/obs-ffmpeg/CMakeLists.txt @@ -112,9 +112,10 @@ elseif(OS_LINUX OR OS_FREEBSD) @@ -1510,7 +1518,7 @@ index 778d93ffba753..97376182fbfae 100644 set_target_properties_obs(obs-ffmpeg PROPERTIES FOLDER plugins/obs-ffmpeg PREFIX "") diff --git a/plugins/obs-ffmpeg/cmake/legacy.cmake b/plugins/obs-ffmpeg/cmake/legacy.cmake -index 78b8c30a10d32..b29eef673586a 100644 +index 78b8c30a1..b29eef673 100644 --- a/plugins/obs-ffmpeg/cmake/legacy.cmake +++ b/plugins/obs-ffmpeg/cmake/legacy.cmake @@ -109,8 +109,9 @@ elseif(OS_POSIX AND NOT OS_MACOS) @@ -1525,7 +1533,7 @@ index 78b8c30a10d32..b29eef673586a 100644 setup_plugin_target(obs-ffmpeg) diff --git a/plugins/obs-ffmpeg/texture-amf.cpp b/plugins/obs-ffmpeg/texture-amf.cpp -index fe651f0e13d82..0f5ee7b9105a8 100644 +index fe651f0e1..0f5ee7b91 100644 --- a/plugins/obs-ffmpeg/texture-amf.cpp +++ b/plugins/obs-ffmpeg/texture-amf.cpp @@ -29,6 +29,15 @@ @@ -2665,3 +2673,6 @@ index fe651f0e13d82..0f5ee7b9105a8 100644 amf_encoder_info.create = amf_av1_create_fallback; amf_encoder_info.encode = amf_encode_fallback; amf_encoder_info.get_video_info = av1_video_info_fallback; +-- +2.40.0 + diff --git a/patches/0003-8788.patch b/patches/0003-8788.patch new file mode 100644 index 0000000..270eab8 --- /dev/null +++ b/patches/0003-8788.patch @@ -0,0 +1,63 @@ +From 8e5fec4c7765b1c43d40f652b46d034340877a31 Mon Sep 17 00:00:00 2001 +From: Ryan Foster +Date: Fri, 14 Apr 2023 12:05:59 -0400 +Subject: [PATCH 1/2] obs-ffmpeg: Use 2x2 tiles in NVENC AV1 for 4K+ + +When resolution is 4K or higher, use 2x2 uniform tiles for NVENC AV1. +--- + plugins/obs-ffmpeg/jim-nvenc.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/plugins/obs-ffmpeg/jim-nvenc.c b/plugins/obs-ffmpeg/jim-nvenc.c +index 10a7dd18549b9..c1e8bee154770 100644 +--- a/plugins/obs-ffmpeg/jim-nvenc.c ++++ b/plugins/obs-ffmpeg/jim-nvenc.c +@@ -922,6 +922,17 @@ static bool init_encoder_av1(struct nvenc_data *enc, obs_data_t *settings, + if (config->rcParams.rateControlMode == NV_ENC_PARAMS_RC_CBR) + av1_config->enableBitstreamPadding = 1; + ++#define FOUR_K_CX 3840 ++#define FOUR_K_CY 2160 ++#define PIXELCOUNT_4K (FOUR_K_CX * FOUR_K_CY) ++ ++ /* If 4K+, set tiles to 2x2 uniform tiles. */ ++ if ((voi->width * voi->height) >= PIXELCOUNT_4K) { ++ av1_config->enableCustomTileConfig = 0; ++ av1_config->numTileColumns = 2; ++ av1_config->numTileRows = 2; ++ } ++ + switch (voi->colorspace) { + case VIDEO_CS_601: + av1_config->colorPrimaries = 6; + +From 872f0353e68191d69bcc4678a2d195144fdcabeb Mon Sep 17 00:00:00 2001 +From: Ryan Foster +Date: Fri, 14 Apr 2023 12:07:50 -0400 +Subject: [PATCH 2/2] obs-ffmpeg: Use 2 tiles per frame in AMF AV1 for 4K+ + +When resolution is 4K or higher, use 2 tiles per frame in AMF AV1. +--- + plugins/obs-ffmpeg/texture-amf.cpp | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/plugins/obs-ffmpeg/texture-amf.cpp b/plugins/obs-ffmpeg/texture-amf.cpp +index 88914a027f699..5979b903385ad 100644 +--- a/plugins/obs-ffmpeg/texture-amf.cpp ++++ b/plugins/obs-ffmpeg/texture-amf.cpp +@@ -2018,6 +2018,15 @@ static void amf_av1_create_internal(amf_base *enc, obs_data_t *settings) + const bool is10bit = enc->amf_format == AMF_SURFACE_P010; + const char *preset = obs_data_get_string(settings, "preset"); + ++ constexpr uint32_t four_k_cx = 3840; ++ constexpr uint32_t four_k_cy = 2160; ++ constexpr uint32_t pixelcount_4k = four_k_cx * four_k_cy; ++ ++ /* If 4K+, set tiles per frame to 2. */ ++ if ((enc->cx * enc->cy) >= pixelcount_4k) { ++ set_av1_property(enc, TILES_PER_FRAME, 2); ++ } ++ + set_av1_property(enc, FRAMESIZE, AMFConstructSize(enc->cx, enc->cy)); + set_av1_property(enc, USAGE, AMF_VIDEO_ENCODER_USAGE_TRANSCODING); + set_av1_property(enc, ALIGNMENT_MODE, diff --git a/patches/0004-8794.patch b/patches/0004-8794.patch new file mode 100644 index 0000000..4e76a95 --- /dev/null +++ b/patches/0004-8794.patch @@ -0,0 +1,225 @@ +From 50270b270250a2a95a3d5e2799e40331fb4f83e9 Mon Sep 17 00:00:00 2001 +From: Bleuzen <12885163+Bleuzen@users.noreply.github.com> +Date: Thu, 27 Apr 2023 22:42:49 +0200 +Subject: [PATCH] obs-ffmpeg: Add NVENC AV1 FFmpeg encoder, part 1 + +--- + plugins/obs-ffmpeg/obs-ffmpeg-nvenc.c | 100 ++++++++++++++++++++++++-- + plugins/obs-ffmpeg/obs-ffmpeg.c | 8 ++- + 2 files changed, 100 insertions(+), 8 deletions(-) + +diff --git a/plugins/obs-ffmpeg/obs-ffmpeg-nvenc.c b/plugins/obs-ffmpeg/obs-ffmpeg-nvenc.c +index 8cd813837c1e8..35c3822453741 100644 +--- a/plugins/obs-ffmpeg/obs-ffmpeg-nvenc.c ++++ b/plugins/obs-ffmpeg/obs-ffmpeg-nvenc.c +@@ -35,6 +35,7 @@ struct nvenc_encoder { + #ifdef ENABLE_HEVC + bool hevc; + #endif ++ bool av1; + int gpu; + DARRAY(uint8_t) header; + DARRAY(uint8_t) sei; +@@ -61,6 +62,13 @@ static const char *hevc_nvenc_getname(void *unused) + } + #endif + ++#define ENCODER_NAME_AV1 "GPU: NVIDIA NVENC AV1 (FFmpeg)" ++static const char *av1_nvenc_getname(void *unused) ++{ ++ UNUSED_PARAMETER(unused); ++ return ENCODER_NAME_AV1; ++} ++ + static inline bool valid_format(enum video_format format) + { + switch (format) { +@@ -286,7 +294,9 @@ static void on_first_packet(void *data, AVPacket *pkt, struct darray *da) + &enc->sei.array, &enc->sei.num); + } else + #endif +- { ++ if (enc->av1) { ++ // TODO: add obs_extract_av1_headers ++ } else { + obs_extract_avc_headers(pkt->data, pkt->size, + (uint8_t **)&da->array, &da->num, + &enc->header.array, &enc->header.num, +@@ -305,10 +315,11 @@ static void on_first_packet(void *data, AVPacket *pkt, struct darray *da) + } + + static void *nvenc_create_internal(obs_data_t *settings, obs_encoder_t *encoder, +- bool psycho_aq, bool hevc) ++ bool psycho_aq, bool hevc, bool av1) + { + struct nvenc_encoder *enc = bzalloc(sizeof(*enc)); + ++ enc->av1 = av1; + #ifdef ENABLE_HEVC + enc->hevc = hevc; + if (hevc) { +@@ -321,7 +332,12 @@ static void *nvenc_create_internal(obs_data_t *settings, obs_encoder_t *encoder, + #else + UNUSED_PARAMETER(hevc); + #endif +- { ++ if (av1) { ++ if (!ffmpeg_video_encoder_init( ++ &enc->ffve, enc, encoder, "av1_nvenc", "nvenc_av1", ++ ENCODER_NAME_AV1, on_init_error, on_first_packet)) ++ goto fail; ++ } else { + if (!ffmpeg_video_encoder_init(&enc->ffve, enc, encoder, + "h264_nvenc", "nvenc_h264", + ENCODER_NAME_H264, on_init_error, +@@ -365,12 +381,14 @@ static void *h264_nvenc_create(obs_data_t *settings, obs_encoder_t *encoder) + } + + bool psycho_aq = obs_data_get_bool(settings, "psycho_aq"); +- void *enc = nvenc_create_internal(settings, encoder, psycho_aq, false); ++ void *enc = nvenc_create_internal(settings, encoder, psycho_aq, false, ++ false); + if ((enc == NULL) && psycho_aq) { + blog(LOG_WARNING, + "[NVENC encoder] nvenc_create_internal failed, " + "trying again without Psycho Visual Tuning"); +- enc = nvenc_create_internal(settings, encoder, false, false); ++ enc = nvenc_create_internal(settings, encoder, false, false, ++ false); + } + + return enc; +@@ -404,18 +422,59 @@ static void *hevc_nvenc_create(obs_data_t *settings, obs_encoder_t *encoder) + } + + bool psycho_aq = obs_data_get_bool(settings, "psycho_aq"); +- void *enc = nvenc_create_internal(settings, encoder, psycho_aq, true); ++ void *enc = nvenc_create_internal(settings, encoder, psycho_aq, true, ++ false); + if ((enc == NULL) && psycho_aq) { + blog(LOG_WARNING, + "[NVENC encoder] nvenc_create_internal failed, " + "trying again without Psycho Visual Tuning"); +- enc = nvenc_create_internal(settings, encoder, false, true); ++ enc = nvenc_create_internal(settings, encoder, false, true, ++ false); + } + + return enc; + } + #endif + ++static void *av1_nvenc_create(obs_data_t *settings, obs_encoder_t *encoder) ++{ ++ video_t *video = obs_encoder_video(encoder); ++ const struct video_output_info *voi = video_output_get_info(video); ++ switch (voi->format) { ++ case VIDEO_FORMAT_I010: ++ case VIDEO_FORMAT_P010: { ++ const char *const text = ++ obs_module_text("NVENC.10bitUnsupported"); ++ obs_encoder_set_last_error(encoder, text); ++ blog(LOG_ERROR, "[NVENC encoder] %s", text); ++ return NULL; ++ } ++ default: ++ if (voi->colorspace == VIDEO_CS_2100_PQ || ++ voi->colorspace == VIDEO_CS_2100_HLG) { ++ const char *const text = ++ obs_module_text("NVENC.8bitUnsupportedHdr"); ++ obs_encoder_set_last_error(encoder, text); ++ blog(LOG_ERROR, "[NVENC encoder] %s", text); ++ return NULL; ++ } ++ break; ++ } ++ ++ bool psycho_aq = obs_data_get_bool(settings, "psycho_aq"); ++ void *enc = nvenc_create_internal(settings, encoder, psycho_aq, false, ++ true); ++ if ((enc == NULL) && psycho_aq) { ++ blog(LOG_WARNING, ++ "[NVENC encoder] nvenc_create_internal failed, " ++ "trying again without Psycho Visual Tuning"); ++ enc = nvenc_create_internal(settings, encoder, false, false, ++ true); ++ } ++ ++ return enc; ++} ++ + static bool nvenc_encode(void *data, struct encoder_frame *frame, + struct encoder_packet *packet, bool *received_packet) + { +@@ -658,6 +717,12 @@ obs_properties_t *hevc_nvenc_properties_ffmpeg(void *unused) + } + #endif + ++obs_properties_t *av1_nvenc_properties_ffmpeg(void *unused) ++{ ++ UNUSED_PARAMETER(unused); ++ return nvenc_properties_internal(CODEC_AV1, true); ++} ++ + static bool nvenc_extra_data(void *data, uint8_t **extra_data, size_t *size) + { + struct nvenc_encoder *enc = data; +@@ -719,3 +784,24 @@ struct obs_encoder_info hevc_nvenc_encoder_info = { + #endif + }; + #endif ++ ++struct obs_encoder_info av1_nvenc_encoder_info = { ++ .id = "ffmpeg_av1_nvenc", ++ .type = OBS_ENCODER_VIDEO, ++ .codec = "av1", ++ .get_name = av1_nvenc_getname, ++ .create = av1_nvenc_create, ++ .destroy = nvenc_destroy, ++ .encode = nvenc_encode, ++ .update = nvenc_reconfigure, ++ .get_defaults = av1_nvenc_defaults, ++ .get_properties = av1_nvenc_properties_ffmpeg, ++ .get_extra_data = nvenc_extra_data, ++ .get_sei_data = nvenc_sei_data, ++ .get_video_info = nvenc_video_info, ++#ifdef _WIN32 ++ .caps = OBS_ENCODER_CAP_DYN_BITRATE | OBS_ENCODER_CAP_INTERNAL, ++#else ++ .caps = OBS_ENCODER_CAP_DYN_BITRATE, ++#endif ++}; +diff --git a/plugins/obs-ffmpeg/obs-ffmpeg.c b/plugins/obs-ffmpeg/obs-ffmpeg.c +index da0b2c2b46f7a..e06f8ac7a9192 100644 +--- a/plugins/obs-ffmpeg/obs-ffmpeg.c ++++ b/plugins/obs-ffmpeg/obs-ffmpeg.c +@@ -43,6 +43,7 @@ extern struct obs_encoder_info h264_nvenc_encoder_info; + #ifdef ENABLE_HEVC + extern struct obs_encoder_info hevc_nvenc_encoder_info; + #endif ++extern struct obs_encoder_info av1_nvenc_encoder_info; + extern struct obs_encoder_info svt_av1_encoder_info; + extern struct obs_encoder_info aom_av1_encoder_info; + +@@ -307,8 +308,11 @@ static bool nvenc_supported(bool *out_h264, bool *out_hevc, bool *out_av1) + if (success) { + void *const lib = os_dlopen("libnvidia-encode.so.1"); + success = lib != NULL; +- if (success) ++ if (success) { + os_dlclose(lib); ++ av1 = nvenc_codec_exists("av1_nvenc", ++ "nvenc_av1"); ++ } + } + #else + void *const lib = os_dlopen("libnvidia-encode.so.1"); +@@ -432,6 +436,8 @@ bool obs_module_load(void) + if (hevc) + obs_register_encoder(&hevc_nvenc_encoder_info); + #endif ++ if (av1) ++ obs_register_encoder(&av1_nvenc_encoder_info); + } + + #ifdef _WIN32 diff --git a/patches/0005-8832.patch b/patches/0005-8832.patch new file mode 100644 index 0000000..b411861 --- /dev/null +++ b/patches/0005-8832.patch @@ -0,0 +1,925 @@ +From 7f0532049b2fe1f3c1f37f45d540e0a7a18663df Mon Sep 17 00:00:00 2001 +From: David Rosca +Date: Tue, 2 May 2023 13:14:18 +0200 +Subject: [PATCH 1/2] libobs: Add AV1 parsing functions + +--- + libobs/CMakeLists.txt | 2 + + libobs/cmake/legacy.cmake | 2 + + libobs/obs-av1.c | 123 ++++++++++++++++++++++++++++++++++++++ + libobs/obs-av1.h | 35 +++++++++++ + 4 files changed, 162 insertions(+) + create mode 100644 libobs/obs-av1.c + create mode 100644 libobs/obs-av1.h + +diff --git a/libobs/CMakeLists.txt b/libobs/CMakeLists.txt +index d7bb1839c579e..0783feb07ccbb 100644 +--- a/libobs/CMakeLists.txt ++++ b/libobs/CMakeLists.txt +@@ -33,6 +33,8 @@ target_sources( + obs-audio-controls.c + obs-audio-controls.h + obs-audio.c ++ obs-av1.c ++ obs-av1.h + obs-avc.c + obs-avc.h + obs-data.c +diff --git a/libobs/cmake/legacy.cmake b/libobs/cmake/legacy.cmake +index e8458591c4f2f..a80c5b7c1df24 100644 +--- a/libobs/cmake/legacy.cmake ++++ b/libobs/cmake/legacy.cmake +@@ -37,6 +37,8 @@ target_sources( + obs-audio.c + obs-audio-controls.c + obs-audio-controls.h ++ obs-av1.c ++ obs-av1.h + obs-avc.c + obs-avc.h + obs-data.c +diff --git a/libobs/obs-av1.c b/libobs/obs-av1.c +new file mode 100644 +index 0000000000000..a015130537cf2 +--- /dev/null ++++ b/libobs/obs-av1.c +@@ -0,0 +1,123 @@ ++// SPDX-FileCopyrightText: 2023 David Rosca ++// ++// SPDX-License-Identifier: GPL-2.0-or-later ++ ++#include "obs-av1.h" ++ ++#include "obs.h" ++ ++static inline uint64_t leb128(const uint8_t *buf, size_t size, size_t *len) ++{ ++ uint64_t value = 0; ++ uint8_t leb128_byte; ++ ++ *len = 0; ++ ++ for (int i = 0; i < 8; i++) { ++ if (size-- < 1) ++ break; ++ (*len)++; ++ leb128_byte = buf[i]; ++ value |= (leb128_byte & 0x7f) << (i * 7); ++ if (!(leb128_byte & 0x80)) ++ break; ++ } ++ ++ return value; ++} ++ ++static inline unsigned int get_bits(uint8_t val, unsigned int n, ++ unsigned int count) ++{ ++ return (val >> (8 - n - count)) & ((1 << (count - 1)) * 2 - 1); ++} ++ ++static void parse_obu_header(const uint8_t *buf, size_t size, size_t *obu_start, ++ size_t *obu_size, int *obu_type) ++{ ++ int extension_flag, has_size_field; ++ size_t size_len = 0; ++ ++ *obu_start = 0; ++ *obu_size = 0; ++ *obu_type = 0; ++ ++ if (size < 1) ++ return; ++ ++ *obu_type = get_bits(*buf, 1, 4); ++ extension_flag = get_bits(*buf, 5, 1); ++ has_size_field = get_bits(*buf, 6, 1); ++ ++ if (extension_flag) ++ (*obu_start)++; ++ ++ (*obu_start)++; ++ ++ if (has_size_field) ++ *obu_size = (size_t)leb128(buf + *obu_start, size - *obu_start, ++ &size_len); ++ else ++ *obu_size = size - 1; ++ ++ *obu_start += size_len; ++} ++ ++bool obs_av1_keyframe(const uint8_t *data, size_t size) ++{ ++ const uint8_t *start = data, *end = data + size; ++ ++ while (start < end) { ++ size_t obu_start, obu_size; ++ int obu_type; ++ parse_obu_header(start, end - start, &obu_start, &obu_size, ++ &obu_type); ++ ++ if (obu_size) { ++ if (obu_type == OBS_OBU_FRAME || ++ obu_type == OBS_OBU_FRAME_HEADER) { ++ uint8_t val = *(start + obu_start); ++ if (!get_bits(val, 0, 1)) // show_existing_frame ++ return get_bits(val, 1, 2) == ++ 0; // frame_type ++ return false; ++ } ++ } ++ ++ start += obu_start + obu_size; ++ } ++ ++ return false; ++} ++ ++void obs_extract_av1_headers(const uint8_t *packet, size_t size, ++ uint8_t **new_packet_data, size_t *new_packet_size, ++ uint8_t **header_data, size_t *header_size) ++{ ++ DARRAY(uint8_t) new_packet; ++ DARRAY(uint8_t) header; ++ const uint8_t *start = packet, *end = packet + size; ++ ++ da_init(new_packet); ++ da_init(header); ++ ++ while (start < end) { ++ size_t obu_start, obu_size; ++ int obu_type; ++ parse_obu_header(start, end - start, &obu_start, &obu_size, ++ &obu_type); ++ ++ if (obu_type == OBS_OBU_METADATA || ++ obu_type == OBS_OBU_SEQUENCE_HEADER) { ++ da_push_back_array(header, start, obu_start + obu_size); ++ } ++ da_push_back_array(new_packet, start, obu_start + obu_size); ++ ++ start += obu_start + obu_size; ++ } ++ ++ *new_packet_data = new_packet.array; ++ *new_packet_size = new_packet.num; ++ *header_data = header.array; ++ *header_size = header.num; ++} +diff --git a/libobs/obs-av1.h b/libobs/obs-av1.h +new file mode 100644 +index 0000000000000..031299da0a415 +--- /dev/null ++++ b/libobs/obs-av1.h +@@ -0,0 +1,35 @@ ++// SPDX-FileCopyrightText: 2023 David Rosca ++// ++// SPDX-License-Identifier: GPL-2.0-or-later ++ ++#pragma once ++ ++#include "util/c99defs.h" ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++enum { ++ OBS_OBU_SEQUENCE_HEADER = 1, ++ OBS_OBU_TEMPORAL_DELIMITER = 2, ++ OBS_OBU_FRAME_HEADER = 3, ++ OBS_OBU_TILE_GROUP = 4, ++ OBS_OBU_METADATA = 5, ++ OBS_OBU_FRAME = 6, ++ OBS_OBU_REDUNDANT_FRAME_HEADER = 7, ++ OBS_OBU_TILE_LIST = 8, ++ OBS_OBU_PADDING = 15, ++}; ++ ++/* Helpers for parsing AV1 OB units. */ ++ ++EXPORT bool obs_av1_keyframe(const uint8_t *data, size_t size); ++EXPORT void obs_extract_av1_headers(const uint8_t *packet, size_t size, ++ uint8_t **new_packet_data, ++ size_t *new_packet_size, ++ uint8_t **header_data, size_t *header_size); ++ ++#ifdef __cplusplus ++} ++#endif + +From 479e25f59234622e2f868b5f3f295f8c4f702db0 Mon Sep 17 00:00:00 2001 +From: David Rosca +Date: Tue, 2 May 2023 13:39:13 +0200 +Subject: [PATCH 2/2] obs-ffmpeg: Add AV1 support for VA-API + +--- + plugins/obs-ffmpeg/obs-ffmpeg-vaapi.c | 295 +++++++++++++++++--------- + plugins/obs-ffmpeg/obs-ffmpeg.c | 19 ++ + plugins/obs-ffmpeg/vaapi-utils.c | 60 ++++++ + plugins/obs-ffmpeg/vaapi-utils.h | 4 + + 4 files changed, 274 insertions(+), 104 deletions(-) + +diff --git a/plugins/obs-ffmpeg/obs-ffmpeg-vaapi.c b/plugins/obs-ffmpeg/obs-ffmpeg-vaapi.c +index c5aa0128a54b9..d6e61f8cb41b9 100644 +--- a/plugins/obs-ffmpeg/obs-ffmpeg-vaapi.c ++++ b/plugins/obs-ffmpeg/obs-ffmpeg-vaapi.c +@@ -26,6 +26,7 @@ + #include + #include + #include ++#include + #ifdef ENABLE_HEVC + #include + #endif +@@ -53,8 +54,15 @@ + #define info(format, ...) do_log(LOG_INFO, format, ##__VA_ARGS__) + #define debug(format, ...) do_log(LOG_DEBUG, format, ##__VA_ARGS__) + ++enum codec_type { ++ CODEC_H264, ++ CODEC_HEVC, ++ CODEC_AV1, ++}; ++ + struct vaapi_encoder { + obs_encoder_t *encoder; ++ enum codec_type codec; + + AVBufferRef *vadevice_ref; + AVBufferRef *vaframes_ref; +@@ -85,59 +93,48 @@ static const char *h264_vaapi_getname(void *unused) + return "FFmpeg VAAPI H.264"; + } + +-#ifdef ENABLE_HEVC +-static const char *hevc_vaapi_getname(void *unused) ++static const char *av1_vaapi_getname(void *unused) + { + UNUSED_PARAMETER(unused); +- return "FFmpeg VAAPI HEVC"; +-} +-#endif +- +-static inline bool h264_valid_format(enum video_format format) +-{ +- return format == VIDEO_FORMAT_NV12; ++ return "FFmpeg VAAPI AV1"; + } + + #ifdef ENABLE_HEVC +-static inline bool hevc_valid_format(enum video_format format) ++static const char *hevc_vaapi_getname(void *unused) + { +- return (format == VIDEO_FORMAT_NV12) || (format == VIDEO_FORMAT_P010); ++ UNUSED_PARAMETER(unused); ++ return "FFmpeg VAAPI HEVC"; + } + #endif + +-static void h264_vaapi_video_info(void *data, struct video_scale_info *info) ++static inline bool vaapi_valid_format(struct vaapi_encoder *enc, ++ enum video_format format) + { +- struct vaapi_encoder *enc = data; +- enum video_format pref_format; +- +- pref_format = obs_encoder_get_preferred_video_format(enc->encoder); +- +- if (!h264_valid_format(pref_format)) { +- pref_format = h264_valid_format(info->format) +- ? info->format +- : VIDEO_FORMAT_NV12; ++ if (enc->codec == CODEC_H264) { ++ return format == VIDEO_FORMAT_NV12; ++ } else if (enc->codec == CODEC_HEVC || enc->codec == CODEC_AV1) { ++ return (format == VIDEO_FORMAT_NV12) || ++ (format == VIDEO_FORMAT_P010); ++ } else { ++ return false; + } +- +- info->format = pref_format; + } + +-#ifdef ENABLE_HEVC +-static void hevc_vaapi_video_info(void *data, struct video_scale_info *info) ++static void vaapi_video_info(void *data, struct video_scale_info *info) + { + struct vaapi_encoder *enc = data; + enum video_format pref_format; + + pref_format = obs_encoder_get_preferred_video_format(enc->encoder); + +- if (!hevc_valid_format(pref_format)) { +- pref_format = hevc_valid_format(info->format) ++ if (!vaapi_valid_format(enc, pref_format)) { ++ pref_format = vaapi_valid_format(enc, info->format) + ? info->format + : VIDEO_FORMAT_NV12; + } + + info->format = pref_format; + } +-#endif + + static bool vaapi_init_codec(struct vaapi_encoder *enc, const char *path) + { +@@ -234,7 +231,7 @@ static const rc_mode_t *get_rc_mode(const char *name) + return rc_mode ? rc_mode : RC_MODES; + } + +-static bool vaapi_update(void *data, obs_data_t *settings, bool hevc) ++static bool vaapi_update(void *data, obs_data_t *settings) + { + struct vaapi_encoder *enc = data; + +@@ -249,7 +246,7 @@ static bool vaapi_update(void *data, obs_data_t *settings, bool hevc) + int bf = (int)obs_data_get_int(settings, "bf"); + int qp = rc_mode->qp ? (int)obs_data_get_int(settings, "qp") : 0; + +- av_opt_set_int(enc->context->priv_data, "qp", qp, 0); ++ enc->context->global_quality = enc->codec == CODEC_AV1 ? qp * 4 : qp; + + int level = (int)obs_data_get_int(settings, "level"); + int bitrate = rc_mode->bitrate +@@ -279,21 +276,15 @@ static bool vaapi_update(void *data, obs_data_t *settings, bool hevc) + info.range = voi->range; + + #ifdef ENABLE_HEVC +- if (hevc) { ++ if (enc->codec == CODEC_HEVC) { + if ((profile == FF_PROFILE_HEVC_MAIN) && + (info.format == VIDEO_FORMAT_P010)) { + warn("Forcing Main10 for P010"); + profile = FF_PROFILE_HEVC_MAIN_10; + } +- +- hevc_vaapi_video_info(enc, &info); +- } else +-#else +- UNUSED_PARAMETER(hevc); +-#endif +- { +- h264_vaapi_video_info(enc, &info); + } ++#endif ++ vaapi_video_info(enc, &info); + + enc->context->profile = profile; + enc->context->max_b_frames = bf; +@@ -355,6 +346,17 @@ static bool vaapi_update(void *data, obs_data_t *settings, bool hevc) + enc->context->gop_size = 120; + } + ++#define FOUR_K_CX 3840 ++#define FOUR_K_CY 2160 ++#define PIXELCOUNT_4K (FOUR_K_CX * FOUR_K_CY) ++ ++ /* If 4K+, set tiles to 2x2 uniform tiles. */ ++ if (enc->codec == CODEC_AV1 && ++ (enc->context->width * enc->context->height) >= PIXELCOUNT_4K) { ++ av_opt_set_int(enc->context->priv_data, "tile_cols", 2, 0); ++ av_opt_set_int(enc->context->priv_data, "tile_rows", 2, 0); ++ } ++ + enc->height = enc->context->height; + + const char *ffmpeg_opts = obs_data_get_string(settings, "ffmpeg_opts"); +@@ -424,8 +426,20 @@ static void vaapi_destroy(void *data) + bfree(enc); + } + ++static inline const char *vaapi_encoder_name(enum codec_type codec) ++{ ++ if (codec == CODEC_H264) { ++ return "h264_vaapi"; ++ } else if (codec == CODEC_HEVC) { ++ return "hevc_vaapi"; ++ } else if (codec == CODEC_AV1) { ++ return "av1_vaapi"; ++ } ++ return NULL; ++} ++ + static void *vaapi_create_internal(obs_data_t *settings, obs_encoder_t *encoder, +- bool hevc) ++ enum codec_type codec) + { + struct vaapi_encoder *enc; + #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 9, 100) +@@ -435,8 +449,8 @@ static void *vaapi_create_internal(obs_data_t *settings, obs_encoder_t *encoder, + enc = bzalloc(sizeof(*enc)); + enc->encoder = encoder; + +- const char *const name = hevc ? "hevc_vaapi" : "h264_vaapi"; +- enc->vaapi = avcodec_find_encoder_by_name(name); ++ enc->codec = codec; ++ enc->vaapi = avcodec_find_encoder_by_name(vaapi_encoder_name(codec)); + + enc->first_packet = true; + +@@ -453,7 +467,7 @@ static void *vaapi_create_internal(obs_data_t *settings, obs_encoder_t *encoder, + goto fail; + } + +- if (!vaapi_update(enc, settings, hevc)) ++ if (!vaapi_update(enc, settings)) + goto fail; + + return enc; +@@ -465,13 +479,18 @@ static void *vaapi_create_internal(obs_data_t *settings, obs_encoder_t *encoder, + + static void *h264_vaapi_create(obs_data_t *settings, obs_encoder_t *encoder) + { +- return vaapi_create_internal(settings, encoder, false); ++ return vaapi_create_internal(settings, encoder, CODEC_H264); ++} ++ ++static void *av1_vaapi_create(obs_data_t *settings, obs_encoder_t *encoder) ++{ ++ return vaapi_create_internal(settings, encoder, CODEC_AV1); + } + + #ifdef ENABLE_HEVC + static void *hevc_vaapi_create(obs_data_t *settings, obs_encoder_t *encoder) + { +- return vaapi_create_internal(settings, encoder, true); ++ return vaapi_create_internal(settings, encoder, CODEC_HEVC); + } + #endif + +@@ -501,9 +520,8 @@ static inline void copy_data(AVFrame *pic, const struct encoder_frame *frame, + } + } + +-static bool vaapi_encode_internal(void *data, struct encoder_frame *frame, +- struct encoder_packet *packet, +- bool *received_packet, bool hevc) ++static bool vaapi_encode(void *data, struct encoder_frame *frame, ++ struct encoder_packet *packet, bool *received_packet) + { + struct vaapi_encoder *enc = data; + AVFrame *hwframe = NULL; +@@ -569,7 +587,7 @@ static bool vaapi_encode_internal(void *data, struct encoder_frame *frame, + + enc->first_packet = false; + #ifdef ENABLE_HEVC +- if (hevc) { ++ if (enc->codec == CODEC_HEVC) { + obs_extract_hevc_headers( + enc->packet->data, enc->packet->size, + &new_packet, &size, &enc->header, +@@ -579,12 +597,18 @@ static bool vaapi_encode_internal(void *data, struct encoder_frame *frame, + #else + UNUSED_PARAMETER(hevc); + #endif +- { ++ if (enc->codec == CODEC_H264) { + obs_extract_avc_headers( + enc->packet->data, enc->packet->size, + &new_packet, &size, &enc->header, + &enc->header_size, &enc->sei, + &enc->sei_size); ++ } else if (enc->codec == CODEC_AV1) { ++ obs_extract_av1_headers(enc->packet->data, ++ enc->packet->size, ++ &new_packet, &size, ++ &enc->header, ++ &enc->header_size); + } + + da_copy_array(enc->buffer, new_packet, size); +@@ -600,14 +624,17 @@ static bool vaapi_encode_internal(void *data, struct encoder_frame *frame, + packet->size = enc->buffer.num; + packet->type = OBS_ENCODER_VIDEO; + #ifdef ENABLE_HEVC +- if (hevc) { ++ if (enc->codec == CODEC_HEVC) { + packet->keyframe = + obs_hevc_keyframe(packet->data, packet->size); + } else + #endif +- { ++ if (enc->codec == CODEC_H264) { + packet->keyframe = + obs_avc_keyframe(packet->data, packet->size); ++ } else if (enc->codec == CODEC_AV1) { ++ packet->keyframe = ++ obs_av1_keyframe(packet->data, packet->size); + } + *received_packet = true; + } else { +@@ -623,54 +650,65 @@ static bool vaapi_encode_internal(void *data, struct encoder_frame *frame, + return false; + } + +-static bool h264_vaapi_encode(void *data, struct encoder_frame *frame, +- struct encoder_packet *packet, +- bool *received_packet) ++static void set_visible(obs_properties_t *ppts, const char *name, bool visible) + { +- return vaapi_encode_internal(data, frame, packet, received_packet, +- false); ++ obs_property_t *p = obs_properties_get(ppts, name); ++ obs_property_set_visible(p, visible); + } + +-#ifdef ENABLE_HEVC +-static bool hevc_vaapi_encode(void *data, struct encoder_frame *frame, +- struct encoder_packet *packet, +- bool *received_packet) ++static inline VAProfile vaapi_profile(enum codec_type codec) + { +- return vaapi_encode_internal(data, frame, packet, received_packet, +- true); +-} ++ if (codec == CODEC_H264) { ++ return VAProfileH264ConstrainedBaseline; ++#if VA_CHECK_VERSION(1, 14, 0) ++ } else if (codec == CODEC_AV1) { ++ return VAProfileAV1Profile0; + #endif +- +-static void set_visible(obs_properties_t *ppts, const char *name, bool visible) +-{ +- obs_property_t *p = obs_properties_get(ppts, name); +- obs_property_set_visible(p, visible); ++#if ENABLE_HEVC ++ } else if (codec == CODEC_HEVC) { ++ return VAProfileHEVCMain; ++#endif ++ } ++ return VAProfileNone; + } + +-static void vaapi_defaults_internal(obs_data_t *settings, bool hevc) ++static inline const char *vaapi_default_device(enum codec_type codec) + { +-#ifdef ENABLE_HEVC +- const char *device = hevc ? vaapi_get_hevc_default_device() +- : vaapi_get_h264_default_device(); +-#else +- const char *const device = vaapi_get_h264_default_device(); ++ if (codec == CODEC_H264) { ++ return vaapi_get_h264_default_device(); ++ } else if (codec == CODEC_AV1) { ++ return vaapi_get_av1_default_device(); ++#if ENABLE_HEVC ++ } else if (codec == CODEC_HEVC) { ++ return vaapi_get_hevc_default_device(); + #endif ++ } ++ return NULL; ++} + ++static void vaapi_defaults_internal(obs_data_t *settings, enum codec_type codec) ++{ ++ const char *const device = vaapi_default_device(codec); + obs_data_set_default_string(settings, "vaapi_device", device); + #ifdef ENABLE_HEVC +- if (hevc) { ++ if (codec == CODEC_HEVC) { + obs_data_set_default_int(settings, "profile", + FF_PROFILE_HEVC_MAIN); ++ obs_data_set_default_int(settings, "level", 120); + + } else + #else + UNUSED_PARAMETER(hevc); + #endif +- { ++ if (codec == CODEC_H264) { + obs_data_set_default_int(settings, "profile", + FF_PROFILE_H264_CONSTRAINED_BASELINE); ++ obs_data_set_default_int(settings, "level", 40); ++ } else if (codec == CODEC_AV1) { ++ obs_data_set_default_int(settings, "profile", ++ FF_PROFILE_AV1_MAIN); ++ obs_data_set_default_int(settings, "level", 8); + } +- obs_data_set_default_int(settings, "level", 40); + obs_data_set_default_int(settings, "bitrate", 2500); + obs_data_set_default_int(settings, "keyint_sec", 0); + obs_data_set_default_int(settings, "bf", 0); +@@ -683,12 +721,7 @@ static void vaapi_defaults_internal(obs_data_t *settings, bool hevc) + if (!va_dpy) + return; + +-#ifdef ENABLE_HEVC +- const VAProfile profile = hevc ? VAProfileHEVCMain +- : VAProfileH264ConstrainedBaseline; +-#else +- const VAProfile profile = VAProfileH264ConstrainedBaseline; +-#endif ++ const VAProfile profile = vaapi_profile(codec); + if (vaapi_device_rc_supported(profile, va_dpy, VA_RC_CBR, device)) + obs_data_set_default_string(settings, "rate_control", "CBR"); + else if (vaapi_device_rc_supported(profile, va_dpy, VA_RC_VBR, device)) +@@ -701,12 +734,17 @@ static void vaapi_defaults_internal(obs_data_t *settings, bool hevc) + + static void h264_vaapi_defaults(obs_data_t *settings) + { +- vaapi_defaults_internal(settings, false); ++ vaapi_defaults_internal(settings, CODEC_H264); ++} ++ ++static void av1_vaapi_defaults(obs_data_t *settings) ++{ ++ vaapi_defaults_internal(settings, CODEC_AV1); + } + + static void hevc_vaapi_defaults(obs_data_t *settings) + { +- vaapi_defaults_internal(settings, true); ++ vaapi_defaults_internal(settings, CODEC_HEVC); + } + + static bool vaapi_device_modified(obs_properties_t *ppts, obs_property_t *p, +@@ -742,6 +780,13 @@ static bool vaapi_device_modified(obs_properties_t *ppts, obs_property_t *p, + goto fail; + profile = VAProfileH264High; + break; ++#if VA_CHECK_VERSION(1, 14, 0) ++ case FF_PROFILE_AV1_MAIN: ++ if (!vaapi_display_av1_supported(va_dpy, device)) ++ goto fail; ++ profile = VAProfileAV1Profile0; ++ break; ++#endif + #ifdef ENABLE_HEVC + case FF_PROFILE_HEVC_MAIN: + if (!vaapi_display_hevc_supported(va_dpy, device)) +@@ -813,7 +858,7 @@ static bool get_device_name_from_pci(struct pci_access *pacc, char *pci_slot, + return false; + } + +-static obs_properties_t *vaapi_properties_internal(bool hevc) ++static obs_properties_t *vaapi_properties_internal(enum codec_type codec) + { + obs_properties_t *props = obs_properties_create(); + obs_property_t *list; +@@ -904,16 +949,18 @@ static obs_properties_t *vaapi_properties_internal(bool hevc) + obs_module_text("Profile"), + OBS_COMBO_TYPE_LIST, + OBS_COMBO_FORMAT_INT); +- if (hevc) { ++ if (codec == CODEC_HEVC) { + obs_property_list_add_int(list, "Main", FF_PROFILE_HEVC_MAIN); + obs_property_list_add_int(list, "Main10", + FF_PROFILE_HEVC_MAIN_10); +- } else { ++ } else if (codec == CODEC_H264) { + obs_property_list_add_int(list, + "Constrained Baseline (default)", + FF_PROFILE_H264_CONSTRAINED_BASELINE); + obs_property_list_add_int(list, "Main", FF_PROFILE_H264_MAIN); + obs_property_list_add_int(list, "High", FF_PROFILE_H264_HIGH); ++ } else if (codec == CODEC_AV1) { ++ obs_property_list_add_int(list, "Main", FF_PROFILE_AV1_MAIN); + } + + obs_property_set_modified_callback(list, vaapi_device_modified); +@@ -922,15 +969,34 @@ static obs_properties_t *vaapi_properties_internal(bool hevc) + OBS_COMBO_TYPE_LIST, + OBS_COMBO_FORMAT_INT); + obs_property_list_add_int(list, "Auto", FF_LEVEL_UNKNOWN); +- obs_property_list_add_int(list, "3.0", 30); +- obs_property_list_add_int(list, "3.1", 31); +- obs_property_list_add_int(list, "4.0 (default) (Compatibility mode)", +- 40); +- obs_property_list_add_int(list, "4.1", 41); +- obs_property_list_add_int(list, "4.2", 42); +- obs_property_list_add_int(list, "5.0", 50); +- obs_property_list_add_int(list, "5.1", 51); +- obs_property_list_add_int(list, "5.2", 52); ++ if (codec == CODEC_H264) { ++ obs_property_list_add_int(list, "3.0", 30); ++ obs_property_list_add_int(list, "3.1", 31); ++ obs_property_list_add_int( ++ list, "4.0 (default) (Compatibility mode)", 40); ++ obs_property_list_add_int(list, "4.1", 41); ++ obs_property_list_add_int(list, "4.2", 42); ++ obs_property_list_add_int(list, "5.0", 50); ++ obs_property_list_add_int(list, "5.1", 51); ++ obs_property_list_add_int(list, "5.2", 52); ++ } else if (codec == CODEC_HEVC) { ++ obs_property_list_add_int(list, "3.0", 90); ++ obs_property_list_add_int(list, "3.1", 93); ++ obs_property_list_add_int(list, "4.0 (default)", 120); ++ obs_property_list_add_int(list, "4.1", 123); ++ obs_property_list_add_int(list, "5.0", 150); ++ obs_property_list_add_int(list, "5.1", 153); ++ obs_property_list_add_int(list, "5.2", 156); ++ } else if (codec == CODEC_AV1) { ++ obs_property_list_add_int(list, "3.0", 4); ++ obs_property_list_add_int(list, "3.1", 5); ++ obs_property_list_add_int(list, "4.0 (default)", 8); ++ obs_property_list_add_int(list, "4.1", 9); ++ obs_property_list_add_int(list, "5.0", 12); ++ obs_property_list_add_int(list, "5.1", 13); ++ obs_property_list_add_int(list, "5.2", 14); ++ obs_property_list_add_int(list, "5.3", 15); ++ } + + list = obs_properties_add_list(props, "rate_control", + obs_module_text("RateControl"), +@@ -965,14 +1031,20 @@ static obs_properties_t *vaapi_properties_internal(bool hevc) + static obs_properties_t *h264_vaapi_properties(void *unused) + { + UNUSED_PARAMETER(unused); +- return vaapi_properties_internal(false); ++ return vaapi_properties_internal(CODEC_H264); ++} ++ ++static obs_properties_t *av1_vaapi_properties(void *unused) ++{ ++ UNUSED_PARAMETER(unused); ++ return vaapi_properties_internal(CODEC_AV1); + } + + #ifdef ENABLE_HEVC + static obs_properties_t *hevc_vaapi_properties(void *unused) + { + UNUSED_PARAMETER(unused); +- return vaapi_properties_internal(true); ++ return vaapi_properties_internal(CODEC_HEVC); + } + #endif + +@@ -1001,12 +1073,27 @@ struct obs_encoder_info h264_vaapi_encoder_info = { + .get_name = h264_vaapi_getname, + .create = h264_vaapi_create, + .destroy = vaapi_destroy, +- .encode = h264_vaapi_encode, ++ .encode = vaapi_encode, + .get_defaults = h264_vaapi_defaults, + .get_properties = h264_vaapi_properties, + .get_extra_data = vaapi_extra_data, + .get_sei_data = vaapi_sei_data, +- .get_video_info = h264_vaapi_video_info, ++ .get_video_info = vaapi_video_info, ++}; ++ ++struct obs_encoder_info av1_vaapi_encoder_info = { ++ .id = "av1_ffmpeg_vaapi", ++ .type = OBS_ENCODER_VIDEO, ++ .codec = "av1", ++ .get_name = av1_vaapi_getname, ++ .create = av1_vaapi_create, ++ .destroy = vaapi_destroy, ++ .encode = vaapi_encode, ++ .get_defaults = av1_vaapi_defaults, ++ .get_properties = av1_vaapi_properties, ++ .get_extra_data = vaapi_extra_data, ++ .get_sei_data = vaapi_sei_data, ++ .get_video_info = vaapi_video_info, + }; + + #ifdef ENABLE_HEVC +@@ -1017,12 +1104,12 @@ struct obs_encoder_info hevc_vaapi_encoder_info = { + .get_name = hevc_vaapi_getname, + .create = hevc_vaapi_create, + .destroy = vaapi_destroy, +- .encode = hevc_vaapi_encode, ++ .encode = vaapi_encode, + .get_defaults = hevc_vaapi_defaults, + .get_properties = hevc_vaapi_properties, + .get_extra_data = vaapi_extra_data, + .get_sei_data = vaapi_sei_data, +- .get_video_info = hevc_vaapi_video_info, ++ .get_video_info = vaapi_video_info, + }; + #endif + +diff --git a/plugins/obs-ffmpeg/obs-ffmpeg.c b/plugins/obs-ffmpeg/obs-ffmpeg.c +index c62d0d65fff7b..bd7e1cafea3d1 100644 +--- a/plugins/obs-ffmpeg/obs-ffmpeg.c ++++ b/plugins/obs-ffmpeg/obs-ffmpeg.c +@@ -48,6 +48,7 @@ extern struct obs_encoder_info aom_av1_encoder_info; + + #ifdef LIBAVUTIL_VAAPI_AVAILABLE + extern struct obs_encoder_info h264_vaapi_encoder_info; ++extern struct obs_encoder_info av1_vaapi_encoder_info; + #ifdef ENABLE_HEVC + extern struct obs_encoder_info hevc_vaapi_encoder_info; + #endif +@@ -342,6 +343,17 @@ static bool h264_vaapi_supported(void) + * that support H264. */ + return vaapi_get_h264_default_device() != NULL; + } ++static bool av1_vaapi_supported(void) ++{ ++ const AVCodec *vaenc = avcodec_find_encoder_by_name("av1_vaapi"); ++ ++ if (!vaenc) ++ return false; ++ ++ /* NOTE: If default device is NULL, it means there is no device ++ * that support AV1. */ ++ return vaapi_get_av1_default_device() != NULL; ++} + #ifdef ENABLE_HEVC + static bool hevc_vaapi_supported(void) + { +@@ -452,6 +464,13 @@ bool obs_module_load(void) + blog(LOG_INFO, "FFmpeg VAAPI H264 encoding not supported"); + } + ++ if (av1_vaapi_supported()) { ++ blog(LOG_INFO, "FFmpeg VAAPI AV1 encoding supported"); ++ obs_register_encoder(&av1_vaapi_encoder_info); ++ } else { ++ blog(LOG_INFO, "FFmpeg VAAPI AV1 encoding not supported"); ++ } ++ + #ifdef ENABLE_HEVC + if (hevc_vaapi_supported()) { + blog(LOG_INFO, "FFmpeg VAAPI HEVC encoding supported"); +diff --git a/plugins/obs-ffmpeg/vaapi-utils.c b/plugins/obs-ffmpeg/vaapi-utils.c +index 4198ee59c6ab4..ad527ec525e0e 100644 +--- a/plugins/obs-ffmpeg/vaapi-utils.c ++++ b/plugins/obs-ffmpeg/vaapi-utils.c +@@ -261,6 +261,66 @@ const char *vaapi_get_h264_default_device() + return default_h264_device; + } + ++bool vaapi_display_av1_supported(VADisplay dpy, const char *device_path) ++{ ++ bool ret = false; ++ ++#if VA_CHECK_VERSION(1, 14, 0) ++ CHECK_PROFILE(ret, VAProfileAV1Profile0, dpy, device_path); ++ ++ if (!ret) { ++ CHECK_PROFILE_LP(ret, VAProfileAV1Profile0, dpy, device_path); ++ } ++#else ++ UNUSED_PARAMETER(dpy); ++ UNUSED_PARAMETER(device_path); ++#endif ++ ++ return ret; ++} ++ ++bool vaapi_device_av1_supported(const char *device_path) ++{ ++ bool ret = false; ++ VADisplay va_dpy; ++ ++ int drm_fd = -1; ++ ++ va_dpy = vaapi_open_device(&drm_fd, device_path, ++ "vaapi_device_av1_supported"); ++ if (!va_dpy) ++ return false; ++ ++ ret = vaapi_display_av1_supported(va_dpy, device_path); ++ ++ vaapi_close_device(&drm_fd, va_dpy); ++ ++ return ret; ++} ++ ++const char *vaapi_get_av1_default_device() ++{ ++ static const char *default_av1_device = NULL; ++ ++ if (!default_av1_device) { ++ bool ret = false; ++ char path[32] = "/dev/dri/renderD1"; ++ for (int i = 28;; i++) { ++ sprintf(path, "/dev/dri/renderD1%d", i); ++ if (access(path, F_OK) != 0) ++ break; ++ ++ ret = vaapi_device_av1_supported(path); ++ if (ret) { ++ default_av1_device = strdup(path); ++ break; ++ } ++ } ++ } ++ ++ return default_av1_device; ++} ++ + #ifdef ENABLE_HEVC + + bool vaapi_display_hevc_supported(VADisplay dpy, const char *device_path) +diff --git a/plugins/obs-ffmpeg/vaapi-utils.h b/plugins/obs-ffmpeg/vaapi-utils.h +index b90b2394710b3..2d7ee29dc9ab9 100644 +--- a/plugins/obs-ffmpeg/vaapi-utils.h ++++ b/plugins/obs-ffmpeg/vaapi-utils.h +@@ -19,6 +19,10 @@ bool vaapi_display_h264_supported(VADisplay dpy, const char *device_path); + bool vaapi_device_h264_supported(const char *device_path); + const char *vaapi_get_h264_default_device(void); + ++bool vaapi_display_av1_supported(VADisplay dpy, const char *device_path); ++bool vaapi_device_av1_supported(const char *device_path); ++const char *vaapi_get_av1_default_device(void); ++ + #ifdef ENABLE_HEVC + bool vaapi_display_hevc_supported(VADisplay dpy, const char *device_path); + bool vaapi_device_hevc_supported(const char *device_path); diff --git a/patches/0006-encoder-rename.patch b/patches/0006-encoder-rename.patch new file mode 100644 index 0000000..e9f5059 --- /dev/null +++ b/patches/0006-encoder-rename.patch @@ -0,0 +1,151 @@ +From 11dae1dd5a7600534807e254dfa30c9613779dd7 Mon Sep 17 00:00:00 2001 +From: GloriousEggroll +Date: Sat, 29 Apr 2023 14:46:16 -0600 +Subject: [PATCH] encoder rename + +--- + plugins/obs-ffmpeg/jim-nvenc.c | 4 ++-- + plugins/obs-ffmpeg/obs-ffmpeg-av1.c | 4 ++-- + plugins/obs-ffmpeg/obs-ffmpeg-nvenc.c | 4 ++-- + plugins/obs-ffmpeg/texture-amf.cpp | 6 +++--- + plugins/obs-x264/obs-x264.c | 2 +- + 5 files changed, 10 insertions(+), 10 deletions(-) + +diff --git a/plugins/obs-ffmpeg/jim-nvenc.c b/plugins/obs-ffmpeg/jim-nvenc.c +index 10a7dd1..c912205 100644 +--- a/plugins/obs-ffmpeg/jim-nvenc.c ++++ b/plugins/obs-ffmpeg/jim-nvenc.c +@@ -227,14 +227,14 @@ static void nv_texture_free(struct nvenc_data *enc, struct nv_texture *nvtex) + static const char *h264_nvenc_get_name(void *type_data) + { + UNUSED_PARAMETER(type_data); +- return "NVIDIA NVENC H.264"; ++ return "GPU: NVIDIA NVENC H.264 (FFmpeg)"; + } + + #ifdef ENABLE_HEVC + static const char *hevc_nvenc_get_name(void *type_data) + { + UNUSED_PARAMETER(type_data); +- return "NVIDIA NVENC HEVC"; ++ return "GPU: NVIDIA NVENC H.265/HEVC (FFmpeg)"; + } + #endif + +diff --git a/plugins/obs-ffmpeg/obs-ffmpeg-av1.c b/plugins/obs-ffmpeg/obs-ffmpeg-av1.c +index 0b671ae..681f728 100644 +--- a/plugins/obs-ffmpeg/obs-ffmpeg-av1.c ++++ b/plugins/obs-ffmpeg/obs-ffmpeg-av1.c +@@ -41,13 +41,13 @@ struct av1_encoder { + static const char *aom_av1_getname(void *unused) + { + UNUSED_PARAMETER(unused); +- return "AOM AV1"; ++ return "CPU: AOM AV1 (FFmpeg)"; + } + + static const char *svt_av1_getname(void *unused) + { + UNUSED_PARAMETER(unused); +- return "SVT-AV1"; ++ return "CPU: SVT-AV1 (FFmpeg)"; + } + + static void av1_video_info(void *data, struct video_scale_info *info) +diff --git a/plugins/obs-ffmpeg/obs-ffmpeg-nvenc.c b/plugins/obs-ffmpeg/obs-ffmpeg-nvenc.c +index 8cd8138..add8e02 100644 +--- a/plugins/obs-ffmpeg/obs-ffmpeg-nvenc.c ++++ b/plugins/obs-ffmpeg/obs-ffmpeg-nvenc.c +@@ -45,7 +45,7 @@ struct nvenc_encoder { + extern bool ubuntu_20_04_nvenc_fallback; + #endif + +-#define ENCODER_NAME_H264 "NVIDIA NVENC H.264 (FFmpeg)" ++#define ENCODER_NAME_H264 "GPU: NVIDIA NVENC H.264 (FFmpeg)" + static const char *h264_nvenc_getname(void *unused) + { + UNUSED_PARAMETER(unused); +@@ -53,7 +53,7 @@ static const char *h264_nvenc_getname(void *unused) + } + + #ifdef ENABLE_HEVC +-#define ENCODER_NAME_HEVC "NVIDIA NVENC HEVC (FFmpeg)" ++#define ENCODER_NAME_HEVC "GPU: NVIDIA NVENC H.265/HEVC (FFmpeg)" + static const char *hevc_nvenc_getname(void *unused) + { + UNUSED_PARAMETER(unused); +diff --git a/plugins/obs-ffmpeg/texture-amf.cpp b/plugins/obs-ffmpeg/texture-amf.cpp +index 0f5ee7b..e350257 100644 +--- a/plugins/obs-ffmpeg/texture-amf.cpp ++++ b/plugins/obs-ffmpeg/texture-amf.cpp +@@ -2101,7 +2101,7 @@ static obs_properties_t *amf_av1_properties(void *unused) + + static const char *amf_avc_get_name(void *) + { +- return "AMD HW H.264 (AVC)"; ++ return "GPU: AMD AMF H.264 (FFmpeg)"; + } + + static inline int get_avc_preset(amf_base *enc, const char *preset) +@@ -2443,7 +2443,7 @@ static void register_avc() + + static const char *amf_hevc_get_name(void *) + { +- return "AMD HW H.265 (HEVC)"; ++ return "GPU: AMD AMF H.265/HEVC (FFmpeg)"; + } + + static inline int get_hevc_preset(amf_base *enc, const char *preset) +@@ -2788,7 +2788,7 @@ static void register_hevc() + + static const char *amf_av1_get_name(void *) + { +- return "AMD HW AV1"; ++ return "GPU: AMD AMF AV1 (FFmpeg)"; + } + + static inline int get_av1_preset(amf_base *enc, const char *preset) +diff --git a/plugins/obs-x264/obs-x264.c b/plugins/obs-x264/obs-x264.c +index 1de88d3..d4c377d 100644 +--- a/plugins/obs-x264/obs-x264.c ++++ b/plugins/obs-x264/obs-x264.c +@@ -68,7 +68,7 @@ struct obs_x264 { + static const char *obs_x264_getname(void *unused) + { + UNUSED_PARAMETER(unused); +- return "x264"; ++ return "CPU: x264"; + } + + static void obs_x264_stop(void *data); +diff --git a/plugins/obs-ffmpeg/obs-ffmpeg-vaapi.c b/plugins/obs-ffmpeg/obs-ffmpeg-vaapi.c +index 370f9b7..e0bbd82 100644 +--- a/plugins/obs-ffmpeg/obs-ffmpeg-vaapi.c ++++ b/plugins/obs-ffmpeg/obs-ffmpeg-vaapi.c +@@ -89,20 +89,20 @@ struct vaapi_encoder { + static const char *h264_vaapi_getname(void *unused) + { + UNUSED_PARAMETER(unused); +- return "FFmpeg VAAPI H.264"; ++ return "GPU: AMD/Intel VAAPI H.264 (FFmpeg)"; + } + + static const char *av1_vaapi_getname(void *unused) + { + UNUSED_PARAMETER(unused); +- return "FFmpeg VAAPI AV1"; ++ return "GPU: AMD/Intel VAAPI AV1 (FFmpeg)"; + } + + #ifdef ENABLE_HEVC + static const char *hevc_vaapi_getname(void *unused) + { + UNUSED_PARAMETER(unused); +- return "FFmpeg VAAPI HEVC"; ++ return "GPU: AMD/Intel VAAPI H.265/HEVC (FFmpeg)"; + } + #endif + +-- +2.40.0 + diff --git a/patches/0007-5fdda179ed2768304a98d48f4074e54fe7cbf5b3.patch b/patches/0007-5fdda179ed2768304a98d48f4074e54fe7cbf5b3.patch new file mode 100644 index 0000000..6f93acf --- /dev/null +++ b/patches/0007-5fdda179ed2768304a98d48f4074e54fe7cbf5b3.patch @@ -0,0 +1,27 @@ +From 5fdda179ed2768304a98d48f4074e54fe7cbf5b3 Mon Sep 17 00:00:00 2001 +From: David Rosca +Date: Fri, 30 Jun 2023 07:23:41 +0200 +Subject: [PATCH] obs-ffmpeg: Increase initial buffer fullness for VAAPI + +Default ffmpeg initial buffer fullness (75%) is too low +and results in significantly lower video quality on AMD cards. + +Changing it to 100% fixes the quality and also matches what +AMF encoder is doing. +--- + plugins/obs-ffmpeg/obs-ffmpeg-vaapi.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/plugins/obs-ffmpeg/obs-ffmpeg-vaapi.c b/plugins/obs-ffmpeg/obs-ffmpeg-vaapi.c +index c5aa0128a54b9..1a6ecd63ae4d4 100644 +--- a/plugins/obs-ffmpeg/obs-ffmpeg-vaapi.c ++++ b/plugins/obs-ffmpeg/obs-ffmpeg-vaapi.c +@@ -300,6 +300,8 @@ static bool vaapi_update(void *data, obs_data_t *settings, bool hevc) + enc->context->level = level; + enc->context->bit_rate = bitrate * 1000; + enc->context->rc_max_rate = maxrate * 1000; ++ enc->context->rc_initial_buffer_occupancy = ++ (maxrate ? maxrate : bitrate) * 1000; + + enc->context->width = obs_encoder_get_width(enc->encoder); + enc->context->height = obs_encoder_get_height(enc->encoder); diff --git a/patches/8293.patch b/patches/8293.patch deleted file mode 100644 index 7647957..0000000 --- a/patches/8293.patch +++ /dev/null @@ -1,101 +0,0 @@ -From 6b022ae4b58af7a069a422d346f102bf18684249 Mon Sep 17 00:00:00 2001 -From: columbarius -Date: Sat, 21 Jan 2023 08:45:38 +0100 -Subject: [PATCH] pipewire: calc spa buffer size - -Modern GPUs might support a lot of modifiers. As such the hardcoded size -for the ENUM_Formats PipeWire params are not enough and we should -calculate the required size manually. - -Added logs if a ENUM_Format can't be assembled, which happens when the -buffer size was not large enough. ---- - plugins/linux-pipewire/pipewire.c | 47 +++++++++++++++++++++++++++++-- - 1 file changed, 45 insertions(+), 2 deletions(-) - -diff --git a/plugins/linux-pipewire/pipewire.c b/plugins/linux-pipewire/pipewire.c -index d639e86df0f25..e7a941d778b04 100644 ---- a/plugins/linux-pipewire/pipewire.c -+++ b/plugins/linux-pipewire/pipewire.c -@@ -144,6 +144,41 @@ static void update_pw_versions(obs_pipewire *obs_pw, const char *version) - blog(LOG_WARNING, "[pipewire] failed to parse server version"); - } - -+static uint32_t calc_spa_enumformat_buffer_size(obs_pipewire *obs_pw) -+{ -+ // from spa/pod/pod.h -+ uint32_t spa_pod_object_size = sizeof(struct spa_pod_object); -+ uint32_t spa_pod_prop_size = sizeof(struct spa_pod_prop); -+ uint32_t spa_pod_value_size = 1 * sizeof(uint64_t); -+ uint32_t spa_pod_choice_size = 2 * sizeof(uint64_t); -+ // This is counted from the build_format function -+ uint32_t n_objects = 0; -+ uint32_t n_props = 0; -+ uint32_t n_values = 0; -+ uint32_t n_choices = 0; -+ uint32_t size; -+ -+ for (size_t i = 0; i < obs_pw->format_info.num; i++) { -+ if (obs_pw->format_info.array[i].modifiers.num == 0) -+ continue; -+ n_objects += 1; -+ n_props += 5 + 1; -+ n_values += 9 + 2 + obs_pw->format_info.array[i].modifiers.num; -+ n_choices += 2 + 1; -+ } -+ for (size_t i = 0; i < obs_pw->format_info.num; i++) { -+ n_objects += 1; -+ n_props += 5; -+ n_values += 9; -+ n_choices += 2; -+ } -+ size = n_objects * spa_pod_object_size + n_props * spa_pod_prop_size + -+ n_values * spa_pod_value_size + n_choices * spa_pod_choice_size; -+ blog(LOG_DEBUG, "[pipewire]: calculated spa enumFormat buffer size %u", -+ size); -+ return size; -+} -+ - static void teardown_pipewire(obs_pipewire *obs_pw) - { - if (obs_pw->thread_loop) { -@@ -408,6 +443,10 @@ static bool build_format_params(obs_pipewire *obs_pw, - obs_pw->format_info.array[i].spa_format, - obs_pw->format_info.array[i].modifiers.array, - obs_pw->format_info.array[i].modifiers.num); -+ if (!params[params_count - 1]) { -+ blog(LOG_ERROR, "[pipewire] Failed to format param"); -+ return false; -+ } - } - - build_shm: -@@ -415,6 +454,10 @@ static bool build_format_params(obs_pipewire *obs_pw, - params[params_count++] = build_format( - pod_builder, &obs_pw->video_info, - obs_pw->format_info.array[i].spa_format, NULL, 0); -+ if (!params[params_count - 1]) { -+ blog(LOG_ERROR, "[pipewire] Failed to format param"); -+ return false; -+ } - } - *param_list = params; - *n_params = params_count; -@@ -521,7 +564,7 @@ static void renegotiate_format(void *data, uint64_t expirations) - - pw_thread_loop_lock(obs_pw->thread_loop); - -- uint8_t params_buffer[2048]; -+ uint8_t params_buffer[calc_spa_enumformat_buffer_size(obs_pw)]; - struct spa_pod_builder pod_builder = - SPA_POD_BUILDER_INIT(params_buffer, sizeof(params_buffer)); - uint32_t n_params; -@@ -970,7 +1013,7 @@ void obs_pipewire_connect_stream(obs_pipewire *obs_pw, int pipewire_node, - struct spa_pod_builder pod_builder; - const struct spa_pod **params = NULL; - uint32_t n_params; -- uint8_t params_buffer[2048]; -+ uint8_t params_buffer[calc_spa_enumformat_buffer_size(obs_pw)]; - - pw_thread_loop_lock(obs_pw->thread_loop); - diff --git a/patches/encoder-rename.patch b/patches/encoder-rename.patch deleted file mode 100644 index 4b48f44..0000000 --- a/patches/encoder-rename.patch +++ /dev/null @@ -1,93 +0,0 @@ -From 323db1c9072aa1338a00dc0ddd35c655bf1e4918 Mon Sep 17 00:00:00 2001 -From: GloriousEggroll -Date: Mon, 16 Jan 2023 11:30:15 -0700 -Subject: [PATCH] encoder rename - ---- - plugins/obs-ffmpeg/jim-nvenc.c | 4 ++-- - plugins/obs-ffmpeg/obs-ffmpeg-av1.c | 4 ++-- - plugins/obs-ffmpeg/obs-ffmpeg-nvenc.c | 4 ++-- - plugins/obs-ffmpeg/texture-amf.cpp | 4 ++-- - plugins/obs-x264/obs-x264.c | 2 +- - 5 files changed, 9 insertions(+), 9 deletions(-) - -diff --git a/plugins/obs-ffmpeg/jim-nvenc.c b/plugins/obs-ffmpeg/jim-nvenc.c -index 7b247c8..5c4be0f 100644 ---- a/plugins/obs-ffmpeg/jim-nvenc.c -+++ b/plugins/obs-ffmpeg/jim-nvenc.c -@@ -227,14 +227,14 @@ static void nv_texture_free(struct nvenc_data *enc, struct nv_texture *nvtex) - static const char *h264_nvenc_get_name(void *type_data) - { - UNUSED_PARAMETER(type_data); -- return "NVIDIA NVENC H.264"; -+ return "GPU: Nvidia NVENC H.264/AVC"; - } - - #ifdef ENABLE_HEVC - static const char *hevc_nvenc_get_name(void *type_data) - { - UNUSED_PARAMETER(type_data); -- return "NVIDIA NVENC HEVC"; -+ return "GPU: Nvidia NVENC H.265/HEVC"; - } - #endif - -diff --git a/plugins/obs-ffmpeg/obs-ffmpeg-av1.c b/plugins/obs-ffmpeg/obs-ffmpeg-av1.c -index de7e237..7ea3cf7 100644 ---- a/plugins/obs-ffmpeg/obs-ffmpeg-av1.c -+++ b/plugins/obs-ffmpeg/obs-ffmpeg-av1.c -@@ -41,13 +41,13 @@ struct av1_encoder { - static const char *aom_av1_getname(void *unused) - { - UNUSED_PARAMETER(unused); -- return "AOM AV1"; -+ return "CPU: AOM AV1"; - } - - static const char *svt_av1_getname(void *unused) - { - UNUSED_PARAMETER(unused); -- return "SVT-AV1"; -+ return "CPU: SVT-AV1"; - } - - static void av1_video_info(void *data, struct video_scale_info *info) -diff --git a/plugins/obs-ffmpeg/obs-ffmpeg-nvenc.c b/plugins/obs-ffmpeg/obs-ffmpeg-nvenc.c -index f0f7747..b5f5d0d 100644 ---- a/plugins/obs-ffmpeg/obs-ffmpeg-nvenc.c -+++ b/plugins/obs-ffmpeg/obs-ffmpeg-nvenc.c -@@ -43,7 +43,7 @@ struct nvenc_encoder { - extern bool ubuntu_20_04_nvenc_fallback; - #endif - --#define ENCODER_NAME_H264 "NVIDIA NVENC H.264 (FFmpeg)" -+#define ENCODER_NAME_H264 "GPU: Nvidia NVENC H.264/AVC" - static const char *h264_nvenc_getname(void *unused) - { - UNUSED_PARAMETER(unused); -@@ -51,7 +51,7 @@ static const char *h264_nvenc_getname(void *unused) - } - - #ifdef ENABLE_HEVC --#define ENCODER_NAME_HEVC "NVIDIA NVENC HEVC (FFmpeg)" -+#define ENCODER_NAME_HEVC "GPU: Nvidia NVENC H.265/HEVC" - static const char *hevc_nvenc_getname(void *unused) - { - UNUSED_PARAMETER(unused); - -diff --git a/plugins/obs-x264/obs-x264.c b/plugins/obs-x264/obs-x264.c -index 3955dff..b60e990 100644 ---- a/plugins/obs-x264/obs-x264.c -+++ b/plugins/obs-x264/obs-x264.c -@@ -68,7 +68,7 @@ struct obs_x264 { - static const char *obs_x264_getname(void *unused) - { - UNUSED_PARAMETER(unused); -- return "x264"; -+ return "CPU: x264"; - } - - static void obs_x264_stop(void *data); --- -2.39.0 - diff --git a/release.sh b/release.sh index 5c59923..1575255 100755 --- a/release.sh +++ b/release.sh @@ -2,7 +2,7 @@ rsync -azP --include './' --include '*.deb' --exclude '*' ./output/ ferreo@direct.pika-os.com:/srv/www/incoming/ # add debs to repo -ssh ferreo@direct.pika-os.com 'aptly repo add -force-replace -remove-files pika-main /srv/www/incoming/' +ssh ferreo@direct.pika-os.com 'aptly repo add -force-replace -remove-files pikauwu-main /srv/www/incoming/' # publish the repo -ssh ferreo@direct.pika-os.com 'aptly publish update -batch -skip-contents -force-overwrite lunar filesystem:pikarepo:' +ssh ferreo@direct.pika-os.com 'aptly publish update -batch -skip-contents -force-overwrite pikauwu filesystem:pikarepo:' \ No newline at end of file