mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-04 13:30:12 -05:00
client-node: manage io areas
Manage the memory of io areas
This commit is contained in:
parent
76ed4e9468
commit
811ea2b1c9
1 changed files with 82 additions and 18 deletions
|
|
@ -47,6 +47,7 @@
|
||||||
|
|
||||||
#define MAX_BUFFERS 64
|
#define MAX_BUFFERS 64
|
||||||
#define MAX_AREAS 1024
|
#define MAX_AREAS 1024
|
||||||
|
#define MAX_IO 16
|
||||||
|
|
||||||
#define CHECK_IN_PORT_ID(this,d,p) ((d) == SPA_DIRECTION_INPUT && (p) < MAX_INPUTS)
|
#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)
|
#define CHECK_OUT_PORT_ID(this,d,p) ((d) == SPA_DIRECTION_OUTPUT && (p) < MAX_OUTPUTS)
|
||||||
|
|
@ -81,6 +82,11 @@ struct buffer {
|
||||||
uint32_t memid;
|
uint32_t memid;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct io {
|
||||||
|
uint32_t id;
|
||||||
|
uint32_t memid;
|
||||||
|
};
|
||||||
|
|
||||||
struct port {
|
struct port {
|
||||||
bool valid;
|
bool valid;
|
||||||
struct spa_port_info info;
|
struct spa_port_info info;
|
||||||
|
|
@ -89,10 +95,11 @@ struct port {
|
||||||
bool have_format;
|
bool have_format;
|
||||||
uint32_t n_params;
|
uint32_t n_params;
|
||||||
struct spa_pod **params;
|
struct spa_pod **params;
|
||||||
struct spa_io_buffers *io;
|
|
||||||
|
|
||||||
uint32_t n_buffers;
|
uint32_t n_buffers;
|
||||||
struct buffer buffers[MAX_BUFFERS];
|
struct buffer buffers[MAX_BUFFERS];
|
||||||
|
|
||||||
|
struct io ios[MAX_IO];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct node {
|
struct node {
|
||||||
|
|
@ -139,7 +146,6 @@ struct impl {
|
||||||
|
|
||||||
struct pw_map io_map;
|
struct pw_map io_map;
|
||||||
struct pw_memblock *io_areas;
|
struct pw_memblock *io_areas;
|
||||||
uint32_t io_memid;
|
|
||||||
|
|
||||||
struct spa_hook node_listener;
|
struct spa_hook node_listener;
|
||||||
struct spa_hook resource_listener;
|
struct spa_hook resource_listener;
|
||||||
|
|
@ -185,6 +191,53 @@ static struct mem *ensure_mem(struct impl *impl, int fd, uint32_t type, uint32_t
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void clear_io(struct node *node, struct io *io)
|
||||||
|
{
|
||||||
|
struct mem *m;
|
||||||
|
m = pw_array_get_unchecked(&node->impl->mems, io->memid, struct mem);
|
||||||
|
m->ref--;
|
||||||
|
io->id = SPA_ID_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct io *update_io(struct impl *impl, struct port *port, uint32_t id, uint32_t memid)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
struct io *io, *f = NULL;
|
||||||
|
|
||||||
|
for (i = 0; i < MAX_IO; i++) {
|
||||||
|
io = &port->ios[i];
|
||||||
|
if (io->id == SPA_ID_INVALID)
|
||||||
|
f = io;
|
||||||
|
else if (io->id == id) {
|
||||||
|
if (io->memid != memid) {
|
||||||
|
clear_io(&impl->node, io);
|
||||||
|
if (memid == SPA_ID_INVALID)
|
||||||
|
io->id = SPA_ID_INVALID;
|
||||||
|
}
|
||||||
|
goto found;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (f == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
io = f;
|
||||||
|
io->id = id;
|
||||||
|
io->memid = memid;
|
||||||
|
|
||||||
|
found:
|
||||||
|
return io;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void clear_ios(struct node *this, struct port *port)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < MAX_IO; i++) {
|
||||||
|
struct io *io = &port->ios[i];
|
||||||
|
if (io->id != SPA_ID_INVALID)
|
||||||
|
clear_io(this, io);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int clear_buffers(struct node *this, struct port *port)
|
static int clear_buffers(struct node *this, struct port *port)
|
||||||
{
|
{
|
||||||
|
|
@ -266,12 +319,12 @@ static int impl_node_set_param(struct spa_node *node, uint32_t id, uint32_t flag
|
||||||
return SPA_RESULT_RETURN_ASYNC(this->seq++);
|
return SPA_RESULT_RETURN_ASYNC(this->seq++);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void do_flush(struct node *this)
|
static inline void send_process(struct node *this)
|
||||||
{
|
{
|
||||||
uint64_t cmd = 1;
|
uint64_t cmd = 1;
|
||||||
|
pw_log_trace("client-node %p: send process", this);
|
||||||
if (write(this->writefd, &cmd, 8) != 8)
|
if (write(this->writefd, &cmd, 8) != 8)
|
||||||
spa_log_warn(this->log, "node %p: error flushing : %s", this, strerror(errno));
|
spa_log_warn(this->log, "node %p: error %s", this, strerror(errno));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int impl_node_send_command(struct spa_node *node, const struct spa_command *command)
|
static int impl_node_send_command(struct spa_node *node, const struct spa_command *command)
|
||||||
|
|
@ -384,12 +437,11 @@ do_update_port(struct node *this,
|
||||||
{
|
{
|
||||||
struct port *port;
|
struct port *port;
|
||||||
struct pw_type *t = this->impl->t;
|
struct pw_type *t = this->impl->t;
|
||||||
|
int i;
|
||||||
|
|
||||||
port = GET_PORT(this, direction, port_id);
|
port = GET_PORT(this, direction, port_id);
|
||||||
|
|
||||||
if (change_mask & PW_CLIENT_NODE_PORT_UPDATE_PARAMS) {
|
if (change_mask & PW_CLIENT_NODE_PORT_UPDATE_PARAMS) {
|
||||||
int i;
|
|
||||||
|
|
||||||
port->have_format = false;
|
port->have_format = false;
|
||||||
|
|
||||||
spa_log_info(this->log, "node %p: port %u update %d params", this, port_id, n_params);
|
spa_log_info(this->log, "node %p: port %u update %d params", this, port_id, n_params);
|
||||||
|
|
@ -425,6 +477,8 @@ do_update_port(struct node *this,
|
||||||
spa_log_info(this->log, "node %p: adding port %d", this, port_id);
|
spa_log_info(this->log, "node %p: adding port %d", this, port_id);
|
||||||
port->have_format = false;
|
port->have_format = false;
|
||||||
port->valid = true;
|
port->valid = true;
|
||||||
|
for (i = 0; i < MAX_IO; i++)
|
||||||
|
port->ios[i].id = SPA_ID_INVALID;
|
||||||
|
|
||||||
if (direction == SPA_DIRECTION_INPUT)
|
if (direction == SPA_DIRECTION_INPUT)
|
||||||
this->n_inputs++;
|
this->n_inputs++;
|
||||||
|
|
@ -443,6 +497,7 @@ clear_port(struct node *this,
|
||||||
PW_CLIENT_NODE_PORT_UPDATE_PARAMS |
|
PW_CLIENT_NODE_PORT_UPDATE_PARAMS |
|
||||||
PW_CLIENT_NODE_PORT_UPDATE_INFO, 0, NULL, NULL);
|
PW_CLIENT_NODE_PORT_UPDATE_INFO, 0, NULL, NULL);
|
||||||
clear_buffers(this, port);
|
clear_buffers(this, port);
|
||||||
|
clear_ios(this, port);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void do_uninit_port(struct node *this, enum spa_direction direction, uint32_t port_id)
|
static void do_uninit_port(struct node *this, enum spa_direction direction, uint32_t port_id)
|
||||||
|
|
@ -597,6 +652,7 @@ static int do_port_set_io(struct impl *impl,
|
||||||
struct pw_memblock *mem;
|
struct pw_memblock *mem;
|
||||||
struct mem *m;
|
struct mem *m;
|
||||||
uint32_t memid, mem_offset, mem_size;
|
uint32_t memid, mem_offset, mem_size;
|
||||||
|
struct port *port;
|
||||||
|
|
||||||
pw_log_debug("client-node %p: %s port %d.%d set io %p %zd", impl,
|
pw_log_debug("client-node %p: %s port %d.%d set io %p %zd", impl,
|
||||||
direction == SPA_DIRECTION_INPUT ? "input" : "output",
|
direction == SPA_DIRECTION_INPUT ? "input" : "output",
|
||||||
|
|
@ -608,6 +664,8 @@ static int do_port_set_io(struct impl *impl,
|
||||||
if (this->resource == NULL)
|
if (this->resource == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
port = GET_PORT(this, direction, port_id);
|
||||||
|
|
||||||
if (data) {
|
if (data) {
|
||||||
if ((mem = pw_memblock_find(data)) == NULL)
|
if ((mem = pw_memblock_find(data)) == NULL)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
@ -625,6 +683,7 @@ static int do_port_set_io(struct impl *impl,
|
||||||
memid = SPA_ID_INVALID;
|
memid = SPA_ID_INVALID;
|
||||||
mem_offset = mem_size = 0;
|
mem_offset = mem_size = 0;
|
||||||
}
|
}
|
||||||
|
update_io(impl, port, id, memid);
|
||||||
|
|
||||||
pw_client_node_resource_port_set_io(this->resource,
|
pw_client_node_resource_port_set_io(this->resource,
|
||||||
this->seq,
|
this->seq,
|
||||||
|
|
@ -805,7 +864,7 @@ impl_node_port_reuse_buffer(struct spa_node *node, uint32_t port_id, uint32_t bu
|
||||||
|
|
||||||
pw_client_node_transport_add_message(impl->transport, (struct pw_client_node_message *)
|
pw_client_node_transport_add_message(impl->transport, (struct pw_client_node_message *)
|
||||||
&PW_CLIENT_NODE_MESSAGE_PORT_REUSE_BUFFER_INIT(port_id, buffer_id));
|
&PW_CLIENT_NODE_MESSAGE_PORT_REUSE_BUFFER_INIT(port_id, buffer_id));
|
||||||
do_flush(this);
|
send_process(this);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -842,14 +901,14 @@ impl_node_port_send_command(struct spa_node *node,
|
||||||
static int impl_node_process(struct spa_node *node)
|
static int impl_node_process(struct spa_node *node)
|
||||||
{
|
{
|
||||||
struct node *this = SPA_CONTAINER_OF(node, struct node, node);
|
struct node *this = SPA_CONTAINER_OF(node, struct node, node);
|
||||||
uint64_t cmd = 1;
|
struct impl *impl = this->impl;
|
||||||
|
|
||||||
pw_log_trace("client-node %p: send process", this);
|
if (impl->this.node->driver)
|
||||||
|
return SPA_STATUS_HAVE_BUFFER;
|
||||||
if (write(this->writefd, &cmd, 8) != 8)
|
else {
|
||||||
spa_log_warn(this->log, "node %p: error flushing : %s", this, strerror(errno));
|
send_process(this);
|
||||||
|
return SPA_STATUS_OK;
|
||||||
return SPA_STATUS_OK;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -1091,7 +1150,6 @@ static void node_initialized(void *data)
|
||||||
struct pw_client_node *this = &impl->this;
|
struct pw_client_node *this = &impl->this;
|
||||||
struct pw_node *node = this->node;
|
struct pw_node *node = this->node;
|
||||||
struct pw_type *t = impl->t;
|
struct pw_type *t = impl->t;
|
||||||
struct mem *m;
|
|
||||||
|
|
||||||
if (this->resource == NULL)
|
if (this->resource == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
@ -1113,8 +1171,7 @@ static void node_initialized(void *data)
|
||||||
&impl->io_areas) < 0)
|
&impl->io_areas) < 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m = ensure_mem(impl, impl->io_areas->fd, t->data.MemFd, impl->io_areas->flags);
|
ensure_mem(impl, impl->io_areas->fd, t->data.MemFd, impl->io_areas->flags);
|
||||||
impl->io_memid = m->id;
|
|
||||||
pw_log_debug("client-node %p: io areas %p", node, impl->io_areas->ptr);
|
pw_log_debug("client-node %p: io areas %p", node, impl->io_areas->ptr);
|
||||||
|
|
||||||
pw_client_node_resource_transport(this->resource,
|
pw_client_node_resource_transport(this->resource,
|
||||||
|
|
@ -1218,11 +1275,18 @@ static void node_port_added(void *data, struct pw_port *port)
|
||||||
port->owner_data = impl;
|
port->owner_data = impl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void node_finish(void *data)
|
||||||
|
{
|
||||||
|
struct impl *impl = data;
|
||||||
|
send_process(&impl->node);
|
||||||
|
}
|
||||||
|
|
||||||
static const struct pw_node_events node_events = {
|
static const struct pw_node_events node_events = {
|
||||||
PW_VERSION_NODE_EVENTS,
|
PW_VERSION_NODE_EVENTS,
|
||||||
.free = node_free,
|
.free = node_free,
|
||||||
.initialized = node_initialized,
|
.initialized = node_initialized,
|
||||||
.port_added = node_port_added,
|
.port_added = node_port_added,
|
||||||
|
.finish = node_finish,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct pw_resource_events resource_events = {
|
static const struct pw_resource_events resource_events = {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue