diff --git a/include/screencast_common.h b/include/screencast_common.h index 0724bd11..c8702b06 100644 --- a/include/screencast_common.h +++ b/include/screencast_common.h @@ -107,6 +107,7 @@ struct xdpw_wlr_output { }; void randname(char *buf); +int anonymous_shm_open(void); enum spa_video_format xdpw_format_pw_from_wl_shm( struct xdpw_screencast_instance *cast); enum spa_video_format xdpw_format_pw_strip_alpha(enum spa_video_format format); diff --git a/src/screencast/pipewire_screencast.c b/src/screencast/pipewire_screencast.c index 9c771a59..db8c051f 100644 --- a/src/screencast/pipewire_screencast.c +++ b/src/screencast/pipewire_screencast.c @@ -5,6 +5,8 @@ #include #include #include +#include +#include #include "wlr_screencast.h" #include "xdpw.h" @@ -148,18 +150,47 @@ static void pwr_handle_stream_add_buffer(void *data, struct pw_buffer *buffer) { // Prepare buffer for choosen type if (d[0].type == SPA_DATA_MemPtr) { + d[0].type = SPA_DATA_MemFd; d[0].maxsize = cast->simple_frame.size; d[0].mapoffset = 0; d[0].chunk->size = cast->simple_frame.size; d[0].chunk->stride = cast->simple_frame.stride; d[0].chunk->offset = 0; - d[0].flags = 0; - d[0].fd = -1; + d[0].flags = SPA_DATA_FLAG_READWRITE; + d[0].fd = anonymous_shm_open(); + + if (d[0].fd == -1) { + logprint(ERROR, "pipewire: unable to create anonymous filedescriptor"); + return; + } + + if (ftruncate(d[0].fd, d[0].maxsize) < 0) { + logprint(ERROR, "pipewire: unable to truncate filedescriptor"); + return; + } + + d[0].data = mmap(NULL, d[0].maxsize, PROT_READ | PROT_WRITE, MAP_SHARED, d[0].fd, d[0].mapoffset); + if (d[0].data == MAP_FAILED) { + logprint(ERROR, "pipewire: unable to mmap memory"); + return; + } } } static void pwr_handle_stream_remove_buffer(void *data, struct pw_buffer *buffer) { + struct spa_data *d; + logprint(TRACE, "pipewire: remove buffer event handle"); + + d = buffer->buffer->datas; + switch (d[0].type) { + case SPA_DATA_MemFd: + munmap(d[0].data, d[0].maxsize); + close(d[0].fd); + break; + default: + break; + } } static const struct pw_stream_events pwr_stream_events = { @@ -228,7 +259,8 @@ void xdpw_pwr_stream_init(struct xdpw_screencast_instance *cast) { pw_stream_connect(cast->stream, PW_DIRECTION_OUTPUT, PW_ID_ANY, - PW_STREAM_FLAG_DRIVER, + (PW_STREAM_FLAG_DRIVER | + PW_STREAM_FLAG_ALLOC_BUFFERS), ¶m, 1); } diff --git a/src/screencast/screencast_common.c b/src/screencast/screencast_common.c index f185ad7a..7d78364f 100644 --- a/src/screencast/screencast_common.c +++ b/src/screencast/screencast_common.c @@ -1,5 +1,9 @@ #include "screencast_common.h" #include +#include +#include +#include +#include void randname(char *buf) { struct timespec ts; @@ -12,6 +16,25 @@ void randname(char *buf) { } } +int anonymous_shm_open(void) { + char name[] = "/xdpw-shm-XXXXXX"; + int retries = 100; + + do { + randname(name + strlen(name) - 6); + + --retries; + // shm_open guarantees that O_CLOEXEC is set + int fd = shm_open(name, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR); + if (fd >= 0) { + shm_unlink(name); + return fd; + } + } while (retries > 0 && errno == EEXIST); + + return -1; +} + enum spa_video_format xdpw_format_pw_from_wl_shm( struct xdpw_screencast_instance *cast) { switch (cast->simple_frame.format) { diff --git a/src/screencast/wlr_screencast.c b/src/screencast/wlr_screencast.c index a93e248a..ac230fae 100644 --- a/src/screencast/wlr_screencast.c +++ b/src/screencast/wlr_screencast.c @@ -54,25 +54,6 @@ void xdpw_wlr_frame_free(struct xdpw_screencast_instance *cast) { xdpw_wlr_register_cb(cast); } -static int anonymous_shm_open(void) { - char name[] = "/xdpw-shm-XXXXXX"; - int retries = 100; - - do { - randname(name + strlen(name) - 6); - - --retries; - // shm_open guarantees that O_CLOEXEC is set - int fd = shm_open(name, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR); - if (fd >= 0) { - shm_unlink(name); - return fd; - } - } while (retries > 0 && errno == EEXIST); - - return -1; -} - static struct wl_buffer *create_shm_buffer(struct xdpw_screencast_instance *cast, enum wl_shm_format fmt, int width, int height, int stride, void **data_out) {