mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-04 13:30:12 -05:00
make per mix port io and buffers
Move the io areas to a separate memory block. Make per link io areas for the ports Send per mix port io area and buffers
This commit is contained in:
parent
07f12c9713
commit
4f680c224b
11 changed files with 242 additions and 161 deletions
|
|
@ -42,10 +42,11 @@
|
|||
|
||||
/** \cond */
|
||||
|
||||
#define MAX_INPUTS 64
|
||||
#define MAX_OUTPUTS 64
|
||||
#define MAX_INPUTS 64
|
||||
#define MAX_OUTPUTS 64
|
||||
|
||||
#define MAX_BUFFERS 64
|
||||
#define MAX_BUFFERS 64
|
||||
#define MAX_AREAS 1024
|
||||
|
||||
#define CHECK_IN_PORT_ID(this,d,p) ((d) == SPA_DIRECTION_INPUT && (p) < MAX_INPUTS)
|
||||
#define CHECK_OUT_PORT_ID(this,d,p) ((d) == SPA_DIRECTION_OUTPUT && (p) < MAX_OUTPUTS)
|
||||
|
|
@ -136,6 +137,9 @@ struct impl {
|
|||
|
||||
struct pw_client_node_transport *transport;
|
||||
|
||||
struct pw_memblock *io_areas;
|
||||
uint32_t io_memid;
|
||||
|
||||
struct spa_hook node_listener;
|
||||
struct spa_hook resource_listener;
|
||||
|
||||
|
|
@ -593,52 +597,7 @@ impl_node_port_set_io(struct spa_node *node,
|
|||
uint32_t id,
|
||||
void *data, size_t size)
|
||||
{
|
||||
struct node *this;
|
||||
struct impl *impl;
|
||||
struct pw_type *t;
|
||||
struct pw_memblock *mem;
|
||||
struct mem *m;
|
||||
uint32_t memid, mem_offset, mem_size;
|
||||
|
||||
if (node == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
this = SPA_CONTAINER_OF(node, struct node, node);
|
||||
impl = this->impl;
|
||||
t = impl->t;
|
||||
|
||||
if (this->resource == NULL)
|
||||
return 0;
|
||||
|
||||
if (!CHECK_PORT(this, direction, port_id))
|
||||
return -EINVAL;
|
||||
|
||||
if (data) {
|
||||
if ((mem = pw_memblock_find(data)) == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
mem_offset = SPA_PTRDIFF(data, mem->ptr);
|
||||
mem_size = mem->size;
|
||||
if (mem_size - mem_offset < size)
|
||||
return -EINVAL;
|
||||
|
||||
mem_offset += mem->offset;
|
||||
m = ensure_mem(impl, mem->fd, t->data.MemFd, mem->flags);
|
||||
memid = m->id;
|
||||
}
|
||||
else {
|
||||
memid = SPA_ID_INVALID;
|
||||
mem_offset = mem_size = 0;
|
||||
}
|
||||
|
||||
pw_client_node_resource_port_set_io(this->resource,
|
||||
this->seq,
|
||||
direction, port_id,
|
||||
id,
|
||||
memid,
|
||||
mem_offset, mem_size);
|
||||
|
||||
return SPA_RESULT_RETURN_ASYNC(this->seq++);
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
@ -750,7 +709,7 @@ impl_node_port_use_buffers(struct spa_node *node,
|
|||
|
||||
pw_client_node_resource_port_use_buffers(this->resource,
|
||||
this->seq,
|
||||
direction, port_id,
|
||||
direction, port_id, 0,
|
||||
n_buffers, mb);
|
||||
|
||||
return SPA_RESULT_RETURN_ASYNC(this->seq++);
|
||||
|
|
@ -855,7 +814,6 @@ static int impl_node_process_input(struct spa_node *node)
|
|||
struct spa_io_buffers *io = p->io;
|
||||
|
||||
pw_log_trace("set io status to %d %d", io->status, io->buffer_id);
|
||||
impl->transport->inputs[p->port_id] = *io;
|
||||
|
||||
/* explicitly recycle buffers when the client is not going to do it */
|
||||
if (!client_reuse && (pp = p->peer))
|
||||
|
|
@ -876,29 +834,10 @@ static int impl_node_process_output(struct spa_node *node)
|
|||
{
|
||||
struct node *this;
|
||||
struct impl *impl;
|
||||
struct spa_graph_node *n;
|
||||
struct spa_graph_port *p;
|
||||
|
||||
this = SPA_CONTAINER_OF(node, struct node, node);
|
||||
impl = this->impl;
|
||||
n = &impl->this.node->rt.node;
|
||||
|
||||
if (impl->out_pending)
|
||||
goto done;
|
||||
|
||||
impl->out_pending = true;
|
||||
|
||||
spa_list_for_each(p, &n->ports[SPA_DIRECTION_OUTPUT], link) {
|
||||
struct spa_io_buffers *io = p->io;
|
||||
|
||||
impl->transport->outputs[p->port_id] = *io;
|
||||
|
||||
pw_log_trace("%d %d -> %d %d", io->status, io->buffer_id,
|
||||
impl->transport->outputs[p->port_id].status,
|
||||
impl->transport->outputs[p->port_id].buffer_id);
|
||||
}
|
||||
|
||||
done:
|
||||
pw_client_node_transport_add_message(impl->transport,
|
||||
&PW_CLIENT_NODE_MESSAGE_INIT(PW_CLIENT_NODE_MESSAGE_PROCESS_OUTPUT));
|
||||
do_flush(this);
|
||||
|
|
@ -916,18 +855,15 @@ static int handle_node_message(struct node *this, struct pw_client_node_message
|
|||
|
||||
switch (PW_CLIENT_NODE_MESSAGE_TYPE(message)) {
|
||||
case PW_CLIENT_NODE_MESSAGE_HAVE_OUTPUT:
|
||||
spa_list_for_each(p, &n->ports[SPA_DIRECTION_OUTPUT], link) {
|
||||
*p->io = impl->transport->outputs[p->port_id];
|
||||
pw_log_trace("have output %d %d", p->io->status, p->io->buffer_id);
|
||||
}
|
||||
impl->out_pending = false;
|
||||
this->callbacks->have_output(this->callbacks_data);
|
||||
break;
|
||||
|
||||
case PW_CLIENT_NODE_MESSAGE_NEED_INPUT:
|
||||
spa_list_for_each(p, &n->ports[SPA_DIRECTION_INPUT], link) {
|
||||
*p->io = impl->transport->inputs[p->port_id];
|
||||
pw_log_trace("need input %d %d", p->io->status, p->io->buffer_id);
|
||||
spa_list_for_each(p, &n->ports[SPA_DIRECTION_OUTPUT], link) {
|
||||
struct spa_graph_node *ni = p->peer->node;
|
||||
spa_node_process_output(ni->implementation);
|
||||
pw_log_trace("need input %p %d %d", p->io, p->io->status, p->io->buffer_id);
|
||||
}
|
||||
impl->input_ready++;
|
||||
this->callbacks->need_input(this->callbacks_data);
|
||||
|
|
@ -1205,6 +1141,8 @@ static void node_initialized(void *data)
|
|||
struct impl *impl = data;
|
||||
struct pw_client_node *this = &impl->this;
|
||||
struct pw_node *node = this->node;
|
||||
struct pw_type *t = impl->t;
|
||||
struct mem *m;
|
||||
|
||||
if (this->resource == NULL)
|
||||
return;
|
||||
|
|
@ -1219,6 +1157,16 @@ static void node_initialized(void *data)
|
|||
spa_loop_add_source(impl->node.data_loop, &impl->node.data_source);
|
||||
pw_log_debug("client-node %p: transport fd %d %d", node, impl->fds[0], impl->fds[1]);
|
||||
|
||||
if (pw_memblock_alloc(PW_MEMBLOCK_FLAG_WITH_FD |
|
||||
PW_MEMBLOCK_FLAG_MAP_READWRITE |
|
||||
PW_MEMBLOCK_FLAG_SEAL,
|
||||
sizeof(struct spa_io_buffers) * MAX_AREAS,
|
||||
&impl->io_areas) < 0)
|
||||
return;
|
||||
|
||||
m = ensure_mem(impl, impl->io_areas->fd, t->data.MemFd, impl->io_areas->flags);
|
||||
impl->io_memid = m->id;
|
||||
|
||||
pw_client_node_resource_transport(this->resource,
|
||||
pw_global_get_id(pw_node_get_global(node)),
|
||||
impl->other_fds[0],
|
||||
|
|
@ -1247,10 +1195,98 @@ static void node_free(void *data)
|
|||
free(impl);
|
||||
}
|
||||
|
||||
static void *port_get_io(void *data, uint32_t id, size_t size)
|
||||
{
|
||||
struct impl *impl = data;
|
||||
|
||||
return impl->io_areas->ptr;
|
||||
}
|
||||
|
||||
static const struct pw_port_implementation port_impl = {
|
||||
PW_VERSION_PORT_IMPLEMENTATION,
|
||||
.get_io = port_get_io,
|
||||
};
|
||||
|
||||
static int mix_port_set_io(struct spa_node *node,
|
||||
enum spa_direction direction, uint32_t port_id,
|
||||
uint32_t id, void *data, size_t size)
|
||||
{
|
||||
struct pw_port *p = SPA_CONTAINER_OF(node, struct pw_port, mix_node);
|
||||
struct impl *impl = p->owner_data;
|
||||
struct node *this = &impl->node;
|
||||
struct pw_type *t = impl->t;
|
||||
struct pw_memblock *mem;
|
||||
struct mem *m;
|
||||
uint32_t memid, mem_offset, mem_size;
|
||||
|
||||
pw_log_debug("client-node %p: mix port %d set io %p, %zd", impl, port_id, data, size);
|
||||
|
||||
p->rt.port.io = data;
|
||||
p->rt.mix_port.io = data;
|
||||
|
||||
if (this->resource == NULL)
|
||||
return 0;
|
||||
|
||||
if (!CHECK_PORT(this, direction, port_id))
|
||||
return -EINVAL;
|
||||
|
||||
if (data) {
|
||||
if ((mem = pw_memblock_find(data)) == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
mem_offset = mem->offset;
|
||||
mem_size = mem->size;
|
||||
if (mem_size - mem_offset < size)
|
||||
return -EINVAL;
|
||||
|
||||
m = ensure_mem(impl, mem->fd, t->data.MemFd, mem->flags);
|
||||
memid = m->id;
|
||||
}
|
||||
else {
|
||||
memid = SPA_ID_INVALID;
|
||||
mem_offset = mem_size = 0;
|
||||
}
|
||||
|
||||
pw_client_node_resource_port_set_io(this->resource,
|
||||
this->seq,
|
||||
direction, port_id, 0,
|
||||
id,
|
||||
memid,
|
||||
mem_offset, mem_size);
|
||||
|
||||
return SPA_RESULT_RETURN_ASYNC(this->seq++);
|
||||
}
|
||||
|
||||
static int mix_port_process_input(struct spa_node *data)
|
||||
{
|
||||
return SPA_STATUS_HAVE_BUFFER;
|
||||
}
|
||||
|
||||
static int mix_port_process_output(struct spa_node *data)
|
||||
{
|
||||
return SPA_STATUS_NEED_BUFFER;
|
||||
}
|
||||
|
||||
static void node_port_added(void *data, struct pw_port *port)
|
||||
{
|
||||
struct impl *impl = data;
|
||||
|
||||
pw_log_debug("client-node %p: port added", &impl->this);
|
||||
port->mix_node.port_set_io = mix_port_set_io;
|
||||
port->mix_node.process_input = mix_port_process_input;
|
||||
port->mix_node.process_output = mix_port_process_output;
|
||||
|
||||
port->implementation = &port_impl;
|
||||
port->implementation_data = impl;
|
||||
|
||||
port->owner_data = impl;
|
||||
}
|
||||
|
||||
static const struct pw_node_events node_events = {
|
||||
PW_VERSION_NODE_EVENTS,
|
||||
.free = node_free,
|
||||
.initialized = node_initialized,
|
||||
.port_added = node_port_added,
|
||||
};
|
||||
|
||||
static const struct pw_resource_events resource_events = {
|
||||
|
|
|
|||
|
|
@ -333,7 +333,7 @@ static int client_node_demarshal_port_use_buffers(void *object, void *data, size
|
|||
{
|
||||
struct pw_proxy *proxy = object;
|
||||
struct spa_pod_parser prs;
|
||||
uint32_t seq, direction, port_id, n_buffers, data_id;
|
||||
uint32_t seq, direction, port_id, mix_id, n_buffers, data_id;
|
||||
struct pw_client_node_buffer *buffers;
|
||||
int i, j;
|
||||
|
||||
|
|
@ -343,6 +343,7 @@ static int client_node_demarshal_port_use_buffers(void *object, void *data, size
|
|||
"i", &seq,
|
||||
"i", &direction,
|
||||
"i", &port_id,
|
||||
"i", &mix_id,
|
||||
"i", &n_buffers, NULL) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
|
|
@ -388,6 +389,7 @@ static int client_node_demarshal_port_use_buffers(void *object, void *data, size
|
|||
pw_proxy_notify(proxy, struct pw_client_node_proxy_events, port_use_buffers, seq,
|
||||
direction,
|
||||
port_id,
|
||||
mix_id,
|
||||
n_buffers, buffers);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -417,7 +419,7 @@ static int client_node_demarshal_port_set_io(void *object, void *data, size_t si
|
|||
{
|
||||
struct pw_proxy *proxy = object;
|
||||
struct spa_pod_parser prs;
|
||||
uint32_t seq, direction, port_id, id, memid, off, sz;
|
||||
uint32_t seq, direction, port_id, mix_id, id, memid, off, sz;
|
||||
|
||||
spa_pod_parser_init(&prs, data, size, 0);
|
||||
if (spa_pod_parser_get(&prs,
|
||||
|
|
@ -425,6 +427,7 @@ static int client_node_demarshal_port_set_io(void *object, void *data, size_t si
|
|||
"i", &seq,
|
||||
"i", &direction,
|
||||
"i", &port_id,
|
||||
"i", &mix_id,
|
||||
"I", &id,
|
||||
"i", &memid,
|
||||
"i", &off,
|
||||
|
|
@ -433,7 +436,7 @@ static int client_node_demarshal_port_set_io(void *object, void *data, size_t si
|
|||
|
||||
pw_proxy_notify(proxy, struct pw_client_node_proxy_events, port_set_io,
|
||||
seq,
|
||||
direction, port_id,
|
||||
direction, port_id, mix_id,
|
||||
id, memid,
|
||||
off, sz);
|
||||
return 0;
|
||||
|
|
@ -588,6 +591,7 @@ client_node_marshal_port_use_buffers(void *object,
|
|||
uint32_t seq,
|
||||
enum spa_direction direction,
|
||||
uint32_t port_id,
|
||||
uint32_t mix_id,
|
||||
uint32_t n_buffers, struct pw_client_node_buffer *buffers)
|
||||
{
|
||||
struct pw_resource *resource = object;
|
||||
|
|
@ -601,6 +605,7 @@ client_node_marshal_port_use_buffers(void *object,
|
|||
"i", seq,
|
||||
"i", direction,
|
||||
"i", port_id,
|
||||
"i", mix_id,
|
||||
"i", n_buffers, NULL);
|
||||
|
||||
for (i = 0; i < n_buffers; i++) {
|
||||
|
|
@ -659,6 +664,7 @@ client_node_marshal_port_set_io(void *object,
|
|||
uint32_t seq,
|
||||
uint32_t direction,
|
||||
uint32_t port_id,
|
||||
uint32_t mix_id,
|
||||
uint32_t id,
|
||||
uint32_t memid,
|
||||
uint32_t offset,
|
||||
|
|
@ -673,6 +679,7 @@ client_node_marshal_port_set_io(void *object,
|
|||
"i", seq,
|
||||
"i", direction,
|
||||
"i", port_id,
|
||||
"i", mix_id,
|
||||
"I", id,
|
||||
"i", memid,
|
||||
"i", offset,
|
||||
|
|
|
|||
|
|
@ -48,8 +48,6 @@ static size_t area_get_size(struct pw_client_node_area *area)
|
|||
{
|
||||
size_t size;
|
||||
size = sizeof(struct pw_client_node_area);
|
||||
size += area->max_input_ports * sizeof(struct spa_io_buffers);
|
||||
size += area->max_output_ports * sizeof(struct spa_io_buffers);
|
||||
size += sizeof(struct spa_ringbuffer);
|
||||
size += INPUT_BUFFER_SIZE;
|
||||
size += sizeof(struct spa_ringbuffer);
|
||||
|
|
@ -64,12 +62,6 @@ static void transport_setup_area(void *p, struct pw_client_node_transport *trans
|
|||
trans->area = a = p;
|
||||
p = SPA_MEMBER(p, sizeof(struct pw_client_node_area), struct spa_io_buffers);
|
||||
|
||||
trans->inputs = p;
|
||||
p = SPA_MEMBER(p, a->max_input_ports * sizeof(struct spa_io_buffers), void);
|
||||
|
||||
trans->outputs = p;
|
||||
p = SPA_MEMBER(p, a->max_output_ports * sizeof(struct spa_io_buffers), void);
|
||||
|
||||
trans->input_buffer = p;
|
||||
p = SPA_MEMBER(p, sizeof(struct spa_ringbuffer), void);
|
||||
|
||||
|
|
@ -85,17 +77,6 @@ static void transport_setup_area(void *p, struct pw_client_node_transport *trans
|
|||
|
||||
static void transport_reset_area(struct pw_client_node_transport *trans)
|
||||
{
|
||||
int i;
|
||||
struct pw_client_node_area *a = trans->area;
|
||||
|
||||
for (i = 0; i < a->max_input_ports; i++) {
|
||||
trans->inputs[i].status = SPA_STATUS_OK;
|
||||
trans->inputs[i].buffer_id = SPA_ID_INVALID;
|
||||
}
|
||||
for (i = 0; i < a->max_output_ports; i++) {
|
||||
trans->outputs[i].status = SPA_STATUS_OK;
|
||||
trans->outputs[i].buffer_id = SPA_ID_INVALID;
|
||||
}
|
||||
spa_ringbuffer_init(trans->input_buffer);
|
||||
spa_ringbuffer_init(trans->output_buffer);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue