Compare commits

...

8 Commits
4.2.0 ... 4.2.3

Author SHA1 Message Date
dec05eba
10165977f6 4.2.3 2024-10-19 00:48:53 +02:00
dec05eba
62509a4b60 nixos fix: look for gsr-kms-server in PATH if not found in same directory as gpu-screen-recorder 2024-10-19 00:48:04 +02:00
dec05eba
eb602b9b53 4.2.2: AMD IS SHIT 2024-10-16 01:07:58 +02:00
dec05eba
19d77b8a96 Enable low latency encoding mode on amd (only available on amd since mesa version mesa 24.1.4) 2024-10-16 00:35:18 +02:00
dec05eba
601219febb README kdenlive 2024-10-14 14:22:37 +02:00
dec05eba
3e199f241a 4.2.1 2024-10-12 12:20:23 +02:00
dec05eba
a5895b775d appendum 2024-10-12 11:58:56 +02:00
dec05eba
2c4b077f43 Better frametimes when recording is too slow 2024-10-12 11:49:31 +02:00
6 changed files with 82 additions and 22 deletions

View File

@@ -168,4 +168,6 @@ Try recording to an SSD and make sure it's not using NTFS file system. Also reco
## 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.
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).

11
TODO
View File

@@ -156,9 +156,6 @@ Restart replay/update video resolution if monitor resolution changes.
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 @@ Support recording while in replay mode. This will be needed when enabling replay
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).
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.

View File

@@ -183,6 +183,40 @@ static void file_get_directory(char *filepath) {
*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 @@ int gsr_kms_client_init(gsr_kms_client *self, const char *card_path) {
}
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);

View File

@@ -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.3', default_options : ['warning_level=2'])
add_project_arguments('-Wshadow', language : ['c', 'cpp'])
if get_option('buildtype') == 'debug'

View File

@@ -1,7 +1,7 @@
[package]
name = "gpu-screen-recorder"
type = "executable"
version = "4.2.0"
version = "4.2.3"
platforms = ["posix"]
[config]

View File

@@ -810,10 +810,9 @@ static void open_video_software(AVCodecContext *codec_context, VideoQuality vide
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 @@ static void open_video_hardware(AVCodecContext *codec_context, VideoQuality vide
// TODO: Enable multipass
if(vendor == GSR_GPU_VENDOR_NVIDIA) {
// TODO: Test these, if they are needed, if they should be used
// 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 @@ static void usage_full() {
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 @@ static void usage_full() {
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 @@ static void usage_full() {
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");
@@ -2600,6 +2608,13 @@ int main(int argc, char **argv) {
// 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 +3415,7 @@ int main(int argc, char **argv) {
}
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 +3653,7 @@ int main(int argc, char **argv) {
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 +3795,8 @@ int main(int argc, char **argv) {
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 +3804,18 @@ int main(int argc, char **argv) {
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;
}