From 4c7cee6b288ff22cac546ea19b4c9cd42a3d787a Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Mon, 11 Jul 2016 17:45:54 +0200 Subject: [PATCH] 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. --- spa/include/spa/buffer.h | 7 +- spa/include/spa/node.h | 2 +- spa/plugins/alsa/alsa-sink.c | 2 +- spa/plugins/audiomixer/audiomixer.c | 2 +- spa/plugins/audiotestsrc/audiotestsrc.c | 2 +- spa/plugins/v4l2/v4l2-source.c | 4 +- spa/plugins/v4l2/v4l2-utils.c | 31 ++--- spa/plugins/volume/volume.c | 2 +- spa/plugins/xv/xv-sink.c | 2 +- spa/tests/test-v4l2.c | 176 +++++++++++++----------- 10 files changed, 120 insertions(+), 110 deletions(-) diff --git a/spa/include/spa/buffer.h b/spa/include/spa/buffer.h index 7a94753e2..d7c4b04f4 100644 --- a/spa/include/spa/buffer.h +++ b/spa/include/spa/buffer.h @@ -36,6 +36,7 @@ typedef struct _SpaBuffer SpaBuffer; typedef enum { SPA_META_TYPE_INVALID = 0, SPA_META_TYPE_HEADER, + SPA_META_TYPE_POINTER, } SpaMetaType; /** @@ -66,6 +67,11 @@ typedef struct { int64_t dts_offset; } SpaMetaHeader; +typedef struct { + const char *type; + void *ptr; +} SpaMetaPointer; + /** * SpaMeta: * @type: metadata type @@ -118,7 +124,6 @@ typedef struct { * @datas: array of @n_datas data pointers */ struct _SpaBuffer { - uint32_t id; volatile int refcount; SpaNotify notify; size_t size; diff --git a/spa/include/spa/node.h b/spa/include/spa/node.h index 190095915..74cf3f9f6 100644 --- a/spa/include/spa/node.h +++ b/spa/include/spa/node.h @@ -316,7 +316,7 @@ struct _SpaNode { SpaResult (*port_use_buffers) (SpaHandle *handle, uint32_t port_id, - SpaBuffer *buffers, + SpaBuffer **buffers, uint32_t n_buffers); SpaResult (*port_alloc_buffers) (SpaHandle *handle, uint32_t port_id, diff --git a/spa/plugins/alsa/alsa-sink.c b/spa/plugins/alsa/alsa-sink.c index 0123a3b4e..fdff26754 100644 --- a/spa/plugins/alsa/alsa-sink.c +++ b/spa/plugins/alsa/alsa-sink.c @@ -465,7 +465,7 @@ spa_alsa_sink_node_port_get_status (SpaHandle *handle, static SpaResult spa_alsa_sink_node_port_use_buffers (SpaHandle *handle, uint32_t port_id, - SpaBuffer *buffers, + SpaBuffer **buffers, uint32_t n_buffers) { return SPA_RESULT_NOT_IMPLEMENTED; diff --git a/spa/plugins/audiomixer/audiomixer.c b/spa/plugins/audiomixer/audiomixer.c index e6ac72241..4c78e71e3 100644 --- a/spa/plugins/audiomixer/audiomixer.c +++ b/spa/plugins/audiomixer/audiomixer.c @@ -431,7 +431,7 @@ spa_audiomixer_node_port_get_status (SpaHandle *handle, static SpaResult spa_audiomixer_node_port_use_buffers (SpaHandle *handle, uint32_t port_id, - SpaBuffer *buffers, + SpaBuffer **buffers, uint32_t n_buffers) { return SPA_RESULT_NOT_IMPLEMENTED; diff --git a/spa/plugins/audiotestsrc/audiotestsrc.c b/spa/plugins/audiotestsrc/audiotestsrc.c index 4800723cf..e0cd4d825 100644 --- a/spa/plugins/audiotestsrc/audiotestsrc.c +++ b/spa/plugins/audiotestsrc/audiotestsrc.c @@ -408,7 +408,7 @@ spa_audiotestsrc_node_port_get_status (SpaHandle *handle, static SpaResult spa_audiotestsrc_node_port_use_buffers (SpaHandle *handle, uint32_t port_id, - SpaBuffer *buffers, + SpaBuffer **buffers, uint32_t n_buffers) { return SPA_RESULT_NOT_IMPLEMENTED; diff --git a/spa/plugins/v4l2/v4l2-source.c b/spa/plugins/v4l2/v4l2-source.c index 0c59e3744..f47afb843 100644 --- a/spa/plugins/v4l2/v4l2-source.c +++ b/spa/plugins/v4l2/v4l2-source.c @@ -54,8 +54,8 @@ struct _V4l2Buffer { SpaMetaHeader header; SpaData datas[1]; SpaV4l2Source *source; - bool outstanding; SpaBuffer *imported; + bool outstanding; struct v4l2_buffer v4l2_buffer; V4l2Buffer *next; }; @@ -448,7 +448,7 @@ spa_v4l2_source_node_port_get_status (SpaHandle *handle, static SpaResult spa_v4l2_source_node_port_use_buffers (SpaHandle *handle, uint32_t port_id, - SpaBuffer *buffers, + SpaBuffer **buffers, uint32_t n_buffers) { SpaV4l2Source *this = (SpaV4l2Source *) handle; diff --git a/spa/plugins/v4l2/v4l2-utils.c b/spa/plugins/v4l2/v4l2-utils.c index c3be56506..a5e53c56d 100644 --- a/spa/plugins/v4l2/v4l2-utils.c +++ b/spa/plugins/v4l2/v4l2-utils.c @@ -409,7 +409,7 @@ v4l2_buffer_free (void *data) } 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]; struct v4l2_requestbuffers reqbuf; @@ -437,34 +437,24 @@ spa_v4l2_import_buffers (SpaV4l2Source *this, SpaBuffer *buffers, uint32_t n_buf V4l2Buffer *b; b = &state->buffers[i]; + b->source = this; b->buffer.refcount = 0; b->buffer.notify = v4l2_buffer_free; - b->buffer.size = buffers[i].size; - b->buffer.n_metas = 1; - b->buffer.metas = b->metas; - b->buffer.n_datas = 1; - b->buffer.datas = b->datas; - - 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->buffer.size = buffers[i]->size; + b->buffer.n_metas = buffers[i]->n_metas; + b->buffer.metas = buffers[i]->metas; + b->buffer.n_datas = buffers[i]->n_datas; + b->buffer.datas = buffers[i]->datas; + b->imported = buffers[i]; b->outstanding = true; CLEAR (b->v4l2_buffer); 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) b->datas[0].data; - b->v4l2_buffer.length = b->datas[0].size; + b->v4l2_buffer.m.userptr = (unsigned long) b->buffer.datas[0].data; + b->v4l2_buffer.length = b->buffer.datas[0].size; v4l2_buffer_free (b); } @@ -543,7 +533,6 @@ mmap_init (SpaV4l2Source *this) b->datas[0].offset = 0; b->datas[0].size = buf.length; b->datas[0].stride = state->fmt.fmt.pix.bytesperline; - b->imported = NULL; b->outstanding = true; if (b->datas[0].data == MAP_FAILED) { diff --git a/spa/plugins/volume/volume.c b/spa/plugins/volume/volume.c index 543241a6c..a061aac09 100644 --- a/spa/plugins/volume/volume.c +++ b/spa/plugins/volume/volume.c @@ -389,7 +389,7 @@ spa_volume_node_port_get_status (SpaHandle *handle, static SpaResult spa_volume_node_port_use_buffers (SpaHandle *handle, uint32_t port_id, - SpaBuffer *buffers, + SpaBuffer **buffers, uint32_t n_buffers) { return SPA_RESULT_NOT_IMPLEMENTED; diff --git a/spa/plugins/xv/xv-sink.c b/spa/plugins/xv/xv-sink.c index 457c066b9..c19794d30 100644 --- a/spa/plugins/xv/xv-sink.c +++ b/spa/plugins/xv/xv-sink.c @@ -433,7 +433,7 @@ spa_xv_sink_node_port_get_status (SpaHandle *handle, static SpaResult spa_xv_sink_node_port_use_buffers (SpaHandle *handle, uint32_t port_id, - SpaBuffer *buffers, + SpaBuffer **buffers, uint32_t n_buffers) { return SPA_RESULT_NOT_IMPLEMENTED; diff --git a/spa/tests/test-v4l2.c b/spa/tests/test-v4l2.c index a4501d1e2..763b63282 100644 --- a/spa/tests/test-v4l2.c +++ b/spa/tests/test-v4l2.c @@ -31,14 +31,17 @@ #include #include +#define USE_BUFFER + #define MAX_BUFFERS 8 typedef struct { - SpaMeta meta[1]; + SpaBuffer buffer; + SpaMeta metas[2]; SpaMetaHeader header; - SpaData data[1]; - SDL_Texture *texture; -} SDLBufferData; + SpaMetaPointer ptr; + SpaData datas[1]; +} SDLBuffer; typedef struct { SpaHandle *source; @@ -51,8 +54,8 @@ typedef struct { SpaPollFd fds[16]; unsigned int n_fds; SpaPollItem poll; - SpaBuffer buffers[MAX_BUFFERS]; - SDLBufferData bdata[MAX_BUFFERS]; + SpaBuffer *bp[MAX_BUFFERS]; + SDLBuffer buffers[MAX_BUFFERS]; } AppData; static SpaResult @@ -109,61 +112,55 @@ on_source_event (SpaHandle *handle, SpaEvent *event, void *user_data) { SpaOutputInfo info[1] = { 0, }; SpaResult res; -#if 0 - void *mem; - int stride; SpaBuffer *b; - SDLBufferData *bd; -#else void *sdata, *ddata; int sstride, dstride; int i; uint8_t *src, *dst; -#endif if ((res = data->source_node->port_pull_output (data->source, 1, info)) < 0) printf ("got pull error %d\n", res); -#if 0 b = info[0].buffer; - bd = &data->bdata[b->id]; - SDL_UnlockTexture(bd->texture); -#else - if (SDL_LockTexture (data->texture, NULL, &ddata, &dstride) < 0) { - fprintf (stderr, "Couldn't lock texture: %s\n", SDL_GetError()); - return; + if (b->metas[1].type == SPA_META_TYPE_POINTER && + strcmp (((SpaMetaPointer*)b->metas[1].data)->type, "SDL_Texture") == 0) { + SDL_Texture *texture; + texture = ((SpaMetaPointer*)b->metas[1].data)->ptr; + + 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; - 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); + spa_buffer_unref (b); break; } case SPA_EVENT_TYPE_ADD_POLL: @@ -208,56 +205,62 @@ make_nodes (AppData *data, const char *device) return res; } -#if 0 +#ifdef USE_BUFFER static void alloc_buffers (AppData *data) { int i; for (i = 0; i < MAX_BUFFERS; i++) { - SpaBuffer *b = &data->buffers[i]; - SDLBufferData *bd = &data->bdata[i]; + SDLBuffer *b = &data->buffers[i]; + SDL_Texture *texture; void *mem; int stride; - bd->texture = SDL_CreateTexture (data->renderer, - SDL_PIXELFORMAT_YUY2, - SDL_TEXTUREACCESS_STREAMING, - 320, 240); - if (!bd->texture) { + data->bp[i] = &b->buffer; + + texture = SDL_CreateTexture (data->renderer, + SDL_PIXELFORMAT_YUY2, + SDL_TEXTUREACCESS_STREAMING, + 320, 240); + if (!texture) { printf ("can't create texture: %s\n", SDL_GetError ()); 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()); return; } - b->id = i; - b->refcount = 1; - b->notify = NULL; - b->size = stride * 240; - b->n_metas = 1; - b->metas = bd->meta; - b->n_datas = 1; - b->datas = bd->data; + b->buffer.refcount = 1; + b->buffer.notify = NULL; + b->buffer.size = stride * 240; + b->buffer.n_metas = 2; + b->buffer.metas = b->metas; + b->buffer.n_datas = 1; + b->buffer.datas = b->datas; - bd->header.flags = 0; - bd->header.seq = 0; - bd->header.pts = 0; - bd->header.dts_offset = 0; + 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); - bd->meta[0].type = SPA_META_TYPE_HEADER; - bd->meta[0].data = &bd->header; - bd->meta[0].size = sizeof (bd->header); + b->ptr.type = "SDL_Texture"; + b->ptr.ptr = texture; + 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; - bd->data[0].data = mem; - bd->data[0].offset = 0; - bd->data[0].size = stride * 240; - bd->data[0].stride = stride; + b->datas[0].type = SPA_DATA_TYPE_MEMPTR; + b->datas[0].data = mem; + b->datas[0].offset = 0; + b->datas[0].size = stride * 240; + 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 @@ -270,6 +273,7 @@ negotiate_formats (AppData *data) uint32_t val; SpaFraction frac; SpaPropValue value; + const SpaPortInfo *info; if ((res = data->source_node->port_enum_formats (data->source, 0, 0, &format)) < 0) return res; @@ -302,7 +306,19 @@ negotiate_formats (AppData *data) if ((res = data->source_node->port_set_format (data->source, 0, false, format)) < 0) 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); #else data->texture = SDL_CreateTexture (data->renderer,