From ce9d77c90c54dd9d9d3240b9c5eb85102ab57c29 Mon Sep 17 00:00:00 2001 From: columbarius Date: Wed, 2 Mar 2022 18:06:22 +0100 Subject: [PATCH] screencast: relax buffer flip In case a client doesn't return a buffer early enough we can give it a second chance by triggering on_process before we pass the buffer to wlroots in the frame_buffer_done event. --- include/screencast_common.h | 1 + src/screencast/pipewire_screencast.c | 17 +++++++++++++++++ src/screencast/screencast.c | 1 + src/screencast/wlr_screencast.c | 1 + 4 files changed, 20 insertions(+) diff --git a/include/screencast_common.h b/include/screencast_common.h index 90f6ef1..02bd544 100644 --- a/include/screencast_common.h +++ b/include/screencast_common.h @@ -131,6 +131,7 @@ struct xdpw_screencast_instance { bool with_cursor; int err; bool quit; + bool need_buffer; // fps limit struct fps_limit_state fps_limit; diff --git a/src/screencast/pipewire_screencast.c b/src/screencast/pipewire_screencast.c index 8384d85..ffda23e 100644 --- a/src/screencast/pipewire_screencast.c +++ b/src/screencast/pipewire_screencast.c @@ -44,6 +44,18 @@ static struct spa_pod *build_format(struct spa_pod_builder *b, enum spa_video_fo return spa_pod_builder_pop(b, &f[0]); } +static void pwr_handle_stream_on_process(void *data) { + logprint(TRACE, "pipewire: stream process"); + struct xdpw_screencast_instance *cast = data; + + if (cast->need_buffer) { + xdpw_pwr_dequeue_buffer(cast); + if (cast->current_frame.pw_buffer) { + cast->need_buffer = false; + } + } +} + 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; @@ -166,6 +178,7 @@ static const struct pw_stream_events pwr_stream_events = { .param_changed = pwr_handle_stream_param_changed, .add_buffer = pwr_handle_stream_add_buffer, .remove_buffer = pwr_handle_stream_remove_buffer, + .process = pwr_handle_stream_on_process, }; void xdpw_pwr_dequeue_buffer(struct xdpw_screencast_instance *cast) { @@ -240,7 +253,11 @@ void xdpw_pwr_swap_buffer(struct xdpw_screencast_instance *cast) { dequeue_buffer: assert(!cast->current_frame.pw_buffer); + cast->need_buffer = false; xdpw_pwr_dequeue_buffer(cast); + if (!cast->current_frame.pw_buffer) { + cast->need_buffer = true; + } } void pwr_update_stream_param(struct xdpw_screencast_instance *cast) { diff --git a/src/screencast/screencast.c b/src/screencast/screencast.c index 9fcc7de..08a920c 100644 --- a/src/screencast/screencast.c +++ b/src/screencast/screencast.c @@ -70,6 +70,7 @@ void xdpw_screencast_instance_init(struct xdpw_screencast_context *ctx, cast->with_cursor = with_cursor; cast->refcount = 1; cast->node_id = SPA_ID_INVALID; + cast->need_buffer = false; wl_list_init(&cast->buffer_list); logprint(INFO, "xdpw: screencast instance %p has %d references", cast, cast->refcount); wl_list_insert(&ctx->screencast_instances, &cast->link); diff --git a/src/screencast/wlr_screencast.c b/src/screencast/wlr_screencast.c index 0003a27..c410ee0 100644 --- a/src/screencast/wlr_screencast.c +++ b/src/screencast/wlr_screencast.c @@ -130,6 +130,7 @@ static void wlr_frame_buffer_done(void *data, xdpw_pwr_dequeue_buffer(cast); } + cast->need_buffer = false; if (!cast->current_frame.xdpw_buffer) { logprint(WARN, "wlroots: no current buffer"); xdpw_wlr_frame_finish(cast);