diff --git a/spa/include/spa/buffer/alloc.h b/spa/include/spa/buffer/alloc.h index e404a5d5c..8e6858d72 100644 --- a/spa/include/spa/buffer/alloc.h +++ b/spa/include/spa/buffer/alloc.h @@ -30,28 +30,32 @@ struct spa_buffer_alloc_info { #define SPA_BUFFER_ALLOC_FLAG_INLINE_META (1<<0) /**< add metadata data in the skeleton */ #define SPA_BUFFER_ALLOC_FLAG_INLINE_CHUNK (1<<1) /**< add chunk data in the skeleton */ #define SPA_BUFFER_ALLOC_FLAG_INLINE_DATA (1<<2) /**< add buffer data to the skeleton */ +#define SPA_BUFFER_ALLOC_FLAG_INLINE_ALL 0b111 +#define SPA_BUFFER_ALLOC_FLAG_NO_DATA (1<<3) /**< don't set data pointers */ uint32_t flags; uint32_t n_metas; - uint32_t *meta_sizes; + struct spa_meta *metas; uint32_t n_datas; - uint32_t *data_sizes; + struct spa_data *datas; uint32_t *data_aligns; - size_t skel_size; /**< size of the struct spa_buffer */ - size_t data_size; /**< size of the metadata/chunk/data if not inlined */ + size_t skel_size; /**< size of the struct spa_buffer and inlined meta/chunk/data */ + size_t meta_size; /**< size of the meta if not inlined */ + size_t chunk_size; /**< size of the chunk if not inlined */ + size_t data_size; /**< size of the data if not inlined */ }; static inline int spa_buffer_alloc_fill_info(struct spa_buffer_alloc_info *info, - uint32_t n_metas, uint32_t meta_sizes[n_metas], - uint32_t n_datas, uint32_t data_sizes[n_datas], + uint32_t n_metas, struct spa_meta metas[n_metas], + uint32_t n_datas, struct spa_data datas[n_datas], uint32_t data_aligns[n_datas]) { size_t size; int i; info->n_metas = n_metas; - info->meta_sizes = meta_sizes; + info->metas = metas; info->n_datas = n_datas; - info->data_sizes = data_sizes; + info->datas = datas; info->data_aligns = data_aligns; info->skel_size = sizeof(struct spa_buffer); @@ -59,33 +63,30 @@ static inline int spa_buffer_alloc_fill_info(struct spa_buffer_alloc_info *info, info->skel_size += n_datas * sizeof(struct spa_data); for (i = 0, size = 0; i < n_metas; i++) - size += meta_sizes[i]; + size += metas[i].size; + info->meta_size = size; if (SPA_FLAG_CHECK(info->flags, SPA_BUFFER_ALLOC_FLAG_INLINE_META)) - info->skel_size += size; - else - info->data_size += size; + info->skel_size += info->meta_size; - size = n_datas * sizeof(struct spa_chunk); + info->chunk_size = n_datas * sizeof(struct spa_chunk); if (SPA_FLAG_CHECK(info->flags, SPA_BUFFER_ALLOC_FLAG_INLINE_CHUNK)) - info->skel_size += size; - else - info->data_size += size; + info->skel_size += info->chunk_size; for (i = 0, size = 0; i < n_datas; i++) - size += data_sizes[i]; + size += datas[i].maxsize; + info->data_size = size; - if (SPA_FLAG_CHECK(info->flags, SPA_BUFFER_ALLOC_FLAG_INLINE_DATA)) + if (!SPA_FLAG_CHECK(info->flags, SPA_BUFFER_ALLOC_FLAG_NO_DATA) && + SPA_FLAG_CHECK(info->flags, SPA_BUFFER_ALLOC_FLAG_INLINE_DATA)) info->skel_size += size; - else - info->data_size += size; return 0; } static inline struct spa_buffer * spa_buffer_alloc_layout(struct spa_buffer_alloc_info *info, - void *skel_mem, void *data_mem, uint32_t id, uint32_t mem_type) + void *skel_mem, void *data_mem, uint32_t id) { struct spa_buffer *b = skel_mem; size_t size; @@ -109,7 +110,7 @@ spa_buffer_alloc_layout(struct spa_buffer_alloc_info *info, for (i = 0; i < info->n_metas; i++) { struct spa_meta *m = &b->metas[i]; - m->size = info->meta_sizes[i]; + *m = info->metas[i]; m->data = *dp; *dp += m->size; } @@ -132,11 +133,10 @@ spa_buffer_alloc_layout(struct spa_buffer_alloc_info *info, for (i = 0; i < info->n_datas; i++) { struct spa_data *d = &b->datas[i]; + *d = info->datas[i]; d->chunk = &cp[i]; - d->type = mem_type; - if (info->data_sizes[i] > 0) { + if (!SPA_FLAG_CHECK(info->flags, SPA_BUFFER_ALLOC_FLAG_NO_DATA)) { d->data = *dp; - d->maxsize = info->data_sizes[i]; *dp += d->maxsize; } } @@ -146,11 +146,11 @@ spa_buffer_alloc_layout(struct spa_buffer_alloc_info *info, static inline int spa_buffer_alloc_layout_array(struct spa_buffer_alloc_info *info, uint32_t n_buffers, struct spa_buffer *buffers[n_buffers], - void *skel_mem, void *data_mem, uint32_t mem_type) + void *skel_mem, void *data_mem) { int i; for (i = 0; i < n_buffers; i++) { - buffers[i] = spa_buffer_alloc_layout(info, skel_mem, data_mem, i, mem_type); + buffers[i] = spa_buffer_alloc_layout(info, skel_mem, data_mem, i); skel_mem = SPA_MEMBER(skel_mem, info->skel_size, void); data_mem = SPA_MEMBER(data_mem, info->data_size, void); } @@ -158,31 +158,25 @@ spa_buffer_alloc_layout_array(struct spa_buffer_alloc_info *info, } static inline struct spa_buffer ** -spa_buffer_alloc_array(uint32_t n_buffers, uint32_t mem_type, - uint32_t n_metas, uint32_t meta_sizes[n_metas], - uint32_t n_datas, uint32_t data_sizes[n_datas], +spa_buffer_alloc_array(uint32_t n_buffers, uint32_t flags, + uint32_t n_metas, struct spa_meta metas[n_metas], + uint32_t n_datas, struct spa_data datas[n_datas], uint32_t data_aligns[n_datas]) { - size_t size; struct spa_buffer **buffers; - struct spa_buffer_alloc_info info = { 0, }; + struct spa_buffer_alloc_info info = { flags | SPA_BUFFER_ALLOC_FLAG_INLINE_ALL, }; void *skel; - info.flags = SPA_BUFFER_ALLOC_FLAG_INLINE_META | - SPA_BUFFER_ALLOC_FLAG_INLINE_CHUNK | - SPA_BUFFER_ALLOC_FLAG_INLINE_DATA; + spa_buffer_alloc_fill_info(&info, n_metas, metas, n_datas, datas, data_aligns); - spa_buffer_alloc_fill_info(&info, n_metas, meta_sizes, n_datas, data_sizes, data_aligns); + info.skel_size = SPA_ROUND_UP_N(info.skel_size, 16); - info.skel_size = SPA_ROUND_UP_N(info.skel_size, 16); - - size = sizeof(struct spa_buffer *) + info.skel_size; - buffers = calloc(n_buffers, size); + buffers = calloc(n_buffers, sizeof(struct spa_buffer *) + info.skel_size); skel = SPA_MEMBER(buffers, sizeof(struct spa_buffer *) * n_buffers, void); - spa_buffer_alloc_layout_array(&info, n_buffers, buffers, skel, NULL, mem_type); + spa_buffer_alloc_layout_array(&info, n_buffers, buffers, skel, NULL); return buffers; } diff --git a/spa/plugins/audioconvert/channelmix.c b/spa/plugins/audioconvert/channelmix.c index 720868967..b08eb7fe0 100644 --- a/spa/plugins/audioconvert/channelmix.c +++ b/spa/plugins/audioconvert/channelmix.c @@ -800,25 +800,25 @@ static int impl_node_process(struct spa_node *node) { int i, n_bytes; - uint32_t n_src_datas = sbuf->outbuf->n_datas; - uint32_t n_dst_datas = dbuf->outbuf->n_datas; + struct spa_buffer *sb = sbuf->outbuf, *db = dbuf->outbuf; + uint32_t n_src_datas = sb->n_datas; + uint32_t n_dst_datas = db->n_datas; const void *src_datas[n_src_datas]; void *dst_datas[n_dst_datas]; - n_bytes = sbuf->outbuf->datas[0].chunk->size; + n_bytes = sb->datas[0].chunk->size; for (i = 0; i < n_src_datas; i++) - src_datas[i] = sbuf->outbuf->datas[i].data; - for (i = 0; i < n_dst_datas; i++) - dst_datas[i] = dbuf->outbuf->datas[i].data; + src_datas[i] = sb->datas[i].data; + for (i = 0; i < n_dst_datas; i++) { + dst_datas[i] = db->datas[i].data; + db->datas[i].chunk->size = + (n_bytes / inport->stride) * outport->stride; + } this->convert(this, n_dst_datas, dst_datas, n_src_datas, src_datas, this->matrix, n_bytes); - - for (i = 0; i < n_dst_datas; i++) - dbuf->outbuf->datas[i].chunk->size = (n_bytes / inport->stride) * - outport->stride; } outio->status = SPA_STATUS_HAVE_BUFFER; diff --git a/spa/plugins/audioconvert/fmt-ops.c b/spa/plugins/audioconvert/fmt-ops.c index 78590bb58..dac3946ed 100644 --- a/spa/plugins/audioconvert/fmt-ops.c +++ b/spa/plugins/audioconvert/fmt-ops.c @@ -55,7 +55,7 @@ conv_u8_to_f32(void *data, int n_dst, void *dst[n_dst], int n_src, const void *s int i, j; for (i = 0; i < n_src; i++) { - const int8_t *s = src[i]; + const uint8_t *s = src[i]; float *d = dst[i]; for (j = 0; j < n_bytes; j++) @@ -66,7 +66,7 @@ conv_u8_to_f32(void *data, int n_dst, void *dst[n_dst], int n_src, const void *s static void conv_u8_to_f32d(void *data, int n_dst, void *dst[n_dst], int n_src, const void *src[n_src], int n_bytes) { - const int8_t *s = src[0]; + const uint8_t *s = src[0]; float **d = (float **) dst; int i, j; @@ -80,7 +80,7 @@ conv_u8_to_f32d(void *data, int n_dst, void *dst[n_dst], int n_src, const void * static void conv_u8d_to_f32(void *data, int n_dst, void *dst[n_dst], int n_src, const void *src[n_src], int n_bytes) { - const int8_t **s = (const int8_t **) src; + const uint8_t **s = (const uint8_t **) src; float *d = dst[0]; int i, j; diff --git a/spa/plugins/audioconvert/fmtconvert.c b/spa/plugins/audioconvert/fmtconvert.c index 36ed0fe69..51110b28d 100644 --- a/spa/plugins/audioconvert/fmtconvert.c +++ b/spa/plugins/audioconvert/fmtconvert.c @@ -858,22 +858,23 @@ static int impl_node_process(struct spa_node *node) { int i, n_bytes; - uint32_t n_src_datas = sbuf->outbuf->n_datas; - uint32_t n_dst_datas = dbuf->outbuf->n_datas; + struct spa_buffer *sb = sbuf->outbuf, *db = dbuf->outbuf; + uint32_t n_src_datas = sb->n_datas; + uint32_t n_dst_datas = db->n_datas; const void *src_datas[n_src_datas]; void *dst_datas[n_dst_datas]; - n_bytes = sbuf->outbuf->datas[0].chunk->size; + n_bytes = sb->datas[0].chunk->size; for (i = 0; i < n_src_datas; i++) - src_datas[i] = sbuf->outbuf->datas[i].data; - for (i = 0; i < n_dst_datas; i++) - dst_datas[i] = dbuf->outbuf->datas[i].data; + src_datas[i] = sb->datas[i].data; + for (i = 0; i < n_dst_datas; i++) { + dst_datas[i] = db->datas[i].data; + db->datas[i].chunk->size = + (n_bytes / inport->stride) * outport->stride; + } this->convert(this, n_dst_datas, dst_datas, n_src_datas, src_datas, n_bytes); - - for (i = 0; i < n_dst_datas; i++) - dbuf->outbuf->datas[i].chunk->size = (n_bytes / inport->stride) * outport->stride; } outio->status = SPA_STATUS_HAVE_BUFFER; diff --git a/spa/tests/test-convert2.c b/spa/tests/test-convert2.c index 49614a221..87e62f1e8 100644 --- a/spa/tests/test-convert2.c +++ b/spa/tests/test-convert2.c @@ -93,8 +93,10 @@ struct node { struct link { struct node *out_node; uint32_t out_port; + const struct spa_port_info *out_info; struct node *in_node; uint32_t in_port; + const struct spa_port_info *in_info; struct spa_io_buffers io; uint32_t n_buffers; struct spa_buffer **buffers; @@ -198,14 +200,22 @@ static int make_link(struct data *data, struct link *link, link->io = SPA_IO_BUFFERS_INIT; link->n_buffers = 0; link->buffers = NULL; + link->in_info = NULL; + link->out_info = NULL; if (out_node != NULL) { + spa_node_port_get_info(out_node->node, + SPA_DIRECTION_OUTPUT, out_port, + &link->out_info); spa_node_port_set_io(out_node->node, SPA_DIRECTION_OUTPUT, out_port, t->io.Buffers, &link->io, sizeof(link->io)); } if (in_node != NULL) { + spa_node_port_get_info(in_node->node, + SPA_DIRECTION_INPUT, in_port, + &link->in_info); spa_node_port_set_io(in_node->node, SPA_DIRECTION_INPUT, in_port, t->io.Buffers, @@ -326,8 +336,10 @@ static int negotiate_link_buffers(struct data *data, struct link *link) uint32_t state; struct spa_pod *param = NULL; int res, i; - int32_t size, stride, buffers, blocks, align; - uint32_t *sizes, *aligns; + bool in_alloc, out_alloc; + int32_t size, buffers, blocks, align, flags; + uint32_t *aligns; + struct spa_data *datas; if (link->out_node != NULL) { state = 0; @@ -349,40 +361,74 @@ static int negotiate_link_buffers(struct data *data, struct link *link) spa_pod_fixate(param); spa_debug_pod(param, 0); + if (link->in_info) + in_alloc = SPA_FLAG_CHECK(link->in_info->flags, SPA_PORT_INFO_FLAG_CAN_ALLOC_BUFFERS); + else + in_alloc = false; + + if (link->out_info) + out_alloc = SPA_FLAG_CHECK(link->out_info->flags, SPA_PORT_INFO_FLAG_CAN_ALLOC_BUFFERS); + else + out_alloc = false; + + flags = 0; + if (out_alloc || in_alloc) { + flags |= SPA_BUFFER_ALLOC_FLAG_NO_DATA; + if (out_alloc) + in_alloc = false; + } + if (spa_pod_object_parse(param, ":", t->param_buffers.buffers, "i", &buffers, ":", t->param_buffers.blocks, "i", &blocks, ":", t->param_buffers.size, "i", &size, - ":", t->param_buffers.stride, "i", &stride, ":", t->param_buffers.align, "i", &align, NULL) < 0) return -EINVAL; - sizes = alloca(sizeof(uint32_t) * blocks); + datas = alloca(sizeof(struct spa_data) * blocks); aligns = alloca(sizeof(uint32_t) * blocks); for (i = 0; i < blocks; i++) { - sizes[i] = size; + datas[i].type = t->data.MemPtr; + datas[i].maxsize = size; aligns[i] = align; } - link->buffers = spa_buffer_alloc_array(buffers, t->data.MemPtr, - 0, NULL, blocks, sizes, aligns); + link->buffers = spa_buffer_alloc_array(buffers, flags, 0, NULL, blocks, datas, aligns); if (link->buffers == NULL) return -ENOMEM; link->n_buffers = buffers; if (link->out_node != NULL) { - if ((res = spa_node_port_use_buffers(link->out_node->node, + if (out_alloc) { + if ((res = spa_node_port_alloc_buffers(link->out_node->node, + SPA_DIRECTION_OUTPUT, link->out_port, + NULL, 0, + link->buffers, &link->n_buffers)) < 0) + return res; + } + else { + if ((res = spa_node_port_use_buffers(link->out_node->node, SPA_DIRECTION_OUTPUT, link->out_port, link->buffers, link->n_buffers)) < 0) - return res; + return res; + } } if (link->in_node != NULL) { - if ((res = spa_node_port_use_buffers(link->in_node->node, + if (in_alloc) { + if ((res = spa_node_port_alloc_buffers(link->in_node->node, + SPA_DIRECTION_INPUT, link->in_port, + NULL, 0, + link->buffers, &link->n_buffers)) < 0) + return res; + } + else { + if ((res = spa_node_port_use_buffers(link->in_node->node, SPA_DIRECTION_INPUT, link->in_port, link->buffers, link->n_buffers)) < 0) - return res; + return res; + } } return 0; diff --git a/src/pipewire/stream.c b/src/pipewire/stream.c index 58112821b..cb84f5941 100644 --- a/src/pipewire/stream.c +++ b/src/pipewire/stream.c @@ -614,7 +614,8 @@ static int impl_port_use_buffers(struct spa_node *node, enum spa_direction direc impl->n_buffers = n_buffers; if (impl->use_converter) { - uint32_t data_sizes[1], data_aligns[1]; + struct spa_data datas[1]; + uint32_t data_aligns[1]; if ((res = spa_node_port_use_buffers(impl->convert, impl->direction, 0, @@ -622,12 +623,13 @@ static int impl_port_use_buffers(struct spa_node *node, enum spa_direction direc n_buffers)) < 0) return res; - data_sizes[0] = size * 2; + datas[0].type = t->data.MemPtr; + datas[0].maxsize = size * 2; data_aligns[0] = 16; - buffers = spa_buffer_alloc_array(n_buffers, t->data.MemPtr, + buffers = spa_buffer_alloc_array(n_buffers, 0, 0, NULL, - 1, data_sizes, data_aligns); + 1, datas, data_aligns); if (buffers == NULL) return -ENOMEM;