diff --git a/pinos/client/stream.c b/pinos/client/stream.c index 5de84f5da..a43b48855 100644 --- a/pinos/client/stream.c +++ b/pinos/client/stream.c @@ -1143,15 +1143,15 @@ parse_control (PinosStream *stream, case SPA_DATA_TYPE_ID: { MemId *bmid = find_mem (stream, SPA_PTR_TO_UINT32 (d->data)); - d->type = SPA_DATA_TYPE_FD; + d->type = SPA_DATA_TYPE_MEMFD; d->data = SPA_INT_TO_PTR (bmid->fd); - g_debug (" data %d %u -> %d", j, bmid->id, bmid->fd); + g_debug (" data %d %u -> fd %d", j, bmid->id, bmid->fd); break; } case SPA_DATA_TYPE_MEMPTR: { d->data = SPA_MEMBER (bid.buf_ptr, SPA_PTR_TO_INT (d->data), void); - g_debug (" data %d %u -> %p", j, bid.id, d->data); + g_debug (" data %d %u -> mem %p", j, bid.id, d->data); break; } default: diff --git a/pinos/gst/gstpinossink.c b/pinos/gst/gstpinossink.c index f0f57ab24..4cf857e61 100644 --- a/pinos/gst/gstpinossink.c +++ b/pinos/gst/gstpinossink.c @@ -385,20 +385,28 @@ on_add_buffer (GObject *gobject, } for (i = 0; i < b->n_datas; i++) { SpaData *d = &b->datas[i]; + GstMemory *gmem = NULL; - if (d->type == SPA_DATA_TYPE_FD) { - GstMemory *fdmem = NULL; - gint fd = *(int*)d->data; + switch (d->type) { + case SPA_DATA_TYPE_MEMFD: + case SPA_DATA_TYPE_DMABUF: + { + gint fd = SPA_PTR_TO_INT (d->data); - fdmem = gst_fd_allocator_alloc (pinossink->allocator, dup (fd), - d->offset + d->maxsize, 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, d->data, d->offset + d->maxsize, d->offset, - d->size, NULL, NULL)); + gmem = gst_fd_allocator_alloc (pinossink->allocator, dup (fd), + d->maxsize, GST_FD_MEMORY_FLAG_NONE); + gst_memory_resize (gmem, d->offset, d->size); + break; + } + case SPA_DATA_TYPE_MEMPTR: + gmem = gst_memory_new_wrapped (0, d->data, d->maxsize, d->offset, + d->size, NULL, NULL); + break; + default: + break; } + if (gmem) + gst_buffer_append_memory (buf, gmem); } data.flags = GST_BUFFER_FLAGS (buf); gst_mini_object_set_qdata (GST_MINI_OBJECT_CAST (buf), @@ -624,7 +632,7 @@ gst_pinos_sink_render (GstBaseSink * bsink, GstBuffer * buffer) } for (i = 0; i < data->buf->n_datas; i++) { SpaData *d = &data->buf->datas[i]; - GstMemory *mem = gst_buffer_get_memory (buffer, i); + GstMemory *mem = gst_buffer_peek_memory (buffer, i); d->offset = mem->offset; d->size = mem->size; } diff --git a/pinos/gst/gstpinossrc.c b/pinos/gst/gstpinossrc.c index 3a2b20e17..36bbc1b5b 100644 --- a/pinos/gst/gstpinossrc.c +++ b/pinos/gst/gstpinossrc.c @@ -398,19 +398,27 @@ on_add_buffer (GObject *gobject, } for (i = 0; i < b->n_datas; i++) { SpaData *d = &b->datas[i]; - GstMemory *gmem; + GstMemory *gmem = NULL; - if (d->type == SPA_DATA_TYPE_FD) { - gint fd = SPA_PTR_TO_INT (d->data); + switch (d->type) { + case SPA_DATA_TYPE_MEMFD: + case SPA_DATA_TYPE_DMABUF: + { + gint fd = SPA_PTR_TO_INT (d->data); - gmem = gst_fd_allocator_alloc (pinossrc->fd_allocator, dup (fd), - d->offset + d->maxsize, GST_FD_MEMORY_FLAG_NONE); - gst_memory_resize (gmem, d->offset, d->size); - } else { - gmem = gst_memory_new_wrapped (0, d->data, d->offset + d->maxsize, d->offset, - d->size, NULL, NULL); + gmem = gst_fd_allocator_alloc (pinossrc->fd_allocator, dup (fd), + d->maxsize, GST_FD_MEMORY_FLAG_NONE); + gst_memory_resize (gmem, d->offset, d->size); + break; + } + case SPA_DATA_TYPE_MEMPTR: + gmem = gst_memory_new_wrapped (0, d->data, d->maxsize, d->offset, + d->size, NULL, NULL); + default: + break; } - gst_buffer_append_memory (buf, gmem); + if (gmem) + gst_buffer_append_memory (buf, gmem); } data.flags = GST_BUFFER_FLAGS (buf); gst_mini_object_set_qdata (GST_MINI_OBJECT_CAST (buf), @@ -467,8 +475,9 @@ on_new_buffer (GObject *gobject, } for (i = 0; i < data->buf->n_datas; i++) { SpaData *d = &data->buf->datas[i]; - GstMemory *mem = gst_buffer_get_memory (buf, i); - gst_memory_resize (mem, 0, d->size); + GstMemory *mem = gst_buffer_peek_memory (buf, i); + mem->offset = d->offset; + mem->size = d->size; } g_queue_push_tail (&pinossrc->queue, buf); diff --git a/pinos/server/link.c b/pinos/server/link.c index cd9042d05..66431ba15 100644 --- a/pinos/server/link.c +++ b/pinos/server/link.c @@ -433,24 +433,26 @@ do_allocation (PinosLink *this, SpaNodeState in_state, SpaNodeState out_state) if (priv->buffers == NULL) { SpaAllocParamBuffers *in_alloc, *out_alloc; - guint max_buffers = MAX_BUFFERS, min_size = 4096; - gboolean alloc_data = TRUE; + guint max_buffers = MAX_BUFFERS; + size_t minsize = 4096, stride = 0; max_buffers = MAX_BUFFERS; in_alloc = find_param (iinfo, SPA_ALLOC_PARAM_TYPE_BUFFERS); if (in_alloc) { max_buffers = in_alloc->max_buffers == 0 ? max_buffers : SPA_MIN (in_alloc->max_buffers, max_buffers); - min_size = SPA_MAX (min_size, in_alloc->minsize); + minsize = SPA_MAX (minsize, in_alloc->minsize); + stride = SPA_MAX (stride, in_alloc->stride); } out_alloc = find_param (oinfo, SPA_ALLOC_PARAM_TYPE_BUFFERS); if (out_alloc) { max_buffers = out_alloc->max_buffers == 0 ? max_buffers : SPA_MIN (out_alloc->max_buffers, max_buffers); - min_size = SPA_MAX (min_size, out_alloc->minsize); + minsize = SPA_MAX (minsize, out_alloc->minsize); + stride = SPA_MAX (stride, out_alloc->stride); } if ((in_flags & SPA_PORT_INFO_FLAG_CAN_ALLOC_BUFFERS) || (out_flags & SPA_PORT_INFO_FLAG_CAN_ALLOC_BUFFERS)) - alloc_data = FALSE; + minsize = 0; if (this->output->allocated) { out_flags = 0; @@ -460,77 +462,88 @@ do_allocation (PinosLink *this, SpaNodeState in_state, SpaNodeState out_state) priv->allocated = FALSE; g_debug ("reusing %d output buffers %p", priv->n_buffers, priv->buffers); } else { - guint i; - size_t hdr_size, data_size, buf_size; + guint i, j; + size_t hdr_size, buf_size, arr_size; void *p; + guint n_metas, n_datas; - spa_alloc_params_get_header_size (oinfo->params, oinfo->n_params, 1, &hdr_size); - if (alloc_data) - data_size = min_size; - else - data_size = 0; + n_metas = 0; + n_datas = 1; - buf_size = hdr_size + data_size; + hdr_size = sizeof (SpaBuffer); + hdr_size += n_datas * sizeof (SpaData); + for (i = 0; i < oinfo->n_params; i++) { + SpaAllocParam *ap = oinfo->params[i]; + + if (ap->type == SPA_ALLOC_PARAM_TYPE_META_ENABLE) { + SpaAllocParamMetaEnable *pme = (SpaAllocParamMetaEnable *) ap; + + hdr_size += spa_meta_type_get_size (pme->type); + n_metas++; + } + } + hdr_size += n_metas * sizeof (SpaMeta); + + buf_size = hdr_size + minsize; priv->n_buffers = max_buffers; - pinos_memblock_alloc (PINOS_MEMBLOCK_FLAG_WITH_FD | PINOS_MEMBLOCK_FLAG_MAP_READWRITE | PINOS_MEMBLOCK_FLAG_SEAL, priv->n_buffers * (sizeof (SpaBuffer*) + buf_size), &priv->buffer_mem); + arr_size = priv->n_buffers * sizeof (SpaBuffer*); priv->buffers = p = priv->buffer_mem.ptr; - p = SPA_MEMBER (p, priv->n_buffers * sizeof (SpaBuffer*), void); - for (i = 0; i < priv->n_buffers; i++) - priv->buffers[i] = SPA_MEMBER (p, buf_size * i, SpaBuffer); + p = SPA_MEMBER (p, arr_size, void); - if ((res = spa_buffer_init_headers (oinfo->params, - oinfo->n_params, - 1, - priv->buffers, - priv->n_buffers)) < 0) { - g_set_error (&error, - PINOS_ERROR, - PINOS_ERROR_BUFFER_ALLOCATION, - "error buffer alloc: %d", res); - goto error; - } for (i = 0; i < priv->n_buffers; i++) { - SpaData *d = &priv->buffers[i]->datas[0]; + SpaBuffer *b; + SpaData *d; + void *pd; + guint mi; - g_debug (" buffers %p %d", priv->buffers[i], priv->buffers[i]->id); - d->type = SPA_DATA_TYPE_MEMPTR; - d->data = SPA_MEMBER (priv->buffers[i], hdr_size, void); - d->size = data_size; - d->maxsize = data_size; - d->offset = 0; - d->stride = 0; + b = priv->buffers[i] = SPA_MEMBER (p, buf_size * i, SpaBuffer); + + b->id = i; + b->n_metas = n_metas; + b->metas = SPA_MEMBER (b, sizeof (SpaBuffer), SpaMeta); + b->n_datas = n_datas; + b->datas = SPA_MEMBER (b->metas, sizeof (SpaMeta) * n_metas, SpaData); + pd = SPA_MEMBER (b->datas, sizeof (SpaData) * n_datas, void); + + for (j = 0, mi = 0; j < oinfo->n_params; j++) { + SpaAllocParam *ap = oinfo->params[j]; + + if (ap->type == SPA_ALLOC_PARAM_TYPE_META_ENABLE) { + SpaAllocParamMetaEnable *pme = (SpaAllocParamMetaEnable *) ap; + + b->metas[mi].type = pme->type; + b->metas[mi].data = pd; + b->metas[mi].size = spa_meta_type_get_size (pme->type); + pd = SPA_MEMBER (pd, b->metas[mi].size, void); + mi++; + } + } + + d = &b->datas[0]; + if (minsize > 0) { + d->type = SPA_DATA_TYPE_MEMFD; + d->data = SPA_INT_TO_PTR (priv->buffer_mem.fd); + d->maxsize = priv->buffer_mem.size; + d->offset = arr_size + hdr_size + (buf_size * i); + d->size = minsize; + d->stride = stride; + } else { + d->type = SPA_DATA_TYPE_INVALID; + d->data = NULL; + } } g_debug ("allocated %d buffers %p", priv->n_buffers, priv->buffers); priv->allocated = TRUE; } - if (in_flags & SPA_PORT_INFO_FLAG_CAN_ALLOC_BUFFERS) { - if ((res = spa_node_port_alloc_buffers (this->input->node->node, - SPA_DIRECTION_INPUT, - this->input->port, - oinfo->params, oinfo->n_params, - priv->buffers, &priv->n_buffers)) < 0) { - g_set_error (&error, - PINOS_ERROR, - PINOS_ERROR_BUFFER_ALLOCATION, - "error alloc input buffers: %d", res); - goto error; - } - this->input->buffers = priv->buffers; - this->input->n_buffers = priv->n_buffers; - this->input->allocated = TRUE; - this->input->buffer_mem = priv->buffer_mem; - priv->allocated = FALSE; - g_debug ("allocated %d buffers %p from input port", priv->n_buffers, priv->buffers); - } - else if (out_flags & SPA_PORT_INFO_FLAG_CAN_ALLOC_BUFFERS) { + if (out_flags & SPA_PORT_INFO_FLAG_CAN_ALLOC_BUFFERS) { if ((res = spa_node_port_alloc_buffers (this->output->node->node, SPA_DIRECTION_OUTPUT, this->output->port, @@ -548,6 +561,24 @@ do_allocation (PinosLink *this, SpaNodeState in_state, SpaNodeState out_state) this->output->buffer_mem = priv->buffer_mem; priv->allocated = FALSE; g_debug ("allocated %d buffers %p from output port", priv->n_buffers, priv->buffers); + } else if (in_flags & SPA_PORT_INFO_FLAG_CAN_ALLOC_BUFFERS) { + if ((res = spa_node_port_alloc_buffers (this->input->node->node, + SPA_DIRECTION_INPUT, + this->input->port, + oinfo->params, oinfo->n_params, + priv->buffers, &priv->n_buffers)) < 0) { + g_set_error (&error, + PINOS_ERROR, + PINOS_ERROR_BUFFER_ALLOCATION, + "error alloc input buffers: %d", res); + goto error; + } + this->input->buffers = priv->buffers; + this->input->n_buffers = priv->n_buffers; + this->input->allocated = TRUE; + this->input->buffer_mem = priv->buffer_mem; + priv->allocated = FALSE; + g_debug ("allocated %d buffers %p from input port", priv->n_buffers, priv->buffers); } } @@ -770,9 +801,28 @@ pinos_link_dispose (GObject * object) g_signal_emit (this, signals[SIGNAL_REMOVE], 0, NULL); - this->input = NULL; - this->output = NULL; - + if (this->input) { + if (!this->input->allocated) { + spa_node_port_use_buffers (this->input->node->node, + SPA_DIRECTION_INPUT, + this->input->port, + NULL, 0); + this->input->buffers = NULL; + this->input->n_buffers = 0; + } + this->input = NULL; + } + if (this->output) { + if (!this->output->allocated) { + spa_node_port_use_buffers (this->output->node->node, + SPA_DIRECTION_OUTPUT, + this->output->port, + NULL, 0); + this->output->buffers = NULL; + this->output->n_buffers = 0; + } + this->output = NULL; + } link_unregister_object (this); G_OBJECT_CLASS (pinos_link_parent_class)->dispose (object); @@ -789,8 +839,9 @@ pinos_link_finalize (GObject * object) g_clear_object (&priv->iface); g_free (priv->object_path); - if (priv->allocated) + if (priv->allocated) { pinos_memblock_free (&priv->buffer_mem); + } G_OBJECT_CLASS (pinos_link_parent_class)->finalize (object); } diff --git a/spa/include/spa/buffer.h b/spa/include/spa/buffer.h index ea4b690c4..2c06b89ae 100644 --- a/spa/include/spa/buffer.h +++ b/spa/include/spa/buffer.h @@ -30,6 +30,9 @@ typedef struct _SpaBuffer SpaBuffer; * SpaMetaType: * @SPA_META_TYPE_INVALID: invalid metadata, should be ignored * @SPA_META_TYPE_HEADER: header metadata + * @SPA_META_TYPE_POINTER: a generic pointer + * @SPA_META_TYPE_VIDEO_CROP: video cropping region + * @SPA_META_TYPE_RINGBUFFER: a ringbuffer */ typedef enum { SPA_META_TYPE_INVALID = 0, @@ -39,6 +42,23 @@ typedef enum { SPA_META_TYPE_RINGBUFFER, } SpaMetaType; +/** + * SpaDataType: + * @SPA_DATA_TYPE_INVALID: invalid data, should be ignored + * @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_DMABUF: data is an int file descriptor, use SPA_PTR_TO_INT + * @SPA_DATA_TYPE_ID: data is an id use SPA_PTR_TO_INT32. The definition of + * the ID is conveyed in some other way + */ +typedef enum { + SPA_DATA_TYPE_INVALID = 0, + SPA_DATA_TYPE_MEMPTR, + SPA_DATA_TYPE_MEMFD, + SPA_DATA_TYPE_DMABUF, + SPA_DATA_TYPE_ID, +} SpaDataType; + #include #include @@ -113,35 +133,21 @@ typedef struct { size_t size; } SpaMeta; -/** - * SpaDataType: - * @SPA_DATA_TYPE_INVALID: invalid data, should be ignored - * @SPA_DATA_TYPE_MEMPTR: data points to CPU accessible memory - * @SPA_DATA_TYPE_FD: data is an int file descriptor, use SPA_PTR_TO_INT - * @SPA_DATA_TYPE_ID: data is an id use SPA_PTR_TO_INT32 - */ -typedef enum { - SPA_DATA_TYPE_INVALID = 0, - SPA_DATA_TYPE_MEMPTR, - SPA_DATA_TYPE_FD, - SPA_DATA_TYPE_ID, -} SpaDataType; - /** * SpaData: * @type: memory type * @data: pointer to memory + * @maxsize: size of @data * @offset: offset in @data * @size: valid size of @data - * @maxsize: size of @data * @stride: stride of data if applicable */ typedef struct { SpaDataType type; void *data; + size_t maxsize; off_t offset; size_t size; - size_t maxsize; ssize_t stride; } SpaData; @@ -168,16 +174,7 @@ SpaBuffer * spa_buffer_deserialize (void *src, off_t offset); -SpaResult spa_alloc_params_get_header_size (SpaAllocParam **params, - unsigned int n_params, - unsigned int n_datas, - size_t *size); - -SpaResult spa_buffer_init_headers (SpaAllocParam **params, - unsigned int n_params, - unsigned int n_datas, - SpaBuffer **buffers, - unsigned int n_buffers); +size_t spa_meta_type_get_size (SpaMetaType type); #ifdef __cplusplus } /* extern "C" */ diff --git a/spa/include/spa/control.h b/spa/include/spa/control.h index 761674b55..c13fcc84c 100644 --- a/spa/include/spa/control.h +++ b/spa/include/spa/control.h @@ -160,6 +160,7 @@ typedef struct { SpaDirection direction; uint32_t port_id; uint32_t mem_id; + SpaDataType type; unsigned int fd_index; uint32_t flags; off_t offset; diff --git a/spa/include/spa/defs.h b/spa/include/spa/defs.h index 0a42687ae..14632ee8b 100644 --- a/spa/include/spa/defs.h +++ b/spa/include/spa/defs.h @@ -85,6 +85,7 @@ typedef void (*SpaNotify) (void *data); #define SPA_N_ELEMENTS(arr) (sizeof (arr) / sizeof ((arr)[0])) #define SPA_MIN(a,b) ((a)<(b) ? (a) : (b)) #define SPA_MAX(a,b) ((a)>(b) ? (a) : (b)) +#define SPA_CLAMP(v,a,b) ((v)>(b) ? (b) : ((v) < (a) ? (a) : (v))) #define SPA_MEMBER(b,o,t) ((t*)((uint8_t*)(b) + (o))) #define SPA_PTRDIFF(p1,p2) ((uint8_t*)(p1) - (uint8_t*)(p2)) diff --git a/spa/lib/buffer.c b/spa/lib/buffer.c index 6037d1e4b..79abc054b 100644 --- a/spa/lib/buffer.c +++ b/spa/lib/buffer.c @@ -33,104 +33,15 @@ static const size_t header_sizes[] = { sizeof (SpaMetaRingbuffer), }; -SpaResult -spa_alloc_params_get_header_size (SpaAllocParam **params, - unsigned int n_params, - unsigned int n_datas, - size_t *size) +size_t +spa_meta_type_get_size (SpaMetaType type) { - unsigned int i, n_metas = 0; + if (type <= 0 || type >= SPA_N_ELEMENTS (header_sizes)) + return 0; - *size = sizeof (SpaBuffer); - - for (i = 0; i < n_params; i++) { - SpaAllocParam *p = params[i]; - - switch (p->type) { - case SPA_ALLOC_PARAM_TYPE_META_ENABLE: - { - SpaAllocParamMetaEnable *b = (SpaAllocParamMetaEnable *) p; - - if (b->type > 0 && b->type < SPA_N_ELEMENTS (header_sizes)) { - n_metas++; - *size += header_sizes[b->type]; - } - break; - } - default: - break; - } - } - *size += n_metas * sizeof (SpaMeta); - *size += n_datas * sizeof (SpaData); - - return SPA_RESULT_OK; + return header_sizes[type]; } -SpaResult -spa_buffer_init_headers (SpaAllocParam **params, - unsigned int n_params, - unsigned int n_datas, - SpaBuffer **buffers, - unsigned int n_buffers) -{ - unsigned int i; - int n_metas = 0; - - for (i = 0; i < n_params; i++) { - SpaAllocParam *p = params[i]; - - switch (p->type) { - case SPA_ALLOC_PARAM_TYPE_META_ENABLE: - { - SpaAllocParamMetaEnable *b = (SpaAllocParamMetaEnable *) p; - if (b->type > 0 && b->type <= SPA_N_ELEMENTS (header_sizes)) - n_metas++; - } - default: - break; - } - } - - for (i = 0; i < n_buffers; i++) { - int mi = 0, j; - SpaBuffer *b; - void *p; - - b = buffers[i]; - b->id = i; - b->n_metas = n_metas; - b->metas = SPA_MEMBER (b, sizeof (SpaBuffer), SpaMeta); - b->n_datas = n_datas; - b->datas = SPA_MEMBER (b->metas, sizeof (SpaMeta) * n_metas, SpaData); - p = SPA_MEMBER (b->datas, sizeof (SpaData) * n_datas, void); - - for (j = 0, mi = 0; j < n_params; j++) { - SpaAllocParam *prm = params[j]; - - switch (prm->type) { - case SPA_ALLOC_PARAM_TYPE_META_ENABLE: - { - SpaAllocParamMetaEnable *pme = (SpaAllocParamMetaEnable *) prm; - - if (pme->type > 0 && pme->type <= SPA_N_ELEMENTS (header_sizes)) { - b->metas[mi].type = pme->type; - b->metas[mi].data = p; - b->metas[mi].size = header_sizes[pme->type]; - p = SPA_MEMBER (p, header_sizes[pme->type], void); - mi++; - } - break; - } - default: - break; - } - } - } - return SPA_RESULT_OK; -} - - size_t spa_buffer_get_size (const SpaBuffer *buffer) { diff --git a/spa/lib/debug.c b/spa/lib/debug.c index 2a710bf6b..f6f9cb00e 100644 --- a/spa/lib/debug.c +++ b/spa/lib/debug.c @@ -23,6 +23,30 @@ #include "spa/props.h" #include "spa/format.h" +struct meta_type_name { + const char *name; +} meta_type_names[] = { + { "invalid" }, + { "SpaMetaHeader" }, + { "SpaMetaPointer" }, + { "SpaMetaVideoCrop" }, + { "SpaMetaRingbuffer" }, + { "invalid" }, +}; +#define META_TYPE_NAME(t) meta_type_names[SPA_CLAMP(t,0,SPA_N_ELEMENTS(meta_type_names)-1)].name + +struct data_type_name { + const char *name; +} data_type_names[] = { + { "invalid" }, + { "memptr" }, + { "memfd" }, + { "dmabuf" }, + { "ID" }, + { "invalid" }, +}; +#define DATA_TYPE_NAME(t) data_type_names[SPA_CLAMP(t,0,SPA_N_ELEMENTS(data_type_names)-1)].name + SpaResult spa_debug_port_info (const SpaPortInfo *info) { @@ -58,7 +82,7 @@ spa_debug_port_info (const SpaPortInfo *info) { SpaAllocParamMetaEnable *p = (SpaAllocParamMetaEnable *)param; fprintf (stderr, " SpaAllocParamMetaEnable:\n"); - fprintf (stderr, " type: \t%d\n", p->type); + fprintf (stderr, " type: \t%d (%s)\n", p->type, META_TYPE_NAME(p->type)); break; } case SPA_ALLOC_PARAM_TYPE_VIDEO_PADDING: @@ -94,7 +118,7 @@ spa_debug_buffer (const SpaBuffer *buffer) fprintf (stderr, " n_metas: %u (at %p)\n", buffer->n_metas, buffer->metas); for (i = 0; i < buffer->n_metas; i++) { SpaMeta *m = &buffer->metas[i]; - fprintf (stderr, " meta %d: type %d, data %p, size %zd:\n", i, m->type, m->data, m->size); + fprintf (stderr, " meta %d: type %d (%s), data %p, size %zd:\n", i, m->type, META_TYPE_NAME (m->type), m->data, m->size); switch (m->type) { case SPA_META_TYPE_HEADER: { @@ -107,13 +131,34 @@ spa_debug_buffer (const SpaBuffer *buffer) break; } case SPA_META_TYPE_POINTER: + { + SpaMetaPointer *h = m->data; fprintf (stderr, " SpaMetaPointer:\n"); + fprintf (stderr, " ptr_type: %s\n", h->ptr_type); + fprintf (stderr, " ptr: %p\n", h->ptr); spa_debug_dump_mem (m->data, m->size); break; + } case SPA_META_TYPE_VIDEO_CROP: + { + SpaMetaVideoCrop *h = m->data; fprintf (stderr, " SpaMetaVideoCrop:\n"); - spa_debug_dump_mem (m->data, m->size); + fprintf (stderr, " x: %d\n", h->x); + fprintf (stderr, " y: %d\n", h->y); + fprintf (stderr, " width: %d\n", h->width); + fprintf (stderr, " height: %d\n", h->height); break; + } + case SPA_META_TYPE_RINGBUFFER: + { + SpaMetaRingbuffer *h = m->data; + fprintf (stderr, " SpaMetaRingbuffer:\n"); + fprintf (stderr, " readindex: %d\n", h->readindex); + fprintf (stderr, " writeindex: %d\n", h->writeindex); + fprintf (stderr, " size: %d\n", h->size); + fprintf (stderr, " size_mask: %d\n", h->size_mask); + break; + } default: spa_debug_dump_mem (m->data, m->size); break; @@ -122,7 +167,7 @@ spa_debug_buffer (const SpaBuffer *buffer) fprintf (stderr, " n_datas: \t%u (at %p)\n", buffer->n_datas, buffer->datas); for (i = 0; i < buffer->n_datas; i++) { SpaData *d = &buffer->datas[i]; - fprintf (stderr, " type: %d\n", d->type); + fprintf (stderr, " type: %d (%s)\n", d->type, DATA_TYPE_NAME (d->type)); fprintf (stderr, " data: %p\n", d->data); fprintf (stderr, " offset: %zd\n", d->offset); fprintf (stderr, " size: %zd\n", d->size); diff --git a/spa/plugins/ffmpeg/ffmpeg-dec.c b/spa/plugins/ffmpeg/ffmpeg-dec.c index f116a3516..908e82033 100644 --- a/spa/plugins/ffmpeg/ffmpeg-dec.c +++ b/spa/plugins/ffmpeg/ffmpeg-dec.c @@ -36,20 +36,13 @@ reset_ffmpeg_dec_props (SpaFFMpegDecProps *props) { } -#define INPUT_PORT_ID 0 -#define OUTPUT_PORT_ID 1 -#define IS_VALID_PORT(id) ((id) < 2) +#define IS_VALID_PORT(this,d,id) ((id) == 0) #define MAX_BUFFERS 32 typedef struct _FFMpegBuffer FFMpegBuffer; struct _FFMpegBuffer { - SpaBuffer buffer; - SpaMeta metas[1]; - SpaMetaHeader header; - SpaData datas[1]; - SpaFFMpegDec *dec; - SpaBuffer *imported; + SpaBuffer *outbuf; bool outstanding; FFMpegBuffer *next; }; @@ -63,7 +56,7 @@ typedef struct { SpaAllocParam *params[1]; SpaAllocParamBuffers param_buffers; SpaPortStatus status; -} SpaFFMpegState; +} SpaFFMpegPort; struct _SpaFFMpegDec { SpaHandle handle; @@ -74,7 +67,8 @@ struct _SpaFFMpegDec { SpaNodeEventCallback event_cb; void *user_data; - SpaFFMpegState state[2]; + SpaFFMpegPort in_ports[1]; + SpaFFMpegPort out_ports[1]; }; enum { @@ -218,7 +212,7 @@ spa_ffmpeg_dec_node_get_port_ids (SpaNode *node, if (n_input_ports > 0 && input_ids != NULL) input_ids[0] = 0; if (n_output_ports > 0 && output_ids != NULL) - output_ids[0] = 1; + output_ids[0] = 0; return SPA_RESULT_OK; } @@ -226,6 +220,7 @@ spa_ffmpeg_dec_node_get_port_ids (SpaNode *node, static SpaResult spa_ffmpeg_dec_node_add_port (SpaNode *node, + SpaDirection direction, uint32_t port_id) { return SPA_RESULT_NOT_IMPLEMENTED; @@ -233,6 +228,7 @@ spa_ffmpeg_dec_node_add_port (SpaNode *node, static SpaResult spa_ffmpeg_dec_node_remove_port (SpaNode *node, + SpaDirection direction, uint32_t port_id) { return SPA_RESULT_NOT_IMPLEMENTED; @@ -240,13 +236,14 @@ spa_ffmpeg_dec_node_remove_port (SpaNode *node, static SpaResult spa_ffmpeg_dec_node_port_enum_formats (SpaNode *node, + SpaDirection direction, uint32_t port_id, SpaFormat **format, const SpaFormat *filter, void **state) { SpaFFMpegDec *this; - SpaFFMpegState *s; + SpaFFMpegPort *port; int index; if (node == NULL || node->handle == NULL || format == NULL || state == NULL) @@ -254,10 +251,10 @@ spa_ffmpeg_dec_node_port_enum_formats (SpaNode *node, this = (SpaFFMpegDec *) node->handle; - if (!IS_VALID_PORT (port_id)) + if (!IS_VALID_PORT (this, direction, port_id)) return SPA_RESULT_INVALID_PORT; - s = &this->state[port_id]; + port = direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id]; index = (*state == NULL ? 0 : *(int*)state); @@ -265,12 +262,12 @@ spa_ffmpeg_dec_node_port_enum_formats (SpaNode *node, case 0: spa_format_video_init (SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_RAW, - &s->format[0]); + &port->format[0]); break; default: return SPA_RESULT_ENUM_END; } - *format = &s->format[0].format; + *format = &port->format[0].format; *(int*)state = ++index; return SPA_RESULT_OK; @@ -278,12 +275,13 @@ spa_ffmpeg_dec_node_port_enum_formats (SpaNode *node, static SpaResult spa_ffmpeg_dec_node_port_set_format (SpaNode *node, + SpaDirection direction, uint32_t port_id, SpaPortFormatFlags flags, const SpaFormat *format) { SpaFFMpegDec *this; - SpaFFMpegState *state; + SpaFFMpegPort *port; SpaResult res; if (node == NULL || node->handle == NULL || format == NULL) @@ -291,22 +289,22 @@ spa_ffmpeg_dec_node_port_set_format (SpaNode *node, this = (SpaFFMpegDec *) node->handle; - if (!IS_VALID_PORT (port_id)) + if (!IS_VALID_PORT (this, direction, port_id)) return SPA_RESULT_INVALID_PORT; - state = &this->state[port_id]; + port = direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id]; if (format == NULL) { - state->current_format = NULL; + port->current_format = NULL; return SPA_RESULT_OK; } - if ((res = spa_format_video_parse (format, &state->format[0]) < 0)) + if ((res = spa_format_video_parse (format, &port->format[0]) < 0)) return res; if (!(flags & SPA_PORT_FORMAT_FLAG_TEST_ONLY)) { - memcpy (&state->format[1], &state->format[0], sizeof (SpaFormatVideo)); - state->current_format = &state->format[1].format; + memcpy (&port->format[1], &port->format[0], sizeof (SpaFormatVideo)); + port->current_format = &port->format[1].format; } return SPA_RESULT_OK; @@ -314,60 +312,66 @@ spa_ffmpeg_dec_node_port_set_format (SpaNode *node, static SpaResult spa_ffmpeg_dec_node_port_get_format (SpaNode *node, + SpaDirection direction, uint32_t port_id, const SpaFormat **format) { SpaFFMpegDec *this; - SpaFFMpegState *state; + SpaFFMpegPort *port; if (node == NULL || node->handle == NULL || format == NULL) return SPA_RESULT_INVALID_ARGUMENTS; this = (SpaFFMpegDec *) node->handle; - if (!IS_VALID_PORT (port_id)) + if (!IS_VALID_PORT (this, direction, port_id)) return SPA_RESULT_INVALID_PORT; - state = &this->state[port_id]; + port = direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id]; - if (state->current_format == NULL) + if (port->current_format == NULL) return SPA_RESULT_NO_FORMAT; - *format = state->current_format; + *format = port->current_format; return SPA_RESULT_OK; } static SpaResult spa_ffmpeg_dec_node_port_get_info (SpaNode *node, + SpaDirection direction, uint32_t port_id, const SpaPortInfo **info) { SpaFFMpegDec *this; + SpaFFMpegPort *port; if (node == NULL || node->handle == NULL || info == NULL) return SPA_RESULT_INVALID_ARGUMENTS; this = (SpaFFMpegDec *) node->handle; - if (!IS_VALID_PORT (port_id)) + if (!IS_VALID_PORT (this, direction, port_id)) return SPA_RESULT_INVALID_PORT; - *info = &this->state[port_id].info; + port = direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id]; + *info = &port->info; return SPA_RESULT_OK; } static SpaResult -spa_ffmpeg_dec_node_port_get_props (SpaNode *node, - uint32_t port_id, - SpaProps **props) +spa_ffmpeg_dec_node_port_get_props (SpaNode *node, + SpaDirection direction, + uint32_t port_id, + SpaProps **props) { return SPA_RESULT_NOT_IMPLEMENTED; } static SpaResult spa_ffmpeg_dec_node_port_set_props (SpaNode *node, + SpaDirection direction, uint32_t port_id, const SpaProps *props) { @@ -376,6 +380,7 @@ spa_ffmpeg_dec_node_port_set_props (SpaNode *node, static SpaResult spa_ffmpeg_dec_node_port_use_buffers (SpaNode *node, + SpaDirection direction, uint32_t port_id, SpaBuffer **buffers, uint32_t n_buffers) @@ -383,7 +388,7 @@ spa_ffmpeg_dec_node_port_use_buffers (SpaNode *node, if (node == NULL || node->handle == NULL) return SPA_RESULT_INVALID_ARGUMENTS; - if (!IS_VALID_PORT (port_id)) + if (!IS_VALID_PORT (node, direction, port_id)) return SPA_RESULT_INVALID_PORT; return SPA_RESULT_NOT_IMPLEMENTED; @@ -391,6 +396,7 @@ spa_ffmpeg_dec_node_port_use_buffers (SpaNode *node, static SpaResult spa_ffmpeg_dec_node_port_alloc_buffers (SpaNode *node, + SpaDirection direction, uint32_t port_id, SpaAllocParam **params, uint32_t n_params, @@ -402,20 +408,23 @@ spa_ffmpeg_dec_node_port_alloc_buffers (SpaNode *node, static SpaResult spa_ffmpeg_dec_node_port_get_status (SpaNode *node, + SpaDirection direction, uint32_t port_id, const SpaPortStatus **status) { SpaFFMpegDec *this; + SpaFFMpegPort *port; if (node == NULL || node->handle == NULL || status == NULL) return SPA_RESULT_INVALID_ARGUMENTS; this = (SpaFFMpegDec *) node->handle; - if (!IS_VALID_PORT (port_id)) + if (!IS_VALID_PORT (this, direction, port_id)) return SPA_RESULT_INVALID_PORT; - *status = &this->state[port_id].status; + port = direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id]; + *status = &port->status; return SPA_RESULT_OK; } @@ -434,7 +443,7 @@ spa_ffmpeg_dec_node_port_pull_output (SpaNode *node, SpaPortOutputInfo *info) { SpaFFMpegDec *this; - SpaFFMpegState *state; + SpaFFMpegPort *port; unsigned int i; bool have_error = false; @@ -444,14 +453,14 @@ spa_ffmpeg_dec_node_port_pull_output (SpaNode *node, this = (SpaFFMpegDec *) node->handle; for (i = 0; i < n_info; i++) { - if (info[i].port_id != OUTPUT_PORT_ID) { + if (info[i].port_id != 0) { info[i].status = SPA_RESULT_INVALID_PORT; have_error = true; continue; } - state = &this->state[info[i].port_id]; + port = &this->out_ports[info[i].port_id]; - if (state->current_format == NULL) { + if (port->current_format == NULL) { info[i].status = SPA_RESULT_NO_FORMAT; have_error = true; continue; @@ -472,7 +481,7 @@ spa_ffmpeg_dec_node_port_reuse_buffer (SpaNode *node, if (node == NULL || node->handle == NULL) return SPA_RESULT_INVALID_ARGUMENTS; - if (!IS_VALID_PORT (port_id)) + if (port_id != 0) return SPA_RESULT_INVALID_PORT; return SPA_RESULT_NOT_IMPLEMENTED; @@ -480,6 +489,7 @@ spa_ffmpeg_dec_node_port_reuse_buffer (SpaNode *node, static SpaResult spa_ffmpeg_dec_node_port_push_event (SpaNode *node, + SpaDirection direction, uint32_t port_id, SpaNodeEvent *event) { @@ -551,11 +561,11 @@ spa_ffmpeg_dec_init (SpaHandle *handle) this->props[1].props.prop_info = prop_info; reset_ffmpeg_dec_props (&this->props[1]); - this->state[INPUT_PORT_ID].info.flags = SPA_PORT_INFO_FLAG_NONE; - this->state[INPUT_PORT_ID].status.flags = SPA_PORT_STATUS_FLAG_NONE; + this->in_ports[0].info.flags = SPA_PORT_INFO_FLAG_NONE; + this->in_ports[0].status.flags = SPA_PORT_STATUS_FLAG_NONE; - this->state[OUTPUT_PORT_ID].info.flags = SPA_PORT_INFO_FLAG_NONE; - this->state[OUTPUT_PORT_ID].status.flags = SPA_PORT_STATUS_FLAG_NONE; + this->out_ports[0].info.flags = SPA_PORT_INFO_FLAG_NONE; + this->out_ports[0].status.flags = SPA_PORT_STATUS_FLAG_NONE; return SPA_RESULT_OK; } diff --git a/spa/plugins/ffmpeg/ffmpeg-enc.c b/spa/plugins/ffmpeg/ffmpeg-enc.c index 94a7f4ecb..af323044f 100644 --- a/spa/plugins/ffmpeg/ffmpeg-enc.c +++ b/spa/plugins/ffmpeg/ffmpeg-enc.c @@ -36,9 +36,7 @@ reset_ffmpeg_enc_props (SpaFFMpegEncProps *props) { } -#define INPUT_PORT_ID 0 -#define OUTPUT_PORT_ID 1 -#define IS_VALID_PORT(id) ((id) < 2) +#define IS_VALID_PORT(this,d,id) ((id) == 0) #define MAX_BUFFERS 32 typedef struct _FFMpegBuffer FFMpegBuffer; @@ -63,7 +61,7 @@ typedef struct { SpaAllocParam *params[1]; SpaAllocParamBuffers param_buffers; SpaPortStatus status; -} SpaFFMpegState; +} SpaFFMpegPort; struct _SpaFFMpegEnc { SpaHandle handle; @@ -74,7 +72,8 @@ struct _SpaFFMpegEnc { SpaNodeEventCallback event_cb; void *user_data; - SpaFFMpegState state[2]; + SpaFFMpegPort in_ports[0]; + SpaFFMpegPort out_ports[0]; }; enum { @@ -218,7 +217,7 @@ spa_ffmpeg_enc_node_get_port_ids (SpaNode *node, if (n_input_ports > 0 && input_ids != NULL) input_ids[0] = 0; if (n_output_ports > 0 && output_ids != NULL) - output_ids[0] = 1; + output_ids[0] = 0; return SPA_RESULT_OK; } @@ -226,6 +225,7 @@ spa_ffmpeg_enc_node_get_port_ids (SpaNode *node, static SpaResult spa_ffmpeg_enc_node_add_port (SpaNode *node, + SpaDirection direction, uint32_t port_id) { return SPA_RESULT_NOT_IMPLEMENTED; @@ -233,6 +233,7 @@ spa_ffmpeg_enc_node_add_port (SpaNode *node, static SpaResult spa_ffmpeg_enc_node_remove_port (SpaNode *node, + SpaDirection direction, uint32_t port_id) { return SPA_RESULT_NOT_IMPLEMENTED; @@ -240,13 +241,14 @@ spa_ffmpeg_enc_node_remove_port (SpaNode *node, static SpaResult spa_ffmpeg_enc_node_port_enum_formats (SpaNode *node, + SpaDirection direction, uint32_t port_id, SpaFormat **format, const SpaFormat *filter, void **state) { SpaFFMpegEnc *this; - SpaFFMpegState *s; + SpaFFMpegPort *port; int index; if (node == NULL || node->handle == NULL || format == NULL) @@ -254,10 +256,10 @@ spa_ffmpeg_enc_node_port_enum_formats (SpaNode *node, this = (SpaFFMpegEnc *) node->handle; - if (!IS_VALID_PORT (port_id)) + if (!IS_VALID_PORT (this, direction, port_id)) return SPA_RESULT_INVALID_PORT; - s = &this->state[port_id]; + port = direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id]; index = (*state == NULL ? 0 : *(int*)state); @@ -265,12 +267,12 @@ spa_ffmpeg_enc_node_port_enum_formats (SpaNode *node, case 0: spa_format_video_init (SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_RAW, - &s->format[0]); + &port->format[0]); break; default: return SPA_RESULT_ENUM_END; } - *format = &s->format[0].format; + *format = &port->format[0].format; *(int*)state = ++index; return SPA_RESULT_OK; @@ -278,12 +280,13 @@ spa_ffmpeg_enc_node_port_enum_formats (SpaNode *node, static SpaResult spa_ffmpeg_enc_node_port_set_format (SpaNode *node, + SpaDirection direction, uint32_t port_id, SpaPortFormatFlags flags, const SpaFormat *format) { SpaFFMpegEnc *this; - SpaFFMpegState *state; + SpaFFMpegPort *port; SpaResult res; if (node == NULL || node->handle == NULL || format == NULL) @@ -291,16 +294,16 @@ spa_ffmpeg_enc_node_port_set_format (SpaNode *node, this = (SpaFFMpegEnc *) node->handle; - if (!IS_VALID_PORT (port_id)) + if (!IS_VALID_PORT (this, direction, port_id)) return SPA_RESULT_INVALID_PORT; - state = &this->state[port_id]; + port = direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id]; if (format == NULL) { - state->current_format = NULL; + port->current_format = NULL; return SPA_RESULT_OK; } - if ((res = spa_format_video_parse (format, &state->format[0]) < 0)) + if ((res = spa_format_video_parse (format, &port->format[0]) < 0)) return res; if (format->media_type != SPA_MEDIA_TYPE_VIDEO || @@ -308,8 +311,8 @@ spa_ffmpeg_enc_node_port_set_format (SpaNode *node, return SPA_RESULT_INVALID_MEDIA_TYPE; if (!(flags & SPA_PORT_FORMAT_FLAG_TEST_ONLY)) { - memcpy (&state->format[1], &state->format[0], sizeof (SpaFormatVideo)); - state->current_format = &state->format[1].format; + memcpy (&port->format[1], &port->format[0], sizeof (SpaFormatVideo)); + port->current_format = &port->format[1].format; } return SPA_RESULT_OK; @@ -317,60 +320,66 @@ spa_ffmpeg_enc_node_port_set_format (SpaNode *node, static SpaResult spa_ffmpeg_enc_node_port_get_format (SpaNode *node, + SpaDirection direction, uint32_t port_id, const SpaFormat **format) { SpaFFMpegEnc *this; - SpaFFMpegState *state; + SpaFFMpegPort *port; if (node == NULL || node->handle == NULL || format == NULL) return SPA_RESULT_INVALID_ARGUMENTS; this = (SpaFFMpegEnc *) node->handle; - if (!IS_VALID_PORT (port_id)) + if (!IS_VALID_PORT (this, direction, port_id)) return SPA_RESULT_INVALID_PORT; - state = &this->state[port_id]; + port = direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id]; - if (state->current_format == NULL) + if (port->current_format == NULL) return SPA_RESULT_NO_FORMAT; - *format = state->current_format; + *format = port->current_format; return SPA_RESULT_OK; } static SpaResult spa_ffmpeg_enc_node_port_get_info (SpaNode *node, + SpaDirection direction, uint32_t port_id, const SpaPortInfo **info) { SpaFFMpegEnc *this; + SpaFFMpegPort *port; if (node == NULL || node->handle == NULL || info == NULL) return SPA_RESULT_INVALID_ARGUMENTS; this = (SpaFFMpegEnc *) node->handle; - if (!IS_VALID_PORT (port_id)) + if (!IS_VALID_PORT (this, direction, port_id)) return SPA_RESULT_INVALID_PORT; - *info = &this->state[port_id].info; + port = direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id]; + *info = &port->info; return SPA_RESULT_OK; } static SpaResult -spa_ffmpeg_enc_node_port_get_props (SpaNode *node, - uint32_t port_id, - SpaProps **props) +spa_ffmpeg_enc_node_port_get_props (SpaNode *node, + SpaDirection direction, + uint32_t port_id, + SpaProps **props) { return SPA_RESULT_NOT_IMPLEMENTED; } static SpaResult spa_ffmpeg_enc_node_port_set_props (SpaNode *node, + SpaDirection direction, uint32_t port_id, const SpaProps *props) { @@ -379,6 +388,7 @@ spa_ffmpeg_enc_node_port_set_props (SpaNode *node, static SpaResult spa_ffmpeg_enc_node_port_use_buffers (SpaNode *node, + SpaDirection direction, uint32_t port_id, SpaBuffer **buffers, uint32_t n_buffers) @@ -386,7 +396,7 @@ spa_ffmpeg_enc_node_port_use_buffers (SpaNode *node, if (node == NULL || node->handle == NULL) return SPA_RESULT_INVALID_ARGUMENTS; - if (!IS_VALID_PORT (port_id)) + if (!IS_VALID_PORT (node, direction, port_id)) return SPA_RESULT_INVALID_PORT; return SPA_RESULT_NOT_IMPLEMENTED; @@ -394,6 +404,7 @@ spa_ffmpeg_enc_node_port_use_buffers (SpaNode *node, static SpaResult spa_ffmpeg_enc_node_port_alloc_buffers (SpaNode *node, + SpaDirection direction, uint32_t port_id, SpaAllocParam **params, uint32_t n_params, @@ -405,20 +416,23 @@ spa_ffmpeg_enc_node_port_alloc_buffers (SpaNode *node, static SpaResult spa_ffmpeg_enc_node_port_get_status (SpaNode *node, + SpaDirection direction, uint32_t port_id, const SpaPortStatus **status) { SpaFFMpegEnc *this; + SpaFFMpegPort *port; if (node == NULL || node->handle == NULL || status == NULL) return SPA_RESULT_INVALID_ARGUMENTS; this = (SpaFFMpegEnc *) node->handle; - if (!IS_VALID_PORT (port_id)) + if (!IS_VALID_PORT (this, direction, port_id)) return SPA_RESULT_INVALID_PORT; - *status = &this->state[port_id].status; + port = direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id]; + *status = &port->status; return SPA_RESULT_OK; } @@ -437,7 +451,7 @@ spa_ffmpeg_enc_node_port_pull_output (SpaNode *node, SpaPortOutputInfo *info) { SpaFFMpegEnc *this; - SpaFFMpegState *state; + SpaFFMpegPort *port; unsigned int i; bool have_error = false; @@ -448,14 +462,14 @@ spa_ffmpeg_enc_node_port_pull_output (SpaNode *node, for (i = 0; i < n_info; i++) { - if (info[i].port_id != OUTPUT_PORT_ID) { + if (info[i].port_id != 0) { info[i].status = SPA_RESULT_INVALID_PORT; have_error = true; continue; } - state = &this->state[info[i].port_id]; + port = &this->out_ports[info[i].port_id]; - if (state->current_format == NULL) { + if (port->current_format == NULL) { info[i].status = SPA_RESULT_NO_FORMAT; have_error = true; continue; @@ -476,7 +490,7 @@ spa_ffmpeg_enc_node_port_reuse_buffer (SpaNode *node, if (node == NULL || node->handle == NULL) return SPA_RESULT_INVALID_ARGUMENTS; - if (!IS_VALID_PORT (port_id)) + if (port_id != 0) return SPA_RESULT_INVALID_PORT; return SPA_RESULT_NOT_IMPLEMENTED; @@ -484,6 +498,7 @@ spa_ffmpeg_enc_node_port_reuse_buffer (SpaNode *node, static SpaResult spa_ffmpeg_enc_node_port_push_event (SpaNode *node, + SpaDirection direction, uint32_t port_id, SpaNodeEvent *event) { @@ -554,11 +569,11 @@ spa_ffmpeg_enc_init (SpaHandle *handle) this->props[1].props.prop_info = prop_info; reset_ffmpeg_enc_props (&this->props[1]); - this->state[INPUT_PORT_ID].info.flags = SPA_PORT_INFO_FLAG_NONE; - this->state[INPUT_PORT_ID].status.flags = SPA_PORT_STATUS_FLAG_NONE; + this->in_ports[0].info.flags = SPA_PORT_INFO_FLAG_NONE; + this->in_ports[0].status.flags = SPA_PORT_STATUS_FLAG_NONE; - this->state[OUTPUT_PORT_ID].info.flags = SPA_PORT_INFO_FLAG_NONE; - this->state[OUTPUT_PORT_ID].status.flags = SPA_PORT_STATUS_FLAG_NONE; + this->out_ports[0].info.flags = SPA_PORT_INFO_FLAG_NONE; + this->out_ports[0].status.flags = SPA_PORT_STATUS_FLAG_NONE; this->node.state = SPA_NODE_STATE_CONFIGURE; diff --git a/spa/plugins/remote/proxy.c b/spa/plugins/remote/proxy.c index 3a95fc54c..a8be0686f 100644 --- a/spa/plugins/remote/proxy.c +++ b/spa/plugins/remote/proxy.c @@ -747,10 +747,12 @@ spa_proxy_node_port_use_buffers (SpaNode *node, memcpy (&b->buffer.datas[j], d, sizeof (SpaData)); switch (d->type) { - case SPA_DATA_TYPE_FD: + case SPA_DATA_TYPE_DMABUF: + case SPA_DATA_TYPE_MEMFD: am.direction = direction; am.port_id = port_id; am.mem_id = n_mem; + am.type = d->type; am.fd_index = spa_control_builder_add_fd (&builder, SPA_PTR_TO_INT (d->data), false); am.flags = 0; am.offset = d->offset; @@ -821,6 +823,7 @@ spa_proxy_node_port_use_buffers (SpaNode *node, am.direction = direction; am.port_id = port_id; am.mem_id = port->buffer_mem_id; + am.type = SPA_DATA_TYPE_MEMFD; am.fd_index = spa_control_builder_add_fd (&builder, port->buffer_mem_fd, false); am.flags = 0; am.offset = 0; @@ -901,7 +904,7 @@ copy_meta_in (SpaProxy *this, SpaProxyPort *port, uint32_t buffer_id) } static void -copy_meta (SpaProxy *this, SpaProxyPort *port, uint32_t buffer_id) +copy_meta_out (SpaProxy *this, SpaProxyPort *port, uint32_t buffer_id) { ProxyBuffer *b = &port->buffers[buffer_id]; unsigned int i; @@ -966,7 +969,7 @@ spa_proxy_node_port_push_input (SpaNode *node, continue; } - copy_meta (this, port, info[i].buffer_id); + copy_meta_out (this, port, info[i].buffer_id); pb.direction = SPA_DIRECTION_INPUT; pb.port_id = info[i].port_id; diff --git a/spa/plugins/v4l2/v4l2-source.c b/spa/plugins/v4l2/v4l2-source.c index 0304f9d0f..231f8d7a8 100644 --- a/spa/plugins/v4l2/v4l2-source.c +++ b/spa/plugins/v4l2/v4l2-source.c @@ -47,7 +47,7 @@ reset_v4l2_source_props (SpaV4l2SourceProps *props) props->props.unset_mask = 7; } -#define MAX_BUFFERS 256 +#define MAX_BUFFERS 64 typedef struct _V4l2Buffer V4l2Buffer; @@ -57,6 +57,8 @@ struct _V4l2Buffer { bool outstanding; struct v4l2_buffer v4l2_buffer; V4l2Buffer *next; + void *ptr; + size_t size; }; typedef struct _V4l2Format V4l2Format; diff --git a/spa/plugins/v4l2/v4l2-utils.c b/spa/plugins/v4l2/v4l2-utils.c index 5e5134e29..0d6781ff2 100644 --- a/spa/plugins/v4l2/v4l2-utils.c +++ b/spa/plugins/v4l2/v4l2-utils.c @@ -32,27 +32,27 @@ spa_v4l2_open (SpaV4l2Source *this) return 0; if (props->props.unset_mask & 1) { - fprintf(stderr, "Device property not set\n"); + fprintf(stderr, "v4l2: Device property not set\n"); return -1; } - fprintf (stderr, "Playback device is '%s'\n", props->device); + fprintf (stderr, "v4l2: Playback device is '%s'\n", props->device); if (stat (props->device, &st) < 0) { - fprintf(stderr, "Cannot identify '%s': %d, %s\n", + fprintf(stderr, "v4l2: Cannot identify '%s': %d, %s\n", props->device, errno, strerror (errno)); return -1; } if (!S_ISCHR (st.st_mode)) { - fprintf(stderr, "%s is no device\n", props->device); + fprintf(stderr, "v4l2: %s is no device\n", props->device); return -1; } state->fd = open (props->device, O_RDWR | O_NONBLOCK, 0); if (state->fd == -1) { - fprintf (stderr, "Cannot open '%s': %d, %s\n", + fprintf (stderr, "v4l2: Cannot open '%s': %d, %s\n", props->device, errno, strerror (errno)); return -1; } @@ -63,7 +63,7 @@ spa_v4l2_open (SpaV4l2Source *this) } if ((state->cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == 0) { - fprintf (stderr, "%s is no video capture device\n", props->device); + fprintf (stderr, "v4l2: %s is no video capture device\n", props->device); return -1; } state->opened = true; @@ -103,12 +103,15 @@ spa_v4l2_clear_buffers (SpaV4l2Source *this) b = &state->buffers[i]; if (b->outstanding) { - fprintf (stderr, "queueing outstanding buffer %p\n", b); + fprintf (stderr, "v4l2: queueing outstanding buffer %p\n", b); spa_v4l2_buffer_recycle (this, i); } - if (state->export_buf) { - close (SPA_PTR_TO_INT (b->outbuf->datas[0].data)); + if (b->ptr) { + munmap (b->ptr, b->size); + b->ptr = NULL; } + if (b->outbuf->datas[0].type == SPA_DATA_TYPE_DMABUF) + close (SPA_PTR_TO_INT (b->outbuf->datas[0].data)); } CLEAR(reqbuf); @@ -135,7 +138,7 @@ spa_v4l2_close (SpaV4l2Source *this) if (state->n_buffers > 0) return 0; - fprintf (stderr, "close\n"); + fprintf (stderr, "v4l2: close\n"); if (close(state->fd)) perror ("close"); @@ -745,7 +748,7 @@ spa_v4l2_set_format (SpaV4l2Source *this, V4l2Format *f, bool try_only) f->format, 0); if (info == NULL) { - fprintf (stderr, "unknown media type %d %d %d\n", f->fmt.media_type, + fprintf (stderr, "v4l2: unknown media type %d %d %d\n", f->fmt.media_type, f->fmt.media_subtype, f->format); return -1; } @@ -757,7 +760,7 @@ spa_v4l2_set_format (SpaV4l2Source *this, V4l2Format *f, bool try_only) streamparm.parm.capture.timeperframe.numerator = f->framerate.denom; streamparm.parm.capture.timeperframe.denominator = f->framerate.num; - fprintf (stderr, "set %08x %dx%d %d/%d\n", fmt.fmt.pix.pixelformat, + fprintf (stderr, "v4l2: set %08x %dx%d %d/%d\n", fmt.fmt.pix.pixelformat, fmt.fmt.pix.width, fmt.fmt.pix.height, streamparm.parm.capture.timeperframe.numerator, streamparm.parm.capture.timeperframe.denominator); @@ -777,7 +780,7 @@ spa_v4l2_set_format (SpaV4l2Source *this, V4l2Format *f, bool try_only) if (xioctl (state->fd, VIDIOC_S_PARM, &streamparm) < 0) perror ("VIDIOC_S_PARM"); - fprintf (stderr, "got %08x %dx%d %d/%d\n", fmt.fmt.pix.pixelformat, + fprintf (stderr, "v4l2: got %08x %dx%d %d/%d\n", fmt.fmt.pix.pixelformat, fmt.fmt.pix.width, fmt.fmt.pix.height, streamparm.parm.capture.timeperframe.numerator, streamparm.parm.capture.timeperframe.denominator); @@ -908,8 +911,22 @@ spa_v4l2_use_buffers (SpaV4l2Source *this, SpaBuffer **buffers, uint32_t n_buffe SpaV4l2State *state = &this->state[0]; struct v4l2_requestbuffers reqbuf; int i; + SpaData *d; - state->memtype = V4L2_MEMORY_USERPTR; + if (n_buffers > 0) { + switch (buffers[0]->datas[0].type) { + case SPA_DATA_TYPE_MEMPTR: + case SPA_DATA_TYPE_MEMFD: + state->memtype = V4L2_MEMORY_USERPTR; + break; + case SPA_DATA_TYPE_DMABUF: + state->memtype = V4L2_MEMORY_DMABUF; + break; + default: + fprintf (stderr, "v4l2: can't use buffers\n"); + return SPA_RESULT_ERROR; + } + } CLEAR(reqbuf); reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; @@ -920,25 +937,25 @@ spa_v4l2_use_buffers (SpaV4l2Source *this, SpaBuffer **buffers, uint32_t n_buffe perror ("VIDIOC_REQBUFS"); return SPA_RESULT_ERROR; } - fprintf (stderr, "got %d buffers\n", reqbuf.count); + fprintf (stderr, "v4l2: got %d buffers\n", reqbuf.count); if (reqbuf.count < 2) { - fprintf (stderr, "can't allocate enough buffers\n"); + fprintf (stderr, "v4l2: can't allocate enough buffers\n"); return SPA_RESULT_ERROR; } for (i = 0; i < reqbuf.count; i++) { V4l2Buffer *b; - SpaData *d; b = &state->buffers[i]; b->outbuf = buffers[i]; b->outstanding = true; b->h = find_meta_data (b->outbuf, SPA_META_TYPE_HEADER); + b->ptr = NULL; - fprintf (stderr, "import buffer %p\n", buffers[i]); + fprintf (stderr, "v4l2: import buffer %p\n", buffers[i]); if (buffers[i]->n_datas < 1) { - fprintf (stderr, "invalid memory on buffer %p\n", buffers[i]); + fprintf (stderr, "v4l2: invalid memory on buffer %p\n", buffers[i]); continue; } d = buffers[i]->datas; @@ -947,9 +964,33 @@ spa_v4l2_use_buffers (SpaV4l2Source *this, SpaBuffer **buffers, uint32_t n_buffe 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_MEMBER (d[0].data, d[0].offset, void *); - b->v4l2_buffer.length = d[0].maxsize; - + switch (d[0].type) { + case SPA_DATA_TYPE_MEMPTR: + b->v4l2_buffer.m.userptr = (unsigned long) SPA_MEMBER (d[0].data, d[0].offset, void *); + b->v4l2_buffer.length = d[0].size; + 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: + b->v4l2_buffer.m.fd = SPA_PTR_TO_INT (d[0].data); + break; + default: + break; + } spa_v4l2_buffer_recycle (this, buffers[i]->id); } state->n_buffers = reqbuf.count; @@ -980,22 +1021,22 @@ mmap_init (SpaV4l2Source *this, return SPA_RESULT_ERROR; } - fprintf (stderr, "got %d buffers\n", reqbuf.count); + fprintf (stderr, "v4l2: got %d buffers\n", reqbuf.count); *n_buffers = reqbuf.count; if (reqbuf.count < 2) { - fprintf (stderr, "can't allocate enough buffers\n"); + fprintf (stderr, "v4l2: can't allocate enough buffers\n"); return SPA_RESULT_ERROR; } if (state->export_buf) - fprintf (stderr, "using EXPBUF\n"); + fprintf (stderr, "v4l2: using EXPBUF\n"); for (i = 0; i < reqbuf.count; i++) { V4l2Buffer *b; SpaData *d; if (buffers[i]->n_datas < 1) { - fprintf (stderr, "invalid buffer data\n"); + fprintf (stderr, "v4l2: invalid buffer data\n"); return SPA_RESULT_ERROR; } @@ -1003,6 +1044,7 @@ mmap_init (SpaV4l2Source *this, b->outbuf = buffers[i]; b->outstanding = true; b->h = find_meta_data (b->outbuf, SPA_META_TYPE_HEADER); + b->ptr = NULL; CLEAR (b->v4l2_buffer); b->v4l2_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; @@ -1031,8 +1073,7 @@ mmap_init (SpaV4l2Source *this, perror("VIDIOC_EXPBUF"); continue; } - fprintf (stderr, "expbuf %d\n", expbuf.fd); - d[0].type = SPA_DATA_TYPE_FD; + d[0].type = SPA_DATA_TYPE_DMABUF; d[0].data = SPA_INT_TO_PTR (expbuf.fd); } else { d[0].type = SPA_DATA_TYPE_MEMPTR; @@ -1046,6 +1087,8 @@ mmap_init (SpaV4l2Source *this, perror ("mmap"); continue; } + b->ptr = d[0].data; + b->size = b->v4l2_buffer.length; } spa_v4l2_buffer_recycle (this, i); }