mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-10-31 22:25:38 -04:00
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:
parent
98993c680b
commit
1169c2419b
19 changed files with 383 additions and 356 deletions
|
|
@ -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 ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -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) {
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
106
spa/lib/memory.c
106
spa/lib/memory.c
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue