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:
parent
d548d2fe18
commit
a629c0bfb3
2
TODO
2
TODO
@ -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.
|
||||||
|
31
src/main.cpp
31
src/main.cpp
@ -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
|
||||||
|
10
src/utils.c
10
src/utils.c
@ -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);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user