From 6cc3a017417fa77fd9f3dd4fe230a9caf10418fb Mon Sep 17 00:00:00 2001 From: columbarius Date: Mon, 26 Oct 2020 16:22:08 +0100 Subject: [PATCH] screencast: pipewire change to self allocation of shm buffers --- include/screencast_common.h | 1 + src/screencast/pipewire_screencast.c | 48 ++++++++++++++++++++++++---- src/screencast/screencast_common.c | 24 ++++++++++++++ src/screencast/wlr_screencast.c | 19 ----------- 4 files changed, 67 insertions(+), 25 deletions(-) diff --git a/include/screencast_common.h b/include/screencast_common.h index e35fc2d..4f7b414 100644 --- a/include/screencast_common.h +++ b/include/screencast_common.h @@ -122,6 +122,7 @@ struct xdpw_wlr_output { }; void randname(char *buf); +int anonymous_shm_open(void); enum spa_video_format xdpw_format_pw_from_wl_shm(enum wl_shm_format format); 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 babca82..d8efb10 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" @@ -145,7 +147,7 @@ static void pwr_handle_stream_param_changed(void *data, uint32_t id, SPA_PARAM_BUFFERS_size, SPA_POD_Int(cast->simple_frame.size), SPA_PARAM_BUFFERS_stride, SPA_POD_Int(cast->simple_frame.stride), SPA_PARAM_BUFFERS_align, SPA_POD_Int(XDPW_PWR_ALIGN), - SPA_PARAM_BUFFERS_dataType,SPA_POD_CHOICE_FLAGS_Int(1<buffer->datas; // Select buffer type from negotiation result - if ((d[0].type & (1u << SPA_DATA_MemPtr)) > 0) { - d[0].type = SPA_DATA_MemPtr; + if ((d[0].type & (1u << SPA_DATA_MemFd)) > 0) { + d[0].type = SPA_DATA_MemFd; } else { logprint(ERROR, "pipewire: unsupported buffer type"); cast->err = 1; return; } + logprint(TRACE, "pipewire: selected buffertype %u", d[0].type); // Prepare buffer for choosen type - if (d[0].type == SPA_DATA_MemPtr) { + if (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].fd = anonymous_shm_open(); + + if (d[0].fd == -1) { + logprint(ERROR, "pipewire: unable to create anonymous filedescriptor"); + cast->err = 1; + return; + } + + if (ftruncate(d[0].fd, d[0].maxsize) < 0) { + logprint(ERROR, "pipewire: unable to truncate filedescriptor"); + close(d[0].fd); + d[0].fd = -1; + cast->err = 1; + return; + } + + // mmap buffer, so we can use the data_ptr in on_process + 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"); + cast->err = 1; + return; + } } } static void pwr_handle_stream_remove_buffer(void *data, struct pw_buffer *buffer) { logprint(TRACE, "pipewire: remove buffer event handle"); + + struct spa_data *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 = { @@ -250,7 +285,8 @@ void xdpw_pwr_stream_create(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 63d8d9a..915a585 100644 --- a/src/screencast/screencast_common.c +++ b/src/screencast/screencast_common.c @@ -1,5 +1,10 @@ #include "screencast_common.h" #include +#include +#include +#include +#include +#include void randname(char *buf) { struct timespec ts; @@ -12,6 +17,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(enum wl_shm_format format) { switch (format) { case WL_SHM_FORMAT_ARGB8888: diff --git a/src/screencast/wlr_screencast.c b/src/screencast/wlr_screencast.c index ca8ef93..21164a2 100644 --- a/src/screencast/wlr_screencast.c +++ b/src/screencast/wlr_screencast.c @@ -61,25 +61,6 @@ void xdpw_wlr_frame_free(struct xdpw_screencast_instance *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) {