From 0eb44b340aece98beef072d7c097a1c2f77306f2 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Thu, 18 Jan 2018 15:39:03 +0100 Subject: [PATCH] link: use DISABLED flag on port of inactive links Don't unlink the ports of an inactive link because then it might be possible that the scheduler can't recycle a buffer, instead use a port flag to mark the ports disabled and change to scheduler to skip those ports. --- spa/include/spa/graph/graph-scheduler6.h | 4 ++-- spa/include/spa/graph/graph.h | 3 ++- spa/include/spa/utils/defs.h | 4 ++++ spa/plugins/alsa/alsa-utils.c | 1 - spa/plugins/bluez5/a2dp-sink.c | 2 +- src/pipewire/link.c | 11 +++++++---- 6 files changed, 16 insertions(+), 9 deletions(-) diff --git a/spa/include/spa/graph/graph-scheduler6.h b/spa/include/spa/graph/graph-scheduler6.h index 1dacb5768..68e84e1d7 100644 --- a/spa/include/spa/graph/graph-scheduler6.h +++ b/spa/include/spa/graph/graph-scheduler6.h @@ -49,7 +49,7 @@ static inline int spa_graph_impl_need_input(void *data, struct spa_graph_node *n struct spa_graph_node *pnode; uint32_t prequired, pready; - if ((pport = p->peer) == NULL) { + if ((pport = p->peer) == NULL || (pport->flags & SPA_GRAPH_PORT_FLAG_DISABLED)) { spa_debug("node %p port %p has no peer", node, p); continue; } @@ -94,7 +94,7 @@ static inline int spa_graph_impl_have_output(void *data, struct spa_graph_node * struct spa_graph_node *pnode; uint32_t prequired, pready; - if ((pport = p->peer) == NULL) { + if ((pport = p->peer) == NULL || (pport->flags & SPA_GRAPH_PORT_FLAG_DISABLED)) { spa_debug("node %p port %p has no peer", node, p); continue; } diff --git a/spa/include/spa/graph/graph.h b/spa/include/spa/graph/graph.h index 4338b1193..ed33bc5b4 100644 --- a/spa/include/spa/graph/graph.h +++ b/spa/include/spa/graph/graph.h @@ -60,7 +60,7 @@ struct spa_graph_node { struct spa_graph *graph; /**< owner graph */ struct spa_list ports[2]; /**< list of input and output ports */ struct spa_list ready_link; /**< link for scheduler */ -#define SPA_GRAPH_NODE_FLAG_ASYNC (1 << 0) +#define SPA_GRAPH_NODE_FLAG_ASYNC (1 << 0) uint32_t flags; /**< node flags */ uint32_t required[2]; /**< required number of ports */ uint32_t ready[2]; /**< number of ports with data */ @@ -74,6 +74,7 @@ struct spa_graph_port { struct spa_graph_node *node; /**< owner node */ enum spa_direction direction; /**< port direction */ uint32_t port_id; /**< port id */ +#define SPA_GRAPH_PORT_FLAG_DISABLED (1 << 0) uint32_t flags; /**< port flags */ struct spa_io_buffers *io; /**< io area of the port */ struct spa_graph_port *peer; /**< peer */ diff --git a/spa/include/spa/utils/defs.h b/spa/include/spa/utils/defs.h index 3312ad127..0486c0251 100644 --- a/spa/include/spa/utils/defs.h +++ b/spa/include/spa/utils/defs.h @@ -42,6 +42,10 @@ extern "C" { #define SPA_RESULT_ASYNC_SEQ(res) ((res) & SPA_ASYNC_SEQ_MASK) #define SPA_RESULT_RETURN_ASYNC(seq) (SPA_ASYNC_BIT | ((seq) & SPA_ASYNC_SEQ_MASK)) +#define SPA_FLAG_CHECK(field,flag) (((field) & (flag)) == (flag)) +#define SPA_FLAG_SET(field,flag) ((field) |= (flag)) +#define SPA_FLAG_UNSET(field,flag) ((field) &= ~(flag)) + enum spa_direction { SPA_DIRECTION_INPUT = 0, SPA_DIRECTION_OUTPUT = 1, diff --git a/spa/plugins/alsa/alsa-utils.c b/spa/plugins/alsa/alsa-utils.c index 04f41363f..129a18f4e 100644 --- a/spa/plugins/alsa/alsa-utils.c +++ b/spa/plugins/alsa/alsa-utils.c @@ -413,7 +413,6 @@ pull_frames(struct state *state, if (total_frames == 0 && do_pull) { total_frames = SPA_MIN(frames, state->threshold); - spa_log_warn(state->log, "write %zd frames of silence", total_frames); snd_pcm_areas_silence(my_areas, offset, state->channels, total_frames, state->format); state->underrun += total_frames; underrun = true; diff --git a/spa/plugins/bluez5/a2dp-sink.c b/spa/plugins/bluez5/a2dp-sink.c index 8803b1197..f02a800cb 100644 --- a/spa/plugins/bluez5/a2dp-sink.c +++ b/spa/plugins/bluez5/a2dp-sink.c @@ -305,7 +305,7 @@ static inline void try_pull(struct impl *this, uint32_t frames, bool do_pull) struct spa_io_buffers *io = this->io; if (spa_list_is_empty(&this->ready) && do_pull) { - spa_log_trace(this->log, "alsa-util %p: %d", this, io->status); + spa_log_trace(this->log, "a2dp-sink %p: %d", this, io->status); io->status = SPA_STATUS_NEED_BUFFER; if (this->range) { this->range->offset = this->sample_count * this->frame_size; diff --git a/src/pipewire/link.c b/src/pipewire/link.c index 272c80d6b..1c1d61d12 100644 --- a/src/pipewire/link.c +++ b/src/pipewire/link.c @@ -712,7 +712,8 @@ do_activate_link(struct spa_loop *loop, bool async, uint32_t seq, const void *data, size_t size, void *user_data) { struct pw_link *this = user_data; - spa_graph_port_link(&this->rt.out_port, &this->rt.in_port); + SPA_FLAG_UNSET(this->rt.out_port.flags, SPA_GRAPH_PORT_FLAG_DISABLED); + SPA_FLAG_UNSET(this->rt.in_port.flags, SPA_GRAPH_PORT_FLAG_DISABLED); return 0; } @@ -953,7 +954,8 @@ do_deactivate_link(struct spa_loop *loop, bool async, uint32_t seq, const void *data, size_t size, void *user_data) { struct pw_link *this = user_data; - spa_graph_port_unlink(&this->rt.out_port); + SPA_FLAG_SET(this->rt.out_port.flags, SPA_GRAPH_PORT_FLAG_DISABLED); + SPA_FLAG_SET(this->rt.in_port.flags, SPA_GRAPH_PORT_FLAG_DISABLED); return 0; } @@ -1165,13 +1167,14 @@ struct pw_link *pw_link_new(struct pw_core *core, spa_graph_port_init(&this->rt.out_port, PW_DIRECTION_OUTPUT, this->rt.out_port.port_id, - 0, + SPA_GRAPH_PORT_FLAG_DISABLED, &this->io); spa_graph_port_init(&this->rt.in_port, PW_DIRECTION_INPUT, this->rt.in_port.port_id, - 0, + SPA_GRAPH_PORT_FLAG_DISABLED, &this->io); + spa_graph_port_link(&this->rt.out_port, &this->rt.in_port); this->rt.in_port.scheduler_data = this; this->rt.out_port.scheduler_data = this;