mem: remove memory stuff

Remove the memory stuff from the spa API, we can do thing more simple
and efficiently if we always allocate buffers outside of the plugins and
only implement an alloc function on the node when it can do something
clever.
Move serialize code to the props/format/buffer code
Make it possible to copy a format and properties.
This commit is contained in:
Wim Taymans 2016-09-29 18:18:59 +02:00
parent fe37e2bc1b
commit 24108e01c1
46 changed files with 901 additions and 1546 deletions

View file

@ -288,7 +288,7 @@ spa_format_audio_parse (const SpaFormat *format,
props = &format->props;
idx = spa_props_index_for_id (props, SPA_PROP_ID_AUDIO_INFO);
if ((res = spa_props_get_prop (props, idx, &value)) < 0)
if ((res = spa_props_get_value (props, idx, &value)) < 0)
goto fallback;
if (props->prop_info[idx].type != SPA_PROP_TYPE_POINTER)
@ -300,7 +300,7 @@ spa_format_audio_parse (const SpaFormat *format,
return SPA_RESULT_OK;
fallback:
res = spa_props_copy (props, &aformat->format.props);
res = spa_props_copy_values (props, &aformat->format.props);
return res;
}

View file

@ -35,16 +35,16 @@ typedef struct {
} Buffer;
SpaResult
spa_buffer_alloc (SpaAllocParam **params,
unsigned int n_params,
SpaBuffer **buffers,
unsigned int *n_buffers)
spa_buffer_alloc (SpaBufferAllocFlags flags,
SpaAllocParam **params,
unsigned int n_params,
SpaBuffer **buffers,
unsigned int *n_buffers)
{
unsigned int i, nbufs;
size_t size = 0, stride = 0;
SpaMemory *bmem, *dmem;
void *mem;
Buffer *bufs;
Buffer *b;
bool add_header = false;
int n_metas = 0;
@ -91,28 +91,26 @@ spa_buffer_alloc (SpaAllocParam **params,
*n_buffers = nbufs;
bmem = spa_memory_alloc_with_fd (SPA_MEMORY_POOL_SHARED,
NULL, sizeof (Buffer) * nbufs);
dmem = spa_memory_alloc_with_fd (SPA_MEMORY_POOL_SHARED,
NULL, size * nbufs);
if (flags & SPA_BUFFER_ALLOC_FLAG_NO_MEM)
size = 0;
bufs = spa_memory_ensure_ptr (bmem);
mem = calloc (nbufs, sizeof (Buffer) + size);
bufs = mem;
for (i = 0; i < nbufs; i++) {
int mi = 0;
Buffer *b;
b = &bufs[i];
b->buffer.id = i;
b->buffer.mem.mem = bmem->mem;
b->buffer.mem.offset = sizeof (Buffer) * i;
b->buffer.mem.size = sizeof (Buffer);
buffers[i] = &b->buffer;
b->buffer.n_metas = n_metas;
b->buffer.metas = offsetof (Buffer, metas);
b->buffer.metas = b->metas;
b->buffer.n_datas = 1;
b->buffer.datas = offsetof (Buffer, datas);
b->buffer.datas = b->datas;
if (add_header) {
b->header.flags = 0;
@ -121,15 +119,92 @@ spa_buffer_alloc (SpaAllocParam **params,
b->header.dts_offset = 0;
b->metas[mi].type = SPA_META_TYPE_HEADER;
b->metas[mi].offset = offsetof (Buffer, header);
b->metas[mi].data = &b->header;
b->metas[mi].size = sizeof (b->header);
mi++;
}
b->datas[0].mem.mem = dmem->mem;
b->datas[0].mem.offset = size * i;
b->datas[0].mem.size = size;
if (size == 0) {
b->datas[0].type = SPA_DATA_TYPE_INVALID;
b->datas[0].data = NULL;
} else {
b->datas[0].type = SPA_DATA_TYPE_MEMPTR;
b->datas[0].data = mem + sizeof (Buffer);
}
b->datas[0].offset = size * i;
b->datas[0].size = size;
b->datas[0].stride = stride;
}
return SPA_RESULT_OK;
}
size_t
spa_buffer_get_size (const SpaBuffer *buffer)
{
size_t size;
unsigned int i;
if (buffer == NULL)
return 0;
size = sizeof (SpaBuffer);
for (i = 0; i < buffer->n_metas; i++)
size += buffer->metas[i].size * sizeof (SpaMeta);
for (i = 0; i < buffer->n_datas; i++)
size += sizeof (SpaData);
return size;
}
size_t
spa_buffer_serialize (void *dest, const SpaBuffer *buffer)
{
SpaBuffer *tb;
SpaMeta *mp;
SpaData *dp;
void *p;
unsigned int i;
if (buffer == NULL)
return 0;
tb = dest;
memcpy (tb, buffer, sizeof (SpaBuffer));
mp = SPA_MEMBER (tb, sizeof(SpaBuffer), SpaMeta);
dp = SPA_MEMBER (mp, sizeof(SpaMeta) * tb->n_metas, SpaData);
p = SPA_MEMBER (dp, sizeof(SpaData) * tb->n_datas, void);
tb->metas = SPA_INT_TO_PTR (SPA_PTRDIFF (mp, tb));
tb->datas = SPA_INT_TO_PTR (SPA_PTRDIFF (dp, tb));
for (i = 0; i < tb->n_metas; i++) {
memcpy (&mp[i], &buffer->metas[i], sizeof (SpaMeta));
memcpy (p, mp[i].data, mp[i].size);
mp[i].data = SPA_INT_TO_PTR (SPA_PTRDIFF (p, tb));
p += mp[i].size;
}
for (i = 0; i < tb->n_datas; i++)
memcpy (&dp[i], &buffer->datas[i], sizeof (SpaData));
return SPA_PTRDIFF (p, tb);
}
SpaBuffer *
spa_buffer_deserialize (void *src, off_t offset)
{
SpaBuffer *b;
unsigned int i;
b = SPA_MEMBER (src, offset, SpaBuffer);
if (b->metas)
b->metas = SPA_MEMBER (b, SPA_PTR_TO_INT (b->metas), SpaMeta);
for (i = 0; i < b->n_metas; i++) {
SpaMeta *m = &b->metas[i];
if (m->data)
m->data = SPA_MEMBER (b, SPA_PTR_TO_INT (m->data), void);
}
if (b->datas)
b->datas = SPA_MEMBER (b, SPA_PTR_TO_INT (b->datas), SpaData);
return b;
}

View file

@ -340,65 +340,12 @@ spa_control_iter_get_data (SpaControlIter *iter, size_t *size)
return si->data;
}
static SpaProps *
parse_props (void *p, off_t offset)
{
SpaProps *tp;
unsigned int i, j;
SpaPropInfo *pi;
SpaPropRangeInfo *ri;
tp = SPA_MEMBER (p, offset, SpaProps);
tp->prop_info = SPA_MEMBER (tp, SPA_PTR_TO_INT (tp->prop_info), SpaPropInfo);
/* now fix all the pointers */
for (i = 0; i < tp->n_prop_info; i++) {
pi = (SpaPropInfo *) &tp->prop_info[i];
if (pi->name)
pi->name = SPA_MEMBER (tp, SPA_PTR_TO_INT (pi->name), char);
if (pi->description)
pi->description = SPA_MEMBER (tp, SPA_PTR_TO_INT (pi->description), char);
if (pi->range_values)
pi->range_values = SPA_MEMBER (tp, SPA_PTR_TO_INT (pi->range_values), SpaPropRangeInfo);
for (j = 0; j < pi->n_range_values; j++) {
ri = (SpaPropRangeInfo *) &pi->range_values[j];
if (ri->name)
ri->name = SPA_MEMBER (tp, SPA_PTR_TO_INT (ri->name), char);
if (ri->description)
ri->description = SPA_MEMBER (tp, SPA_PTR_TO_INT (ri->description), char);
if (ri->val.value)
ri->val.value = SPA_MEMBER (tp, SPA_PTR_TO_INT (ri->val.value), void);
}
}
return tp;
}
static SpaFormat *
parse_format (void *p, size_t size, off_t offset)
{
SpaFormat *f;
if (offset == 0)
return NULL;
f = SPA_MEMBER (p, offset, SpaFormat);
f->mem.mem.pool_id = 0;
f->mem.mem.id = 0;
f->mem.offset = offset;
f->mem.size = size - offset;
parse_props (f, offsetof (SpaFormat, props));
return f;
}
static void
iter_parse_node_update (struct stack_iter *si, SpaControlCmdNodeUpdate *nu)
{
memcpy (nu, si->data, sizeof (SpaControlCmdNodeUpdate));
if (nu->props)
nu->props = parse_props (si->data, SPA_PTR_TO_INT (nu->props));
nu->props = spa_props_deserialize (si->data, SPA_PTR_TO_INT (nu->props));
}
static void
@ -415,14 +362,16 @@ iter_parse_port_update (struct stack_iter *si, SpaControlCmdPortUpdate *pu)
pu->possible_formats = SPA_MEMBER (p,
SPA_PTR_TO_INT (pu->possible_formats), SpaFormat *);
for (i = 0; i < pu->n_possible_formats; i++) {
pu->possible_formats[i] = parse_format (p, si->size,
SPA_PTR_TO_INT (pu->possible_formats[i]));
if (pu->possible_formats[i]) {
pu->possible_formats[i] = spa_format_deserialize (p,
SPA_PTR_TO_INT (pu->possible_formats[i]));
}
}
if (pu->format)
pu->format = parse_format (p, si->size, SPA_PTR_TO_INT (pu->format));
pu->format = spa_format_deserialize (p, SPA_PTR_TO_INT (pu->format));
if (pu->props)
pu->props = parse_props (p, SPA_PTR_TO_INT (pu->props));
pu->props = spa_props_deserialize (p, SPA_PTR_TO_INT (pu->props));
if (pu->info) {
SpaPortInfo *pi;
@ -440,28 +389,19 @@ static void
iter_parse_set_format (struct stack_iter *si, SpaControlCmdSetFormat *cmd)
{
memcpy (cmd, si->data, sizeof (SpaControlCmdSetFormat));
cmd->format = parse_format (si->data, si->size, SPA_PTR_TO_INT (cmd->format));
if (cmd->format)
cmd->format = spa_format_deserialize (si->data, SPA_PTR_TO_INT (cmd->format));
}
static void
iter_parse_use_buffers (struct stack_iter *si, SpaControlCmdUseBuffers *cmd)
{
void *p;
int i;
p = si->data;
memcpy (cmd, p, sizeof (SpaControlCmdUseBuffers));
if (cmd->buffers)
cmd->buffers = SPA_MEMBER (p, SPA_PTR_TO_INT (cmd->buffers), SpaBuffer *);
for (i = 0; i < cmd->n_buffers; i++) {
SpaMemoryChunk *mc;
SpaMemory *mem;
mc = SPA_MEMBER (p, SPA_PTR_TO_INT (cmd->buffers[i]), SpaMemoryChunk);
mem = spa_memory_find (&mc->mem);
cmd->buffers[i] = mem ? SPA_MEMBER (spa_memory_ensure_ptr (mem), mc->offset, SpaBuffer) : NULL;
}
cmd->buffers = SPA_MEMBER (p, SPA_PTR_TO_INT (cmd->buffers), SpaControlMemRef);
}
static void
@ -819,161 +759,6 @@ builder_add_cmd (struct stack_builder *sb, SpaControlCmd cmd, size_t size)
return p;
}
static size_t
calc_props_len (const SpaProps *props)
{
size_t len;
unsigned int i, j;
SpaPropInfo *pi;
SpaPropRangeInfo *ri;
if (props == NULL)
return 0;
/* props and unset mask */
len = sizeof (SpaProps) + sizeof (uint32_t);
for (i = 0; i < props->n_prop_info; i++) {
pi = (SpaPropInfo *) &props->prop_info[i];
len += sizeof (SpaPropInfo);
len += pi->name ? strlen (pi->name) + 1 : 0;
len += pi->description ? strlen (pi->description) + 1 : 0;
/* for the value */
len += pi->maxsize;
for (j = 0; j < pi->n_range_values; j++) {
ri = (SpaPropRangeInfo *)&pi->range_values[j];
len += sizeof (SpaPropRangeInfo);
len += ri->name ? strlen (ri->name) + 1 : 0;
len += ri->description ? strlen (ri->description) + 1 : 0;
/* the size of the range value */
len += ri->val.size;
}
}
return len;
}
static size_t
write_props (void *p, const SpaProps *props, off_t offset)
{
size_t len, slen;
unsigned int i, j;
SpaProps *tp;
SpaPropInfo *pi, *bpi;
SpaPropRangeInfo *ri, *bri;
tp = p;
memcpy (tp, props, sizeof (SpaProps));
tp->prop_info = SPA_INT_TO_PTR (offset + sizeof (uint32_t));
/* write propinfo array */
bpi = pi = SPA_MEMBER (tp, SPA_PTR_TO_INT (tp->prop_info), SpaPropInfo);
for (i = 0; i < tp->n_prop_info; i++) {
memcpy (pi, &props->prop_info[i], sizeof (SpaPropInfo));
pi++;
}
bri = ri = (SpaPropRangeInfo *) pi;
pi = bpi;
/* write range info arrays, adjust offset to it */
for (i = 0; i < tp->n_prop_info; i++) {
pi->range_values = SPA_INT_TO_PTR (SPA_PTRDIFF (ri, tp));
for (j = 0; j < pi->n_range_values; j++) {
memcpy (ri, &props->prop_info[i].range_values[j], sizeof (SpaPropRangeInfo));
ri++;
}
pi++;
}
p = ri;
pi = bpi;
ri = bri;
/* strings and default values from props and ranges */
for (i = 0; i < tp->n_prop_info; i++) {
if (pi->name) {
slen = strlen (pi->name) + 1;
memcpy (p, pi->name, slen);
pi->name = SPA_INT_TO_PTR (SPA_PTRDIFF (p, tp));
p += slen;
} else {
pi->name = 0;
}
if (pi->description) {
slen = strlen (pi->description) + 1;
memcpy (p, pi->description, slen);
pi->description = SPA_INT_TO_PTR (SPA_PTRDIFF (p, tp));
p += slen;
} else {
pi->description = 0;
}
for (j = 0; j < pi->n_range_values; j++) {
if (ri->name) {
slen = strlen (ri->name) + 1;
memcpy (p, ri->name, slen);
ri->name = SPA_INT_TO_PTR (SPA_PTRDIFF (p, tp));
p += slen;
} else {
ri->name = 0;
}
if (ri->description) {
slen = strlen (ri->description) + 1;
memcpy (p, ri->description, slen);
ri->description = SPA_INT_TO_PTR (SPA_PTRDIFF (p, tp));
p += slen;
} else {
ri->description = 0;
}
if (ri->val.size) {
memcpy (p, ri->val.value, ri->val.size);
ri->val.value = SPA_INT_TO_PTR (SPA_PTRDIFF (p, tp));
p += ri->val.size;
} else {
ri->val.value = 0;
}
ri++;
}
pi++;
}
/* and the actual values */
pi = bpi;
for (i = 0; i < tp->n_prop_info; i++) {
if (pi->offset) {
memcpy (p, SPA_MEMBER (props, pi->offset, void), pi->maxsize);
pi->offset = SPA_PTRDIFF (p, tp);
p += pi->maxsize;
} else {
pi->offset = 0;
}
pi++;
}
len = SPA_PTRDIFF (p, tp);
return len;
}
static size_t
calc_format_len (const SpaFormat *format)
{
if (format == NULL)
return 0;
return calc_props_len (&format->props) - sizeof (SpaProps) + sizeof (SpaFormat);
}
static size_t
write_format (void *p, const SpaFormat *format)
{
SpaFormat *tf;
tf = p;
tf->media_type = format->media_type;
tf->media_subtype = format->media_subtype;
tf->mem.mem.pool_id = 0;
tf->mem.mem.id = 0;
tf->mem.offset = 0;
tf->mem.size = 0;
p = SPA_MEMBER (tf, offsetof (SpaFormat, props), void);
return write_props (p, &format->props, sizeof (SpaFormat));
}
static size_t
write_port_info (void *p, const SpaPortInfo *info)
{
@ -1016,7 +801,7 @@ builder_add_node_update (struct stack_builder *sb, SpaControlCmdNodeUpdate *nu)
/* calc len */
len = sizeof (SpaControlCmdNodeUpdate);
len += calc_props_len (nu->props);
len += spa_props_get_size (nu->props);
p = builder_add_cmd (sb, SPA_CONTROL_CMD_NODE_UPDATE, len);
memcpy (p, nu, sizeof (SpaControlCmdNodeUpdate));
@ -1024,7 +809,7 @@ builder_add_node_update (struct stack_builder *sb, SpaControlCmdNodeUpdate *nu)
p = SPA_MEMBER (d, sizeof (SpaControlCmdNodeUpdate), void);
if (nu->props) {
len = write_props (p, nu->props, sizeof (SpaProps));
len = spa_props_serialize (p, nu->props);
d->props = SPA_INT_TO_PTR (SPA_PTRDIFF (p, d));
} else {
d->props = 0;
@ -1043,10 +828,11 @@ builder_add_port_update (struct stack_builder *sb, SpaControlCmdPortUpdate *pu)
/* calc len */
len = sizeof (SpaControlCmdPortUpdate);
len += pu->n_possible_formats * sizeof (SpaFormat *);
for (i = 0; i < pu->n_possible_formats; i++)
len += calc_format_len (pu->possible_formats[i]);
len += calc_format_len (pu->format);
len += calc_props_len (pu->props);
for (i = 0; i < pu->n_possible_formats; i++) {
len += spa_format_get_size (pu->possible_formats[i]);
}
len += spa_format_get_size (pu->format);
len += spa_props_get_size (pu->props);
if (pu->info) {
len += sizeof (SpaPortInfo);
len += pu->info->n_params * sizeof (SpaAllocParam *);
@ -1068,19 +854,19 @@ builder_add_port_update (struct stack_builder *sb, SpaControlCmdPortUpdate *pu)
p = SPA_MEMBER (p, sizeof (SpaFormat*) * pu->n_possible_formats, void);
for (i = 0; i < pu->n_possible_formats; i++) {
len = write_format (p, pu->possible_formats[i]);
len = spa_format_serialize (p, pu->possible_formats[i]);
bfa[i] = SPA_INT_TO_PTR (SPA_PTRDIFF (p, d));
p = SPA_MEMBER (p, len, void);
}
if (pu->format) {
len = write_format (p, pu->format);
len = spa_format_serialize (p, pu->format);
d->format = SPA_INT_TO_PTR (SPA_PTRDIFF (p, d));
p = SPA_MEMBER (p, len, void);
} else {
d->format = 0;
}
if (pu->props) {
len = write_props (p, pu->props, sizeof (SpaProps));
len = spa_props_serialize (p, pu->props);
d->props = SPA_INT_TO_PTR (SPA_PTRDIFF (p, d));
p = SPA_MEMBER (p, len, void);
} else {
@ -1103,14 +889,14 @@ builder_add_set_format (struct stack_builder *sb, SpaControlCmdSetFormat *sf)
/* calculate length */
/* port_id + format + mask */
len = sizeof (SpaControlCmdSetFormat) + calc_format_len (sf->format);
len = sizeof (SpaControlCmdSetFormat) + spa_format_get_size (sf->format);
p = builder_add_cmd (sb, SPA_CONTROL_CMD_SET_FORMAT, len);
memcpy (p, sf, sizeof (SpaControlCmdSetFormat));
sf = p;
p = SPA_MEMBER (sf, sizeof (SpaControlCmdSetFormat), void);
if (sf->format) {
len = write_format (p, sf->format);
len = spa_format_serialize (p, sf->format);
sf->format = SPA_INT_TO_PTR (SPA_PTRDIFF (p, sf));
} else
sf->format = 0;
@ -1120,35 +906,26 @@ static void
builder_add_use_buffers (struct stack_builder *sb, SpaControlCmdUseBuffers *ub)
{
size_t len;
void *p;
int i;
SpaMemoryChunk **bmc;
SpaControlCmdUseBuffers *d;
SpaControlMemRef *mr;
/* calculate length */
/* port_id + format + mask */
len = sizeof (SpaControlCmdUseBuffers);
len += ub->n_buffers * sizeof (SpaBuffer *);
len += ub->n_buffers * sizeof (SpaMemoryChunk);
len += ub->n_buffers * sizeof (SpaControlMemRef);
p = builder_add_cmd (sb, SPA_CONTROL_CMD_USE_BUFFERS, len);
memcpy (p, ub, sizeof (SpaControlCmdUseBuffers));
d = p;
d = builder_add_cmd (sb, SPA_CONTROL_CMD_USE_BUFFERS, len);
memcpy (d, ub, sizeof (SpaControlCmdUseBuffers));
p = SPA_MEMBER (d, sizeof (SpaControlCmdUseBuffers), void);
bmc = p;
mr = SPA_MEMBER (d, sizeof (SpaControlCmdUseBuffers), void);
if (d->n_buffers)
d->buffers = SPA_INT_TO_PTR (SPA_PTRDIFF (bmc, d));
d->buffers = SPA_INT_TO_PTR (SPA_PTRDIFF (mr, d));
else
d->buffers = 0;
p = SPA_MEMBER (p, sizeof (SpaMemoryChunk*) * ub->n_buffers, void);
for (i = 0; i < ub->n_buffers; i++) {
memcpy (p, &ub->buffers[i]->mem, sizeof (SpaMemoryChunk));
bmc[i] = SPA_INT_TO_PTR (SPA_PTRDIFF (p, d));
p = SPA_MEMBER (p, sizeof (SpaMemoryChunk), void);
}
for (i = 0; i < ub->n_buffers; i++)
memcpy (&mr[i], &ub->buffers[i], sizeof (SpaControlMemRef));
}
static void

View file

@ -20,7 +20,6 @@
#include <stdio.h>
#include "spa/debug.h"
#include "spa/memory.h"
#include "spa/props.h"
#include "spa/format.h"
@ -92,18 +91,14 @@ spa_debug_buffer (const SpaBuffer *buffer)
fprintf (stderr, "SpaBuffer %p:\n", buffer);
fprintf (stderr, " id: %08X\n", buffer->id);
fprintf (stderr, " pool_id: %08X\n", buffer->mem.mem.pool_id);
fprintf (stderr, " mem_id: %08X\n", buffer->mem.mem.id);
fprintf (stderr, " offset: %zd\n", buffer->mem.offset);
fprintf (stderr, " size: %zd\n", buffer->mem.size);
fprintf (stderr, " n_metas: %u (offset %zd)\n", buffer->n_metas, buffer->metas);
fprintf (stderr, " n_metas: %u (at %p)\n", buffer->n_metas, buffer->metas);
for (i = 0; i < buffer->n_metas; i++) {
SpaMeta *m = &SPA_BUFFER_METAS (buffer)[i];
fprintf (stderr, " meta %d: type %d, offset %zd, size %zd:\n", i, m->type, m->offset, m->size);
SpaMeta *m = &buffer->metas[i];
fprintf (stderr, " meta %d: type %d, data %p, size %zd:\n", i, m->type, m->data, m->size);
switch (m->type) {
case SPA_META_TYPE_HEADER:
{
SpaMetaHeader *h = SPA_MEMBER (buffer, m->offset, SpaMetaHeader);
SpaMetaHeader *h = m->data;
fprintf (stderr, " SpaMetaHeader:\n");
fprintf (stderr, " flags: %08x\n", h->flags);
fprintf (stderr, " seq: %u\n", h->seq);
@ -113,37 +108,24 @@ spa_debug_buffer (const SpaBuffer *buffer)
}
case SPA_META_TYPE_POINTER:
fprintf (stderr, " SpaMetaPointer:\n");
spa_debug_dump_mem (SPA_MEMBER (buffer, m->offset, void), m->size);
spa_debug_dump_mem (m->data, m->size);
break;
case SPA_META_TYPE_VIDEO_CROP:
fprintf (stderr, " SpaMetaVideoCrop:\n");
spa_debug_dump_mem (SPA_MEMBER (buffer, m->offset, void), m->size);
spa_debug_dump_mem (m->data, m->size);
break;
default:
spa_debug_dump_mem (SPA_MEMBER (buffer, m->offset, void), m->size);
spa_debug_dump_mem (m->data, m->size);
break;
}
}
fprintf (stderr, " n_datas: \t%u (offset %zd)\n", buffer->n_datas, buffer->datas);
fprintf (stderr, " n_datas: \t%u (at %p)\n", buffer->n_datas, buffer->datas);
for (i = 0; i < buffer->n_datas; i++) {
SpaData *d = &SPA_BUFFER_DATAS (buffer)[i];
SpaMemory *mem;
mem = spa_memory_find (&d->mem.mem);
fprintf (stderr, " data %d: (memory %p)\n", i, mem);
if (mem) {
fprintf (stderr, " pool_id: %u\n", mem->mem.pool_id);
fprintf (stderr, " id: %u\n", mem->mem.id);
fprintf (stderr, " flags: %08x\n", mem->flags);
fprintf (stderr, " type: %s\n", mem->type ? mem->type : "*unknown*");
fprintf (stderr, " fd: %d\n", mem->fd);
fprintf (stderr, " ptr: %p\n", mem->ptr);
fprintf (stderr, " size: %zd\n", mem->size);
} else {
fprintf (stderr, " invalid memory reference\n");
}
fprintf (stderr, " offset: %zd\n", d->mem.offset);
fprintf (stderr, " size: %zd\n", d->mem.size);
SpaData *d = &buffer->datas[i];
fprintf (stderr, " type: %d\n", d->type);
fprintf (stderr, " data: %p\n", d->data);
fprintf (stderr, " offset: %zd\n", d->offset);
fprintf (stderr, " size: %zd\n", d->size);
fprintf (stderr, " stride: %zd\n", d->stride);
}
return SPA_RESULT_OK;
@ -361,7 +343,7 @@ spa_debug_props (const SpaProps *props, bool print_ranges)
fprintf (stderr, "%-23.23s %s. ", "", prop_type_names[info->type].CCName);
res = spa_props_get_prop (props, i, &value);
res = spa_props_get_value (props, i, &value);
fprintf (stderr, "Current: ");
if (res == SPA_RESULT_OK)
@ -453,7 +435,7 @@ spa_debug_format (const SpaFormat *format)
SpaPropValue value;
SpaResult res;
res = spa_props_get_prop (props, i, &value);
res = spa_props_get_value (props, i, &value);
if (info->flags & SPA_PROP_FLAG_INFO)
continue;

View file

@ -23,15 +23,8 @@
#include <string.h>
#include <spa/format.h>
#include <spa/debug.h>
SpaResult
spa_format_to_string (const SpaFormat *format, char **result)
{
if (format == NULL || result == NULL)
return SPA_RESULT_INVALID_ARGUMENTS;
return SPA_RESULT_OK;
}
SpaResult
spa_format_fixate (SpaFormat *format)
@ -43,3 +36,52 @@ spa_format_fixate (SpaFormat *format)
return SPA_RESULT_OK;
}
size_t
spa_format_get_size (const SpaFormat *format)
{
if (format == NULL)
return 0;
return spa_props_get_size (&format->props) - sizeof (SpaProps) + sizeof (SpaFormat);
}
size_t
spa_format_serialize (void *dest, const SpaFormat *format)
{
SpaFormat *tf;
size_t size;
if (format == NULL)
return 0;
tf = dest;
tf->media_type = format->media_type;
tf->media_subtype = format->media_subtype;
dest = SPA_MEMBER (tf, offsetof (SpaFormat, props), void);
size = spa_props_serialize (dest, &format->props) - sizeof (SpaProps) + sizeof (SpaFormat);
return size;
}
SpaFormat *
spa_format_deserialize (void *src, off_t offset)
{
SpaFormat *f;
f = SPA_MEMBER (src, offset, SpaFormat);
spa_props_deserialize (f, offsetof (SpaFormat, props));
return f;
}
SpaFormat *
spa_format_copy_into (void *dest, const SpaFormat *format)
{
if (format == NULL)
return NULL;
spa_format_serialize (dest, format);
return spa_format_deserialize (dest, 0);
}

View file

@ -1,341 +0,0 @@
/* Simple Plugin API
* Copyright (C) 2016 Wim Taymans <wim.taymans@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#define _GNU_SOURCE
#include <string.h>
#include <stddef.h>
#include <stdio.h>
#include <sys/socket.h>
#include <errno.h>
#include <sys/mman.h>
#include <unistd.h>
#include <fcntl.h>
#include "spa/memory.h"
#include "memfd-wrappers.h"
#undef USE_MEMFD
#if 1
#define SPA_DEBUG_MEMORY(format,args...) fprintf(stderr,format,##args)
#else
#define SPA_DEBUG_MEMORY(format,args...)
#endif
#define MAX_POOLS 16
#define MAX_MEMORIES 1024
struct _SpaMemoryPool {
bool valid;
uint32_t id;
SpaMemory memories[MAX_MEMORIES];
unsigned int n_free;
uint32_t free_mem[MAX_MEMORIES];
};
static SpaMemoryPool pools[MAX_POOLS];
static void
spa_memory_pool_init (SpaMemoryPool *pool, uint32_t id)
{
int i;
memset (pool, 0, sizeof (SpaMemoryPool));
for (i = 0; i < MAX_MEMORIES; i++)
pool->free_mem[i] = MAX_MEMORIES - 1 - i;
pool->n_free = MAX_MEMORIES - 1;
pool->id = id;
pool->valid = true;
}
void
spa_memory_init (void)
{
static bool initialized = false;
if (!initialized) {
spa_memory_pool_init (&pools[0], SPA_MEMORY_POOL_SHARED);
spa_memory_pool_init (&pools[1], SPA_MEMORY_POOL_LOCAL);
initialized = true;
}
}
uint32_t
spa_memory_pool_get (uint32_t type)
{
return pools[type].id;
}
uint32_t
spa_memory_pool_new (void)
{
int i;
for (i = 0; i < MAX_POOLS; i++) {
if (!pools[i].valid) {
spa_memory_pool_init (&pools[i], i);
return i;
}
}
return SPA_ID_INVALID;
}
void
spa_memory_pool_free (uint32_t pool_id)
{
pools[pool_id].valid = false;
}
SpaMemory *
spa_memory_alloc (uint32_t pool_id)
{
SpaMemory *mem;
SpaMemoryPool *pool;
uint32_t id;
if (pool_id >= MAX_POOLS || !pools[pool_id].valid)
return NULL;
pool = &pools[pool_id];
if (pool->n_free == 0)
return NULL;
id = pool->free_mem[pool->n_free - 1];
pool->n_free--;
mem = &pool->memories[id];
mem->refcount = 1;
mem->notify = NULL;
mem->fd = -1;
mem->ptr = NULL;
mem->mem.pool_id = pool_id;
mem->mem.id = id;
SPA_DEBUG_MEMORY ("mem %p: alloc %u:%u\n", mem, pool_id, id);
return mem;
}
SpaMemory *
spa_memory_alloc_size (uint32_t pool_id, void *data, size_t size)
{
SpaMemory *mem;
if (!(mem = spa_memory_alloc (pool_id)))
return NULL;
mem->flags = SPA_MEMORY_FLAG_READWRITE;
mem->ptr = malloc (size);
mem->size = size;
if (data)
memcpy (mem->ptr, data, size);
return mem;
}
SpaMemory *
spa_memory_alloc_with_fd (uint32_t pool_id, void *data, size_t size)
{
SpaMemory *mem;
if (!(mem = spa_memory_alloc (pool_id)))
return NULL;
#ifdef USE_MEMFD
mem->fd = memfd_create ("spa-memfd", MFD_CLOEXEC | MFD_ALLOW_SEALING);
#else
{
char filename[] = "/dev/shm/spa-tmpfile.XXXXXX";
mem->fd = mkostemp (filename, O_CLOEXEC);
if (mem->fd == -1) {
fprintf (stderr, "Failed to create temporary file: %s\n", strerror (errno));
return NULL;
}
unlink (filename);
}
#endif
if (data) {
if (write (mem->fd, data, size) != (ssize_t) size) {
fprintf (stderr, "Failed to write data: %s\n", strerror (errno));
close (mem->fd);
return NULL;
}
} else {
if (ftruncate (mem->fd, size) < 0) {
fprintf (stderr, "Failed to truncate temporary file: %s\n", strerror (errno));
close (mem->fd);
return NULL;
}
}
#ifdef USE_MEMFD
{
unsigned int seals;
seals = F_SEAL_GROW | F_SEAL_SHRINK | F_SEAL_SEAL;
if (fcntl (mem->fd, F_ADD_SEALS, seals) == -1) {
fprintf (stderr, "Failed to add seals: %s\n", strerror (errno));
close (mem->fd);
return NULL;
}
}
#endif
mem->flags = SPA_MEMORY_FLAG_READWRITE;
mem->size = size;
return mem;
}
SpaMemory *
spa_memory_import (SpaMemoryRef *ref)
{
SpaMemory *mem = NULL;
SpaMemoryPool *pool;
int i;
bool init = false;
uint32_t id, pool_id;
if (ref == NULL || ref->pool_id >= MAX_POOLS || !pools[ref->pool_id].valid)
return NULL;
id = ref->id;
pool_id = ref->pool_id;
pool = &pools[pool_id];
for (i = 0; i < pool->n_free; i++) {
if (pool->free_mem[i] == id) {
pool->free_mem[i] = pool->free_mem[pool->n_free - 1];
pool->n_free--;
init = true;
break;
}
}
mem = &pool->memories[id];
if (init) {
mem->refcount = 1;
mem->notify = NULL;
mem->mem = *ref;
mem->ptr = NULL;
mem->fd = -1;
} else {
mem->refcount++;
}
SPA_DEBUG_MEMORY ("mem %p: import %u:%u\n", mem, pool_id, id);
return mem;
}
SpaResult
spa_memory_ref (SpaMemoryRef *ref)
{
SpaMemory *mem;
if (!(mem = spa_memory_find (ref)))
return SPA_RESULT_ERROR;
if (mem->mem.id > 0)
mem->refcount++;
return SPA_RESULT_OK;
}
static void
spa_memory_free (SpaMemory *mem)
{
SpaMemoryPool *pool;
SPA_DEBUG_MEMORY ("mem %p: free %u:%u\n", mem, mem->mem.pool_id, mem->mem.id);
if (mem->fd != -1) {
if (mem->ptr)
munmap (mem->ptr, mem->size);
close (mem->fd);
} else {
if (mem->ptr)
free (mem->ptr);
}
pool = &pools[mem->mem.pool_id];
pool->free_mem[pool->n_free] = mem->mem.id;
pool->n_free++;
}
SpaResult
spa_memory_unref (SpaMemoryRef *ref)
{
SpaMemory *mem;
if (!(mem = spa_memory_find (ref)))
return SPA_RESULT_ERROR;
if (mem->mem.id > 0 && --mem->refcount == 0) {
if (mem->notify)
mem->notify (mem);
if (mem->refcount == 0)
spa_memory_free (mem);
}
return SPA_RESULT_OK;
}
SpaMemory *
spa_memory_find (SpaMemoryRef *ref)
{
SpaMemoryPool *pool;
if (ref == NULL || ref->pool_id >= MAX_POOLS || !pools[ref->pool_id].valid || ref->id <= 0)
return NULL;
pool = &pools[ref->pool_id];
if (ref->id >= MAX_MEMORIES || pool->memories[ref->id].refcount <= 0) {
SPA_DEBUG_MEMORY ("can't find mem %u:%u\n", ref->pool_id, ref->id);
}
return &pool->memories[ref->id];
}
void *
spa_memory_ensure_ptr (SpaMemory *mem)
{
int prot = 0;
if (mem == NULL)
return NULL;
if (mem->ptr)
return mem->ptr;
if (mem->flags & SPA_MEMORY_FLAG_READABLE)
prot |= PROT_READ;
if (mem->flags & SPA_MEMORY_FLAG_WRITABLE)
prot |= PROT_WRITE;
mem->ptr = mmap (NULL, mem->size, prot, MAP_SHARED, mem->fd, 0);
if (mem->ptr == MAP_FAILED) {
mem->ptr = NULL;
fprintf (stderr, "Failed to mmap memory %zd %p: %s\n", mem->size, mem, strerror (errno));
}
return mem->ptr;
}

View file

@ -3,7 +3,6 @@ spalib_sources = ['audio-raw.c',
'control.c',
'debug.c',
'format.c',
'memory.c',
'props.c',
'ringbuffer.c',
'video-raw.c']
@ -12,10 +11,6 @@ spalib = shared_library('spa-lib',
spalib_sources,
include_directories : spa_inc,
install : true)
#spalibs = static_library('spa-lib',
# spalib_sources,
# include_directories : spa_inc,
# install : true)
spalib_dep = declare_dependency(link_with : spalib,
include_directories : spa_inc,

View file

@ -25,9 +25,9 @@
#include <spa/props.h>
SpaResult
spa_props_set_prop (SpaProps *props,
unsigned int index,
const SpaPropValue *value)
spa_props_set_value (SpaProps *props,
unsigned int index,
const SpaPropValue *value)
{
const SpaPropInfo *info;
@ -51,9 +51,9 @@ spa_props_set_prop (SpaProps *props,
SpaResult
spa_props_get_prop (const SpaProps *props,
unsigned int index,
SpaPropValue *value)
spa_props_get_value (const SpaProps *props,
unsigned int index,
SpaPropValue *value)
{
const SpaPropInfo *info;
@ -76,8 +76,8 @@ spa_props_get_prop (const SpaProps *props,
}
SpaResult
spa_props_copy (const SpaProps *src,
SpaProps *dest)
spa_props_copy_values (const SpaProps *src,
SpaProps *dest)
{
int i;
SpaResult res;
@ -91,7 +91,7 @@ spa_props_copy (const SpaProps *src,
if (!(info->flags & SPA_PROP_FLAG_WRITABLE))
continue;
if ((res = spa_props_get_prop (src, spa_props_index_for_id (src, info->id), &value)) < 0)
if ((res = spa_props_get_value (src, spa_props_index_for_id (src, info->id), &value)) < 0)
continue;
if (value.size > info->maxsize)
return SPA_RESULT_WRONG_PROPERTY_SIZE;
@ -102,3 +102,165 @@ spa_props_copy (const SpaProps *src,
}
return SPA_RESULT_OK;
}
size_t
spa_props_get_size (const SpaProps *props)
{
size_t len;
unsigned int i, j;
SpaPropInfo *pi;
SpaPropRangeInfo *ri;
if (props == NULL)
return 0;
len = sizeof (SpaProps);
for (i = 0; i < props->n_prop_info; i++) {
pi = (SpaPropInfo *) &props->prop_info[i];
len += sizeof (SpaPropInfo);
len += pi->name ? strlen (pi->name) + 1 : 0;
len += pi->description ? strlen (pi->description) + 1 : 0;
/* for the value */
len += pi->maxsize;
for (j = 0; j < pi->n_range_values; j++) {
ri = (SpaPropRangeInfo *)&pi->range_values[j];
len += sizeof (SpaPropRangeInfo);
len += ri->name ? strlen (ri->name) + 1 : 0;
len += ri->description ? strlen (ri->description) + 1 : 0;
/* the size of the range value */
len += ri->val.size;
}
}
return len;
}
size_t
spa_props_serialize (void *p, const SpaProps *props)
{
size_t len, slen;
unsigned int i, j, c;
SpaProps *tp;
SpaPropInfo *pi;
SpaPropRangeInfo *ri;
if (props == NULL)
return 0;
tp = p;
memcpy (tp, props, sizeof (SpaProps));
pi = SPA_MEMBER (tp, sizeof(SpaProps), SpaPropInfo);
ri = SPA_MEMBER (pi, sizeof(SpaPropInfo) * tp->n_prop_info, SpaPropRangeInfo);
tp->prop_info = SPA_INT_TO_PTR (SPA_PTRDIFF (pi, tp));
/* write propinfo array */
for (i = 0, c = 0; i < tp->n_prop_info; i++) {
memcpy (&pi[i], &props->prop_info[i], sizeof (SpaPropInfo));
pi[i].range_values = SPA_INT_TO_PTR (SPA_PTRDIFF (&ri[c], tp));
for (j = 0; j < pi[i].n_range_values; j++, c++) {
memcpy (&ri[c], &props->prop_info[i].range_values[j], sizeof (SpaPropRangeInfo));
}
}
p = &ri[c];
/* strings and default values from props and ranges */
for (i = 0, c = 0; i < tp->n_prop_info; i++) {
if (pi[i].name) {
slen = strlen (pi[i].name) + 1;
memcpy (p, pi[i].name, slen);
pi[i].name = SPA_INT_TO_PTR (SPA_PTRDIFF (p, tp));
p += slen;
} else {
pi[i].name = 0;
}
if (pi[i].description) {
slen = strlen (pi[i].description) + 1;
memcpy (p, pi[i].description, slen);
pi[i].description = SPA_INT_TO_PTR (SPA_PTRDIFF (p, tp));
p += slen;
} else {
pi[i].description = 0;
}
for (j = 0; j < pi[i].n_range_values; j++, c++) {
if (ri[c].name) {
slen = strlen (ri[c].name) + 1;
memcpy (p, ri[c].name, slen);
ri[c].name = SPA_INT_TO_PTR (SPA_PTRDIFF (p, tp));
p += slen;
} else {
ri[c].name = 0;
}
if (ri[c].description) {
slen = strlen (ri[c].description) + 1;
memcpy (p, ri[c].description, slen);
ri[c].description = SPA_INT_TO_PTR (SPA_PTRDIFF (p, tp));
p += slen;
} else {
ri[c].description = 0;
}
if (ri[c].val.size) {
memcpy (p, ri[c].val.value, ri[c].val.size);
ri[c].val.value = SPA_INT_TO_PTR (SPA_PTRDIFF (p, tp));
p += ri[c].val.size;
} else {
ri[c].val.value = 0;
}
}
}
/* and the actual values */
for (i = 0; i < tp->n_prop_info; i++) {
if (pi[i].offset) {
memcpy (p, SPA_MEMBER (props, pi[i].offset, void), pi[i].maxsize);
pi[i].offset = SPA_PTRDIFF (p, tp);
p += pi[i].maxsize;
} else {
pi[i].offset = 0;
}
}
len = SPA_PTRDIFF (p, tp);
return len;
}
SpaProps *
spa_props_deserialize (void *p, off_t offset)
{
SpaProps *tp;
unsigned int i, j;
SpaPropInfo *pi;
SpaPropRangeInfo *ri;
tp = SPA_MEMBER (p, offset, SpaProps);
if (tp->prop_info)
tp->prop_info = SPA_MEMBER (tp, SPA_PTR_TO_INT (tp->prop_info), SpaPropInfo);
/* now fix all the pointers */
for (i = 0; i < tp->n_prop_info; i++) {
pi = (SpaPropInfo *) &tp->prop_info[i];
if (pi->name)
pi->name = SPA_MEMBER (tp, SPA_PTR_TO_INT (pi->name), char);
if (pi->description)
pi->description = SPA_MEMBER (tp, SPA_PTR_TO_INT (pi->description), char);
if (pi->range_values)
pi->range_values = SPA_MEMBER (tp, SPA_PTR_TO_INT (pi->range_values), SpaPropRangeInfo);
for (j = 0; j < pi->n_range_values; j++) {
ri = (SpaPropRangeInfo *) &pi->range_values[j];
if (ri->name)
ri->name = SPA_MEMBER (tp, SPA_PTR_TO_INT (ri->name), char);
if (ri->description)
ri->description = SPA_MEMBER (tp, SPA_PTR_TO_INT (ri->description), char);
if (ri->val.value)
ri->val.value = SPA_MEMBER (tp, SPA_PTR_TO_INT (ri->val.value), void);
}
}
return tp;
}
SpaProps *
spa_props_copy_into (void *dest, const SpaProps *props)
{
if (props == NULL)
return NULL;
spa_props_serialize (dest, props);
return spa_props_deserialize (dest, 0);
}

View file

@ -464,7 +464,7 @@ spa_prop_info_fill_video (SpaPropInfo *info,
return SPA_RESULT_INVALID_PROPERTY_INDEX;
memcpy (info, &format_prop_info[i], sizeof (SpaPropInfo));
info->offset = offset;
info->offset = offset - sizeof (SpaFormat) + sizeof (SpaProps);
return SPA_RESULT_OK;
}
@ -619,7 +619,7 @@ spa_format_video_parse (const SpaFormat *format,
props = &format->props;
idx = spa_props_index_for_id (props, SPA_PROP_ID_VIDEO_INFO);
if ((res = spa_props_get_prop (props, idx, &value)) < 0)
if ((res = spa_props_get_value (props, idx, &value)) < 0)
goto fallback;
if (props->prop_info[idx].type != SPA_PROP_TYPE_POINTER)
@ -631,7 +631,7 @@ spa_format_video_parse (const SpaFormat *format,
return SPA_RESULT_OK;
fallback:
res = spa_props_copy (props, &vformat->format.props);
res = spa_props_copy_values (props, &vformat->format.props);
return res;
}