mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-10 13:30:05 -05:00
Make scheduler more generic
Add some callbacks to trigger push and pull in a graph Remove the scheduler, make some implementations of graph push/pull functions. Add some properties to jack clients and nodes Fix the parent of the clients. Notify link format changes
This commit is contained in:
parent
eba2b82c8e
commit
bece3a013b
20 changed files with 248 additions and 158 deletions
|
|
@ -31,39 +31,39 @@ extern "C" {
|
|||
#define SPA_GRAPH_STATE_CHECK_IN 2
|
||||
#define SPA_GRAPH_STATE_CHECK_OUT 3
|
||||
|
||||
struct spa_graph_scheduler {
|
||||
struct spa_graph_data {
|
||||
struct spa_graph *graph;
|
||||
struct spa_list ready;
|
||||
struct spa_graph_node *node;
|
||||
};
|
||||
|
||||
static inline void spa_graph_scheduler_init(struct spa_graph_scheduler *sched,
|
||||
struct spa_graph *graph)
|
||||
static inline void spa_graph_data_init(struct spa_graph_data *data,
|
||||
struct spa_graph *graph)
|
||||
{
|
||||
sched->graph = graph;
|
||||
spa_list_init(&sched->ready);
|
||||
sched->node = NULL;
|
||||
data->graph = graph;
|
||||
spa_list_init(&data->ready);
|
||||
data->node = NULL;
|
||||
}
|
||||
|
||||
static inline int spa_graph_scheduler_input(void *data)
|
||||
static inline int spa_graph_node_impl_input(void *data)
|
||||
{
|
||||
struct spa_node *n = data;
|
||||
return spa_node_process_input(n);
|
||||
}
|
||||
|
||||
static inline int spa_graph_scheduler_output(void *data)
|
||||
static inline int spa_graph_node_impl_output(void *data)
|
||||
{
|
||||
struct spa_node *n = data;
|
||||
return spa_node_process_output(n);
|
||||
}
|
||||
|
||||
static const struct spa_graph_node_callbacks spa_graph_scheduler_default = {
|
||||
static const struct spa_graph_node_callbacks spa_graph_node_impl_default = {
|
||||
SPA_VERSION_GRAPH_NODE_CALLBACKS,
|
||||
spa_graph_scheduler_input,
|
||||
spa_graph_scheduler_output,
|
||||
spa_graph_node_impl_input,
|
||||
spa_graph_node_impl_output,
|
||||
};
|
||||
|
||||
static inline void spa_scheduler_port_check(struct spa_graph_scheduler *sched, struct spa_graph_port *port)
|
||||
static inline void spa_graph_data_port_check(struct spa_graph_data *data, struct spa_graph_port *port)
|
||||
{
|
||||
struct spa_graph_node *node = port->node;
|
||||
|
||||
|
|
@ -75,23 +75,23 @@ static inline void spa_scheduler_port_check(struct spa_graph_scheduler *sched, s
|
|||
if (node->required_in > 0 && node->ready_in == node->required_in) {
|
||||
node->state = SPA_GRAPH_STATE_IN;
|
||||
if (node->ready_link.next == NULL)
|
||||
spa_list_insert(sched->ready.prev, &node->ready_link);
|
||||
spa_list_insert(data->ready.prev, &node->ready_link);
|
||||
} else if (node->ready_link.next) {
|
||||
spa_list_remove(&node->ready_link);
|
||||
node->ready_link.next = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool spa_graph_scheduler_iterate(struct spa_graph_scheduler *sched)
|
||||
static inline bool spa_graph_data_iterate(struct spa_graph_data *data)
|
||||
{
|
||||
bool res;
|
||||
int state;
|
||||
struct spa_graph_port *p;
|
||||
struct spa_graph_node *n;
|
||||
|
||||
res = !spa_list_is_empty(&sched->ready);
|
||||
res = !spa_list_is_empty(&data->ready);
|
||||
if (res) {
|
||||
n = spa_list_first(&sched->ready, struct spa_graph_node, ready_link);
|
||||
n = spa_list_first(&data->ready, struct spa_graph_node, ready_link);
|
||||
|
||||
spa_list_remove(&n->ready_link);
|
||||
n->ready_link.next = NULL;
|
||||
|
|
@ -106,9 +106,9 @@ static inline bool spa_graph_scheduler_iterate(struct spa_graph_scheduler *sched
|
|||
else if (state == SPA_RESULT_HAVE_BUFFER)
|
||||
n->state = SPA_GRAPH_STATE_CHECK_OUT;
|
||||
debug("node %p processed input state %d\n", n, n->state);
|
||||
if (n == sched->node)
|
||||
if (n == data->node)
|
||||
break;
|
||||
spa_list_insert(sched->ready.prev, &n->ready_link);
|
||||
spa_list_append(&data->ready, &n->ready_link);
|
||||
break;
|
||||
|
||||
case SPA_GRAPH_STATE_OUT:
|
||||
|
|
@ -118,7 +118,7 @@ static inline bool spa_graph_scheduler_iterate(struct spa_graph_scheduler *sched
|
|||
else if (state == SPA_RESULT_HAVE_BUFFER)
|
||||
n->state = SPA_GRAPH_STATE_CHECK_OUT;
|
||||
debug("node %p processed output state %d\n", n, n->state);
|
||||
spa_list_insert(sched->ready.prev, &n->ready_link);
|
||||
spa_list_append(&data->ready, &n->ready_link);
|
||||
break;
|
||||
|
||||
case SPA_GRAPH_STATE_CHECK_IN:
|
||||
|
|
@ -126,10 +126,10 @@ static inline bool spa_graph_scheduler_iterate(struct spa_graph_scheduler *sched
|
|||
spa_list_for_each(p, &n->ports[SPA_DIRECTION_INPUT], link) {
|
||||
struct spa_graph_node *pn = p->peer->node;
|
||||
if (p->io->status == SPA_RESULT_NEED_BUFFER) {
|
||||
if (pn != sched->node
|
||||
if (pn != data->node
|
||||
|| pn->flags & SPA_GRAPH_NODE_FLAG_ASYNC) {
|
||||
pn->state = SPA_GRAPH_STATE_OUT;
|
||||
spa_list_insert(sched->ready.prev,
|
||||
spa_list_append(&data->ready,
|
||||
&pn->ready_link);
|
||||
}
|
||||
} else if (p->io->status == SPA_RESULT_OK)
|
||||
|
|
@ -137,35 +137,52 @@ static inline bool spa_graph_scheduler_iterate(struct spa_graph_scheduler *sched
|
|||
}
|
||||
case SPA_GRAPH_STATE_CHECK_OUT:
|
||||
spa_list_for_each(p, &n->ports[SPA_DIRECTION_OUTPUT], link)
|
||||
spa_scheduler_port_check(sched, p->peer);
|
||||
spa_graph_data_port_check(data, p->peer);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
res = !spa_list_is_empty(&sched->ready);
|
||||
res = !spa_list_is_empty(&data->ready);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static inline void spa_graph_scheduler_pull(struct spa_graph_scheduler *sched, struct spa_graph_node *node)
|
||||
static inline int spa_graph_impl_need_input(void *data, struct spa_graph_node *node)
|
||||
{
|
||||
struct spa_graph_data *d = data;
|
||||
debug("node %p start pull\n", node);
|
||||
node->state = SPA_GRAPH_STATE_CHECK_IN;
|
||||
sched->node = node;
|
||||
d->node = node;
|
||||
if (node->ready_link.next == NULL)
|
||||
spa_list_insert(sched->ready.prev, &node->ready_link);
|
||||
spa_list_append(&d->ready, &node->ready_link);
|
||||
|
||||
while(spa_graph_data_iterate(data));
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
||||
static inline void spa_graph_scheduler_push(struct spa_graph_scheduler *sched, struct spa_graph_node *node)
|
||||
static inline int spa_graph_impl_have_output(void *data, struct spa_graph_node *node)
|
||||
{
|
||||
struct spa_graph_data *d = data;
|
||||
debug("node %p start push\n", node);
|
||||
node->state = SPA_GRAPH_STATE_OUT;
|
||||
sched->node = node;
|
||||
d->node = node;
|
||||
if (node->ready_link.next == NULL)
|
||||
spa_list_insert(sched->ready.prev, &node->ready_link);
|
||||
spa_list_append(&d->ready, &node->ready_link);
|
||||
|
||||
while(spa_graph_data_iterate(data));
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
||||
static const struct spa_graph_callbacks spa_graph_impl_default = {
|
||||
SPA_VERSION_GRAPH_CALLBACKS,
|
||||
.need_input = spa_graph_impl_need_input,
|
||||
.have_output = spa_graph_impl_have_output,
|
||||
};
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -26,37 +26,26 @@ extern "C" {
|
|||
|
||||
#include <spa/graph.h>
|
||||
|
||||
struct spa_graph_scheduler {
|
||||
struct spa_graph *graph;
|
||||
};
|
||||
|
||||
static inline void spa_graph_scheduler_init(struct spa_graph_scheduler *sched,
|
||||
struct spa_graph *graph)
|
||||
{
|
||||
sched->graph = graph;
|
||||
}
|
||||
|
||||
static inline int spa_graph_node_scheduler_input(void *data)
|
||||
static inline int spa_graph_node_impl_input(void *data)
|
||||
{
|
||||
struct spa_node *n = data;
|
||||
return spa_node_process_input(n);
|
||||
}
|
||||
|
||||
static inline int spa_graph_node_scheduler_output(void *data)
|
||||
static inline int spa_graph_node_impl_output(void *data)
|
||||
{
|
||||
struct spa_node *n = data;
|
||||
return spa_node_process_output(n);
|
||||
}
|
||||
|
||||
|
||||
static const struct spa_graph_node_callbacks spa_graph_node_scheduler_default = {
|
||||
static const struct spa_graph_node_callbacks spa_graph_node_impl_default = {
|
||||
SPA_VERSION_GRAPH_NODE_CALLBACKS,
|
||||
spa_graph_node_scheduler_input,
|
||||
spa_graph_node_scheduler_output,
|
||||
spa_graph_node_impl_input,
|
||||
spa_graph_node_impl_output,
|
||||
};
|
||||
|
||||
static inline int spa_graph_port_scheduler_reuse_buffer(void *data,
|
||||
uint32_t buffer_id)
|
||||
static inline int spa_graph_port_impl_reuse_buffer(void *data,
|
||||
uint32_t buffer_id)
|
||||
{
|
||||
struct spa_graph_port *port = data;
|
||||
struct spa_node *node = port->node->callbacks_data;
|
||||
|
|
@ -64,12 +53,12 @@ static inline int spa_graph_port_scheduler_reuse_buffer(void *data,
|
|||
return spa_node_port_reuse_buffer(node, port->port_id, buffer_id);
|
||||
}
|
||||
|
||||
static const struct spa_graph_port_callbacks spa_graph_port_scheduler_default = {
|
||||
static const struct spa_graph_port_callbacks spa_graph_port_impl_default = {
|
||||
SPA_VERSION_GRAPH_PORT_CALLBACKS,
|
||||
spa_graph_port_scheduler_reuse_buffer,
|
||||
spa_graph_port_impl_reuse_buffer,
|
||||
};
|
||||
|
||||
static inline void spa_graph_scheduler_pull(struct spa_graph_scheduler *sched, struct spa_graph_node *node)
|
||||
static inline int spa_graph_impl_need_input(void *data, struct spa_graph_node *node)
|
||||
{
|
||||
struct spa_graph_port *p;
|
||||
struct spa_graph_node *n, *t;
|
||||
|
|
@ -99,7 +88,7 @@ static inline void spa_graph_scheduler_pull(struct spa_graph_scheduler *sched, s
|
|||
n->state = n->callbacks->process_output(n->callbacks_data);
|
||||
debug("peer %p processed out %d\n", n, n->state);
|
||||
if (n->state == SPA_RESULT_NEED_BUFFER)
|
||||
spa_graph_scheduler_pull(sched, n);
|
||||
spa_graph_need_input(n->graph, n);
|
||||
else {
|
||||
spa_list_for_each(p, &n->ports[SPA_DIRECTION_OUTPUT], link) {
|
||||
if (p->io->status == SPA_RESULT_HAVE_BUFFER)
|
||||
|
|
@ -123,43 +112,14 @@ static inline void spa_graph_scheduler_pull(struct spa_graph_scheduler *sched, s
|
|||
}
|
||||
}
|
||||
}
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
||||
static inline bool spa_graph_scheduler_iterate(struct spa_graph_scheduler *sched)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline void spa_graph_scheduler_push(struct spa_graph_scheduler *sched, struct spa_graph_node *node);
|
||||
|
||||
static inline void spa_graph_scheduler_chain(struct spa_graph_scheduler *sched,
|
||||
struct spa_list *ready)
|
||||
{
|
||||
struct spa_graph_node *n, *t;
|
||||
struct spa_graph_port *p;
|
||||
|
||||
|
||||
spa_list_for_each_safe(n, t, ready, ready_link) {
|
||||
n->state = n->callbacks->process_input(n->callbacks_data);
|
||||
debug("node %p chain processed in %d\n", n, n->state);
|
||||
if (n->state == SPA_RESULT_HAVE_BUFFER)
|
||||
spa_graph_scheduler_push(sched, n);
|
||||
else {
|
||||
n->ready_in = 0;
|
||||
spa_list_for_each(p, &n->ports[SPA_DIRECTION_INPUT], link) {
|
||||
if (p->io->status == SPA_RESULT_OK && !(n->flags & SPA_GRAPH_NODE_FLAG_ASYNC))
|
||||
n->ready_in++;
|
||||
}
|
||||
}
|
||||
spa_list_remove(&n->ready_link);
|
||||
n->ready_link.next = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void spa_graph_scheduler_push(struct spa_graph_scheduler *sched, struct spa_graph_node *node)
|
||||
static inline int spa_graph_impl_have_output(void *data, struct spa_graph_node *node)
|
||||
{
|
||||
struct spa_graph_port *p;
|
||||
struct spa_list ready;
|
||||
struct spa_graph_node *n, *t;
|
||||
|
||||
debug("node %p start push\n", node);
|
||||
|
||||
|
|
@ -182,7 +142,22 @@ static inline void spa_graph_scheduler_push(struct spa_graph_scheduler *sched, s
|
|||
spa_list_append(&ready, &pnode->ready_link);
|
||||
}
|
||||
|
||||
spa_graph_scheduler_chain(sched, &ready);
|
||||
spa_list_for_each_safe(n, t, &ready, ready_link) {
|
||||
n->state = n->callbacks->process_input(n->callbacks_data);
|
||||
debug("node %p chain processed in %d\n", n, n->state);
|
||||
if (n->state == SPA_RESULT_HAVE_BUFFER)
|
||||
spa_graph_have_output(n->graph, n);
|
||||
else {
|
||||
n->ready_in = 0;
|
||||
spa_list_for_each(p, &n->ports[SPA_DIRECTION_INPUT], link) {
|
||||
if (p->io->status == SPA_RESULT_OK &&
|
||||
!(n->flags & SPA_GRAPH_NODE_FLAG_ASYNC))
|
||||
n->ready_in++;
|
||||
}
|
||||
}
|
||||
spa_list_remove(&n->ready_link);
|
||||
n->ready_link.next = NULL;
|
||||
}
|
||||
|
||||
node->state = node->callbacks->process_output(node->callbacks_data);
|
||||
debug("node %p processed out %d\n", node, node->state);
|
||||
|
|
@ -193,8 +168,16 @@ static inline void spa_graph_scheduler_push(struct spa_graph_scheduler *sched, s
|
|||
node->ready_in++;
|
||||
}
|
||||
}
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
||||
static const struct spa_graph_callbacks spa_graph_impl_default = {
|
||||
SPA_VERSION_GRAPH_CALLBACKS,
|
||||
.need_input = spa_graph_impl_need_input,
|
||||
.have_output = spa_graph_impl_have_output,
|
||||
};
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -40,10 +40,23 @@ struct spa_graph;
|
|||
struct spa_graph_node;
|
||||
struct spa_graph_port;
|
||||
|
||||
struct spa_graph_callbacks {
|
||||
#define SPA_VERSION_GRAPH_CALLBACKS 0
|
||||
uint32_t version;
|
||||
|
||||
int (*need_input) (void *data, struct spa_graph_node *node);
|
||||
int (*have_output) (void *data, struct spa_graph_node *node);
|
||||
};
|
||||
|
||||
struct spa_graph {
|
||||
struct spa_list nodes;
|
||||
const struct spa_graph_callbacks *callbacks;
|
||||
void *callbacks_data;
|
||||
};
|
||||
|
||||
#define spa_graph_need_input(g,n) ((g)->callbacks->need_input((g)->callbacks_data, (n)))
|
||||
#define spa_graph_have_output(g,n) ((g)->callbacks->have_output((g)->callbacks_data, (n)))
|
||||
|
||||
struct spa_graph_node_callbacks {
|
||||
#define SPA_VERSION_GRAPH_NODE_CALLBACKS 0
|
||||
uint32_t version;
|
||||
|
|
@ -61,6 +74,7 @@ struct spa_graph_port_callbacks {
|
|||
|
||||
struct spa_graph_node {
|
||||
struct spa_list link; /**< link in graph nodes list */
|
||||
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)
|
||||
|
|
@ -93,6 +107,15 @@ static inline void spa_graph_init(struct spa_graph *graph)
|
|||
spa_list_init(&graph->nodes);
|
||||
}
|
||||
|
||||
static inline void
|
||||
spa_graph_set_callbacks(struct spa_graph *graph,
|
||||
const struct spa_graph_callbacks *callbacks,
|
||||
void *data)
|
||||
{
|
||||
graph->callbacks = callbacks;
|
||||
graph->callbacks_data = data;
|
||||
}
|
||||
|
||||
static inline void
|
||||
spa_graph_node_init(struct spa_graph_node *node)
|
||||
{
|
||||
|
|
@ -116,6 +139,7 @@ static inline void
|
|||
spa_graph_node_add(struct spa_graph *graph,
|
||||
struct spa_graph_node *node)
|
||||
{
|
||||
node->graph = graph;
|
||||
node->state = SPA_RESULT_NEED_BUFFER;
|
||||
node->ready_link.next = NULL;
|
||||
spa_list_append(&graph->nodes, &node->link);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue