From c5a31acf8c28414db11981a55c3a44f2893ebaee Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Fri, 8 Jul 2016 20:12:56 +0200 Subject: [PATCH] v4l2: add support for buffer import Add support for buffer import Rename some methods --- spa/include/spa/buffer.h | 1 + spa/include/spa/node.h | 40 +++-- spa/include/spa/port.h | 8 +- spa/plugins/alsa/alsa-sink.c | 57 ++++--- spa/plugins/audiomixer/audiomixer.c | 56 ++++--- spa/plugins/audiotestsrc/audiotestsrc.c | 57 ++++--- spa/plugins/v4l2/v4l2-source.c | 130 ++++++++++------ spa/plugins/v4l2/v4l2-utils.c | 198 +++++++++++++++++------- spa/plugins/volume/volume.c | 57 ++++--- spa/plugins/xv/xv-sink.c | 56 ++++--- spa/tests/test-mixer.c | 24 +-- spa/tests/test-v4l2.c | 135 ++++++++++++++-- spa/tools/spa-inspect.c | 6 +- 13 files changed, 585 insertions(+), 240 deletions(-) diff --git a/spa/include/spa/buffer.h b/spa/include/spa/buffer.h index 478b62d42..7a94753e2 100644 --- a/spa/include/spa/buffer.h +++ b/spa/include/spa/buffer.h @@ -118,6 +118,7 @@ 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 a23d77c3b..190095915 100644 --- a/spa/include/spa/node.h +++ b/spa/include/spa/node.h @@ -237,7 +237,7 @@ struct _SpaNode { uint32_t port_id); /** - * SpaNode::enum_port_formats: + * SpaNode::port_enum_formats: * @handle: a #SpaHandle * @port_id: the port to query * @index: the format index to retrieve @@ -249,7 +249,7 @@ struct _SpaNode { * returns #SPA_RESULT_ENUM_END. * * The result format can be queried and modified and ultimately be used - * to call SpaNode::set_port_format. + * to call SpaNode::port_set_format. * * Returns: #SPA_RESULT_OK on success * #SPA_RESULT_INVALID_ARGUMENTS when node or format is %NULL @@ -257,12 +257,12 @@ struct _SpaNode { * #SPA_RESULT_ENUM_END when no format exists for @index * */ - SpaResult (*enum_port_formats) (SpaHandle *handle, + SpaResult (*port_enum_formats) (SpaHandle *handle, uint32_t port_id, unsigned int index, SpaFormat **format); /** - * SpaNode::set_port_format: + * SpaNode::port_set_format: * @handle: a #SpaHandle * @port_id: the port to configure * @test_only: only check if the format is accepted @@ -281,12 +281,12 @@ struct _SpaNode { * #SPA_RESULT_WRONG_PROPERTY_TYPE when the type or size of a property * is not correct. */ - SpaResult (*set_port_format) (SpaHandle *handle, + SpaResult (*port_set_format) (SpaHandle *handle, uint32_t port_id, bool test_only, const SpaFormat *format); /** - * SpaNode::get_port_format: + * SpaNode::port_get_format: * @handle: a #SpaHandle * @port_id: the port to query * @format: a pointer to a location to hold the #SpaFormat @@ -299,27 +299,35 @@ struct _SpaNode { * #SPA_RESULT_INVALID_PORT when @port_id is not valid * #SPA_RESULT_INVALID_NO_FORMAT when no format was set */ - SpaResult (*get_port_format) (SpaHandle *handle, + SpaResult (*port_get_format) (SpaHandle *handle, uint32_t port_id, const SpaFormat **format); - SpaResult (*get_port_info) (SpaHandle *handle, + SpaResult (*port_get_info) (SpaHandle *handle, uint32_t port_id, const SpaPortInfo **info); - SpaResult (*get_port_props) (SpaHandle *handle, + SpaResult (*port_get_props) (SpaHandle *handle, uint32_t port_id, SpaProps **props); - SpaResult (*set_port_props) (SpaHandle *handle, + SpaResult (*port_set_props) (SpaHandle *handle, uint32_t port_id, const SpaProps *props); - SpaResult (*get_port_status) (SpaHandle *handle, + SpaResult (*port_use_buffers) (SpaHandle *handle, + uint32_t port_id, + SpaBuffer *buffers, + uint32_t n_buffers); + SpaResult (*port_alloc_buffers) (SpaHandle *handle, + uint32_t port_id, + SpaBuffer **buffers, + uint32_t *n_buffers); + + SpaResult (*port_get_status) (SpaHandle *handle, uint32_t port_id, const SpaPortStatus **status); - /** - * SpaNode::push_port_input: + * SpaNode::port_push_input: * @handle: a #SpaHandle * @n_info: number of #SpaInputInfo in @info * @info: array of #SpaInputInfo @@ -334,11 +342,11 @@ struct _SpaNode { * @info. * #SPA_RESULT_HAVE_ENOUGH_INPUT when output can be produced. */ - SpaResult (*push_port_input) (SpaHandle *handle, + SpaResult (*port_push_input) (SpaHandle *handle, unsigned int n_info, SpaInputInfo *info); /** - * SpaNode::pull_port_output: + * SpaNode::port_pull_output: * @handle: a #SpaHandle * @n_info: number of #SpaOutputInfo in @info * @info: array of #SpaOutputInfo @@ -359,7 +367,7 @@ struct _SpaNode { * #SPA_RESULT_NEED_MORE_INPUT when no output can be produced * because more input is needed. */ - SpaResult (*pull_port_output) (SpaHandle *handle, + SpaResult (*port_pull_output) (SpaHandle *handle, unsigned int n_info, SpaOutputInfo *info); }; diff --git a/spa/include/spa/port.h b/spa/include/spa/port.h index b65445ca8..866f2b4be 100644 --- a/spa/include/spa/port.h +++ b/spa/include/spa/port.h @@ -50,7 +50,10 @@ typedef enum { /** * SpaPortInfo * @flags: extra port flags - * @size: minimum size of the buffers or 0 when not specified + * @minsize: minimum size of the buffers or 0 when not specified + * @stride: suggested stride or 0 when not specified + * @min_buffers: minimum number of buffers + * @max_buffers: maximum number of buffers * @align: required alignment of the data * @maxbuffering: the maximum amount of bytes that the element will keep * around internally @@ -61,6 +64,9 @@ typedef enum { typedef struct { SpaPortInfoFlags flags; size_t minsize; + size_t stride; + uint32_t min_buffers; + uint32_t max_buffers; uint32_t align; unsigned int maxbuffering; uint64_t latency; diff --git a/spa/plugins/alsa/alsa-sink.c b/spa/plugins/alsa/alsa-sink.c index c3ebf8767..0123a3b4e 100644 --- a/spa/plugins/alsa/alsa-sink.c +++ b/spa/plugins/alsa/alsa-sink.c @@ -69,7 +69,6 @@ struct _ALSABuffer { SpaMeta meta[1]; SpaMetaHeader header; SpaData data[1]; - ALSABuffer *next; }; struct _SpaALSASink { @@ -332,7 +331,7 @@ spa_alsa_sink_node_remove_port (SpaHandle *handle, } static SpaResult -spa_alsa_sink_node_enum_port_formats (SpaHandle *handle, +spa_alsa_sink_node_port_enum_formats (SpaHandle *handle, uint32_t port_id, unsigned int index, SpaFormat **format) @@ -361,7 +360,7 @@ spa_alsa_sink_node_enum_port_formats (SpaHandle *handle, } static SpaResult -spa_alsa_sink_node_set_port_format (SpaHandle *handle, +spa_alsa_sink_node_port_set_format (SpaHandle *handle, uint32_t port_id, bool test_only, const SpaFormat *format) @@ -391,7 +390,7 @@ spa_alsa_sink_node_set_port_format (SpaHandle *handle, } static SpaResult -spa_alsa_sink_node_get_port_format (SpaHandle *handle, +spa_alsa_sink_node_port_get_format (SpaHandle *handle, uint32_t port_id, const SpaFormat **format) { @@ -412,7 +411,7 @@ spa_alsa_sink_node_get_port_format (SpaHandle *handle, } static SpaResult -spa_alsa_sink_node_get_port_info (SpaHandle *handle, +spa_alsa_sink_node_port_get_info (SpaHandle *handle, uint32_t port_id, const SpaPortInfo **info) { @@ -430,7 +429,7 @@ spa_alsa_sink_node_get_port_info (SpaHandle *handle, } static SpaResult -spa_alsa_sink_node_get_port_props (SpaHandle *handle, +spa_alsa_sink_node_port_get_props (SpaHandle *handle, uint32_t port_id, SpaProps **props) { @@ -438,7 +437,7 @@ spa_alsa_sink_node_get_port_props (SpaHandle *handle, } static SpaResult -spa_alsa_sink_node_set_port_props (SpaHandle *handle, +spa_alsa_sink_node_port_set_props (SpaHandle *handle, uint32_t port_id, const SpaProps *props) { @@ -446,7 +445,7 @@ spa_alsa_sink_node_set_port_props (SpaHandle *handle, } static SpaResult -spa_alsa_sink_node_get_port_status (SpaHandle *handle, +spa_alsa_sink_node_port_get_status (SpaHandle *handle, uint32_t port_id, const SpaPortStatus **status) { @@ -464,7 +463,25 @@ spa_alsa_sink_node_get_port_status (SpaHandle *handle, } static SpaResult -spa_alsa_sink_node_push_port_input (SpaHandle *handle, +spa_alsa_sink_node_port_use_buffers (SpaHandle *handle, + uint32_t port_id, + SpaBuffer *buffers, + uint32_t n_buffers) +{ + return SPA_RESULT_NOT_IMPLEMENTED; +} + +static SpaResult +spa_alsa_sink_node_port_alloc_buffers (SpaHandle *handle, + uint32_t port_id, + SpaBuffer **buffers, + uint32_t *n_buffers) +{ + return SPA_RESULT_NOT_IMPLEMENTED; +} + +static SpaResult +spa_alsa_sink_node_port_push_input (SpaHandle *handle, unsigned int n_info, SpaInputInfo *info) { @@ -507,7 +524,7 @@ spa_alsa_sink_node_push_port_input (SpaHandle *handle, } static SpaResult -spa_alsa_sink_node_pull_port_output (SpaHandle *handle, +spa_alsa_sink_node_port_pull_output (SpaHandle *handle, unsigned int n_info, SpaOutputInfo *info) { @@ -524,15 +541,17 @@ static const SpaNode alsasink_node = { spa_alsa_sink_node_get_port_ids, spa_alsa_sink_node_add_port, spa_alsa_sink_node_remove_port, - spa_alsa_sink_node_enum_port_formats, - spa_alsa_sink_node_set_port_format, - spa_alsa_sink_node_get_port_format, - spa_alsa_sink_node_get_port_info, - spa_alsa_sink_node_get_port_props, - spa_alsa_sink_node_set_port_props, - spa_alsa_sink_node_get_port_status, - spa_alsa_sink_node_push_port_input, - spa_alsa_sink_node_pull_port_output, + spa_alsa_sink_node_port_enum_formats, + spa_alsa_sink_node_port_set_format, + spa_alsa_sink_node_port_get_format, + spa_alsa_sink_node_port_get_info, + spa_alsa_sink_node_port_get_props, + spa_alsa_sink_node_port_set_props, + spa_alsa_sink_node_port_use_buffers, + spa_alsa_sink_node_port_alloc_buffers, + spa_alsa_sink_node_port_get_status, + spa_alsa_sink_node_port_push_input, + spa_alsa_sink_node_port_pull_output, }; static SpaResult diff --git a/spa/plugins/audiomixer/audiomixer.c b/spa/plugins/audiomixer/audiomixer.c index 06c032d95..e6ac72241 100644 --- a/spa/plugins/audiomixer/audiomixer.c +++ b/spa/plugins/audiomixer/audiomixer.c @@ -299,7 +299,7 @@ spa_audiomixer_node_remove_port (SpaHandle *handle, static SpaResult -spa_audiomixer_node_enum_port_formats (SpaHandle *handle, +spa_audiomixer_node_port_enum_formats (SpaHandle *handle, uint32_t port_id, unsigned int index, SpaFormat **format) @@ -325,7 +325,7 @@ spa_audiomixer_node_enum_port_formats (SpaHandle *handle, } static SpaResult -spa_audiomixer_node_set_port_format (SpaHandle *handle, +spa_audiomixer_node_port_set_format (SpaHandle *handle, uint32_t port_id, bool test_only, const SpaFormat *format) @@ -353,7 +353,7 @@ spa_audiomixer_node_set_port_format (SpaHandle *handle, } static SpaResult -spa_audiomixer_node_get_port_format (SpaHandle *handle, +spa_audiomixer_node_port_get_format (SpaHandle *handle, uint32_t port_id, const SpaFormat **format) { @@ -374,7 +374,7 @@ spa_audiomixer_node_get_port_format (SpaHandle *handle, } static SpaResult -spa_audiomixer_node_get_port_info (SpaHandle *handle, +spa_audiomixer_node_port_get_info (SpaHandle *handle, uint32_t port_id, const SpaPortInfo **info) { @@ -392,7 +392,7 @@ spa_audiomixer_node_get_port_info (SpaHandle *handle, } static SpaResult -spa_audiomixer_node_get_port_props (SpaHandle *handle, +spa_audiomixer_node_port_get_props (SpaHandle *handle, uint32_t port_id, SpaProps **props) { @@ -400,7 +400,7 @@ spa_audiomixer_node_get_port_props (SpaHandle *handle, } static SpaResult -spa_audiomixer_node_set_port_props (SpaHandle *handle, +spa_audiomixer_node_port_set_props (SpaHandle *handle, uint32_t port_id, const SpaProps *props) { @@ -408,7 +408,7 @@ spa_audiomixer_node_set_port_props (SpaHandle *handle, } static SpaResult -spa_audiomixer_node_get_port_status (SpaHandle *handle, +spa_audiomixer_node_port_get_status (SpaHandle *handle, uint32_t port_id, const SpaPortStatus **status) { @@ -429,7 +429,25 @@ spa_audiomixer_node_get_port_status (SpaHandle *handle, } static SpaResult -spa_audiomixer_node_push_port_input (SpaHandle *handle, +spa_audiomixer_node_port_use_buffers (SpaHandle *handle, + uint32_t port_id, + SpaBuffer *buffers, + uint32_t n_buffers) +{ + return SPA_RESULT_NOT_IMPLEMENTED; +} + +static SpaResult +spa_audiomixer_node_port_alloc_buffers (SpaHandle *handle, + uint32_t port_id, + SpaBuffer **buffers, + uint32_t *n_buffers) +{ + return SPA_RESULT_NOT_IMPLEMENTED; +} + +static SpaResult +spa_audiomixer_node_port_push_input (SpaHandle *handle, unsigned int n_info, SpaInputInfo *info) { @@ -641,7 +659,7 @@ mix_data (SpaAudioMixer *this, SpaOutputInfo *info) } static SpaResult -spa_audiomixer_node_pull_port_output (SpaHandle *handle, +spa_audiomixer_node_port_pull_output (SpaHandle *handle, unsigned int n_info, SpaOutputInfo *info) { @@ -684,15 +702,17 @@ static const SpaNode audiomixer_node = { spa_audiomixer_node_get_port_ids, spa_audiomixer_node_add_port, spa_audiomixer_node_remove_port, - spa_audiomixer_node_enum_port_formats, - spa_audiomixer_node_set_port_format, - spa_audiomixer_node_get_port_format, - spa_audiomixer_node_get_port_info, - spa_audiomixer_node_get_port_props, - spa_audiomixer_node_set_port_props, - spa_audiomixer_node_get_port_status, - spa_audiomixer_node_push_port_input, - spa_audiomixer_node_pull_port_output, + spa_audiomixer_node_port_enum_formats, + spa_audiomixer_node_port_set_format, + spa_audiomixer_node_port_get_format, + spa_audiomixer_node_port_get_info, + spa_audiomixer_node_port_get_props, + spa_audiomixer_node_port_set_props, + spa_audiomixer_node_port_use_buffers, + spa_audiomixer_node_port_alloc_buffers, + spa_audiomixer_node_port_get_status, + spa_audiomixer_node_port_push_input, + spa_audiomixer_node_port_pull_output, }; static SpaResult diff --git a/spa/plugins/audiotestsrc/audiotestsrc.c b/spa/plugins/audiotestsrc/audiotestsrc.c index 6ca2ab00a..4800723cf 100644 --- a/spa/plugins/audiotestsrc/audiotestsrc.c +++ b/spa/plugins/audiotestsrc/audiotestsrc.c @@ -276,7 +276,7 @@ spa_audiotestsrc_node_remove_port (SpaHandle *handle, } static SpaResult -spa_audiotestsrc_node_enum_port_formats (SpaHandle *handle, +spa_audiotestsrc_node_port_enum_formats (SpaHandle *handle, uint32_t port_id, unsigned int index, SpaFormat **format) @@ -302,7 +302,7 @@ spa_audiotestsrc_node_enum_port_formats (SpaHandle *handle, } static SpaResult -spa_audiotestsrc_node_set_port_format (SpaHandle *handle, +spa_audiotestsrc_node_port_set_format (SpaHandle *handle, uint32_t port_id, bool test_only, const SpaFormat *format) @@ -330,7 +330,7 @@ spa_audiotestsrc_node_set_port_format (SpaHandle *handle, } static SpaResult -spa_audiotestsrc_node_get_port_format (SpaHandle *handle, +spa_audiotestsrc_node_port_get_format (SpaHandle *handle, uint32_t port_id, const SpaFormat **format) { @@ -351,7 +351,7 @@ spa_audiotestsrc_node_get_port_format (SpaHandle *handle, } static SpaResult -spa_audiotestsrc_node_get_port_info (SpaHandle *handle, +spa_audiotestsrc_node_port_get_info (SpaHandle *handle, uint32_t port_id, const SpaPortInfo **info) { @@ -369,7 +369,7 @@ spa_audiotestsrc_node_get_port_info (SpaHandle *handle, } static SpaResult -spa_audiotestsrc_node_get_port_props (SpaHandle *handle, +spa_audiotestsrc_node_port_get_props (SpaHandle *handle, uint32_t port_id, SpaProps **props) { @@ -377,7 +377,7 @@ spa_audiotestsrc_node_get_port_props (SpaHandle *handle, } static SpaResult -spa_audiotestsrc_node_set_port_props (SpaHandle *handle, +spa_audiotestsrc_node_port_set_props (SpaHandle *handle, uint32_t port_id, const SpaProps *props) { @@ -385,7 +385,7 @@ spa_audiotestsrc_node_set_port_props (SpaHandle *handle, } static SpaResult -spa_audiotestsrc_node_get_port_status (SpaHandle *handle, +spa_audiotestsrc_node_port_get_status (SpaHandle *handle, uint32_t port_id, const SpaPortStatus **status) { @@ -406,7 +406,26 @@ spa_audiotestsrc_node_get_port_status (SpaHandle *handle, } static SpaResult -spa_audiotestsrc_node_push_port_input (SpaHandle *handle, +spa_audiotestsrc_node_port_use_buffers (SpaHandle *handle, + uint32_t port_id, + SpaBuffer *buffers, + uint32_t n_buffers) +{ + return SPA_RESULT_NOT_IMPLEMENTED; +} + +static SpaResult +spa_audiotestsrc_node_port_alloc_buffers (SpaHandle *handle, + uint32_t port_id, + SpaBuffer **buffers, + uint32_t *n_buffers) +{ + return SPA_RESULT_NOT_IMPLEMENTED; +} + + +static SpaResult +spa_audiotestsrc_node_port_push_input (SpaHandle *handle, unsigned int n_info, SpaInputInfo *info) { @@ -414,7 +433,7 @@ spa_audiotestsrc_node_push_port_input (SpaHandle *handle, } static SpaResult -spa_audiotestsrc_node_pull_port_output (SpaHandle *handle, +spa_audiotestsrc_node_port_pull_output (SpaHandle *handle, unsigned int n_info, SpaOutputInfo *info) { @@ -470,15 +489,17 @@ static const SpaNode audiotestsrc_node = { spa_audiotestsrc_node_get_port_ids, spa_audiotestsrc_node_add_port, spa_audiotestsrc_node_remove_port, - spa_audiotestsrc_node_enum_port_formats, - spa_audiotestsrc_node_set_port_format, - spa_audiotestsrc_node_get_port_format, - spa_audiotestsrc_node_get_port_info, - spa_audiotestsrc_node_get_port_props, - spa_audiotestsrc_node_set_port_props, - spa_audiotestsrc_node_get_port_status, - spa_audiotestsrc_node_push_port_input, - spa_audiotestsrc_node_pull_port_output, + spa_audiotestsrc_node_port_enum_formats, + spa_audiotestsrc_node_port_set_format, + spa_audiotestsrc_node_port_get_format, + spa_audiotestsrc_node_port_get_info, + spa_audiotestsrc_node_port_get_props, + spa_audiotestsrc_node_port_set_props, + spa_audiotestsrc_node_port_use_buffers, + spa_audiotestsrc_node_port_alloc_buffers, + spa_audiotestsrc_node_port_get_status, + spa_audiotestsrc_node_port_push_input, + spa_audiotestsrc_node_port_pull_output, }; static SpaResult diff --git a/spa/plugins/v4l2/v4l2-source.c b/spa/plugins/v4l2/v4l2-source.c index ea5b691f9..0c59e3744 100644 --- a/spa/plugins/v4l2/v4l2-source.c +++ b/spa/plugins/v4l2/v4l2-source.c @@ -50,27 +50,34 @@ typedef struct _V4l2Buffer V4l2Buffer; struct _V4l2Buffer { SpaBuffer buffer; - SpaMeta meta[1]; + SpaMeta metas[1]; SpaMetaHeader header; - SpaData data[1]; - V4l2Buffer *next; - uint32_t index; + SpaData datas[1]; SpaV4l2Source *source; bool outstanding; + SpaBuffer *imported; + struct v4l2_buffer v4l2_buffer; + V4l2Buffer *next; }; typedef struct { + SpaVideoRawFormat raw_format[2]; + SpaFormat *current_format; bool opened; + bool have_buffers; int fd; struct v4l2_capability cap; struct v4l2_format fmt; enum v4l2_buf_type type; + enum v4l2_memory memtype; struct v4l2_requestbuffers reqbuf; V4l2Buffer buffers[MAX_BUFFERS]; V4l2Buffer *ready; uint32_t ready_count; SpaPollFd fds[1]; SpaPollItem poll; + SpaPortInfo info; + SpaPortStatus status; } SpaV4l2State; struct _SpaV4l2Source { @@ -81,13 +88,7 @@ struct _SpaV4l2Source { SpaEventCallback event_cb; void *user_data; - SpaVideoRawFormat raw_format[2]; - SpaFormat *current_format; - - SpaV4l2State state; - - SpaPortInfo info; - SpaPortStatus status; + SpaV4l2State state[1]; }; #include "v4l2-utils.c" @@ -291,12 +292,13 @@ spa_v4l2_source_node_remove_port (SpaHandle *handle, } static SpaResult -spa_v4l2_source_node_enum_port_formats (SpaHandle *handle, +spa_v4l2_source_node_port_enum_formats (SpaHandle *handle, uint32_t port_id, unsigned int index, SpaFormat **format) { SpaV4l2Source *this = (SpaV4l2Source *) handle; + SpaV4l2State *state; if (handle == NULL || format == NULL) return SPA_RESULT_INVALID_ARGUMENTS; @@ -304,25 +306,28 @@ spa_v4l2_source_node_enum_port_formats (SpaHandle *handle, if (port_id != 0) return SPA_RESULT_INVALID_PORT; + state = &this->state[port_id]; + switch (index) { case 0: - spa_video_raw_format_init (&this->raw_format[0]); + spa_video_raw_format_init (&state->raw_format[0]); break; default: return SPA_RESULT_ENUM_END; } - *format = &this->raw_format[0].format; + *format = &state->raw_format[0].format; return SPA_RESULT_OK; } static SpaResult -spa_v4l2_source_node_set_port_format (SpaHandle *handle, +spa_v4l2_source_node_port_set_format (SpaHandle *handle, uint32_t port_id, bool test_only, const SpaFormat *format) { SpaV4l2Source *this = (SpaV4l2Source *) handle; + SpaV4l2State *state; SpaResult res; SpaFormat *f, *tf; size_t fs; @@ -333,18 +338,20 @@ spa_v4l2_source_node_set_port_format (SpaHandle *handle, if (port_id != 0) return SPA_RESULT_INVALID_PORT; + state = &this->state[port_id]; + if (format == NULL) { - this->current_format = NULL; + state->current_format = NULL; return SPA_RESULT_OK; } if (format->media_type == SPA_MEDIA_TYPE_VIDEO) { if (format->media_subtype == SPA_MEDIA_SUBTYPE_RAW) { - if ((res = spa_video_raw_format_parse (format, &this->raw_format[0]) < 0)) + if ((res = spa_video_raw_format_parse (format, &state->raw_format[0]) < 0)) return res; - f = &this->raw_format[0].format; - tf = &this->raw_format[1].format; + f = &state->raw_format[0].format; + tf = &state->raw_format[1].format; fs = sizeof (SpaVideoRawFormat); } else return SPA_RESULT_INVALID_MEDIA_TYPE; @@ -356,18 +363,19 @@ spa_v4l2_source_node_set_port_format (SpaHandle *handle, if (!test_only) { memcpy (tf, f, fs); - this->current_format = tf; + state->current_format = tf; } return SPA_RESULT_OK; } static SpaResult -spa_v4l2_source_node_get_port_format (SpaHandle *handle, +spa_v4l2_source_node_port_get_format (SpaHandle *handle, uint32_t port_id, const SpaFormat **format) { SpaV4l2Source *this = (SpaV4l2Source *) handle; + SpaV4l2State *state; if (handle == NULL || format == NULL) return SPA_RESULT_INVALID_ARGUMENTS; @@ -375,16 +383,18 @@ spa_v4l2_source_node_get_port_format (SpaHandle *handle, if (port_id != 0) return SPA_RESULT_INVALID_PORT; - if (this->current_format == NULL) + state = &this->state[port_id]; + + if (state->current_format == NULL) return SPA_RESULT_NO_FORMAT; - *format = this->current_format; + *format = state->current_format; return SPA_RESULT_OK; } static SpaResult -spa_v4l2_source_node_get_port_info (SpaHandle *handle, +spa_v4l2_source_node_port_get_info (SpaHandle *handle, uint32_t port_id, const SpaPortInfo **info) { @@ -396,13 +406,13 @@ spa_v4l2_source_node_get_port_info (SpaHandle *handle, if (port_id != 0) return SPA_RESULT_INVALID_PORT; - *info = &this->info; + *info = &this->state[port_id].info; return SPA_RESULT_OK; } static SpaResult -spa_v4l2_source_node_get_port_props (SpaHandle *handle, +spa_v4l2_source_node_port_get_props (SpaHandle *handle, uint32_t port_id, SpaProps **props) { @@ -410,7 +420,7 @@ spa_v4l2_source_node_get_port_props (SpaHandle *handle, } static SpaResult -spa_v4l2_source_node_set_port_props (SpaHandle *handle, +spa_v4l2_source_node_port_set_props (SpaHandle *handle, uint32_t port_id, const SpaProps *props) { @@ -418,7 +428,7 @@ spa_v4l2_source_node_set_port_props (SpaHandle *handle, } static SpaResult -spa_v4l2_source_node_get_port_status (SpaHandle *handle, +spa_v4l2_source_node_port_get_status (SpaHandle *handle, uint32_t port_id, const SpaPortStatus **status) { @@ -430,13 +440,42 @@ spa_v4l2_source_node_get_port_status (SpaHandle *handle, if (port_id != 0) return SPA_RESULT_INVALID_PORT; - *status = &this->status; + *status = &this->state[port_id].status; return SPA_RESULT_OK; } static SpaResult -spa_v4l2_source_node_push_port_input (SpaHandle *handle, +spa_v4l2_source_node_port_use_buffers (SpaHandle *handle, + uint32_t port_id, + SpaBuffer *buffers, + uint32_t n_buffers) +{ + SpaV4l2Source *this = (SpaV4l2Source *) handle; + + if (handle == NULL) + return SPA_RESULT_INVALID_ARGUMENTS; + + if (port_id != 0) + return SPA_RESULT_INVALID_PORT; + + spa_v4l2_import_buffers (this, buffers, n_buffers); + + return SPA_RESULT_OK; +} + +static SpaResult +spa_v4l2_source_node_port_alloc_buffers (SpaHandle *handle, + uint32_t port_id, + SpaBuffer **buffers, + uint32_t *n_buffers) +{ + return SPA_RESULT_NOT_IMPLEMENTED; +} + + +static SpaResult +spa_v4l2_source_node_port_push_input (SpaHandle *handle, unsigned int n_info, SpaInputInfo *info) { @@ -444,7 +483,7 @@ spa_v4l2_source_node_push_port_input (SpaHandle *handle, } static SpaResult -spa_v4l2_source_node_pull_port_output (SpaHandle *handle, +spa_v4l2_source_node_port_pull_output (SpaHandle *handle, unsigned int n_info, SpaOutputInfo *info) { @@ -456,7 +495,6 @@ spa_v4l2_source_node_pull_port_output (SpaHandle *handle, if (handle == NULL || n_info == 0 || info == NULL) return SPA_RESULT_INVALID_ARGUMENTS; - state = &this->state; for (i = 0; i < n_info; i++) { V4l2Buffer *b; @@ -466,7 +504,9 @@ spa_v4l2_source_node_pull_port_output (SpaHandle *handle, have_error = true; continue; } - if (this->current_format == NULL) { + state = &this->state[info[i].port_id]; + + if (state->current_format == NULL) { info[i].status = SPA_RESULT_NO_FORMAT; have_error = true; continue; @@ -502,15 +542,17 @@ static const SpaNode v4l2source_node = { spa_v4l2_source_node_get_port_ids, spa_v4l2_source_node_add_port, spa_v4l2_source_node_remove_port, - spa_v4l2_source_node_enum_port_formats, - spa_v4l2_source_node_set_port_format, - spa_v4l2_source_node_get_port_format, - spa_v4l2_source_node_get_port_info, - spa_v4l2_source_node_get_port_props, - spa_v4l2_source_node_set_port_props, - spa_v4l2_source_node_get_port_status, - spa_v4l2_source_node_push_port_input, - spa_v4l2_source_node_pull_port_output, + spa_v4l2_source_node_port_enum_formats, + spa_v4l2_source_node_port_set_format, + spa_v4l2_source_node_port_get_format, + spa_v4l2_source_node_port_get_info, + spa_v4l2_source_node_port_get_props, + spa_v4l2_source_node_port_set_props, + spa_v4l2_source_node_port_use_buffers, + spa_v4l2_source_node_port_alloc_buffers, + spa_v4l2_source_node_port_get_status, + spa_v4l2_source_node_port_push_input, + spa_v4l2_source_node_port_pull_output, }; static SpaResult @@ -547,7 +589,7 @@ spa_v4l2_source_new (void) this->props[1].props.get_prop = spa_props_generic_get_prop; reset_v4l2_source_props (&this->props[1]); - this->info.flags = SPA_PORT_INFO_FLAG_NONE; - this->status.flags = SPA_PORT_STATUS_FLAG_NONE; + this->state[0].info.flags = SPA_PORT_INFO_FLAG_NONE; + this->state[0].status.flags = SPA_PORT_STATUS_FLAG_NONE; return handle; } diff --git a/spa/plugins/v4l2/v4l2-utils.c b/spa/plugins/v4l2/v4l2-utils.c index abec0db2e..c3be56506 100644 --- a/spa/plugins/v4l2/v4l2-utils.c +++ b/spa/plugins/v4l2/v4l2-utils.c @@ -24,7 +24,7 @@ xioctl (int fd, int request, void *arg) static int spa_v4l2_open (SpaV4l2Source *this) { - SpaV4l2State *state = &this->state; + SpaV4l2State *state = &this->state[0]; struct stat st; SpaV4l2SourceProps *props = &this->props[1]; @@ -260,12 +260,15 @@ video_format_to_fourcc (SpaVideoFormat format) static int spa_v4l2_set_format (SpaV4l2Source *this, SpaFormat *format, bool try_only) { - SpaV4l2State *state = &this->state; + SpaV4l2State *state = &this->state[0]; int cmd = try_only ? VIDIOC_TRY_FMT : VIDIOC_S_FMT; struct v4l2_format reqfmt, fmt; + struct v4l2_streamparm streamparm; CLEAR (fmt); + CLEAR (streamparm); fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (format->media_type == SPA_MEDIA_TYPE_VIDEO) { if (format->media_subtype == SPA_MEDIA_SUBTYPE_RAW) { @@ -275,8 +278,13 @@ spa_v4l2_set_format (SpaV4l2Source *this, SpaFormat *format, bool try_only) fmt.fmt.pix.width = f->info.width; fmt.fmt.pix.height = f->info.height; fmt.fmt.pix.field = V4L2_FIELD_ANY; - fprintf (stderr, "set %08x %dx%d\n", fmt.fmt.pix.pixelformat, - fmt.fmt.pix.width, fmt.fmt.pix.height); + streamparm.parm.capture.timeperframe.numerator = f->info.framerate.denom; + streamparm.parm.capture.timeperframe.denominator = f->info.framerate.num; + + fprintf (stderr, "set %08x %dx%d %d/%d\n", fmt.fmt.pix.pixelformat, + fmt.fmt.pix.width, fmt.fmt.pix.height, f->info.framerate.denom, + f->info.framerate.num); + } else return -1; } else @@ -292,6 +300,10 @@ spa_v4l2_set_format (SpaV4l2Source *this, SpaFormat *format, bool try_only) return -1; } + /* some cheap USB cam's won't accept any change */ + if (xioctl (state->fd, VIDIOC_S_PARM, &streamparm) < 0) + perror ("VIDIOC_S_PARM"); + if (reqfmt.fmt.pix.pixelformat != fmt.fmt.pix.pixelformat || reqfmt.fmt.pix.width != fmt.fmt.pix.width || reqfmt.fmt.pix.height != fmt.fmt.pix.height) @@ -301,6 +313,15 @@ spa_v4l2_set_format (SpaV4l2Source *this, SpaFormat *format, bool try_only) return 0; state->fmt = fmt; + state->info.flags = SPA_PORT_INFO_FLAG_CAN_GIVE_BUFFER; + state->info.minsize = fmt.fmt.pix.sizeimage; + state->info.stride = fmt.fmt.pix.bytesperline; + state->info.min_buffers = 2; + state->info.max_buffers = MAX_BUFFERS; + state->info.align = 16; + state->info.maxbuffering = -1; + state->info.latency = -1; + state->info.features = NULL; return 0; } @@ -308,7 +329,7 @@ spa_v4l2_set_format (SpaV4l2Source *this, SpaFormat *format, bool try_only) static int spa_v4l2_close (SpaV4l2Source *this) { - SpaV4l2State *state = &this->state; + SpaV4l2State *state = &this->state[0]; if (!state->opened) return 0; @@ -318,6 +339,7 @@ spa_v4l2_close (SpaV4l2Source *this) state->fd = -1; state->opened = false; + state->have_buffers = false; return 0; } @@ -325,13 +347,13 @@ spa_v4l2_close (SpaV4l2Source *this) static int mmap_read (SpaV4l2Source *this) { - SpaV4l2State *state = &this->state; + SpaV4l2State *state = &this->state[0]; struct v4l2_buffer buf; V4l2Buffer *b; CLEAR(buf); buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - buf.memory = V4L2_MEMORY_MMAP; + buf.memory = state->memtype; if (xioctl (state->fd, VIDIOC_DQBUF, &buf) < 0) { switch (errno) { @@ -376,32 +398,93 @@ v4l2_buffer_free (void *data) { V4l2Buffer *b = (V4l2Buffer *) data; SpaV4l2Source *this = b->source; - SpaV4l2State *state = &this->state; - struct v4l2_buffer buf; - - CLEAR (buf); - buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - buf.memory = V4L2_MEMORY_MMAP; - buf.index = b->index; + SpaV4l2State *state = &this->state[0]; b->buffer.refcount = 1; b->outstanding = false; - if (xioctl (state->fd, VIDIOC_QBUF, &buf) < 0) { + if (xioctl (state->fd, VIDIOC_QBUF, &b->v4l2_buffer) < 0) { perror ("VIDIOC_QBUF"); } } static int -mmap_init (SpaV4l2Source *this) +spa_v4l2_import_buffers (SpaV4l2Source *this, SpaBuffer *buffers, uint32_t n_buffers) { - SpaV4l2State *state = &this->state; + SpaV4l2State *state = &this->state[0]; struct v4l2_requestbuffers reqbuf; int i; + state->memtype = V4L2_MEMORY_USERPTR; + CLEAR(reqbuf); reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - reqbuf.memory = V4L2_MEMORY_MMAP; + reqbuf.memory = state->memtype; + reqbuf.count = n_buffers; + + if (xioctl (state->fd, VIDIOC_REQBUFS, &reqbuf) < 0) { + perror ("VIDIOC_REQBUFS"); + return -1; + } + fprintf (stderr, "got %d buffers\n", reqbuf.count); + if (reqbuf.count < 2) { + fprintf (stderr, "can't allocate enough buffers\n"); + return -1; + } + state->reqbuf = reqbuf; + + for (i = 0; i < reqbuf.count; i++) { + 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->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; + + v4l2_buffer_free (b); + } + state->have_buffers = true; + + return 0; +} + +static int +mmap_init (SpaV4l2Source *this) +{ + SpaV4l2State *state = &this->state[0]; + struct v4l2_requestbuffers reqbuf; + int i; + + state->memtype = V4L2_MEMORY_MMAP; + + CLEAR(reqbuf); + reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + reqbuf.memory = state->memtype; reqbuf.count = MAX_BUFFERS; if (xioctl (state->fd, VIDIOC_REQBUFS, &reqbuf) < 0) { @@ -423,7 +506,7 @@ mmap_init (SpaV4l2Source *this) CLEAR (buf); buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - buf.memory = V4L2_MEMORY_MMAP; + buf.memory = state->memtype; buf.index = i; if (xioctl (state->fd, VIDIOC_QUERYBUF, &buf) < 0) { @@ -432,54 +515,51 @@ mmap_init (SpaV4l2Source *this) } b = &state->buffers[i]; - b->index = i; b->source = this; - b->buffer.refcount = 1; + b->buffer.refcount = 0; b->buffer.notify = v4l2_buffer_free; b->buffer.size = buf.length; b->buffer.n_metas = 1; - b->buffer.metas = b->meta; + b->buffer.metas = b->metas; b->buffer.n_datas = 1; - b->buffer.datas = b->data; + b->buffer.datas = b->datas; b->header.flags = 0; b->header.seq = 0; b->header.pts = 0; b->header.dts_offset = 0; - b->meta[0].type = SPA_META_TYPE_HEADER; - b->meta[0].data = &b->header; - b->meta[0].size = sizeof (b->header); + b->metas[0].type = SPA_META_TYPE_HEADER; + b->metas[0].data = &b->header; + b->metas[0].size = sizeof (b->header); - b->data[0].type = SPA_DATA_TYPE_MEMPTR; - b->data[0].data = mmap (NULL, - buf.length, - PROT_READ | PROT_WRITE, - MAP_SHARED, - state->fd, - buf.m.offset); - b->data[0].offset = 0; - b->data[0].size = buf.length; - b->data[0].stride = state->fmt.fmt.pix.bytesperline; + b->datas[0].type = SPA_DATA_TYPE_MEMPTR; + b->datas[0].data = mmap (NULL, + buf.length, + PROT_READ | PROT_WRITE, + MAP_SHARED, + state->fd, + buf.m.offset); + 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->data[0].data == MAP_FAILED) { + if (b->datas[0].data == MAP_FAILED) { perror ("mmap"); - return -1; + continue; } - } - for (i = 0; i < state->reqbuf.count; ++i) { - struct v4l2_buffer buf; - CLEAR (buf); - buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - buf.memory = V4L2_MEMORY_MMAP; - buf.index = i; + CLEAR (b->v4l2_buffer); + b->v4l2_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + b->v4l2_buffer.memory = state->memtype; + b->v4l2_buffer.index = i; - if (xioctl (state->fd, VIDIOC_QBUF, &buf) < 0) { - perror ("VIDIOC_QBUF"); - return -1; - } + v4l2_buffer_free (b); } + state->have_buffers = true; + return 0; } @@ -498,22 +578,24 @@ read_init (SpaV4l2Source *this) static int spa_v4l2_start (SpaV4l2Source *this) { - SpaV4l2State *state = &this->state; + SpaV4l2State *state = &this->state[0]; enum v4l2_buf_type type; SpaEvent event; if (spa_v4l2_open (this) < 0) return -1; - if (state->cap.capabilities & V4L2_CAP_STREAMING) { - if (mmap_init (this) < 0) - if (userptr_init (this) < 0) + if (!state->have_buffers) { + if (state->cap.capabilities & V4L2_CAP_STREAMING) { + if (mmap_init (this) < 0) + if (userptr_init (this) < 0) + return -1; + } else if (state->cap.capabilities & V4L2_CAP_READWRITE) { + if (read_init (this) < 0) return -1; - } else if (state->cap.capabilities & V4L2_CAP_READWRITE) { - if (read_init (this) < 0) + } else return -1; - } else - return -1; + } event.refcount = 1; event.notify = NULL; @@ -545,7 +627,7 @@ spa_v4l2_start (SpaV4l2Source *this) static int spa_v4l2_stop (SpaV4l2Source *this) { - SpaV4l2State *state = &this->state; + SpaV4l2State *state = &this->state[0]; enum v4l2_buf_type type; SpaEvent event; diff --git a/spa/plugins/volume/volume.c b/spa/plugins/volume/volume.c index a8bb62259..543241a6c 100644 --- a/spa/plugins/volume/volume.c +++ b/spa/plugins/volume/volume.c @@ -257,7 +257,7 @@ spa_volume_node_remove_port (SpaHandle *handle, } static SpaResult -spa_volume_node_enum_port_formats (SpaHandle *handle, +spa_volume_node_port_enum_formats (SpaHandle *handle, uint32_t port_id, unsigned int index, SpaFormat **format) @@ -283,7 +283,7 @@ spa_volume_node_enum_port_formats (SpaHandle *handle, } static SpaResult -spa_volume_node_set_port_format (SpaHandle *handle, +spa_volume_node_port_set_format (SpaHandle *handle, uint32_t port_id, bool test_only, const SpaFormat *format) @@ -311,7 +311,7 @@ spa_volume_node_set_port_format (SpaHandle *handle, } static SpaResult -spa_volume_node_get_port_format (SpaHandle *handle, +spa_volume_node_port_get_format (SpaHandle *handle, uint32_t port_id, const SpaFormat **format) { @@ -332,7 +332,7 @@ spa_volume_node_get_port_format (SpaHandle *handle, } static SpaResult -spa_volume_node_get_port_info (SpaHandle *handle, +spa_volume_node_port_get_info (SpaHandle *handle, uint32_t port_id, const SpaPortInfo **info) { @@ -350,7 +350,7 @@ spa_volume_node_get_port_info (SpaHandle *handle, } static SpaResult -spa_volume_node_get_port_props (SpaHandle *handle, +spa_volume_node_port_get_props (SpaHandle *handle, uint32_t port_id, SpaProps **props) { @@ -358,7 +358,7 @@ spa_volume_node_get_port_props (SpaHandle *handle, } static SpaResult -spa_volume_node_set_port_props (SpaHandle *handle, +spa_volume_node_port_set_props (SpaHandle *handle, uint32_t port_id, const SpaProps *props) { @@ -366,7 +366,7 @@ spa_volume_node_set_port_props (SpaHandle *handle, } static SpaResult -spa_volume_node_get_port_status (SpaHandle *handle, +spa_volume_node_port_get_status (SpaHandle *handle, uint32_t port_id, const SpaPortStatus **status) { @@ -387,7 +387,26 @@ spa_volume_node_get_port_status (SpaHandle *handle, } static SpaResult -spa_volume_node_push_port_input (SpaHandle *handle, +spa_volume_node_port_use_buffers (SpaHandle *handle, + uint32_t port_id, + SpaBuffer *buffers, + uint32_t n_buffers) +{ + return SPA_RESULT_NOT_IMPLEMENTED; +} + +static SpaResult +spa_volume_node_port_alloc_buffers (SpaHandle *handle, + uint32_t port_id, + SpaBuffer **buffers, + uint32_t *n_buffers) +{ + return SPA_RESULT_NOT_IMPLEMENTED; +} + + +static SpaResult +spa_volume_node_port_push_input (SpaHandle *handle, unsigned int n_info, SpaInputInfo *info) { @@ -453,7 +472,7 @@ spa_volume_node_push_port_input (SpaHandle *handle, #define MIN(a,b) ((a) < (b) ? (a) : (b)) static SpaResult -spa_volume_node_pull_port_output (SpaHandle *handle, +spa_volume_node_port_pull_output (SpaHandle *handle, unsigned int n_info, SpaOutputInfo *info) { @@ -543,15 +562,17 @@ static const SpaNode volume_node = { spa_volume_node_get_port_ids, spa_volume_node_add_port, spa_volume_node_remove_port, - spa_volume_node_enum_port_formats, - spa_volume_node_set_port_format, - spa_volume_node_get_port_format, - spa_volume_node_get_port_info, - spa_volume_node_get_port_props, - spa_volume_node_set_port_props, - spa_volume_node_get_port_status, - spa_volume_node_push_port_input, - spa_volume_node_pull_port_output, + spa_volume_node_port_enum_formats, + spa_volume_node_port_set_format, + spa_volume_node_port_get_format, + spa_volume_node_port_get_info, + spa_volume_node_port_get_props, + spa_volume_node_port_set_props, + spa_volume_node_port_use_buffers, + spa_volume_node_port_alloc_buffers, + spa_volume_node_port_get_status, + spa_volume_node_port_push_input, + spa_volume_node_port_pull_output, }; static SpaResult diff --git a/spa/plugins/xv/xv-sink.c b/spa/plugins/xv/xv-sink.c index 875832bd7..457c066b9 100644 --- a/spa/plugins/xv/xv-sink.c +++ b/spa/plugins/xv/xv-sink.c @@ -286,7 +286,7 @@ spa_xv_sink_node_remove_port (SpaHandle *handle, } static SpaResult -spa_xv_sink_node_enum_port_formats (SpaHandle *handle, +spa_xv_sink_node_port_enum_formats (SpaHandle *handle, uint32_t port_id, unsigned int index, SpaFormat **format) @@ -312,7 +312,7 @@ spa_xv_sink_node_enum_port_formats (SpaHandle *handle, } static SpaResult -spa_xv_sink_node_set_port_format (SpaHandle *handle, +spa_xv_sink_node_port_set_format (SpaHandle *handle, uint32_t port_id, bool test_only, const SpaFormat *format) @@ -358,7 +358,7 @@ spa_xv_sink_node_set_port_format (SpaHandle *handle, } static SpaResult -spa_xv_sink_node_get_port_format (SpaHandle *handle, +spa_xv_sink_node_port_get_format (SpaHandle *handle, uint32_t port_id, const SpaFormat **format) { @@ -379,7 +379,7 @@ spa_xv_sink_node_get_port_format (SpaHandle *handle, } static SpaResult -spa_xv_sink_node_get_port_info (SpaHandle *handle, +spa_xv_sink_node_port_get_info (SpaHandle *handle, uint32_t port_id, const SpaPortInfo **info) { @@ -397,7 +397,7 @@ spa_xv_sink_node_get_port_info (SpaHandle *handle, } static SpaResult -spa_xv_sink_node_get_port_props (SpaHandle *handle, +spa_xv_sink_node_port_get_props (SpaHandle *handle, uint32_t port_id, SpaProps **props) { @@ -405,7 +405,7 @@ spa_xv_sink_node_get_port_props (SpaHandle *handle, } static SpaResult -spa_xv_sink_node_set_port_props (SpaHandle *handle, +spa_xv_sink_node_port_set_props (SpaHandle *handle, uint32_t port_id, const SpaProps *props) { @@ -413,7 +413,7 @@ spa_xv_sink_node_set_port_props (SpaHandle *handle, } static SpaResult -spa_xv_sink_node_get_port_status (SpaHandle *handle, +spa_xv_sink_node_port_get_status (SpaHandle *handle, uint32_t port_id, const SpaPortStatus **status) { @@ -431,7 +431,25 @@ spa_xv_sink_node_get_port_status (SpaHandle *handle, } static SpaResult -spa_xv_sink_node_push_port_input (SpaHandle *handle, +spa_xv_sink_node_port_use_buffers (SpaHandle *handle, + uint32_t port_id, + SpaBuffer *buffers, + uint32_t n_buffers) +{ + return SPA_RESULT_NOT_IMPLEMENTED; +} + +static SpaResult +spa_xv_sink_node_port_alloc_buffers (SpaHandle *handle, + uint32_t port_id, + SpaBuffer **buffers, + uint32_t *n_buffers) +{ + return SPA_RESULT_NOT_IMPLEMENTED; +} + +static SpaResult +spa_xv_sink_node_port_push_input (SpaHandle *handle, unsigned int n_info, SpaInputInfo *info) { @@ -439,7 +457,7 @@ spa_xv_sink_node_push_port_input (SpaHandle *handle, } static SpaResult -spa_xv_sink_node_pull_port_output (SpaHandle *handle, +spa_xv_sink_node_port_pull_output (SpaHandle *handle, unsigned int n_info, SpaOutputInfo *info) { @@ -497,15 +515,17 @@ static const SpaNode xvsink_node = { spa_xv_sink_node_get_port_ids, spa_xv_sink_node_add_port, spa_xv_sink_node_remove_port, - spa_xv_sink_node_enum_port_formats, - spa_xv_sink_node_set_port_format, - spa_xv_sink_node_get_port_format, - spa_xv_sink_node_get_port_info, - spa_xv_sink_node_get_port_props, - spa_xv_sink_node_set_port_props, - spa_xv_sink_node_get_port_status, - spa_xv_sink_node_push_port_input, - spa_xv_sink_node_pull_port_output, + spa_xv_sink_node_port_enum_formats, + spa_xv_sink_node_port_set_format, + spa_xv_sink_node_port_get_format, + spa_xv_sink_node_port_get_info, + spa_xv_sink_node_port_get_props, + spa_xv_sink_node_port_set_props, + spa_xv_sink_node_port_use_buffers, + spa_xv_sink_node_port_alloc_buffers, + spa_xv_sink_node_port_get_status, + spa_xv_sink_node_port_push_input, + spa_xv_sink_node_port_pull_output, }; static SpaResult diff --git a/spa/tests/test-mixer.c b/spa/tests/test-mixer.c index 449b653f8..217c20b2e 100644 --- a/spa/tests/test-mixer.c +++ b/spa/tests/test-mixer.c @@ -110,10 +110,10 @@ on_mix_event (SpaHandle *handle, SpaEvent *event, void *user_data) oinfo.event = NULL; if (event->port_id == data->mix_ports[0]) { - if ((res = data->source1_node->pull_port_output (data->source1, 1, &oinfo)) < 0) + if ((res = data->source1_node->port_pull_output (data->source1, 1, &oinfo)) < 0) printf ("got error %d\n", res); } else { - if ((res = data->source2_node->pull_port_output (data->source2, 1, &oinfo)) < 0) + if ((res = data->source2_node->port_pull_output (data->source2, 1, &oinfo)) < 0) printf ("got error %d\n", res); } @@ -122,7 +122,7 @@ on_mix_event (SpaHandle *handle, SpaEvent *event, void *user_data) iinfo.buffer = oinfo.buffer; iinfo.event = oinfo.event; - if ((res = data->mix_node->push_port_input (data->mix, 1, &iinfo)) < 0) + if ((res = data->mix_node->port_push_input (data->mix, 1, &iinfo)) < 0) printf ("got error from mixer %d\n", res); break; } @@ -152,7 +152,7 @@ on_sink_event (SpaHandle *handle, SpaEvent *event, void *user_data) oinfo.buffer = buf; oinfo.event = NULL; - if ((res = data->mix_node->pull_port_output (data->mix, 1, &oinfo)) < 0) + if ((res = data->mix_node->port_pull_output (data->mix, 1, &oinfo)) < 0) printf ("got error %d\n", res); iinfo.port_id = event->port_id; @@ -160,7 +160,7 @@ on_sink_event (SpaHandle *handle, SpaEvent *event, void *user_data) iinfo.buffer = oinfo.buffer; iinfo.event = oinfo.event; - if ((res = data->sink_node->push_port_input (data->sink, 1, &iinfo)) < 0) + if ((res = data->sink_node->port_push_input (data->sink, 1, &iinfo)) < 0) printf ("got error %d\n", res); break; } @@ -234,7 +234,7 @@ negotiate_formats (AppData *data) uint32_t val; SpaPropValue value; - if ((res = data->sink_node->enum_port_formats (data->sink, 0, 0, &format)) < 0) + if ((res = data->sink_node->port_enum_formats (data->sink, 0, 0, &format)) < 0) return res; props = &format->props; @@ -256,28 +256,28 @@ negotiate_formats (AppData *data) if ((res = props->set_prop (props, spa_props_index_for_id (props, SPA_PROP_ID_AUDIO_CHANNELS), &value)) < 0) return res; - if ((res = data->sink_node->set_port_format (data->sink, 0, false, format)) < 0) + if ((res = data->sink_node->port_set_format (data->sink, 0, false, format)) < 0) return res; - if ((res = data->mix_node->set_port_format (data->mix, 0, false, format)) < 0) + if ((res = data->mix_node->port_set_format (data->mix, 0, false, format)) < 0) return res; if ((res = data->mix_node->add_port (data->mix, SPA_DIRECTION_INPUT, &data->mix_ports[0])) < 0) return res; - if ((res = data->mix_node->set_port_format (data->mix, data->mix_ports[0], false, format)) < 0) + if ((res = data->mix_node->port_set_format (data->mix, data->mix_ports[0], false, format)) < 0) return res; - if ((res = data->source1_node->set_port_format (data->source1, 0, false, format)) < 0) + if ((res = data->source1_node->port_set_format (data->source1, 0, false, format)) < 0) return res; if ((res = data->mix_node->add_port (data->mix, SPA_DIRECTION_INPUT, &data->mix_ports[1])) < 0) return res; - if ((res = data->mix_node->set_port_format (data->mix, data->mix_ports[1], false, format)) < 0) + if ((res = data->mix_node->port_set_format (data->mix, data->mix_ports[1], false, format)) < 0) return res; - if ((res = data->source2_node->set_port_format (data->source2, 0, false, format)) < 0) + if ((res = data->source2_node->port_set_format (data->source2, 0, false, format)) < 0) return res; diff --git a/spa/tests/test-v4l2.c b/spa/tests/test-v4l2.c index 1942218fd..a4501d1e2 100644 --- a/spa/tests/test-v4l2.c +++ b/spa/tests/test-v4l2.c @@ -31,6 +31,15 @@ #include #include +#define MAX_BUFFERS 8 + +typedef struct { + SpaMeta meta[1]; + SpaMetaHeader header; + SpaData data[1]; + SDL_Texture *texture; +} SDLBufferData; + typedef struct { SpaHandle *source; const SpaNode *source_node; @@ -42,6 +51,8 @@ typedef struct { SpaPollFd fds[16]; unsigned int n_fds; SpaPollItem poll; + SpaBuffer buffers[MAX_BUFFERS]; + SDLBufferData bdata[MAX_BUFFERS]; } AppData; static SpaResult @@ -98,14 +109,27 @@ 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->pull_port_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); +#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; @@ -118,15 +142,28 @@ on_source_event (SpaHandle *handle, SpaEvent *event, void *user_data) 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); +#endif - if (info[0].buffer) { - spa_buffer_unref (info[0].buffer); +#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; } case SPA_EVENT_TYPE_ADD_POLL: @@ -171,6 +208,59 @@ make_nodes (AppData *data, const char *device) return res; } +#if 0 +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]; + void *mem; + int stride; + + bd->texture = SDL_CreateTexture (data->renderer, + SDL_PIXELFORMAT_YUY2, + SDL_TEXTUREACCESS_STREAMING, + 320, 240); + if (!bd->texture) { + printf ("can't create texture: %s\n", SDL_GetError ()); + return; + } + if (SDL_LockTexture (bd->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; + + bd->header.flags = 0; + bd->header.seq = 0; + bd->header.pts = 0; + bd->header.dts_offset = 0; + + bd->meta[0].type = SPA_META_TYPE_HEADER; + bd->meta[0].data = &bd->header; + bd->meta[0].size = sizeof (bd->header); + + 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; + } + data->source_node->port_use_buffers (data->source, 0, data->buffers, MAX_BUFFERS); +} +#endif + static SpaResult negotiate_formats (AppData *data) { @@ -178,9 +268,10 @@ negotiate_formats (AppData *data) SpaFormat *format; SpaProps *props; uint32_t val; + SpaFraction frac; SpaPropValue value; - if ((res = data->source_node->enum_port_formats (data->source, 0, 0, &format)) < 0) + if ((res = data->source_node->port_enum_formats (data->source, 0, 0, &format)) < 0) return res; props = &format->props; @@ -199,9 +290,31 @@ negotiate_formats (AppData *data) if ((res = props->set_prop (props, spa_props_index_for_id (props, SPA_PROP_ID_VIDEO_HEIGHT), &value)) < 0) return res; - if ((res = data->source_node->set_port_format (data->source, 0, false, format)) < 0) + value.type = SPA_PROP_TYPE_FRACTION; + value.size = sizeof (SpaFraction); + value.value = &frac; + + frac.num = 25; + frac.denom = 1; + if ((res = props->set_prop (props, spa_props_index_for_id (props, SPA_PROP_ID_VIDEO_FRAMERATE), &value)) < 0) return res; + if ((res = data->source_node->port_set_format (data->source, 0, false, format)) < 0) + return res; + +#if 0 + alloc_buffers (data); +#else + data->texture = SDL_CreateTexture (data->renderer, + SDL_PIXELFORMAT_YUY2, + SDL_TEXTUREACCESS_STREAMING, + 320, 240); + if (!data->texture) { + printf ("can't create texture: %s\n", SDL_GetError ()); + return -1; + } +#endif + return SPA_RESULT_OK; } @@ -298,14 +411,6 @@ main (int argc, char *argv[]) return -1; } - data.texture = SDL_CreateTexture (data.renderer, - SDL_PIXELFORMAT_YUY2, - SDL_TEXTUREACCESS_STREAMING, - 320, 240); - if (!data.texture) { - printf ("can't create texture: %s\n", SDL_GetError ()); - return -1; - } if ((res = make_nodes (&data, argv[1])) < 0) { printf ("can't make nodes: %d\n", res); diff --git a/spa/tools/spa-inspect.c b/spa/tools/spa-inspect.c index 3a76d1190..a15d5893f 100644 --- a/spa/tools/spa-inspect.c +++ b/spa/tools/spa-inspect.c @@ -160,15 +160,15 @@ inspect_node (const SpaNode *node, SpaHandle *handle) printf ("supported ports %d %d %d %d\n", n_input, max_input, n_output, max_output); for (i = 0; ; i++) { - if ((res = node->enum_port_formats (handle, 0, i, &format)) < 0) { + if ((res = node->port_enum_formats (handle, 0, i, &format)) < 0) { if (res != SPA_RESULT_ENUM_END) printf ("got error %d\n", res); break; } print_format (format, 1); } - if ((res = node->get_port_props (handle, 0, &props)) < 0) - printf ("get_port_props error: %d\n", res); + if ((res = node->port_get_props (handle, 0, &props)) < 0) + printf ("port_get_props error: %d\n", res); else print_props (props, 1); }