Make buffer data point to memory blocks

Make buffer data point to a registered memory block by its mem_id.
Add some more helpers to allocate memfd backed memory.
Allocate buffers in memfd so that we easily share them between client
and server.
Update pts and seq in v4l2 now that this change will actually be visible
at the client.
This commit is contained in:
Wim Taymans 2016-08-03 21:33:57 +02:00
parent 98993c680b
commit 1169c2419b
19 changed files with 383 additions and 356 deletions

View file

@ -20,6 +20,7 @@
#include <gst/gst.h> #include <gst/gst.h>
#include "pinos/client/pinos.h" #include "pinos/client/pinos.h"
#include "spa/include/spa/memory.h"
/** /**
* pinos_init: * pinos_init:
@ -33,6 +34,7 @@ void
pinos_init (int *argc, char **argv[]) pinos_init (int *argc, char **argv[])
{ {
gst_init (argc, argv); gst_init (argc, argv);
spa_memory_init ();
} }
/** /**

View file

@ -33,23 +33,12 @@
#include "pinos/client/private.h" #include "pinos/client/private.h"
#include "spa/include/spa/control.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_BUFFER_SIZE 1024
#define MAX_FDS 16 #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 { typedef struct {
bool cleanup; bool cleanup;
uint32_t id; uint32_t id;
@ -104,7 +93,6 @@ struct _PinosStreamPrivate
guint8 send_data[MAX_BUFFER_SIZE]; guint8 send_data[MAX_BUFFER_SIZE];
int send_fds[MAX_FDS]; int send_fds[MAX_FDS];
GArray *mem_ids;
GArray *buffer_ids; GArray *buffer_ids;
}; };
@ -430,8 +418,6 @@ pinos_stream_init (PinosStream * stream)
g_debug ("new stream %p", stream); g_debug ("new stream %p", stream);
priv->state = PINOS_STREAM_STATE_UNCONNECTED; 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); priv->buffer_ids = g_array_sized_new (FALSE, FALSE, sizeof (BufferId), 64);
g_array_set_clear_func (priv->buffer_ids, (GDestroyNotify) clear_buffer_id); 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; 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 static gboolean
parse_control (PinosStream *stream, parse_control (PinosStream *stream,
SpaControl *ctrl) SpaControl *ctrl)
@ -664,7 +637,7 @@ parse_control (PinosStream *stream,
case SPA_CONTROL_CMD_ADD_MEM: case SPA_CONTROL_CMD_ADD_MEM:
{ {
SpaControlCmdAddMem p; SpaControlCmdAddMem p;
MemId mid; SpaMemory *mem;
int fd; int fd;
if (spa_control_iter_parse_cmd (&it, &p) < 0) if (spa_control_iter_parse_cmd (&it, &p) < 0)
@ -674,44 +647,44 @@ parse_control (PinosStream *stream,
if (fd == -1) if (fd == -1)
break; break;
g_debug ("add mem %d, %d", p.mem_id, fd); g_debug ("add mem %d, %d, %d", p.mem_id, fd, p.flags);
mid.cleanup = false; mem = spa_memory_import (0, p.mem_id);
mid.id = p.mem_id; mem->flags = p.flags;
mid.fd = fd; mem->fd = fd;
g_array_append_val (priv->mem_ids, mid); mem->ptr = NULL;
mem->size = p.size;
break; break;
} }
case SPA_CONTROL_CMD_REMOVE_MEM: case SPA_CONTROL_CMD_REMOVE_MEM:
{ {
SpaControlCmdRemoveMem p; SpaControlCmdRemoveMem p;
MemId *mid; SpaMemory *mem;
if (spa_control_iter_parse_cmd (&it, &p) < 0) if (spa_control_iter_parse_cmd (&it, &p) < 0)
break; break;
g_debug ("stream %p: stop", stream); g_debug ("stream %p: stop", stream);
if ((mid = find_mem (stream, p.mem_id))) mem = spa_memory_find (0, p.mem_id);
mid->cleanup = true; if (--mem->refcount == 0)
mem->notify (mem);
break; break;
} }
case SPA_CONTROL_CMD_ADD_BUFFER: case SPA_CONTROL_CMD_ADD_BUFFER:
{ {
SpaControlCmdAddBuffer p; SpaControlCmdAddBuffer p;
BufferId bid; BufferId bid;
SpaMemory *mem;
if (spa_control_iter_parse_cmd (&it, &p) < 0) if (spa_control_iter_parse_cmd (&it, &p) < 0)
break; 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); g_debug ("add buffer %d", p.buffer_id);
mem = spa_memory_find (0, p.mem_id);
bid.cleanup = false; bid.cleanup = false;
bid.id = p.buffer_id; bid.id = p.buffer_id;
bid.offset = p.offset; bid.offset = p.offset;
bid.size = p.size; 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); spa_debug_buffer (bid.buf);
g_array_append_val (priv->buffer_ids, bid); g_array_append_val (priv->buffer_ids, bid);
@ -733,29 +706,16 @@ parse_control (PinosStream *stream,
case SPA_CONTROL_CMD_PROCESS_BUFFER: case SPA_CONTROL_CMD_PROCESS_BUFFER:
{ {
SpaControlCmdProcessBuffer p; SpaControlCmdProcessBuffer p;
unsigned int i;
BufferId *bid; BufferId *bid;
if (spa_control_iter_parse_cmd (&it, &p) < 0) if (spa_control_iter_parse_cmd (&it, &p) < 0)
break; break;
if ((bid = find_buffer (stream, p.buffer_id))) { if ((bid = find_buffer (stream, p.buffer_id))) {
SpaBuffer *b = bid->buf; priv->buffer = bid->buf;
SpaData *d = SPA_BUFFER_DATAS (b); spa_debug_buffer (bid->buf);
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;
} }
break; break;
} }
case SPA_CONTROL_CMD_REUSE_BUFFER: case SPA_CONTROL_CMD_REUSE_BUFFER:
@ -810,13 +770,6 @@ on_socket_condition (GSocket *socket,
send_need_input (stream, 0, priv->buffer->id); send_need_input (stream, 0, priv->buffer->id);
priv->buffer = NULL; 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++) { for (i = 0; i < priv->buffer_ids->len; i++) {
BufferId *bid = &g_array_index (priv->buffer_ids, BufferId, i); BufferId *bid = &g_array_index (priv->buffer_ids, BufferId, i);
if (bid->cleanup) { if (bid->cleanup) {

View file

@ -24,6 +24,7 @@
#include <server/daemon.h> #include <server/daemon.h>
#include <modules/gst/gst-manager.h> #include <modules/gst/gst-manager.h>
#include <modules/gst/gst-node-factory.h> #include <modules/gst/gst-node-factory.h>
#include <spa/include/spa/memory.h>
gint gint
main (gint argc, gchar *argv[]) main (gint argc, gchar *argv[])
@ -34,6 +35,7 @@ main (gint argc, gchar *argv[])
PinosNodeFactory *factory; PinosNodeFactory *factory;
pinos_init (&argc, &argv); pinos_init (&argc, &argv);
spa_memory_init ();
loop = g_main_loop_new (NULL, FALSE); loop = g_main_loop_new (NULL, FALSE);

View file

@ -46,6 +46,8 @@ GST_DEBUG_CATEGORY (pinos_debug);
static gboolean static gboolean
plugin_init (GstPlugin * plugin) plugin_init (GstPlugin * plugin)
{ {
pinos_init (NULL, NULL);
// gst_element_register (plugin, "pinospay", GST_RANK_NONE, // gst_element_register (plugin, "pinospay", GST_RANK_NONE,
// GST_TYPE_PINOS_PAY); // GST_TYPE_PINOS_PAY);
// gst_element_register (plugin, "pinosdepay", GST_RANK_NONE, // gst_element_register (plugin, "pinosdepay", GST_RANK_NONE,

View file

@ -562,9 +562,8 @@ gst_pinos_sink_render (GstBaseSink * bsink, GstBuffer * buffer)
b->mem = mem; b->mem = mem;
b->fd = gst_fd_memory_get_fd (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].mem_id = 0;
b->datas[0].ptr_type = mem->allocator->mem_type;
b->datas[0].offset = mem->offset; b->datas[0].offset = mem->offset;
b->datas[0].size = mem->size; b->datas[0].size = mem->size;
b->datas[0].stride = 0; b->datas[0].stride = 0;

View file

@ -44,6 +44,7 @@
#include <gst/allocators/gstfdmemory.h> #include <gst/allocators/gstfdmemory.h>
#include <gst/video/video.h> #include <gst/video/video.h>
#include <spa/include/spa/memory.h>
#include <spa/include/spa/buffer.h> #include <spa/include/spa/buffer.h>
@ -385,28 +386,21 @@ on_new_buffer (GObject *gobject,
} }
for (i = 0; i < b->n_datas; i++) { for (i = 0; i < b->n_datas; i++) {
SpaData *d = &SPA_BUFFER_DATAS (b)[i]; SpaData *d = &SPA_BUFFER_DATAS (b)[i];
SpaMemory *mem;
switch (d->type) { mem = spa_memory_find (0, d->mem_id);
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);
fdmem = gst_fd_allocator_alloc (pinossrc->fd_allocator, dup (fd), if (mem->fd) {
d->offset + d->size, GST_FD_MEMORY_FLAG_NONE); GstMemory *fdmem = NULL;
gst_memory_resize (fdmem, d->offset, d->size);
gst_buffer_append_memory (buf, fdmem); fdmem = gst_fd_allocator_alloc (pinossrc->fd_allocator, dup (mem->fd),
break; d->offset + d->size, GST_FD_MEMORY_FLAG_NONE);
} gst_memory_resize (fdmem, d->offset, d->size);
default: gst_buffer_append_memory (buf, fdmem);
break; } else {
gst_buffer_append_memory (buf,
gst_memory_new_wrapped (0, mem->ptr, mem->size, d->offset,
d->size, NULL, NULL));
} }
} }

View file

@ -27,6 +27,7 @@
#include <gio/gio.h> #include <gio/gio.h>
#include <spa/include/spa/node.h> #include <spa/include/spa/node.h>
#include <spa/include/spa/memory.h>
#include <spa/include/spa/audio/format.h> #include <spa/include/spa/audio/format.h>
#include "spa-alsa-sink.h" #include "spa-alsa-sink.h"
@ -438,15 +439,15 @@ on_received_buffer (PinosPort *port,
for (i = 0; i < buffer->n_datas; i++) { for (i = 0; i < buffer->n_datas; i++) {
SpaData *d = SPA_BUFFER_DATAS (buffer); SpaData *d = SPA_BUFFER_DATAS (buffer);
SpaMemory *mem;
PinosRingbufferArea areas[2]; PinosRingbufferArea areas[2];
uint8_t *data; uint8_t *data;
size_t size, towrite, total; size_t size, towrite, total;
if (d[i].type != SPA_DATA_TYPE_MEMPTR) mem = spa_memory_find (0, d[i].mem_id);
continue;
size = d[i].size; 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); pinos_ringbuffer_get_write_areas (priv->ringbuffer, areas);

View file

@ -98,39 +98,15 @@ typedef struct {
size_t size; size_t size;
} SpaMeta; } 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: * SpaData:
* @id: user id * @mem_id: the memory id to use
* @type: the type of data * @offset: offset of memory
* @ptr_type: more info about the type of @ptr * @size: size of memory
* @ptr: pointer to data or fd * @stride: stride of memory if applicable
* @offset: offset of data
* @size: size of data
* @stride: stride of data if applicable
*/ */
typedef struct { typedef struct {
SpaDataType type; uint32_t mem_id;
const char *ptr_type;
void *ptr;
off_t offset; off_t offset;
size_t size; size_t size;
size_t stride; size_t stride;
@ -139,6 +115,8 @@ typedef struct {
/** /**
* SpaBuffer: * SpaBuffer:
* @id: buffer id * @id: buffer id
* @mem_id: memory id of the buffer
* @offset: offset into the memory
* @size: total size of the buffer structure * @size: total size of the buffer structure
* @n_metas: number of metadata * @n_metas: number of metadata
* @metas: offset of array of @n_metas metadata * @metas: offset of array of @n_metas metadata
@ -147,6 +125,8 @@ typedef struct {
*/ */
struct _SpaBuffer { struct _SpaBuffer {
uint32_t id; uint32_t id;
uint32_t mem_id;
off_t offset;
size_t size; size_t size;
unsigned int n_metas; unsigned int n_metas;
off_t metas; off_t metas;

View file

@ -165,7 +165,7 @@ typedef struct {
uint32_t mem_id; uint32_t mem_id;
uint32_t mem_type; uint32_t mem_type;
uint32_t fd_index; uint32_t fd_index;
uint64_t offset; uint32_t flags;
uint64_t size; uint64_t size;
} SpaControlCmdAddMem; } SpaControlCmdAddMem;
@ -179,7 +179,7 @@ typedef struct {
typedef struct { typedef struct {
uint32_t port_id; uint32_t port_id;
uint32_t buffer_id; uint32_t buffer_id;
int fd_index; uint32_t mem_id;
uint64_t offset; uint64_t offset;
uint64_t size; uint64_t size;
} SpaControlCmdAddBuffer; } SpaControlCmdAddBuffer;

View file

@ -41,6 +41,8 @@ typedef enum {
SPA_MEMORY_FLAG_WRITABLE = (1 << 1), SPA_MEMORY_FLAG_WRITABLE = (1 << 1),
} SpaMemoryFlags; } SpaMemoryFlags;
#define SPA_MEMORY_FLAG_READWRITE (SPA_MEMORY_FLAG_READABLE|SPA_MEMORY_FLAG_WRITABLE)
/** /**
* SpaMemory: * SpaMemory:
* @refcount: a refcount * @refcount: a refcount
@ -65,15 +67,21 @@ struct _SpaMemory {
size_t size; size_t size;
}; };
void spa_memory_init (void);
uint32_t spa_memory_pool_get (uint32_t type); uint32_t spa_memory_pool_get (uint32_t type);
uint32_t spa_memory_pool_new (void); uint32_t spa_memory_pool_new (void);
void spa_memory_pool_free (uint32_t); void spa_memory_pool_free (uint32_t);
SpaMemory * spa_memory_alloc (uint32_t pool_id); 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); 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); SpaMemory * spa_memory_find (uint32_t pool_id, uint32_t id);
void * spa_memory_ensure_ptr (SpaMemory *mem);
#ifdef __cplusplus #ifdef __cplusplus
} /* extern "C" */ } /* extern "C" */
#endif #endif

View file

@ -339,54 +339,6 @@ spa_control_iter_get_data (SpaControlIter *iter, size_t *size)
return si->data; 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 SpaResult
spa_control_iter_parse_cmd (SpaControlIter *iter, spa_control_iter_parse_cmd (SpaControlIter *iter,
void *command) void *command)
@ -719,60 +671,6 @@ builder_add_cmd (struct stack_builder *sb, SpaControlCmd cmd, size_t size)
return p; 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: * spa_control_builder_add_cmd:
* @builder: a #SpaControlBuilder * @builder: a #SpaControlBuilder

View file

@ -20,6 +20,7 @@
#include <stdio.h> #include <stdio.h>
#include "spa/debug.h" #include "spa/debug.h"
#include "spa/memory.h"
SpaResult SpaResult
spa_debug_port_info (const SpaPortInfo *info) spa_debug_port_info (const SpaPortInfo *info)
@ -88,9 +89,11 @@ spa_debug_buffer (const SpaBuffer *buffer)
return SPA_RESULT_INVALID_ARGUMENTS; return SPA_RESULT_INVALID_ARGUMENTS;
fprintf (stderr, "SpaBuffer %p:\n", buffer); fprintf (stderr, "SpaBuffer %p:\n", buffer);
fprintf (stderr, " id: \t%08x\n", buffer->id); fprintf (stderr, " id: %08X\n", buffer->id);
fprintf (stderr, " size: \t%zd\n", buffer->size); fprintf (stderr, " mem_id: %08X\n", buffer->mem_id);
fprintf (stderr, " n_metas: \t%u (offset %zd)\n", buffer->n_metas, buffer->metas); 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++) { for (i = 0; i < buffer->n_metas; i++) {
SpaMeta *m = &SPA_BUFFER_METAS (buffer)[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); 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); fprintf (stderr, " n_datas: \t%u (offset %zd)\n", buffer->n_datas, buffer->datas);
for (i = 0; i < buffer->n_datas; i++) { for (i = 0; i < buffer->n_datas; i++) {
SpaData *d = &SPA_BUFFER_DATAS (buffer)[i]; SpaData *d = &SPA_BUFFER_DATAS (buffer)[i];
fprintf (stderr, " data %d: type %d\n", i, d->type); SpaMemory *mem;
switch (d->type) {
case SPA_DATA_TYPE_MEMPTR: mem = spa_memory_find (0, d->mem_id);
fprintf (stderr, " memptr %p\n", d->ptr); fprintf (stderr, " data %d: (memory %p)\n", i, mem);
break; if (mem) {
case SPA_DATA_TYPE_FD: fprintf (stderr, " pool_id: %u\n", mem->pool_id);
fprintf (stderr, " fd %d\n", SPA_PTR_TO_INT (d->ptr)); fprintf (stderr, " id: %u\n", mem->id);
break; fprintf (stderr, " flags: %08x\n", mem->flags);
case SPA_DATA_TYPE_MEMID: fprintf (stderr, " type: %s\n", mem->type ? mem->type : "*unknown*");
fprintf (stderr, " memid %d\n", SPA_PTR_TO_UINT32 (d->ptr)); fprintf (stderr, " fd: %d\n", mem->fd);
break; fprintf (stderr, " ptr: %p\n", mem->ptr);
case SPA_DATA_TYPE_POINTER: fprintf (stderr, " size: %zd\n", mem->size);
fprintf (stderr, " pointer %p\n", d->ptr); } else {
break; fprintf (stderr, " invalid memory reference\n");
default:
break;
} }
fprintf (stderr, " offset %zd:\n", d->offset); fprintf (stderr, " offset: %zd\n", d->offset);
fprintf (stderr, " size %zd:\n", d->size); fprintf (stderr, " size: %zd\n", d->size);
fprintf (stderr, " stride %zd:\n", d->stride); fprintf (stderr, " stride: %zd\n", d->stride);
} }
return SPA_RESULT_OK; return SPA_RESULT_OK;
} }

View file

@ -17,7 +17,16 @@
* Boston, MA 02110-1301, USA. * Boston, MA 02110-1301, USA.
*/ */
#define _GNU_SOURCE
#include <string.h>
#include <stddef.h>
#include <stdio.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 "spa/memory.h"
@ -39,6 +48,7 @@ spa_memory_pool_init (SpaMemoryPool *pool, uint32_t id)
{ {
int i; int i;
memset (pool, 0, sizeof (SpaMemoryPool));
for (i = 0; i < MAX_MEMORIES; i++) for (i = 0; i < MAX_MEMORIES; i++)
pool->free_mem[i] = MAX_MEMORIES - 1 - i; pool->free_mem[i] = MAX_MEMORIES - 1 - i;
pool->n_free = MAX_MEMORIES; pool->n_free = MAX_MEMORIES;
@ -103,12 +113,84 @@ spa_memory_alloc (uint32_t pool_id)
mem = &pool->memories[id]; mem = &pool->memories[id];
mem->refcount = 1; mem->refcount = 1;
mem->notify = NULL;
mem->pool_id = pool_id; mem->pool_id = pool_id;
mem->id = id; mem->id = id;
return mem; 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 SpaResult
spa_memory_free (uint32_t pool_id, uint32_t id) 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]; 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;
}

View file

@ -21,6 +21,7 @@
#include <stdio.h> #include <stdio.h>
#include <spa/node.h> #include <spa/node.h>
#include <spa/memory.h>
#include <spa/audio/format.h> #include <spa/audio/format.h>
#define MAX_PORTS 128 #define MAX_PORTS 128
@ -590,16 +591,19 @@ add_port_data (SpaAudioMixer *this, SpaBuffer *out, SpaAudioMixerPort *port)
size_t os, is, chunk; size_t os, is, chunk;
SpaData *odatas = SPA_BUFFER_DATAS (out); SpaData *odatas = SPA_BUFFER_DATAS (out);
SpaData *idatas = SPA_BUFFER_DATAS (port->buffer); SpaData *idatas = SPA_BUFFER_DATAS (port->buffer);
SpaMemory *mem;
op = ip = NULL; op = ip = NULL;
while (true) { while (true) {
if (op == NULL) { 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; os = odatas[oi].size;
} }
if (ip == NULL) { 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; is = idatas[port->buffer_index].size;
ip += port->buffer_offset; ip += port->buffer_offset;
is -= port->buffer_offset; is -= port->buffer_offset;

View file

@ -17,8 +17,6 @@
* Boston, MA 02110-1301, USA. * Boston, MA 02110-1301, USA.
*/ */
#define _GNU_SOURCE
#include <string.h> #include <string.h>
#include <stddef.h> #include <stddef.h>
#include <stdio.h> #include <stdio.h>
@ -31,6 +29,7 @@
#include <spa/node.h> #include <spa/node.h>
#include <spa/memory.h>
#include <spa/control.h> #include <spa/control.h>
#define MAX_INPUTS 64 #define MAX_INPUTS 64
@ -548,25 +547,6 @@ spa_proxy_node_port_get_status (SpaNode *node,
return SPA_RESULT_OK; 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 static SpaResult
add_buffer (SpaProxy *this, uint32_t port_id, SpaBuffer *buffer) 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; SpaControlBuilder builder;
uint8_t buf[1024]; uint8_t buf[1024];
int fds[16]; int fds[16];
SpaControlCmdAddMem am;
SpaControlCmdAddBuffer ab; SpaControlCmdAddBuffer ab;
int fd, i; int i;
SpaResult res; SpaResult res;
SpaBuffer *b; SpaBuffer *b;
SpaMemory *bmem;
spa_control_builder_init_into (&builder, buf, sizeof (buf), fds, sizeof (fds)); 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++) { for (i = 0; i < b->n_datas; i++) {
SpaData *d = &SPA_BUFFER_DATAS (b)[i]; SpaData *d = &SPA_BUFFER_DATAS (b)[i];
int fd; SpaMemory *mem;
SpaControlCmdAddMem am;
bool tmpfile;
if (d->type == SPA_DATA_TYPE_FD) { if (!(mem = spa_memory_find (0, d->mem_id))) {
fd = SPA_PTR_TO_INT (d->ptr); fprintf (stderr, "proxy %p: error invalid memory\n", this);
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);
continue; continue;
} }
am.port_id = port_id; am.port_id = port_id;
am.mem_id = b->id * 64 + i; am.mem_id = mem->id;
am.mem_type = 0; am.mem_type = 0;
am.fd_index = spa_control_builder_add_fd (&builder, fd, tmpfile ? true : false); am.fd_index = spa_control_builder_add_fd (&builder, mem->fd, false);
am.offset = d->offset; am.flags = mem->flags;
am.size = d->size; am.size = mem->size;
spa_control_builder_add_cmd (&builder, SPA_CONTROL_CMD_ADD_MEM, &am); 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.port_id = port_id;
ab.buffer_id = b->id; ab.buffer_id = b->id;
ab.fd_index = spa_control_builder_add_fd (&builder, fd, true); ab.mem_id = bmem->id;
ab.offset = 0; ab.offset = b->offset;
ab.size = b->size; ab.size = b->size;
spa_control_builder_add_cmd (&builder, SPA_CONTROL_CMD_ADD_BUFFER, &ab); spa_control_builder_add_cmd (&builder, SPA_CONTROL_CMD_ADD_BUFFER, &ab);
munmap (b, buffer->size);
spa_control_builder_end (&builder, &control); spa_control_builder_end (&builder, &control);
@ -632,6 +616,71 @@ add_buffer (SpaProxy *this, uint32_t port_id, SpaBuffer *buffer)
return SPA_RESULT_OK; 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 static SpaResult
remove_buffer (SpaProxy *this, uint32_t port_id, SpaBuffer *buffer) remove_buffer (SpaProxy *this, uint32_t port_id, SpaBuffer *buffer)
{ {

View file

@ -25,6 +25,7 @@
#include <linux/videodev2.h> #include <linux/videodev2.h>
#include <spa/node.h> #include <spa/node.h>
#include <spa/memory.h>
#include <spa/video/format.h> #include <spa/video/format.h>
#include <spa/debug.h> #include <spa/debug.h>
@ -54,8 +55,7 @@ struct _V4l2Buffer {
SpaMeta metas[1]; SpaMeta metas[1];
SpaMetaHeader header; SpaMetaHeader header;
SpaData datas[1]; SpaData datas[1];
SpaV4l2Source *source; SpaBuffer *outbuf;
SpaBuffer *imported;
bool outstanding; bool outstanding;
struct v4l2_buffer v4l2_buffer; struct v4l2_buffer v4l2_buffer;
V4l2Buffer *next; V4l2Buffer *next;
@ -102,7 +102,8 @@ typedef struct {
enum v4l2_memory memtype; enum v4l2_memory memtype;
struct v4l2_requestbuffers reqbuf; struct v4l2_requestbuffers reqbuf;
V4l2Buffer buffers[MAX_BUFFERS]; SpaMemory *alloc_mem;
V4l2Buffer *alloc_buffers;
V4l2Buffer *ready; V4l2Buffer *ready;
uint32_t ready_count; uint32_t ready_count;

View file

@ -408,7 +408,7 @@ spa_v4l2_set_format (SpaV4l2Source *this, V4l2Format *f, bool try_only)
state->info.params = state->params; state->info.params = state->params;
state->params[0] = &state->param_buffers.param; state->params[0] = &state->param_buffers.param;
state->param_buffers.param.type = SPA_ALLOC_PARAM_TYPE_BUFFERS; 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.minsize = fmt.fmt.pix.sizeimage;
state->param_buffers.stride = fmt.fmt.pix.bytesperline; state->param_buffers.stride = fmt.fmt.pix.bytesperline;
state->param_buffers.min_buffers = 2; 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; b->next = state->ready;
state->ready = b; state->ready = b;
state->ready_count++; state->ready_count++;
@ -489,7 +491,7 @@ static void
spa_v4l2_buffer_recycle (SpaV4l2Source *this, uint32_t buffer_id) spa_v4l2_buffer_recycle (SpaV4l2Source *this, uint32_t buffer_id)
{ {
SpaV4l2State *state = &this->state[0]; SpaV4l2State *state = &this->state[0];
V4l2Buffer *b = &state->buffers[buffer_id]; V4l2Buffer *b = &state->alloc_buffers[buffer_id];
b->outstanding = false; b->outstanding = false;
@ -523,24 +525,39 @@ spa_v4l2_import_buffers (SpaV4l2Source *this, SpaBuffer **buffers, uint32_t n_bu
} }
state->reqbuf = reqbuf; 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++) { for (i = 0; i < reqbuf.count; i++) {
V4l2Buffer *b; 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]); fprintf (stderr, "import buffer %p\n", buffers[i]);
b->source = this; mem_id = SPA_BUFFER_DATAS (buffers[i])[0].mem_id;
b->buffer.id = SPA_ID_INVALID; if (!(mem = spa_memory_find (0, mem_id))) {
b->imported = buffers[i]; fprintf (stderr, "invalid memory on buffer %p\n", buffers[i]);
b->outstanding = true; continue;
}
CLEAR (b->v4l2_buffer); CLEAR (b->v4l2_buffer);
b->v4l2_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; b->v4l2_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
b->v4l2_buffer.memory = state->memtype; b->v4l2_buffer.memory = state->memtype;
b->v4l2_buffer.index = i; b->v4l2_buffer.index = i;
b->v4l2_buffer.m.userptr = (unsigned long) SPA_BUFFER_DATAS (buffers[i])[0].ptr; b->v4l2_buffer.m.userptr = (unsigned long) ((uint8_t*)mem->ptr + d[0].offset);
b->v4l2_buffer.length = SPA_BUFFER_DATAS (buffers[i])[0].size; b->v4l2_buffer.length = d[0].size;
spa_v4l2_buffer_recycle (this, buffers[i]->id); spa_v4l2_buffer_recycle (this, buffers[i]->id);
} }
@ -584,9 +601,15 @@ mmap_init (SpaV4l2Source *this,
state->reqbuf = reqbuf; 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++) { for (i = 0; i < reqbuf.count; i++) {
struct v4l2_buffer buf; struct v4l2_buffer buf;
V4l2Buffer *b; V4l2Buffer *b;
SpaMemory *mem;
CLEAR (buf); CLEAR (buf);
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
@ -598,13 +621,14 @@ mmap_init (SpaV4l2Source *this,
return SPA_RESULT_ERROR; 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; buffers[i] = &b->buffer;
b->source = this;
b->buffer.id = i;
b->buffer.size = sizeof (V4l2Buffer);
b->buffer.n_metas = 1; b->buffer.n_metas = 1;
b->buffer.metas = offsetof (V4l2Buffer, metas); b->buffer.metas = offsetof (V4l2Buffer, metas);
b->buffer.n_datas = 1; b->buffer.n_datas = 1;
@ -619,6 +643,14 @@ mmap_init (SpaV4l2Source *this,
b->metas[0].offset = offsetof (V4l2Buffer, header); b->metas[0].offset = offsetof (V4l2Buffer, header);
b->metas[0].size = sizeof (b->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) { if (state->export_buf) {
struct v4l2_exportbuffer expbuf; struct v4l2_exportbuffer expbuf;
@ -630,39 +662,25 @@ mmap_init (SpaV4l2Source *this,
continue; continue;
} }
mem->fd = expbuf.fd;
mem->type = "dmabuf";
mem->ptr = NULL;
b->dmafd = expbuf.fd; 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 { } else {
#if 1 mem->fd = -1;
b->datas[0].type = SPA_DATA_TYPE_MEMPTR; mem->type = "sysmem";
b->datas[0].ptr_type = "sysmem"; mem->ptr = mmap (NULL,
b->datas[0].ptr = mmap (NULL, buf.length,
buf.length, PROT_READ | PROT_WRITE,
PROT_READ | PROT_WRITE, MAP_SHARED,
MAP_SHARED, state->fd,
state->fd, buf.m.offset);
buf.m.offset); if (mem->ptr == MAP_FAILED) {
b->datas[0].offset = 0;
b->datas[0].size = buf.length;
if (b->datas[0].ptr == MAP_FAILED) {
perror ("mmap"); perror ("mmap");
continue; 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; b->outstanding = true;
CLEAR (b->v4l2_buffer); CLEAR (b->v4l2_buffer);
@ -772,17 +790,20 @@ spa_v4l2_stop (SpaV4l2Source *this)
for (i = 0; i < state->reqbuf.count; i++) { for (i = 0; i < state->reqbuf.count; i++) {
V4l2Buffer *b; V4l2Buffer *b;
SpaMemory *mem;
b = &state->buffers[i]; b = &state->alloc_buffers[i];
if (b->outstanding) { if (b->outstanding) {
fprintf (stderr, "queueing outstanding buffer %p\n", b); fprintf (stderr, "queueing outstanding buffer %p\n", b);
spa_v4l2_buffer_recycle (this, i); spa_v4l2_buffer_recycle (this, i);
} }
mem = spa_memory_find (0, b->datas[0].mem_id);
if (state->export_buf) { if (state->export_buf) {
close (b->dmafd); close (mem->fd);
} else { } 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; state->have_buffers = false;

View file

@ -21,6 +21,7 @@
#include <stddef.h> #include <stddef.h>
#include <spa/node.h> #include <spa/node.h>
#include <spa/memory.h>
#include <spa/audio/format.h> #include <spa/audio/format.h>
typedef struct _SpaVolume SpaVolume; typedef struct _SpaVolume SpaVolume;
@ -550,6 +551,7 @@ spa_volume_node_port_pull_output (SpaNode *node,
SpaData *sd, *dd; SpaData *sd, *dd;
uint16_t *src, *dst; uint16_t *src, *dst;
double volume; double volume;
SpaMemory *sm, *dm;
if (node == NULL || node->handle == NULL || n_info == 0 || info == NULL) if (node == NULL || node->handle == NULL || n_info == 0 || info == NULL)
return SPA_RESULT_INVALID_ARGUMENTS; return SPA_RESULT_INVALID_ARGUMENTS;
@ -581,16 +583,11 @@ spa_volume_node_port_pull_output (SpaNode *node,
sd = &SPA_BUFFER_DATAS (sbuf)[si]; sd = &SPA_BUFFER_DATAS (sbuf)[si];
dd = &SPA_BUFFER_DATAS (dbuf)[di]; dd = &SPA_BUFFER_DATAS (dbuf)[di];
if (sd->type != SPA_DATA_TYPE_MEMPTR) { sm = spa_memory_find (0, sd->mem_id);
si++; dm = spa_memory_find (0, dd->mem_id);
continue;
} src = (uint16_t*) ((uint8_t*)sm->ptr + sd->offset + soff);
if (dd->type != SPA_DATA_TYPE_MEMPTR) { dst = (uint16_t*) ((uint8_t*)dm->ptr + dd->offset + doff);
di++;
continue;
}
src = (uint16_t*) ((uint8_t*)sd->ptr + soff);
dst = (uint16_t*) ((uint8_t*)dd->ptr + doff);
n_bytes = SPA_MIN (sd->size - soff, dd->size - doff); n_bytes = SPA_MIN (sd->size - soff, dd->size - doff);
n_samples = n_bytes / sizeof (uint16_t); n_samples = n_bytes / sizeof (uint16_t);

View file

@ -30,6 +30,7 @@
#include <spa/node.h> #include <spa/node.h>
#include <spa/debug.h> #include <spa/debug.h>
#include <spa/memory.h>
#include <spa/video/format.h> #include <spa/video/format.h>
#undef USE_BUFFER #undef USE_BUFFER
@ -123,6 +124,7 @@ on_source_event (SpaNode *node, SpaEvent *event, void *user_data)
uint8_t *src, *dst; uint8_t *src, *dst;
SpaMeta *metas; SpaMeta *metas;
SpaData *datas; SpaData *datas;
SpaMemory *mem;
if ((res = spa_node_port_pull_output (data->source, 1, info)) < 0) if ((res = spa_node_port_pull_output (data->source, 1, info)) < 0)
printf ("got pull error %d\n", res); 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()); fprintf (stderr, "Couldn't lock texture: %s\n", SDL_GetError());
return; return;
} }
datas[0].ptr = sdata; mem = spa_memory_find (0, datas[0].mem_id);
datas[0].ptr_type = "sysmem"; mem->ptr = sdata;
mem->type = "sysmem";
mem->size = sstride * 240;
datas[0].size = sstride * 240; datas[0].size = sstride * 240;
datas[0].stride = sstride; datas[0].stride = sstride;
} else { } 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()); fprintf (stderr, "Couldn't lock texture: %s\n", SDL_GetError());
return; return;
} }
sdata = datas[0].ptr; mem = spa_memory_find (0, datas[0].mem_id);
sdata = spa_memory_ensure_ptr (mem);
sstride = datas[0].stride; sstride = datas[0].stride;
for (i = 0; i < 240; i++) { for (i = 0; i < 240; i++) {
@ -438,6 +445,8 @@ main (int argc, char *argv[])
AppData data; AppData data;
SpaResult res; SpaResult res;
spa_memory_init ();
if (SDL_Init (SDL_INIT_VIDEO) < 0) { if (SDL_Init (SDL_INIT_VIDEO) < 0) {
printf ("can't initialize SDL: %s\n", SDL_GetError ()); printf ("can't initialize SDL: %s\n", SDL_GetError ());
return -1; return -1;