mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-01 22:58:50 -04:00
spa: allocate ports dynamically
So that we don't need to allocate large memory blocks that are mostly unused. See #1840
This commit is contained in:
parent
3f87741b27
commit
2ed62f53d9
5 changed files with 107 additions and 44 deletions
|
|
@ -118,7 +118,7 @@ struct impl {
|
|||
|
||||
uint32_t port_count;
|
||||
uint32_t last_port;
|
||||
struct port in_ports[MAX_PORTS];
|
||||
struct port *in_ports[MAX_PORTS];
|
||||
struct port out_ports[1];
|
||||
|
||||
int n_formats;
|
||||
|
|
@ -133,11 +133,12 @@ struct impl {
|
|||
|
||||
};
|
||||
|
||||
#define CHECK_FREE_IN_PORT(this,d,p) ((d) == SPA_DIRECTION_INPUT && (p) < MAX_PORTS && !this->in_ports[(p)].valid)
|
||||
#define CHECK_IN_PORT(this,d,p) ((d) == SPA_DIRECTION_INPUT && (p) < MAX_PORTS && this->in_ports[(p)].valid)
|
||||
#define PORT_VALID(p) ((p) != NULL && (p)->valid)
|
||||
#define CHECK_FREE_IN_PORT(this,d,p) ((d) == SPA_DIRECTION_INPUT && (p) < MAX_PORTS && !PORT_VALID(this->in_ports[(p)]))
|
||||
#define CHECK_IN_PORT(this,d,p) ((d) == SPA_DIRECTION_INPUT && (p) < MAX_PORTS && PORT_VALID(this->in_ports[(p)]))
|
||||
#define CHECK_OUT_PORT(this,d,p) ((d) == SPA_DIRECTION_OUTPUT && (p) == 0)
|
||||
#define CHECK_PORT(this,d,p) (CHECK_OUT_PORT(this,d,p) || CHECK_IN_PORT (this,d,p))
|
||||
#define GET_IN_PORT(this,p) (&this->in_ports[p])
|
||||
#define GET_IN_PORT(this,p) (this->in_ports[p])
|
||||
#define GET_OUT_PORT(this,p) (&this->out_ports[p])
|
||||
#define GET_PORT(this,d,p) (d == SPA_DIRECTION_INPUT ? GET_IN_PORT(this,p) : GET_OUT_PORT(this,p))
|
||||
|
||||
|
|
@ -218,7 +219,7 @@ static int impl_node_add_listener(void *object,
|
|||
emit_node_info(this, true);
|
||||
emit_port_info(this, GET_OUT_PORT(this, 0), true);
|
||||
for (i = 0; i < this->last_port; i++) {
|
||||
if (this->in_ports[i].valid)
|
||||
if (PORT_VALID(this->in_ports[i]))
|
||||
emit_port_info(this, GET_IN_PORT(this, i), true);
|
||||
}
|
||||
|
||||
|
|
@ -245,6 +246,12 @@ static int impl_node_add_port(void *object, enum spa_direction direction, uint32
|
|||
spa_return_val_if_fail(CHECK_FREE_IN_PORT(this, direction, port_id), -EINVAL);
|
||||
|
||||
port = GET_IN_PORT(this, port_id);
|
||||
if (port == NULL) {
|
||||
port = calloc(1, sizeof(struct port));
|
||||
if (port == NULL)
|
||||
return -errno;
|
||||
this->in_ports[port_id] = port;
|
||||
}
|
||||
port->direction = SPA_DIRECTION_INPUT;
|
||||
port->id = port_id;
|
||||
|
||||
|
|
@ -301,7 +308,7 @@ impl_node_remove_port(void *object, enum spa_direction direction, uint32_t port_
|
|||
int i;
|
||||
|
||||
for (i = this->last_port - 1; i >= 0; i--)
|
||||
if (GET_IN_PORT (this, i)->valid)
|
||||
if (PORT_VALID(GET_IN_PORT(this, i)))
|
||||
break;
|
||||
|
||||
this->last_port = i + 1;
|
||||
|
|
@ -749,13 +756,13 @@ static int impl_node_process(void *object)
|
|||
struct spa_io_buffers *inio = NULL;
|
||||
struct buffer *inb;
|
||||
|
||||
if (SPA_UNLIKELY(!inport->valid ||
|
||||
if (SPA_UNLIKELY(!PORT_VALID(inport) ||
|
||||
(inio = inport->io) == NULL ||
|
||||
inio->buffer_id >= inport->n_buffers ||
|
||||
inio->status != SPA_STATUS_HAVE_DATA)) {
|
||||
spa_log_trace_fp(this->log, "%p: skip input idx:%d valid:%d "
|
||||
"io:%p status:%d buf_id:%d n_buffers:%d", this,
|
||||
i, inport->valid, inio,
|
||||
i, PORT_VALID(inport), inio,
|
||||
inio ? inio->status : -1,
|
||||
inio ? inio->buffer_id : SPA_ID_INVALID,
|
||||
inport->n_buffers);
|
||||
|
|
@ -841,11 +848,14 @@ static int impl_get_interface(struct spa_handle *handle, const char *type, void
|
|||
static int impl_clear(struct spa_handle *handle)
|
||||
{
|
||||
struct impl *this;
|
||||
uint32_t i;
|
||||
|
||||
spa_return_val_if_fail(handle != NULL, -EINVAL);
|
||||
|
||||
this = (struct impl *) handle;
|
||||
|
||||
for (i = 0; i < MAX_PORTS; i++)
|
||||
free(this->in_ports[i]);
|
||||
mix_ops_free(&this->ops);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -117,7 +117,7 @@ struct impl {
|
|||
|
||||
uint32_t port_count;
|
||||
uint32_t last_port;
|
||||
struct port in_ports[MAX_PORTS];
|
||||
struct port *in_ports[MAX_PORTS];
|
||||
struct port out_ports[1];
|
||||
|
||||
int n_formats;
|
||||
|
|
@ -130,11 +130,12 @@ struct impl {
|
|||
float empty[MAX_SAMPLES + MAX_ALIGN];
|
||||
};
|
||||
|
||||
#define CHECK_FREE_IN_PORT(this,d,p) ((d) == SPA_DIRECTION_INPUT && (p) < MAX_PORTS && !this->in_ports[(p)].valid)
|
||||
#define CHECK_IN_PORT(this,d,p) ((d) == SPA_DIRECTION_INPUT && (p) < MAX_PORTS && this->in_ports[(p)].valid)
|
||||
#define PORT_VALID(p) ((p) != NULL && (p)->valid)
|
||||
#define CHECK_FREE_IN_PORT(this,d,p) ((d) == SPA_DIRECTION_INPUT && (p) < MAX_PORTS && !PORT_VALID(this->in_ports[(p)]))
|
||||
#define CHECK_IN_PORT(this,d,p) ((d) == SPA_DIRECTION_INPUT && (p) < MAX_PORTS && PORT_VALID(this->in_ports[(p)]))
|
||||
#define CHECK_OUT_PORT(this,d,p) ((d) == SPA_DIRECTION_OUTPUT && (p) == 0)
|
||||
#define CHECK_PORT(this,d,p) (CHECK_OUT_PORT(this,d,p) || CHECK_IN_PORT (this,d,p))
|
||||
#define GET_IN_PORT(this,p) (&this->in_ports[p])
|
||||
#define GET_IN_PORT(this,p) (this->in_ports[p])
|
||||
#define GET_OUT_PORT(this,p) (&this->out_ports[p])
|
||||
#define GET_PORT(this,d,p) (d == SPA_DIRECTION_INPUT ? GET_IN_PORT(this,p) : GET_OUT_PORT(this,p))
|
||||
|
||||
|
|
@ -215,7 +216,7 @@ static int impl_node_add_listener(void *object,
|
|||
emit_node_info(this, true);
|
||||
emit_port_info(this, GET_OUT_PORT(this, 0), true);
|
||||
for (i = 0; i < this->last_port; i++) {
|
||||
if (this->in_ports[i].valid)
|
||||
if (PORT_VALID(this->in_ports[i]))
|
||||
emit_port_info(this, GET_IN_PORT(this, i), true);
|
||||
}
|
||||
|
||||
|
|
@ -242,6 +243,13 @@ static int impl_node_add_port(void *object, enum spa_direction direction, uint32
|
|||
spa_return_val_if_fail(CHECK_FREE_IN_PORT(this, direction, port_id), -EINVAL);
|
||||
|
||||
port = GET_IN_PORT (this, port_id);
|
||||
if (port == NULL) {
|
||||
port = calloc(1, sizeof(struct port));
|
||||
if (port == NULL)
|
||||
return -errno;
|
||||
this->in_ports[port_id] = port;
|
||||
}
|
||||
|
||||
port->direction = direction;
|
||||
port->id = port_id;
|
||||
|
||||
|
|
@ -298,7 +306,7 @@ impl_node_remove_port(void *object, enum spa_direction direction, uint32_t port_
|
|||
int i;
|
||||
|
||||
for (i = this->last_port - 1; i >= 0; i--)
|
||||
if (GET_IN_PORT (this, i)->valid)
|
||||
if (PORT_VALID(GET_IN_PORT(this, i)))
|
||||
break;
|
||||
|
||||
this->last_port = i + 1;
|
||||
|
|
@ -695,13 +703,13 @@ static int impl_node_process(void *object)
|
|||
struct spa_io_buffers *inio = NULL;
|
||||
struct buffer *inb;
|
||||
|
||||
if (SPA_UNLIKELY(!inport->valid ||
|
||||
if (SPA_UNLIKELY(!PORT_VALID(inport) ||
|
||||
(inio = inport->io) == NULL ||
|
||||
inio->buffer_id >= inport->n_buffers ||
|
||||
inio->status != SPA_STATUS_HAVE_DATA)) {
|
||||
spa_log_trace_fp(this->log, "%p: skip input idx:%d valid:%d "
|
||||
"io:%p status:%d buf_id:%d n_buffers:%d", this,
|
||||
i, inport->valid, inio,
|
||||
i, PORT_VALID(inport), inio,
|
||||
inio ? inio->status : -1,
|
||||
inio ? inio->buffer_id : SPA_ID_INVALID,
|
||||
inport->n_buffers);
|
||||
|
|
@ -785,6 +793,15 @@ static int impl_get_interface(struct spa_handle *handle, const char *type, void
|
|||
|
||||
static int impl_clear(struct spa_handle *handle)
|
||||
{
|
||||
struct impl *this;
|
||||
uint32_t i;
|
||||
|
||||
spa_return_val_if_fail(handle != NULL, -EINVAL);
|
||||
|
||||
this = (struct impl *) handle;
|
||||
|
||||
for (i = 0; i < MAX_PORTS; i++)
|
||||
free(this->in_ports[i]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue