From 42e0b520aa21fb619695b0cbfca601ba47759e14 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Fri, 6 Aug 2021 13:09:39 +0200 Subject: [PATCH] stream: Detect if we are driving or not We need to check the position vs the clock to see if we are currently driving the graph. We can only call the node ready callback when we are actually driving the graph. --- src/pipewire/stream.c | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/src/pipewire/stream.c b/src/pipewire/stream.c index e4873c144..cea3b733e 100644 --- a/src/pipewire/stream.c +++ b/src/pipewire/stream.c @@ -112,6 +112,7 @@ struct stream { struct spa_hook_list hooks; struct spa_callbacks callbacks; + struct spa_io_clock *clock; struct spa_io_position *position; struct spa_io_buffers *io; struct { @@ -164,6 +165,7 @@ struct stream { unsigned int allow_mlock:1; unsigned int warn_mlock:1; unsigned int process_rt:1; + unsigned int driving:1; }; static int get_param_index(uint32_t id) @@ -433,15 +435,25 @@ static int impl_set_io(void *object, uint32_t id, void *data, size_t size) spa_debug_type_find_name(spa_type_io, id), data, size); switch(id) { + case SPA_IO_Clock: + if (data && size >= sizeof(struct spa_io_clock)) + impl->clock = data; + else + impl->clock = NULL; + break; case SPA_IO_Position: if (data && size >= sizeof(struct spa_io_position)) impl->position = data; else impl->position = NULL; + pw_loop_invoke(impl->context->data_loop, do_set_position, 1, NULL, 0, true, impl); break; + default: + break; } + impl->driving = impl->clock && impl->position && impl->position->clock.id == impl->clock->id; pw_stream_emit_io_changed(stream, id, data, size); return 0; @@ -938,8 +950,7 @@ again: copy_position(impl, impl->queued.outcount); - if (!impl->draining && - !SPA_FLAG_IS_SET(impl->flags, PW_STREAM_FLAG_DRIVER)) { + if (!impl->draining && !impl->driving) { /* we're not draining, not a driver check if we need to get * more buffers */ if (!impl->process_rt) { @@ -1993,7 +2004,7 @@ int pw_stream_get_time(struct pw_stream *stream, struct pw_time *time) } static int -do_process(struct spa_loop *loop, +do_trigger(struct spa_loop *loop, bool async, uint32_t seq, const void *data, size_t size, void *user_data) { struct stream *impl = user_data; @@ -2001,16 +2012,6 @@ do_process(struct spa_loop *loop, return spa_node_call_ready(&impl->callbacks, res); } -static inline int call_trigger(struct stream *impl) -{ - int res = 0; - if (SPA_FLAG_IS_SET(impl->flags, PW_STREAM_FLAG_DRIVER)) { - res = pw_loop_invoke(impl->context->data_loop, - do_process, 1, NULL, 0, false, impl); - } - return res; -} - SPA_EXPORT struct pw_buffer *pw_stream_dequeue_buffer(struct pw_stream *stream) { @@ -2052,9 +2053,11 @@ int pw_stream_queue_buffer(struct pw_stream *stream, struct pw_buffer *buffer) if ((res = push_queue(impl, &impl->queued, b)) < 0) return res; - if (impl->direction == SPA_DIRECTION_OUTPUT) - res = call_trigger(impl); - + if (impl->direction == SPA_DIRECTION_OUTPUT && + impl->driving) { + res = pw_loop_invoke(impl->context->data_loop, + do_trigger, 1, NULL, 0, false, impl); + } return res; }