From 270a8636aed52ddb97242bcf1a77f9d36206cf36 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Mon, 3 Oct 2022 17:29:13 +0200 Subject: [PATCH] Capture cursor in direct capture mode if supported by the driver (driver version >= 515.57) --- README.md | 2 +- include/NvFBCLibrary.hpp | 32 +++++++++++++++++++++++++++++--- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 867c15c..4f20586 100644 --- a/README.md +++ b/README.md @@ -53,6 +53,6 @@ FFMPEG only uses the GPU with CUDA when doing transcoding from an input video to libraries at compile-time. * Clean up the code! * Dynamically change bitrate/resolution to match desired fps. This would be helpful when streaming for example, where the encode output speed also depends on upload speed to the streaming service. -* Show cursor when recording. Currently the cursor is not visible when recording a window and it's disabled when recording screen-direct to allow direct nvfbc capture for fullscreen windows, which allows for better performance and variable refresh rate monitors to work. +* Show cursor when recording. Currently the cursor is not visible when recording a window. * Implement opengl injection to capture texture. This fixes composition issues and (VRR) without having to use NvFBC direct capture. * Always use direct capture with NvFBC once the capture issue in mpv fullscreen has been resolved (maybe detect if direct capture fails in nvfbc and switch to non-direct recording. NvFBC says if direct capture fails). diff --git a/include/NvFBCLibrary.hpp b/include/NvFBCLibrary.hpp index 6ce6635..3a642f4 100644 --- a/include/NvFBCLibrary.hpp +++ b/include/NvFBCLibrary.hpp @@ -4,6 +4,7 @@ #include #include #include +#include class NvFBCLibrary { public: @@ -55,7 +56,7 @@ public: return true; } - // If |display_to_capture| is "screen", then the entire x11 screen is captured (all displays) + // If |display_to_capture| is "screen", then the entire x11 screen is captured (all displays). bool create(const char *display_to_capture, uint32_t fps, /*out*/ uint32_t *display_width, /*out*/ uint32_t *display_height, uint32_t x = 0, uint32_t y = 0, uint32_t width = 0, uint32_t height = 0, bool direct_capture = false) { if(!library || !display_to_capture || !display_width || !display_height || fbc_handle_created) return false; @@ -120,7 +121,7 @@ public: memset(&create_capture_params, 0, sizeof(create_capture_params)); create_capture_params.dwVersion = NVFBC_CREATE_CAPTURE_SESSION_PARAMS_VER; create_capture_params.eCaptureType = NVFBC_CAPTURE_SHARED_CUDA; - create_capture_params.bWithCursor = direct_capture ? NVFBC_FALSE : NVFBC_TRUE; + create_capture_params.bWithCursor = (!direct_capture || driver_supports_direct_capture_cursor()) ? NVFBC_TRUE : NVFBC_FALSE; if(capture_region) { create_capture_params.captureBox = { x, y, width, height }; *display_width = width; @@ -221,7 +222,7 @@ private: } // Returns 0 on failure - uint32_t get_output_id_from_display_name(NVFBC_RANDR_OUTPUT_INFO *outputs, uint32_t num_outputs, const char *display_name, uint32_t *display_width, uint32_t *display_height) { + static uint32_t get_output_id_from_display_name(NVFBC_RANDR_OUTPUT_INFO *outputs, uint32_t num_outputs, const char *display_name, uint32_t *display_width, uint32_t *display_height) { if(!outputs) return 0; @@ -235,6 +236,31 @@ private: return 0; } + + // TODO: Test with optimus and open kernel modules + static bool driver_supports_direct_capture_cursor() { + FILE *f = fopen("/proc/driver/nvidia/version", "rb"); + if(!f) + return false; + + char buffer[2048]; + size_t bytes_read = fread(buffer, 1, sizeof(buffer) - 1, f); + buffer[bytes_read] = '\0'; + + bool supports_cursor = false; + const char *p = strstr(buffer, "Kernel Module"); + if(p) { + p += 13; + int driver_major_version = 0, driver_minor_version = 0; + if(sscanf(p, "%d.%d", &driver_major_version, &driver_minor_version) == 2) { + if(driver_major_version > 515 || (driver_major_version == 515 && driver_minor_version >= 57)) + supports_cursor = true; + } + } + + fclose(f); + return supports_cursor; + } private: void *library = nullptr; PNVFBCCREATEINSTANCE nv_fbc_create_instance = nullptr;