mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-10-31 22:25:38 -04:00
stream: don't emit drain when in progress
We keep on calling the drain event for as long as we are drained. The application is supposed to inactivate the stream or provide more data at some point. Because we do this from the data thread, we use a non-blocking invoke. If for some reason the event callback takes a long time we might place a lot of these invoke calls into the invoke queue, which will then be dispatched one after another (and cause more blocking or a burst of useless invoke calls). Avoid this by only placing one drain invoke call into the queue at a time. Fixes #4529
This commit is contained in:
parent
b341668fda
commit
864438e8e9
2 changed files with 17 additions and 4 deletions
|
|
@ -146,6 +146,7 @@ struct filter {
|
|||
unsigned int warn_mlock:1;
|
||||
unsigned int trigger:1;
|
||||
int in_emit_param_changed;
|
||||
int pending_drain;
|
||||
};
|
||||
|
||||
static int get_param_index(uint32_t id)
|
||||
|
|
@ -989,13 +990,19 @@ do_call_drained(struct spa_loop *loop,
|
|||
struct pw_filter *filter = &impl->this;
|
||||
pw_log_trace("%p: drained", filter);
|
||||
pw_filter_emit_drained(filter);
|
||||
SPA_ATOMIC_DEC(impl->pending_drain);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void call_drained(struct filter *impl)
|
||||
{
|
||||
pw_loop_invoke(impl->main_loop,
|
||||
do_call_drained, 1, NULL, 0, false, impl);
|
||||
pw_log_info("%p: drained", impl);
|
||||
if (SPA_ATOMIC_INC(impl->pending_drain) == 1) {
|
||||
pw_loop_invoke(impl->main_loop,
|
||||
do_call_drained, 1, NULL, 0, false, impl);
|
||||
} else {
|
||||
SPA_ATOMIC_DEC(impl->pending_drain);
|
||||
}
|
||||
}
|
||||
|
||||
static int impl_node_process(void *object)
|
||||
|
|
|
|||
|
|
@ -154,6 +154,7 @@ struct stream {
|
|||
unsigned int trigger_done_rt:1;
|
||||
int in_set_param;
|
||||
int in_emit_param_changed;
|
||||
int pending_drain;
|
||||
};
|
||||
|
||||
static int get_param_index(uint32_t id)
|
||||
|
|
@ -455,14 +456,19 @@ do_call_drained(struct spa_loop *loop,
|
|||
struct pw_stream *stream = &impl->this;
|
||||
pw_log_trace_fp("%p: drained", stream);
|
||||
pw_stream_emit_drained(stream);
|
||||
SPA_ATOMIC_DEC(impl->pending_drain);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void call_drained(struct stream *impl)
|
||||
{
|
||||
pw_log_info("%p: drained", impl);
|
||||
pw_loop_invoke(impl->main_loop,
|
||||
do_call_drained, 1, NULL, 0, false, impl);
|
||||
if (SPA_ATOMIC_INC(impl->pending_drain) == 1) {
|
||||
pw_loop_invoke(impl->main_loop,
|
||||
do_call_drained, 1, NULL, 0, false, impl);
|
||||
} else {
|
||||
SPA_ATOMIC_DEC(impl->pending_drain);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue