Make amd/intel nvidia/wayland capture display match x11 connector name, allow screen capture on amd/intel nvidia/wayland (select the first output for now)

This commit is contained in:
dec05eba 2023-11-17 10:09:51 +01:00
parent d548d2fe18
commit a629c0bfb3
3 changed files with 36 additions and 7 deletions

2
TODO
View File

@ -56,7 +56,7 @@ Intel is a bit weird with monitor capture and multiple monitors. If one of the m
Support vp8/vp9. This is especially important on amd which on some distros (such as Manjaro) where hardware accelerated h264/hevc is disabled in the mesa package. Support vp8/vp9. This is especially important on amd which on some distros (such as Manjaro) where hardware accelerated h264/hevc is disabled in the mesa package.
Support screen (all monitors) capture on amd/intel when no combined plane is found. Support screen (all monitors) capture on amd/intel and nvidia wayland when no combined plane is found. Right now screen just takes the first output.
Use separate plane (which has offset and pitch) from combined plane instead of the combined plane. Use separate plane (which has offset and pitch) from combined plane instead of the combined plane.
Both twitch and youtube support variable bitrate but twitch recommends constant bitrate to reduce stream buffering/dropped frames when going from low motion to high motion: https://help.twitch.tv/s/article/broadcasting-guidelines?language=en_US. Info for youtube: https://support.google.com/youtube/answer/2853702?hl=en#zippy=%2Cvariable-bitrate-with-custom-stream-keys-in-live-control-room%2Ck-p-fps%2Cp-fps. Both twitch and youtube support variable bitrate but twitch recommends constant bitrate to reduce stream buffering/dropped frames when going from low motion to high motion: https://help.twitch.tv/s/article/broadcasting-guidelines?language=en_US. Info for youtube: https://support.google.com/youtube/answer/2853702?hl=en#zippy=%2Cvariable-bitrate-with-custom-stream-keys-in-live-control-room%2Ck-p-fps%2Cp-fps.

View File

