Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package gpu-screen-recorder for openSUSE:Factory checked in at 2024-10-23 21:10:20 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/gpu-screen-recorder (Old) and /work/SRC/openSUSE:Factory/.gpu-screen-recorder.new.26871 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "gpu-screen-recorder" Wed Oct 23 21:10:20 2024 rev:7 rq:1217107 version:20241022 Changes: -------- --- /work/SRC/openSUSE:Factory/gpu-screen-recorder/gpu-screen-recorder.changes 2024-10-12 13:36:11.518320821 +0200 +++ /work/SRC/openSUSE:Factory/.gpu-screen-recorder.new.26871/gpu-screen-recorder.changes 2024-10-23 21:11:33.789908023 +0200 @@ -1,0 +2,11 @@ +Tue Oct 22 18:58:39 UTC 2024 - mantari...@pm.me + +- Update to version 20241022: + * Fix capture not working if one of the audio inputs is a virtual + audio device with forward slash in its name, for example if + NoiseTorch is used + * Enable AMD low latency mode + * Better frame timing when hardware is too slow to record at the + desired framerate + +------------------------------------------------------------------- Old: ---- gpu-screen-recorder-20241012.tar.zst New: ---- gpu-screen-recorder-20241022.tar.zst ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ gpu-screen-recorder.spec ++++++ --- /var/tmp/diff_new_pack.Kns0Jt/_old 2024-10-23 21:11:34.433934909 +0200 +++ /var/tmp/diff_new_pack.Kns0Jt/_new 2024-10-23 21:11:34.433934909 +0200 @@ -18,7 +18,7 @@ %bcond_with test Name: gpu-screen-recorder -Version: 20241012 +Version: 20241022 Release: 0 Summary: An extremely fast hardware-accelerated screen recorder License: GPL-3.0-only ++++++ _servicedata ++++++ --- /var/tmp/diff_new_pack.Kns0Jt/_old 2024-10-23 21:11:34.477936746 +0200 +++ /var/tmp/diff_new_pack.Kns0Jt/_new 2024-10-23 21:11:34.481936912 +0200 @@ -1,6 +1,6 @@ <servicedata> <service name="tar_scm"> <param name="url">https://repo.dec05eba.com/gpu-screen-recorder.git</param> - <param name="changesrevision">1e6866236d0ce6e8b50b7c72f617bd45e02532d6</param></service></servicedata> + <param name="changesrevision">422f214283ba50649acca4d9b5a9778d313fe05b</param></service></servicedata> (No newline at EOF) ++++++ gpu-screen-recorder-20241012.tar.zst -> gpu-screen-recorder-20241022.tar.zst ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gpu-screen-recorder-20241012/README.md new/gpu-screen-recorder-20241022/README.md --- old/gpu-screen-recorder-20241012/README.md 2024-10-12 01:47:11.000000000 +0200 +++ new/gpu-screen-recorder-20241022/README.md 2024-10-22 18:47:23.000000000 +0200 @@ -168,4 +168,6 @@ ## The colors look washed out when recording a monitor with HDR enabled You have to either record in hdr mode (-k `hevc_hdr` or -k `av1_hdr` option) to record a HDR video or record with desktop portal option (`-w portal`) to turn the HDR recording into SDR. ## GPU Screen Recorder records night light when recording in HDR mode -You can record with desktop portal option (`-w portal`) instead which ignores night light, if you are ok with recording without HDR. \ No newline at end of file +You can record with desktop portal option (`-w portal`) instead which ignores night light, if you are ok with recording without HDR. +## Kdenlive says that the video is not usable for editing because it has variable frame rate +To fix this you can either record the video in .mkv format or constant frame rate (-fm cfr). diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gpu-screen-recorder-20241012/TODO new/gpu-screen-recorder-20241022/TODO --- old/gpu-screen-recorder-20241012/TODO 2024-10-12 01:47:11.000000000 +0200 +++ new/gpu-screen-recorder-20241022/TODO 2024-10-22 18:47:23.000000000 +0200 @@ -156,9 +156,6 @@ Fix pure vaapi copy on intel. -ffmpeg supports vulkan encoding now (h264!). Doesn't work on amd yet because mesa is missing VK_KHR_video_maintenance1, see https://gitlab.freedesktop.org/mesa/mesa/-/issues/11857. Test on nvidia! - -Test vaapi low latency mode (setenv("AMD_DEBUG", "lowlatencyenc", true);), added in mesa 24.1.4, released on july 17, 2024. Note that this forces gpu power usage to max at all times, even when recording at 2 fps. Use nvidia low latency options for better encoding times. Test ideal async_depth value. Increasing async_depth also increased gpu memory usage a lot (from 100mb to 500mb when moving from async_depth 2 to 16) at 4k resolution. Setting it to 8 increases it by 200mb which might be ok. @@ -175,4 +172,10 @@ 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. Implement opengl injection to capture texture. This fixes VRR without having to use NvFBC direct capture and also allows perfect frame timing. -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). \ No newline at end of file +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). + +Support ROI (AV_FRAME_DATA_REGIONS_OF_INTEREST). + +Default to hevc if capture size is larger than 4096 in width or height. + +Set low latency mode on vulkan encoding. \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gpu-screen-recorder-20241012/kms/client/kms_client.c new/gpu-screen-recorder-20241022/kms/client/kms_client.c --- old/gpu-screen-recorder-20241012/kms/client/kms_client.c 2024-10-12 01:47:11.000000000 +0200 +++ new/gpu-screen-recorder-20241022/kms/client/kms_client.c 2024-10-22 18:47:23.000000000 +0200 @@ -183,6 +183,40 @@ *end = '\0'; } +static bool find_program_in_path(const char *program_name, char *filepath, int filepath_len) { + const char *path = getenv("PATH"); + if(!path) + return false; + + int program_name_len = strlen(program_name); + const char *end = path + strlen(path); + while(path != end) { + const char *part_end = strchr(path, ':'); + const char *next = part_end; + if(part_end) { + next = part_end + 1; + } else { + part_end = end; + next = end; + } + + int len = part_end - path; + if(len + 1 + program_name_len < filepath_len) { + memcpy(filepath, path, len); + filepath[len] = '/'; + memcpy(filepath + len + 1, program_name, program_name_len); + filepath[len + 1 + program_name_len] = '\0'; + + if(access(filepath, F_OK) == 0) + return true; + } + + path = next; + } + + return false; +} + int gsr_kms_client_init(gsr_kms_client *self, const char *card_path) { int result = -1; self->kms_server_pid = -1; @@ -212,8 +246,11 @@ } if(access(server_filepath, F_OK) != 0) { - fprintf(stderr, "gsr error: gsr_kms_client_init: gsr-kms-server is not installed (%s not found)\n", server_filepath); - return -1; + fprintf(stderr, "gsr info: gsr_kms_client_init: gsr-kms-server is not installed in the same directory as gpu-screen-recorder (%s not found), looking for gsr-kms-server in PATH instead\n", server_filepath); + if(!find_program_in_path("gsr-kms-server", server_filepath, sizeof(server_filepath)) || access(server_filepath, F_OK) != 0) { + fprintf(stderr, "gsr error: gsr_kms_client_init: gsr-kms-server was not found in PATH. Please install gpu-screen-recorder properly\n"); + return -1; + } } fprintf(stderr, "gsr info: gsr_kms_client_init: setting up connection to %s\n", server_filepath); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gpu-screen-recorder-20241012/meson.build new/gpu-screen-recorder-20241022/meson.build --- old/gpu-screen-recorder-20241012/meson.build 2024-10-12 01:47:11.000000000 +0200 +++ new/gpu-screen-recorder-20241022/meson.build 2024-10-22 18:47:23.000000000 +0200 @@ -1,4 +1,4 @@ -project('gpu-screen-recorder', ['c', 'cpp'], version : '4.2.0', default_options : ['warning_level=2']) +project('gpu-screen-recorder', ['c', 'cpp'], version : '4.2.4', default_options : ['warning_level=2']) add_project_arguments('-Wshadow', language : ['c', 'cpp']) if get_option('buildtype') == 'debug' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gpu-screen-recorder-20241012/project.conf new/gpu-screen-recorder-20241022/project.conf --- old/gpu-screen-recorder-20241012/project.conf 2024-10-12 01:47:11.000000000 +0200 +++ new/gpu-screen-recorder-20241022/project.conf 2024-10-22 18:47:23.000000000 +0200 @@ -1,7 +1,7 @@ [package] name = "gpu-screen-recorder" type = "executable" -version = "4.2.0" +version = "4.2.4" platforms = ["posix"] [config] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gpu-screen-recorder-20241012/src/main.cpp new/gpu-screen-recorder-20241022/src/main.cpp --- old/gpu-screen-recorder-20241012/src/main.cpp 2024-10-12 01:47:11.000000000 +0200 +++ new/gpu-screen-recorder-20241022/src/main.cpp 2024-10-22 18:47:23.000000000 +0200 @@ -810,10 +810,9 @@ if(bitrate_mode == BitrateMode::QP) video_software_set_qp(codec_context, video_quality, hdr, &options); - av_dict_set(&options, "preset", "medium", 0); + av_dict_set(&options, "preset", "fast", 0); dict_set_profile(codec_context, GSR_GPU_VENDOR_INTEL, color_depth, &options); - // TODO: If streaming or piping output set this to zerolatency - av_dict_set(&options, "tune", "fastdecode", 0); + av_dict_set(&options, "tune", "zerolatency", 0); if(codec_context->codec_id == AV_CODEC_ID_H264) { av_dict_set(&options, "coder", "cabac", 0); // TODO: cavlc is faster than cabac but worse compression. Which to use? @@ -990,6 +989,14 @@ // TODO: Enable multipass if(vendor == GSR_GPU_VENDOR_NVIDIA) { + // TODO: These dont seem to be necessary + // av_dict_set_int(&options, "zerolatency", 1, 0); + // if(codec_context->codec_id == AV_CODEC_ID_AV1) { + // av_dict_set(&options, "tune", "ll", 0); + // } else if(codec_context->codec_id == AV_CODEC_ID_H264 || codec_context->codec_id == AV_CODEC_ID_HEVC) { + // av_dict_set(&options, "preset", "llhq", 0); + // av_dict_set(&options, "tune", "ll", 0); + // } av_dict_set(&options, "tune", "hq", 0); dict_set_profile(codec_context, vendor, color_depth, &options); @@ -1155,7 +1162,7 @@ fprintf(stderr, " Note: the directory to the portal session token file is created automatically if it doesn't exist.\n"); fprintf(stderr, "\n"); fprintf(stderr, " -encoder\n"); - fprintf(stderr, " Which device should be used for video encoding. Should either be 'gpu' or 'cpu'. Does currently only work with h264 codec option (-k).\n"); + fprintf(stderr, " Which device should be used for video encoding. Should either be 'gpu' or 'cpu'. 'cpu' option currently only work with h264 codec option (-k).\n"); fprintf(stderr, " Optional, set to 'gpu' by default.\n"); fprintf(stderr, "\n"); fprintf(stderr, " --info\n"); @@ -1170,6 +1177,7 @@ fprintf(stderr, " For example:\n"); fprintf(stderr, " bluez_input.88:C9:E8:66:A2:27|WH-1000XM4\n"); fprintf(stderr, " The <audio_device_name> is the name to pass to GPU Screen Recorder in a -a option.\n"); + fprintf(stderr, "\n"); fprintf(stderr, " --version\n"); fprintf(stderr, " Print version (%s) and exit\n", GSR_VERSION); fprintf(stderr, "\n"); @@ -1178,7 +1186,7 @@ fprintf(stderr, " In replay mode this has to be a directory instead of a file.\n"); fprintf(stderr, " Note: the directory to the file is created automatically if it doesn't already exist.\n"); fprintf(stderr, "\n"); - fprintf(stderr, " -v Prints per second, fps updates. Optional, set to 'yes' by default.\n"); + fprintf(stderr, " -v Prints fps and damage info once per second. Optional, set to 'yes' by default.\n"); fprintf(stderr, "\n"); fprintf(stderr, " -h, --help\n"); fprintf(stderr, " Show this help.\n"); @@ -1573,16 +1581,27 @@ } } -static std::vector<AudioInput> parse_audio_input_arg(const char *str) { +static const AudioInput* get_audio_device_by_name(const std::vector<AudioInput> &audio_inputs, const std::string &name) { + for(const auto &audio_input : audio_inputs) { + if(audio_input.name == name) + return &audio_input; + } + return nullptr; +} + +static std::vector<AudioInput> parse_audio_input_arg(const char *str, const AudioDevices &audio_devices) { std::vector<AudioInput> audio_inputs; - split_string(str, '|', [&audio_inputs](const char *sub, size_t size) { + split_string(str, '|', [&](const char *sub, size_t size) { AudioInput audio_input; audio_input.name.assign(sub, size); + + const bool name_is_existing_audio_device = get_audio_device_by_name(audio_devices.audio_inputs, audio_input.name); const size_t index = audio_input.name.find('/'); - if(index != std::string::npos) { + if(!name_is_existing_audio_device && index != std::string::npos) { audio_input.description = audio_input.name.substr(0, index); audio_input.name.erase(audio_input.name.begin(), audio_input.name.begin() + index + 1); } + audio_inputs.push_back(std::move(audio_input)); return true; }); @@ -2257,7 +2276,7 @@ if(!audio_input || audio_input[0] == '\0') continue; - requested_audio_inputs.push_back({parse_audio_input_arg(audio_input)}); + requested_audio_inputs.push_back({parse_audio_input_arg(audio_input, audio_devices)}); if(requested_audio_inputs.back().audio_inputs.size() > 1) uses_amix = true; @@ -2278,14 +2297,11 @@ match = true; } - for(const auto &existing_audio_input : audio_devices.audio_inputs) { - if(request_audio_input.name == existing_audio_input.name) { - if(request_audio_input.description.empty()) - request_audio_input.description = "gsr-" + existing_audio_input.description; - - match = true; - break; - } + const AudioInput* existing_audio_input = get_audio_device_by_name(audio_devices.audio_inputs, request_audio_input.name); + if(existing_audio_input) { + if(request_audio_input.description.empty()) + request_audio_input.description = "gsr-" + existing_audio_input->description; + match = true; } if(!match) { @@ -2294,8 +2310,8 @@ fprintf(stderr, " default_output (Default output)\n"); if(!audio_devices.default_input.empty()) fprintf(stderr, " default_input (Default input)\n"); - for(const auto &existing_audio_input : audio_devices.audio_inputs) { - fprintf(stderr, " %s (%s)\n", existing_audio_input.name.c_str(), existing_audio_input.description.c_str()); + for(const auto &audio_input : audio_devices.audio_inputs) { + fprintf(stderr, " %s (%s)\n", audio_input.name.c_str(), audio_input.description.c_str()); } _exit(2); } @@ -2600,6 +2616,13 @@ // If this is set to 1 then cuGraphicsGLRegisterImage will fail for egl context with error: invalid OpenGL or DirectX context, // so we overwrite it setenv("__GL_THREADED_OPTIMIZATIONS", "0", true); + // Forces low latency encoding mode. Use this environment variable until vaapi supports setting this as a parameter. + // The downside of this is that it always uses maximum power, which is not ideal for replay mode that runs on system startup. + // This option was added in mesa 24.1.4, released in july 17, 2024. + // TODO: Add an option to enable/disable this? + // Seems like the performance issue is not in encoding, but rendering the frame. + // Some frames end up taking 10 times longer. Seems to be an issue with amd gpu power management when letting the application sleep on the cpu side? + setenv("AMD_DEBUG", "lowlatencyenc", true); // Some people set this to nvidia (for nvdec) or vdpau (for nvidia vdpau), which breaks gpu screen recorder since // nvidia doesn't support vaapi and nvidia-vaapi-driver doesn't support encoding yet. // Let vaapi find the match vaapi driver instead of forcing a specific one. @@ -3400,7 +3423,7 @@ } double fps_start_time = clock_get_monotonic_seconds(); - double frame_timer_start = fps_start_time; + //double frame_timer_start = fps_start_time; int fps_counter = 0; int damage_fps_counter = 0; @@ -3638,7 +3661,7 @@ bool wait_until_frame_time_elapsed = false; while(running) { - //const double frame_start = clock_get_monotonic_seconds(); + const double frame_start = clock_get_monotonic_seconds(); while(gsr_egl_process_event(&egl)) { gsr_damage_on_event(&damage, gsr_egl_get_event_data(&egl)); @@ -3780,7 +3803,8 @@ save_replay_async(video_codec_context, VIDEO_STREAM_INDEX, audio_tracks, frame_data_queue, frames_erased, filename, container_format, file_extension, write_output_mutex, date_folders, hdr, capture); } - const double time_at_frame_end = clock_get_monotonic_seconds() - paused_time_offset; + const double frame_end = clock_get_monotonic_seconds(); + const double time_at_frame_end = frame_end - paused_time_offset; const double time_elapsed_total = time_at_frame_end - record_start_time; const int64_t frames_elapsed = (int64_t)(time_elapsed_total / target_fps); const double time_at_next_frame = (frames_elapsed + 1) * target_fps; @@ -3788,16 +3812,18 @@ if(time_to_next_frame > target_fps*1.1) time_to_next_frame = target_fps; - //const double frame_end = clock_get_monotonic_seconds(); - //const double frame_time = frame_end - frame_start; - if(time_to_next_frame > 0.0) + const double frame_time = frame_end - frame_start; + const bool frame_deadline_missed = frame_time > target_fps; + if(time_to_next_frame > 0.0 && !frame_deadline_missed && frame_captured) av_usleep(time_to_next_frame * 1000.0 * 1000.0); else { if(paused) - av_usleep(20.0 * 1000.0); // 10 milliseconds + av_usleep(20.0 * 1000.0); // 20 milliseconds + else if(frame_deadline_missed) + {} else if(framerate_mode == FramerateMode::CONTENT || !frame_captured) av_usleep(2.8 * 1000.0); // 2.8 milliseconds - else if(!damaged) + else if(!frame_captured) av_usleep(1.0 * 1000.0); // 1 milliseconds wait_until_frame_time_elapsed = true; }