From 76de766cd84101e9304c1ff347478f2728794870 Mon Sep 17 00:00:00 2001 From: Demi Marie Obenour Date: Wed, 3 Jan 2024 14:16:20 -0500 Subject: [PATCH] Draft: Allow calling trigger_done from the RT thread This allows streams to know when the graph is finished and they can safely drive it again. Fixes: #3759 --- src/pipewire/stream.c | 12 ++++++++++-- src/pipewire/stream.h | 8 +++++++- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/pipewire/stream.c b/src/pipewire/stream.c index ee35c4f0a..7a7a6216b 100644 --- a/src/pipewire/stream.c +++ b/src/pipewire/stream.c @@ -158,6 +158,7 @@ struct stream { unsigned int using_trigger:1; unsigned int trigger:1; unsigned int early_process:1; + unsigned int trigger_done_rt:1; int in_set_param; int in_emit_param_changed; }; @@ -499,8 +500,14 @@ do_call_trigger_done(struct spa_loop *loop, static void call_trigger_done(struct stream *impl) { - pw_loop_invoke(impl->main_loop, - do_call_trigger_done, 1, NULL, 0, false, impl); + pw_log_trace_fp("%p: call trigger_done rt:%u", impl, impl->trigger_done_rt); + if (impl->trigger_done_rt) { + if (impl->rt_callbacks.funcs) + spa_callbacks_call(&impl->rt_callbacks, struct pw_stream_events, trigger_done, 2); + } else { + pw_loop_invoke(impl->main_loop, + do_call_trigger_done, 1, NULL, 0, false, impl); + } } static int @@ -1921,6 +1928,7 @@ pw_stream_connect(struct pw_stream *stream, impl->node_methods.process = impl_node_process_output; impl->process_rt = SPA_FLAG_IS_SET(flags, PW_STREAM_FLAG_RT_PROCESS); + impl->trigger_done_rt = SPA_FLAG_IS_SET(flags, PW_STREAM_FLAG_RT_TRIGGER_DONE); impl->early_process = SPA_FLAG_IS_SET(flags, PW_STREAM_FLAG_EARLY_PROCESS); impl->impl_node.iface = SPA_INTERFACE_INIT( diff --git a/src/pipewire/stream.h b/src/pipewire/stream.h index 3508d92a2..5a1fa1913 100644 --- a/src/pipewire/stream.h +++ b/src/pipewire/stream.h @@ -356,7 +356,10 @@ struct pw_stream_events { /** A command notify, Since 0.3.39:1 */ void (*command) (void *data, const struct spa_command *command); - /** a trigger_process completed. Since version 0.3.40:2 */ + /** a trigger_process completed. Since version 0.3.40:2. + * This is normally called from the mainloop but since 1.1.0 it + * can also be called directly from the realtime data + * thread if the user is prepared to deal with this. */ void (*trigger_done) (void *data); }; @@ -401,6 +404,9 @@ enum pw_stream_flags { * playback and when not using RT_PROCESS. It * can be used to keep the maximum number of * buffers queued. Since 0.3.81 */ + PW_STREAM_FLAG_RT_TRIGGER_DONE = (1 << 12), /**< Call trigger_done from the realtime + * thread. You MUST use RT safe functions + * in the trigger_done callback. Since 1.1.0 */ }; /** Create a new unconneced \ref pw_stream