Add fd to the data

Add the fd to the SpaData so that we can noth use the fd and the mmapped
memory when we want instead of needing to mmap again in the plugin.
various cleanups
This commit is contained in:
Wim Taymans 2016-10-04 19:37:44 +02:00
parent b8f693ceea
commit 06765a2dea
15 changed files with 158 additions and 179 deletions

View file

@ -1144,13 +1144,15 @@ parse_control (PinosStream *stream,
{ {
MemId *bmid = find_mem (stream, SPA_PTR_TO_UINT32 (d->data)); MemId *bmid = find_mem (stream, SPA_PTR_TO_UINT32 (d->data));
d->type = SPA_DATA_TYPE_MEMFD; d->type = SPA_DATA_TYPE_MEMFD;
d->data = SPA_INT_TO_PTR (bmid->fd); d->data = NULL;
d->fd = bmid->fd;
g_debug (" data %d %u -> fd %d", j, bmid->id, bmid->fd); g_debug (" data %d %u -> fd %d", j, bmid->id, bmid->fd);
break; break;
} }
case SPA_DATA_TYPE_MEMPTR: case SPA_DATA_TYPE_MEMPTR:
{ {
d->data = SPA_MEMBER (bid.buf_ptr, SPA_PTR_TO_INT (d->data), void); d->data = SPA_MEMBER (bid.buf_ptr, SPA_PTR_TO_INT (d->data), void);
d->fd = -1;
g_debug (" data %d %u -> mem %p", j, bid.id, d->data); g_debug (" data %d %u -> mem %p", j, bid.id, d->data);
break; break;
} }

View file

@ -391,9 +391,7 @@ on_add_buffer (GObject *gobject,
case SPA_DATA_TYPE_MEMFD: case SPA_DATA_TYPE_MEMFD:
case SPA_DATA_TYPE_DMABUF: case SPA_DATA_TYPE_DMABUF:
{ {
gint fd = SPA_PTR_TO_INT (d->data); gmem = gst_fd_allocator_alloc (pinossink->allocator, dup (d->fd),
gmem = gst_fd_allocator_alloc (pinossink->allocator, dup (fd),
d->maxsize, GST_FD_MEMORY_FLAG_NONE); d->maxsize, GST_FD_MEMORY_FLAG_NONE);
gst_memory_resize (gmem, d->offset, d->size); gst_memory_resize (gmem, d->offset, d->size);
break; break;

View file

@ -404,9 +404,7 @@ on_add_buffer (GObject *gobject,
case SPA_DATA_TYPE_MEMFD: case SPA_DATA_TYPE_MEMFD:
case SPA_DATA_TYPE_DMABUF: case SPA_DATA_TYPE_DMABUF:
{ {
gint fd = SPA_PTR_TO_INT (d->data); gmem = gst_fd_allocator_alloc (pinossrc->fd_allocator, dup (d->fd),
gmem = gst_fd_allocator_alloc (pinossrc->fd_allocator, dup (fd),
d->maxsize, GST_FD_MEMORY_FLAG_NONE); d->maxsize, GST_FD_MEMORY_FLAG_NONE);
gst_memory_resize (gmem, d->offset, d->size); gst_memory_resize (gmem, d->offset, d->size);
break; break;

View file

@ -434,7 +434,7 @@ do_allocation (PinosLink *this, SpaNodeState in_state, SpaNodeState out_state)
if (priv->buffers == NULL) { if (priv->buffers == NULL) {
SpaAllocParamBuffers *in_alloc, *out_alloc; SpaAllocParamBuffers *in_alloc, *out_alloc;
guint max_buffers = MAX_BUFFERS; guint max_buffers = MAX_BUFFERS;
size_t minsize = 4096, stride = 0; size_t minsize = 0, stride = 0;
max_buffers = MAX_BUFFERS; max_buffers = MAX_BUFFERS;
in_alloc = find_param (iinfo, SPA_ALLOC_PARAM_TYPE_BUFFERS); in_alloc = find_param (iinfo, SPA_ALLOC_PARAM_TYPE_BUFFERS);
@ -529,7 +529,9 @@ do_allocation (PinosLink *this, SpaNodeState in_state, SpaNodeState out_state)
d = &b->datas[0]; d = &b->datas[0];
if (minsize > 0) { if (minsize > 0) {
d->type = SPA_DATA_TYPE_MEMFD; d->type = SPA_DATA_TYPE_MEMFD;
d->data = SPA_INT_TO_PTR (priv->buffer_mem.fd); d->flags = 0;
d->data = priv->buffer_mem.ptr;
d->fd = priv->buffer_mem.fd;
d->maxsize = priv->buffer_mem.size; d->maxsize = priv->buffer_mem.size;
d->offset = arr_size + hdr_size + (buf_size * i); d->offset = arr_size + hdr_size + (buf_size * i);
d->size = minsize; d->size = minsize;

View file

@ -46,8 +46,8 @@ typedef enum {
* SpaDataType: * SpaDataType:
* @SPA_DATA_TYPE_INVALID: invalid data, should be ignored * @SPA_DATA_TYPE_INVALID: invalid data, should be ignored
* @SPA_DATA_TYPE_MEMPTR: data points to CPU accessible memory * @SPA_DATA_TYPE_MEMPTR: data points to CPU accessible memory
* @SPA_DATA_TYPE_MEMFD: data is an int file descriptor, use SPA_PTR_TO_INT * @SPA_DATA_TYPE_MEMFD: fd is memfd, data can be mmapped
* @SPA_DATA_TYPE_DMABUF: data is an int file descriptor, use SPA_PTR_TO_INT * @SPA_DATA_TYPE_DMABUF: fd is dmabuf, data can be mmapped
* @SPA_DATA_TYPE_ID: data is an id use SPA_PTR_TO_INT32. The definition of * @SPA_DATA_TYPE_ID: data is an id use SPA_PTR_TO_INT32. The definition of
* the ID is conveyed in some other way * the ID is conveyed in some other way
*/ */
@ -136,15 +136,19 @@ typedef struct {
/** /**
* SpaData: * SpaData:
* @type: memory type * @type: memory type
* @flags: memory flags
* @data: pointer to memory * @data: pointer to memory
* @maxsize: size of @data * @fd: file descriptor
* @maxsize: maximum size of the memory
* @offset: offset in @data * @offset: offset in @data
* @size: valid size of @data * @size: valid size of @data
* @stride: stride of data if applicable * @stride: stride of data if applicable
*/ */
typedef struct { typedef struct {
SpaDataType type; SpaDataType type;
int flags;
void *data; void *data;
int fd;
size_t maxsize; size_t maxsize;
off_t offset; off_t offset;
size_t size; size_t size;
@ -167,13 +171,21 @@ struct _SpaBuffer {
SpaData *datas; SpaData *datas;
}; };
inline void *
spa_buffer_find_meta (SpaBuffer *b, SpaMetaType type)
{
unsigned int i;
for (i = 0; i < b->n_metas; i++)
if (b->metas[i].type == type)
return b->metas[i].data;
return NULL;
}
size_t spa_buffer_get_size (const SpaBuffer *buffer); size_t spa_buffer_get_size (const SpaBuffer *buffer);
size_t spa_buffer_serialize (void *dest, const SpaBuffer *buffer); size_t spa_buffer_serialize (void *dest, const SpaBuffer *buffer);
SpaBuffer * spa_buffer_deserialize (void *src, off_t offset); SpaBuffer * spa_buffer_deserialize (void *src, off_t offset);
size_t spa_meta_type_get_size (SpaMetaType type); size_t spa_meta_type_get_size (SpaMetaType type);
#ifdef __cplusplus #ifdef __cplusplus

View file

@ -168,10 +168,12 @@ spa_debug_buffer (const SpaBuffer *buffer)
for (i = 0; i < buffer->n_datas; i++) { for (i = 0; i < buffer->n_datas; i++) {
SpaData *d = &buffer->datas[i]; SpaData *d = &buffer->datas[i];
fprintf (stderr, " type: %d (%s)\n", d->type, DATA_TYPE_NAME (d->type)); fprintf (stderr, " type: %d (%s)\n", d->type, DATA_TYPE_NAME (d->type));
fprintf (stderr, " flags: %d\n", d->flags);
fprintf (stderr, " data: %p\n", d->data); fprintf (stderr, " data: %p\n", d->data);
fprintf (stderr, " fd: %d\n", d->fd);
fprintf (stderr, " maxsize: %zd\n", d->maxsize);
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, " maxsize: %zd\n", d->maxsize);
fprintf (stderr, " stride: %zd\n", d->stride); fprintf (stderr, " stride: %zd\n", d->stride);
} }
return SPA_RESULT_OK; return SPA_RESULT_OK;

View file

@ -317,7 +317,7 @@ spa_alsa_sink_node_port_set_format (SpaNode *node,
if (format == NULL) { if (format == NULL) {
this->have_format = false; this->have_format = false;
this->have_buffers = false; this->n_buffers = 0;
update_state (this, SPA_NODE_STATE_CONFIGURE); update_state (this, SPA_NODE_STATE_CONFIGURE);
return SPA_RESULT_OK; return SPA_RESULT_OK;
} }
@ -328,7 +328,7 @@ spa_alsa_sink_node_port_set_format (SpaNode *node,
if (spa_alsa_set_format (this, &this->current_format, false) < 0) if (spa_alsa_set_format (this, &this->current_format, false) < 0)
return SPA_RESULT_ERROR; return SPA_RESULT_ERROR;
this->info.flags = SPA_PORT_INFO_FLAG_CAN_ALLOC_BUFFERS; this->info.flags = SPA_PORT_INFO_FLAG_CAN_USE_BUFFERS;
this->info.maxbuffering = -1; this->info.maxbuffering = -1;
this->info.latency = -1; this->info.latency = -1;
this->info.n_params = 1; this->info.n_params = 1;

View file

@ -318,14 +318,11 @@ recycle_buffer (SpaALSASource *this, uint32_t buffer_id)
static SpaResult static SpaResult
spa_alsa_clear_buffers (SpaALSASource *this) spa_alsa_clear_buffers (SpaALSASource *this)
{ {
if (!this->have_buffers) if (this->n_buffers > 0) {
return SPA_RESULT_OK;
SPA_QUEUE_INIT (&this->free); SPA_QUEUE_INIT (&this->free);
SPA_QUEUE_INIT (&this->ready); SPA_QUEUE_INIT (&this->ready);
this->n_buffers = 0; this->n_buffers = 0;
this->have_buffers = false; }
return SPA_RESULT_OK; return SPA_RESULT_OK;
} }
@ -360,11 +357,11 @@ spa_alsa_source_node_port_set_format (SpaNode *node,
if (spa_alsa_set_format (this, &this->current_format, flags) < 0) if (spa_alsa_set_format (this, &this->current_format, flags) < 0)
return SPA_RESULT_ERROR; return SPA_RESULT_ERROR;
this->info.flags = SPA_PORT_INFO_FLAG_CAN_ALLOC_BUFFERS | this->info.flags = SPA_PORT_INFO_FLAG_CAN_USE_BUFFERS |
SPA_PORT_INFO_FLAG_LIVE; SPA_PORT_INFO_FLAG_LIVE;
this->info.maxbuffering = this->buffer_frames * this->frame_size; this->info.maxbuffering = this->buffer_frames * this->frame_size;
this->info.latency = (this->period_frames * SPA_NSEC_PER_SEC) / this->rate; this->info.latency = (this->period_frames * SPA_NSEC_PER_SEC) / this->rate;
this->info.n_params = 1; this->info.n_params = 2;
this->info.params = this->params; this->info.params = this->params;
this->params[0] = &this->param_buffers.param; this->params[0] = &this->param_buffers.param;
this->param_buffers.param.type = SPA_ALLOC_PARAM_TYPE_BUFFERS; this->param_buffers.param.type = SPA_ALLOC_PARAM_TYPE_BUFFERS;
@ -374,6 +371,10 @@ spa_alsa_source_node_port_set_format (SpaNode *node,
this->param_buffers.min_buffers = 1; this->param_buffers.min_buffers = 1;
this->param_buffers.max_buffers = 32; this->param_buffers.max_buffers = 32;
this->param_buffers.align = 16; this->param_buffers.align = 16;
this->params[1] = &this->param_meta.param;
this->param_meta.param.type = SPA_ALLOC_PARAM_TYPE_META_ENABLE;
this->param_meta.param.size = sizeof (this->param_meta);
this->param_meta.type = SPA_META_TYPE_HEADER;
this->info.features = NULL; this->info.features = NULL;
this->have_format = true; this->have_format = true;
@ -468,23 +469,35 @@ spa_alsa_source_node_port_use_buffers (SpaNode *node,
if (!this->have_format) if (!this->have_format)
return SPA_RESULT_NO_FORMAT; return SPA_RESULT_NO_FORMAT;
if (this->have_buffers) { if (this->n_buffers > 0) {
if ((res = spa_alsa_clear_buffers (this)) < 0) if ((res = spa_alsa_clear_buffers (this)) < 0)
return res; return res;
} }
if (n_buffers > 0) {
for (i = 0; i < n_buffers; i++) { for (i = 0; i < n_buffers; i++) {
SpaALSABuffer *b = &this->buffers[i]; SpaALSABuffer *b = &this->buffers[i];
b->outbuf = buffers[i]; b->outbuf = buffers[i];
b->outstanding = false; b->outstanding = false;
b->h = spa_buffer_find_meta (b->outbuf, SPA_META_TYPE_HEADER);
switch (buffers[i]->datas[0].type) {
case SPA_DATA_TYPE_MEMFD:
case SPA_DATA_TYPE_DMABUF:
case SPA_DATA_TYPE_MEMPTR:
if (buffers[i]->datas[0].data == NULL) {
fprintf (stderr, "alsa-source: need mapped memory\n");
continue;
}
break;
default:
break;
}
b->next = NULL; b->next = NULL;
SPA_QUEUE_PUSH_TAIL (&this->free, SpaALSABuffer, next, b); SPA_QUEUE_PUSH_TAIL (&this->free, SpaALSABuffer, next, b);
} }
this->n_buffers = n_buffers; this->n_buffers = n_buffers;
this->have_buffers = true;
}
if (this->have_buffers) if (this->n_buffers > 0)
update_state (this, SPA_NODE_STATE_PAUSED); update_state (this, SPA_NODE_STATE_PAUSED);
else else
update_state (this, SPA_NODE_STATE_READY); update_state (this, SPA_NODE_STATE_READY);
@ -512,7 +525,7 @@ spa_alsa_source_node_port_alloc_buffers (SpaNode *node,
this = (SpaALSASource *) node->handle; this = (SpaALSASource *) node->handle;
if (!this->have_format) if (this->n_buffers == 0)
return SPA_RESULT_NO_FORMAT; return SPA_RESULT_NO_FORMAT;
return SPA_RESULT_NOT_IMPLEMENTED; return SPA_RESULT_NOT_IMPLEMENTED;
@ -609,7 +622,7 @@ spa_alsa_source_node_port_reuse_buffer (SpaNode *node,
if (port_id != 0) if (port_id != 0)
return SPA_RESULT_INVALID_PORT; return SPA_RESULT_INVALID_PORT;
if (!this->have_buffers) if (this->n_buffers == 0)
return SPA_RESULT_NO_BUFFERS; return SPA_RESULT_NO_BUFFERS;
if (buffer_id >= this->n_buffers) if (buffer_id >= this->n_buffers)

View file

@ -310,6 +310,7 @@ mmap_read (SpaALSAState *state)
snd_htimestamp_t htstamp = { 0, 0 }; snd_htimestamp_t htstamp = { 0, 0 };
int64_t now; int64_t now;
uint8_t *dest = NULL; uint8_t *dest = NULL;
size_t destsize;
snd_pcm_status_alloca(&status); snd_pcm_status_alloca(&status);
@ -327,12 +328,15 @@ mmap_read (SpaALSAState *state)
if (b == NULL) { if (b == NULL) {
fprintf (stderr, "no more buffers\n"); fprintf (stderr, "no more buffers\n");
} else { } else {
dest = b->ptr; dest = SPA_MEMBER (b->outbuf->datas[0].data, b->outbuf->datas[0].offset, void);
destsize = b->outbuf->datas[0].size;
if (b->h) { if (b->h) {
b->h->seq = state->sample_count; b->h->seq = state->sample_count;
b->h->pts = state->last_monotonic; b->h->pts = state->last_monotonic;
b->h->dts_offset = 0; b->h->dts_offset = 0;
} }
avail = SPA_MIN (avail, destsize / state->frame_size);
} }
state->sample_count += avail; state->sample_count += avail;
@ -439,7 +443,7 @@ spa_alsa_start (SpaALSAState *state)
if (spa_alsa_open (state) < 0) if (spa_alsa_open (state) < 0)
return -1; return -1;
if (!state->have_buffers) if (state->n_buffers == 0)
return -1; return -1;
CHECK (set_swparams (state), "swparams"); CHECK (set_swparams (state), "swparams");

View file

@ -50,7 +50,6 @@ typedef struct {
struct _SpaALSABuffer { struct _SpaALSABuffer {
SpaBuffer *outbuf; SpaBuffer *outbuf;
SpaMetaHeader *h; SpaMetaHeader *h;
void *ptr;
bool outstanding; bool outstanding;
SpaALSABuffer *next; SpaALSABuffer *next;
}; };
@ -82,11 +81,11 @@ struct _SpaALSAState {
size_t frame_size; size_t frame_size;
SpaPortInfo info; SpaPortInfo info;
SpaAllocParam *params[1]; SpaAllocParam *params[2];
SpaAllocParamBuffers param_buffers; SpaAllocParamBuffers param_buffers;
SpaAllocParamMetaEnable param_meta;
SpaPortStatus status; SpaPortStatus status;
bool have_buffers;
SpaALSABuffer buffers[MAX_BUFFERS]; SpaALSABuffer buffers[MAX_BUFFERS];
unsigned int n_buffers; unsigned int n_buffers;

View file

@ -80,7 +80,6 @@ struct _SpaAudioTestSrc {
SpaFormatAudio current_format; SpaFormatAudio current_format;
size_t bpf; size_t bpf;
bool have_buffers;
ATSBuffer buffers[MAX_BUFFERS]; ATSBuffer buffers[MAX_BUFFERS];
unsigned int n_buffers; unsigned int n_buffers;
@ -356,7 +355,7 @@ spa_audiotestsrc_node_send_command (SpaNode *node,
if (!this->have_format) if (!this->have_format)
return SPA_RESULT_NO_FORMAT; return SPA_RESULT_NO_FORMAT;
if (!this->have_buffers) if (this->n_buffers == 0)
return SPA_RESULT_NO_BUFFERS; return SPA_RESULT_NO_BUFFERS;
if (this->started) if (this->started)
@ -380,7 +379,7 @@ spa_audiotestsrc_node_send_command (SpaNode *node,
if (!this->have_format) if (!this->have_format)
return SPA_RESULT_NO_FORMAT; return SPA_RESULT_NO_FORMAT;
if (!this->have_buffers) if (this->n_buffers == 0)
return SPA_RESULT_NO_BUFFERS; return SPA_RESULT_NO_BUFFERS;
if (!this->started) if (!this->started)
@ -528,10 +527,9 @@ spa_audiotestsrc_node_port_enum_formats (SpaNode *node,
static SpaResult static SpaResult
clear_buffers (SpaAudioTestSrc *this) clear_buffers (SpaAudioTestSrc *this)
{ {
if (this->have_buffers) { if (this->n_buffers > 0) {
fprintf (stderr, "audiotestsrc %p: clear buffers\n", this); fprintf (stderr, "audiotestsrc %p: clear buffers\n", this);
this->n_buffers = 0; this->n_buffers = 0;
this->have_buffers = false;
SPA_QUEUE_INIT (&this->empty); SPA_QUEUE_INIT (&this->empty);
SPA_QUEUE_INIT (&this->ready); SPA_QUEUE_INIT (&this->ready);
} }
@ -665,6 +663,7 @@ spa_audiotestsrc_node_port_use_buffers (SpaNode *node,
uint32_t n_buffers) uint32_t n_buffers)
{ {
SpaAudioTestSrc *this; SpaAudioTestSrc *this;
unsigned int i;
if (node == NULL || node->handle == NULL) if (node == NULL || node->handle == NULL)
return SPA_RESULT_INVALID_ARGUMENTS; return SPA_RESULT_INVALID_ARGUMENTS;
@ -679,44 +678,35 @@ spa_audiotestsrc_node_port_use_buffers (SpaNode *node,
clear_buffers (this); clear_buffers (this);
if (buffers != NULL && n_buffers != 0) {
unsigned int i, j;
for (i = 0; i < n_buffers; i++) { for (i = 0; i < n_buffers; i++) {
ATSBuffer *b; ATSBuffer *b;
SpaData *d = buffers[i]->datas; SpaData *d = buffers[i]->datas;
SpaMeta *m = buffers[i]->metas;
b = &this->buffers[i]; b = &this->buffers[i];
b->outbuf = buffers[i]; b->outbuf = buffers[i];
b->outstanding = true; b->outstanding = true;
b->h = NULL; b->h = spa_buffer_find_meta (buffers[i], SPA_META_TYPE_HEADER);
for (j = 0; j < buffers[i]->n_metas; j++) { switch (d[0].type) {
switch (m[j].type) { case SPA_DATA_TYPE_MEMPTR:
case SPA_META_TYPE_HEADER: case SPA_DATA_TYPE_MEMFD:
b->h = m[j].data; case SPA_DATA_TYPE_DMABUF:
if (d[0].data == NULL) {
fprintf (stderr, "audiotestsrc %p: invalid memory on buffer %p\n", this, buffers[i]);
continue;
}
b->ptr = SPA_MEMBER (d[0].data, d[0].offset, void);
b->size = d[0].size;
break; break;
default: default:
break; break;
} }
}
if (buffers[i]->n_datas < 1 || d[0].type != SPA_DATA_TYPE_MEMPTR) {
fprintf (stderr, "audiotestsrc %p: invalid memory on buffer %p\n", this, buffers[i]);
continue;
}
b->ptr = SPA_MEMBER (d[0].data, d[0].offset, void);
b->size = d[0].size;
b->next = NULL; b->next = NULL;
SPA_QUEUE_PUSH_TAIL (&this->empty, ATSBuffer, next, b); SPA_QUEUE_PUSH_TAIL (&this->empty, ATSBuffer, next, b);
} }
this->n_buffers = n_buffers; this->n_buffers = n_buffers;
this->have_buffers = true;
}
if (this->have_buffers) { if (this->n_buffers > 0) {
update_state (this, SPA_NODE_STATE_PAUSED); update_state (this, SPA_NODE_STATE_PAUSED);
} else { } else {
update_state (this, SPA_NODE_STATE_READY); update_state (this, SPA_NODE_STATE_READY);
@ -747,7 +737,7 @@ spa_audiotestsrc_node_port_alloc_buffers (SpaNode *node,
if (!this->have_format) if (!this->have_format)
return SPA_RESULT_NO_FORMAT; return SPA_RESULT_NO_FORMAT;
if (!this->have_buffers) if (this->n_buffers == 0)
return SPA_RESULT_NO_BUFFERS; return SPA_RESULT_NO_BUFFERS;
return SPA_RESULT_NOT_IMPLEMENTED; return SPA_RESULT_NOT_IMPLEMENTED;
@ -848,7 +838,7 @@ spa_audiotestsrc_node_port_reuse_buffer (SpaNode *node,
if (port_id != 0) if (port_id != 0)
return SPA_RESULT_INVALID_PORT; return SPA_RESULT_INVALID_PORT;
if (!this->have_buffers) if (this->n_buffers == 0)
return SPA_RESULT_NO_BUFFERS; return SPA_RESULT_NO_BUFFERS;
if (buffer_id >= this->n_buffers) if (buffer_id >= this->n_buffers)

View file

@ -753,8 +753,8 @@ spa_proxy_node_port_use_buffers (SpaNode *node,
am.port_id = port_id; am.port_id = port_id;
am.mem_id = n_mem; am.mem_id = n_mem;
am.type = d->type; am.type = d->type;
am.fd_index = spa_control_builder_add_fd (&builder, SPA_PTR_TO_INT (d->data), false); am.fd_index = spa_control_builder_add_fd (&builder, d->fd, false);
am.flags = 0; am.flags = d->flags;
am.offset = d->offset; am.offset = d->offset;
am.size = d->maxsize; am.size = d->maxsize;
spa_control_builder_add_cmd (&builder, SPA_CONTROL_CMD_ADD_MEM, &am); spa_control_builder_add_cmd (&builder, SPA_CONTROL_CMD_ADD_MEM, &am);

View file

@ -55,10 +55,9 @@ struct _V4l2Buffer {
SpaBuffer *outbuf; SpaBuffer *outbuf;
SpaMetaHeader *h; SpaMetaHeader *h;
bool outstanding; bool outstanding;
bool allocated;
struct v4l2_buffer v4l2_buffer; struct v4l2_buffer v4l2_buffer;
V4l2Buffer *next; V4l2Buffer *next;
void *ptr;
size_t size;
}; };
typedef struct _V4l2Format V4l2Format; typedef struct _V4l2Format V4l2Format;

View file

@ -106,12 +106,13 @@ spa_v4l2_clear_buffers (SpaV4l2Source *this)
fprintf (stderr, "v4l2: queueing outstanding buffer %p\n", b); fprintf (stderr, "v4l2: queueing outstanding buffer %p\n", b);
spa_v4l2_buffer_recycle (this, i); spa_v4l2_buffer_recycle (this, i);
} }
if (b->ptr) { if (b->allocated) {
munmap (b->ptr, b->size); if (b->outbuf->datas[0].data)
b->ptr = NULL; munmap (b->outbuf->datas[0].data, b->outbuf->datas[0].maxsize);
if (b->outbuf->datas[0].fd != -1)
close (b->outbuf->datas[0].fd);
b->outbuf->datas[0].type = SPA_DATA_TYPE_INVALID;
} }
if (b->outbuf->datas[0].type == SPA_DATA_TYPE_DMABUF)
close (SPA_PTR_TO_INT (b->outbuf->datas[0].data));
} }
CLEAR(reqbuf); CLEAR(reqbuf);
@ -893,18 +894,6 @@ v4l2_on_fd_events (SpaPollNotifyData *data)
return 0; return 0;
} }
static void *
find_meta_data (SpaBuffer *b, SpaMetaType type)
{
unsigned int i;
for (i = 0; i < b->n_metas; i++)
if (b->metas[i].type == type)
return b->metas[i].data;
return NULL;
}
static SpaResult static SpaResult
spa_v4l2_use_buffers (SpaV4l2Source *this, SpaBuffer **buffers, uint32_t n_buffers) spa_v4l2_use_buffers (SpaV4l2Source *this, SpaBuffer **buffers, uint32_t n_buffers)
{ {
@ -949,8 +938,8 @@ spa_v4l2_use_buffers (SpaV4l2Source *this, SpaBuffer **buffers, uint32_t n_buffe
b = &state->buffers[i]; b = &state->buffers[i];
b->outbuf = buffers[i]; b->outbuf = buffers[i];
b->outstanding = true; b->outstanding = true;
b->h = find_meta_data (b->outbuf, SPA_META_TYPE_HEADER); b->allocated = false;
b->ptr = NULL; b->h = spa_buffer_find_meta (b->outbuf, SPA_META_TYPE_HEADER);
fprintf (stderr, "v4l2: import buffer %p\n", buffers[i]); fprintf (stderr, "v4l2: import buffer %p\n", buffers[i]);
@ -966,27 +955,16 @@ spa_v4l2_use_buffers (SpaV4l2Source *this, SpaBuffer **buffers, uint32_t n_buffe
b->v4l2_buffer.index = i; b->v4l2_buffer.index = i;
switch (d[0].type) { switch (d[0].type) {
case SPA_DATA_TYPE_MEMPTR: case SPA_DATA_TYPE_MEMPTR:
case SPA_DATA_TYPE_MEMFD:
if (d[0].data == NULL) {
fprintf (stderr, "v4l2: need mmaped memory\n");
continue;
}
b->v4l2_buffer.m.userptr = (unsigned long) SPA_MEMBER (d[0].data, d[0].offset, void *); b->v4l2_buffer.m.userptr = (unsigned long) SPA_MEMBER (d[0].data, d[0].offset, void *);
b->v4l2_buffer.length = d[0].size; b->v4l2_buffer.length = d[0].size;
break; break;
case SPA_DATA_TYPE_MEMFD:
b->v4l2_buffer.length = d[0].size;
b->ptr = mmap (NULL,
d[0].maxsize,
PROT_READ | PROT_WRITE,
MAP_SHARED,
SPA_PTR_TO_INT (d[0].data),
0);
if (b->ptr == MAP_FAILED) {
perror ("mmap");
b->ptr = NULL;
continue;
}
b->size = d[0].maxsize;
b->v4l2_buffer.m.userptr = (unsigned long) SPA_MEMBER (b->ptr, d[0].offset, void *);
break;
case SPA_DATA_TYPE_DMABUF: case SPA_DATA_TYPE_DMABUF:
b->v4l2_buffer.m.fd = SPA_PTR_TO_INT (d[0].data); b->v4l2_buffer.m.fd = d[0].fd;
break; break;
default: default:
break; break;
@ -1043,8 +1021,8 @@ mmap_init (SpaV4l2Source *this,
b = &state->buffers[i]; b = &state->buffers[i];
b->outbuf = buffers[i]; b->outbuf = buffers[i];
b->outstanding = true; b->outstanding = true;
b->h = find_meta_data (b->outbuf, SPA_META_TYPE_HEADER); b->allocated = true;
b->ptr = NULL; b->h = spa_buffer_find_meta (b->outbuf, SPA_META_TYPE_HEADER);
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;
@ -1074,9 +1052,11 @@ mmap_init (SpaV4l2Source *this,
continue; continue;
} }
d[0].type = SPA_DATA_TYPE_DMABUF; d[0].type = SPA_DATA_TYPE_DMABUF;
d[0].data = SPA_INT_TO_PTR (expbuf.fd); d[0].fd = expbuf.fd;
d[0].data = NULL;
} else { } else {
d[0].type = SPA_DATA_TYPE_MEMPTR; d[0].type = SPA_DATA_TYPE_MEMPTR;
d[0].fd = -1;
d[0].data = mmap (NULL, d[0].data = mmap (NULL,
b->v4l2_buffer.length, b->v4l2_buffer.length,
PROT_READ, PROT_READ,
@ -1087,8 +1067,6 @@ mmap_init (SpaV4l2Source *this,
perror ("mmap"); perror ("mmap");
continue; continue;
} }
b->ptr = d[0].data;
b->size = b->v4l2_buffer.length;
} }
spa_v4l2_buffer_recycle (this, i); spa_v4l2_buffer_recycle (this, i);
} }

View file

@ -83,7 +83,6 @@ struct _SpaVideoTestSrc {
SpaFormatVideo current_format; SpaFormatVideo current_format;
size_t bpp; size_t bpp;
bool have_buffers;
VTSBuffer buffers[MAX_BUFFERS]; VTSBuffer buffers[MAX_BUFFERS];
unsigned int n_buffers; unsigned int n_buffers;
@ -304,7 +303,7 @@ spa_videotestsrc_node_send_command (SpaNode *node,
if (!this->have_format) if (!this->have_format)
return SPA_RESULT_NO_FORMAT; return SPA_RESULT_NO_FORMAT;
if (!this->have_buffers) if (this->n_buffers == 0)
return SPA_RESULT_NO_BUFFERS; return SPA_RESULT_NO_BUFFERS;
if (this->started) if (this->started)
@ -328,7 +327,7 @@ spa_videotestsrc_node_send_command (SpaNode *node,
if (!this->have_format) if (!this->have_format)
return SPA_RESULT_NO_FORMAT; return SPA_RESULT_NO_FORMAT;
if (!this->have_buffers) if (this->n_buffers == 0)
return SPA_RESULT_NO_BUFFERS; return SPA_RESULT_NO_BUFFERS;
if (!this->started) if (!this->started)
@ -476,10 +475,9 @@ spa_videotestsrc_node_port_enum_formats (SpaNode *node,
static SpaResult static SpaResult
clear_buffers (SpaVideoTestSrc *this) clear_buffers (SpaVideoTestSrc *this)
{ {
if (this->have_buffers) { if (this->n_buffers > 0) {
fprintf (stderr, "videotestsrc %p: clear buffers\n", this); fprintf (stderr, "videotestsrc %p: clear buffers\n", this);
this->n_buffers = 0; this->n_buffers = 0;
this->have_buffers = false;
SPA_QUEUE_INIT (&this->empty); SPA_QUEUE_INIT (&this->empty);
SPA_QUEUE_INIT (&this->ready); SPA_QUEUE_INIT (&this->ready);
} }
@ -614,6 +612,7 @@ spa_videotestsrc_node_port_use_buffers (SpaNode *node,
uint32_t n_buffers) uint32_t n_buffers)
{ {
SpaVideoTestSrc *this; SpaVideoTestSrc *this;
unsigned int i;
if (node == NULL || node->handle == NULL) if (node == NULL || node->handle == NULL)
return SPA_RESULT_INVALID_ARGUMENTS; return SPA_RESULT_INVALID_ARGUMENTS;
@ -627,47 +626,36 @@ spa_videotestsrc_node_port_use_buffers (SpaNode *node,
return SPA_RESULT_NO_FORMAT; return SPA_RESULT_NO_FORMAT;
clear_buffers (this); clear_buffers (this);
if (buffers != NULL && n_buffers != 0) {
unsigned int i, j;
for (i = 0; i < n_buffers; i++) { for (i = 0; i < n_buffers; i++) {
VTSBuffer *b = &this->buffers[i]; VTSBuffer *b = &this->buffers[i];
SpaData *d = buffers[i]->datas; SpaData *d = buffers[i]->datas;
SpaMeta *m = buffers[i]->metas;
b = &this->buffers[i]; b = &this->buffers[i];
b->outbuf = buffers[i]; b->outbuf = buffers[i];
b->outstanding = true; b->outstanding = true;
b->h = NULL; b->h = spa_buffer_find_meta (buffers[i], SPA_META_TYPE_HEADER);
for (j = 0; j < buffers[i]->n_metas; j++) { switch (d[0].type) {
switch (m[j].type) { case SPA_DATA_TYPE_MEMPTR:
case SPA_META_TYPE_HEADER: case SPA_DATA_TYPE_MEMFD:
b->h = m[j].data; case SPA_DATA_TYPE_DMABUF:
break; if (d[0].data == NULL) {
default:
break;
}
}
if (d[0].type != SPA_DATA_TYPE_MEMPTR) {
fprintf (stderr, "videotestsrc %p: invalid memory on buffer %p\n", this, buffers[i]); fprintf (stderr, "videotestsrc %p: invalid memory on buffer %p\n", this, buffers[i]);
continue; continue;
} }
b->ptr = SPA_MEMBER (d[0].data, d[0].offset, void); b->ptr = SPA_MEMBER (d[0].data, d[0].offset, void);
b->stride = d[0].stride; b->stride = d[0].stride;
break;
default:
break;
}
b->next = NULL; b->next = NULL;
SPA_QUEUE_PUSH_TAIL (&this->empty, VTSBuffer, next, b); SPA_QUEUE_PUSH_TAIL (&this->empty, VTSBuffer, next, b);
} }
this->n_buffers = n_buffers; this->n_buffers = n_buffers;
this->have_buffers = true;
this->info.flags |= SPA_PORT_INFO_FLAG_CAN_ALLOC_BUFFERS;
} else {
this->info.flags &= ~SPA_PORT_INFO_FLAG_CAN_ALLOC_BUFFERS;
}
if (this->have_buffers) { if (this->n_buffers > 0) {
update_state (this, SPA_NODE_STATE_PAUSED); update_state (this, SPA_NODE_STATE_PAUSED);
} else { } else {
update_state (this, SPA_NODE_STATE_READY); update_state (this, SPA_NODE_STATE_READY);
@ -686,7 +674,6 @@ spa_videotestsrc_node_port_alloc_buffers (SpaNode *node,
uint32_t *n_buffers) uint32_t *n_buffers)
{ {
SpaVideoTestSrc *this; SpaVideoTestSrc *this;
unsigned int i;
if (node == NULL || node->handle == NULL) if (node == NULL || node->handle == NULL)
return SPA_RESULT_INVALID_ARGUMENTS; return SPA_RESULT_INVALID_ARGUMENTS;
@ -699,15 +686,10 @@ spa_videotestsrc_node_port_alloc_buffers (SpaNode *node,
if (!this->have_format) if (!this->have_format)
return SPA_RESULT_NO_FORMAT; return SPA_RESULT_NO_FORMAT;
if (!this->have_buffers) if (this->n_buffers == 0)
return SPA_RESULT_NO_BUFFERS; return SPA_RESULT_NO_BUFFERS;
*n_buffers = SPA_MIN (*n_buffers, this->n_buffers); return SPA_RESULT_NOT_IMPLEMENTED;
for (i = 0; i < *n_buffers; i++)
buffers[i] = this->buffers[i].outbuf;
return SPA_RESULT_OK;
} }
static SpaResult static SpaResult
@ -804,7 +786,7 @@ spa_videotestsrc_node_port_reuse_buffer (SpaNode *node,
if (port_id != 0) if (port_id != 0)
return SPA_RESULT_INVALID_PORT; return SPA_RESULT_INVALID_PORT;
if (!this->have_buffers) if (this->n_buffers == 0)
return SPA_RESULT_NO_BUFFERS; return SPA_RESULT_NO_BUFFERS;
if (buffer_id >= this->n_buffers) if (buffer_id >= this->n_buffers)