mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-02 09:01:50 -05:00
More work on memory
Add explicit DMABUF memory because we can't use it like an fd in v4l2. mmap random fd memory and use userptr in v4l2 to use it. Allocate buffer data memory in memfd when no node can allocate. Improve debug some more
This commit is contained in:
parent
d828073bb8
commit
b8f693ceea
14 changed files with 425 additions and 329 deletions
|
|
@ -1143,15 +1143,15 @@ parse_control (PinosStream *stream,
|
||||||
case SPA_DATA_TYPE_ID:
|
case SPA_DATA_TYPE_ID:
|
||||||
{
|
{
|
||||||
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_FD;
|
d->type = SPA_DATA_TYPE_MEMFD;
|
||||||
d->data = SPA_INT_TO_PTR (bmid->fd);
|
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;
|
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);
|
||||||
g_debug (" data %d %u -> %p", j, bid.id, d->data);
|
g_debug (" data %d %u -> mem %p", j, bid.id, d->data);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
|
|
||||||
|
|
@ -385,20 +385,28 @@ on_add_buffer (GObject *gobject,
|
||||||
}
|
}
|
||||||
for (i = 0; i < b->n_datas; i++) {
|
for (i = 0; i < b->n_datas; i++) {
|
||||||
SpaData *d = &b->datas[i];
|
SpaData *d = &b->datas[i];
|
||||||
|
GstMemory *gmem = NULL;
|
||||||
|
|
||||||
if (d->type == SPA_DATA_TYPE_FD) {
|
switch (d->type) {
|
||||||
GstMemory *fdmem = NULL;
|
case SPA_DATA_TYPE_MEMFD:
|
||||||
gint fd = *(int*)d->data;
|
case SPA_DATA_TYPE_DMABUF:
|
||||||
|
{
|
||||||
|
gint fd = SPA_PTR_TO_INT (d->data);
|
||||||
|
|
||||||
fdmem = gst_fd_allocator_alloc (pinossink->allocator, dup (fd),
|
gmem = gst_fd_allocator_alloc (pinossink->allocator, dup (fd),
|
||||||
d->offset + d->maxsize, GST_FD_MEMORY_FLAG_NONE);
|
d->maxsize, GST_FD_MEMORY_FLAG_NONE);
|
||||||
gst_memory_resize (fdmem, d->offset, d->size);
|
gst_memory_resize (gmem, d->offset, d->size);
|
||||||
gst_buffer_append_memory (buf, fdmem);
|
break;
|
||||||
} else {
|
}
|
||||||
gst_buffer_append_memory (buf,
|
case SPA_DATA_TYPE_MEMPTR:
|
||||||
gst_memory_new_wrapped (0, d->data, d->offset + d->maxsize, d->offset,
|
gmem = gst_memory_new_wrapped (0, d->data, d->maxsize, d->offset,
|
||||||
d->size, NULL, NULL));
|
d->size, NULL, NULL);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
if (gmem)
|
||||||
|
gst_buffer_append_memory (buf, gmem);
|
||||||
}
|
}
|
||||||
data.flags = GST_BUFFER_FLAGS (buf);
|
data.flags = GST_BUFFER_FLAGS (buf);
|
||||||
gst_mini_object_set_qdata (GST_MINI_OBJECT_CAST (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++) {
|
for (i = 0; i < data->buf->n_datas; i++) {
|
||||||
SpaData *d = &data->buf->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->offset = mem->offset;
|
||||||
d->size = mem->size;
|
d->size = mem->size;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -398,19 +398,27 @@ on_add_buffer (GObject *gobject,
|
||||||
}
|
}
|
||||||
for (i = 0; i < b->n_datas; i++) {
|
for (i = 0; i < b->n_datas; i++) {
|
||||||
SpaData *d = &b->datas[i];
|
SpaData *d = &b->datas[i];
|
||||||
GstMemory *gmem;
|
GstMemory *gmem = NULL;
|
||||||
|
|
||||||
if (d->type == SPA_DATA_TYPE_FD) {
|
switch (d->type) {
|
||||||
gint fd = SPA_PTR_TO_INT (d->data);
|
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),
|
gmem = gst_fd_allocator_alloc (pinossrc->fd_allocator, dup (fd),
|
||||||
d->offset + 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);
|
||||||
} else {
|
break;
|
||||||
gmem = gst_memory_new_wrapped (0, d->data, d->offset + d->maxsize, d->offset,
|
}
|
||||||
d->size, NULL, NULL);
|
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);
|
data.flags = GST_BUFFER_FLAGS (buf);
|
||||||
gst_mini_object_set_qdata (GST_MINI_OBJECT_CAST (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++) {
|
for (i = 0; i < data->buf->n_datas; i++) {
|
||||||
SpaData *d = &data->buf->datas[i];
|
SpaData *d = &data->buf->datas[i];
|
||||||
GstMemory *mem = gst_buffer_get_memory (buf, i);
|
GstMemory *mem = gst_buffer_peek_memory (buf, i);
|
||||||
gst_memory_resize (mem, 0, d->size);
|
mem->offset = d->offset;
|
||||||
|
mem->size = d->size;
|
||||||
}
|
}
|
||||||
g_queue_push_tail (&pinossrc->queue, buf);
|
g_queue_push_tail (&pinossrc->queue, buf);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -433,24 +433,26 @@ 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, min_size = 4096;
|
guint max_buffers = MAX_BUFFERS;
|
||||||
gboolean alloc_data = TRUE;
|
size_t minsize = 4096, 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);
|
||||||
if (in_alloc) {
|
if (in_alloc) {
|
||||||
max_buffers = in_alloc->max_buffers == 0 ? max_buffers : SPA_MIN (in_alloc->max_buffers, max_buffers);
|
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);
|
out_alloc = find_param (oinfo, SPA_ALLOC_PARAM_TYPE_BUFFERS);
|
||||||
if (out_alloc) {
|
if (out_alloc) {
|
||||||
max_buffers = out_alloc->max_buffers == 0 ? max_buffers : SPA_MIN (out_alloc->max_buffers, max_buffers);
|
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) ||
|
if ((in_flags & SPA_PORT_INFO_FLAG_CAN_ALLOC_BUFFERS) ||
|
||||||
(out_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) {
|
if (this->output->allocated) {
|
||||||
out_flags = 0;
|
out_flags = 0;
|
||||||
|
|
@ -460,77 +462,88 @@ do_allocation (PinosLink *this, SpaNodeState in_state, SpaNodeState out_state)
|
||||||
priv->allocated = FALSE;
|
priv->allocated = FALSE;
|
||||||
g_debug ("reusing %d output buffers %p", priv->n_buffers, priv->buffers);
|
g_debug ("reusing %d output buffers %p", priv->n_buffers, priv->buffers);
|
||||||
} else {
|
} else {
|
||||||
guint i;
|
guint i, j;
|
||||||
size_t hdr_size, data_size, buf_size;
|
size_t hdr_size, buf_size, arr_size;
|
||||||
void *p;
|
void *p;
|
||||||
|
guint n_metas, n_datas;
|
||||||
|
|
||||||
spa_alloc_params_get_header_size (oinfo->params, oinfo->n_params, 1, &hdr_size);
|
n_metas = 0;
|
||||||
if (alloc_data)
|
n_datas = 1;
|
||||||
data_size = min_size;
|
|
||||||
else
|
|
||||||
data_size = 0;
|
|
||||||
|
|
||||||
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;
|
priv->n_buffers = max_buffers;
|
||||||
|
|
||||||
pinos_memblock_alloc (PINOS_MEMBLOCK_FLAG_WITH_FD |
|
pinos_memblock_alloc (PINOS_MEMBLOCK_FLAG_WITH_FD |
|
||||||
PINOS_MEMBLOCK_FLAG_MAP_READWRITE |
|
PINOS_MEMBLOCK_FLAG_MAP_READWRITE |
|
||||||
PINOS_MEMBLOCK_FLAG_SEAL,
|
PINOS_MEMBLOCK_FLAG_SEAL,
|
||||||
priv->n_buffers * (sizeof (SpaBuffer*) + buf_size),
|
priv->n_buffers * (sizeof (SpaBuffer*) + buf_size),
|
||||||
&priv->buffer_mem);
|
&priv->buffer_mem);
|
||||||
|
|
||||||
|
arr_size = priv->n_buffers * sizeof (SpaBuffer*);
|
||||||
priv->buffers = p = priv->buffer_mem.ptr;
|
priv->buffers = p = priv->buffer_mem.ptr;
|
||||||
p = SPA_MEMBER (p, priv->n_buffers * sizeof (SpaBuffer*), void);
|
p = SPA_MEMBER (p, arr_size, void);
|
||||||
for (i = 0; i < priv->n_buffers; i++)
|
|
||||||
priv->buffers[i] = SPA_MEMBER (p, buf_size * i, SpaBuffer);
|
|
||||||
|
|
||||||
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++) {
|
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);
|
b = priv->buffers[i] = SPA_MEMBER (p, buf_size * i, SpaBuffer);
|
||||||
d->type = SPA_DATA_TYPE_MEMPTR;
|
|
||||||
d->data = SPA_MEMBER (priv->buffers[i], hdr_size, void);
|
b->id = i;
|
||||||
d->size = data_size;
|
b->n_metas = n_metas;
|
||||||
d->maxsize = data_size;
|
b->metas = SPA_MEMBER (b, sizeof (SpaBuffer), SpaMeta);
|
||||||
d->offset = 0;
|
b->n_datas = n_datas;
|
||||||
d->stride = 0;
|
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);
|
g_debug ("allocated %d buffers %p", priv->n_buffers, priv->buffers);
|
||||||
priv->allocated = TRUE;
|
priv->allocated = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (in_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->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 ((res = spa_node_port_alloc_buffers (this->output->node->node,
|
if ((res = spa_node_port_alloc_buffers (this->output->node->node,
|
||||||
SPA_DIRECTION_OUTPUT,
|
SPA_DIRECTION_OUTPUT,
|
||||||
this->output->port,
|
this->output->port,
|
||||||
|
|
@ -548,6 +561,24 @@ do_allocation (PinosLink *this, SpaNodeState in_state, SpaNodeState out_state)
|
||||||
this->output->buffer_mem = priv->buffer_mem;
|
this->output->buffer_mem = priv->buffer_mem;
|
||||||
priv->allocated = FALSE;
|
priv->allocated = FALSE;
|
||||||
g_debug ("allocated %d buffers %p from output port", priv->n_buffers, priv->buffers);
|
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);
|
g_signal_emit (this, signals[SIGNAL_REMOVE], 0, NULL);
|
||||||
|
|
||||||
this->input = NULL;
|
if (this->input) {
|
||||||
this->output = NULL;
|
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);
|
link_unregister_object (this);
|
||||||
|
|
||||||
G_OBJECT_CLASS (pinos_link_parent_class)->dispose (object);
|
G_OBJECT_CLASS (pinos_link_parent_class)->dispose (object);
|
||||||
|
|
@ -789,8 +839,9 @@ pinos_link_finalize (GObject * object)
|
||||||
g_clear_object (&priv->iface);
|
g_clear_object (&priv->iface);
|
||||||
g_free (priv->object_path);
|
g_free (priv->object_path);
|
||||||
|
|
||||||
if (priv->allocated)
|
if (priv->allocated) {
|
||||||
pinos_memblock_free (&priv->buffer_mem);
|
pinos_memblock_free (&priv->buffer_mem);
|
||||||
|
}
|
||||||
|
|
||||||
G_OBJECT_CLASS (pinos_link_parent_class)->finalize (object);
|
G_OBJECT_CLASS (pinos_link_parent_class)->finalize (object);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,9 @@ typedef struct _SpaBuffer SpaBuffer;
|
||||||
* SpaMetaType:
|
* SpaMetaType:
|
||||||
* @SPA_META_TYPE_INVALID: invalid metadata, should be ignored
|
* @SPA_META_TYPE_INVALID: invalid metadata, should be ignored
|
||||||
* @SPA_META_TYPE_HEADER: header metadata
|
* @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 {
|
typedef enum {
|
||||||
SPA_META_TYPE_INVALID = 0,
|
SPA_META_TYPE_INVALID = 0,
|
||||||
|
|
@ -39,6 +42,23 @@ typedef enum {
|
||||||
SPA_META_TYPE_RINGBUFFER,
|
SPA_META_TYPE_RINGBUFFER,
|
||||||
} SpaMetaType;
|
} 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 <spa/defs.h>
|
#include <spa/defs.h>
|
||||||
#include <spa/port.h>
|
#include <spa/port.h>
|
||||||
|
|
||||||
|
|
@ -113,35 +133,21 @@ typedef struct {
|
||||||
size_t size;
|
size_t size;
|
||||||
} SpaMeta;
|
} 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:
|
* SpaData:
|
||||||
* @type: memory type
|
* @type: memory type
|
||||||
* @data: pointer to memory
|
* @data: pointer to memory
|
||||||
|
* @maxsize: size of @data
|
||||||
* @offset: offset in @data
|
* @offset: offset in @data
|
||||||
* @size: valid size of @data
|
* @size: valid size of @data
|
||||||
* @maxsize: size of @data
|
|
||||||
* @stride: stride of data if applicable
|
* @stride: stride of data if applicable
|
||||||
*/
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
SpaDataType type;
|
SpaDataType type;
|
||||||
void *data;
|
void *data;
|
||||||
|
size_t maxsize;
|
||||||
off_t offset;
|
off_t offset;
|
||||||
size_t size;
|
size_t size;
|
||||||
size_t maxsize;
|
|
||||||
ssize_t stride;
|
ssize_t stride;
|
||||||
} SpaData;
|
} SpaData;
|
||||||
|
|
||||||
|
|
@ -168,16 +174,7 @@ SpaBuffer * spa_buffer_deserialize (void *src, off_t offset);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
SpaResult spa_alloc_params_get_header_size (SpaAllocParam **params,
|
size_t spa_meta_type_get_size (SpaMetaType type);
|
||||||
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);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} /* extern "C" */
|
} /* extern "C" */
|
||||||
|
|
|
||||||
|
|
@ -160,6 +160,7 @@ typedef struct {
|
||||||
SpaDirection direction;
|
SpaDirection direction;
|
||||||
uint32_t port_id;
|
uint32_t port_id;
|
||||||
uint32_t mem_id;
|
uint32_t mem_id;
|
||||||
|
SpaDataType type;
|
||||||
unsigned int fd_index;
|
unsigned int fd_index;
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
off_t offset;
|
off_t offset;
|
||||||
|
|
|
||||||
|
|
@ -85,6 +85,7 @@ typedef void (*SpaNotify) (void *data);
|
||||||
#define SPA_N_ELEMENTS(arr) (sizeof (arr) / sizeof ((arr)[0]))
|
#define SPA_N_ELEMENTS(arr) (sizeof (arr) / sizeof ((arr)[0]))
|
||||||
#define SPA_MIN(a,b) ((a)<(b) ? (a) : (b))
|
#define SPA_MIN(a,b) ((a)<(b) ? (a) : (b))
|
||||||
#define SPA_MAX(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_MEMBER(b,o,t) ((t*)((uint8_t*)(b) + (o)))
|
||||||
#define SPA_PTRDIFF(p1,p2) ((uint8_t*)(p1) - (uint8_t*)(p2))
|
#define SPA_PTRDIFF(p1,p2) ((uint8_t*)(p1) - (uint8_t*)(p2))
|
||||||
|
|
|
||||||
|
|
@ -33,104 +33,15 @@ static const size_t header_sizes[] = {
|
||||||
sizeof (SpaMetaRingbuffer),
|
sizeof (SpaMetaRingbuffer),
|
||||||
};
|
};
|
||||||
|
|
||||||
SpaResult
|
size_t
|
||||||
spa_alloc_params_get_header_size (SpaAllocParam **params,
|
spa_meta_type_get_size (SpaMetaType type)
|
||||||
unsigned int n_params,
|
|
||||||
unsigned int n_datas,
|
|
||||||
size_t *size)
|
|
||||||
{
|
{
|
||||||
unsigned int i, n_metas = 0;
|
if (type <= 0 || type >= SPA_N_ELEMENTS (header_sizes))
|
||||||
|
return 0;
|
||||||
|
|
||||||
*size = sizeof (SpaBuffer);
|
return header_sizes[type];
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
size_t
|
||||||
spa_buffer_get_size (const SpaBuffer *buffer)
|
spa_buffer_get_size (const SpaBuffer *buffer)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,30 @@
|
||||||
#include "spa/props.h"
|
#include "spa/props.h"
|
||||||
#include "spa/format.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
|
SpaResult
|
||||||
spa_debug_port_info (const SpaPortInfo *info)
|
spa_debug_port_info (const SpaPortInfo *info)
|
||||||
{
|
{
|
||||||
|
|
@ -58,7 +82,7 @@ spa_debug_port_info (const SpaPortInfo *info)
|
||||||
{
|
{
|
||||||
SpaAllocParamMetaEnable *p = (SpaAllocParamMetaEnable *)param;
|
SpaAllocParamMetaEnable *p = (SpaAllocParamMetaEnable *)param;
|
||||||
fprintf (stderr, " SpaAllocParamMetaEnable:\n");
|
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;
|
break;
|
||||||
}
|
}
|
||||||
case SPA_ALLOC_PARAM_TYPE_VIDEO_PADDING:
|
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);
|
fprintf (stderr, " n_metas: %u (at %p)\n", buffer->n_metas, buffer->metas);
|
||||||
for (i = 0; i < buffer->n_metas; i++) {
|
for (i = 0; i < buffer->n_metas; i++) {
|
||||||
SpaMeta *m = &buffer->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) {
|
switch (m->type) {
|
||||||
case SPA_META_TYPE_HEADER:
|
case SPA_META_TYPE_HEADER:
|
||||||
{
|
{
|
||||||
|
|
@ -107,13 +131,34 @@ spa_debug_buffer (const SpaBuffer *buffer)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SPA_META_TYPE_POINTER:
|
case SPA_META_TYPE_POINTER:
|
||||||
|
{
|
||||||
|
SpaMetaPointer *h = m->data;
|
||||||
fprintf (stderr, " SpaMetaPointer:\n");
|
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);
|
spa_debug_dump_mem (m->data, m->size);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case SPA_META_TYPE_VIDEO_CROP:
|
case SPA_META_TYPE_VIDEO_CROP:
|
||||||
|
{
|
||||||
|
SpaMetaVideoCrop *h = m->data;
|
||||||
fprintf (stderr, " SpaMetaVideoCrop:\n");
|
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;
|
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:
|
default:
|
||||||
spa_debug_dump_mem (m->data, m->size);
|
spa_debug_dump_mem (m->data, m->size);
|
||||||
break;
|
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);
|
fprintf (stderr, " n_datas: \t%u (at %p)\n", buffer->n_datas, buffer->datas);
|
||||||
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\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, " data: %p\n", d->data);
|
||||||
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);
|
||||||
|
|
|
||||||
|
|
@ -36,20 +36,13 @@ reset_ffmpeg_dec_props (SpaFFMpegDecProps *props)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
#define INPUT_PORT_ID 0
|
#define IS_VALID_PORT(this,d,id) ((id) == 0)
|
||||||
#define OUTPUT_PORT_ID 1
|
|
||||||
#define IS_VALID_PORT(id) ((id) < 2)
|
|
||||||
#define MAX_BUFFERS 32
|
#define MAX_BUFFERS 32
|
||||||
|
|
||||||
typedef struct _FFMpegBuffer FFMpegBuffer;
|
typedef struct _FFMpegBuffer FFMpegBuffer;
|
||||||
|
|
||||||
struct _FFMpegBuffer {
|
struct _FFMpegBuffer {
|
||||||
SpaBuffer buffer;
|
SpaBuffer *outbuf;
|
||||||
SpaMeta metas[1];
|
|
||||||
SpaMetaHeader header;
|
|
||||||
SpaData datas[1];
|
|
||||||
SpaFFMpegDec *dec;
|
|
||||||
SpaBuffer *imported;
|
|
||||||
bool outstanding;
|
bool outstanding;
|
||||||
FFMpegBuffer *next;
|
FFMpegBuffer *next;
|
||||||
};
|
};
|
||||||
|
|
@ -63,7 +56,7 @@ typedef struct {
|
||||||
SpaAllocParam *params[1];
|
SpaAllocParam *params[1];
|
||||||
SpaAllocParamBuffers param_buffers;
|
SpaAllocParamBuffers param_buffers;
|
||||||
SpaPortStatus status;
|
SpaPortStatus status;
|
||||||
} SpaFFMpegState;
|
} SpaFFMpegPort;
|
||||||
|
|
||||||
struct _SpaFFMpegDec {
|
struct _SpaFFMpegDec {
|
||||||
SpaHandle handle;
|
SpaHandle handle;
|
||||||
|
|
@ -74,7 +67,8 @@ struct _SpaFFMpegDec {
|
||||||
SpaNodeEventCallback event_cb;
|
SpaNodeEventCallback event_cb;
|
||||||
void *user_data;
|
void *user_data;
|
||||||
|
|
||||||
SpaFFMpegState state[2];
|
SpaFFMpegPort in_ports[1];
|
||||||
|
SpaFFMpegPort out_ports[1];
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
|
|
@ -218,7 +212,7 @@ spa_ffmpeg_dec_node_get_port_ids (SpaNode *node,
|
||||||
if (n_input_ports > 0 && input_ids != NULL)
|
if (n_input_ports > 0 && input_ids != NULL)
|
||||||
input_ids[0] = 0;
|
input_ids[0] = 0;
|
||||||
if (n_output_ports > 0 && output_ids != NULL)
|
if (n_output_ports > 0 && output_ids != NULL)
|
||||||
output_ids[0] = 1;
|
output_ids[0] = 0;
|
||||||
|
|
||||||
return SPA_RESULT_OK;
|
return SPA_RESULT_OK;
|
||||||
}
|
}
|
||||||
|
|
@ -226,6 +220,7 @@ spa_ffmpeg_dec_node_get_port_ids (SpaNode *node,
|
||||||
|
|
||||||
static SpaResult
|
static SpaResult
|
||||||
spa_ffmpeg_dec_node_add_port (SpaNode *node,
|
spa_ffmpeg_dec_node_add_port (SpaNode *node,
|
||||||
|
SpaDirection direction,
|
||||||
uint32_t port_id)
|
uint32_t port_id)
|
||||||
{
|
{
|
||||||
return SPA_RESULT_NOT_IMPLEMENTED;
|
return SPA_RESULT_NOT_IMPLEMENTED;
|
||||||
|
|
@ -233,6 +228,7 @@ spa_ffmpeg_dec_node_add_port (SpaNode *node,
|
||||||
|
|
||||||
static SpaResult
|
static SpaResult
|
||||||
spa_ffmpeg_dec_node_remove_port (SpaNode *node,
|
spa_ffmpeg_dec_node_remove_port (SpaNode *node,
|
||||||
|
SpaDirection direction,
|
||||||
uint32_t port_id)
|
uint32_t port_id)
|
||||||
{
|
{
|
||||||
return SPA_RESULT_NOT_IMPLEMENTED;
|
return SPA_RESULT_NOT_IMPLEMENTED;
|
||||||
|
|
@ -240,13 +236,14 @@ spa_ffmpeg_dec_node_remove_port (SpaNode *node,
|
||||||
|
|
||||||
static SpaResult
|
static SpaResult
|
||||||
spa_ffmpeg_dec_node_port_enum_formats (SpaNode *node,
|
spa_ffmpeg_dec_node_port_enum_formats (SpaNode *node,
|
||||||
|
SpaDirection direction,
|
||||||
uint32_t port_id,
|
uint32_t port_id,
|
||||||
SpaFormat **format,
|
SpaFormat **format,
|
||||||
const SpaFormat *filter,
|
const SpaFormat *filter,
|
||||||
void **state)
|
void **state)
|
||||||
{
|
{
|
||||||
SpaFFMpegDec *this;
|
SpaFFMpegDec *this;
|
||||||
SpaFFMpegState *s;
|
SpaFFMpegPort *port;
|
||||||
int index;
|
int index;
|
||||||
|
|
||||||
if (node == NULL || node->handle == NULL || format == NULL || state == NULL)
|
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;
|
this = (SpaFFMpegDec *) node->handle;
|
||||||
|
|
||||||
if (!IS_VALID_PORT (port_id))
|
if (!IS_VALID_PORT (this, direction, port_id))
|
||||||
return SPA_RESULT_INVALID_PORT;
|
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);
|
index = (*state == NULL ? 0 : *(int*)state);
|
||||||
|
|
||||||
|
|
@ -265,12 +262,12 @@ spa_ffmpeg_dec_node_port_enum_formats (SpaNode *node,
|
||||||
case 0:
|
case 0:
|
||||||
spa_format_video_init (SPA_MEDIA_TYPE_VIDEO,
|
spa_format_video_init (SPA_MEDIA_TYPE_VIDEO,
|
||||||
SPA_MEDIA_SUBTYPE_RAW,
|
SPA_MEDIA_SUBTYPE_RAW,
|
||||||
&s->format[0]);
|
&port->format[0]);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return SPA_RESULT_ENUM_END;
|
return SPA_RESULT_ENUM_END;
|
||||||
}
|
}
|
||||||
*format = &s->format[0].format;
|
*format = &port->format[0].format;
|
||||||
*(int*)state = ++index;
|
*(int*)state = ++index;
|
||||||
|
|
||||||
return SPA_RESULT_OK;
|
return SPA_RESULT_OK;
|
||||||
|
|
@ -278,12 +275,13 @@ spa_ffmpeg_dec_node_port_enum_formats (SpaNode *node,
|
||||||
|
|
||||||
static SpaResult
|
static SpaResult
|
||||||
spa_ffmpeg_dec_node_port_set_format (SpaNode *node,
|
spa_ffmpeg_dec_node_port_set_format (SpaNode *node,
|
||||||
|
SpaDirection direction,
|
||||||
uint32_t port_id,
|
uint32_t port_id,
|
||||||
SpaPortFormatFlags flags,
|
SpaPortFormatFlags flags,
|
||||||
const SpaFormat *format)
|
const SpaFormat *format)
|
||||||
{
|
{
|
||||||
SpaFFMpegDec *this;
|
SpaFFMpegDec *this;
|
||||||
SpaFFMpegState *state;
|
SpaFFMpegPort *port;
|
||||||
SpaResult res;
|
SpaResult res;
|
||||||
|
|
||||||
if (node == NULL || node->handle == NULL || format == NULL)
|
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;
|
this = (SpaFFMpegDec *) node->handle;
|
||||||
|
|
||||||
if (!IS_VALID_PORT (port_id))
|
if (!IS_VALID_PORT (this, direction, port_id))
|
||||||
return SPA_RESULT_INVALID_PORT;
|
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) {
|
if (format == NULL) {
|
||||||
state->current_format = NULL;
|
port->current_format = NULL;
|
||||||
return SPA_RESULT_OK;
|
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;
|
return res;
|
||||||
|
|
||||||
if (!(flags & SPA_PORT_FORMAT_FLAG_TEST_ONLY)) {
|
if (!(flags & SPA_PORT_FORMAT_FLAG_TEST_ONLY)) {
|
||||||
memcpy (&state->format[1], &state->format[0], sizeof (SpaFormatVideo));
|
memcpy (&port->format[1], &port->format[0], sizeof (SpaFormatVideo));
|
||||||
state->current_format = &state->format[1].format;
|
port->current_format = &port->format[1].format;
|
||||||
}
|
}
|
||||||
|
|
||||||
return SPA_RESULT_OK;
|
return SPA_RESULT_OK;
|
||||||
|
|
@ -314,60 +312,66 @@ spa_ffmpeg_dec_node_port_set_format (SpaNode *node,
|
||||||
|
|
||||||
static SpaResult
|
static SpaResult
|
||||||
spa_ffmpeg_dec_node_port_get_format (SpaNode *node,
|
spa_ffmpeg_dec_node_port_get_format (SpaNode *node,
|
||||||
|
SpaDirection direction,
|
||||||
uint32_t port_id,
|
uint32_t port_id,
|
||||||
const SpaFormat **format)
|
const SpaFormat **format)
|
||||||
{
|
{
|
||||||
SpaFFMpegDec *this;
|
SpaFFMpegDec *this;
|
||||||
SpaFFMpegState *state;
|
SpaFFMpegPort *port;
|
||||||
|
|
||||||
if (node == NULL || node->handle == NULL || format == NULL)
|
if (node == NULL || node->handle == NULL || format == NULL)
|
||||||
return SPA_RESULT_INVALID_ARGUMENTS;
|
return SPA_RESULT_INVALID_ARGUMENTS;
|
||||||
|
|
||||||
this = (SpaFFMpegDec *) node->handle;
|
this = (SpaFFMpegDec *) node->handle;
|
||||||
|
|
||||||
if (!IS_VALID_PORT (port_id))
|
if (!IS_VALID_PORT (this, direction, port_id))
|
||||||
return SPA_RESULT_INVALID_PORT;
|
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;
|
return SPA_RESULT_NO_FORMAT;
|
||||||
|
|
||||||
*format = state->current_format;
|
*format = port->current_format;
|
||||||
|
|
||||||
return SPA_RESULT_OK;
|
return SPA_RESULT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static SpaResult
|
static SpaResult
|
||||||
spa_ffmpeg_dec_node_port_get_info (SpaNode *node,
|
spa_ffmpeg_dec_node_port_get_info (SpaNode *node,
|
||||||
|
SpaDirection direction,
|
||||||
uint32_t port_id,
|
uint32_t port_id,
|
||||||
const SpaPortInfo **info)
|
const SpaPortInfo **info)
|
||||||
{
|
{
|
||||||
SpaFFMpegDec *this;
|
SpaFFMpegDec *this;
|
||||||
|
SpaFFMpegPort *port;
|
||||||
|
|
||||||
if (node == NULL || node->handle == NULL || info == NULL)
|
if (node == NULL || node->handle == NULL || info == NULL)
|
||||||
return SPA_RESULT_INVALID_ARGUMENTS;
|
return SPA_RESULT_INVALID_ARGUMENTS;
|
||||||
|
|
||||||
this = (SpaFFMpegDec *) node->handle;
|
this = (SpaFFMpegDec *) node->handle;
|
||||||
|
|
||||||
if (!IS_VALID_PORT (port_id))
|
if (!IS_VALID_PORT (this, direction, port_id))
|
||||||
return SPA_RESULT_INVALID_PORT;
|
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;
|
return SPA_RESULT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static SpaResult
|
static SpaResult
|
||||||
spa_ffmpeg_dec_node_port_get_props (SpaNode *node,
|
spa_ffmpeg_dec_node_port_get_props (SpaNode *node,
|
||||||
uint32_t port_id,
|
SpaDirection direction,
|
||||||
SpaProps **props)
|
uint32_t port_id,
|
||||||
|
SpaProps **props)
|
||||||
{
|
{
|
||||||
return SPA_RESULT_NOT_IMPLEMENTED;
|
return SPA_RESULT_NOT_IMPLEMENTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
static SpaResult
|
static SpaResult
|
||||||
spa_ffmpeg_dec_node_port_set_props (SpaNode *node,
|
spa_ffmpeg_dec_node_port_set_props (SpaNode *node,
|
||||||
|
SpaDirection direction,
|
||||||
uint32_t port_id,
|
uint32_t port_id,
|
||||||
const SpaProps *props)
|
const SpaProps *props)
|
||||||
{
|
{
|
||||||
|
|
@ -376,6 +380,7 @@ spa_ffmpeg_dec_node_port_set_props (SpaNode *node,
|
||||||
|
|
||||||
static SpaResult
|
static SpaResult
|
||||||
spa_ffmpeg_dec_node_port_use_buffers (SpaNode *node,
|
spa_ffmpeg_dec_node_port_use_buffers (SpaNode *node,
|
||||||
|
SpaDirection direction,
|
||||||
uint32_t port_id,
|
uint32_t port_id,
|
||||||
SpaBuffer **buffers,
|
SpaBuffer **buffers,
|
||||||
uint32_t n_buffers)
|
uint32_t n_buffers)
|
||||||
|
|
@ -383,7 +388,7 @@ spa_ffmpeg_dec_node_port_use_buffers (SpaNode *node,
|
||||||
if (node == NULL || node->handle == NULL)
|
if (node == NULL || node->handle == NULL)
|
||||||
return SPA_RESULT_INVALID_ARGUMENTS;
|
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_INVALID_PORT;
|
||||||
|
|
||||||
return SPA_RESULT_NOT_IMPLEMENTED;
|
return SPA_RESULT_NOT_IMPLEMENTED;
|
||||||
|
|
@ -391,6 +396,7 @@ spa_ffmpeg_dec_node_port_use_buffers (SpaNode *node,
|
||||||
|
|
||||||
static SpaResult
|
static SpaResult
|
||||||
spa_ffmpeg_dec_node_port_alloc_buffers (SpaNode *node,
|
spa_ffmpeg_dec_node_port_alloc_buffers (SpaNode *node,
|
||||||
|
SpaDirection direction,
|
||||||
uint32_t port_id,
|
uint32_t port_id,
|
||||||
SpaAllocParam **params,
|
SpaAllocParam **params,
|
||||||
uint32_t n_params,
|
uint32_t n_params,
|
||||||
|
|
@ -402,20 +408,23 @@ spa_ffmpeg_dec_node_port_alloc_buffers (SpaNode *node,
|
||||||
|
|
||||||
static SpaResult
|
static SpaResult
|
||||||
spa_ffmpeg_dec_node_port_get_status (SpaNode *node,
|
spa_ffmpeg_dec_node_port_get_status (SpaNode *node,
|
||||||
|
SpaDirection direction,
|
||||||
uint32_t port_id,
|
uint32_t port_id,
|
||||||
const SpaPortStatus **status)
|
const SpaPortStatus **status)
|
||||||
{
|
{
|
||||||
SpaFFMpegDec *this;
|
SpaFFMpegDec *this;
|
||||||
|
SpaFFMpegPort *port;
|
||||||
|
|
||||||
if (node == NULL || node->handle == NULL || status == NULL)
|
if (node == NULL || node->handle == NULL || status == NULL)
|
||||||
return SPA_RESULT_INVALID_ARGUMENTS;
|
return SPA_RESULT_INVALID_ARGUMENTS;
|
||||||
|
|
||||||
this = (SpaFFMpegDec *) node->handle;
|
this = (SpaFFMpegDec *) node->handle;
|
||||||
|
|
||||||
if (!IS_VALID_PORT (port_id))
|
if (!IS_VALID_PORT (this, direction, port_id))
|
||||||
return SPA_RESULT_INVALID_PORT;
|
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;
|
return SPA_RESULT_OK;
|
||||||
}
|
}
|
||||||
|
|
@ -434,7 +443,7 @@ spa_ffmpeg_dec_node_port_pull_output (SpaNode *node,
|
||||||
SpaPortOutputInfo *info)
|
SpaPortOutputInfo *info)
|
||||||
{
|
{
|
||||||
SpaFFMpegDec *this;
|
SpaFFMpegDec *this;
|
||||||
SpaFFMpegState *state;
|
SpaFFMpegPort *port;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
bool have_error = false;
|
bool have_error = false;
|
||||||
|
|
||||||
|
|
@ -444,14 +453,14 @@ spa_ffmpeg_dec_node_port_pull_output (SpaNode *node,
|
||||||
this = (SpaFFMpegDec *) node->handle;
|
this = (SpaFFMpegDec *) node->handle;
|
||||||
|
|
||||||
for (i = 0; i < n_info; i++) {
|
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;
|
info[i].status = SPA_RESULT_INVALID_PORT;
|
||||||
have_error = true;
|
have_error = true;
|
||||||
continue;
|
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;
|
info[i].status = SPA_RESULT_NO_FORMAT;
|
||||||
have_error = true;
|
have_error = true;
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -472,7 +481,7 @@ spa_ffmpeg_dec_node_port_reuse_buffer (SpaNode *node,
|
||||||
if (node == NULL || node->handle == NULL)
|
if (node == NULL || node->handle == NULL)
|
||||||
return SPA_RESULT_INVALID_ARGUMENTS;
|
return SPA_RESULT_INVALID_ARGUMENTS;
|
||||||
|
|
||||||
if (!IS_VALID_PORT (port_id))
|
if (port_id != 0)
|
||||||
return SPA_RESULT_INVALID_PORT;
|
return SPA_RESULT_INVALID_PORT;
|
||||||
|
|
||||||
return SPA_RESULT_NOT_IMPLEMENTED;
|
return SPA_RESULT_NOT_IMPLEMENTED;
|
||||||
|
|
@ -480,6 +489,7 @@ spa_ffmpeg_dec_node_port_reuse_buffer (SpaNode *node,
|
||||||
|
|
||||||
static SpaResult
|
static SpaResult
|
||||||
spa_ffmpeg_dec_node_port_push_event (SpaNode *node,
|
spa_ffmpeg_dec_node_port_push_event (SpaNode *node,
|
||||||
|
SpaDirection direction,
|
||||||
uint32_t port_id,
|
uint32_t port_id,
|
||||||
SpaNodeEvent *event)
|
SpaNodeEvent *event)
|
||||||
{
|
{
|
||||||
|
|
@ -551,11 +561,11 @@ spa_ffmpeg_dec_init (SpaHandle *handle)
|
||||||
this->props[1].props.prop_info = prop_info;
|
this->props[1].props.prop_info = prop_info;
|
||||||
reset_ffmpeg_dec_props (&this->props[1]);
|
reset_ffmpeg_dec_props (&this->props[1]);
|
||||||
|
|
||||||
this->state[INPUT_PORT_ID].info.flags = SPA_PORT_INFO_FLAG_NONE;
|
this->in_ports[0].info.flags = SPA_PORT_INFO_FLAG_NONE;
|
||||||
this->state[INPUT_PORT_ID].status.flags = SPA_PORT_STATUS_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->out_ports[0].info.flags = SPA_PORT_INFO_FLAG_NONE;
|
||||||
this->state[OUTPUT_PORT_ID].status.flags = SPA_PORT_STATUS_FLAG_NONE;
|
this->out_ports[0].status.flags = SPA_PORT_STATUS_FLAG_NONE;
|
||||||
|
|
||||||
return SPA_RESULT_OK;
|
return SPA_RESULT_OK;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,9 +36,7 @@ reset_ffmpeg_enc_props (SpaFFMpegEncProps *props)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
#define INPUT_PORT_ID 0
|
#define IS_VALID_PORT(this,d,id) ((id) == 0)
|
||||||
#define OUTPUT_PORT_ID 1
|
|
||||||
#define IS_VALID_PORT(id) ((id) < 2)
|
|
||||||
#define MAX_BUFFERS 32
|
#define MAX_BUFFERS 32
|
||||||
|
|
||||||
typedef struct _FFMpegBuffer FFMpegBuffer;
|
typedef struct _FFMpegBuffer FFMpegBuffer;
|
||||||
|
|
@ -63,7 +61,7 @@ typedef struct {
|
||||||
SpaAllocParam *params[1];
|
SpaAllocParam *params[1];
|
||||||
SpaAllocParamBuffers param_buffers;
|
SpaAllocParamBuffers param_buffers;
|
||||||
SpaPortStatus status;
|
SpaPortStatus status;
|
||||||
} SpaFFMpegState;
|
} SpaFFMpegPort;
|
||||||
|
|
||||||
struct _SpaFFMpegEnc {
|
struct _SpaFFMpegEnc {
|
||||||
SpaHandle handle;
|
SpaHandle handle;
|
||||||
|
|
@ -74,7 +72,8 @@ struct _SpaFFMpegEnc {
|
||||||
SpaNodeEventCallback event_cb;
|
SpaNodeEventCallback event_cb;
|
||||||
void *user_data;
|
void *user_data;
|
||||||
|
|
||||||
SpaFFMpegState state[2];
|
SpaFFMpegPort in_ports[0];
|
||||||
|
SpaFFMpegPort out_ports[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
|
|
@ -218,7 +217,7 @@ spa_ffmpeg_enc_node_get_port_ids (SpaNode *node,
|
||||||
if (n_input_ports > 0 && input_ids != NULL)
|
if (n_input_ports > 0 && input_ids != NULL)
|
||||||
input_ids[0] = 0;
|
input_ids[0] = 0;
|
||||||
if (n_output_ports > 0 && output_ids != NULL)
|
if (n_output_ports > 0 && output_ids != NULL)
|
||||||
output_ids[0] = 1;
|
output_ids[0] = 0;
|
||||||
|
|
||||||
return SPA_RESULT_OK;
|
return SPA_RESULT_OK;
|
||||||
}
|
}
|
||||||
|
|
@ -226,6 +225,7 @@ spa_ffmpeg_enc_node_get_port_ids (SpaNode *node,
|
||||||
|
|
||||||
static SpaResult
|
static SpaResult
|
||||||
spa_ffmpeg_enc_node_add_port (SpaNode *node,
|
spa_ffmpeg_enc_node_add_port (SpaNode *node,
|
||||||
|
SpaDirection direction,
|
||||||
uint32_t port_id)
|
uint32_t port_id)
|
||||||
{
|
{
|
||||||
return SPA_RESULT_NOT_IMPLEMENTED;
|
return SPA_RESULT_NOT_IMPLEMENTED;
|
||||||
|
|
@ -233,6 +233,7 @@ spa_ffmpeg_enc_node_add_port (SpaNode *node,
|
||||||
|
|
||||||
static SpaResult
|
static SpaResult
|
||||||
spa_ffmpeg_enc_node_remove_port (SpaNode *node,
|
spa_ffmpeg_enc_node_remove_port (SpaNode *node,
|
||||||
|
SpaDirection direction,
|
||||||
uint32_t port_id)
|
uint32_t port_id)
|
||||||
{
|
{
|
||||||
return SPA_RESULT_NOT_IMPLEMENTED;
|
return SPA_RESULT_NOT_IMPLEMENTED;
|
||||||
|
|
@ -240,13 +241,14 @@ spa_ffmpeg_enc_node_remove_port (SpaNode *node,
|
||||||
|
|
||||||
static SpaResult
|
static SpaResult
|
||||||
spa_ffmpeg_enc_node_port_enum_formats (SpaNode *node,
|
spa_ffmpeg_enc_node_port_enum_formats (SpaNode *node,
|
||||||
|
SpaDirection direction,
|
||||||
uint32_t port_id,
|
uint32_t port_id,
|
||||||
SpaFormat **format,
|
SpaFormat **format,
|
||||||
const SpaFormat *filter,
|
const SpaFormat *filter,
|
||||||
void **state)
|
void **state)
|
||||||
{
|
{
|
||||||
SpaFFMpegEnc *this;
|
SpaFFMpegEnc *this;
|
||||||
SpaFFMpegState *s;
|
SpaFFMpegPort *port;
|
||||||
int index;
|
int index;
|
||||||
|
|
||||||
if (node == NULL || node->handle == NULL || format == NULL)
|
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;
|
this = (SpaFFMpegEnc *) node->handle;
|
||||||
|
|
||||||
if (!IS_VALID_PORT (port_id))
|
if (!IS_VALID_PORT (this, direction, port_id))
|
||||||
return SPA_RESULT_INVALID_PORT;
|
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);
|
index = (*state == NULL ? 0 : *(int*)state);
|
||||||
|
|
||||||
|
|
@ -265,12 +267,12 @@ spa_ffmpeg_enc_node_port_enum_formats (SpaNode *node,
|
||||||
case 0:
|
case 0:
|
||||||
spa_format_video_init (SPA_MEDIA_TYPE_VIDEO,
|
spa_format_video_init (SPA_MEDIA_TYPE_VIDEO,
|
||||||
SPA_MEDIA_SUBTYPE_RAW,
|
SPA_MEDIA_SUBTYPE_RAW,
|
||||||
&s->format[0]);
|
&port->format[0]);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return SPA_RESULT_ENUM_END;
|
return SPA_RESULT_ENUM_END;
|
||||||
}
|
}
|
||||||
*format = &s->format[0].format;
|
*format = &port->format[0].format;
|
||||||
*(int*)state = ++index;
|
*(int*)state = ++index;
|
||||||
|
|
||||||
return SPA_RESULT_OK;
|
return SPA_RESULT_OK;
|
||||||
|
|
@ -278,12 +280,13 @@ spa_ffmpeg_enc_node_port_enum_formats (SpaNode *node,
|
||||||
|
|
||||||
static SpaResult
|
static SpaResult
|
||||||
spa_ffmpeg_enc_node_port_set_format (SpaNode *node,
|
spa_ffmpeg_enc_node_port_set_format (SpaNode *node,
|
||||||
|
SpaDirection direction,
|
||||||
uint32_t port_id,
|
uint32_t port_id,
|
||||||
SpaPortFormatFlags flags,
|
SpaPortFormatFlags flags,
|
||||||
const SpaFormat *format)
|
const SpaFormat *format)
|
||||||
{
|
{
|
||||||
SpaFFMpegEnc *this;
|
SpaFFMpegEnc *this;
|
||||||
SpaFFMpegState *state;
|
SpaFFMpegPort *port;
|
||||||
SpaResult res;
|
SpaResult res;
|
||||||
|
|
||||||
if (node == NULL || node->handle == NULL || format == NULL)
|
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;
|
this = (SpaFFMpegEnc *) node->handle;
|
||||||
|
|
||||||
if (!IS_VALID_PORT (port_id))
|
if (!IS_VALID_PORT (this, direction, port_id))
|
||||||
return SPA_RESULT_INVALID_PORT;
|
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) {
|
if (format == NULL) {
|
||||||
state->current_format = NULL;
|
port->current_format = NULL;
|
||||||
return SPA_RESULT_OK;
|
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;
|
return res;
|
||||||
|
|
||||||
if (format->media_type != SPA_MEDIA_TYPE_VIDEO ||
|
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;
|
return SPA_RESULT_INVALID_MEDIA_TYPE;
|
||||||
|
|
||||||
if (!(flags & SPA_PORT_FORMAT_FLAG_TEST_ONLY)) {
|
if (!(flags & SPA_PORT_FORMAT_FLAG_TEST_ONLY)) {
|
||||||
memcpy (&state->format[1], &state->format[0], sizeof (SpaFormatVideo));
|
memcpy (&port->format[1], &port->format[0], sizeof (SpaFormatVideo));
|
||||||
state->current_format = &state->format[1].format;
|
port->current_format = &port->format[1].format;
|
||||||
}
|
}
|
||||||
|
|
||||||
return SPA_RESULT_OK;
|
return SPA_RESULT_OK;
|
||||||
|
|
@ -317,60 +320,66 @@ spa_ffmpeg_enc_node_port_set_format (SpaNode *node,
|
||||||
|
|
||||||
static SpaResult
|
static SpaResult
|
||||||
spa_ffmpeg_enc_node_port_get_format (SpaNode *node,
|
spa_ffmpeg_enc_node_port_get_format (SpaNode *node,
|
||||||
|
SpaDirection direction,
|
||||||
uint32_t port_id,
|
uint32_t port_id,
|
||||||
const SpaFormat **format)
|
const SpaFormat **format)
|
||||||
{
|
{
|
||||||
SpaFFMpegEnc *this;
|
SpaFFMpegEnc *this;
|
||||||
SpaFFMpegState *state;
|
SpaFFMpegPort *port;
|
||||||
|
|
||||||
if (node == NULL || node->handle == NULL || format == NULL)
|
if (node == NULL || node->handle == NULL || format == NULL)
|
||||||
return SPA_RESULT_INVALID_ARGUMENTS;
|
return SPA_RESULT_INVALID_ARGUMENTS;
|
||||||
|
|
||||||
this = (SpaFFMpegEnc *) node->handle;
|
this = (SpaFFMpegEnc *) node->handle;
|
||||||
|
|
||||||
if (!IS_VALID_PORT (port_id))
|
if (!IS_VALID_PORT (this, direction, port_id))
|
||||||
return SPA_RESULT_INVALID_PORT;
|
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;
|
return SPA_RESULT_NO_FORMAT;
|
||||||
|
|
||||||
*format = state->current_format;
|
*format = port->current_format;
|
||||||
|
|
||||||
return SPA_RESULT_OK;
|
return SPA_RESULT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static SpaResult
|
static SpaResult
|
||||||
spa_ffmpeg_enc_node_port_get_info (SpaNode *node,
|
spa_ffmpeg_enc_node_port_get_info (SpaNode *node,
|
||||||
|
SpaDirection direction,
|
||||||
uint32_t port_id,
|
uint32_t port_id,
|
||||||
const SpaPortInfo **info)
|
const SpaPortInfo **info)
|
||||||
{
|
{
|
||||||
SpaFFMpegEnc *this;
|
SpaFFMpegEnc *this;
|
||||||
|
SpaFFMpegPort *port;
|
||||||
|
|
||||||
if (node == NULL || node->handle == NULL || info == NULL)
|
if (node == NULL || node->handle == NULL || info == NULL)
|
||||||
return SPA_RESULT_INVALID_ARGUMENTS;
|
return SPA_RESULT_INVALID_ARGUMENTS;
|
||||||
|
|
||||||
this = (SpaFFMpegEnc *) node->handle;
|
this = (SpaFFMpegEnc *) node->handle;
|
||||||
|
|
||||||
if (!IS_VALID_PORT (port_id))
|
if (!IS_VALID_PORT (this, direction, port_id))
|
||||||
return SPA_RESULT_INVALID_PORT;
|
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;
|
return SPA_RESULT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static SpaResult
|
static SpaResult
|
||||||
spa_ffmpeg_enc_node_port_get_props (SpaNode *node,
|
spa_ffmpeg_enc_node_port_get_props (SpaNode *node,
|
||||||
uint32_t port_id,
|
SpaDirection direction,
|
||||||
SpaProps **props)
|
uint32_t port_id,
|
||||||
|
SpaProps **props)
|
||||||
{
|
{
|
||||||
return SPA_RESULT_NOT_IMPLEMENTED;
|
return SPA_RESULT_NOT_IMPLEMENTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
static SpaResult
|
static SpaResult
|
||||||
spa_ffmpeg_enc_node_port_set_props (SpaNode *node,
|
spa_ffmpeg_enc_node_port_set_props (SpaNode *node,
|
||||||
|
SpaDirection direction,
|
||||||
uint32_t port_id,
|
uint32_t port_id,
|
||||||
const SpaProps *props)
|
const SpaProps *props)
|
||||||
{
|
{
|
||||||
|
|
@ -379,6 +388,7 @@ spa_ffmpeg_enc_node_port_set_props (SpaNode *node,
|
||||||
|
|
||||||
static SpaResult
|
static SpaResult
|
||||||
spa_ffmpeg_enc_node_port_use_buffers (SpaNode *node,
|
spa_ffmpeg_enc_node_port_use_buffers (SpaNode *node,
|
||||||
|
SpaDirection direction,
|
||||||
uint32_t port_id,
|
uint32_t port_id,
|
||||||
SpaBuffer **buffers,
|
SpaBuffer **buffers,
|
||||||
uint32_t n_buffers)
|
uint32_t n_buffers)
|
||||||
|
|
@ -386,7 +396,7 @@ spa_ffmpeg_enc_node_port_use_buffers (SpaNode *node,
|
||||||
if (node == NULL || node->handle == NULL)
|
if (node == NULL || node->handle == NULL)
|
||||||
return SPA_RESULT_INVALID_ARGUMENTS;
|
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_INVALID_PORT;
|
||||||
|
|
||||||
return SPA_RESULT_NOT_IMPLEMENTED;
|
return SPA_RESULT_NOT_IMPLEMENTED;
|
||||||
|
|
@ -394,6 +404,7 @@ spa_ffmpeg_enc_node_port_use_buffers (SpaNode *node,
|
||||||
|
|
||||||
static SpaResult
|
static SpaResult
|
||||||
spa_ffmpeg_enc_node_port_alloc_buffers (SpaNode *node,
|
spa_ffmpeg_enc_node_port_alloc_buffers (SpaNode *node,
|
||||||
|
SpaDirection direction,
|
||||||
uint32_t port_id,
|
uint32_t port_id,
|
||||||
SpaAllocParam **params,
|
SpaAllocParam **params,
|
||||||
uint32_t n_params,
|
uint32_t n_params,
|
||||||
|
|
@ -405,20 +416,23 @@ spa_ffmpeg_enc_node_port_alloc_buffers (SpaNode *node,
|
||||||
|
|
||||||
static SpaResult
|
static SpaResult
|
||||||
spa_ffmpeg_enc_node_port_get_status (SpaNode *node,
|
spa_ffmpeg_enc_node_port_get_status (SpaNode *node,
|
||||||
|
SpaDirection direction,
|
||||||
uint32_t port_id,
|
uint32_t port_id,
|
||||||
const SpaPortStatus **status)
|
const SpaPortStatus **status)
|
||||||
{
|
{
|
||||||
SpaFFMpegEnc *this;
|
SpaFFMpegEnc *this;
|
||||||
|
SpaFFMpegPort *port;
|
||||||
|
|
||||||
if (node == NULL || node->handle == NULL || status == NULL)
|
if (node == NULL || node->handle == NULL || status == NULL)
|
||||||
return SPA_RESULT_INVALID_ARGUMENTS;
|
return SPA_RESULT_INVALID_ARGUMENTS;
|
||||||
|
|
||||||
this = (SpaFFMpegEnc *) node->handle;
|
this = (SpaFFMpegEnc *) node->handle;
|
||||||
|
|
||||||
if (!IS_VALID_PORT (port_id))
|
if (!IS_VALID_PORT (this, direction, port_id))
|
||||||
return SPA_RESULT_INVALID_PORT;
|
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;
|
return SPA_RESULT_OK;
|
||||||
}
|
}
|
||||||
|
|
@ -437,7 +451,7 @@ spa_ffmpeg_enc_node_port_pull_output (SpaNode *node,
|
||||||
SpaPortOutputInfo *info)
|
SpaPortOutputInfo *info)
|
||||||
{
|
{
|
||||||
SpaFFMpegEnc *this;
|
SpaFFMpegEnc *this;
|
||||||
SpaFFMpegState *state;
|
SpaFFMpegPort *port;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
bool have_error = false;
|
bool have_error = false;
|
||||||
|
|
||||||
|
|
@ -448,14 +462,14 @@ spa_ffmpeg_enc_node_port_pull_output (SpaNode *node,
|
||||||
|
|
||||||
|
|
||||||
for (i = 0; i < n_info; i++) {
|
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;
|
info[i].status = SPA_RESULT_INVALID_PORT;
|
||||||
have_error = true;
|
have_error = true;
|
||||||
continue;
|
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;
|
info[i].status = SPA_RESULT_NO_FORMAT;
|
||||||
have_error = true;
|
have_error = true;
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -476,7 +490,7 @@ spa_ffmpeg_enc_node_port_reuse_buffer (SpaNode *node,
|
||||||
if (node == NULL || node->handle == NULL)
|
if (node == NULL || node->handle == NULL)
|
||||||
return SPA_RESULT_INVALID_ARGUMENTS;
|
return SPA_RESULT_INVALID_ARGUMENTS;
|
||||||
|
|
||||||
if (!IS_VALID_PORT (port_id))
|
if (port_id != 0)
|
||||||
return SPA_RESULT_INVALID_PORT;
|
return SPA_RESULT_INVALID_PORT;
|
||||||
|
|
||||||
return SPA_RESULT_NOT_IMPLEMENTED;
|
return SPA_RESULT_NOT_IMPLEMENTED;
|
||||||
|
|
@ -484,6 +498,7 @@ spa_ffmpeg_enc_node_port_reuse_buffer (SpaNode *node,
|
||||||
|
|
||||||
static SpaResult
|
static SpaResult
|
||||||
spa_ffmpeg_enc_node_port_push_event (SpaNode *node,
|
spa_ffmpeg_enc_node_port_push_event (SpaNode *node,
|
||||||
|
SpaDirection direction,
|
||||||
uint32_t port_id,
|
uint32_t port_id,
|
||||||
SpaNodeEvent *event)
|
SpaNodeEvent *event)
|
||||||
{
|
{
|
||||||
|
|
@ -554,11 +569,11 @@ spa_ffmpeg_enc_init (SpaHandle *handle)
|
||||||
this->props[1].props.prop_info = prop_info;
|
this->props[1].props.prop_info = prop_info;
|
||||||
reset_ffmpeg_enc_props (&this->props[1]);
|
reset_ffmpeg_enc_props (&this->props[1]);
|
||||||
|
|
||||||
this->state[INPUT_PORT_ID].info.flags = SPA_PORT_INFO_FLAG_NONE;
|
this->in_ports[0].info.flags = SPA_PORT_INFO_FLAG_NONE;
|
||||||
this->state[INPUT_PORT_ID].status.flags = SPA_PORT_STATUS_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->out_ports[0].info.flags = SPA_PORT_INFO_FLAG_NONE;
|
||||||
this->state[OUTPUT_PORT_ID].status.flags = SPA_PORT_STATUS_FLAG_NONE;
|
this->out_ports[0].status.flags = SPA_PORT_STATUS_FLAG_NONE;
|
||||||
|
|
||||||
this->node.state = SPA_NODE_STATE_CONFIGURE;
|
this->node.state = SPA_NODE_STATE_CONFIGURE;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -747,10 +747,12 @@ spa_proxy_node_port_use_buffers (SpaNode *node,
|
||||||
memcpy (&b->buffer.datas[j], d, sizeof (SpaData));
|
memcpy (&b->buffer.datas[j], d, sizeof (SpaData));
|
||||||
|
|
||||||
switch (d->type) {
|
switch (d->type) {
|
||||||
case SPA_DATA_TYPE_FD:
|
case SPA_DATA_TYPE_DMABUF:
|
||||||
|
case SPA_DATA_TYPE_MEMFD:
|
||||||
am.direction = direction;
|
am.direction = direction;
|
||||||
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.fd_index = spa_control_builder_add_fd (&builder, SPA_PTR_TO_INT (d->data), false);
|
am.fd_index = spa_control_builder_add_fd (&builder, SPA_PTR_TO_INT (d->data), false);
|
||||||
am.flags = 0;
|
am.flags = 0;
|
||||||
am.offset = d->offset;
|
am.offset = d->offset;
|
||||||
|
|
@ -821,6 +823,7 @@ spa_proxy_node_port_use_buffers (SpaNode *node,
|
||||||
am.direction = direction;
|
am.direction = direction;
|
||||||
am.port_id = port_id;
|
am.port_id = port_id;
|
||||||
am.mem_id = port->buffer_mem_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.fd_index = spa_control_builder_add_fd (&builder, port->buffer_mem_fd, false);
|
||||||
am.flags = 0;
|
am.flags = 0;
|
||||||
am.offset = 0;
|
am.offset = 0;
|
||||||
|
|
@ -901,7 +904,7 @@ copy_meta_in (SpaProxy *this, SpaProxyPort *port, uint32_t buffer_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
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];
|
ProxyBuffer *b = &port->buffers[buffer_id];
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
@ -966,7 +969,7 @@ spa_proxy_node_port_push_input (SpaNode *node,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
copy_meta (this, port, info[i].buffer_id);
|
copy_meta_out (this, port, info[i].buffer_id);
|
||||||
|
|
||||||
pb.direction = SPA_DIRECTION_INPUT;
|
pb.direction = SPA_DIRECTION_INPUT;
|
||||||
pb.port_id = info[i].port_id;
|
pb.port_id = info[i].port_id;
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ reset_v4l2_source_props (SpaV4l2SourceProps *props)
|
||||||
props->props.unset_mask = 7;
|
props->props.unset_mask = 7;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MAX_BUFFERS 256
|
#define MAX_BUFFERS 64
|
||||||
|
|
||||||
typedef struct _V4l2Buffer V4l2Buffer;
|
typedef struct _V4l2Buffer V4l2Buffer;
|
||||||
|
|
||||||
|
|
@ -57,6 +57,8 @@ struct _V4l2Buffer {
|
||||||
bool outstanding;
|
bool outstanding;
|
||||||
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;
|
||||||
|
|
|
||||||
|
|
@ -32,27 +32,27 @@ spa_v4l2_open (SpaV4l2Source *this)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (props->props.unset_mask & 1) {
|
if (props->props.unset_mask & 1) {
|
||||||
fprintf(stderr, "Device property not set\n");
|
fprintf(stderr, "v4l2: Device property not set\n");
|
||||||
return -1;
|
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) {
|
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));
|
props->device, errno, strerror (errno));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!S_ISCHR (st.st_mode)) {
|
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;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
state->fd = open (props->device, O_RDWR | O_NONBLOCK, 0);
|
state->fd = open (props->device, O_RDWR | O_NONBLOCK, 0);
|
||||||
|
|
||||||
if (state->fd == -1) {
|
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));
|
props->device, errno, strerror (errno));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
@ -63,7 +63,7 @@ spa_v4l2_open (SpaV4l2Source *this)
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((state->cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == 0) {
|
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;
|
return -1;
|
||||||
}
|
}
|
||||||
state->opened = true;
|
state->opened = true;
|
||||||
|
|
@ -103,12 +103,15 @@ spa_v4l2_clear_buffers (SpaV4l2Source *this)
|
||||||
|
|
||||||
b = &state->buffers[i];
|
b = &state->buffers[i];
|
||||||
if (b->outstanding) {
|
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);
|
spa_v4l2_buffer_recycle (this, i);
|
||||||
}
|
}
|
||||||
if (state->export_buf) {
|
if (b->ptr) {
|
||||||
close (SPA_PTR_TO_INT (b->outbuf->datas[0].data));
|
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);
|
CLEAR(reqbuf);
|
||||||
|
|
@ -135,7 +138,7 @@ spa_v4l2_close (SpaV4l2Source *this)
|
||||||
if (state->n_buffers > 0)
|
if (state->n_buffers > 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
fprintf (stderr, "close\n");
|
fprintf (stderr, "v4l2: close\n");
|
||||||
if (close(state->fd))
|
if (close(state->fd))
|
||||||
perror ("close");
|
perror ("close");
|
||||||
|
|
||||||
|
|
@ -745,7 +748,7 @@ spa_v4l2_set_format (SpaV4l2Source *this, V4l2Format *f, bool try_only)
|
||||||
f->format,
|
f->format,
|
||||||
0);
|
0);
|
||||||
if (info == NULL) {
|
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);
|
f->fmt.media_subtype, f->format);
|
||||||
return -1;
|
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.numerator = f->framerate.denom;
|
||||||
streamparm.parm.capture.timeperframe.denominator = f->framerate.num;
|
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,
|
fmt.fmt.pix.width, fmt.fmt.pix.height,
|
||||||
streamparm.parm.capture.timeperframe.numerator,
|
streamparm.parm.capture.timeperframe.numerator,
|
||||||
streamparm.parm.capture.timeperframe.denominator);
|
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)
|
if (xioctl (state->fd, VIDIOC_S_PARM, &streamparm) < 0)
|
||||||
perror ("VIDIOC_S_PARM");
|
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,
|
fmt.fmt.pix.width, fmt.fmt.pix.height,
|
||||||
streamparm.parm.capture.timeperframe.numerator,
|
streamparm.parm.capture.timeperframe.numerator,
|
||||||
streamparm.parm.capture.timeperframe.denominator);
|
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];
|
SpaV4l2State *state = &this->state[0];
|
||||||
struct v4l2_requestbuffers reqbuf;
|
struct v4l2_requestbuffers reqbuf;
|
||||||
int i;
|
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);
|
CLEAR(reqbuf);
|
||||||
reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
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");
|
perror ("VIDIOC_REQBUFS");
|
||||||
return SPA_RESULT_ERROR;
|
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) {
|
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;
|
return SPA_RESULT_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < reqbuf.count; i++) {
|
for (i = 0; i < reqbuf.count; i++) {
|
||||||
V4l2Buffer *b;
|
V4l2Buffer *b;
|
||||||
SpaData *d;
|
|
||||||
|
|
||||||
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->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) {
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
d = buffers[i]->datas;
|
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.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||||
b->v4l2_buffer.memory = state->memtype;
|
b->v4l2_buffer.memory = state->memtype;
|
||||||
b->v4l2_buffer.index = i;
|
b->v4l2_buffer.index = i;
|
||||||
b->v4l2_buffer.m.userptr = (unsigned long) SPA_MEMBER (d[0].data, d[0].offset, void *);
|
switch (d[0].type) {
|
||||||
b->v4l2_buffer.length = d[0].maxsize;
|
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);
|
spa_v4l2_buffer_recycle (this, buffers[i]->id);
|
||||||
}
|
}
|
||||||
state->n_buffers = reqbuf.count;
|
state->n_buffers = reqbuf.count;
|
||||||
|
|
@ -980,22 +1021,22 @@ mmap_init (SpaV4l2Source *this,
|
||||||
return SPA_RESULT_ERROR;
|
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;
|
*n_buffers = reqbuf.count;
|
||||||
|
|
||||||
if (reqbuf.count < 2) {
|
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;
|
return SPA_RESULT_ERROR;
|
||||||
}
|
}
|
||||||
if (state->export_buf)
|
if (state->export_buf)
|
||||||
fprintf (stderr, "using EXPBUF\n");
|
fprintf (stderr, "v4l2: using EXPBUF\n");
|
||||||
|
|
||||||
for (i = 0; i < reqbuf.count; i++) {
|
for (i = 0; i < reqbuf.count; i++) {
|
||||||
V4l2Buffer *b;
|
V4l2Buffer *b;
|
||||||
SpaData *d;
|
SpaData *d;
|
||||||
|
|
||||||
if (buffers[i]->n_datas < 1) {
|
if (buffers[i]->n_datas < 1) {
|
||||||
fprintf (stderr, "invalid buffer data\n");
|
fprintf (stderr, "v4l2: invalid buffer data\n");
|
||||||
return SPA_RESULT_ERROR;
|
return SPA_RESULT_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1003,6 +1044,7 @@ mmap_init (SpaV4l2Source *this,
|
||||||
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->h = find_meta_data (b->outbuf, SPA_META_TYPE_HEADER);
|
||||||
|
b->ptr = NULL;
|
||||||
|
|
||||||
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;
|
||||||
|
|
@ -1031,8 +1073,7 @@ mmap_init (SpaV4l2Source *this,
|
||||||
perror("VIDIOC_EXPBUF");
|
perror("VIDIOC_EXPBUF");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
fprintf (stderr, "expbuf %d\n", expbuf.fd);
|
d[0].type = SPA_DATA_TYPE_DMABUF;
|
||||||
d[0].type = SPA_DATA_TYPE_FD;
|
|
||||||
d[0].data = SPA_INT_TO_PTR (expbuf.fd);
|
d[0].data = SPA_INT_TO_PTR (expbuf.fd);
|
||||||
} else {
|
} else {
|
||||||
d[0].type = SPA_DATA_TYPE_MEMPTR;
|
d[0].type = SPA_DATA_TYPE_MEMPTR;
|
||||||
|
|
@ -1046,6 +1087,8 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue