diff --git a/pinos/client/pinos.c b/pinos/client/pinos.c index a169a1e78..c12e47aa7 100644 --- a/pinos/client/pinos.c +++ b/pinos/client/pinos.c @@ -20,6 +20,7 @@ #include #include "pinos/client/pinos.h" +#include "spa/include/spa/memory.h" /** * pinos_init: @@ -33,6 +34,7 @@ void pinos_init (int *argc, char **argv[]) { gst_init (argc, argv); + spa_memory_init (); } /** diff --git a/pinos/client/stream.c b/pinos/client/stream.c index 6c96aa133..cc835abeb 100644 --- a/pinos/client/stream.c +++ b/pinos/client/stream.c @@ -33,23 +33,12 @@ #include "pinos/client/private.h" #include "spa/include/spa/control.h" +#include "spa/include/spa/debug.h" +#include "spa/include/spa/memory.h" #define MAX_BUFFER_SIZE 1024 #define MAX_FDS 16 -typedef struct { - bool cleanup; - uint32_t id; - int fd; -} MemId; - -static void -clear_mem_id (MemId *id) -{ - close (id->fd); - id->fd = -1; -} - typedef struct { bool cleanup; uint32_t id; @@ -104,7 +93,6 @@ struct _PinosStreamPrivate guint8 send_data[MAX_BUFFER_SIZE]; int send_fds[MAX_FDS]; - GArray *mem_ids; GArray *buffer_ids; }; @@ -430,8 +418,6 @@ pinos_stream_init (PinosStream * stream) g_debug ("new stream %p", stream); priv->state = PINOS_STREAM_STATE_UNCONNECTED; - priv->mem_ids = g_array_sized_new (FALSE, FALSE, sizeof (MemId), 64); - g_array_set_clear_func (priv->mem_ids, (GDestroyNotify) clear_mem_id); priv->buffer_ids = g_array_sized_new (FALSE, FALSE, sizeof (BufferId), 64); g_array_set_clear_func (priv->buffer_ids, (GDestroyNotify) clear_buffer_id); } @@ -565,19 +551,6 @@ find_buffer (PinosStream *stream, uint32_t id) return NULL; } -static MemId * -find_mem (PinosStream *stream, uint32_t id) -{ - PinosStreamPrivate *priv = stream->priv; - guint i; - for (i = 0; i < priv->mem_ids->len; i++) { - MemId *mid = &g_array_index (priv->mem_ids, MemId, i); - if (mid->id == id) - return mid; - } - return NULL; -} - static gboolean parse_control (PinosStream *stream, SpaControl *ctrl) @@ -664,7 +637,7 @@ parse_control (PinosStream *stream, case SPA_CONTROL_CMD_ADD_MEM: { SpaControlCmdAddMem p; - MemId mid; + SpaMemory *mem; int fd; if (spa_control_iter_parse_cmd (&it, &p) < 0) @@ -674,44 +647,44 @@ parse_control (PinosStream *stream, if (fd == -1) break; - g_debug ("add mem %d, %d", p.mem_id, fd); - mid.cleanup = false; - mid.id = p.mem_id; - mid.fd = fd; - g_array_append_val (priv->mem_ids, mid); + g_debug ("add mem %d, %d, %d", p.mem_id, fd, p.flags); + mem = spa_memory_import (0, p.mem_id); + mem->flags = p.flags; + mem->fd = fd; + mem->ptr = NULL; + mem->size = p.size; break; } case SPA_CONTROL_CMD_REMOVE_MEM: { SpaControlCmdRemoveMem p; - MemId *mid; + SpaMemory *mem; if (spa_control_iter_parse_cmd (&it, &p) < 0) break; g_debug ("stream %p: stop", stream); - if ((mid = find_mem (stream, p.mem_id))) - mid->cleanup = true; + mem = spa_memory_find (0, p.mem_id); + if (--mem->refcount == 0) + mem->notify (mem); break; } case SPA_CONTROL_CMD_ADD_BUFFER: { SpaControlCmdAddBuffer p; BufferId bid; + SpaMemory *mem; if (spa_control_iter_parse_cmd (&it, &p) < 0) break; - bid.fd = spa_control_get_fd (ctrl, p.fd_index, false); - if (bid.fd == -1) - break; - g_debug ("add buffer %d", p.buffer_id); + mem = spa_memory_find (0, p.mem_id); bid.cleanup = false; bid.id = p.buffer_id; bid.offset = p.offset; bid.size = p.size; - bid.buf = mmap (NULL, p.size, PROT_READ | PROT_WRITE, MAP_SHARED, bid.fd, p.offset); + bid.buf = (SpaBuffer *)((uint8_t*) spa_memory_ensure_ptr (mem) + p.offset); spa_debug_buffer (bid.buf); g_array_append_val (priv->buffer_ids, bid); @@ -733,29 +706,16 @@ parse_control (PinosStream *stream, case SPA_CONTROL_CMD_PROCESS_BUFFER: { SpaControlCmdProcessBuffer p; - unsigned int i; BufferId *bid; if (spa_control_iter_parse_cmd (&it, &p) < 0) break; if ((bid = find_buffer (stream, p.buffer_id))) { - SpaBuffer *b = bid->buf; - SpaData *d = SPA_BUFFER_DATAS (b); - - for (i = 0; i < b->n_datas; i++) { - if (d[i].type == SPA_DATA_TYPE_MEMID) { - uint32_t id = SPA_PTR_TO_UINT32 (d[i].ptr); - MemId *mid; - - if ((mid = find_mem (stream, id))) { - d[i].type = SPA_DATA_TYPE_FD; - d[i].ptr = SPA_INT_TO_PTR (mid->fd); - } - } - } - priv->buffer = b; + priv->buffer = bid->buf; + spa_debug_buffer (bid->buf); } + break; } case SPA_CONTROL_CMD_REUSE_BUFFER: @@ -810,13 +770,6 @@ on_socket_condition (GSocket *socket, send_need_input (stream, 0, priv->buffer->id); priv->buffer = NULL; } - for (i = 0; i < priv->mem_ids->len; i++) { - MemId *mid = &g_array_index (priv->mem_ids, MemId, i); - if (mid->cleanup) { - g_array_remove_index_fast (priv->mem_ids, i); - i--; - } - } for (i = 0; i < priv->buffer_ids->len; i++) { BufferId *bid = &g_array_index (priv->buffer_ids, BufferId, i); if (bid->cleanup) { diff --git a/pinos/daemon/main.c b/pinos/daemon/main.c index 71f3b823c..10c8bf5e9 100644 --- a/pinos/daemon/main.c +++ b/pinos/daemon/main.c @@ -24,6 +24,7 @@ #include #include #include +#include gint main (gint argc, gchar *argv[]) @@ -34,6 +35,7 @@ main (gint argc, gchar *argv[]) PinosNodeFactory *factory; pinos_init (&argc, &argv); + spa_memory_init (); loop = g_main_loop_new (NULL, FALSE); diff --git a/pinos/gst/gstpinos.c b/pinos/gst/gstpinos.c index db4ef2f74..4c1f4a66c 100644 --- a/pinos/gst/gstpinos.c +++ b/pinos/gst/gstpinos.c @@ -46,6 +46,8 @@ GST_DEBUG_CATEGORY (pinos_debug); static gboolean plugin_init (GstPlugin * plugin) { + pinos_init (NULL, NULL); + // gst_element_register (plugin, "pinospay", GST_RANK_NONE, // GST_TYPE_PINOS_PAY); // gst_element_register (plugin, "pinosdepay", GST_RANK_NONE, diff --git a/pinos/gst/gstpinossink.c b/pinos/gst/gstpinossink.c index b5cd19b33..6b27b6d0e 100644 --- a/pinos/gst/gstpinossink.c +++ b/pinos/gst/gstpinossink.c @@ -562,9 +562,8 @@ gst_pinos_sink_render (GstBaseSink * bsink, GstBuffer * buffer) b->mem = mem; b->fd = gst_fd_memory_get_fd (mem); - b->datas[0].type = SPA_DATA_TYPE_FD; - b->datas[0].ptr = &b->fd; - b->datas[0].ptr_type = mem->allocator->mem_type; + + b->datas[0].mem_id = 0; b->datas[0].offset = mem->offset; b->datas[0].size = mem->size; b->datas[0].stride = 0; diff --git a/pinos/gst/gstpinossrc.c b/pinos/gst/gstpinossrc.c index 016776772..39b92fed7 100644 --- a/pinos/gst/gstpinossrc.c +++ b/pinos/gst/gstpinossrc.c @@ -44,6 +44,7 @@ #include #include +#include #include @@ -385,28 +386,21 @@ on_new_buffer (GObject *gobject, } for (i = 0; i < b->n_datas; i++) { SpaData *d = &SPA_BUFFER_DATAS (b)[i]; + SpaMemory *mem; - switch (d->type) { - case SPA_DATA_TYPE_MEMPTR: - { - gst_buffer_append_memory (buf, - gst_memory_new_wrapped (0, d->ptr, d->offset + d->size, d->offset, - d->size, NULL, NULL)); - break; - } - case SPA_DATA_TYPE_FD: - { - GstMemory *fdmem = NULL; - int fd = SPA_PTR_TO_INT (d->ptr); + mem = spa_memory_find (0, d->mem_id); - fdmem = gst_fd_allocator_alloc (pinossrc->fd_allocator, dup (fd), - d->offset + d->size, GST_FD_MEMORY_FLAG_NONE); - gst_memory_resize (fdmem, d->offset, d->size); - gst_buffer_append_memory (buf, fdmem); - break; - } - default: - break; + if (mem->fd) { + GstMemory *fdmem = NULL; + + fdmem = gst_fd_allocator_alloc (pinossrc->fd_allocator, dup (mem->fd), + d->offset + d->size, GST_FD_MEMORY_FLAG_NONE); + gst_memory_resize (fdmem, d->offset, d->size); + gst_buffer_append_memory (buf, fdmem); + } else { + gst_buffer_append_memory (buf, + gst_memory_new_wrapped (0, mem->ptr, mem->size, d->offset, + d->size, NULL, NULL)); } } diff --git a/pinos/modules/spa/spa-alsa-sink.c b/pinos/modules/spa/spa-alsa-sink.c index 34687add4..8990bd90d 100644 --- a/pinos/modules/spa/spa-alsa-sink.c +++ b/pinos/modules/spa/spa-alsa-sink.c @@ -27,6 +27,7 @@ #include #include +#include #include #include "spa-alsa-sink.h" @@ -438,15 +439,15 @@ on_received_buffer (PinosPort *port, for (i = 0; i < buffer->n_datas; i++) { SpaData *d = SPA_BUFFER_DATAS (buffer); + SpaMemory *mem; PinosRingbufferArea areas[2]; uint8_t *data; size_t size, towrite, total; - if (d[i].type != SPA_DATA_TYPE_MEMPTR) - continue; + mem = spa_memory_find (0, d[i].mem_id); size = d[i].size; - data = (guint8*)d[i].ptr + d[i].offset; + data = (guint8*)mem->ptr + d[i].offset; pinos_ringbuffer_get_write_areas (priv->ringbuffer, areas); diff --git a/spa/include/spa/buffer.h b/spa/include/spa/buffer.h index b02cd1085..59be11415 100644 --- a/spa/include/spa/buffer.h +++ b/spa/include/spa/buffer.h @@ -98,39 +98,15 @@ typedef struct { size_t size; } SpaMeta; -/** - * SpaDataType: - * @SPA_DATA_TYPE_INVALID: invalid data type, is ignored - * @SPA_DATA_TYPE_MEMPTR: data and size point to memory accessible by the - * CPU. - * @SPA_DATA_TYPE_FD: data points to an int file descriptor that can be - * mmapped. - * @SPA_DATA_TYPE_MEMID: data points to the id of the memory block to use - * @SPA_DATA_TYPE_POINTER: data points to some other datastructure, the - * type can be found in ptr_type - */ -typedef enum { - SPA_DATA_TYPE_INVALID = 0, - SPA_DATA_TYPE_MEMPTR, - SPA_DATA_TYPE_FD, - SPA_DATA_TYPE_MEMID, - SPA_DATA_TYPE_POINTER, -} SpaDataType; - /** * SpaData: - * @id: user id - * @type: the type of data - * @ptr_type: more info about the type of @ptr - * @ptr: pointer to data or fd - * @offset: offset of data - * @size: size of data - * @stride: stride of data if applicable + * @mem_id: the memory id to use + * @offset: offset of memory + * @size: size of memory + * @stride: stride of memory if applicable */ typedef struct { - SpaDataType type; - const char *ptr_type; - void *ptr; + uint32_t mem_id; off_t offset; size_t size; size_t stride; @@ -139,6 +115,8 @@ typedef struct { /** * SpaBuffer: * @id: buffer id + * @mem_id: memory id of the buffer + * @offset: offset into the memory * @size: total size of the buffer structure * @n_metas: number of metadata * @metas: offset of array of @n_metas metadata @@ -147,6 +125,8 @@ typedef struct { */ struct _SpaBuffer { uint32_t id; + uint32_t mem_id; + off_t offset; size_t size; unsigned int n_metas; off_t metas; diff --git a/spa/include/spa/control.h b/spa/include/spa/control.h index fcf061e6f..1244320df 100644 --- a/spa/include/spa/control.h +++ b/spa/include/spa/control.h @@ -165,7 +165,7 @@ typedef struct { uint32_t mem_id; uint32_t mem_type; uint32_t fd_index; - uint64_t offset; + uint32_t flags; uint64_t size; } SpaControlCmdAddMem; @@ -179,7 +179,7 @@ typedef struct { typedef struct { uint32_t port_id; uint32_t buffer_id; - int fd_index; + uint32_t mem_id; uint64_t offset; uint64_t size; } SpaControlCmdAddBuffer; diff --git a/spa/include/spa/memory.h b/spa/include/spa/memory.h index a8305e1da..f9ea8fa69 100644 --- a/spa/include/spa/memory.h +++ b/spa/include/spa/memory.h @@ -41,6 +41,8 @@ typedef enum { SPA_MEMORY_FLAG_WRITABLE = (1 << 1), } SpaMemoryFlags; +#define SPA_MEMORY_FLAG_READWRITE (SPA_MEMORY_FLAG_READABLE|SPA_MEMORY_FLAG_WRITABLE) + /** * SpaMemory: * @refcount: a refcount @@ -65,15 +67,21 @@ struct _SpaMemory { size_t size; }; +void spa_memory_init (void); + uint32_t spa_memory_pool_get (uint32_t type); uint32_t spa_memory_pool_new (void); void spa_memory_pool_free (uint32_t); SpaMemory * spa_memory_alloc (uint32_t pool_id); +SpaMemory * spa_memory_alloc_with_fd (uint32_t pool_id, void *data, size_t size); SpaResult spa_memory_free (uint32_t pool_id, uint32_t id); +SpaMemory * spa_memory_import (uint32_t pool_id, uint32_t id); SpaMemory * spa_memory_find (uint32_t pool_id, uint32_t id); +void * spa_memory_ensure_ptr (SpaMemory *mem); + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/spa/lib/control.c b/spa/lib/control.c index cac534d3e..d4556e2b9 100644 --- a/spa/lib/control.c +++ b/spa/lib/control.c @@ -339,54 +339,6 @@ spa_control_iter_get_data (SpaControlIter *iter, size_t *size) return si->data; } -#if 0 -typedef struct { - SpaBuffer buffer; - SpaMeta metas[16]; - SpaData datas[16]; - int memid[16]; -} MyBuffer; - -static SpaResult -parse_add_buffer (struct stack_iter *si, - SpaControlCmdAddBuffer *command) -{ - MyBuffer *b; - uint32_t *p = si->data; - unsigned int i; - - command->port_id = *p++; - b = malloc (sizeof (MyBuffer)); - b->buffer.id = *(uint32_t *)p++; - b->buffer.size = *(uint32_t *)p++; - b->buffer.n_metas = *(uint32_t *)p++; - b->buffer.metas = offsetof (MyBuffer, metas); - b->buffer.n_datas = *(uint32_t *)p++; - b->buffer.datas = offsetof (MyBuffer, datas); - - for (i = 0; i < b->buffer.n_metas; i++) { - SpaMeta *m = &b->metas[i]; - m->type = *p++; - m->size = *p++; - m->offset = 0; - p = p + (m->size + 3) / 4; - } - for (i = 0; i < b->buffer.n_datas; i++) { - SpaData *d = &b->datas[i]; - d->type = SPA_DATA_TYPE_MEMID; - d->ptr_type = NULL; - b->memid[i] = *p++; - d->ptr = &b->memid[i]; - d->offset = *p++; - d->size = *p++; - d->stride = *p++; - } - command->buffer = &b->buffer; - - return SPA_RESULT_OK; -} -#endif - SpaResult spa_control_iter_parse_cmd (SpaControlIter *iter, void *command) @@ -719,60 +671,6 @@ builder_add_cmd (struct stack_builder *sb, SpaControlCmd cmd, size_t size) return p; } -#if 0 -static SpaResult -build_add_buffer (struct stack_builder *sb, - SpaControlCmdAddBuffer *command) -{ - unsigned int i; - size_t size; - SpaBuffer *b = command->buffer; - uint32_t *p; - - /* port + id + size + n_metas + n_datas */ - size = 4 + 4 + 4 + 4 + 4; - - for (i = 0; i < b->n_metas; i++) { - SpaMeta *m = &b->metas[i]; - /* type + size + data */ - size += 4 + 4 + m->size; - } - for (i = 0; i < b->n_datas; i++) { - SpaData *d = &b->datas[i]; - if (d->type != SPA_DATA_TYPE_MEMID) - continue; - /* memidx + offset + size + stride */ - size += 4 + 4 + 4 + 4; - } - p = builder_add_cmd (sb, SPA_CONTROL_CMD_ADD_BUFFER, size); - - *p++ = command->port_id; - *p++ = b->id; - *p++ = b->size; - *p++ = b->n_metas; - *p++ = b->n_datas; - - for (i = 0; i < b->n_metas; i++) { - SpaMeta *m = &b->metas[i]; - - *p++ = m->type; - *p++ = m->size; - memcpy (p, m->data, m->size); - p = p + m->size / 4; - } - for (i = 0; i < b->n_datas; i++) { - SpaData *d = &b->datas[i]; - if (d->type != SPA_DATA_TYPE_MEMID) - continue; - *p++ = *((uint32_t*)(d->ptr)); - *p++ = d->offset; - *p++ = d->size; - *p++ = d->stride; - } - return SPA_RESULT_OK; -} -#endif - /** * spa_control_builder_add_cmd: * @builder: a #SpaControlBuilder diff --git a/spa/lib/debug.c b/spa/lib/debug.c index 4efce1285..d80ac8d83 100644 --- a/spa/lib/debug.c +++ b/spa/lib/debug.c @@ -20,6 +20,7 @@ #include #include "spa/debug.h" +#include "spa/memory.h" SpaResult spa_debug_port_info (const SpaPortInfo *info) @@ -88,9 +89,11 @@ spa_debug_buffer (const SpaBuffer *buffer) return SPA_RESULT_INVALID_ARGUMENTS; fprintf (stderr, "SpaBuffer %p:\n", buffer); - fprintf (stderr, " id: \t%08x\n", buffer->id); - fprintf (stderr, " size: \t%zd\n", buffer->size); - fprintf (stderr, " n_metas: \t%u (offset %zd)\n", buffer->n_metas, buffer->metas); + fprintf (stderr, " id: %08X\n", buffer->id); + fprintf (stderr, " mem_id: %08X\n", buffer->mem_id); + fprintf (stderr, " offset: %zd\n", buffer->offset); + fprintf (stderr, " size: %zd\n", buffer->size); + fprintf (stderr, " n_metas: %u (offset %zd)\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); @@ -121,26 +124,24 @@ spa_debug_buffer (const SpaBuffer *buffer) fprintf (stderr, " n_datas: \t%u (offset %zd)\n", buffer->n_datas, buffer->datas); for (i = 0; i < buffer->n_datas; i++) { SpaData *d = &SPA_BUFFER_DATAS (buffer)[i]; - fprintf (stderr, " data %d: type %d\n", i, d->type); - switch (d->type) { - case SPA_DATA_TYPE_MEMPTR: - fprintf (stderr, " memptr %p\n", d->ptr); - break; - case SPA_DATA_TYPE_FD: - fprintf (stderr, " fd %d\n", SPA_PTR_TO_INT (d->ptr)); - break; - case SPA_DATA_TYPE_MEMID: - fprintf (stderr, " memid %d\n", SPA_PTR_TO_UINT32 (d->ptr)); - break; - case SPA_DATA_TYPE_POINTER: - fprintf (stderr, " pointer %p\n", d->ptr); - break; - default: - break; + SpaMemory *mem; + + mem = spa_memory_find (0, d->mem_id); + fprintf (stderr, " data %d: (memory %p)\n", i, mem); + if (mem) { + fprintf (stderr, " pool_id: %u\n", mem->pool_id); + fprintf (stderr, " id: %u\n", 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->offset); - fprintf (stderr, " size %zd:\n", d->size); - fprintf (stderr, " stride %zd:\n", d->stride); + 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; } diff --git a/spa/lib/memory.c b/spa/lib/memory.c index c202ef54d..cc79dffdb 100644 --- a/spa/lib/memory.c +++ b/spa/lib/memory.c @@ -17,7 +17,16 @@ * Boston, MA 02110-1301, USA. */ +#define _GNU_SOURCE + +#include +#include #include +#include +#include +#include +#include +#include #include "spa/memory.h" @@ -39,6 +48,7 @@ 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; @@ -103,12 +113,84 @@ spa_memory_alloc (uint32_t pool_id) mem = &pool->memories[id]; mem->refcount = 1; + mem->notify = NULL; mem->pool_id = pool_id; mem->id = id; return mem; } +SpaMemory * +spa_memory_alloc_with_fd (uint32_t pool_id, void *data, size_t size) +{ + SpaMemory *mem; + char filename[] = "/dev/shm/spa-tmpfile.XXXXXX"; + + if (!(mem = spa_memory_alloc (pool_id))) + return NULL; + + 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); + + 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; + } + } + + mem->flags = SPA_MEMORY_FLAG_READWRITE; + mem->ptr = NULL; + mem->size = size; + + return mem; +} + + +SpaMemory * +spa_memory_import (uint32_t pool_id, uint32_t id) +{ + SpaMemory *mem = NULL; + SpaMemoryPool *pool; + int i; + bool init = false; + + if (pool_id >= MAX_POOLS || !pools[pool_id].valid) + return NULL; + + 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->pool_id = pool_id; + mem->id = id; + } + + return mem; +} + SpaResult spa_memory_free (uint32_t pool_id, uint32_t id) { @@ -139,3 +221,27 @@ spa_memory_find (uint32_t pool_id, uint32_t id) return &pool->memories[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 %p: %s\n", mem, strerror (errno)); + } + return mem->ptr; +} diff --git a/spa/plugins/audiomixer/audiomixer.c b/spa/plugins/audiomixer/audiomixer.c index cb17f9974..1aa03666c 100644 --- a/spa/plugins/audiomixer/audiomixer.c +++ b/spa/plugins/audiomixer/audiomixer.c @@ -21,6 +21,7 @@ #include #include +#include #include #define MAX_PORTS 128 @@ -590,16 +591,19 @@ add_port_data (SpaAudioMixer *this, SpaBuffer *out, SpaAudioMixerPort *port) size_t os, is, chunk; SpaData *odatas = SPA_BUFFER_DATAS (out); SpaData *idatas = SPA_BUFFER_DATAS (port->buffer); + SpaMemory *mem; op = ip = NULL; while (true) { if (op == NULL) { - op = odatas[oi].ptr; + mem = spa_memory_find (0, odatas[oi].mem_id); + op = (uint8_t*)mem->ptr + odatas[oi].offset; os = odatas[oi].size; } if (ip == NULL) { - ip = idatas[port->buffer_index].ptr; + mem = spa_memory_find (0, idatas[port->buffer_index].mem_id); + ip = (uint8_t*)mem->ptr + odatas[oi].offset; is = idatas[port->buffer_index].size; ip += port->buffer_offset; is -= port->buffer_offset; diff --git a/spa/plugins/remote/proxy.c b/spa/plugins/remote/proxy.c index f5bdbdd6b..9673812ba 100644 --- a/spa/plugins/remote/proxy.c +++ b/spa/plugins/remote/proxy.c @@ -17,8 +17,6 @@ * Boston, MA 02110-1301, USA. */ -#define _GNU_SOURCE - #include #include #include @@ -31,6 +29,7 @@ #include +#include #include #define MAX_INPUTS 64 @@ -548,25 +547,6 @@ spa_proxy_node_port_get_status (SpaNode *node, return SPA_RESULT_OK; } -static int -tmpfile_create (void *data, size_t size) -{ - char filename[] = "/dev/shm/tmpfilepay.XXXXXX"; - int fd; - - fd = mkostemp (filename, O_CLOEXEC); - if (fd == -1) { - fprintf (stderr, "Failed to create temporary file: %s\n", strerror (errno)); - return -1; - } - unlink (filename); - - if (write (fd, data, size) != (ssize_t) size) - fprintf (stderr, "Failed to write data: %s\n", strerror (errno)); - - return fd; -} - static SpaResult add_buffer (SpaProxy *this, uint32_t port_id, SpaBuffer *buffer) { @@ -574,53 +554,57 @@ add_buffer (SpaProxy *this, uint32_t port_id, SpaBuffer *buffer) SpaControlBuilder builder; uint8_t buf[1024]; int fds[16]; + SpaControlCmdAddMem am; SpaControlCmdAddBuffer ab; - int fd, i; + int i; SpaResult res; SpaBuffer *b; + SpaMemory *bmem; spa_control_builder_init_into (&builder, buf, sizeof (buf), fds, sizeof (fds)); - fd = tmpfile_create (buffer, buffer->size); + if (buffer->mem_id == SPA_ID_INVALID) { + fprintf (stderr, "proxy %p: alloc buffer space\n", this); + bmem = spa_memory_alloc_with_fd (0, buffer, buffer->size); + b = spa_memory_ensure_ptr (bmem); + b->mem_id = bmem->id; + b->offset = 0; + } else { + bmem = spa_memory_find (0, buffer->mem_id); + b = buffer; + } + + am.port_id = port_id; + am.mem_id = bmem->id; + am.mem_type = 0; + am.fd_index = spa_control_builder_add_fd (&builder, bmem->fd, false); + am.flags = bmem->flags; + am.size = bmem->size; + spa_control_builder_add_cmd (&builder, SPA_CONTROL_CMD_ADD_MEM, &am); - b = mmap (NULL, buffer->size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); for (i = 0; i < b->n_datas; i++) { SpaData *d = &SPA_BUFFER_DATAS (b)[i]; - int fd; - SpaControlCmdAddMem am; - bool tmpfile; + SpaMemory *mem; - if (d->type == SPA_DATA_TYPE_FD) { - fd = SPA_PTR_TO_INT (d->ptr); - tmpfile = false; - } else if (d->type == SPA_DATA_TYPE_MEMPTR) { - fd = tmpfile_create (d->ptr, d->size + d->offset); - tmpfile = true; - } else { - fprintf (stderr, "proxy %p: invalid mem type received %d\n", this, d->type); + if (!(mem = spa_memory_find (0, d->mem_id))) { + fprintf (stderr, "proxy %p: error invalid memory\n", this); continue; } am.port_id = port_id; - am.mem_id = b->id * 64 + i; + am.mem_id = mem->id; am.mem_type = 0; - am.fd_index = spa_control_builder_add_fd (&builder, fd, tmpfile ? true : false); - am.offset = d->offset; - am.size = d->size; + am.fd_index = spa_control_builder_add_fd (&builder, mem->fd, false); + am.flags = mem->flags; + am.size = mem->size; spa_control_builder_add_cmd (&builder, SPA_CONTROL_CMD_ADD_MEM, &am); - - d->type = SPA_DATA_TYPE_MEMID; - d->ptr_type = NULL; - d->ptr = SPA_UINT32_TO_PTR (am.mem_id); - d->offset = 0; } ab.port_id = port_id; ab.buffer_id = b->id; - ab.fd_index = spa_control_builder_add_fd (&builder, fd, true); - ab.offset = 0; + ab.mem_id = bmem->id; + ab.offset = b->offset; ab.size = b->size; spa_control_builder_add_cmd (&builder, SPA_CONTROL_CMD_ADD_BUFFER, &ab); - munmap (b, buffer->size); spa_control_builder_end (&builder, &control); @@ -632,6 +616,71 @@ add_buffer (SpaProxy *this, uint32_t port_id, SpaBuffer *buffer) return SPA_RESULT_OK; } +#if 0 +static SpaResult +add_buffer (SpaProxy *this, uint32_t port_id, SpaBuffer *buffer) +{ + SpaControl control; + SpaControlBuilder builder; + uint8_t buf[1024]; + int fds[16]; + SpaControlCmdAddMem am; + SpaControlCmdAddBuffer ab; + int i; + SpaResult res; + SpaBuffer *b; + SpaMemory *bmem; + + spa_control_builder_init_into (&builder, buf, sizeof (buf), fds, sizeof (fds)); + + bmem = spa_memory_alloc_with_fd (0, buffer, buffer->size); + b = spa_memory_ensure_ptr (bmem); + b->mem_id = bmem->id; + b->offset = 0; + + am.port_id = port_id; + am.mem_id = bmem->id; + am.mem_type = 0; + am.fd_index = spa_control_builder_add_fd (&builder, bmem->fd, false); + am.offset = 0; + am.size = buffer->size; + spa_control_builder_add_cmd (&builder, SPA_CONTROL_CMD_ADD_MEM, &am); + + for (i = 0; i < b->n_datas; i++) { + SpaData *d = &SPA_BUFFER_DATAS (b)[i]; + SpaMemory *mem; + + if (!(mem = spa_memory_find (0, d->mem_id))) { + fprintf (stderr, "proxy %p: error invalid memory\n", this); + continue; + } + + am.port_id = port_id; + am.mem_id = mem->id; + am.mem_type = 0; + am.fd_index = spa_control_builder_add_fd (&builder, mem->fd, false); + am.offset = d->offset; + am.size = d->size; + spa_control_builder_add_cmd (&builder, SPA_CONTROL_CMD_ADD_MEM, &am); + } + ab.port_id = port_id; + ab.buffer_id = b->id; + ab.mem_id = bmem->id; + ab.offset = 0; + ab.size = b->size; + spa_control_builder_add_cmd (&builder, SPA_CONTROL_CMD_ADD_BUFFER, &ab); + + spa_control_builder_end (&builder, &control); + + if ((res = spa_control_write (&control, this->fds[0].fd)) < 0) + fprintf (stderr, "proxy %p: error writing control\n", this); + + spa_control_clear (&control); + + return SPA_RESULT_OK; +} +#endif + static SpaResult remove_buffer (SpaProxy *this, uint32_t port_id, SpaBuffer *buffer) { diff --git a/spa/plugins/v4l2/v4l2-source.c b/spa/plugins/v4l2/v4l2-source.c index 57db19114..fc0cbda5c 100644 --- a/spa/plugins/v4l2/v4l2-source.c +++ b/spa/plugins/v4l2/v4l2-source.c @@ -25,6 +25,7 @@ #include #include +#include #include #include @@ -54,8 +55,7 @@ struct _V4l2Buffer { SpaMeta metas[1]; SpaMetaHeader header; SpaData datas[1]; - SpaV4l2Source *source; - SpaBuffer *imported; + SpaBuffer *outbuf; bool outstanding; struct v4l2_buffer v4l2_buffer; V4l2Buffer *next; @@ -102,7 +102,8 @@ typedef struct { enum v4l2_memory memtype; struct v4l2_requestbuffers reqbuf; - V4l2Buffer buffers[MAX_BUFFERS]; + SpaMemory *alloc_mem; + V4l2Buffer *alloc_buffers; V4l2Buffer *ready; uint32_t ready_count; diff --git a/spa/plugins/v4l2/v4l2-utils.c b/spa/plugins/v4l2/v4l2-utils.c index 5aee58174..b7c96a235 100644 --- a/spa/plugins/v4l2/v4l2-utils.c +++ b/spa/plugins/v4l2/v4l2-utils.c @@ -408,7 +408,7 @@ spa_v4l2_set_format (SpaV4l2Source *this, V4l2Format *f, bool try_only) state->info.params = state->params; state->params[0] = &state->param_buffers.param; state->param_buffers.param.type = SPA_ALLOC_PARAM_TYPE_BUFFERS; - state->param_buffers.param.size = sizeof (&state->buffers); + state->param_buffers.param.size = sizeof (state->param_buffers); state->param_buffers.minsize = fmt.fmt.pix.sizeimage; state->param_buffers.stride = fmt.fmt.pix.bytesperline; state->param_buffers.min_buffers = 2; @@ -459,7 +459,9 @@ mmap_read (SpaV4l2Source *this) } } - b = &state->buffers[buf.index]; + b = &state->alloc_buffers[buf.index]; + b->header.seq = buf.sequence; + b->header.pts = (uint64_t)buf.timestamp.tv_sec * 1000000000lu + (uint64_t)buf.timestamp.tv_usec * 1000lu; b->next = state->ready; state->ready = b; state->ready_count++; @@ -489,7 +491,7 @@ static void spa_v4l2_buffer_recycle (SpaV4l2Source *this, uint32_t buffer_id) { SpaV4l2State *state = &this->state[0]; - V4l2Buffer *b = &state->buffers[buffer_id]; + V4l2Buffer *b = &state->alloc_buffers[buffer_id]; b->outstanding = false; @@ -523,24 +525,39 @@ spa_v4l2_import_buffers (SpaV4l2Source *this, SpaBuffer **buffers, uint32_t n_bu } state->reqbuf = reqbuf; + if (state->alloc_mem) + spa_memory_free (state->alloc_mem->pool_id, state->alloc_mem->id); + state->alloc_mem = spa_memory_alloc_with_fd (0, NULL, sizeof (V4l2Buffer) * reqbuf.count); + state->alloc_buffers = spa_memory_ensure_ptr (state->alloc_mem); + for (i = 0; i < reqbuf.count; i++) { V4l2Buffer *b; + uint32_t mem_id; + SpaMemory *mem; + SpaData *d = SPA_BUFFER_DATAS (buffers[i]); - b = &state->buffers[i]; + b = &state->alloc_buffers[i]; + b->buffer.mem_id = state->alloc_mem->id; + b->buffer.offset = sizeof (V4l2Buffer) * i; + b->buffer.size = sizeof (V4l2Buffer); + b->buffer.id = SPA_ID_INVALID; + b->outbuf = buffers[i]; + b->outstanding = true; fprintf (stderr, "import buffer %p\n", buffers[i]); - b->source = this; - b->buffer.id = SPA_ID_INVALID; - b->imported = buffers[i]; - b->outstanding = true; + mem_id = SPA_BUFFER_DATAS (buffers[i])[0].mem_id; + if (!(mem = spa_memory_find (0, mem_id))) { + fprintf (stderr, "invalid memory on buffer %p\n", buffers[i]); + continue; + } CLEAR (b->v4l2_buffer); b->v4l2_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; b->v4l2_buffer.memory = state->memtype; b->v4l2_buffer.index = i; - b->v4l2_buffer.m.userptr = (unsigned long) SPA_BUFFER_DATAS (buffers[i])[0].ptr; - b->v4l2_buffer.length = SPA_BUFFER_DATAS (buffers[i])[0].size; + b->v4l2_buffer.m.userptr = (unsigned long) ((uint8_t*)mem->ptr + d[0].offset); + b->v4l2_buffer.length = d[0].size; spa_v4l2_buffer_recycle (this, buffers[i]->id); } @@ -584,9 +601,15 @@ mmap_init (SpaV4l2Source *this, state->reqbuf = reqbuf; + if (state->alloc_mem) + spa_memory_free (state->alloc_mem->pool_id, state->alloc_mem->id); + state->alloc_mem = spa_memory_alloc_with_fd (0, NULL, sizeof (V4l2Buffer) * reqbuf.count); + state->alloc_buffers = spa_memory_ensure_ptr (state->alloc_mem); + for (i = 0; i < reqbuf.count; i++) { struct v4l2_buffer buf; V4l2Buffer *b; + SpaMemory *mem; CLEAR (buf); buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; @@ -598,13 +621,14 @@ mmap_init (SpaV4l2Source *this, return SPA_RESULT_ERROR; } - b = &state->buffers[i]; + b = &state->alloc_buffers[i]; + b->buffer.id = i; + b->buffer.mem_id = state->alloc_mem->id; + b->buffer.offset = sizeof (V4l2Buffer) * i; + b->buffer.size = sizeof (V4l2Buffer); buffers[i] = &b->buffer; - b->source = this; - b->buffer.id = i; - b->buffer.size = sizeof (V4l2Buffer); b->buffer.n_metas = 1; b->buffer.metas = offsetof (V4l2Buffer, metas); b->buffer.n_datas = 1; @@ -619,6 +643,14 @@ mmap_init (SpaV4l2Source *this, b->metas[0].offset = offsetof (V4l2Buffer, header); b->metas[0].size = sizeof (b->header); + mem = spa_memory_alloc (0); + mem->flags = SPA_MEMORY_FLAG_READABLE; + mem->size = buf.length; + b->datas[0].mem_id = mem->id; + b->datas[0].offset = 0; + b->datas[0].size = buf.length; + b->datas[0].stride = state->fmt.fmt.pix.bytesperline; + if (state->export_buf) { struct v4l2_exportbuffer expbuf; @@ -630,39 +662,25 @@ mmap_init (SpaV4l2Source *this, continue; } + mem->fd = expbuf.fd; + mem->type = "dmabuf"; + mem->ptr = NULL; b->dmafd = expbuf.fd; - b->datas[0].type = SPA_DATA_TYPE_FD; - b->datas[0].ptr = SPA_INT_TO_PTR (b->dmafd); - b->datas[0].ptr_type = "dmabuf"; - b->datas[0].offset = 0; - b->datas[0].size = buf.length; - b->datas[0].stride = state->fmt.fmt.pix.bytesperline; } else { -#if 1 - b->datas[0].type = SPA_DATA_TYPE_MEMPTR; - b->datas[0].ptr_type = "sysmem"; - b->datas[0].ptr = mmap (NULL, - buf.length, - PROT_READ | PROT_WRITE, - MAP_SHARED, - state->fd, - buf.m.offset); - b->datas[0].offset = 0; - b->datas[0].size = buf.length; - if (b->datas[0].ptr == MAP_FAILED) { + mem->fd = -1; + mem->type = "sysmem"; + mem->ptr = mmap (NULL, + buf.length, + PROT_READ | PROT_WRITE, + MAP_SHARED, + state->fd, + buf.m.offset); + if (mem->ptr == MAP_FAILED) { perror ("mmap"); continue; } -#else - b->datas[0].type = SPA_DATA_TYPE_FD; - b->datas[0].ptr = &state->fd; - b->datas[0].ptr_type = "dmabuf"; - b->datas[0].offset = buf.m.offset; - b->datas[0].size = buf.length; - b->datas[0].stride = state->fmt.fmt.pix.bytesperline; -#endif } - b->imported = &b->buffer; + b->outbuf = &b->buffer; b->outstanding = true; CLEAR (b->v4l2_buffer); @@ -772,17 +790,20 @@ spa_v4l2_stop (SpaV4l2Source *this) for (i = 0; i < state->reqbuf.count; i++) { V4l2Buffer *b; + SpaMemory *mem; - b = &state->buffers[i]; + b = &state->alloc_buffers[i]; if (b->outstanding) { fprintf (stderr, "queueing outstanding buffer %p\n", b); spa_v4l2_buffer_recycle (this, i); } + mem = spa_memory_find (0, b->datas[0].mem_id); if (state->export_buf) { - close (b->dmafd); + close (mem->fd); } else { - munmap (b->datas[0].ptr, b->datas[0].size); + munmap (mem->ptr, mem->size); } + spa_memory_free (0, mem->id); } state->have_buffers = false; diff --git a/spa/plugins/volume/volume.c b/spa/plugins/volume/volume.c index 46f060e21..6548b6cc9 100644 --- a/spa/plugins/volume/volume.c +++ b/spa/plugins/volume/volume.c @@ -21,6 +21,7 @@ #include #include +#include #include typedef struct _SpaVolume SpaVolume; @@ -550,6 +551,7 @@ spa_volume_node_port_pull_output (SpaNode *node, SpaData *sd, *dd; uint16_t *src, *dst; double volume; + SpaMemory *sm, *dm; if (node == NULL || node->handle == NULL || n_info == 0 || info == NULL) return SPA_RESULT_INVALID_ARGUMENTS; @@ -581,16 +583,11 @@ spa_volume_node_port_pull_output (SpaNode *node, sd = &SPA_BUFFER_DATAS (sbuf)[si]; dd = &SPA_BUFFER_DATAS (dbuf)[di]; - if (sd->type != SPA_DATA_TYPE_MEMPTR) { - si++; - continue; - } - if (dd->type != SPA_DATA_TYPE_MEMPTR) { - di++; - continue; - } - src = (uint16_t*) ((uint8_t*)sd->ptr + soff); - dst = (uint16_t*) ((uint8_t*)dd->ptr + doff); + sm = spa_memory_find (0, sd->mem_id); + dm = spa_memory_find (0, dd->mem_id); + + src = (uint16_t*) ((uint8_t*)sm->ptr + sd->offset + soff); + dst = (uint16_t*) ((uint8_t*)dm->ptr + dd->offset + doff); n_bytes = SPA_MIN (sd->size - soff, dd->size - doff); n_samples = n_bytes / sizeof (uint16_t); diff --git a/spa/tests/test-v4l2.c b/spa/tests/test-v4l2.c index d98d30a0a..0ff3b3676 100644 --- a/spa/tests/test-v4l2.c +++ b/spa/tests/test-v4l2.c @@ -30,6 +30,7 @@ #include #include +#include #include #undef USE_BUFFER @@ -123,6 +124,7 @@ on_source_event (SpaNode *node, SpaEvent *event, void *user_data) uint8_t *src, *dst; SpaMeta *metas; SpaData *datas; + SpaMemory *mem; if ((res = spa_node_port_pull_output (data->source, 1, info)) < 0) printf ("got pull error %d\n", res); @@ -146,8 +148,11 @@ on_source_event (SpaNode *node, SpaEvent *event, void *user_data) fprintf (stderr, "Couldn't lock texture: %s\n", SDL_GetError()); return; } - datas[0].ptr = sdata; - datas[0].ptr_type = "sysmem"; + mem = spa_memory_find (0, datas[0].mem_id); + mem->ptr = sdata; + mem->type = "sysmem"; + mem->size = sstride * 240; + datas[0].size = sstride * 240; datas[0].stride = sstride; } else { @@ -155,7 +160,9 @@ on_source_event (SpaNode *node, SpaEvent *event, void *user_data) fprintf (stderr, "Couldn't lock texture: %s\n", SDL_GetError()); return; } - sdata = datas[0].ptr; + mem = spa_memory_find (0, datas[0].mem_id); + + sdata = spa_memory_ensure_ptr (mem); sstride = datas[0].stride; for (i = 0; i < 240; i++) { @@ -438,6 +445,8 @@ main (int argc, char *argv[]) AppData data; SpaResult res; + spa_memory_init (); + if (SDL_Init (SDL_INIT_VIDEO) < 0) { printf ("can't initialize SDL: %s\n", SDL_GetError ()); return -1;