From fa8160bf8daf9c4713b7e8106d62512e28d640e6 Mon Sep 17 00:00:00 2001 From: columbarius Date: Fri, 28 May 2021 10:42:25 +0200 Subject: [PATCH] screencast: renegotiate if buffersize changes --- src/screencast/pipewire_screencast.c | 25 +++++++++++++++++++++++-- src/screencast/wlr_screencast.c | 3 +-- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/screencast/pipewire_screencast.c b/src/screencast/pipewire_screencast.c index 9cf0989e..67e05c7b 100644 --- a/src/screencast/pipewire_screencast.c +++ b/src/screencast/pipewire_screencast.c @@ -50,6 +50,16 @@ static inline struct spa_pod *build_format(struct spa_pod_builder *b, uint32_t f return spa_pod_builder_pop(b, &f[0]); } +void pwr_destroy_shm_buffer(struct xdpw_screencast_instance *cast, struct pw_buffer *buffer) { + struct spa_data *d; + + logprint(TRACE, "pipewire: destroy buffer %p", buffer); + d = buffer->buffer->datas; + wl_buffer_destroy(d[0].data); + d[0].data = NULL; + close(d[0].fd); +} + static void pwr_handle_stream_state_changed(void *data, enum pw_stream_state old, enum pw_stream_state state, const char *error) { struct xdpw_screencast_instance *cast = data; @@ -101,6 +111,7 @@ static void pwr_handle_stream_param_changed(void *data, uint32_t id, SPA_PARAM_META_size, SPA_POD_Int(sizeof(struct spa_meta_header))); pw_stream_update_params(stream, params, 2); + cast->changed = false; } static void pwr_handle_stream_add_buffer(void *data, struct pw_buffer *buffer) { @@ -149,15 +160,23 @@ static void pwr_handle_stream_add_buffer(void *data, struct pw_buffer *buffer) { } static void pwr_handle_stream_remove_buffer(void *data, struct pw_buffer *buffer) { + struct xdpw_screencast_instance *cast = data; struct spa_data *d; logprint(TRACE, "pipewire: remove buffer event handle"); + logprint(TRACE, "pipewire: buffer %p", buffer); d = buffer->buffer->datas; + if (buffer == cast->current_pw_buffer) { + logprint(TRACE, "pipewire: can't remove buffer. still in use"); + // TODO: We shouldn't trigger that currently, because we export the buffer before update_params which should + // flush the buffers at all clients, but what happens, if a client renegotiates parameters? + abort(); + return; + } switch (d[0].type) { case SPA_DATA_MemFd: - wl_buffer_destroy(d[0].data); - close(d[0].fd); + pwr_destroy_shm_buffer(cast, buffer); break; default: break; @@ -240,11 +259,13 @@ void pwr_update_stream_param(struct xdpw_screencast_instance *cast) { SPA_POD_BUILDER_INIT(params_buffer, sizeof(params_buffer)); const struct spa_pod *params[1]; + enum spa_video_format format = xdpw_format_pw_from_wl_shm(cast); params[0] = build_format(&b, format, cast->simple_frame.width, cast->simple_frame.height, cast->framerate); + logprint(TRACE, "pipewire: params updated"); pw_stream_update_params(stream, params, 1); } diff --git a/src/screencast/wlr_screencast.c b/src/screencast/wlr_screencast.c index 64b0db5e..e6567432 100644 --- a/src/screencast/wlr_screencast.c +++ b/src/screencast/wlr_screencast.c @@ -34,7 +34,7 @@ void xdpw_wlr_frame_free(struct xdpw_screencast_instance *cast) { return ; } - if (cast->pwr_stream_state) { + if (cast->pwr_stream_state && !cast->changed) { xdpw_wlr_frame_start(cast); } } @@ -106,7 +106,6 @@ static void wlr_frame_buffer_done(void *data, if (cast->pwr_stream_state) { pwr_update_stream_param(cast); } - cast->changed = false; xdpw_wlr_frame_free(cast); return; }