mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-05 13:30:02 -05:00
meta: remove shared meta data
Make a method to find the memory block for the given ptr. We can use this to find the memfd of the memory if there is any. We can then remove the Shared metadata on buffers.
This commit is contained in:
parent
75cdd20207
commit
140c3959ab
10 changed files with 161 additions and 132 deletions
|
|
@ -36,7 +36,6 @@ extern "C" {
|
||||||
|
|
||||||
#define SPA_TYPE_META__Header SPA_TYPE_META_BASE "Header"
|
#define SPA_TYPE_META__Header SPA_TYPE_META_BASE "Header"
|
||||||
#define SPA_TYPE_META__VideoCrop SPA_TYPE_META_BASE "VideoCrop"
|
#define SPA_TYPE_META__VideoCrop SPA_TYPE_META_BASE "VideoCrop"
|
||||||
#define SPA_TYPE_META__Shared SPA_TYPE_META_BASE "Shared"
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A metadata element.
|
* A metadata element.
|
||||||
|
|
@ -77,16 +76,6 @@ struct spa_meta_video_crop {
|
||||||
int32_t width, height; /**< width and height */
|
int32_t width, height; /**< width and height */
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Describes the shared memory that holds buffer meta/chunk/data
|
|
||||||
*/
|
|
||||||
struct spa_meta_shared {
|
|
||||||
uint32_t flags; /**< flags */
|
|
||||||
int fd; /**< file descriptor of memory */
|
|
||||||
uint32_t offset; /**< offset in memory */
|
|
||||||
uint32_t size; /**< size of memory */
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Describes a control location in the buffer.
|
* Describes a control location in the buffer.
|
||||||
*/
|
*/
|
||||||
|
|
@ -98,7 +87,6 @@ struct spa_meta_control {
|
||||||
struct spa_type_meta {
|
struct spa_type_meta {
|
||||||
uint32_t Header;
|
uint32_t Header;
|
||||||
uint32_t VideoCrop;
|
uint32_t VideoCrop;
|
||||||
uint32_t Shared;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline void spa_type_meta_map(struct spa_type_map *map, struct spa_type_meta *type)
|
static inline void spa_type_meta_map(struct spa_type_map *map, struct spa_type_meta *type)
|
||||||
|
|
@ -106,7 +94,6 @@ static inline void spa_type_meta_map(struct spa_type_map *map, struct spa_type_m
|
||||||
if (type->Header == 0) {
|
if (type->Header == 0) {
|
||||||
type->Header = spa_type_map_get_id(map, SPA_TYPE_META__Header);
|
type->Header = spa_type_map_get_id(map, SPA_TYPE_META__Header);
|
||||||
type->VideoCrop = spa_type_map_get_id(map, SPA_TYPE_META__VideoCrop);
|
type->VideoCrop = spa_type_map_get_id(map, SPA_TYPE_META__VideoCrop);
|
||||||
type->Shared = spa_type_map_get_id(map, SPA_TYPE_META__Shared);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,10 +29,11 @@ struct spa_list {
|
||||||
struct spa_list *prev;
|
struct spa_list *prev;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define SPA_LIST_INIT(list) (struct spa_list){ list, list };
|
||||||
|
|
||||||
static inline void spa_list_init(struct spa_list *list)
|
static inline void spa_list_init(struct spa_list *list)
|
||||||
{
|
{
|
||||||
list->next = list;
|
*list = SPA_LIST_INIT(list);
|
||||||
list->prev = list;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void spa_list_insert(struct spa_list *list, struct spa_list *elem)
|
static inline void spa_list_insert(struct spa_list *list, struct spa_list *elem)
|
||||||
|
|
|
||||||
|
|
@ -79,13 +79,6 @@ int spa_debug_buffer(const struct spa_buffer *buffer)
|
||||||
fprintf(stderr, " y: %d\n", h->y);
|
fprintf(stderr, " y: %d\n", h->y);
|
||||||
fprintf(stderr, " width: %d\n", h->width);
|
fprintf(stderr, " width: %d\n", h->width);
|
||||||
fprintf(stderr, " height: %d\n", h->height);
|
fprintf(stderr, " height: %d\n", h->height);
|
||||||
} else if (!strcmp(type_name, SPA_TYPE_META__Shared)) {
|
|
||||||
struct spa_meta_shared *h = m->data;
|
|
||||||
fprintf(stderr, " struct spa_meta_shared:\n");
|
|
||||||
fprintf(stderr, " flags: %d\n", h->flags);
|
|
||||||
fprintf(stderr, " fd: %d\n", h->fd);
|
|
||||||
fprintf(stderr, " offset: %d\n", h->offset);
|
|
||||||
fprintf(stderr, " size: %d\n", h->size);
|
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, " Unknown:\n");
|
fprintf(stderr, " Unknown:\n");
|
||||||
spa_debug_dump_mem(m->data, m->size);
|
spa_debug_dump_mem(m->data, m->size);
|
||||||
|
|
|
||||||
|
|
@ -550,10 +550,9 @@ spa_proxy_node_port_use_buffers(struct spa_node *node,
|
||||||
struct proxy *this;
|
struct proxy *this;
|
||||||
struct impl *impl;
|
struct impl *impl;
|
||||||
struct port *port;
|
struct port *port;
|
||||||
uint32_t i, j, k;
|
uint32_t i, j;
|
||||||
size_t n_mem;
|
size_t n_mem;
|
||||||
struct pw_client_node_buffer *mb;
|
struct pw_client_node_buffer *mb;
|
||||||
struct spa_meta_shared *msh;
|
|
||||||
struct pw_type *t;
|
struct pw_type *t;
|
||||||
|
|
||||||
this = SPA_CONTAINER_OF(node, struct proxy, node);
|
this = SPA_CONTAINER_OF(node, struct proxy, node);
|
||||||
|
|
@ -586,35 +585,53 @@ spa_proxy_node_port_use_buffers(struct spa_node *node,
|
||||||
n_mem = 0;
|
n_mem = 0;
|
||||||
for (i = 0; i < n_buffers; i++) {
|
for (i = 0; i < n_buffers; i++) {
|
||||||
struct buffer *b = &port->buffers[i];
|
struct buffer *b = &port->buffers[i];
|
||||||
|
struct pw_memblock *m;
|
||||||
msh = spa_buffer_find_meta(buffers[i], t->meta.Shared);
|
size_t data_size;
|
||||||
if (msh == NULL) {
|
void *baseptr;
|
||||||
spa_log_error(this->log, "missing shared metadata on buffer %d", i);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
b->outbuf = buffers[i];
|
b->outbuf = buffers[i];
|
||||||
memcpy(&b->buffer, buffers[i], sizeof(struct spa_buffer));
|
memcpy(&b->buffer, buffers[i], sizeof(struct spa_buffer));
|
||||||
b->buffer.datas = b->datas;
|
b->buffer.datas = b->datas;
|
||||||
b->buffer.metas = b->metas;
|
b->buffer.metas = b->metas;
|
||||||
|
|
||||||
|
if (buffers[i]->n_metas > 0)
|
||||||
|
baseptr = buffers[i]->metas[0].data;
|
||||||
|
else if (buffers[i]->n_datas > 0)
|
||||||
|
baseptr = buffers[i]->datas[0].chunk;
|
||||||
|
else
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if ((m = pw_memblock_find(baseptr)) == NULL)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
data_size = 0;
|
||||||
|
for (j = 0; j < buffers[i]->n_metas; j++) {
|
||||||
|
data_size += buffers[i]->metas[j].size;
|
||||||
|
}
|
||||||
|
for (j = 0; j < buffers[i]->n_datas; j++) {
|
||||||
|
struct spa_data *d = buffers[i]->datas;
|
||||||
|
data_size += sizeof(struct spa_chunk);
|
||||||
|
if (d->type == t->data.MemPtr)
|
||||||
|
data_size += d->maxsize;
|
||||||
|
}
|
||||||
|
|
||||||
mb[i].buffer = &b->buffer;
|
mb[i].buffer = &b->buffer;
|
||||||
mb[i].mem_id = n_mem++;
|
mb[i].mem_id = n_mem++;
|
||||||
mb[i].offset = 0;
|
mb[i].offset = 0;
|
||||||
mb[i].size = msh->size;
|
mb[i].size = data_size;
|
||||||
|
|
||||||
pw_client_node_resource_port_add_mem(this->resource,
|
pw_client_node_resource_port_add_mem(this->resource,
|
||||||
direction,
|
direction,
|
||||||
port_id,
|
port_id,
|
||||||
mb[i].mem_id,
|
mb[i].mem_id,
|
||||||
t->data.MemFd,
|
t->data.MemFd,
|
||||||
msh->fd, msh->flags, msh->offset, msh->size);
|
m->fd, m->flags,
|
||||||
|
SPA_PTRDIFF(baseptr, m->ptr + m->offset),
|
||||||
|
data_size);
|
||||||
|
|
||||||
for (j = 0, k = 0; j < buffers[i]->n_metas; j++) {
|
for (j = 0; j < buffers[i]->n_metas; j++)
|
||||||
if (buffers[i]->metas[j].type != t->meta.Shared)
|
memcpy(&b->buffer.metas[j], &buffers[i]->metas[j], sizeof(struct spa_meta));
|
||||||
memcpy(&b->buffer.metas[k++], &buffers[i]->metas[j], sizeof(struct spa_meta));
|
b->buffer.n_metas = j;
|
||||||
}
|
|
||||||
b->buffer.n_metas = k;
|
|
||||||
|
|
||||||
for (j = 0; j < buffers[i]->n_datas; j++) {
|
for (j = 0; j < buffers[i]->n_datas; j++) {
|
||||||
struct spa_data *d = &buffers[i]->datas[j];
|
struct spa_data *d = &buffers[i]->datas[j];
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@
|
||||||
struct transport {
|
struct transport {
|
||||||
struct pw_client_node_transport trans;
|
struct pw_client_node_transport trans;
|
||||||
|
|
||||||
struct pw_memblock mem;
|
struct pw_memblock *mem;
|
||||||
size_t offset;
|
size_t offset;
|
||||||
|
|
||||||
struct pw_client_node_message current;
|
struct pw_client_node_message current;
|
||||||
|
|
@ -106,7 +106,7 @@ static void destroy(struct pw_client_node_transport *trans)
|
||||||
|
|
||||||
pw_log_debug("transport %p: destroy", trans);
|
pw_log_debug("transport %p: destroy", trans);
|
||||||
|
|
||||||
pw_memblock_free(&impl->mem);
|
pw_memblock_free(impl->mem);
|
||||||
free(impl);
|
free(impl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -184,7 +184,7 @@ pw_client_node_transport_new(uint32_t max_input_ports, uint32_t max_output_ports
|
||||||
{
|
{
|
||||||
struct transport *impl;
|
struct transport *impl;
|
||||||
struct pw_client_node_transport *trans;
|
struct pw_client_node_transport *trans;
|
||||||
struct pw_client_node_area area;
|
struct pw_client_node_area area = { 0 };
|
||||||
|
|
||||||
area.max_input_ports = max_input_ports;
|
area.max_input_ports = max_input_ports;
|
||||||
area.n_input_ports = 0;
|
area.n_input_ports = 0;
|
||||||
|
|
@ -198,12 +198,14 @@ pw_client_node_transport_new(uint32_t max_input_ports, uint32_t max_output_ports
|
||||||
trans = &impl->trans;
|
trans = &impl->trans;
|
||||||
impl->offset = 0;
|
impl->offset = 0;
|
||||||
|
|
||||||
pw_memblock_alloc(PW_MEMBLOCK_FLAG_WITH_FD |
|
if (pw_memblock_alloc(PW_MEMBLOCK_FLAG_WITH_FD |
|
||||||
PW_MEMBLOCK_FLAG_MAP_READWRITE |
|
PW_MEMBLOCK_FLAG_MAP_READWRITE |
|
||||||
PW_MEMBLOCK_FLAG_SEAL, area_get_size(&area), &impl->mem);
|
PW_MEMBLOCK_FLAG_SEAL, area_get_size(&area),
|
||||||
|
&impl->mem) < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
memcpy(impl->mem.ptr, &area, sizeof(struct pw_client_node_area));
|
memcpy(impl->mem->ptr, &area, sizeof(struct pw_client_node_area));
|
||||||
transport_setup_area(impl->mem.ptr, trans);
|
transport_setup_area(impl->mem->ptr, trans);
|
||||||
transport_reset_area(trans);
|
transport_reset_area(trans);
|
||||||
|
|
||||||
trans->destroy = destroy;
|
trans->destroy = destroy;
|
||||||
|
|
@ -220,6 +222,7 @@ pw_client_node_transport_new_from_info(struct pw_client_node_transport_info *inf
|
||||||
struct transport *impl;
|
struct transport *impl;
|
||||||
struct pw_client_node_transport *trans;
|
struct pw_client_node_transport *trans;
|
||||||
void *tmp;
|
void *tmp;
|
||||||
|
int res;
|
||||||
|
|
||||||
impl = calloc(1, sizeof(struct transport));
|
impl = calloc(1, sizeof(struct transport));
|
||||||
if (impl == NULL)
|
if (impl == NULL)
|
||||||
|
|
@ -227,19 +230,19 @@ pw_client_node_transport_new_from_info(struct pw_client_node_transport_info *inf
|
||||||
|
|
||||||
trans = &impl->trans;
|
trans = &impl->trans;
|
||||||
|
|
||||||
impl->mem.flags = PW_MEMBLOCK_FLAG_MAP_READWRITE | PW_MEMBLOCK_FLAG_WITH_FD;
|
if ((res = pw_memblock_import(PW_MEMBLOCK_FLAG_MAP_READWRITE |
|
||||||
impl->mem.fd = info->memfd;
|
PW_MEMBLOCK_FLAG_WITH_FD,
|
||||||
impl->mem.offset = info->offset;
|
info->memfd,
|
||||||
impl->mem.size = info->size;
|
info->offset,
|
||||||
if (pw_memblock_map(&impl->mem) < 0) {
|
info->size, &impl->mem)) < 0) {
|
||||||
pw_log_warn("transport %p: failed to map fd %d: %s", impl, info->memfd,
|
pw_log_warn("transport %p: failed to map fd %d: %s", impl, info->memfd,
|
||||||
strerror(errno));
|
spa_strerror(res));
|
||||||
goto mmap_failed;
|
goto mmap_failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl->offset = info->offset;
|
impl->offset = info->offset;
|
||||||
|
|
||||||
transport_setup_area(impl->mem.ptr, trans);
|
transport_setup_area(impl->mem->ptr, trans);
|
||||||
|
|
||||||
tmp = trans->output_buffer;
|
tmp = trans->output_buffer;
|
||||||
trans->output_buffer = trans->input_buffer;
|
trans->output_buffer = trans->input_buffer;
|
||||||
|
|
@ -258,6 +261,7 @@ pw_client_node_transport_new_from_info(struct pw_client_node_transport_info *inf
|
||||||
|
|
||||||
mmap_failed:
|
mmap_failed:
|
||||||
free(impl);
|
free(impl);
|
||||||
|
errno = -res;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -276,9 +280,9 @@ int pw_client_node_transport_get_info(struct pw_client_node_transport *trans,
|
||||||
{
|
{
|
||||||
struct transport *impl = (struct transport *) trans;
|
struct transport *impl = (struct transport *) trans;
|
||||||
|
|
||||||
info->memfd = impl->mem.fd;
|
info->memfd = impl->mem->fd;
|
||||||
info->offset = impl->offset;
|
info->offset = impl->offset;
|
||||||
info->size = impl->mem.size;
|
info->size = impl->mem->size;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -272,20 +272,10 @@ static struct spa_pod *find_param(struct spa_pod **params, int n_params, uint32_
|
||||||
* +|-| struct spa_data *datas | pointer to array of datas
|
* +|-| struct spa_data *datas | pointer to array of datas
|
||||||
* || +------------------------------+
|
* || +------------------------------+
|
||||||
* |+>| struct spa_meta |
|
* |+>| struct spa_meta |
|
||||||
* | | uint32_t type | Shared meta type, first one always shared
|
* | | uint32_t type | metadata
|
||||||
* |+-| void *data | pointer to inlined shared metadata
|
* +|--| void *data | pointer to mmaped metadata in shared memory
|
||||||
* || | uint32_t size | sizeof(struct spa_meta_shared)
|
* || | uint32_t size | size of metadata
|
||||||
* || | struct spa_meta |
|
* || | ... <n_metas> | more metas follow
|
||||||
* || | uint32_t type | more metadata
|
|
||||||
* +||-| void *data | pointer to mmaped metadata in shared memory
|
|
||||||
* ||| | uint32_t size | size of metadata
|
|
||||||
* ||| | ... <n_metas> | more metas follow
|
|
||||||
* ||| +------------------------------+
|
|
||||||
* ||+>| struct spa_meta_shared | inlined shared metadata
|
|
||||||
* || | uint32_t flags |
|
|
||||||
* || | int fd | fd of the shared memory block
|
|
||||||
* || | uint32_t offset | offset of meta/chunk/data for this buffer
|
|
||||||
* || | uint32_t size | size of meta/chunk/data for this buffer
|
|
||||||
* || +------------------------------+
|
* || +------------------------------+
|
||||||
* |+->| struct spa_data |
|
* |+->| struct spa_data |
|
||||||
* | | uint32_t type | memory type, either MemFd or INVALID
|
* | | uint32_t type | memory type, either MemFd or INVALID
|
||||||
|
|
@ -329,7 +319,7 @@ static struct spa_buffer **alloc_buffers(struct pw_link *this,
|
||||||
uint32_t n_datas,
|
uint32_t n_datas,
|
||||||
size_t *data_sizes,
|
size_t *data_sizes,
|
||||||
ssize_t *data_strides,
|
ssize_t *data_strides,
|
||||||
struct pw_memblock *mem)
|
struct pw_memblock **mem)
|
||||||
{
|
{
|
||||||
struct spa_buffer **buffers, *bp;
|
struct spa_buffer **buffers, *bp;
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
|
|
@ -338,23 +328,14 @@ static struct spa_buffer **alloc_buffers(struct pw_link *this,
|
||||||
void *ddp;
|
void *ddp;
|
||||||
uint32_t n_metas;
|
uint32_t n_metas;
|
||||||
struct spa_meta *metas;
|
struct spa_meta *metas;
|
||||||
|
struct pw_memblock *m;
|
||||||
struct pw_type *t = &this->core->type;
|
struct pw_type *t = &this->core->type;
|
||||||
|
|
||||||
n_metas = data_size = meta_size = 0;
|
n_metas = data_size = meta_size = 0;
|
||||||
|
|
||||||
/* each buffer has 1 meta shared */
|
|
||||||
skel_size = sizeof(struct spa_buffer);
|
skel_size = sizeof(struct spa_buffer);
|
||||||
skel_size += sizeof(struct spa_meta);
|
|
||||||
skel_size += sizeof(struct spa_meta_shared);
|
|
||||||
|
|
||||||
metas = alloca(sizeof(struct spa_meta) * (n_params + 1));
|
metas = alloca(sizeof(struct spa_meta) * n_params);
|
||||||
|
|
||||||
/* add shared metadata this should not go into shared
|
|
||||||
* memory or else a client can damage it so we inline it after
|
|
||||||
* the array of spa_meta. */
|
|
||||||
metas[n_metas].type = t->meta.Shared;
|
|
||||||
metas[n_metas].size = sizeof(struct spa_meta_shared);
|
|
||||||
n_metas++;
|
|
||||||
|
|
||||||
/* collect metadata */
|
/* collect metadata */
|
||||||
for (i = 0; i < n_params; i++) {
|
for (i = 0; i < n_params; i++) {
|
||||||
|
|
@ -390,41 +371,28 @@ static struct spa_buffer **alloc_buffers(struct pw_link *this,
|
||||||
|
|
||||||
pw_memblock_alloc(PW_MEMBLOCK_FLAG_WITH_FD |
|
pw_memblock_alloc(PW_MEMBLOCK_FLAG_WITH_FD |
|
||||||
PW_MEMBLOCK_FLAG_MAP_READWRITE |
|
PW_MEMBLOCK_FLAG_MAP_READWRITE |
|
||||||
PW_MEMBLOCK_FLAG_SEAL, n_buffers * data_size, mem);
|
PW_MEMBLOCK_FLAG_SEAL, n_buffers * data_size, &m);
|
||||||
|
|
||||||
for (i = 0; i < n_buffers; i++) {
|
for (i = 0; i < n_buffers; i++) {
|
||||||
int j;
|
int j;
|
||||||
struct spa_buffer *b;
|
struct spa_buffer *b;
|
||||||
struct spa_meta_shared *msh;
|
|
||||||
void *p;
|
void *p;
|
||||||
|
|
||||||
buffers[i] = b = SPA_MEMBER(bp, skel_size * i, struct spa_buffer);
|
buffers[i] = b = SPA_MEMBER(bp, skel_size * i, struct spa_buffer);
|
||||||
|
|
||||||
p = SPA_MEMBER(mem->ptr, data_size * i, void);
|
p = SPA_MEMBER(m->ptr, data_size * i, void);
|
||||||
|
|
||||||
msh = SPA_MEMBER(b, sizeof(struct spa_buffer), struct spa_meta_shared);
|
|
||||||
msh->flags = 0;
|
|
||||||
msh->fd = mem->fd;
|
|
||||||
msh->offset = data_size * i;
|
|
||||||
msh->size = data_size;
|
|
||||||
|
|
||||||
b->id = i;
|
b->id = i;
|
||||||
b->n_metas = n_metas;
|
b->n_metas = n_metas;
|
||||||
b->metas = SPA_MEMBER(msh, sizeof(struct spa_meta_shared), struct spa_meta);
|
b->metas = SPA_MEMBER(b, sizeof(struct spa_buffer), struct spa_meta);
|
||||||
for (j = 0; j < n_metas; j++) {
|
for (j = 0; j < n_metas; j++) {
|
||||||
struct spa_meta *m = &b->metas[j];
|
struct spa_meta *m = &b->metas[j];
|
||||||
|
|
||||||
m->type = metas[j].type;
|
m->type = metas[j].type;
|
||||||
m->size = metas[j].size;
|
m->size = metas[j].size;
|
||||||
|
|
||||||
if (m->type == t->meta.Shared) {
|
|
||||||
m->data = msh;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
m->data = p;
|
m->data = p;
|
||||||
p += m->size;
|
p += m->size;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
/* pointer to data structure */
|
/* pointer to data structure */
|
||||||
b->n_datas = n_datas;
|
b->n_datas = n_datas;
|
||||||
b->datas = SPA_MEMBER(b->metas, n_metas * sizeof(struct spa_meta), struct spa_data);
|
b->datas = SPA_MEMBER(b->metas, n_metas * sizeof(struct spa_meta), struct spa_data);
|
||||||
|
|
@ -439,10 +407,10 @@ static struct spa_buffer **alloc_buffers(struct pw_link *this,
|
||||||
if (data_sizes[j] > 0) {
|
if (data_sizes[j] > 0) {
|
||||||
d->type = t->data.MemFd;
|
d->type = t->data.MemFd;
|
||||||
d->flags = 0;
|
d->flags = 0;
|
||||||
d->fd = mem->fd;
|
d->fd = m->fd;
|
||||||
d->mapoffset = SPA_PTRDIFF(ddp, mem->ptr);
|
d->mapoffset = SPA_PTRDIFF(ddp, m->ptr);
|
||||||
d->maxsize = data_sizes[j];
|
d->maxsize = data_sizes[j];
|
||||||
d->data = SPA_MEMBER(mem->ptr, d->mapoffset, void);
|
d->data = SPA_MEMBER(m->ptr, d->mapoffset, void);
|
||||||
d->chunk->offset = 0;
|
d->chunk->offset = 0;
|
||||||
d->chunk->size = 0;
|
d->chunk->size = 0;
|
||||||
d->chunk->stride = data_strides[j];
|
d->chunk->stride = data_strides[j];
|
||||||
|
|
@ -454,6 +422,7 @@ static struct spa_buffer **alloc_buffers(struct pw_link *this,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*mem = m;
|
||||||
return buffers;
|
return buffers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1302,7 +1271,7 @@ void pw_link_destroy(struct pw_link *link)
|
||||||
|
|
||||||
if (link->buffer_owner == link) {
|
if (link->buffer_owner == link) {
|
||||||
free(link->buffers);
|
free(link->buffers);
|
||||||
pw_memblock_free(&link->buffer_mem);
|
pw_memblock_free(link->buffer_mem);
|
||||||
}
|
}
|
||||||
free(impl);
|
free(impl);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,8 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <sys/syscall.h>
|
#include <sys/syscall.h>
|
||||||
|
|
||||||
|
#include <spa/utils/list.h>
|
||||||
|
|
||||||
#include <pipewire/log.h>
|
#include <pipewire/log.h>
|
||||||
#include <pipewire/mem.h>
|
#include <pipewire/mem.h>
|
||||||
|
|
||||||
|
|
@ -77,6 +79,12 @@ static inline int memfd_create(const char *name, unsigned int flags)
|
||||||
#define F_SEAL_WRITE 0x0008 /* prevent writes */
|
#define F_SEAL_WRITE 0x0008 /* prevent writes */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
struct memblock {
|
||||||
|
struct pw_memblock mem;
|
||||||
|
struct spa_list link;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct spa_list _memblocks = SPA_LIST_INIT(&_memblocks);
|
||||||
|
|
||||||
#define USE_MEMFD
|
#define USE_MEMFD
|
||||||
|
|
||||||
|
|
@ -140,75 +148,106 @@ int pw_memblock_map(struct pw_memblock *mem)
|
||||||
* \return 0 on success, < 0 on error
|
* \return 0 on success, < 0 on error
|
||||||
* \memberof pw_memblock
|
* \memberof pw_memblock
|
||||||
*/
|
*/
|
||||||
int pw_memblock_alloc(enum pw_memblock_flags flags, size_t size, struct pw_memblock *mem)
|
int pw_memblock_alloc(enum pw_memblock_flags flags, size_t size, struct pw_memblock **mem)
|
||||||
{
|
{
|
||||||
|
struct memblock tmp, *p;
|
||||||
|
struct pw_memblock *m;
|
||||||
bool use_fd;
|
bool use_fd;
|
||||||
|
|
||||||
if (mem == NULL || size == 0)
|
if (mem == NULL)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
mem->offset = 0;
|
m = &tmp.mem;
|
||||||
mem->flags = flags;
|
m->offset = 0;
|
||||||
mem->size = size;
|
m->flags = flags;
|
||||||
mem->ptr = NULL;
|
m->size = size;
|
||||||
|
m->ptr = NULL;
|
||||||
|
|
||||||
use_fd = ! !(flags & (PW_MEMBLOCK_FLAG_MAP_TWICE | PW_MEMBLOCK_FLAG_WITH_FD));
|
use_fd = ! !(flags & (PW_MEMBLOCK_FLAG_MAP_TWICE | PW_MEMBLOCK_FLAG_WITH_FD));
|
||||||
|
|
||||||
if (use_fd) {
|
if (use_fd) {
|
||||||
#ifdef USE_MEMFD
|
#ifdef USE_MEMFD
|
||||||
mem->fd = memfd_create("pipewire-memfd", MFD_CLOEXEC | MFD_ALLOW_SEALING);
|
m->fd = memfd_create("pipewire-memfd", MFD_CLOEXEC | MFD_ALLOW_SEALING);
|
||||||
if (mem->fd == -1) {
|
if (m->fd == -1) {
|
||||||
pw_log_error("Failed to create memfd: %s\n", strerror(errno));
|
pw_log_error("Failed to create memfd: %s\n", strerror(errno));
|
||||||
return -errno;
|
return -errno;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
char filename[] = "/dev/shm/pipewire-tmpfile.XXXXXX";
|
char filename[] = "/dev/shm/pipewire-tmpfile.XXXXXX";
|
||||||
mem->fd = mkostemp(filename, O_CLOEXEC);
|
m->fd = mkostemp(filename, O_CLOEXEC);
|
||||||
if (mem->fd == -1) {
|
if (m->fd == -1) {
|
||||||
pw_log_error("Failed to create temporary file: %s\n", strerror(errno));
|
pw_log_error("Failed to create temporary file: %s\n", strerror(errno));
|
||||||
return -errno;
|
return -errno;
|
||||||
}
|
}
|
||||||
unlink(filename);
|
unlink(filename);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (ftruncate(mem->fd, size) < 0) {
|
if (ftruncate(m->fd, size) < 0) {
|
||||||
pw_log_warn("Failed to truncate temporary file: %s", strerror(errno));
|
pw_log_warn("Failed to truncate temporary file: %s", strerror(errno));
|
||||||
close(mem->fd);
|
close(m->fd);
|
||||||
return -errno;
|
return -errno;
|
||||||
}
|
}
|
||||||
#ifdef USE_MEMFD
|
#ifdef USE_MEMFD
|
||||||
if (flags & PW_MEMBLOCK_FLAG_SEAL) {
|
if (flags & PW_MEMBLOCK_FLAG_SEAL) {
|
||||||
unsigned int seals = F_SEAL_GROW | F_SEAL_SHRINK | F_SEAL_SEAL;
|
unsigned int seals = F_SEAL_GROW | F_SEAL_SHRINK | F_SEAL_SEAL;
|
||||||
if (fcntl(mem->fd, F_ADD_SEALS, seals) == -1) {
|
if (fcntl(m->fd, F_ADD_SEALS, seals) == -1) {
|
||||||
pw_log_warn("Failed to add seals: %s", strerror(errno));
|
pw_log_warn("Failed to add seals: %s", strerror(errno));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (pw_memblock_map(mem) != 0)
|
if (pw_memblock_map(m) != 0)
|
||||||
goto mmap_failed;
|
goto mmap_failed;
|
||||||
} else {
|
} else {
|
||||||
mem->ptr = malloc(size);
|
if (size > 0) {
|
||||||
if (mem->ptr == NULL)
|
m->ptr = malloc(size);
|
||||||
|
if (m->ptr == NULL)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
mem->fd = -1;
|
|
||||||
}
|
}
|
||||||
if (!(flags & PW_MEMBLOCK_FLAG_WITH_FD) && mem->fd != -1) {
|
m->fd = -1;
|
||||||
close(mem->fd);
|
|
||||||
mem->fd = -1;
|
|
||||||
}
|
}
|
||||||
|
if (!(flags & PW_MEMBLOCK_FLAG_WITH_FD) && m->fd != -1) {
|
||||||
|
close(m->fd);
|
||||||
|
m->fd = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = calloc(1, sizeof(struct memblock));
|
||||||
|
*p = tmp;
|
||||||
|
spa_list_prepend(&_memblocks, &p->link);
|
||||||
|
*mem = &p->mem;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
mmap_failed:
|
mmap_failed:
|
||||||
close(mem->fd);
|
close(m->fd);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
pw_memblock_import(enum pw_memblock_flags flags,
|
||||||
|
int fd, off_t offset, size_t size,
|
||||||
|
struct pw_memblock **mem)
|
||||||
|
{
|
||||||
|
int res;
|
||||||
|
|
||||||
|
if ((res = pw_memblock_alloc(0, 0, mem)) < 0)
|
||||||
|
return res;
|
||||||
|
|
||||||
|
(*mem)->flags = flags;
|
||||||
|
(*mem)->fd = fd;
|
||||||
|
(*mem)->offset = offset;
|
||||||
|
(*mem)->size = size;
|
||||||
|
|
||||||
|
return pw_memblock_map(*mem);
|
||||||
|
}
|
||||||
|
|
||||||
/** Free a memblock
|
/** Free a memblock
|
||||||
* \param mem a memblock
|
* \param mem a memblock
|
||||||
* \memberof pw_memblock
|
* \memberof pw_memblock
|
||||||
*/
|
*/
|
||||||
void pw_memblock_free(struct pw_memblock *mem)
|
void pw_memblock_free(struct pw_memblock *mem)
|
||||||
{
|
{
|
||||||
|
struct memblock *m = (struct memblock *)mem;
|
||||||
|
|
||||||
if (mem == NULL)
|
if (mem == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
@ -220,6 +259,17 @@ void pw_memblock_free(struct pw_memblock *mem)
|
||||||
} else {
|
} else {
|
||||||
free(mem->ptr);
|
free(mem->ptr);
|
||||||
}
|
}
|
||||||
mem->ptr = NULL;
|
spa_list_remove(&m->link);
|
||||||
mem->fd = -1;
|
free(mem);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct pw_memblock * pw_memblock_find(const void *ptr)
|
||||||
|
{
|
||||||
|
struct memblock *m;
|
||||||
|
|
||||||
|
spa_list_for_each(m, &_memblocks, link) {
|
||||||
|
if (ptr >= m->mem.ptr && ptr < m->mem.ptr + m->mem.size)
|
||||||
|
return &m->mem;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,12 @@ struct pw_memblock {
|
||||||
};
|
};
|
||||||
|
|
||||||
int
|
int
|
||||||
pw_memblock_alloc(enum pw_memblock_flags flags, size_t size, struct pw_memblock *mem);
|
pw_memblock_alloc(enum pw_memblock_flags flags, size_t size, struct pw_memblock **mem);
|
||||||
|
|
||||||
|
int
|
||||||
|
pw_memblock_import(enum pw_memblock_flags flags,
|
||||||
|
int fd, off_t offset, size_t size,
|
||||||
|
struct pw_memblock **mem);
|
||||||
|
|
||||||
int
|
int
|
||||||
pw_memblock_map(struct pw_memblock *mem);
|
pw_memblock_map(struct pw_memblock *mem);
|
||||||
|
|
@ -57,6 +62,9 @@ pw_memblock_map(struct pw_memblock *mem);
|
||||||
void
|
void
|
||||||
pw_memblock_free(struct pw_memblock *mem);
|
pw_memblock_free(struct pw_memblock *mem);
|
||||||
|
|
||||||
|
/** Find memblock for given \a ptr */
|
||||||
|
struct pw_memblock * pw_memblock_find(const void *ptr);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -348,7 +348,7 @@ void pw_port_destroy(struct pw_port *port)
|
||||||
|
|
||||||
if (port->allocated) {
|
if (port->allocated) {
|
||||||
free(port->buffers);
|
free(port->buffers);
|
||||||
pw_memblock_free(&port->buffer_mem);
|
pw_memblock_free(port->buffer_mem);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (port->properties)
|
if (port->properties)
|
||||||
|
|
@ -394,7 +394,7 @@ int pw_port_set_param(struct pw_port *port, uint32_t id, uint32_t flags,
|
||||||
if (param == NULL || res < 0) {
|
if (param == NULL || res < 0) {
|
||||||
if (port->allocated) {
|
if (port->allocated) {
|
||||||
free(port->buffers);
|
free(port->buffers);
|
||||||
pw_memblock_free(&port->buffer_mem);
|
pw_memblock_free(port->buffer_mem);
|
||||||
}
|
}
|
||||||
port->buffers = NULL;
|
port->buffers = NULL;
|
||||||
port->n_buffers = 0;
|
port->n_buffers = 0;
|
||||||
|
|
@ -426,7 +426,7 @@ int pw_port_use_buffers(struct pw_port *port, struct spa_buffer **buffers, uint3
|
||||||
|
|
||||||
if (port->allocated) {
|
if (port->allocated) {
|
||||||
free(port->buffers);
|
free(port->buffers);
|
||||||
pw_memblock_free(&port->buffer_mem);
|
pw_memblock_free(port->buffer_mem);
|
||||||
}
|
}
|
||||||
port->buffers = buffers;
|
port->buffers = buffers;
|
||||||
port->n_buffers = n_buffers;
|
port->n_buffers = n_buffers;
|
||||||
|
|
@ -459,7 +459,7 @@ int pw_port_alloc_buffers(struct pw_port *port,
|
||||||
|
|
||||||
if (port->allocated) {
|
if (port->allocated) {
|
||||||
free(port->buffers);
|
free(port->buffers);
|
||||||
pw_memblock_free(&port->buffer_mem);
|
pw_memblock_free(port->buffer_mem);
|
||||||
}
|
}
|
||||||
port->buffers = buffers;
|
port->buffers = buffers;
|
||||||
port->n_buffers = *n_buffers;
|
port->n_buffers = *n_buffers;
|
||||||
|
|
|
||||||
|
|
@ -195,7 +195,7 @@ struct pw_link {
|
||||||
struct spa_hook_list listener_list;
|
struct spa_hook_list listener_list;
|
||||||
|
|
||||||
void *buffer_owner;
|
void *buffer_owner;
|
||||||
struct pw_memblock buffer_mem;
|
struct pw_memblock *buffer_mem;
|
||||||
struct spa_buffer **buffers;
|
struct spa_buffer **buffers;
|
||||||
uint32_t n_buffers;
|
uint32_t n_buffers;
|
||||||
|
|
||||||
|
|
@ -273,7 +273,7 @@ struct pw_port {
|
||||||
struct spa_io_buffers io; /**< io area of the port */
|
struct spa_io_buffers io; /**< io area of the port */
|
||||||
|
|
||||||
bool allocated; /**< if buffers are allocated */
|
bool allocated; /**< if buffers are allocated */
|
||||||
struct pw_memblock buffer_mem; /**< allocated buffer memory */
|
struct pw_memblock *buffer_mem; /**< allocated buffer memory */
|
||||||
struct spa_buffer **buffers; /**< port buffers */
|
struct spa_buffer **buffers; /**< port buffers */
|
||||||
uint32_t n_buffers; /**< number of port buffers */
|
uint32_t n_buffers; /**< number of port buffers */
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue