mirror of
https://gitlab.freedesktop.org/pipewire/pipewire
synced 2024-09-20 08:21:45 +00: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
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 <spa/defs.h>
|
||||
#include <spa/port.h>
|
||||
|
||||
|
@ -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" */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue