mirror of
https://repo.dec05eba.com/gpu-screen-recorder
synced 2026-03-31 09:07:13 +09:00
Add --list-monitors option to list only monitors, refactor
This commit is contained in:
@@ -14,13 +14,17 @@ gpu-screen-recorder \- The fastest screen recording tool for Linux
|
|||||||
|
|
|
|
||||||
.B \-\-version
|
.B \-\-version
|
||||||
|
|
|
|
||||||
|
.B \-\-info
|
||||||
|
|
|
||||||
.B \-\-list\-capture\-options
|
.B \-\-list\-capture\-options
|
||||||
|
|
|
|
||||||
|
.B \-\-list\-monitors
|
||||||
|
|
|
||||||
|
.B \-\-list\-v4l2\-devices
|
||||||
|
|
|
||||||
.B \-\-list\-audio\-devices
|
.B \-\-list\-audio\-devices
|
||||||
|
|
|
|
||||||
.B \-\-list\-application\-audio
|
.B \-\-list\-application\-audio
|
||||||
|
|
|
||||||
.B \-\-info
|
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
.B gpu-screen-recorder
|
.B gpu-screen-recorder
|
||||||
is the fastest screen recording tool for Linux. It uses the GPU
|
is the fastest screen recording tool for Linux. It uses the GPU
|
||||||
@@ -92,10 +96,6 @@ Run
|
|||||||
.B \-\-list\-capture\-options
|
.B \-\-list\-capture\-options
|
||||||
to list available capture sources.
|
to list available capture sources.
|
||||||
.PP
|
.PP
|
||||||
Run
|
|
||||||
.B \-\-list\-v4l2\-devices
|
|
||||||
to list available camera devices (V4L2).
|
|
||||||
.PP
|
|
||||||
Additional options can be passed to each capture source by splitting capture source with
|
Additional options can be passed to each capture source by splitting capture source with
|
||||||
.B ;
|
.B ;
|
||||||
for example
|
for example
|
||||||
@@ -403,6 +403,9 @@ Show system info (codecs, capture options).
|
|||||||
.B \-\-list\-capture\-options
|
.B \-\-list\-capture\-options
|
||||||
List available capture sources (window, monitors, portal, v4l2 device path).
|
List available capture sources (window, monitors, portal, v4l2 device path).
|
||||||
.TP
|
.TP
|
||||||
|
.B \-\-list\-monitors
|
||||||
|
List available monitors.
|
||||||
|
.TP
|
||||||
.B \-\-list\-v4l2\-devices
|
.B \-\-list\-v4l2\-devices
|
||||||
List available cameras devices (V4L2).
|
List available cameras devices (V4L2).
|
||||||
.TP
|
.TP
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ typedef struct {
|
|||||||
void (*list_application_audio)(void *userdata);
|
void (*list_application_audio)(void *userdata);
|
||||||
void (*list_v4l2_devices)(void *userdata);
|
void (*list_v4l2_devices)(void *userdata);
|
||||||
void (*list_capture_options)(const char *card_path, void *userdata);
|
void (*list_capture_options)(const char *card_path, void *userdata);
|
||||||
|
void (*list_monitors)(void *userdata);
|
||||||
} args_handlers;
|
} args_handlers;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|||||||
@@ -196,7 +196,8 @@ static void usage_header(void) {
|
|||||||
"[-bm auto|qp|vbr|cbr] [-cr limited|full] [-tune performance|quality] [-df yes|no] [-sc <script_path>] [-p <plugin_path>] "
|
"[-bm auto|qp|vbr|cbr] [-cr limited|full] [-tune performance|quality] [-df yes|no] [-sc <script_path>] [-p <plugin_path>] "
|
||||||
"[-cursor yes|no] [-keyint <value>] [-restore-portal-session yes|no] [-portal-session-token-filepath filepath] [-encoder gpu|cpu] "
|
"[-cursor yes|no] [-keyint <value>] [-restore-portal-session yes|no] [-portal-session-token-filepath filepath] [-encoder gpu|cpu] "
|
||||||
"[-fallback-cpu-encoding yes|no] [-o <output_file>] [-ro <output_directory>] [-ffmpeg-opts <options>] [--list-capture-options [card_path]] "
|
"[-fallback-cpu-encoding yes|no] [-o <output_file>] [-ro <output_directory>] [-ffmpeg-opts <options>] [--list-capture-options [card_path]] "
|
||||||
"[--list-audio-devices] [--list-application-audio] [--list-v4l2-devices] [-write-first-frame-ts yes|no] [-low-power yes|no] [-v yes|no] [-gl-debug yes|no] [--version] [-h|--help]\n", program_name);
|
"[--list-monitors] [--list-audio-devices] [--list-application-audio] [--list-v4l2-devices] [-write-first-frame-ts yes|no] [-low-power yes|no] "
|
||||||
|
"[-v yes|no] [-gl-debug yes|no] [--version] [-h|--help]\n", program_name);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -500,6 +501,11 @@ bool args_parser_parse(args_parser *self, int argc, char **argv, const args_hand
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(strcmp(argv[1], "--list-monitors") == 0) {
|
||||||
|
arg_handlers->list_monitors(userdata);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if(argc == 2 && strcmp(argv[1], "--version") == 0) {
|
if(argc == 2 && strcmp(argv[1], "--version") == 0) {
|
||||||
arg_handlers->version(userdata);
|
arg_handlers->version(userdata);
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
153
src/main.cpp
153
src/main.cpp
@@ -1888,23 +1888,31 @@ static void camera_query_callback(const char *path, const gsr_capture_v4l2_suppo
|
|||||||
printf("%s|%ux%u@%uhz|%s\n", path, setup->resolution.width, setup->resolution.height, gsr_capture_v4l2_framerate_to_number(setup->framerate), gsr_capture_v4l2_pixfmt_to_string(setup->pixfmt));
|
printf("%s|%ux%u@%uhz|%s\n", path, setup->resolution.width, setup->resolution.height, gsr_capture_v4l2_framerate_to_number(setup->framerate), gsr_capture_v4l2_pixfmt_to_string(setup->pixfmt));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void list_supported_capture_options(const gsr_window *window, const char *card_path, bool list_monitors) {
|
// Returns the number of monitors found
|
||||||
|
static int list_monitors(const gsr_window *window, const char *card_path) {
|
||||||
|
capture_options_callback options;
|
||||||
|
options.window = window;
|
||||||
|
options.num_monitors = 0;
|
||||||
|
|
||||||
|
const bool is_x11 = gsr_window_get_display_server(window) == GSR_DISPLAY_SERVER_X11;
|
||||||
|
const gsr_connection_type connection_type = is_x11 ? GSR_CONNECTION_X11 : GSR_CONNECTION_DRM;
|
||||||
|
for_each_active_monitor_output(window, card_path, connection_type, output_monitor_info, &options);
|
||||||
|
|
||||||
|
return options.num_monitors;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void list_supported_capture_options(const gsr_window *window, const char *card_path, bool do_list_monitors) {
|
||||||
const bool wayland = gsr_window_get_display_server(window) == GSR_DISPLAY_SERVER_WAYLAND;
|
const bool wayland = gsr_window_get_display_server(window) == GSR_DISPLAY_SERVER_WAYLAND;
|
||||||
if(!wayland) {
|
if(!wayland) {
|
||||||
puts("window");
|
puts("window");
|
||||||
puts("focused");
|
puts("focused");
|
||||||
}
|
}
|
||||||
|
|
||||||
capture_options_callback options;
|
int num_monitors = 0;
|
||||||
options.window = window;
|
if(do_list_monitors)
|
||||||
options.num_monitors = 0;
|
num_monitors = list_monitors(window, card_path);
|
||||||
if(list_monitors) {
|
|
||||||
const bool is_x11 = gsr_window_get_display_server(window) == GSR_DISPLAY_SERVER_X11;
|
|
||||||
const gsr_connection_type connection_type = is_x11 ? GSR_CONNECTION_X11 : GSR_CONNECTION_DRM;
|
|
||||||
for_each_active_monitor_output(window, card_path, connection_type, output_monitor_info, &options);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(options.num_monitors > 0)
|
if(num_monitors > 0)
|
||||||
puts("region");
|
puts("region");
|
||||||
|
|
||||||
gsr_capture_v4l2_list_devices(camera_query_callback, NULL);
|
gsr_capture_v4l2_list_devices(camera_query_callback, NULL);
|
||||||
@@ -1933,11 +1941,20 @@ static void version_command(void *userdata) {
|
|||||||
_exit(0);
|
_exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void info_command(void *userdata) {
|
struct WindowingSetup {
|
||||||
(void)userdata;
|
Display *dpy;
|
||||||
|
gsr_window *window;
|
||||||
|
gsr_egl egl;
|
||||||
|
bool list_monitors;
|
||||||
|
};
|
||||||
|
|
||||||
|
static WindowingSetup setup_windowing(bool setup_egl) {
|
||||||
|
WindowingSetup setup;
|
||||||
|
memset(&setup, 0, sizeof(setup));
|
||||||
|
|
||||||
bool wayland = false;
|
bool wayland = false;
|
||||||
Display *dpy = XOpenDisplay(nullptr);
|
setup.dpy = XOpenDisplay(nullptr);
|
||||||
if (!dpy) {
|
if (!setup.dpy) {
|
||||||
wayland = true;
|
wayland = true;
|
||||||
fprintf(stderr, "gsr warning: failed to connect to the X server. Assuming wayland is running without Xwayland\n");
|
fprintf(stderr, "gsr warning: failed to connect to the X server. Assuming wayland is running without Xwayland\n");
|
||||||
}
|
}
|
||||||
@@ -1946,7 +1963,7 @@ static void info_command(void *userdata) {
|
|||||||
XSetIOErrorHandler(x11_io_error_handler);
|
XSetIOErrorHandler(x11_io_error_handler);
|
||||||
|
|
||||||
if(!wayland)
|
if(!wayland)
|
||||||
wayland = is_xwayland(dpy);
|
wayland = is_xwayland(setup.dpy);
|
||||||
|
|
||||||
if(!wayland && is_using_prime_run()) {
|
if(!wayland && is_using_prime_run()) {
|
||||||
// Disable prime-run and similar options as it doesn't work, the monitor to capture has to be run on the same device.
|
// Disable prime-run and similar options as it doesn't work, the monitor to capture has to be run on the same device.
|
||||||
@@ -1956,46 +1973,56 @@ static void info_command(void *userdata) {
|
|||||||
disable_prime_run();
|
disable_prime_run();
|
||||||
}
|
}
|
||||||
|
|
||||||
gsr_window *window = gsr_window_create(dpy, wayland);
|
setup.window = gsr_window_create(setup.dpy, wayland);
|
||||||
if(!window) {
|
if(!setup.window) {
|
||||||
fprintf(stderr, "gsr error: failed to create window\n");
|
fprintf(stderr, "gsr error: failed to create window\n");
|
||||||
_exit(1);
|
_exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
gsr_egl egl;
|
setup.list_monitors = true;
|
||||||
if(!gsr_egl_load(&egl, window, false, false)) {
|
|
||||||
fprintf(stderr, "gsr error: failed to load opengl\n");
|
|
||||||
_exit(22);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool list_monitors = true;
|
if(setup_egl) {
|
||||||
egl.card_path[0] = '\0';
|
if(!gsr_egl_load(&setup.egl, setup.window, false, false)) {
|
||||||
if(monitor_capture_use_drm(window, egl.gpu_info.vendor)) {
|
fprintf(stderr, "gsr error: failed to load opengl\n");
|
||||||
// TODO: Allow specifying another card, and in other places
|
_exit(22);
|
||||||
if(!gsr_get_valid_card_path(&egl, egl.card_path, true)) {
|
}
|
||||||
fprintf(stderr, "gsr error: no /dev/dri/cardX device found. Make sure that you have at least one monitor connected\n");
|
|
||||||
list_monitors = false;
|
setup.egl.card_path[0] = '\0';
|
||||||
|
if(monitor_capture_use_drm(setup.window, setup.egl.gpu_info.vendor)) {
|
||||||
|
// TODO: Allow specifying another card, and in other places
|
||||||
|
if(!gsr_get_valid_card_path(&setup.egl, setup.egl.card_path, true)) {
|
||||||
|
fprintf(stderr, "gsr error: no /dev/dri/cardX device found. Make sure that you have at least one monitor connected\n");
|
||||||
|
setup.list_monitors = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return setup;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void info_command(void *userdata) {
|
||||||
|
(void)userdata;
|
||||||
|
WindowingSetup windowing_setup = setup_windowing(true);
|
||||||
|
const bool wayland = gsr_window_get_display_server(windowing_setup.window) == GSR_DISPLAY_SERVER_WAYLAND;
|
||||||
|
|
||||||
av_log_set_level(AV_LOG_FATAL);
|
av_log_set_level(AV_LOG_FATAL);
|
||||||
|
|
||||||
puts("section=system_info");
|
puts("section=system_info");
|
||||||
list_system_info(wayland);
|
list_system_info(wayland);
|
||||||
if(egl.gpu_info.is_steam_deck)
|
if(windowing_setup.egl.gpu_info.is_steam_deck)
|
||||||
puts("is_steam_deck|yes");
|
puts("is_steam_deck|yes");
|
||||||
else
|
else
|
||||||
puts("is_steam_deck|no");
|
puts("is_steam_deck|no");
|
||||||
printf("gsr_version|%s\n", GSR_VERSION);
|
printf("gsr_version|%s\n", GSR_VERSION);
|
||||||
puts("section=gpu_info");
|
puts("section=gpu_info");
|
||||||
list_gpu_info(&egl);
|
list_gpu_info(&windowing_setup.egl);
|
||||||
puts("section=video_codecs");
|
puts("section=video_codecs");
|
||||||
list_supported_video_codecs(&egl, wayland);
|
list_supported_video_codecs(&windowing_setup.egl, wayland);
|
||||||
puts("section=image_formats");
|
puts("section=image_formats");
|
||||||
puts("jpeg");
|
puts("jpeg");
|
||||||
puts("png");
|
puts("png");
|
||||||
puts("section=capture_options");
|
puts("section=capture_options");
|
||||||
list_supported_capture_options(window, egl.card_path, list_monitors);
|
list_supported_capture_options(windowing_setup.window, windowing_setup.egl.card_path, windowing_setup.list_monitors);
|
||||||
|
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
|
|
||||||
@@ -2058,53 +2085,30 @@ static void list_v4l2_devices(void *userdata) {
|
|||||||
// |card_path| can be NULL. If not NULL then |vendor| has to be valid
|
// |card_path| can be NULL. If not NULL then |vendor| has to be valid
|
||||||
static void list_capture_options_command(const char *card_path, void *userdata) {
|
static void list_capture_options_command(const char *card_path, void *userdata) {
|
||||||
(void)userdata;
|
(void)userdata;
|
||||||
bool wayland = false;
|
WindowingSetup windowing_setup = setup_windowing(card_path != nullptr);
|
||||||
Display *dpy = XOpenDisplay(nullptr);
|
|
||||||
if (!dpy) {
|
|
||||||
wayland = true;
|
|
||||||
fprintf(stderr, "gsr warning: failed to connect to the X server. Assuming wayland is running without Xwayland\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
XSetErrorHandler(x11_error_handler);
|
if(card_path)
|
||||||
XSetIOErrorHandler(x11_io_error_handler);
|
list_supported_capture_options(windowing_setup.window, card_path, true);
|
||||||
|
else
|
||||||
|
list_supported_capture_options(windowing_setup.window, windowing_setup.egl.card_path, windowing_setup.list_monitors);
|
||||||
|
|
||||||
if(!wayland)
|
fflush(stdout);
|
||||||
wayland = is_xwayland(dpy);
|
|
||||||
|
|
||||||
if(!wayland && is_using_prime_run()) {
|
// Not needed as this will just slow down shutdown
|
||||||
// Disable prime-run and similar options as it doesn't work, the monitor to capture has to be run on the same device.
|
//gsr_egl_unload(&egl);
|
||||||
// This is fine on wayland since nvidia uses drm interface there and the monitor query checks the monitors connected
|
//gsr_window_destroy(&window);
|
||||||
// to the drm device.
|
//if(dpy)
|
||||||
fprintf(stderr, "gsr warning: use of prime-run on X11 is not supported. Disabling prime-run\n");
|
// XCloseDisplay(dpy);
|
||||||
disable_prime_run();
|
|
||||||
}
|
|
||||||
|
|
||||||
gsr_window *window = gsr_window_create(dpy, wayland);
|
_exit(0);
|
||||||
if(!window) {
|
}
|
||||||
fprintf(stderr, "gsr error: failed to create window\n");
|
|
||||||
_exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(card_path) {
|
static void list_monitors_command(void *userdata) {
|
||||||
list_supported_capture_options(window, card_path, true);
|
(void)userdata;
|
||||||
} else {
|
WindowingSetup windowing_setup = setup_windowing(true);
|
||||||
gsr_egl egl;
|
|
||||||
if(!gsr_egl_load(&egl, window, false, false)) {
|
|
||||||
fprintf(stderr, "gsr error: failed to load opengl\n");
|
|
||||||
_exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool list_monitors = true;
|
if(windowing_setup.list_monitors)
|
||||||
egl.card_path[0] = '\0';
|
list_monitors(windowing_setup.window, windowing_setup.egl.card_path);
|
||||||
if(monitor_capture_use_drm(window, egl.gpu_info.vendor)) {
|
|
||||||
// TODO: Allow specifying another card, and in other places
|
|
||||||
if(!gsr_get_valid_card_path(&egl, egl.card_path, true)) {
|
|
||||||
fprintf(stderr, "gsr error: no /dev/dri/cardX device found. Make sure that you have at least one monitor connected\n");
|
|
||||||
list_monitors = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
list_supported_capture_options(window, egl.card_path, list_monitors);
|
|
||||||
}
|
|
||||||
|
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
|
|
||||||
@@ -3682,6 +3686,7 @@ int main(int argc, char **argv) {
|
|||||||
arg_handlers.list_application_audio = list_application_audio_command;
|
arg_handlers.list_application_audio = list_application_audio_command;
|
||||||
arg_handlers.list_v4l2_devices = list_v4l2_devices;
|
arg_handlers.list_v4l2_devices = list_v4l2_devices;
|
||||||
arg_handlers.list_capture_options = list_capture_options_command;
|
arg_handlers.list_capture_options = list_capture_options_command;
|
||||||
|
arg_handlers.list_monitors = list_monitors_command;
|
||||||
|
|
||||||
args_parser arg_parser;
|
args_parser arg_parser;
|
||||||
if(!args_parser_parse(&arg_parser, argc, argv, &arg_handlers, NULL))
|
if(!args_parser_parse(&arg_parser, argc, argv, &arg_handlers, NULL))
|
||||||
|
|||||||
Reference in New Issue
Block a user