@ -52,6 +52,16 @@ static void monitor_output_callback_print(const gsr_monitor *monitor, void *user
fprintf(stderr, " \"%.*s\" (%dx%d+%d+%d)\n", monitor->name_len, monitor->name, monitor->size.x, monitor->size.y, monitor->pos.x, monitor->pos.y); fprintf(stderr, " \"%.*s\" (%dx%d+%d+%d)\n", monitor->name_len, monitor->name, monitor->size.x, monitor->size.y, monitor->pos.x, monitor->pos.y);
} }
typedef struct {
const char *output_name;
} FirstOutputCallback;
static void get_first_output(const gsr_monitor *monitor, void *userdata) {
FirstOutputCallback *first_output = (FirstOutputCallback*)userdata;
if(!first_output->output_name)
first_output->output_name = strndup(monitor->name, monitor->name_len + 1);
}
static char* av_error_to_string(int err) { static char* av_error_to_string(int err) {
if(av_strerror(err, av_error_buffer, sizeof(av_error_buffer)) < 0) if(av_strerror(err, av_error_buffer, sizeof(av_error_buffer)) < 0)
strcpy(av_error_buffer, "Unknown error"); strcpy(av_error_buffer, "Unknown error");
@ -1557,7 +1567,7 @@ int main(int argc, char **argv) {
} }
const char *screen_region = args["-s"].value(); const char *screen_region = args["-s"].value();
const char *window_str = args["-w"].value(); const char *window_str = strdup(args["-w"].value());
if(screen_region && strcmp(window_str, "focused") != 0) { if(screen_region && strcmp(window_str, "focused") != 0) {
fprintf(stderr, "Error: option -s is only available when using -w focused\n"); fprintf(stderr, "Error: option -s is only available when using -w focused\n");
@ -1593,10 +1603,27 @@ int main(int argc, char **argv) {
follow_focused = true; follow_focused = true;
} else if(contains_non_hex_number(window_str)) { } else if(contains_non_hex_number(window_str)) {
if(wayland || gpu_inf.vendor != GSR_GPU_VENDOR_NVIDIA) { if(wayland || gpu_inf.vendor != GSR_GPU_VENDOR_NVIDIA) {
if(strcmp(window_str, "screen") == 0) {
FirstOutputCallback first_output;
first_output.output_name = NULL;
if(gsr_egl_supports_wayland_capture(&egl)) {
for_each_active_monitor_output(&egl, GSR_CONNECTION_WAYLAND, get_first_output, &first_output);
} else {
for_each_active_monitor_output(card_path, GSR_CONNECTION_DRM, get_first_output, &first_output);
}
if(first_output.output_name) {
window_str = first_output.output_name;
} else {
fprintf(stderr, "Error: no available output found\n");
}
}
if(gsr_egl_supports_wayland_capture(&egl)) { if(gsr_egl_supports_wayland_capture(&egl)) {
gsr_monitor gmon; gsr_monitor gmon;
if(!get_monitor_by_name(&egl, GSR_CONNECTION_WAYLAND, window_str, &gmon)) { if(!get_monitor_by_name(&egl, GSR_CONNECTION_WAYLAND, window_str, &gmon)) {
fprintf(stderr, "gsr error: display \"%s\" not found, expected one of:\n", window_str); fprintf(stderr, "gsr error: display \"%s\" not found, expected one of:\n", window_str);
fprintf(stderr, " \"screen\"\n");
for_each_active_monitor_output(&egl, GSR_CONNECTION_WAYLAND, monitor_output_callback_print, NULL); for_each_active_monitor_output(&egl, GSR_CONNECTION_WAYLAND, monitor_output_callback_print, NULL);
_exit(1); _exit(1);
} }
@ -1604,6 +1631,7 @@ int main(int argc, char **argv) {
gsr_monitor gmon; gsr_monitor gmon;
if(!get_monitor_by_name(card_path, GSR_CONNECTION_DRM, window_str, &gmon)) { if(!get_monitor_by_name(card_path, GSR_CONNECTION_DRM, window_str, &gmon)) {
fprintf(stderr, "gsr error: display \"%s\" not found, expected one of:\n", window_str); fprintf(stderr, "gsr error: display \"%s\" not found, expected one of:\n", window_str);
fprintf(stderr, " \"screen\"\n");
for_each_active_monitor_output(card_path, GSR_CONNECTION_DRM, monitor_output_callback_print, NULL); for_each_active_monitor_output(card_path, GSR_CONNECTION_DRM, monitor_output_callback_print, NULL);
_exit(1); _exit(1);
} }
@ -2357,6 +2385,7 @@ int main(int argc, char **argv) {
//XCloseDisplay(dpy); //XCloseDisplay(dpy);
} }
free((void*)window_str);
free(empty_audio); free(empty_audio);
// We do an _exit here because cuda uses at_exit to do _something_ that causes the program to freeze, // We do an _exit here because cuda uses at_exit to do _something_ that causes the program to freeze,
// but only on some nvidia driver versions on some gpus (RTX?), and _exit exits the program without calling // but only on some nvidia driver versions on some gpus (RTX?), and _exit exits the program without calling

View File

@ -137,17 +137,17 @@ static void for_each_active_monitor_output_drm(const char *drm_card_path, active
if(!connector) if(!connector)
continue; continue;
if(connector->connection != DRM_MODE_CONNECTED) {
drmModeFreeConnector(connector);
continue;
}
drm_connector_type_count *connector_type = drm_connector_types_get_index(type_counts, &num_type_counts, connector->connector_type); drm_connector_type_count *connector_type = drm_connector_types_get_index(type_counts, &num_type_counts, connector->connector_type);
const char *connection_name = drmModeGetConnectorTypeName(connector->connector_type); const char *connection_name = drmModeGetConnectorTypeName(connector->connector_type);
const int connection_name_len = strlen(connection_name); const int connection_name_len = strlen(connection_name);
if(connector_type) if(connector_type)
++connector_type->count; ++connector_type->count;
if(connector->connection != DRM_MODE_CONNECTED) {
drmModeFreeConnector(connector);
continue;
}
uint64_t crtc_id = 0; uint64_t crtc_id = 0;
connector_get_property_by_name(fd, connector, "CRTC_ID", &crtc_id); connector_get_property_by_name(fd, connector, "CRTC_ID", &crtc_id);