Compare commits

...

7 Commits
5.2.1 ... 5.2.3

Author SHA1 Message Date
dec05eba
f23308444a 5.2.3 2025-03-07 20:24:13 +01:00
dec05eba
fadf9b64de Test fix 2: crtc map update 2025-03-07 19:44:08 +01:00
dec05eba
e6f1d47eef Test fix for monitor changing after power off/on 2025-03-07 19:29:19 +01:00
dec05eba
7af4f106e7 Example scripts: use cbr for replay scripts 2025-03-07 02:47:20 +01:00
dec05eba
a26aa2dd3e 5.2.2 2025-03-05 21:24:37 +01:00
dec05eba
8364aaadad Fix pipewire server breaking when pipewire connection is closed too quickly (--info) 2025-03-05 21:20:51 +01:00
dec05eba
5f3a14d3f6 Rename window_wayland to wayland and window_x11 to x11 2025-03-05 18:07:52 +01:00
15 changed files with 58 additions and 55 deletions

4
TODO
View File

@@ -241,4 +241,6 @@ Support reconnecting (and setting things up again) if the audio server is restar
Find out how nvidia-smi fixes nvenc not working on opensuse and do that ourselves instead of relying on nvidia-smi that is not always installed.
Pulseaudio code: add "running" variable to loops to allow stopping the running code when quitting.
Pulseaudio code: add "running" variable to loops to allow stopping the running code when quitting.
Scale screenshot frame libswscale or implement lanczos shader for improved scaline for video as well.

View File

