improve buffer import

Add generic pointer metadata type that is copied on import
Pass array of pointers to SpaBuffers in use_buffers.
Make sure we use the same data and metadata as the imported buffer.
This commit is contained in:
Wim Taymans 2016-07-11 17:45:54 +02:00
parent c5a31acf8c
commit 4c7cee6b28
10 changed files with 120 additions and 110 deletions

View file

@ -36,6 +36,7 @@ typedef struct _SpaBuffer SpaBuffer;
typedef enum { typedef enum {
SPA_META_TYPE_INVALID = 0, SPA_META_TYPE_INVALID = 0,
SPA_META_TYPE_HEADER, SPA_META_TYPE_HEADER,
SPA_META_TYPE_POINTER,
} SpaMetaType; } SpaMetaType;
/** /**
@ -66,6 +67,11 @@ typedef struct {
int64_t dts_offset; int64_t dts_offset;
} SpaMetaHeader; } SpaMetaHeader;
typedef struct {
const char *type;
void *ptr;
} SpaMetaPointer;
/** /**
* SpaMeta: * SpaMeta:
* @type: metadata type * @type: metadata type
@ -118,7 +124,6 @@ typedef struct {
* @datas: array of @n_datas data pointers * @datas: array of @n_datas data pointers
*/ */
struct _SpaBuffer { struct _SpaBuffer {
uint32_t id;
volatile int refcount; volatile int refcount;
SpaNotify notify; SpaNotify notify;
size_t size; size_t size;

View file

@ -316,7 +316,7 @@ struct _SpaNode {
SpaResult (*port_use_buffers) (SpaHandle *handle, SpaResult (*port_use_buffers) (SpaHandle *handle,
uint32_t port_id, uint32_t port_id,
SpaBuffer *buffers, SpaBuffer **buffers,
uint32_t n_buffers); uint32_t n_buffers);
SpaResult (*port_alloc_buffers) (SpaHandle *handle, SpaResult (*port_alloc_buffers) (SpaHandle *handle,
uint32_t port_id, uint32_t port_id,

View file

@ -465,7 +465,7 @@ spa_alsa_sink_node_port_get_status (SpaHandle *handle,
static SpaResult static SpaResult
spa_alsa_sink_node_port_use_buffers (SpaHandle *handle, spa_alsa_sink_node_port_use_buffers (SpaHandle *handle,
uint32_t port_id, uint32_t port_id,
SpaBuffer *buffers, SpaBuffer **buffers,
uint32_t n_buffers) uint32_t n_buffers)
{ {
return SPA_RESULT_NOT_IMPLEMENTED; return SPA_RESULT_NOT_IMPLEMENTED;

View file

@ -431,7 +431,7 @@ spa_audiomixer_node_port_get_status (SpaHandle *handle,
static SpaResult static SpaResult
spa_audiomixer_node_port_use_buffers (SpaHandle *handle, spa_audiomixer_node_port_use_buffers (SpaHandle *handle,
uint32_t port_id, uint32_t port_id,
SpaBuffer *buffers, SpaBuffer **buffers,
uint32_t n_buffers) uint32_t n_buffers)
{ {
return SPA_RESULT_NOT_IMPLEMENTED; return SPA_RESULT_NOT_IMPLEMENTED;

View file

@ -408,7 +408,7 @@ spa_audiotestsrc_node_port_get_status (SpaHandle *handle,
static SpaResult static SpaResult
spa_audiotestsrc_node_port_use_buffers (SpaHandle *handle, spa_audiotestsrc_node_port_use_buffers (SpaHandle *handle,
uint32_t port_id, uint32_t port_id,
SpaBuffer *buffers, SpaBuffer **buffers,
uint32_t n_buffers) uint32_t n_buffers)
{ {
return SPA_RESULT_NOT_IMPLEMENTED; return SPA_RESULT_NOT_IMPLEMENTED;

View file

@ -54,8 +54,8 @@ struct _V4l2Buffer {
SpaMetaHeader header; SpaMetaHeader header;
SpaData datas[1]; SpaData datas[1];
SpaV4l2Source *source; SpaV4l2Source *source;
bool outstanding;
SpaBuffer *imported; SpaBuffer *imported;
bool outstanding;
struct v4l2_buffer v4l2_buffer; struct v4l2_buffer v4l2_buffer;
V4l2Buffer *next; V4l2Buffer *next;
}; };
@ -448,7 +448,7 @@ spa_v4l2_source_node_port_get_status (SpaHandle *handle,
static SpaResult static SpaResult
spa_v4l2_source_node_port_use_buffers (SpaHandle *handle, spa_v4l2_source_node_port_use_buffers (SpaHandle *handle,
uint32_t port_id, uint32_t port_id,
SpaBuffer *buffers, SpaBuffer **buffers,
uint32_t n_buffers) uint32_t n_buffers)
{ {
SpaV4l2Source *this = (SpaV4l2Source *) handle; SpaV4l2Source *this = (SpaV4l2Source *) handle;

View file

@ -409,7 +409,7 @@ v4l2_buffer_free (void *data)
} }
static int static int
spa_v4l2_import_buffers (SpaV4l2Source *this, SpaBuffer *buffers, uint32_t n_buffers) spa_v4l2_import_buffers (SpaV4l2Source *this, SpaBuffer **buffers, uint32_t n_buffers)
{ {
SpaV4l2State *state = &this->state[0]; SpaV4l2State *state = &this->state[0];
struct v4l2_requestbuffers reqbuf; struct v4l2_requestbuffers reqbuf;
@ -437,34 +437,24 @@ spa_v4l2_import_buffers (SpaV4l2Source *this, SpaBuffer *buffers, uint32_t n_buf
V4l2Buffer *b; V4l2Buffer *b;
b = &state->buffers[i]; b = &state->buffers[i];
b->source = this; b->source = this;
b->buffer.refcount = 0; b->buffer.refcount = 0;
b->buffer.notify = v4l2_buffer_free; b->buffer.notify = v4l2_buffer_free;
b->buffer.size = buffers[i].size; b->buffer.size = buffers[i]->size;
b->buffer.n_metas = 1; b->buffer.n_metas = buffers[i]->n_metas;
b->buffer.metas = b->metas; b->buffer.metas = buffers[i]->metas;
b->buffer.n_datas = 1; b->buffer.n_datas = buffers[i]->n_datas;
b->buffer.datas = b->datas; b->buffer.datas = buffers[i]->datas;
b->imported = buffers[i];
b->header.flags = 0;
b->header.seq = 0;
b->header.pts = 0;
b->header.dts_offset = 0;
b->metas[0].type = SPA_META_TYPE_HEADER;
b->metas[0].data = &b->header;
b->metas[0].size = sizeof (b->header);
b->datas[0] = buffers[i].datas[0];
b->imported = &buffers[i];
b->outstanding = true; b->outstanding = true;
CLEAR (b->v4l2_buffer); CLEAR (b->v4l2_buffer);
b->v4l2_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; b->v4l2_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
b->v4l2_buffer.memory = state->memtype; b->v4l2_buffer.memory = state->memtype;
b->v4l2_buffer.index = i; b->v4l2_buffer.index = i;
b->v4l2_buffer.m.userptr = (unsigned long) b->datas[0].data; b->v4l2_buffer.m.userptr = (unsigned long) b->buffer.datas[0].data;
b->v4l2_buffer.length = b->datas[0].size; b->v4l2_buffer.length = b->buffer.datas[0].size;
v4l2_buffer_free (b); v4l2_buffer_free (b);
} }
@ -543,7 +533,6 @@ mmap_init (SpaV4l2Source *this)
b->datas[0].offset = 0; b->datas[0].offset = 0;
b->datas[0].size = buf.length; b->datas[0].size = buf.length;
b->datas[0].stride = state->fmt.fmt.pix.bytesperline; b->datas[0].stride = state->fmt.fmt.pix.bytesperline;
b->imported = NULL;
b->outstanding = true; b->outstanding = true;
if (b->datas[0].data == MAP_FAILED) { if (b->datas[0].data == MAP_FAILED) {

View file

@ -389,7 +389,7 @@ spa_volume_node_port_get_status (SpaHandle *handle,
static SpaResult static SpaResult
spa_volume_node_port_use_buffers (SpaHandle *handle, spa_volume_node_port_use_buffers (SpaHandle *handle,
uint32_t port_id, uint32_t port_id,
SpaBuffer *buffers, SpaBuffer **buffers,
uint32_t n_buffers) uint32_t n_buffers)
{ {
return SPA_RESULT_NOT_IMPLEMENTED; return SPA_RESULT_NOT_IMPLEMENTED;

View file

@ -433,7 +433,7 @@ spa_xv_sink_node_port_get_status (SpaHandle *handle,
static SpaResult static SpaResult
spa_xv_sink_node_port_use_buffers (SpaHandle *handle, spa_xv_sink_node_port_use_buffers (SpaHandle *handle,
uint32_t port_id, uint32_t port_id,
SpaBuffer *buffers, SpaBuffer **buffers,
uint32_t n_buffers) uint32_t n_buffers)
{ {
return SPA_RESULT_NOT_IMPLEMENTED; return SPA_RESULT_NOT_IMPLEMENTED;

View file

@ -31,14 +31,17 @@
#include <spa/node.h> #include <spa/node.h>
#include <spa/video/format.h> #include <spa/video/format.h>
#define USE_BUFFER
#define MAX_BUFFERS 8 #define MAX_BUFFERS 8
typedef struct { typedef struct {
SpaMeta meta[1]; SpaBuffer buffer;
SpaMeta metas[2];
SpaMetaHeader header; SpaMetaHeader header;
SpaData data[1]; SpaMetaPointer ptr;
SDL_Texture *texture; SpaData datas[1];
} SDLBufferData; } SDLBuffer;
typedef struct { typedef struct {
SpaHandle *source; SpaHandle *source;
@ -51,8 +54,8 @@ typedef struct {
SpaPollFd fds[16]; SpaPollFd fds[16];
unsigned int n_fds; unsigned int n_fds;
SpaPollItem poll; SpaPollItem poll;
SpaBuffer buffers[MAX_BUFFERS]; SpaBuffer *bp[MAX_BUFFERS];
SDLBufferData bdata[MAX_BUFFERS]; SDLBuffer buffers[MAX_BUFFERS];
} AppData; } AppData;
static SpaResult static SpaResult
@ -109,61 +112,55 @@ on_source_event (SpaHandle *handle, SpaEvent *event, void *user_data)
{ {
SpaOutputInfo info[1] = { 0, }; SpaOutputInfo info[1] = { 0, };
SpaResult res; SpaResult res;
#if 0
void *mem;
int stride;
SpaBuffer *b; SpaBuffer *b;
SDLBufferData *bd;
#else
void *sdata, *ddata; void *sdata, *ddata;
int sstride, dstride; int sstride, dstride;
int i; int i;
uint8_t *src, *dst; uint8_t *src, *dst;
#endif
if ((res = data->source_node->port_pull_output (data->source, 1, info)) < 0) if ((res = data->source_node->port_pull_output (data->source, 1, info)) < 0)
printf ("got pull error %d\n", res); printf ("got pull error %d\n", res);
#if 0
b = info[0].buffer; b = info[0].buffer;
bd = &data->bdata[b->id];
SDL_UnlockTexture(bd->texture); if (b->metas[1].type == SPA_META_TYPE_POINTER &&
#else strcmp (((SpaMetaPointer*)b->metas[1].data)->type, "SDL_Texture") == 0) {
if (SDL_LockTexture (data->texture, NULL, &ddata, &dstride) < 0) { SDL_Texture *texture;
fprintf (stderr, "Couldn't lock texture: %s\n", SDL_GetError()); texture = ((SpaMetaPointer*)b->metas[1].data)->ptr;
return;
SDL_UnlockTexture(texture);
SDL_RenderClear (data->renderer);
SDL_RenderCopy (data->renderer, texture, NULL, NULL);
SDL_RenderPresent (data->renderer);
if (SDL_LockTexture (texture, NULL, &sdata, &sstride) < 0) {
fprintf (stderr, "Couldn't lock texture: %s\n", SDL_GetError());
return;
}
b->datas[0].data = sdata;
b->datas[0].size = sstride * 240;
b->datas[0].stride = sstride;
} else {
if (SDL_LockTexture (data->texture, NULL, &ddata, &dstride) < 0) {
fprintf (stderr, "Couldn't lock texture: %s\n", SDL_GetError());
return;
}
sdata = b->datas[0].data;
sstride = b->datas[0].stride;
for (i = 0; i < 240; i++) {
src = ((uint8_t*)sdata + i * sstride);
dst = ((uint8_t*)ddata + i * dstride);
memcpy (dst, src, MIN (sstride, dstride));
}
SDL_UnlockTexture(data->texture);
SDL_RenderClear (data->renderer);
SDL_RenderCopy (data->renderer, data->texture, NULL, NULL);
SDL_RenderPresent (data->renderer);
} }
sdata = info[0].buffer->datas[0].data; spa_buffer_unref (b);
sstride = info[0].buffer->datas[0].stride;
for (i = 0; i < 240; i++) {
src = ((uint8_t*)sdata + i * sstride);
dst = ((uint8_t*)ddata + i * dstride);
memcpy (dst, src, MIN (sstride, dstride));
}
SDL_RenderClear (data->renderer);
SDL_RenderCopy (data->renderer, data->texture, NULL, NULL);
SDL_RenderPresent (data->renderer);
#endif
#if 0
SDL_RenderClear (data->renderer);
SDL_RenderCopy (data->renderer, bd->texture, NULL, NULL);
SDL_RenderPresent (data->renderer);
if (SDL_LockTexture (bd->texture, NULL, &mem, &stride) < 0) {
fprintf (stderr, "Couldn't lock texture: %s\n", SDL_GetError());
return;
}
bd->data[0].data = mem;
bd->data[0].size = stride * 240;
bd->data[0].stride = stride;
#else
SDL_UnlockTexture(data->texture);
#endif
spa_buffer_unref (info[0].buffer);
break; break;
} }
case SPA_EVENT_TYPE_ADD_POLL: case SPA_EVENT_TYPE_ADD_POLL:
@ -208,56 +205,62 @@ make_nodes (AppData *data, const char *device)
return res; return res;
} }
#if 0 #ifdef USE_BUFFER
static void static void
alloc_buffers (AppData *data) alloc_buffers (AppData *data)
{ {
int i; int i;
for (i = 0; i < MAX_BUFFERS; i++) { for (i = 0; i < MAX_BUFFERS; i++) {
SpaBuffer *b = &data->buffers[i]; SDLBuffer *b = &data->buffers[i];
SDLBufferData *bd = &data->bdata[i]; SDL_Texture *texture;
void *mem; void *mem;
int stride; int stride;
bd->texture = SDL_CreateTexture (data->renderer, data->bp[i] = &b->buffer;
SDL_PIXELFORMAT_YUY2,
SDL_TEXTUREACCESS_STREAMING, texture = SDL_CreateTexture (data->renderer,
320, 240); SDL_PIXELFORMAT_YUY2,
if (!bd->texture) { SDL_TEXTUREACCESS_STREAMING,
320, 240);
if (!texture) {
printf ("can't create texture: %s\n", SDL_GetError ()); printf ("can't create texture: %s\n", SDL_GetError ());
return; return;
} }
if (SDL_LockTexture (bd->texture, NULL, &mem, &stride) < 0) { if (SDL_LockTexture (texture, NULL, &mem, &stride) < 0) {
fprintf (stderr, "Couldn't lock texture: %s\n", SDL_GetError()); fprintf (stderr, "Couldn't lock texture: %s\n", SDL_GetError());
return; return;
} }
b->id = i; b->buffer.refcount = 1;
b->refcount = 1; b->buffer.notify = NULL;
b->notify = NULL; b->buffer.size = stride * 240;
b->size = stride * 240; b->buffer.n_metas = 2;
b->n_metas = 1; b->buffer.metas = b->metas;
b->metas = bd->meta; b->buffer.n_datas = 1;
b->n_datas = 1; b->buffer.datas = b->datas;
b->datas = bd->data;
bd->header.flags = 0; b->header.flags = 0;
bd->header.seq = 0; b->header.seq = 0;
bd->header.pts = 0; b->header.pts = 0;
bd->header.dts_offset = 0; b->header.dts_offset = 0;
b->metas[0].type = SPA_META_TYPE_HEADER;
b->metas[0].data = &b->header;
b->metas[0].size = sizeof (b->header);
bd->meta[0].type = SPA_META_TYPE_HEADER; b->ptr.type = "SDL_Texture";
bd->meta[0].data = &bd->header; b->ptr.ptr = texture;
bd->meta[0].size = sizeof (bd->header); b->metas[1].type = SPA_META_TYPE_POINTER;
b->metas[1].data = &b->ptr;
b->metas[1].size = sizeof (b->ptr);
bd->data[0].type = SPA_DATA_TYPE_MEMPTR; b->datas[0].type = SPA_DATA_TYPE_MEMPTR;
bd->data[0].data = mem; b->datas[0].data = mem;
bd->data[0].offset = 0; b->datas[0].offset = 0;
bd->data[0].size = stride * 240; b->datas[0].size = stride * 240;
bd->data[0].stride = stride; b->datas[0].stride = stride;
} }
data->source_node->port_use_buffers (data->source, 0, data->buffers, MAX_BUFFERS); data->source_node->port_use_buffers (data->source, 0, data->bp, MAX_BUFFERS);
} }
#endif #endif
@ -270,6 +273,7 @@ negotiate_formats (AppData *data)
uint32_t val; uint32_t val;
SpaFraction frac; SpaFraction frac;
SpaPropValue value; SpaPropValue value;
const SpaPortInfo *info;
if ((res = data->source_node->port_enum_formats (data->source, 0, 0, &format)) < 0) if ((res = data->source_node->port_enum_formats (data->source, 0, 0, &format)) < 0)
return res; return res;
@ -302,7 +306,19 @@ negotiate_formats (AppData *data)
if ((res = data->source_node->port_set_format (data->source, 0, false, format)) < 0) if ((res = data->source_node->port_set_format (data->source, 0, false, format)) < 0)
return res; return res;
#if 0 if ((res = data->source_node->port_get_info (data->source, 0, &info)) < 0)
return res;
printf ("flags: %d\n", info->flags);
printf ("minsize: %zd\n", info->minsize);
printf ("stride: %zd\n", info->stride);
printf ("min_buffers: %d\n", info->min_buffers);
printf ("max_buffers: %d\n", info->max_buffers);
printf ("align: %d\n", info->align);
printf ("maxbuffering: %d\n", info->maxbuffering);
printf ("latency: %lu\n", info->latency);
#ifdef USE_BUFFER
alloc_buffers (data); alloc_buffers (data);
#else #else
data->texture = SDL_CreateTexture (data->renderer, data->texture = SDL_CreateTexture (data->renderer,