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