mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-10-29 05:40:27 -04:00
buffer: more work on buffer allocation
Separate buffer sizes in the info. Make it possible to not set data pointers for when we use memfd for the memory. Improve format conversion. Work on in-place conversion in test-convert2
This commit is contained in:
parent
142ef38df9
commit
53e03019da
6 changed files with 121 additions and 78 deletions
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue