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:
Wim Taymans 2016-10-04 15:56:33 +02:00
parent d828073bb8
commit b8f693ceea
14 changed files with 425 additions and 329 deletions

View file

@ -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:

View file

@ -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;
}

View file

@ -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);

View file

@ -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);
}

View file

@ -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" */

View file

@ -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;

View file

@ -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))

View file

@ -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)
{

View file

@ -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);

View file

@ -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;
}

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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);
}