audioconvert: mark ports and buffers as DYNAMIC

Only passthrough buffer data when the buffer and ports are
marked as DYNAMIC.
Use extra buffer for nodes that keep a ref on buffers (resample).
This commit is contained in:
Wim Taymans 2019-03-21 10:45:24 +01:00
parent df5c81e3be
commit 036ca89c0e
11 changed files with 81 additions and 39 deletions

View file

@ -56,9 +56,10 @@ struct link {
uint32_t in_port; uint32_t in_port;
uint32_t in_flags; uint32_t in_flags;
struct spa_io_buffers io; struct spa_io_buffers io;
bool negotiated; uint32_t min_buffers;
uint32_t n_buffers; uint32_t n_buffers;
struct spa_buffer **buffers; struct spa_buffer **buffers;
int negotiated:1;
}; };
struct impl { struct impl {
@ -94,21 +95,21 @@ struct impl {
static int make_link(struct impl *this, static int make_link(struct impl *this,
struct spa_node *out_node, uint32_t out_port, struct spa_node *out_node, uint32_t out_port,
struct spa_node *in_node, uint32_t in_port, struct spa_node *in_node, uint32_t in_port, uint32_t min_buffers)
struct spa_audio_info *info)
{ {
struct link *l = &this->links[this->n_links++]; struct link *l = &this->links[this->n_links++];
l->out_node = out_node; l->out_node = out_node;
l->out_port = out_port; l->out_port = out_port;
l->out_flags = 0;
l->in_node = in_node; l->in_node = in_node;
l->in_port = in_port; l->in_port = in_port;
l->in_flags = 0;
l->negotiated = false; l->negotiated = false;
l->io.status = SPA_STATUS_NEED_BUFFER; l->io.status = SPA_STATUS_NEED_BUFFER;
l->io.buffer_id = SPA_ID_INVALID; l->io.buffer_id = SPA_ID_INVALID;
l->n_buffers = 0; l->n_buffers = 0;
l->out_flags = 0; l->min_buffers = min_buffers;
l->in_flags = 0;
spa_node_port_set_io(out_node, spa_node_port_set_io(out_node,
SPA_DIRECTION_OUTPUT, out_port, SPA_DIRECTION_OUTPUT, out_port,
@ -238,8 +239,9 @@ static int setup_convert(struct impl *this)
/* pack */ /* pack */
this->nodes[this->n_nodes++] = this->fmt[SPA_DIRECTION_OUTPUT]; this->nodes[this->n_nodes++] = this->fmt[SPA_DIRECTION_OUTPUT];
for (i = 0; i < this->n_nodes - 1; i++) make_link(this, this->nodes[0], 0, this->nodes[1], 0, 2);
make_link(this, this->nodes[i], 0, this->nodes[i+1], 0, NULL); make_link(this, this->nodes[1], 0, this->nodes[2], 0, 2);
make_link(this, this->nodes[2], 0, this->nodes[3], 0, 1);
for (i = 0, j = this->n_links - 1; j >= i; i++, j--) { for (i = 0, j = this->n_links - 1; j >= i; i++, j--) {
spa_log_debug(this->log, "negotiate %d", i); spa_log_debug(this->log, "negotiate %d", i);
@ -258,9 +260,9 @@ static int negotiate_link_buffers(struct impl *this, struct link *link)
struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer)); struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer));
uint32_t state; uint32_t state;
struct spa_pod *param = NULL; struct spa_pod *param = NULL;
int res, i; int res;
bool in_alloc, out_alloc; bool in_alloc, out_alloc;
int32_t size, buffers, blocks, align, flags; uint32_t i, size, buffers, blocks, align, flags;
uint32_t *aligns; uint32_t *aligns;
struct spa_data *datas; struct spa_data *datas;
@ -316,10 +318,13 @@ static int negotiate_link_buffers(struct impl *this, struct link *link)
aligns = alloca(sizeof(uint32_t) * blocks); aligns = alloca(sizeof(uint32_t) * blocks);
for (i = 0; i < blocks; i++) { for (i = 0; i < blocks; i++) {
datas[i].type = SPA_DATA_MemPtr; datas[i].type = SPA_DATA_MemPtr;
datas[i].flags = SPA_DATA_FLAG_DYNAMIC;
datas[i].maxsize = size; datas[i].maxsize = size;
aligns[i] = align; aligns[i] = align;
} }
buffers = SPA_MAX(link->min_buffers, buffers);
if (link->buffers) if (link->buffers)
free(link->buffers); free(link->buffers);
link->buffers = spa_buffer_alloc_array(buffers, flags, 0, NULL, blocks, datas, aligns); link->buffers = spa_buffer_alloc_array(buffers, flags, 0, NULL, blocks, datas, aligns);

View file

@ -111,12 +111,13 @@ struct impl {
struct props props; struct props props;
struct spa_param_info params[8]; struct spa_param_info params[8];
bool started;
struct port in_port; struct port in_port;
struct port out_port; struct port out_port;
channelmix_func_t convert; channelmix_func_t convert;
int started:1;
int is_passthrough:1;
uint32_t cpu_flags; uint32_t cpu_flags;
uint32_t n_matrix; uint32_t n_matrix;
float matrix[4096]; float matrix[4096];
@ -375,9 +376,13 @@ static int make_matrix(struct impl *this,
max = SPA_MAX(max, sum); max = SPA_MAX(max, sum);
} }
this->n_matrix = c; this->n_matrix = c;
this->is_passthrough = dst_chan == src_chan;
for (i = 0; i < dst_chan; i++) { for (i = 0; i < dst_chan; i++) {
for (j = 0; j < src_chan; j++) { for (j = 0; j < src_chan; j++) {
spa_log_debug(this->log, "%d %d: %f", i, j, this->matrix[i * src_chan + j]); float v = this->matrix[i * src_chan + j];
spa_log_debug(this->log, "%d %d: %f", i, j, v);
if (i == j && v != 1.0f)
this->is_passthrough = false;
} }
} }
@ -959,6 +964,9 @@ impl_node_port_use_buffers(struct spa_node *node,
this, j, i); this, j, i);
} }
b->datas[j] = d[j].data; b->datas[j] = d[j].data;
if (direction == SPA_DIRECTION_OUTPUT &&
!SPA_FLAG_CHECK(d[j].flags, SPA_DATA_FLAG_DYNAMIC))
this->is_passthrough = false;
} }
if (direction == SPA_DIRECTION_OUTPUT) if (direction == SPA_DIRECTION_OUTPUT)
spa_list_append(&port->queue, &b->link); spa_list_append(&port->queue, &b->link);
@ -1126,7 +1134,7 @@ static int impl_node_process(struct spa_node *node)
float v; float v;
v = this->props.mute ? 0.0f : this->props.volume; v = this->props.mute ? 0.0f : this->props.volume;
is_passthrough = v == 1.0f; is_passthrough = this->is_passthrough && v == 1.0f;
n_samples = sb->datas[0].chunk->size / inport->stride; n_samples = sb->datas[0].chunk->size / inport->stride;
for (i = 0; i < n_src_datas; i++) for (i = 0; i < n_src_datas; i++)
@ -1252,7 +1260,8 @@ impl_init(const struct spa_handle_factory *factory,
port->info_all = SPA_PORT_CHANGE_MASK_FLAGS | port->info_all = SPA_PORT_CHANGE_MASK_FLAGS |
SPA_PORT_CHANGE_MASK_PARAMS; SPA_PORT_CHANGE_MASK_PARAMS;
port->info = SPA_PORT_INFO_INIT(); port->info = SPA_PORT_INFO_INIT();
port->info.flags = SPA_PORT_FLAG_CAN_USE_BUFFERS; port->info.flags = SPA_PORT_FLAG_CAN_USE_BUFFERS |
SPA_PORT_FLAG_DYNAMIC_DATA;
port->params[0] = SPA_PARAM_INFO(SPA_PARAM_EnumFormat, SPA_PARAM_INFO_READ); port->params[0] = SPA_PARAM_INFO(SPA_PARAM_EnumFormat, SPA_PARAM_INFO_READ);
port->params[1] = SPA_PARAM_INFO(SPA_PARAM_Meta, SPA_PARAM_INFO_READ); port->params[1] = SPA_PARAM_INFO(SPA_PARAM_Meta, SPA_PARAM_INFO_READ);
port->params[2] = SPA_PARAM_INFO(SPA_PARAM_IO, SPA_PARAM_INFO_READ); port->params[2] = SPA_PARAM_INFO(SPA_PARAM_IO, SPA_PARAM_INFO_READ);
@ -1268,7 +1277,9 @@ impl_init(const struct spa_handle_factory *factory,
port->info_all = SPA_PORT_CHANGE_MASK_FLAGS | port->info_all = SPA_PORT_CHANGE_MASK_FLAGS |
SPA_PORT_CHANGE_MASK_PARAMS; SPA_PORT_CHANGE_MASK_PARAMS;
port->info = SPA_PORT_INFO_INIT(); port->info = SPA_PORT_INFO_INIT();
port->info.flags = SPA_PORT_FLAG_CAN_USE_BUFFERS; port->info.flags = SPA_PORT_FLAG_CAN_USE_BUFFERS |
SPA_PORT_FLAG_NO_REF |
SPA_PORT_FLAG_DYNAMIC_DATA;
port->params[0] = SPA_PARAM_INFO(SPA_PARAM_EnumFormat, SPA_PARAM_INFO_READ); port->params[0] = SPA_PARAM_INFO(SPA_PARAM_EnumFormat, SPA_PARAM_INFO_READ);
port->params[1] = SPA_PARAM_INFO(SPA_PARAM_Meta, SPA_PARAM_INFO_READ); port->params[1] = SPA_PARAM_INFO(SPA_PARAM_Meta, SPA_PARAM_INFO_READ);
port->params[2] = SPA_PARAM_INFO(SPA_PARAM_IO, SPA_PARAM_INFO_READ); port->params[2] = SPA_PARAM_INFO(SPA_PARAM_IO, SPA_PARAM_INFO_READ);

View file

@ -689,6 +689,9 @@ impl_node_port_use_buffers(struct spa_node *node,
this, j, i); this, j, i);
} }
b->datas[j] = d[j].data; b->datas[j] = d[j].data;
if (direction == SPA_DIRECTION_OUTPUT &&
!SPA_FLAG_CHECK(d[j].flags, SPA_DATA_FLAG_DYNAMIC))
this->is_passthrough = false;
} }
if (direction == SPA_DIRECTION_OUTPUT) if (direction == SPA_DIRECTION_OUTPUT)
@ -925,7 +928,7 @@ static int impl_clear(struct spa_handle *handle)
return 0; return 0;
} }
static int init_port(struct impl *this, enum spa_direction direction, uint32_t port_id, uint32_t flags) static int init_port(struct impl *this, enum spa_direction direction, uint32_t port_id)
{ {
struct port *port; struct port *port;
@ -936,7 +939,9 @@ static int init_port(struct impl *this, enum spa_direction direction, uint32_t p
spa_list_init(&port->queue); spa_list_init(&port->queue);
port->info_all = SPA_PORT_CHANGE_MASK_FLAGS | SPA_PORT_CHANGE_MASK_PROPS; port->info_all = SPA_PORT_CHANGE_MASK_FLAGS | SPA_PORT_CHANGE_MASK_PROPS;
port->info = SPA_PORT_INFO_INIT(); port->info = SPA_PORT_INFO_INIT();
port->info.flags = flags; port->info.flags = SPA_PORT_FLAG_CAN_USE_BUFFERS |
SPA_PORT_FLAG_NO_REF |
SPA_PORT_FLAG_DYNAMIC_DATA;
port->params[0] = SPA_PARAM_INFO(SPA_PARAM_EnumFormat, SPA_PARAM_INFO_READ); port->params[0] = SPA_PARAM_INFO(SPA_PARAM_EnumFormat, SPA_PARAM_INFO_READ);
port->params[1] = SPA_PARAM_INFO(SPA_PARAM_Meta, SPA_PARAM_INFO_READ); port->params[1] = SPA_PARAM_INFO(SPA_PARAM_Meta, SPA_PARAM_INFO_READ);
port->params[2] = SPA_PARAM_INFO(SPA_PARAM_IO, SPA_PARAM_INFO_READ); port->params[2] = SPA_PARAM_INFO(SPA_PARAM_IO, SPA_PARAM_INFO_READ);
@ -997,8 +1002,8 @@ impl_init(const struct spa_handle_factory *factory,
this->info.n_params = 0; this->info.n_params = 0;
props_reset(&this->props); props_reset(&this->props);
init_port(this, SPA_DIRECTION_OUTPUT, 0, SPA_PORT_FLAG_CAN_USE_BUFFERS); init_port(this, SPA_DIRECTION_OUTPUT, 0);
init_port(this, SPA_DIRECTION_INPUT, 0, SPA_PORT_FLAG_CAN_USE_BUFFERS); init_port(this, SPA_DIRECTION_INPUT, 0);
return 0; return 0;
} }

View file

@ -165,7 +165,9 @@ static int init_port(struct impl *this, enum spa_direction direction, uint32_t p
SPA_PORT_CHANGE_MASK_PROPS | SPA_PORT_CHANGE_MASK_PROPS |
SPA_PORT_CHANGE_MASK_PARAMS; SPA_PORT_CHANGE_MASK_PARAMS;
port->info = SPA_PORT_INFO_INIT(); port->info = SPA_PORT_INFO_INIT();
port->info.flags = SPA_PORT_FLAG_CAN_USE_BUFFERS; port->info.flags = SPA_PORT_FLAG_CAN_USE_BUFFERS |
SPA_PORT_FLAG_NO_REF |
SPA_PORT_FLAG_DYNAMIC_DATA;
port->params[0] = SPA_PARAM_INFO(SPA_PARAM_EnumFormat, SPA_PARAM_INFO_READ); port->params[0] = SPA_PARAM_INFO(SPA_PARAM_EnumFormat, SPA_PARAM_INFO_READ);
port->params[1] = SPA_PARAM_INFO(SPA_PARAM_Meta, SPA_PARAM_INFO_READ); port->params[1] = SPA_PARAM_INFO(SPA_PARAM_Meta, SPA_PARAM_INFO_READ);
port->params[2] = SPA_PARAM_INFO(SPA_PARAM_IO, SPA_PARAM_INFO_READ); port->params[2] = SPA_PARAM_INFO(SPA_PARAM_IO, SPA_PARAM_INFO_READ);
@ -792,6 +794,9 @@ impl_node_port_use_buffers(struct spa_node *node,
this, j, i); this, j, i);
} }
b->datas[j] = d[j].data; b->datas[j] = d[j].data;
if (direction == SPA_DIRECTION_OUTPUT &&
!SPA_FLAG_CHECK(d[j].flags, SPA_DATA_FLAG_DYNAMIC))
this->is_passthrough = false;
} }
if (direction == SPA_DIRECTION_OUTPUT) if (direction == SPA_DIRECTION_OUTPUT)
@ -1099,7 +1104,8 @@ impl_init(const struct spa_handle_factory *factory,
port->info_all = SPA_PORT_CHANGE_MASK_FLAGS | port->info_all = SPA_PORT_CHANGE_MASK_FLAGS |
SPA_PORT_CHANGE_MASK_PARAMS; SPA_PORT_CHANGE_MASK_PARAMS;
port->info = SPA_PORT_INFO_INIT(); port->info = SPA_PORT_INFO_INIT();
port->info.flags = SPA_PORT_FLAG_CAN_USE_BUFFERS; port->info.flags = SPA_PORT_FLAG_CAN_USE_BUFFERS |
SPA_PORT_FLAG_DYNAMIC_DATA;
port->params[0] = SPA_PARAM_INFO(SPA_PARAM_EnumFormat, SPA_PARAM_INFO_READ); port->params[0] = SPA_PARAM_INFO(SPA_PARAM_EnumFormat, SPA_PARAM_INFO_READ);
port->params[1] = SPA_PARAM_INFO(SPA_PARAM_Meta, SPA_PARAM_INFO_READ); port->params[1] = SPA_PARAM_INFO(SPA_PARAM_Meta, SPA_PARAM_INFO_READ);
port->params[2] = SPA_PARAM_INFO(SPA_PARAM_IO, SPA_PARAM_INFO_READ); port->params[2] = SPA_PARAM_INFO(SPA_PARAM_IO, SPA_PARAM_INFO_READ);

View file

@ -64,9 +64,8 @@ static int impl_speex_init(struct resample *r)
r->data = speex_resampler_init_frac(r->channels, r->data = speex_resampler_init_frac(r->channels,
r->i_rate, r->o_rate, r->i_rate, r->o_rate, r->i_rate, r->o_rate, r->i_rate, r->o_rate,
SPEEX_RESAMPLER_QUALITY_DEFAULT, &err); SPEEX_RESAMPLER_QUALITY_DEFAULT, &err);
if (r->data == NULL) { if (r->data == NULL)
return -ENOMEM; return -ENOMEM;
}
return 0; return 0;
} }

View file

@ -80,17 +80,17 @@ struct port {
struct spa_io_range *io_range; struct spa_io_range *io_range;
struct spa_io_sequence *io_control; struct spa_io_sequence *io_control;
bool have_format;
struct spa_audio_info format; struct spa_audio_info format;
uint32_t stride; uint32_t stride;
uint32_t blocks; uint32_t blocks;
uint32_t size; uint32_t size;
int have_format:1;
struct buffer buffers[MAX_BUFFERS]; struct buffer buffers[MAX_BUFFERS];
uint32_t n_buffers; uint32_t n_buffers;
struct spa_list queue;
uint32_t offset; uint32_t offset;
struct spa_list queue;
}; };
struct impl { struct impl {
@ -109,8 +109,8 @@ struct impl {
struct port in_port; struct port in_port;
struct port out_port; struct port out_port;
bool started; int started:1;
bool monitor; int monitor:1;
struct resample resample; struct resample resample;
}; };
@ -785,6 +785,7 @@ static int impl_node_process(struct spa_node *node)
in_len = pin_len; in_len = pin_len;
out_len = pout_len; out_len = pout_len;
src = SPA_MEMBER(sb->datas[i].data, inport->offset, void); src = SPA_MEMBER(sb->datas[i].data, inport->offset, void);
dst = SPA_MEMBER(db->datas[i].data, outport->offset, void); dst = SPA_MEMBER(db->datas[i].data, outport->offset, void);
@ -940,7 +941,8 @@ impl_init(const struct spa_handle_factory *factory,
port->info_all = SPA_PORT_CHANGE_MASK_FLAGS | port->info_all = SPA_PORT_CHANGE_MASK_FLAGS |
SPA_PORT_CHANGE_MASK_PARAMS; SPA_PORT_CHANGE_MASK_PARAMS;
port->info = SPA_PORT_INFO_INIT(); port->info = SPA_PORT_INFO_INIT();
port->info.flags = SPA_PORT_FLAG_CAN_USE_BUFFERS; port->info.flags = SPA_PORT_FLAG_CAN_USE_BUFFERS |
SPA_PORT_FLAG_DYNAMIC_DATA;
port->params[0] = SPA_PARAM_INFO(SPA_PARAM_EnumFormat, SPA_PARAM_INFO_READ); port->params[0] = SPA_PARAM_INFO(SPA_PARAM_EnumFormat, SPA_PARAM_INFO_READ);
port->params[1] = SPA_PARAM_INFO(SPA_PARAM_Meta, SPA_PARAM_INFO_READ); port->params[1] = SPA_PARAM_INFO(SPA_PARAM_Meta, SPA_PARAM_INFO_READ);
port->params[2] = SPA_PARAM_INFO(SPA_PARAM_IO, SPA_PARAM_INFO_READ); port->params[2] = SPA_PARAM_INFO(SPA_PARAM_IO, SPA_PARAM_INFO_READ);

View file

@ -156,7 +156,8 @@ static int init_port(struct impl *this, enum spa_direction direction,
SPA_PORT_CHANGE_MASK_PARAMS; SPA_PORT_CHANGE_MASK_PARAMS;
port->info = SPA_PORT_INFO_INIT(); port->info = SPA_PORT_INFO_INIT();
port->info.flags = SPA_PORT_FLAG_CAN_USE_BUFFERS; port->info.flags = SPA_PORT_FLAG_CAN_USE_BUFFERS |
SPA_PORT_FLAG_DYNAMIC_DATA;
port->info_props_items[0] = SPA_DICT_ITEM_INIT("port.dsp", "32 bit float mono audio"); port->info_props_items[0] = SPA_DICT_ITEM_INIT("port.dsp", "32 bit float mono audio");
port->info_props_items[1] = SPA_DICT_ITEM_INIT("port.channel", port->position); port->info_props_items[1] = SPA_DICT_ITEM_INIT("port.channel", port->position);
port->info_props = SPA_DICT_INIT(port->info_props_items, 2); port->info_props = SPA_DICT_INIT(port->info_props_items, 2);
@ -746,14 +747,18 @@ impl_node_port_use_buffers(struct spa_node *node,
if (!((d[j].type == SPA_DATA_MemPtr || if (!((d[j].type == SPA_DATA_MemPtr ||
d[j].type == SPA_DATA_MemFd || d[j].type == SPA_DATA_MemFd ||
d[j].type == SPA_DATA_DmaBuf) && d[j].data != NULL)) { d[j].type == SPA_DATA_DmaBuf) && d[j].data != NULL)) {
spa_log_error(this->log, NAME " %p: invalid memory %d on buffer %d", spa_log_error(this->log, NAME " %p: invalid memory %d on buffer %d %d %p",
this, j, i); this, j, i, d[j].type, d[j].data);
return -EINVAL; return -EINVAL;
} }
if (!SPA_IS_ALIGNED(d[j].data, 16)) if (!SPA_IS_ALIGNED(d[j].data, 16)) {
spa_log_warn(this->log, NAME " %p: memory %d on buffer %d not aligned", spa_log_warn(this->log, NAME " %p: memory %d on buffer %d not aligned",
this, j, i); this, j, i);
}
b->datas[j] = d[j].data; b->datas[j] = d[j].data;
if (direction == SPA_DIRECTION_OUTPUT &&
!SPA_FLAG_CHECK(d[j].flags, SPA_DATA_FLAG_DYNAMIC))
this->is_passthrough = false;
} }
if (direction == SPA_DIRECTION_OUTPUT) if (direction == SPA_DIRECTION_OUTPUT)
queue_buffer(this, port, i); queue_buffer(this, port, i);
@ -1026,7 +1031,9 @@ impl_init(const struct spa_handle_factory *factory,
port->direction = SPA_DIRECTION_INPUT; port->direction = SPA_DIRECTION_INPUT;
port->id = 0; port->id = 0;
port->info = SPA_PORT_INFO_INIT(); port->info = SPA_PORT_INFO_INIT();
port->info.flags = SPA_PORT_FLAG_CAN_USE_BUFFERS; port->info.flags = SPA_PORT_FLAG_CAN_USE_BUFFERS |
SPA_PORT_FLAG_NO_REF |
SPA_PORT_FLAG_DYNAMIC_DATA;
port->params[0] = SPA_PARAM_INFO(SPA_PARAM_EnumFormat, SPA_PARAM_INFO_READ); port->params[0] = SPA_PARAM_INFO(SPA_PARAM_EnumFormat, SPA_PARAM_INFO_READ);
port->params[1] = SPA_PARAM_INFO(SPA_PARAM_Meta, SPA_PARAM_INFO_READ); port->params[1] = SPA_PARAM_INFO(SPA_PARAM_Meta, SPA_PARAM_INFO_READ);
port->params[2] = SPA_PARAM_INFO(SPA_PARAM_IO, SPA_PARAM_INFO_READ); port->params[2] = SPA_PARAM_INFO(SPA_PARAM_IO, SPA_PARAM_INFO_READ);

View file

@ -98,7 +98,7 @@ static void init_buffer(struct port *port, uint32_t id)
b->buf.n_datas = 1; b->buf.n_datas = 1;
b->buf.datas = b->datas; b->buf.datas = b->datas;
b->datas[0].type = SPA_DATA_MemPtr; b->datas[0].type = SPA_DATA_MemPtr;
b->datas[0].flags = 0; b->datas[0].flags = SPA_DATA_FLAG_DYNAMIC;
b->datas[0].fd = -1; b->datas[0].fd = -1;
b->datas[0].mapoffset = 0; b->datas[0].mapoffset = 0;
b->datas[0].maxsize = SPA_ROUND_DOWN_N(sizeof(port->empty), 16); b->datas[0].maxsize = SPA_ROUND_DOWN_N(sizeof(port->empty), 16);

View file

@ -242,9 +242,10 @@ static int impl_node_add_port(struct spa_node *node, enum spa_direction directio
SPA_PORT_CHANGE_MASK_PARAMS; SPA_PORT_CHANGE_MASK_PARAMS;
port->info = SPA_PORT_INFO_INIT(); port->info = SPA_PORT_INFO_INIT();
port->info.flags = SPA_PORT_FLAG_CAN_USE_BUFFERS | port->info.flags = SPA_PORT_FLAG_CAN_USE_BUFFERS |
SPA_PORT_FLAG_NO_REF |
SPA_PORT_FLAG_DYNAMIC_DATA |
SPA_PORT_FLAG_REMOVABLE | SPA_PORT_FLAG_REMOVABLE |
SPA_PORT_FLAG_OPTIONAL | SPA_PORT_FLAG_OPTIONAL;
SPA_PORT_FLAG_IN_PLACE;
port->params[0] = SPA_PARAM_INFO(SPA_PARAM_EnumFormat, SPA_PARAM_INFO_READ); port->params[0] = SPA_PARAM_INFO(SPA_PARAM_EnumFormat, SPA_PARAM_INFO_READ);
port->params[1] = SPA_PARAM_INFO(SPA_PARAM_Meta, SPA_PARAM_INFO_READ); port->params[1] = SPA_PARAM_INFO(SPA_PARAM_Meta, SPA_PARAM_INFO_READ);
port->params[2] = SPA_PARAM_INFO(SPA_PARAM_IO, SPA_PARAM_INFO_READ); port->params[2] = SPA_PARAM_INFO(SPA_PARAM_IO, SPA_PARAM_INFO_READ);
@ -928,7 +929,7 @@ impl_init(const struct spa_handle_factory *factory,
port->info = SPA_PORT_INFO_INIT(); port->info = SPA_PORT_INFO_INIT();
port->info.change_mask |= SPA_PORT_CHANGE_MASK_FLAGS; port->info.change_mask |= SPA_PORT_CHANGE_MASK_FLAGS;
port->info.flags = SPA_PORT_FLAG_CAN_USE_BUFFERS | port->info.flags = SPA_PORT_FLAG_CAN_USE_BUFFERS |
SPA_PORT_FLAG_NO_REF; SPA_PORT_FLAG_DYNAMIC_DATA;
port->info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS; port->info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS;
port->params[0] = SPA_PARAM_INFO(SPA_PARAM_EnumFormat, SPA_PARAM_INFO_READ); port->params[0] = SPA_PARAM_INFO(SPA_PARAM_EnumFormat, SPA_PARAM_INFO_READ);
port->params[1] = SPA_PARAM_INFO(SPA_PARAM_Meta, SPA_PARAM_INFO_READ); port->params[1] = SPA_PARAM_INFO(SPA_PARAM_Meta, SPA_PARAM_INFO_READ);

View file

@ -633,6 +633,7 @@ static int negotiate_buffers(struct impl *impl)
aligns = alloca(sizeof(uint32_t) * blocks); aligns = alloca(sizeof(uint32_t) * blocks);
for (i = 0; i < blocks; i++) { for (i = 0; i < blocks; i++) {
datas[i].type = SPA_DATA_MemPtr; datas[i].type = SPA_DATA_MemPtr;
datas[i].flags = SPA_DATA_FLAG_DYNAMIC;
datas[i].maxsize = size; datas[i].maxsize = size;
aligns[i] = align; aligns[i] = align;
} }

View file

@ -381,6 +381,7 @@ static int alloc_buffers(struct pw_link *this,
uint32_t *data_sizes, uint32_t *data_sizes,
int32_t *data_strides, int32_t *data_strides,
uint32_t *data_aligns, uint32_t *data_aligns,
uint32_t flags,
struct allocation *allocation) struct allocation *allocation)
{ {
int res; int res;
@ -419,6 +420,7 @@ static int alloc_buffers(struct pw_link *this,
for (i = 0; i < n_datas; i++) { for (i = 0; i < n_datas; i++) {
struct spa_data *d = &datas[i]; struct spa_data *d = &datas[i];
spa_zero(*d);
if (data_sizes[i] > 0) { if (data_sizes[i] > 0) {
d->type = SPA_DATA_MemPtr; d->type = SPA_DATA_MemPtr;
d->maxsize = data_sizes[i]; d->maxsize = data_sizes[i];
@ -426,6 +428,8 @@ static int alloc_buffers(struct pw_link *this,
d->type = SPA_ID_INVALID; d->type = SPA_ID_INVALID;
d->maxsize = 0; d->maxsize = 0;
} }
if (SPA_FLAG_CHECK(flags, SPA_PORT_FLAG_DYNAMIC_DATA))
SPA_FLAG_SET(d->flags, SPA_DATA_FLAG_DYNAMIC);
} }
spa_buffer_alloc_fill_info(&info, n_metas, metas, n_datas, datas, data_aligns); spa_buffer_alloc_fill_info(&info, n_metas, metas, n_datas, datas, data_aligns);
@ -579,8 +583,8 @@ static int do_allocation(struct pw_link *this)
} }
if (output->allocation.n_buffers) { if (output->allocation.n_buffers) {
out_flags = SPA_PORT_FLAG_CAN_USE_BUFFERS; SPA_FLAG_UNSET(out_flags, SPA_PORT_FLAG_CAN_ALLOC_BUFFERS);
in_flags = SPA_PORT_FLAG_CAN_USE_BUFFERS; SPA_FLAG_UNSET(in_flags, SPA_PORT_FLAG_CAN_ALLOC_BUFFERS);
move_allocation(&output->allocation, &allocation); move_allocation(&output->allocation, &allocation);
@ -659,6 +663,7 @@ static int do_allocation(struct pw_link *this)
1, 1,
data_sizes, data_strides, data_sizes, data_strides,
data_aligns, data_aligns,
in_flags & out_flags,
&allocation)) < 0) { &allocation)) < 0) {
asprintf(&error, "error alloc buffers: %d", res); asprintf(&error, "error alloc buffers: %d", res);
goto error; goto error;
@ -676,7 +681,7 @@ static int do_allocation(struct pw_link *this)
goto error; goto error;
} }
out_res = res; out_res = res;
out_flags &= ~SPA_PORT_FLAG_CAN_USE_BUFFERS; SPA_FLAG_UNSET(out_flags, SPA_PORT_FLAG_CAN_USE_BUFFERS);
move_allocation(&allocation, &output->allocation); move_allocation(&allocation, &output->allocation);
pw_log_debug("link %p: allocated %d buffers %p from output port", this, pw_log_debug("link %p: allocated %d buffers %p from output port", this,