diff --git a/src/screencast/pipewire_screencast.c b/src/screencast/pipewire_screencast.c index bbc419b..67d33a2 100644 --- a/src/screencast/pipewire_screencast.c +++ b/src/screencast/pipewire_screencast.c @@ -13,22 +13,6 @@ #include "xdpw.h" #include "logger.h" -static void writeFrameData(void *pwFramePointer, void *wlrFramePointer, - uint32_t height, uint32_t stride, bool inverted) { - if (!inverted) { - memcpy(pwFramePointer, wlrFramePointer, height * stride); - return; - } - - for (size_t i = 0; i < (size_t)height; ++i) { - void *flippedWlrRowPointer = wlrFramePointer + ((height - i - 1) * stride); - void *pwRowPointer = pwFramePointer + (i * stride); - memcpy(pwRowPointer, flippedWlrRowPointer, stride); - } - - return; -} - static struct spa_pod *build_format(struct spa_pod_builder *b, enum spa_video_format format, uint32_t width, uint32_t height, uint32_t framerate) { struct spa_pod_frame f[1]; @@ -143,6 +127,7 @@ static void pwr_handle_stream_add_buffer(void *data, struct pw_buffer *buffer) { d[0].chunk->offset = 0; d[0].flags = 0; d[0].fd = anonymous_shm_open(); + d[0].data = NULL; if (d[0].fd == -1) { logprint(ERROR, "pipewire: unable to create anonymous filedescriptor"); @@ -158,13 +143,9 @@ static void pwr_handle_stream_add_buffer(void *data, struct pw_buffer *buffer) { 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; - } + // create wl_buffer + buffer->user_data = import_wl_shm_buffer(cast, d[0].fd, cast->screencopy_frame.format, + cast->screencopy_frame.width, cast->screencopy_frame.height, cast->screencopy_frame.stride); } } @@ -174,7 +155,7 @@ static void pwr_handle_stream_remove_buffer(void *data, struct pw_buffer *buffer struct spa_data *d = buffer->buffer->datas; switch (d[0].type) { case SPA_DATA_MemFd: - munmap(d[0].data, d[0].maxsize); + wl_buffer_destroy(buffer->user_data); close(d[0].fd); break; default: @@ -196,6 +177,7 @@ void xdpw_pwr_dequeue_buffer(struct xdpw_screencast_instance *cast) { assert(cast->current_frame.current_pw_buffer == NULL); if ((cast->current_frame.current_pw_buffer = pw_stream_dequeue_buffer(cast->stream)) == NULL) { logprint(WARN, "pipewire: out of buffers"); + cast->current_frame.buffer = NULL; return; } @@ -203,6 +185,7 @@ void xdpw_pwr_dequeue_buffer(struct xdpw_screencast_instance *cast) { struct spa_data *d = spa_buf->datas; cast->current_frame.size = d[0].chunk->size; cast->current_frame.stride = d[0].chunk->stride; + cast->current_frame.buffer = cast->current_frame.current_pw_buffer->user_data; } void xdpw_pwr_enqueue_buffer(struct xdpw_screencast_instance *cast) { @@ -224,16 +207,14 @@ void xdpw_pwr_enqueue_buffer(struct xdpw_screencast_instance *cast) { h->seq = cast->seq++; h->dts_offset = 0; } - if (d[0].data == NULL) { - logprint(TRACE, "pipewire: data pointer undefined"); - goto queue; + + if (cast->screencopy_frame.y_invert) { + //TODO: Flip buffer or set stride negative + cast->err = 1; } - writeFrameData(d[0].data, cast->screencopy_frame.data, cast->screencopy_frame.height, - cast->screencopy_frame.stride, cast->screencopy_frame.y_invert); - logprint(TRACE, "********************"); - logprint(TRACE, "pipewire: pointer %p", d[0].data); + logprint(TRACE, "pipewire: fd %u", d[0].fd); logprint(TRACE, "pipewire: size %d", d[0].maxsize); logprint(TRACE, "pipewire: stride %d", d[0].chunk->stride); logprint(TRACE, "pipewire: width %d", cast->screencopy_frame.width); @@ -241,10 +222,10 @@ void xdpw_pwr_enqueue_buffer(struct xdpw_screencast_instance *cast) { logprint(TRACE, "pipewire: y_invert %d", cast->screencopy_frame.y_invert); logprint(TRACE, "********************"); -queue: pw_stream_queue_buffer(cast->stream, pw_buf); cast->current_frame.current_pw_buffer = NULL; + cast->current_frame.buffer = NULL; } void pwr_update_stream_param(struct xdpw_screencast_instance *cast) { diff --git a/src/screencast/wlr_screencast.c b/src/screencast/wlr_screencast.c index b56e8a9..0a88e11 100644 --- a/src/screencast/wlr_screencast.c +++ b/src/screencast/wlr_screencast.c @@ -20,28 +20,9 @@ #include "logger.h" #include "fps_limit.h" -static void wlr_frame_buffer_destroy(struct xdpw_screencast_instance *cast) { - // Even though this check may be deemed unnecessary, - // this has been found to cause SEGFAULTs, like this one: - // https://github.com/emersion/xdg-desktop-portal-wlr/issues/50 - if (cast->screencopy_frame.data != NULL) { - munmap(cast->screencopy_frame.data, cast->screencopy_frame.size); - cast->screencopy_frame.data = NULL; - } - - if (cast->screencopy_frame.buffer != NULL) { - wl_buffer_destroy(cast->screencopy_frame.buffer); - cast->screencopy_frame.buffer = NULL; - } -} - void xdpw_wlr_frame_free(struct xdpw_screencast_instance *cast) { zwlr_screencopy_frame_v1_destroy(cast->wlr_frame); cast->wlr_frame = NULL; - if (cast->quit || cast->err) { - wlr_frame_buffer_destroy(cast); - logprint(TRACE, "xdpw: screencopy_frame buffer destroyed"); - } logprint(TRACE, "wlroots: frame destroyed"); if (cast->quit || cast->err) { @@ -63,44 +44,6 @@ void xdpw_wlr_frame_free(struct xdpw_screencast_instance *cast) { } } -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) { - struct xdpw_screencast_context *ctx = cast->ctx; - int size = stride * height; - - int fd = anonymous_shm_open(); - if (fd < 0) { - logprint(ERROR, "wlroots: shm_open failed"); - return NULL; - } - - int ret; - while ((ret = ftruncate(fd, size)) == EINTR); - - if (ret < 0) { - close(fd); - logprint(ERROR, "wlroots: ftruncate failed"); - return NULL; - } - - void *data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - if (data == MAP_FAILED) { - logprint(ERROR, "wlroots: mmap failed: %m"); - close(fd); - return NULL; - } - - struct wl_shm_pool *pool = wl_shm_create_pool(ctx->shm, fd, size); - close(fd); - struct wl_buffer *buffer = - wl_shm_pool_create_buffer(pool, 0, width, height, stride, fmt); - wl_shm_pool_destroy(pool); - - *data_out = data; - return buffer; -} - static void wlr_frame_linux_dmabuf(void *data, struct zwlr_screencopy_frame_v1 *frame, uint32_t format, uint32_t width, uint32_t height) { @@ -146,7 +89,12 @@ static void wlr_frame_buffer_done(void *data, return; } - zwlr_screencopy_frame_v1_copy_with_damage(frame, cast->screencopy_frame.buffer); + if (cast->current_frame.buffer == NULL) { + logprint(ERROR, "wlroots: imported buffer doesn't contain a wlr_buffer"); + abort(); + } + + zwlr_screencopy_frame_v1_copy_with_damage(frame, cast->current_frame.buffer); logprint(TRACE, "wlroots: frame copied"); fps_limit_measure_start(&cast->fps_limit, cast->framerate); @@ -165,19 +113,6 @@ static void wlr_frame_buffer(void *data, struct zwlr_screencopy_frame_v1 *frame, cast->screencopy_frame.size = stride * height; cast->screencopy_frame.format = format; - if (cast->screencopy_frame.buffer == NULL) { - logprint(DEBUG, "wlroots: create shm buffer"); - cast->screencopy_frame.buffer = create_shm_buffer(cast, format, width, height, - stride, &cast->screencopy_frame.data); - } else { - logprint(TRACE,"wlroots: shm buffer exists"); - } - - if (cast->screencopy_frame.buffer == NULL) { - logprint(ERROR, "wlroots: failed to create buffer"); - abort(); - } - if (zwlr_screencopy_manager_v1_get_version(cast->ctx->screencopy_manager) < 3) { wlr_frame_buffer_done(cast,frame); }