@@ -80,6 +80,7 @@ typedef struct {
struct pw_proxy *metadata_proxy;
struct spa_hook metadata_listener;
struct spa_hook metadata_proxy_listener;
char default_output_device_name[128];
char default_input_device_name[128];

View File

@@ -25,7 +25,6 @@
typedef struct {
int drmfd;
drmModePlaneResPtr planes;
} gsr_drm;
typedef struct {
@@ -289,21 +288,31 @@ static int drm_prime_handles_to_fds(gsr_drm *drm, drmModeFB2Ptr drmfb, int *fb_f
return GSR_KMS_MAX_DMA_BUFS;
}
static int kms_get_fb(gsr_drm *drm, gsr_kms_response *response, connector_to_crtc_map *c2crtc_map) {
static int kms_get_fb(gsr_drm *drm, gsr_kms_response *response) {
int result = -1;
response->result = KMS_RESULT_OK;
response->err_msg[0] = '\0';
response->num_items = 0;
for(uint32_t i = 0; i < drm->planes->count_planes && response->num_items < GSR_KMS_MAX_ITEMS; ++i) {
connector_to_crtc_map c2crtc_map;
c2crtc_map.num_maps = 0;
map_crtc_to_connector_ids(drm, &c2crtc_map);
drmModePlaneResPtr planes = drmModeGetPlaneResources(drm->drmfd);
if(!planes) {
fprintf(stderr, "kms server error: failed to get plane resources, error: %s\n", strerror(errno));
goto done;
}
for(uint32_t i = 0; i < planes->count_planes && response->num_items < GSR_KMS_MAX_ITEMS; ++i) {
drmModePlanePtr plane = NULL;
drmModeFB2Ptr drmfb = NULL;
plane = drmModeGetPlane(drm->drmfd, drm->planes->planes[i]);
plane = drmModeGetPlane(drm->drmfd, planes->planes[i]);
if(!plane) {
response->result = KMS_RESULT_FAILED_TO_GET_PLANE;
snprintf(response->err_msg, sizeof(response->err_msg), "failed to get drm plane with id %u, error: %s\n", drm->planes->planes[i], strerror(errno));
snprintf(response->err_msg, sizeof(response->err_msg), "failed to get drm plane with id %u, error: %s\n", planes->planes[i], strerror(errno));
fprintf(stderr, "kms server error: %s\n", response->err_msg);
goto next;
}
@@ -346,7 +355,7 @@ static int kms_get_fb(gsr_drm *drm, gsr_kms_response *response, connector_to_crt
const int item_index = response->num_items;
const connector_crtc_pair *crtc_pair = get_connector_pair_by_crtc_id(c2crtc_map, plane->crtc_id);
const connector_crtc_pair *crtc_pair = get_connector_pair_by_crtc_id(&c2crtc_map, plane->crtc_id);
if(crtc_pair && crtc_pair->hdr_metadata_blob_id) {
response->items[item_index].has_hdr_metadata = get_hdr_metadata(drm->drmfd, crtc_pair->hdr_metadata_blob_id, &response->items[item_index].hdr_metadata);
} else {
@@ -389,6 +398,11 @@ static int kms_get_fb(gsr_drm *drm, gsr_kms_response *response, connector_to_crt
drmModeFreePlane(plane);
}
done:
if(planes)
drmModeFreePlaneResources(planes);
if(response->num_items > 0)
response->result = KMS_RESULT_OK;
@@ -499,7 +513,6 @@ int main(int argc, char **argv) {
int socket_fd = 0;
gsr_drm drm;
drm.drmfd = 0;
drm.planes = NULL;
if(argc != 3) {
fprintf(stderr, "usage: gsr-kms-server <domain_socket_path> <card_path>\n");
@@ -532,17 +545,6 @@ int main(int argc, char **argv) {
fprintf(stderr, "kms server warning: drmSetClientCap DRM_CLIENT_CAP_ATOMIC failed, error: %s. The wrong monitor may be captured as a result\n", strerror(errno));
}
drm.planes = drmModeGetPlaneResources(drm.drmfd);
if(!drm.planes) {
fprintf(stderr, "kms server error: failed to get plane resources, error: %s\n", strerror(errno));
res = 2;
goto done;
}
connector_to_crtc_map c2crtc_map;
c2crtc_map.num_maps = 0;
map_crtc_to_connector_ids(&drm, &c2crtc_map);
fprintf(stderr, "kms server info: connecting to the client\n");
bool connected = false;
const double connect_timeout_sec = 5.0;
@@ -642,7 +644,7 @@ int main(int argc, char **argv) {
response.version = GSR_KMS_PROTOCOL_VERSION;
response.num_items = 0;
if(kms_get_fb(&drm, &response, &c2crtc_map) == 0) {
if(kms_get_fb(&drm, &response) == 0) {
if(send_msg_to_client(socket_fd, &response) == -1)
fprintf(stderr, "kms server error: failed to respond to client KMS_REQUEST_TYPE_GET_KMS request\n");
} else {
@@ -681,8 +683,6 @@ int main(int argc, char **argv) {
}
done:
if(drm.planes)
drmModeFreePlaneResources(drm.planes);
if(drm.drmfd > 0)
close(drm.drmfd);
if(socket_fd > 0)

View File

@@ -1,4 +1,4 @@
project('gpu-screen-recorder', ['c', 'cpp'], version : '5.2.1', default_options : ['warning_level=2'])
project('gpu-screen-recorder', ['c', 'cpp'], version : '5.2.3', default_options : ['warning_level=2'])
add_project_arguments('-Wshadow', language : ['c', 'cpp'])
if get_option('buildtype') == 'debug'
@@ -22,8 +22,8 @@ src = [
'src/codec_query/vaapi.c',
'src/codec_query/vulkan.c',
'src/window/window.c',
'src/window/window_x11.c',
'src/window/window_wayland.c',
'src/window/x11.c',
'src/window/wayland.c',
'src/egl.c',
'src/cuda.c',
'src/xnvctrl.c',

View File

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

View File

@@ -3,4 +3,4 @@
window=$(xdotool selectwindow)
window_name=$(xdotool getwindowname "$window" || xdotool getwindowclassname "$window" || echo "Game")
window_name="$(echo "$window_name" | tr '/\\' '_')"
gpu-screen-recorder -w "$window" -f 60 -c mkv -a default_output -r 60 -o "$HOME/Videos/Replays/$window_name"
gpu-screen-recorder -w "$window" -f 60 -c mkv -a default_output -bm cbr -q 45000 -r 60 -o "$HOME/Videos/Replays/$window_name"

View File

@@ -3,4 +3,4 @@
pidof -q gpu-screen-recorder && exit 0
video_path="$HOME/Videos"
mkdir -p "$video_path"
gpu-screen-recorder -w screen -f 60 -a default_output -c mkv -r 30 -o "$video_path"
gpu-screen-recorder -w screen -f 60 -a default_output -c mkv -bm cbr -q 45000 -r 30 -o "$video_path"

View File

@@ -16,8 +16,8 @@ extern "C" {
#include "../include/codec_query/nvenc.h"
#include "../include/codec_query/vaapi.h"
#include "../include/codec_query/vulkan.h"
#include "../include/window/window_x11.h"
#include "../include/window/window_wayland.h"
#include "../include/window/x11.h"
#include "../include/window/wayland.h"
#include "../include/egl.h"
#include "../include/utils.h"
#include "../include/damage.h"

View File

@@ -329,22 +329,20 @@ static const struct pw_metadata_events metadata_events = {
static void on_metadata_proxy_removed_cb(void *data) {
gsr_pipewire_audio *self = data;
if(self->metadata_proxy) {
// TODO:
//pw_proxy_destroy(self->metadata_proxy);
//self->metadata_proxy = NULL;
pw_proxy_destroy(self->metadata_proxy);
self->metadata_proxy = NULL;
}
}
static void on_metadata_proxy_destroy_cb(void *data) {
gsr_pipewire_audio *self = data;
// TODO:
//spa_hook_remove(&metadata->metadata_listener);
//spa_hook_remove(&metadata->proxy_listener);
//spa_zero(metadata->metadata_listener);
//spa_zero(metadata->proxy_listener);
spa_hook_remove(&self->metadata_listener);
spa_hook_remove(&self->metadata_proxy_listener);
spa_zero(self->metadata_listener);
spa_zero(self->metadata_proxy_listener);
//self->metadata_proxy = NULL;
self->metadata_proxy = NULL;
}
static const struct pw_proxy_events metadata_proxy_events = {
@@ -365,11 +363,8 @@ static bool gsr_pipewire_audio_listen_on_metadata(gsr_pipewire_audio *self, uint
return false;
}
// TODO:
pw_metadata_add_listener((struct pw_metadata*)self->metadata_proxy, &self->metadata_listener, &metadata_events, self);
//struct spa_hook proxy_listener;
//pw_proxy_add_listener(self->metadata_proxy, &proxy_listener, &metadata_proxy_events, self);
pw_proxy_add_object_listener(self->metadata_proxy, &self->metadata_listener, &metadata_events, self);
pw_proxy_add_listener(self->metadata_proxy, &self->metadata_proxy_listener, &metadata_proxy_events, self);
return true;
}
@@ -549,15 +544,14 @@ bool gsr_pipewire_audio_init(gsr_pipewire_audio *self) {
pw_context_load_module(self->context, "libpipewire-module-link-factory", NULL, NULL);
pw_thread_loop_lock(self->thread_loop);
if(pw_thread_loop_start(self->thread_loop) < 0) {
fprintf(stderr, "gsr error: gsr_pipewire_audio_init: failed to start thread\n");
pw_thread_loop_unlock(self->thread_loop);
gsr_pipewire_audio_deinit(self);
return false;
}
pw_thread_loop_lock(self->thread_loop);
self->core = pw_context_connect(self->context, pw_properties_new(PW_KEY_REMOTE_NAME, NULL, NULL), 0);
if(!self->core) {
pw_thread_loop_unlock(self->thread_loop);
@@ -568,11 +562,12 @@ bool gsr_pipewire_audio_init(gsr_pipewire_audio *self) {
// TODO: Error check
pw_core_add_listener(self->core, &self->core_listener, &core_events, self);
self->server_version_sync = pw_core_sync(self->core, PW_ID_CORE, 0);
pw_thread_loop_wait(self->thread_loop);
self->registry = pw_core_get_registry(self->core, PW_VERSION_REGISTRY, 0);
pw_registry_add_listener(self->registry, &self->registry_listener, &registry_events, self);
self->server_version_sync = pw_core_sync(self->core, PW_ID_CORE, 0);
pw_thread_loop_wait(self->thread_loop);
pw_thread_loop_unlock(self->thread_loop);
return true;
}
@@ -592,7 +587,11 @@ void gsr_pipewire_audio_deinit(gsr_pipewire_audio *self) {
self->num_virtual_sink_proxies = 0;
if(self->metadata_proxy) {
spa_hook_remove(&self->metadata_listener);
spa_hook_remove(&self->metadata_proxy_listener);
pw_proxy_destroy(self->metadata_proxy);
spa_zero(self->metadata_listener);
spa_zero(self->metadata_proxy_listener);
self->metadata_proxy = NULL;
}

View File

@@ -413,6 +413,7 @@ static void renegotiate_format(void *data, uint64_t expirations) {
uint8_t params_buffer[4096];
struct spa_pod_builder pod_builder = SPA_POD_BUILDER_INIT(params_buffer, sizeof(params_buffer));
if (!gsr_pipewire_video_build_format_params(self, &pod_builder, params, &num_video_formats)) {
fprintf(stderr, "gsr error: renegotiate_format: failed to build formats\n");
pw_thread_loop_unlock(self->thread_loop);
return;
}
@@ -509,6 +510,9 @@ static bool gsr_pipewire_video_setup_stream(gsr_pipewire_video *self) {
// TODO: Error check
pw_core_add_listener(self->core, &self->core_listener, &core_events, self);
self->server_version_sync = pw_core_sync(self->core, PW_ID_CORE, 0);
pw_thread_loop_wait(self->thread_loop);
gsr_pipewire_video_init_modifiers(self);
// TODO: Cleanup?
@@ -519,9 +523,6 @@ static bool gsr_pipewire_video_setup_stream(gsr_pipewire_video *self) {
goto error;
}
self->server_version_sync = pw_core_sync(self->core, PW_ID_CORE, 0);
pw_thread_loop_wait(self->thread_loop);
self->stream = pw_stream_new(self->core, "com.dec05eba.gpu_screen_recorder",
pw_properties_new(PW_KEY_MEDIA_TYPE, "Video",
PW_KEY_MEDIA_CATEGORY, "Capture",

View File

@@ -124,7 +124,7 @@ static void subscribe_update_default_devices(pa_context*, const pa_server_info *
static void subscribe_cb(pa_context *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata) {
(void)idx;
pa_handle *handle = (pa_handle*)userdata;
if(t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) {
if((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SERVER) {
pa_operation *pa = pa_context_get_server_info(c, subscribe_update_default_devices, handle);
if(pa)
pa_operation_unref(pa);

View File

@@ -1,4 +1,4 @@
#include "../../include/window/window_wayland.h"
#include "../../include/window/wayland.h"
#include "../../include/vec2.h"
#include "../../include/defs.h"

View File

@@ -1,4 +1,4 @@
#include "../../include/window/window_x11.h"
#include "../../include/window/x11.h"
#include "../../include/vec2.h"
#include "../../include/defs.h"