From b67c216a04dec56fe9c8d1e867726eae6e91d65e Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Fri, 26 Aug 2016 17:43:48 +0200 Subject: [PATCH] Make new USE_BUFFERS command Make a new USE_BUFFERS command to atomically send a buffer array to the remote client. We can use this to then clean up an old array and go to the PAUSED state if possible. Work on formats. Make one structure that can hold all video formats. Work on pipeline suspend and resume. Add jpeg support to v4l2. Work on enum_formats with a filter in v4l2. --- pinos/client/stream.c | 80 ++++----- pinos/gst/gstpinosformat.c | 63 ++++--- pinos/modules/spa/spa-v4l2-source.c | 26 ++- pinos/server/link.c | 84 ++++++---- spa/include/spa/audio/format.h | 8 +- spa/include/spa/control.h | 23 +-- spa/include/spa/props.h | 4 +- spa/include/spa/video/encoded.h | 42 +++++ spa/include/spa/video/format.h | 29 ++-- spa/include/spa/video/raw.h | 6 +- spa/lib/audio-raw.c | 104 +++++++----- spa/lib/control.c | 78 +++++++-- spa/lib/debug.c | 34 +++- spa/lib/video-raw.c | 210 +++++++++++++----------- spa/plugins/alsa/alsa-sink.c | 36 ++-- spa/plugins/audiotestsrc/audiotestsrc.c | 20 +-- spa/plugins/ffmpeg/ffmpeg-dec.c | 28 +--- spa/plugins/ffmpeg/ffmpeg-enc.c | 29 ++-- spa/plugins/remote/proxy.c | 60 ++----- spa/plugins/v4l2/v4l2-source.c | 41 ++--- spa/plugins/v4l2/v4l2-utils.c | 133 ++++++++++----- spa/plugins/volume/volume.c | 12 +- spa/plugins/xv/xv-sink.c | 34 ++-- spa/tests/test-v4l2.c | 18 +- 24 files changed, 688 insertions(+), 514 deletions(-) create mode 100644 spa/include/spa/video/encoded.h diff --git a/pinos/client/stream.c b/pinos/client/stream.c index 527f083ea..882089286 100644 --- a/pinos/client/stream.c +++ b/pinos/client/stream.c @@ -43,9 +43,6 @@ typedef struct { bool cleanup; uint32_t id; - int fd; - off_t offset; - size_t size; bool used; SpaBuffer *buf; } BufferId; @@ -53,10 +50,8 @@ typedef struct { static void clear_buffer_id (BufferId *id) { - munmap (id->buf, id->size); + spa_memory_unref (&id->buf->mem.mem); id->buf = NULL; - close (id->fd); - id->fd = -1; } struct _PinosStreamPrivate @@ -822,45 +817,46 @@ parse_control (PinosStream *stream, spa_memory_unref (&p.mem); break; } - case SPA_CONTROL_CMD_ADD_BUFFER: + case SPA_CONTROL_CMD_USE_BUFFERS: { - SpaControlCmdAddBuffer p; + SpaControlCmdUseBuffers p; BufferId bid; - SpaMemory *mem; + unsigned int i; + SpaControlBuilder builder; + SpaControl control; if (spa_control_iter_parse_cmd (&it, &p) < 0) break; - g_debug ("add buffer %d, %d", p.buffer_id, p.mem.mem.id); - mem = spa_memory_find (&p.mem.mem); - bid.cleanup = false; - bid.id = p.buffer_id; - bid.offset = p.mem.offset; - bid.size = p.mem.size; - bid.buf = SPA_MEMBER (spa_memory_ensure_ptr (mem), p.mem.offset, SpaBuffer); + /* clear previous buffers */ + g_array_set_size (priv->buffer_ids, 0); - if (bid.id != priv->buffer_ids->len) { - g_warning ("unexpected id %u found, expected %u", bid.id, priv->buffer_ids->len); - priv->in_order = FALSE; + for (i = 0; i < p.n_buffers; i++) { + bid.buf = p.buffers[i]; + bid.cleanup = false; + bid.id = bid.buf->id; + g_debug ("add buffer %d, %d", bid.id, bid.buf->mem.mem.id); + + if (bid.id != priv->buffer_ids->len) { + g_warning ("unexpected id %u found, expected %u", bid.id, priv->buffer_ids->len); + priv->in_order = FALSE; + } + g_array_append_val (priv->buffer_ids, bid); + g_signal_emit (stream, signals[SIGNAL_ADD_BUFFER], 0, bid.id); } - g_array_append_val (priv->buffer_ids, bid); - g_signal_emit (stream, signals[SIGNAL_ADD_BUFFER], 0, p.buffer_id); - break; - } - case SPA_CONTROL_CMD_REMOVE_BUFFER: - { - SpaControlCmdRemoveBuffer p; - BufferId *bid; - if (spa_control_iter_parse_cmd (&it, &p) < 0) - break; - - g_debug ("remove buffer %d", p.buffer_id); - if ((bid = find_buffer (stream, p.buffer_id))) { - bid->cleanup = TRUE; - bid->used = TRUE; - g_signal_emit (stream, signals[SIGNAL_REMOVE_BUFFER], 0, p.buffer_id); + control_builder_init (stream, &builder); + if (p.n_buffers) { + add_state_change (stream, &builder, SPA_NODE_STATE_PAUSED); + } else { + add_state_change (stream, &builder, SPA_NODE_STATE_READY); } + spa_control_builder_end (&builder, &control); + + if (spa_control_write (&control, priv->fd) < 0) + g_warning ("stream %p: error writing control", stream); + + spa_control_clear (&control); break; } case SPA_CONTROL_CMD_PROCESS_BUFFER: @@ -875,7 +871,7 @@ parse_control (PinosStream *stream, g_signal_emit (stream, signals[SIGNAL_NEW_BUFFER], 0, p.buffer_id); - send_need_input (stream, 0); + send_need_input (stream, 0); break; } case SPA_CONTROL_CMD_REUSE_BUFFER: @@ -919,7 +915,6 @@ on_socket_condition (GSocket *socket, case G_IO_IN: { SpaControl *control = &priv->recv_control; - guint i; if (spa_control_read (control, priv->fd, @@ -933,17 +928,6 @@ on_socket_condition (GSocket *socket, parse_control (stream, control); - for (i = 0; i < priv->buffer_ids->len; i++) { - BufferId *bid = &g_array_index (priv->buffer_ids, BufferId, i); - if (bid->cleanup) { - g_array_remove_index_fast (priv->buffer_ids, i); - i--; - priv->in_order = FALSE; - } - } - if (!priv->in_order && priv->buffer_ids->len == 0) - priv->in_order = TRUE; - spa_control_clear (control); break; } diff --git a/pinos/gst/gstpinosformat.c b/pinos/gst/gstpinosformat.c index 3306b9dc9..38d57209a 100644 --- a/pinos/gst/gstpinosformat.c +++ b/pinos/gst/gstpinosformat.c @@ -101,6 +101,7 @@ calc_size (GstCapsFeatures *cf, GstStructure *cs, guint *n_infos, guint *n_range n_ranges[0] += c; n_datas[0] += (1 + c) * sizeof (uint32_t); } + } else if (gst_structure_has_name (cs, "image/jpeg")) { } } @@ -147,9 +148,9 @@ convert_1 (GstCapsFeatures *cf, GstStructure *cs) if (val) { SpaVideoFormat *sv = p; - spa_video_raw_fill_prop_info (&bpi[pi], - SPA_PROP_ID_VIDEO_FORMAT, - SPA_PTRDIFF (p, f)); + spa_prop_info_fill_video (&bpi[pi], + SPA_PROP_ID_VIDEO_FORMAT, + SPA_PTRDIFF (p, f)); if (G_VALUE_TYPE (val) == G_TYPE_STRING) { *sv = gst_video_format_from_string (g_value_get_string (val)); @@ -171,7 +172,7 @@ convert_1 (GstCapsFeatures *cf, GstStructure *cs) if (val || val2) { SpaRectangle *sv = p; - spa_video_raw_fill_prop_info (&bpi[pi], + spa_prop_info_fill_video (&bpi[pi], SPA_PROP_ID_VIDEO_SIZE, SPA_PTRDIFF (p, f)); @@ -224,9 +225,9 @@ convert_1 (GstCapsFeatures *cf, GstStructure *cs) if (val) { SpaFraction *sv = p; - spa_video_raw_fill_prop_info (&bpi[pi], - SPA_PROP_ID_VIDEO_FRAMERATE, - SPA_PTRDIFF (p, f)); + spa_prop_info_fill_video (&bpi[pi], + SPA_PROP_ID_VIDEO_FRAMERATE, + SPA_PTRDIFF (p, f)); if (G_VALUE_TYPE (val) == GST_TYPE_FRACTION) { sv->num = gst_value_get_fraction_numerator (val); @@ -284,9 +285,9 @@ convert_1 (GstCapsFeatures *cf, GstStructure *cs) if (val) { SpaAudioFormat *sv = p; - spa_audio_raw_fill_prop_info (&bpi[pi], - SPA_PROP_ID_AUDIO_FORMAT, - SPA_PTRDIFF (p, f)); + spa_prop_info_fill_audio (&bpi[pi], + SPA_PROP_ID_AUDIO_FORMAT, + SPA_PTRDIFF (p, f)); if (G_VALUE_TYPE (val) == G_TYPE_STRING) { *sv = gst_audio_format_from_string (g_value_get_string (val)); @@ -307,9 +308,9 @@ convert_1 (GstCapsFeatures *cf, GstStructure *cs) if (val) { SpaAudioLayout *sv = p; - spa_audio_raw_fill_prop_info (&bpi[pi], - SPA_PROP_ID_AUDIO_LAYOUT, - SPA_PTRDIFF (p, f)); + spa_prop_info_fill_audio (&bpi[pi], + SPA_PROP_ID_AUDIO_LAYOUT, + SPA_PTRDIFF (p, f)); if (G_VALUE_TYPE (val) == G_TYPE_STRING) { const gchar *s = g_value_get_string (val); @@ -334,9 +335,9 @@ convert_1 (GstCapsFeatures *cf, GstStructure *cs) if (val) { uint32_t *sv = p; - spa_audio_raw_fill_prop_info (&bpi[pi], - SPA_PROP_ID_AUDIO_RATE, - SPA_PTRDIFF (p, f)); + spa_prop_info_fill_audio (&bpi[pi], + SPA_PROP_ID_AUDIO_RATE, + SPA_PTRDIFF (p, f)); if (G_VALUE_TYPE (val) == G_TYPE_INT) { *sv = g_value_get_int (val); @@ -357,9 +358,9 @@ convert_1 (GstCapsFeatures *cf, GstStructure *cs) if (val) { uint32_t *sv = p; - spa_audio_raw_fill_prop_info (&bpi[pi], - SPA_PROP_ID_AUDIO_CHANNELS, - SPA_PTRDIFF (p, f)); + spa_prop_info_fill_audio (&bpi[pi], + SPA_PROP_ID_AUDIO_CHANNELS, + SPA_PTRDIFF (p, f)); if (G_VALUE_TYPE (val) == G_TYPE_INT) { *sv = g_value_get_int (val); @@ -376,6 +377,9 @@ convert_1 (GstCapsFeatures *cf, GstStructure *cs) } pi++; } + } else if (gst_structure_has_name (cs, "image/jpeg")) { + f->media_type = SPA_MEDIA_TYPE_VIDEO; + f->media_subtype = SPA_MEDIA_SUBTYPE_MJPG; } return f; } @@ -431,16 +435,21 @@ gst_caps_from_format (SpaFormat *format) GstCaps *res = NULL; if (format->media_type == SPA_MEDIA_TYPE_VIDEO) { + SpaFormatVideo f; + + spa_format_video_parse (format, &f); + if (format->media_subtype == SPA_MEDIA_SUBTYPE_RAW) { - SpaVideoRawFormat f; - - spa_video_raw_format_parse (format, &f); - res = gst_caps_new_simple ("video/x-raw", - "format", G_TYPE_STRING, gst_video_format_to_string (f.info.format), - "width", G_TYPE_INT, f.info.size.width, - "height", G_TYPE_INT, f.info.size.height, - "framerate", GST_TYPE_FRACTION, f.info.framerate.num, f.info.framerate.denom, + "format", G_TYPE_STRING, gst_video_format_to_string (f.info.raw.format), + "width", G_TYPE_INT, f.info.raw.size.width, + "height", G_TYPE_INT, f.info.raw.size.height, + "framerate", GST_TYPE_FRACTION, f.info.raw.framerate.num, f.info.raw.framerate.denom, + NULL); + } + else if (format->media_subtype == SPA_MEDIA_SUBTYPE_MJPG) { + res = gst_caps_new_simple ("image/jpeg", + "framerate", GST_TYPE_FRACTION, f.info.jpeg.framerate.num, f.info.jpeg.framerate.denom, NULL); } } else if (format->media_type == SPA_MEDIA_TYPE_AUDIO) { diff --git a/pinos/modules/spa/spa-v4l2-source.c b/pinos/modules/spa/spa-v4l2-source.c index 3ad44c341..d957e9cdf 100644 --- a/pinos/modules/spa/spa-v4l2-source.c +++ b/pinos/modules/spa/spa-v4l2-source.c @@ -224,25 +224,32 @@ setup_node (PinosSpaV4l2Source *this) } static void -stop_pipeline (PinosSpaV4l2Source *this) +pause_pipeline (PinosSpaV4l2Source *this) { - PinosSpaV4l2SourcePrivate *priv = this->priv; PinosNode *node = PINOS_NODE (this); SpaResult res; SpaCommand cmd; - g_debug ("spa-v4l2-source %p: stopping pipeline", this); - - if (priv->running) { - priv->running = false; - pthread_join (priv->thread, NULL); - } + g_debug ("spa-v4l2-source %p: pause pipeline", this); cmd.type = SPA_COMMAND_PAUSE; if ((res = spa_node_send_command (node->node, &cmd)) < 0) g_debug ("got error %d", res); } +static void +suspend_pipeline (PinosSpaV4l2Source *this) +{ + PinosNode *node = PINOS_NODE (this); + SpaResult res; + + g_debug ("spa-v4l2-source %p: suspend pipeline", this); + + if ((res = spa_node_port_set_format (node->node, 0, 0, NULL)) < 0) { + g_warning ("error unset format output: %d", res); + } +} + static void destroy_pipeline (PinosSpaV4l2Source *this) { @@ -259,13 +266,14 @@ set_state (PinosNode *node, switch (state) { case PINOS_NODE_STATE_SUSPENDED: + suspend_pipeline (this); break; case PINOS_NODE_STATE_INITIALIZING: break; case PINOS_NODE_STATE_IDLE: - stop_pipeline (this); + pause_pipeline (this); break; case PINOS_NODE_STATE_RUNNING: diff --git a/pinos/server/link.c b/pinos/server/link.c index 8f3a75ba6..f4837a174 100644 --- a/pinos/server/link.c +++ b/pinos/server/link.c @@ -47,6 +47,7 @@ struct _PinosLinkPrivate gboolean active; gboolean negotiated; gboolean allocated; + gboolean started; PinosPort *output; PinosPort *input; @@ -227,14 +228,16 @@ do_negotiate (PinosLink *this) g_debug ("link %p: doing set format", this); + priv->negotiated = TRUE; + again: if ((res = spa_node_port_enum_formats (priv->input_node, priv->input_port, &filter, NULL, &istate)) < 0) { - g_warning ("error enum formats: %d", res); - return res; + g_warning ("error input enum formats: %d", res); + goto error; } spa_debug_format (filter); @@ -247,26 +250,30 @@ again: ostate = NULL; goto again; } - g_warning ("error enum formats: %d", res); - return res; + g_warning ("error output enum formats: %d", res); + goto error; } - spa_debug_format (format); - spa_format_fixate (format); + spa_debug_format (format); + if ((res = spa_node_port_set_format (priv->output_node, priv->output_port, 0, format)) < 0) { g_warning ("error set format output: %d", res); - return res; + goto error; } if ((res = spa_node_port_set_format (priv->input_node, priv->input_port, 0, format)) < 0) { g_warning ("error set format input: %d", res); - return res; + goto error; } - priv->negotiated = TRUE; - return SPA_RESULT_OK; + +error: + { + priv->negotiated = FALSE; + return res; + } } static SpaResult @@ -281,13 +288,15 @@ do_allocation (PinosLink *this) /* find out what's possible */ if ((res = spa_node_port_get_info (priv->output_node, priv->output_port, &oinfo)) < 0) { g_warning ("error get port info: %d", res); - return res; + goto error; } if ((res = spa_node_port_get_info (priv->input_node, priv->input_port, &iinfo)) < 0) { g_warning ("error get port info: %d", res); - return res; + goto error; } + priv->allocated = TRUE; + spa_debug_port_info (oinfo); spa_debug_port_info (iinfo); @@ -311,7 +320,7 @@ do_allocation (PinosLink *this) priv->in_buffers, &priv->n_in_buffers)) < 0) { g_warning ("error alloc buffers: %d", res); - return res; + goto error; } memcpy (priv->out_buffers, priv->in_buffers, priv->n_in_buffers * sizeof (SpaBuffer*)); priv->n_out_buffers = priv->n_in_buffers; @@ -321,7 +330,8 @@ do_allocation (PinosLink *this) in_flags = SPA_PORT_INFO_FLAG_CAN_ALLOC_BUFFERS; } else { g_warning ("error no common allocation found"); - return SPA_RESULT_ERROR; + res = SPA_RESULT_ERROR; + goto error; } if (in_flags & SPA_PORT_INFO_FLAG_CAN_ALLOC_BUFFERS) { @@ -329,7 +339,7 @@ do_allocation (PinosLink *this) oinfo->params, oinfo->n_params, priv->in_buffers, &priv->n_in_buffers)) < 0) { g_warning ("error alloc buffers: %d", res); - return res; + goto error; } priv->input->n_buffers = priv->n_in_buffers; priv->input->buffers = priv->in_buffers; @@ -339,7 +349,7 @@ do_allocation (PinosLink *this) iinfo->params, iinfo->n_params, priv->out_buffers, &priv->n_out_buffers)) < 0) { g_warning ("error alloc buffers: %d", res); - return res; + goto error; } priv->output->n_buffers = priv->n_out_buffers; priv->output->buffers = priv->out_buffers; @@ -348,7 +358,7 @@ do_allocation (PinosLink *this) if ((res = spa_node_port_use_buffers (priv->input_node, priv->input_port, priv->out_buffers, priv->n_out_buffers)) < 0) { g_warning ("error use buffers: %d", res); - return res; + goto error; } priv->input->n_buffers = priv->n_out_buffers; priv->input->buffers = priv->out_buffers; @@ -357,15 +367,19 @@ do_allocation (PinosLink *this) if ((res = spa_node_port_use_buffers (priv->output_node, priv->output_port, priv->in_buffers, priv->n_in_buffers)) < 0) { g_warning ("error use buffers: %d", res); - return res; + goto error; } priv->output->n_buffers = priv->n_in_buffers; priv->output->buffers = priv->in_buffers; } - priv->allocated = TRUE; - return SPA_RESULT_OK; + +error: + { + priv->allocated = FALSE; + return res; + } } static SpaResult @@ -375,6 +389,8 @@ do_start (PinosLink *this) SpaCommand cmd; SpaResult res; + priv->started = TRUE; + cmd.type = SPA_COMMAND_START; if ((res = spa_node_send_command (priv->input_node, &cmd)) < 0) g_warning ("got error %d", res); @@ -391,6 +407,8 @@ do_pause (PinosLink *this) SpaCommand cmd; SpaResult res; + priv->started = FALSE; + cmd.type = SPA_COMMAND_PAUSE; if ((res = spa_node_send_command (priv->input_node, &cmd)) < 0) g_warning ("got error %d", res); @@ -408,18 +426,21 @@ check_states (PinosLink *this) g_debug ("link %p: input %d, output %d", this, priv->input_state, priv->output_state); - if (priv->input_state == SPA_NODE_STATE_CONFIGURE && - priv->output_state == SPA_NODE_STATE_CONFIGURE && + if (priv->input_state >= SPA_NODE_STATE_CONFIGURE && + priv->output_state >= SPA_NODE_STATE_CONFIGURE && !priv->negotiated) { if ((res = do_negotiate (this)) < 0) return res; } - if (priv->input_state == SPA_NODE_STATE_READY && - priv->output_state == SPA_NODE_STATE_READY && + if (priv->input_state >= SPA_NODE_STATE_READY && + priv->output_state >= SPA_NODE_STATE_READY && !priv->allocated) { if ((res = do_allocation (this)) < 0) return res; - + } + if (priv->input_state >= SPA_NODE_STATE_PAUSED && + priv->output_state >= SPA_NODE_STATE_PAUSED && + !priv->started) { if ((res = do_start (this)) < 0) return res; } @@ -546,10 +567,15 @@ pinos_link_constructed (GObject * object) static void pinos_link_dispose (GObject * object) { - PinosLink *link = PINOS_LINK (object); - PinosLinkPrivate *priv = link->priv; + PinosLink *this = PINOS_LINK (object); + PinosLinkPrivate *priv = this->priv; - g_debug ("link %p: dispose", link); + g_debug ("link %p: dispose", this); + + g_signal_handlers_disconnect_by_data (priv->input, this); + g_signal_handlers_disconnect_by_data (priv->output, this); + g_signal_handlers_disconnect_by_data (priv->input->node, this); + g_signal_handlers_disconnect_by_data (priv->output->node, this); pinos_port_remove_send_cb (priv->input, priv->input_id); pinos_port_remove_send_cb (priv->output, priv->output_id); @@ -560,7 +586,7 @@ pinos_link_dispose (GObject * object) } priv->input = NULL; priv->output = NULL; - link_unregister_object (link); + link_unregister_object (this); G_OBJECT_CLASS (pinos_link_parent_class)->dispose (object); } diff --git a/spa/include/spa/audio/format.h b/spa/include/spa/audio/format.h index f4198c4f7..17f5505b6 100644 --- a/spa/include/spa/audio/format.h +++ b/spa/include/spa/audio/format.h @@ -39,6 +39,10 @@ typedef enum { SPA_PROP_ID_AUDIO_RAW_INFO, } SpaPropIdAudio; +SpaResult spa_prop_info_fill_audio (SpaPropInfo *info, + SpaPropIdAudio id, + size_t offset); + struct _SpaAudioRawFormat { SpaFormat format; SpaAudioRawInfo info; @@ -48,10 +52,6 @@ SpaResult spa_audio_raw_format_init (SpaAudioRawFormat *format); SpaResult spa_audio_raw_format_parse (const SpaFormat *format, SpaAudioRawFormat *rawformat); -SpaResult spa_audio_raw_fill_prop_info (SpaPropInfo *info, - SpaPropIdAudio id, - size_t offset); - #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/spa/include/spa/control.h b/spa/include/spa/control.h index 4d980354f..e643989a7 100644 --- a/spa/include/spa/control.h +++ b/spa/include/spa/control.h @@ -81,10 +81,9 @@ typedef enum { SPA_CONTROL_CMD_ADD_MEM = 64, SPA_CONTROL_CMD_REMOVE_MEM = 65, - SPA_CONTROL_CMD_ADD_BUFFER = 66, - SPA_CONTROL_CMD_REMOVE_BUFFER = 67, - SPA_CONTROL_CMD_PROCESS_BUFFER = 68, - SPA_CONTROL_CMD_REUSE_BUFFER = 69, + SPA_CONTROL_CMD_USE_BUFFERS = 66, + SPA_CONTROL_CMD_PROCESS_BUFFER = 67, + SPA_CONTROL_CMD_REUSE_BUFFER = 68, } SpaControlCmd; @@ -184,18 +183,12 @@ typedef struct { SpaMemoryRef mem; } SpaControlCmdRemoveMem; -/* SPA_CONTROL_CMD_ADD_BUFFER */ +/* SPA_CONTROL_CMD_USE_BUFFERS */ typedef struct { - uint32_t port_id; - uint32_t buffer_id; - SpaMemoryChunk mem; -} SpaControlCmdAddBuffer; - -/* SPA_CONTROL_CMD_REMOVE_BUFFER */ -typedef struct { - uint32_t port_id; - uint32_t buffer_id; -} SpaControlCmdRemoveBuffer; + uint32_t port_id; + unsigned int n_buffers; + SpaBuffer **buffers; +} SpaControlCmdUseBuffers; /* SPA_CONTROL_CMD_PROCESS_BUFFER */ typedef struct { diff --git a/spa/include/spa/props.h b/spa/include/spa/props.h index 180b5aedd..a6421a617 100644 --- a/spa/include/spa/props.h +++ b/spa/include/spa/props.h @@ -114,6 +114,7 @@ typedef struct { /** * SpaPropInfo: * @id: unique id + * @offset: offset in structure with data * @name: human readable name * @description: description of the property * @flags: property flags @@ -123,10 +124,10 @@ typedef struct { * @n_range_values: number of elements in @range_values * @range_values: array of possible values * @tags: extra tags, NULL terminated - * @offset: offset in structure with data */ typedef struct { uint32_t id; + size_t offset; const char *name; const char *description; SpaPropFlags flags; @@ -136,7 +137,6 @@ typedef struct { unsigned int n_range_values; const SpaPropRangeInfo *range_values; const char **tags; - size_t offset; } SpaPropInfo; typedef struct { diff --git a/spa/include/spa/video/encoded.h b/spa/include/spa/video/encoded.h new file mode 100644 index 000000000..5b5148d28 --- /dev/null +++ b/spa/include/spa/video/encoded.h @@ -0,0 +1,42 @@ +/* Simple Plugin API + * Copyright (C) 2016 Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __SPA_VIDEO_ENCODED_H__ +#define __SPA_VIDEO_ENCODED_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct _SpaVideoInfoJPEG SpaVideoInfoJPEG; + +#include +#include + +struct _SpaVideoInfoJPEG { + SpaRectangle size; + SpaFraction framerate; + SpaFraction max_framerate; +}; + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* __SPA_VIDEO_ENCODED_H__ */ diff --git a/spa/include/spa/video/format.h b/spa/include/spa/video/format.h index eb8b468af..606dd55f6 100644 --- a/spa/include/spa/video/format.h +++ b/spa/include/spa/video/format.h @@ -26,8 +26,9 @@ extern "C" { #include #include +#include -typedef struct _SpaVideoRawFormat SpaVideoRawFormat; +typedef struct _SpaFormatVideo SpaFormatVideo; typedef enum { SPA_PROP_ID_VIDEO_FORMAT = SPA_PROP_ID_MEDIA_CUSTOM_START, @@ -47,20 +48,24 @@ typedef enum { SPA_PROP_ID_VIDEO_RAW_INFO, } SpaPropIdVideo; -struct _SpaVideoRawFormat { +SpaResult spa_prop_info_fill_video (SpaPropInfo *info, + SpaPropIdVideo id, + size_t offset); + +SpaResult spa_format_video_init (SpaMediaType type, + SpaMediaSubType subtype, + SpaFormatVideo *format); +SpaResult spa_format_video_parse (const SpaFormat *format, + SpaFormatVideo *dest); + +struct _SpaFormatVideo { SpaFormat format; - SpaVideoRawInfo info; + union { + SpaVideoInfoRaw raw; + SpaVideoInfoJPEG jpeg; + } info; }; -SpaResult spa_video_raw_format_init (SpaVideoRawFormat *format); -SpaResult spa_video_raw_format_parse (const SpaFormat *format, - SpaVideoRawFormat *rawformat); - -SpaResult spa_video_raw_fill_default_info (SpaVideoRawInfo *info); -SpaResult spa_video_raw_fill_prop_info (SpaPropInfo *info, - SpaPropIdVideo id, - size_t offset); - #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/spa/include/spa/video/raw.h b/spa/include/spa/video/raw.h index 17c2f4b54..93155a766 100644 --- a/spa/include/spa/video/raw.h +++ b/spa/include/spa/video/raw.h @@ -24,7 +24,7 @@ extern "C" { #endif -typedef struct _SpaVideoRawInfo SpaVideoRawInfo; +typedef struct _SpaVideoInfoRaw SpaVideoInfoRaw; #include #include @@ -146,7 +146,7 @@ typedef enum { } SpaVideoInterlaceMode; /** - * SpaVideoRawInfo: + * SpaVideoInfoRaw: * @format: the format * @size: the frame size of the video * @framerate: the framerate of the video 0/1 means variable rate @@ -165,7 +165,7 @@ typedef enum { * @transfer_function: the transfer function. used to convert between R'G'B' and RGB * @color_primaries: color primaries. used to convert between R'G'B' and CIE XYZ */ -struct _SpaVideoRawInfo { +struct _SpaVideoInfoRaw { SpaVideoFormat format; SpaRectangle size; SpaFraction framerate; diff --git a/spa/lib/audio-raw.c b/spa/lib/audio-raw.c index 560de9677..d96dfadae 100644 --- a/spa/lib/audio-raw.c +++ b/spa/lib/audio-raw.c @@ -135,55 +135,95 @@ static const SpaPropRangeInfo uint32_range[] = { { "max", "Maximum value", 4, &max_uint32 }, }; -static const SpaPropInfo raw_format_prop_info[] = +static const SpaPropInfo format_prop_info[] = { - { SPA_PROP_ID_AUDIO_FORMAT, "format", "The media format", + { SPA_PROP_ID_AUDIO_FORMAT, 0, + "format", "The media format", SPA_PROP_FLAG_READWRITE, SPA_PROP_TYPE_UINT32, sizeof (uint32_t), SPA_PROP_RANGE_TYPE_ENUM, SPA_N_ELEMENTS (format_format_range), format_format_range, - NULL, - offsetof (SpaAudioRawFormat, info.format) }, - { SPA_PROP_ID_AUDIO_FLAGS, "flags", "Sample Flags", + NULL }, + { SPA_PROP_ID_AUDIO_FLAGS, 0, + "flags", "Sample Flags", SPA_PROP_FLAG_READWRITE, SPA_PROP_TYPE_UINT32, sizeof (uint32_t), SPA_PROP_RANGE_TYPE_FLAGS, SPA_N_ELEMENTS (flags_range), flags_range, - NULL, - offsetof (SpaAudioRawFormat, info.flags) }, - { SPA_PROP_ID_AUDIO_LAYOUT, "layout", "Sample Layout", + NULL }, + { SPA_PROP_ID_AUDIO_LAYOUT, 0, + "layout", "Sample Layout", SPA_PROP_FLAG_READWRITE, SPA_PROP_TYPE_UINT32, sizeof (uint32_t), SPA_PROP_RANGE_TYPE_ENUM, SPA_N_ELEMENTS (layouts_range), layouts_range, - NULL, - offsetof (SpaAudioRawFormat, info.layout) }, - { SPA_PROP_ID_AUDIO_RATE, "rate", "Audio sample rate", + NULL }, + { SPA_PROP_ID_AUDIO_RATE, 0, + "rate", "Audio sample rate", SPA_PROP_FLAG_READWRITE, SPA_PROP_TYPE_UINT32, sizeof (uint32_t), SPA_PROP_RANGE_TYPE_MIN_MAX, 2, uint32_range, - NULL, - offsetof (SpaAudioRawFormat, info.rate) }, - { SPA_PROP_ID_AUDIO_CHANNELS, "channels", "Audio channels", + NULL }, + { SPA_PROP_ID_AUDIO_CHANNELS, 0, + "channels", "Audio channels", SPA_PROP_FLAG_READWRITE, SPA_PROP_TYPE_UINT32, sizeof (uint32_t), SPA_PROP_RANGE_TYPE_MIN_MAX, 2, uint32_range, - NULL, - offsetof (SpaAudioRawFormat, info.channels) }, - { SPA_PROP_ID_AUDIO_CHANNEL_MASK, "channel-mask", "Audio channel mask", + NULL }, + { SPA_PROP_ID_AUDIO_CHANNEL_MASK, 0, + "channel-mask", "Audio channel mask", SPA_PROP_FLAG_READWRITE, SPA_PROP_TYPE_BITMASK, sizeof (uint32_t), SPA_PROP_RANGE_TYPE_NONE, 0, NULL, - NULL, - offsetof (SpaAudioRawFormat, info.channel_mask) }, - { SPA_PROP_ID_AUDIO_RAW_INFO, "info", "the SpaAudioRawInfo structure", + NULL }, + { SPA_PROP_ID_AUDIO_RAW_INFO, 0, + "info", "the SpaAudioRawInfo structure", SPA_PROP_FLAG_READWRITE, SPA_PROP_TYPE_POINTER, sizeof (SpaAudioRawInfo), SPA_PROP_RANGE_TYPE_NONE, 0, NULL, - NULL, - offsetof (SpaAudioRawFormat, info) }, + NULL }, }; +SpaResult +spa_prop_info_fill_audio (SpaPropInfo *info, + SpaPropIdAudio id, + size_t offset) +{ + unsigned int i; + + if (info == NULL) + return SPA_RESULT_INVALID_ARGUMENTS; + + for (i = 0; i < SPA_N_ELEMENTS (format_prop_info); i++) { + if (format_prop_info[i].id == id) { + memcpy (info, &format_prop_info[i], sizeof (SpaPropInfo)); + info->offset = offset; + return SPA_RESULT_OK; + } + } + return SPA_RESULT_INVALID_PROPERTY_INDEX; +} + SpaResult spa_audio_raw_format_init (SpaAudioRawFormat *format) { + static SpaPropInfo raw_format_prop_info[] = + { + { SPA_PROP_ID_AUDIO_FORMAT, offsetof (SpaAudioRawFormat, info.format), }, + { SPA_PROP_ID_AUDIO_FLAGS, offsetof (SpaAudioRawFormat, info.flags), }, + { SPA_PROP_ID_AUDIO_LAYOUT, offsetof (SpaAudioRawFormat, info.layout), }, + { SPA_PROP_ID_AUDIO_RATE, offsetof (SpaAudioRawFormat, info.rate), }, + { SPA_PROP_ID_AUDIO_CHANNELS, offsetof (SpaAudioRawFormat, info.channels), }, + { SPA_PROP_ID_AUDIO_CHANNEL_MASK, offsetof (SpaAudioRawFormat, info.channel_mask), }, + { SPA_PROP_ID_AUDIO_RAW_INFO, offsetof (SpaAudioRawFormat, info), }, + }; + + if (raw_format_prop_info[0].name == NULL) { + int i; + + for (i = 0; i < SPA_N_ELEMENTS (raw_format_prop_info); i++) + spa_prop_info_fill_audio (&raw_format_prop_info[i], + raw_format_prop_info[i].id, + raw_format_prop_info[i].offset); + } + format->format.media_type = SPA_MEDIA_TYPE_AUDIO; format->format.media_subtype = SPA_MEDIA_SUBTYPE_RAW; format->format.props.n_prop_info = SPA_N_ELEMENTS (raw_format_prop_info); @@ -227,23 +267,3 @@ fallback: return res; } - -SpaResult -spa_audio_raw_fill_prop_info (SpaPropInfo *info, - SpaPropIdAudio id, - size_t offset) -{ - unsigned int i; - - if (info == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; - - for (i = 0; i < SPA_N_ELEMENTS (raw_format_prop_info); i++) { - if (raw_format_prop_info[i].id == id) { - memcpy (info, &raw_format_prop_info[i], sizeof (SpaPropInfo)); - info->offset = offset; - return SPA_RESULT_OK; - } - } - return SPA_RESULT_INVALID_PROPERTY_INDEX; -} diff --git a/spa/lib/control.c b/spa/lib/control.c index a4887dc41..3591ee80e 100644 --- a/spa/lib/control.c +++ b/spa/lib/control.c @@ -456,6 +456,27 @@ iter_parse_set_format (struct stack_iter *si, SpaControlCmdSetFormat *cmd) cmd->format = parse_format (mem, p, SPA_PTR_TO_INT (cmd->format)); } +static void +iter_parse_use_buffers (struct stack_iter *si, SpaControlCmdUseBuffers *cmd) +{ + void *p; + int i; + + p = si->data; + memcpy (cmd, p, sizeof (SpaControlCmdUseBuffers)); + if (cmd->buffers) + cmd->buffers = SPA_MEMBER (p, SPA_PTR_TO_INT (cmd->buffers), SpaBuffer *); + for (i = 0; i < cmd->n_buffers; i++) { + SpaMemoryChunk *mc; + SpaMemory *mem; + + mc = SPA_MEMBER (p, SPA_PTR_TO_INT (cmd->buffers[i]), SpaMemoryChunk); + mem = spa_memory_find (&mc->mem); + + cmd->buffers[i] = SPA_MEMBER (spa_memory_ensure_ptr (mem), mc->offset, SpaBuffer); + } +} + SpaResult spa_control_iter_parse_cmd (SpaControlIter *iter, void *command) @@ -542,16 +563,8 @@ spa_control_iter_parse_cmd (SpaControlIter *iter, memcpy (command, si->data, sizeof (SpaControlCmdRemoveMem)); break; - case SPA_CONTROL_CMD_ADD_BUFFER: - if (si->size < sizeof (SpaControlCmdAddBuffer)) - return SPA_RESULT_ERROR; - memcpy (command, si->data, sizeof (SpaControlCmdAddBuffer)); - break; - - case SPA_CONTROL_CMD_REMOVE_BUFFER: - if (si->size < sizeof (SpaControlCmdRemoveBuffer)) - return SPA_RESULT_ERROR; - memcpy (command, si->data, sizeof (SpaControlCmdRemoveBuffer)); + case SPA_CONTROL_CMD_USE_BUFFERS: + iter_parse_use_buffers (si, command); break; case SPA_CONTROL_CMD_PROCESS_BUFFER: @@ -1077,6 +1090,41 @@ builder_add_set_format (struct stack_builder *sb, SpaControlCmdSetFormat *sf) sf->format = SPA_INT_TO_PTR (SPA_PTRDIFF (p, sf)); } +static void +builder_add_use_buffers (struct stack_builder *sb, SpaControlCmdUseBuffers *ub) +{ + size_t len; + void *p; + int i; + SpaMemoryChunk **bmc; + SpaControlCmdUseBuffers *d; + + /* calculate length */ + /* port_id + format + mask */ + len = sizeof (SpaControlCmdUseBuffers); + len += ub->n_buffers * sizeof (SpaBuffer *); + len += ub->n_buffers * sizeof (SpaMemoryChunk); + + p = builder_add_cmd (sb, SPA_CONTROL_CMD_USE_BUFFERS, len); + memcpy (p, ub, sizeof (SpaControlCmdUseBuffers)); + d = p; + + p = SPA_MEMBER (d, sizeof (SpaControlCmdUseBuffers), void); + bmc = p; + + if (d->n_buffers) + d->buffers = SPA_INT_TO_PTR (SPA_PTRDIFF (bmc, d)); + else + d->buffers = 0; + + p = SPA_MEMBER (p, sizeof (SpaMemoryChunk*) * ub->n_buffers, void); + for (i = 0; i < ub->n_buffers; i++) { + memcpy (p, &ub->buffers[i]->mem, sizeof (SpaMemoryChunk)); + bmc[i] = SPA_INT_TO_PTR (SPA_PTRDIFF (p, d)); + p = SPA_MEMBER (p, sizeof (SpaMemoryChunk), void); + } +} + /** * spa_control_builder_add_cmd: * @builder: a #SpaControlBuilder @@ -1168,14 +1216,8 @@ spa_control_builder_add_cmd (SpaControlBuilder *builder, memcpy (p, command, sizeof (SpaControlCmdRemoveMem)); break; - case SPA_CONTROL_CMD_ADD_BUFFER: - p = builder_add_cmd (sb, cmd, sizeof (SpaControlCmdAddBuffer)); - memcpy (p, command, sizeof (SpaControlCmdAddBuffer)); - break; - - case SPA_CONTROL_CMD_REMOVE_BUFFER: - p = builder_add_cmd (sb, cmd, sizeof (SpaControlCmdRemoveBuffer)); - memcpy (p, command, sizeof (SpaControlCmdRemoveBuffer)); + case SPA_CONTROL_CMD_USE_BUFFERS: + builder_add_use_buffers (sb, command); break; case SPA_CONTROL_CMD_PROCESS_BUFFER: diff --git a/spa/lib/debug.c b/spa/lib/debug.c index a29f16146..6a199c32d 100644 --- a/spa/lib/debug.c +++ b/spa/lib/debug.c @@ -169,18 +169,31 @@ spa_debug_dump_mem (const void *mem, size_t size) struct media_type_name { const char *name; } media_type_names[] = { - { "unknown" }, + { "invalid" }, { "audio" }, { "video" }, + { "image" }, }; struct media_subtype_name { const char *name; } media_subtype_names[] = { - { "unknown" }, + { "invalid" }, { "raw" }, { "h264" }, { "mjpg" }, + { "dv" }, + { "mpegts" }, + { "h263" }, + { "mpeg1" }, + { "mpeg2" }, + { "mpeg4" }, + { "xvid" }, + { "vc1" }, + { "vp8" }, + { "vp9" }, + { "jpeg" }, + { "bayer" }, }; struct prop_type_name { @@ -330,7 +343,7 @@ spa_debug_props (const SpaProps *props, bool print_ranges) res = spa_props_get_prop (props, i, &value); - fprintf (stderr, ". Current: "); + fprintf (stderr, "Current: "); if (res == SPA_RESULT_OK) print_value (info, value.size, value.value); else if (res == SPA_RESULT_PROPERTY_UNSET) @@ -386,14 +399,25 @@ spa_debug_format (const SpaFormat *format) { const SpaProps *props; int i; + const char *media_type; + const char *media_subtype; if (format == NULL) return SPA_RESULT_INVALID_ARGUMENTS; props = &format->props; - fprintf (stderr, "%-6s %s/%s\n", "", media_type_names[format->media_type].name, - media_subtype_names[format->media_subtype].name); + if (format->media_type > 0 && format->media_type < SPA_N_ELEMENTS (media_type_names)) + media_type = media_type_names[format->media_type].name; + else + media_type = "unknown"; + + if (format->media_subtype > 0 && format->media_subtype < SPA_N_ELEMENTS (media_subtype_names)) + media_subtype = media_subtype_names[format->media_subtype].name; + else + media_subtype = "unknown"; + + fprintf (stderr, "%-6s %s/%s\n", "", media_type, media_subtype); for (i = 0; i < props->n_prop_info; i++) { const SpaPropInfo *info = &props->prop_info[i]; diff --git a/spa/lib/video-raw.c b/spa/lib/video-raw.c index 5ed1458b4..b02125003 100644 --- a/spa/lib/video-raw.c +++ b/spa/lib/video-raw.c @@ -25,7 +25,7 @@ #include #include -static const SpaVideoRawInfo default_info = { +static const SpaVideoInfoRaw default_raw_info = { SPA_VIDEO_FORMAT_UNKNOWN, { 320, 240 }, { 0, 1 }, @@ -371,175 +371,193 @@ static const SpaPropRangeInfo framerate_range[] = { { "max", "Maximum value", sizeof (SpaFraction), &max_framerate }, }; -static const SpaPropInfo raw_format_prop_info[] = +static const SpaPropInfo format_prop_info[] = { - { SPA_PROP_ID_VIDEO_FORMAT, "format", "The media format", + { SPA_PROP_ID_VIDEO_FORMAT, 0, + "format", "The media format", SPA_PROP_FLAG_READWRITE, SPA_PROP_TYPE_UINT32, sizeof (uint32_t), SPA_PROP_RANGE_TYPE_ENUM, SPA_N_ELEMENTS (format_range), format_range, - NULL, - offsetof (SpaVideoRawFormat, info.format) }, - { SPA_PROP_ID_VIDEO_SIZE, "size", "Video size", + NULL }, + { SPA_PROP_ID_VIDEO_SIZE, 0, + "size", "Video size", SPA_PROP_FLAG_READWRITE, SPA_PROP_TYPE_RECTANGLE, sizeof (SpaRectangle), SPA_PROP_RANGE_TYPE_MIN_MAX, 2, size_range, - NULL, - offsetof (SpaVideoRawFormat, info.size) }, - { SPA_PROP_ID_VIDEO_FRAMERATE, "framerate", "Video framerate", + NULL }, + { SPA_PROP_ID_VIDEO_FRAMERATE, 0, + "framerate", "Video framerate", SPA_PROP_FLAG_READWRITE, SPA_PROP_TYPE_FRACTION, sizeof (SpaFraction), SPA_PROP_RANGE_TYPE_MIN_MAX, 2, framerate_range, - NULL, - offsetof (SpaVideoRawFormat, info.framerate) }, - { SPA_PROP_ID_VIDEO_MAX_FRAMERATE, "max-framerate", "Video max framerate", + NULL }, + { SPA_PROP_ID_VIDEO_MAX_FRAMERATE, 0, + "max-framerate", "Video max framerate", SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL, SPA_PROP_TYPE_FRACTION, sizeof (SpaFraction), SPA_PROP_RANGE_TYPE_MIN_MAX, 2, framerate_range, - NULL, - offsetof (SpaVideoRawFormat, info.max_framerate) }, - { SPA_PROP_ID_VIDEO_VIEWS, "views", "Video number of views", + NULL }, + { SPA_PROP_ID_VIDEO_VIEWS, 0, + "views", "Video number of views", SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL, SPA_PROP_TYPE_UINT32, sizeof (uint32_t), SPA_PROP_RANGE_TYPE_MIN_MAX, 2, uint32_range, - NULL, - offsetof (SpaVideoRawFormat, info.views) }, - { SPA_PROP_ID_VIDEO_INTERLACE_MODE, "interlace-mode", "Interlace mode", + NULL }, + { SPA_PROP_ID_VIDEO_INTERLACE_MODE, 0, + "interlace-mode", "Interlace mode", SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL, SPA_PROP_TYPE_UINT32, sizeof (uint32_t), SPA_PROP_RANGE_TYPE_ENUM, SPA_N_ELEMENTS (interlace_mode_range), interlace_mode_range, - NULL, - offsetof (SpaVideoRawFormat, info.interlace_mode) }, - { SPA_PROP_ID_VIDEO_PIXEL_ASPECT_RATIO, "pixel-aspect-ratio", "Video pixel aspect ratio", + NULL }, + { SPA_PROP_ID_VIDEO_PIXEL_ASPECT_RATIO, 0, + "pixel-aspect-ratio", "Video pixel aspect ratio", SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL, SPA_PROP_TYPE_FRACTION, sizeof (SpaFraction), SPA_PROP_RANGE_TYPE_MIN_MAX, 2, framerate_range, - NULL, - offsetof (SpaVideoRawFormat, info.pixel_aspect_ratio) }, - { SPA_PROP_ID_VIDEO_MULTIVIEW_MODE, "multiview-mode", "Multiview mode", + NULL }, + { SPA_PROP_ID_VIDEO_MULTIVIEW_MODE, 0, + "multiview-mode", "Multiview mode", SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL, SPA_PROP_TYPE_UINT32, sizeof (uint32_t), SPA_PROP_RANGE_TYPE_ENUM, SPA_N_ELEMENTS (multiview_mode_range), multiview_mode_range, - NULL, - offsetof (SpaVideoRawFormat, info.multiview_mode) }, - { SPA_PROP_ID_VIDEO_MULTIVIEW_FLAGS, "multiview-flags", "Multiview flags", + NULL }, + { SPA_PROP_ID_VIDEO_MULTIVIEW_FLAGS, 0, + "multiview-flags", "Multiview flags", SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL, SPA_PROP_TYPE_UINT32, sizeof (uint32_t), SPA_PROP_RANGE_TYPE_FLAGS, SPA_N_ELEMENTS (multiview_flags_range), multiview_flags_range, - NULL, - offsetof (SpaVideoRawFormat, info.multiview_flags) }, - { SPA_PROP_ID_VIDEO_CHROMA_SITE, "chroma-site", "Chroma site", + NULL }, + { SPA_PROP_ID_VIDEO_CHROMA_SITE, 0, + "chroma-site", "Chroma site", SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL, SPA_PROP_TYPE_UINT32, sizeof (uint32_t), SPA_PROP_RANGE_TYPE_FLAGS, SPA_N_ELEMENTS (chroma_site_range), chroma_site_range, - NULL, - offsetof (SpaVideoRawFormat, info.chroma_site) }, - { SPA_PROP_ID_VIDEO_COLOR_RANGE, "color-range", "Color range", + NULL }, + { SPA_PROP_ID_VIDEO_COLOR_RANGE, 0, + "color-range", "Color range", SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL, SPA_PROP_TYPE_UINT32, sizeof (uint32_t), SPA_PROP_RANGE_TYPE_ENUM, SPA_N_ELEMENTS (color_range_range), color_range_range, - NULL, - offsetof (SpaVideoRawFormat, info.color_range) }, - { SPA_PROP_ID_VIDEO_COLOR_MATRIX, "color-matrix", "Color matrix", + NULL }, + { SPA_PROP_ID_VIDEO_COLOR_MATRIX, 0, + "color-matrix", "Color matrix", SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL, SPA_PROP_TYPE_UINT32, sizeof (uint32_t), SPA_PROP_RANGE_TYPE_ENUM, SPA_N_ELEMENTS (color_matrix_range), color_matrix_range, - NULL, - offsetof (SpaVideoRawFormat, info.color_matrix) }, - { SPA_PROP_ID_VIDEO_TRANSFER_FUNCTION, "transfer-function", "Transfer function", + NULL }, + { SPA_PROP_ID_VIDEO_TRANSFER_FUNCTION, 0, + "transfer-function", "Transfer function", SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL, SPA_PROP_TYPE_UINT32, sizeof (uint32_t), SPA_PROP_RANGE_TYPE_ENUM, SPA_N_ELEMENTS (transfer_function_range), transfer_function_range, - NULL, - offsetof (SpaVideoRawFormat, info.transfer_function) }, - { SPA_PROP_ID_VIDEO_COLOR_PRIMARIES, "color-primaries", "Color primaries", + NULL }, + { SPA_PROP_ID_VIDEO_COLOR_PRIMARIES, 0, + "color-primaries", "Color primaries", SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL, SPA_PROP_TYPE_UINT32, sizeof (uint32_t), SPA_PROP_RANGE_TYPE_ENUM, SPA_N_ELEMENTS (color_primaries_range), color_primaries_range, - NULL, - offsetof (SpaVideoRawFormat, info.color_primaries) }, - { SPA_PROP_ID_VIDEO_RAW_INFO, "info", "the SpaVideoRawInfo structure", + NULL }, + { SPA_PROP_ID_VIDEO_RAW_INFO, 0, + "info", "the SpaVideoRawInfo structure", SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL, - SPA_PROP_TYPE_POINTER, sizeof (SpaVideoRawInfo), + SPA_PROP_TYPE_POINTER, sizeof (SpaVideoInfoRaw), SPA_PROP_RANGE_TYPE_NONE, 0, NULL, - NULL, - offsetof (SpaVideoRawFormat, info) }, + NULL }, }; SpaResult -spa_video_raw_format_init (SpaVideoRawFormat *format) +spa_prop_info_fill_video (SpaPropInfo *info, + SpaPropIdVideo id, + size_t offset) { - format->format.media_type = SPA_MEDIA_TYPE_VIDEO; - format->format.media_subtype = SPA_MEDIA_SUBTYPE_RAW; - format->format.props.n_prop_info = SPA_N_ELEMENTS (raw_format_prop_info); - format->format.props.prop_info = raw_format_prop_info; - format->format.props.unset_mask = (1 << 14)-1; - format->info = default_info; + int i; + + if (info == NULL) + return SPA_RESULT_INVALID_ARGUMENTS; + + i = id - SPA_PROP_ID_MEDIA_CUSTOM_START; + + if (i < 0 || i >= SPA_N_ELEMENTS (format_prop_info)) + return SPA_RESULT_INVALID_PROPERTY_INDEX; + + memcpy (info, &format_prop_info[i], sizeof (SpaPropInfo)); + info->offset = offset; return SPA_RESULT_OK; } SpaResult -spa_video_raw_format_parse (const SpaFormat *format, - SpaVideoRawFormat *rawformat) +spa_format_video_init (SpaMediaType type, + SpaMediaSubType subtype, + SpaFormatVideo *format) +{ + static SpaPropInfo raw_format_prop_info[] = { + { SPA_PROP_ID_VIDEO_FORMAT, offsetof (SpaFormatVideo, info.raw.format) }, + { SPA_PROP_ID_VIDEO_SIZE, offsetof (SpaFormatVideo, info.raw.size) }, + { SPA_PROP_ID_VIDEO_FRAMERATE, offsetof (SpaFormatVideo, info.raw.framerate) }, + { SPA_PROP_ID_VIDEO_MAX_FRAMERATE, offsetof (SpaFormatVideo, info.raw.max_framerate) }, + { SPA_PROP_ID_VIDEO_VIEWS, offsetof (SpaFormatVideo, info.raw.views) }, + { SPA_PROP_ID_VIDEO_INTERLACE_MODE, offsetof (SpaFormatVideo, info.raw.interlace_mode) }, + { SPA_PROP_ID_VIDEO_PIXEL_ASPECT_RATIO, offsetof (SpaFormatVideo, info.raw.pixel_aspect_ratio) }, + { SPA_PROP_ID_VIDEO_MULTIVIEW_MODE, offsetof (SpaFormatVideo, info.raw.multiview_mode) }, + { SPA_PROP_ID_VIDEO_MULTIVIEW_FLAGS, offsetof (SpaFormatVideo, info.raw.multiview_flags) }, + { SPA_PROP_ID_VIDEO_CHROMA_SITE, offsetof (SpaFormatVideo, info.raw.chroma_site) }, + { SPA_PROP_ID_VIDEO_COLOR_RANGE, offsetof (SpaFormatVideo, info.raw.color_range) }, + { SPA_PROP_ID_VIDEO_COLOR_MATRIX, offsetof (SpaFormatVideo, info.raw.color_matrix) }, + { SPA_PROP_ID_VIDEO_TRANSFER_FUNCTION, offsetof (SpaFormatVideo, info.raw.transfer_function) }, + { SPA_PROP_ID_VIDEO_COLOR_PRIMARIES, offsetof (SpaFormatVideo, info.raw.color_primaries) }, + { SPA_PROP_ID_VIDEO_RAW_INFO, offsetof (SpaFormatVideo, info.raw ) }, + }; + + if (raw_format_prop_info[0].name == NULL) { + int i; + for (i = 0; i < SPA_N_ELEMENTS (raw_format_prop_info); i++) + spa_prop_info_fill_video (&raw_format_prop_info[i], + raw_format_prop_info[i].id, + raw_format_prop_info[i].offset); + } + + format->format.media_type = type; + format->format.media_subtype = subtype; + format->format.props.n_prop_info = SPA_N_ELEMENTS (raw_format_prop_info); + format->format.props.prop_info = raw_format_prop_info; + format->format.props.unset_mask = (1 << 14)-1; + format->info.raw = default_raw_info; + + return SPA_RESULT_OK; +} + +SpaResult +spa_format_video_parse (const SpaFormat *format, + SpaFormatVideo *vformat) { SpaPropValue value; const SpaProps *props; SpaResult res; - if ((void *)format == (void *)rawformat) + if ((void *)format == (void *)vformat) return SPA_RESULT_OK; - if (format->media_type != SPA_MEDIA_TYPE_VIDEO || - format->media_subtype != SPA_MEDIA_SUBTYPE_RAW) + if (format->media_type != SPA_MEDIA_TYPE_VIDEO) return SPA_RESULT_INVALID_MEDIA_TYPE; - spa_video_raw_format_init (rawformat); + spa_format_video_init (format->media_type, + format->media_subtype, + vformat); props = &format->props; if ((res = spa_props_get_prop (props, spa_props_index_for_id (props, SPA_PROP_ID_VIDEO_RAW_INFO), &value)) < 0) goto fallback; - if (value.type != SPA_PROP_TYPE_POINTER || value.size != sizeof (SpaVideoRawInfo)) + if (value.type != SPA_PROP_TYPE_POINTER) goto fallback; - memcpy (&rawformat->info, value.value, sizeof (SpaVideoRawInfo)); + memcpy (&vformat->info, value.value, value.size); return SPA_RESULT_OK; fallback: - res = spa_props_copy (props, &rawformat->format.props); + res = spa_props_copy (props, &vformat->format.props); return res; } - -SpaResult -spa_video_raw_fill_default_info (SpaVideoRawInfo *info) -{ - if (info == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; - - memcpy (info, &default_info, sizeof (SpaVideoRawInfo)); - - return SPA_RESULT_OK; -} - - -SpaResult -spa_video_raw_fill_prop_info (SpaPropInfo *info, - SpaPropIdVideo id, - size_t offset) -{ - unsigned int i; - - if (info == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; - - for (i = 0; i < SPA_N_ELEMENTS (raw_format_prop_info); i++) { - if (raw_format_prop_info[i].id == id) { - memcpy (info, &raw_format_prop_info[i], sizeof (SpaPropInfo)); - info->offset = offset; - return SPA_RESULT_OK; - } - } - return SPA_RESULT_INVALID_PROPERTY_INDEX; -} diff --git a/spa/plugins/alsa/alsa-sink.c b/spa/plugins/alsa/alsa-sink.c index d0141cc30..d8f23e0ff 100644 --- a/spa/plugins/alsa/alsa-sink.c +++ b/spa/plugins/alsa/alsa-sink.c @@ -123,42 +123,42 @@ enum { static const SpaPropInfo prop_info[] = { - { PROP_ID_DEVICE, "device", "ALSA device, as defined in an asound configuration file", + { PROP_ID_DEVICE, offsetof (SpaALSASinkProps, device), + "device", "ALSA device, as defined in an asound configuration file", SPA_PROP_FLAG_READWRITE, SPA_PROP_TYPE_STRING, 63, SPA_PROP_RANGE_TYPE_NONE, 0, NULL, - NULL, - offsetof (SpaALSASinkProps, device) }, - { PROP_ID_DEVICE_NAME, "device-name", "Human-readable name of the sound device", + NULL }, + { PROP_ID_DEVICE_NAME, offsetof (SpaALSASinkProps, device_name), + "device-name", "Human-readable name of the sound device", SPA_PROP_FLAG_READABLE, SPA_PROP_TYPE_STRING, 127, SPA_PROP_RANGE_TYPE_NONE, 0, NULL, - NULL, - offsetof (SpaALSASinkProps, device_name) }, - { PROP_ID_CARD_NAME, "card-name", "Human-readable name of the sound card", + NULL }, + { PROP_ID_CARD_NAME, offsetof (SpaALSASinkProps, card_name), + "card-name", "Human-readable name of the sound card", SPA_PROP_FLAG_READABLE, SPA_PROP_TYPE_STRING, 127, SPA_PROP_RANGE_TYPE_NONE, 0, NULL, - NULL, - offsetof (SpaALSASinkProps, card_name) }, - { PROP_ID_BUFFER_TIME, "buffer-time", "The total size of the buffer in time", + NULL }, + { PROP_ID_BUFFER_TIME, offsetof (SpaALSASinkProps, buffer_time), + "buffer-time", "The total size of the buffer in time", SPA_PROP_FLAG_READWRITE, SPA_PROP_TYPE_UINT32, sizeof (uint32_t), SPA_PROP_RANGE_TYPE_MIN_MAX, 2, uint32_range, - NULL, - offsetof (SpaALSASinkProps, buffer_time) }, - { PROP_ID_PERIOD_TIME, "period-time", "The size of a period in time", + NULL }, + { PROP_ID_PERIOD_TIME, offsetof (SpaALSASinkProps, period_time), + "period-time", "The size of a period in time", SPA_PROP_FLAG_READWRITE, SPA_PROP_TYPE_UINT32, sizeof (uint32_t), SPA_PROP_RANGE_TYPE_MIN_MAX, 2, uint32_range, - NULL, - offsetof (SpaALSASinkProps, period_time) }, - { PROP_ID_PERIOD_EVENT, "period-event", "Generate an event each period", + NULL }, + { PROP_ID_PERIOD_EVENT, offsetof (SpaALSASinkProps, period_event), + "period-event", "Generate an event each period", SPA_PROP_FLAG_READWRITE, SPA_PROP_TYPE_BOOL, sizeof (bool), SPA_PROP_RANGE_TYPE_NONE, 0, NULL, - NULL, - offsetof (SpaALSASinkProps, period_event) }, + NULL }, }; static SpaResult diff --git a/spa/plugins/audiotestsrc/audiotestsrc.c b/spa/plugins/audiotestsrc/audiotestsrc.c index 0a1606109..428da327b 100644 --- a/spa/plugins/audiotestsrc/audiotestsrc.c +++ b/spa/plugins/audiotestsrc/audiotestsrc.c @@ -84,24 +84,24 @@ enum { static const SpaPropInfo prop_info[] = { - { PROP_ID_WAVE, "wave", "Oscillator waveform", + { PROP_ID_WAVE, offsetof (SpaAudioTestSrcProps, wave), + "wave", "Oscillator waveform", SPA_PROP_FLAG_READWRITE, SPA_PROP_TYPE_UINT32, sizeof (uint32_t), SPA_PROP_RANGE_TYPE_ENUM, SPA_N_ELEMENTS (wave_range), wave_range, - NULL, - offsetof (SpaAudioTestSrcProps, wave) }, - { PROP_ID_FREQ, "freq", "Frequency of test signal. The sample rate needs to be at least 4 times higher", + NULL }, + { PROP_ID_FREQ, offsetof (SpaAudioTestSrcProps, freq), + "freq", "Frequency of test signal. The sample rate needs to be at least 4 times higher", SPA_PROP_FLAG_READWRITE, SPA_PROP_TYPE_DOUBLE, sizeof (double), SPA_PROP_RANGE_TYPE_MIN_MAX, 2, freq_range, - NULL, - offsetof (SpaAudioTestSrcProps, freq) }, - { PROP_ID_VOLUME, "volume", "The Volume factor", + NULL }, + { PROP_ID_VOLUME, offsetof (SpaAudioTestSrcProps, volume), + "volume", "The Volume factor", SPA_PROP_FLAG_READWRITE, SPA_PROP_TYPE_DOUBLE, sizeof (double), SPA_PROP_RANGE_TYPE_MIN_MAX, 2, volume_range, - NULL, - offsetof (SpaAudioTestSrcProps, volume) }, + NULL }, }; static void @@ -465,7 +465,7 @@ spa_audiotestsrc_node_port_pull_output (SpaNode *node, { SpaAudioTestSrc *this; size_t j, size; - uint8_t *ptr; + uint8_t *ptr = NULL; unsigned int i; bool have_error = false; diff --git a/spa/plugins/ffmpeg/ffmpeg-dec.c b/spa/plugins/ffmpeg/ffmpeg-dec.c index 7ad3d33d5..efaec77bc 100644 --- a/spa/plugins/ffmpeg/ffmpeg-dec.c +++ b/spa/plugins/ffmpeg/ffmpeg-dec.c @@ -55,7 +55,7 @@ struct _FFMpegBuffer { }; typedef struct { - SpaVideoRawFormat raw_format[2]; + SpaFormatVideo format[2]; SpaFormat *current_format; bool have_buffers; FFMpegBuffer buffers[MAX_BUFFERS]; @@ -278,12 +278,14 @@ spa_ffmpeg_dec_node_port_enum_formats (SpaNode *node, switch (index) { case 0: - spa_video_raw_format_init (&s->raw_format[0]); + spa_format_video_init (SPA_MEDIA_TYPE_VIDEO, + SPA_MEDIA_SUBTYPE_RAW, + &s->format[0]); break; default: return SPA_RESULT_ENUM_END; } - *format = &s->raw_format[0].format; + *format = &s->format[0].format; *(int*)state = ++index; return SPA_RESULT_OK; @@ -298,8 +300,6 @@ spa_ffmpeg_dec_node_port_set_format (SpaNode *node, SpaFFMpegDec *this; SpaFFMpegState *state; SpaResult res; - SpaFormat *f, *tf; - size_t fs; if (node == NULL || node->handle == NULL || format == NULL) return SPA_RESULT_INVALID_ARGUMENTS; @@ -316,22 +316,12 @@ spa_ffmpeg_dec_node_port_set_format (SpaNode *node, 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, &state->raw_format[0]) < 0)) - return res; - - f = &state->raw_format[0].format; - tf = &state->raw_format[1].format; - fs = sizeof (SpaVideoRawFormat); - } else - return SPA_RESULT_INVALID_MEDIA_TYPE; - } else - return SPA_RESULT_INVALID_MEDIA_TYPE; + if ((res = spa_format_video_parse (format, &state->format[0]) < 0)) + return res; if (!(flags & SPA_PORT_FORMAT_FLAG_TEST_ONLY)) { - memcpy (tf, f, fs); - state->current_format = tf; + memcpy (&state->format[1], &state->format[0], sizeof (SpaFormatVideo)); + state->current_format = &state->format[1].format; } return SPA_RESULT_OK; diff --git a/spa/plugins/ffmpeg/ffmpeg-enc.c b/spa/plugins/ffmpeg/ffmpeg-enc.c index ecfeebac9..b8725f22e 100644 --- a/spa/plugins/ffmpeg/ffmpeg-enc.c +++ b/spa/plugins/ffmpeg/ffmpeg-enc.c @@ -55,7 +55,7 @@ struct _FFMpegBuffer { }; typedef struct { - SpaVideoRawFormat raw_format[2]; + SpaFormatVideo format[2]; SpaFormat *current_format; bool have_buffers; FFMpegBuffer buffers[MAX_BUFFERS]; @@ -278,12 +278,14 @@ spa_ffmpeg_enc_node_port_enum_formats (SpaNode *node, switch (index) { case 0: - spa_video_raw_format_init (&s->raw_format[0]); + spa_format_video_init (SPA_MEDIA_TYPE_VIDEO, + SPA_MEDIA_SUBTYPE_RAW, + &s->format[0]); break; default: return SPA_RESULT_ENUM_END; } - *format = &s->raw_format[0].format; + *format = &s->format[0].format; *(int*)state = ++index; return SPA_RESULT_OK; @@ -298,8 +300,6 @@ spa_ffmpeg_enc_node_port_set_format (SpaNode *node, SpaFFMpegEnc *this; SpaFFMpegState *state; SpaResult res; - SpaFormat *f, *tf; - size_t fs; if (node == NULL || node->handle == NULL || format == NULL) return SPA_RESULT_INVALID_ARGUMENTS; @@ -315,23 +315,16 @@ spa_ffmpeg_enc_node_port_set_format (SpaNode *node, state->current_format = NULL; return SPA_RESULT_OK; } + if ((res = spa_format_video_parse (format, &state->format[0]) < 0)) + return res; - if (format->media_type == SPA_MEDIA_TYPE_VIDEO) { - if (format->media_subtype == SPA_MEDIA_SUBTYPE_RAW) { - if ((res = spa_video_raw_format_parse (format, &state->raw_format[0]) < 0)) - return res; - - f = &state->raw_format[0].format; - tf = &state->raw_format[1].format; - fs = sizeof (SpaVideoRawFormat); - } else - return SPA_RESULT_INVALID_MEDIA_TYPE; - } else + if (format->media_type != SPA_MEDIA_TYPE_VIDEO || + format->media_subtype != SPA_MEDIA_SUBTYPE_RAW) return SPA_RESULT_INVALID_MEDIA_TYPE; if (!(flags & SPA_PORT_FORMAT_FLAG_TEST_ONLY)) { - memcpy (tf, f, fs); - state->current_format = tf; + memcpy (&state->format[1], &state->format[0], sizeof (SpaFormatVideo)); + state->current_format = &state->format[1].format; } return SPA_RESULT_OK; diff --git a/spa/plugins/remote/proxy.c b/spa/plugins/remote/proxy.c index a8caa2020..d69734649 100644 --- a/spa/plugins/remote/proxy.c +++ b/spa/plugins/remote/proxy.c @@ -88,12 +88,12 @@ enum { static const SpaPropInfo prop_info[PROP_ID_LAST] = { - { PROP_ID_SOCKET, "socket", "The Socket factor", + { PROP_ID_SOCKET, offsetof (SpaProxyProps, socketfd), + "socket", "The Socket factor", SPA_PROP_FLAG_READWRITE, SPA_PROP_TYPE_INT, sizeof (int), SPA_PROP_RANGE_TYPE_NONE, 0, NULL, - NULL, - offsetof (SpaProxyProps, socketfd) }, + NULL }, }; static void @@ -626,10 +626,9 @@ spa_proxy_node_port_get_status (SpaNode *node, } static SpaResult -add_buffer (SpaProxy *this, SpaControlBuilder *builder, uint32_t port_id, SpaBuffer *buffer) +add_buffer_mem (SpaProxy *this, SpaControlBuilder *builder, uint32_t port_id, SpaBuffer *buffer) { SpaControlCmdAddMem am; - SpaControlCmdAddBuffer ab; int i; SpaBuffer *b; SpaMemory *bmem; @@ -661,6 +660,10 @@ add_buffer (SpaProxy *this, SpaControlBuilder *builder, uint32_t port_id, SpaBuf fprintf (stderr, "proxy %p: error invalid memory\n", this); continue; } + if (mem->fd == -1) { + fprintf (stderr, "proxy %p: error memory without fd\n", this); + continue; + } am.port_id = port_id; am.mem = mem->mem; @@ -670,42 +673,10 @@ add_buffer (SpaProxy *this, SpaControlBuilder *builder, uint32_t port_id, SpaBuf am.size = mem->size; spa_control_builder_add_cmd (builder, SPA_CONTROL_CMD_ADD_MEM, &am); } - ab.port_id = port_id; - ab.buffer_id = b->id; - ab.mem.mem = bmem->mem; - ab.mem.offset = b->mem.offset; - ab.mem.size = b->mem.size; - spa_control_builder_add_cmd (builder, SPA_CONTROL_CMD_ADD_BUFFER, &ab); return SPA_RESULT_OK; } -static SpaResult -remove_buffer (SpaProxy *this, SpaControlBuilder *builder, uint32_t port_id, SpaBuffer *buffer) -{ - SpaControlCmdRemoveBuffer rb; - SpaControlCmdRemoveMem rm; - unsigned int i; - - rb.port_id = port_id; - rb.buffer_id = buffer->id; - spa_control_builder_add_cmd (builder, SPA_CONTROL_CMD_REMOVE_BUFFER, &rb); - rm.port_id = port_id; - rm.mem = buffer->mem.mem; - spa_control_builder_add_cmd (builder, SPA_CONTROL_CMD_REMOVE_MEM, &rm); - - for (i = 0; i < buffer->n_datas; i++) { - SpaData *d = &SPA_BUFFER_DATAS (buffer)[i]; - - rm.port_id = port_id; - rm.mem = d->mem.mem; - spa_control_builder_add_cmd (builder, SPA_CONTROL_CMD_REMOVE_MEM, &rm); - } - - return SPA_RESULT_OK; -} - - static SpaResult spa_proxy_node_port_use_buffers (SpaNode *node, uint32_t port_id, @@ -720,6 +691,7 @@ spa_proxy_node_port_use_buffers (SpaNode *node, uint8_t buf[4096]; int fds[32]; SpaResult res; + SpaControlCmdUseBuffers ub; if (node == NULL || node->handle == NULL) return SPA_RESULT_INVALID_ARGUMENTS; @@ -737,9 +709,6 @@ spa_proxy_node_port_use_buffers (SpaNode *node, spa_control_builder_init_into (&builder, buf, sizeof (buf), fds, sizeof (fds)); - for (i = 0; i < port->n_buffers; i++) - remove_buffer (this, &builder, port_id, port->buffers[i]); - if (buffers == NULL || n_buffers == 0) { port->buffers = NULL; port->n_buffers = 0; @@ -748,7 +717,12 @@ spa_proxy_node_port_use_buffers (SpaNode *node, port->n_buffers = n_buffers; } for (i = 0; i < port->n_buffers; i++) - add_buffer (this, &builder, port_id, port->buffers[i]); + add_buffer_mem (this, &builder, port_id, port->buffers[i]); + + ub.port_id = port_id; + ub.n_buffers = port->n_buffers; + ub.buffers = port->buffers; + spa_control_builder_add_cmd (&builder, SPA_CONTROL_CMD_USE_BUFFERS, &ub); spa_control_builder_end (&builder, &control); @@ -1044,9 +1018,7 @@ parse_control (SpaProxy *this, break; case SPA_CONTROL_CMD_REMOVE_MEM: break; - case SPA_CONTROL_CMD_ADD_BUFFER: - break; - case SPA_CONTROL_CMD_REMOVE_BUFFER: + case SPA_CONTROL_CMD_USE_BUFFERS: break; case SPA_CONTROL_CMD_PROCESS_BUFFER: diff --git a/spa/plugins/v4l2/v4l2-source.c b/spa/plugins/v4l2/v4l2-source.c index 02544c59b..2859e9d29 100644 --- a/spa/plugins/v4l2/v4l2-source.c +++ b/spa/plugins/v4l2/v4l2-source.c @@ -140,24 +140,24 @@ enum { static const SpaPropInfo prop_info[] = { - { PROP_ID_DEVICE, "device", "V4l2 device location", + { PROP_ID_DEVICE, offsetof (SpaV4l2SourceProps, device), + "device", "V4l2 device location", SPA_PROP_FLAG_READWRITE, SPA_PROP_TYPE_STRING, 63, SPA_PROP_RANGE_TYPE_NONE, 0, NULL, - NULL, - offsetof (SpaV4l2SourceProps, device) }, - { PROP_ID_DEVICE_NAME, "device-name", "Human-readable name of the device", + NULL }, + { PROP_ID_DEVICE_NAME, offsetof (SpaV4l2SourceProps, device_name), + "device-name", "Human-readable name of the device", SPA_PROP_FLAG_READABLE, SPA_PROP_TYPE_STRING, 127, SPA_PROP_RANGE_TYPE_NONE, 0, NULL, - NULL, - offsetof (SpaV4l2SourceProps, device_name) }, - { PROP_ID_DEVICE_FD, "device-fd", "Device file descriptor", + NULL }, + { PROP_ID_DEVICE_FD, offsetof (SpaV4l2SourceProps, device_fd), + "device-fd", "Device file descriptor", SPA_PROP_FLAG_READABLE, SPA_PROP_TYPE_UINT32, sizeof (uint32_t), SPA_PROP_RANGE_TYPE_NONE, 0, NULL, - NULL, - offsetof (SpaV4l2SourceProps, device_fd) }, + NULL }, }; static SpaResult @@ -357,15 +357,15 @@ spa_v4l2_format_init (V4l2Format *f) f->fmt.props.n_prop_info = 3; f->fmt.props.prop_info = f->infos; - spa_video_raw_fill_prop_info (&f->infos[0], - SPA_PROP_ID_VIDEO_FORMAT, - offsetof (V4l2Format, format)); - spa_video_raw_fill_prop_info (&f->infos[1], - SPA_PROP_ID_VIDEO_SIZE, - offsetof (V4l2Format, size)); - spa_video_raw_fill_prop_info (&f->infos[2], - SPA_PROP_ID_VIDEO_FRAMERATE, - offsetof (V4l2Format, framerate)); + spa_prop_info_fill_video (&f->infos[0], + SPA_PROP_ID_VIDEO_FORMAT, + offsetof (V4l2Format, format)); + spa_prop_info_fill_video (&f->infos[1], + SPA_PROP_ID_VIDEO_SIZE, + offsetof (V4l2Format, size)); + spa_prop_info_fill_video (&f->infos[2], + SPA_PROP_ID_VIDEO_FRAMERATE, + offsetof (V4l2Format, framerate)); } static SpaResult @@ -386,7 +386,7 @@ spa_v4l2_source_node_port_enum_formats (SpaNode *node, if (port_id != 0) return SPA_RESULT_INVALID_PORT; - res = spa_v4l2_enum_format (this, format, state); + res = spa_v4l2_enum_format (this, format, filter, state); return res; } @@ -403,7 +403,7 @@ spa_v4l2_source_node_port_set_format (SpaNode *node, V4l2Format *f, *tf; size_t fs; - if (node == NULL || node->handle == NULL || format == NULL) + if (node == NULL || node->handle == NULL) return SPA_RESULT_INVALID_ARGUMENTS; this = (SpaV4l2Source *) node->handle; @@ -417,6 +417,7 @@ spa_v4l2_source_node_port_set_format (SpaNode *node, spa_v4l2_clear_buffers (this); spa_v4l2_close (this); state->current_format = NULL; + update_state (this, SPA_NODE_STATE_CONFIGURE); return SPA_RESULT_OK; } diff --git a/spa/plugins/v4l2/v4l2-utils.c b/spa/plugins/v4l2/v4l2-utils.c index e5f5e9fd5..ddba19f83 100644 --- a/spa/plugins/v4l2/v4l2-utils.c +++ b/spa/plugins/v4l2/v4l2-utils.c @@ -230,28 +230,28 @@ static const FormatInfo format_info[] = { V4L2_PIX_FMT_SRGGB8, SPA_VIDEO_FORMAT_UNKNOWN, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_BAYER }, /* compressed formats */ - {V4L2_PIX_FMT_MJPEG, SPA_VIDEO_FORMAT_ENCODED, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_MJPG }, - {V4L2_PIX_FMT_JPEG, SPA_VIDEO_FORMAT_ENCODED, SPA_MEDIA_TYPE_IMAGE, SPA_MEDIA_SUBTYPE_JPEG }, - {V4L2_PIX_FMT_PJPG, SPA_VIDEO_FORMAT_UNKNOWN, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_RAW }, - {V4L2_PIX_FMT_DV, SPA_VIDEO_FORMAT_ENCODED, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_DV }, - {V4L2_PIX_FMT_MPEG, SPA_VIDEO_FORMAT_ENCODED, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_MPEGTS }, - {V4L2_PIX_FMT_H264, SPA_VIDEO_FORMAT_ENCODED, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_H264 }, - {V4L2_PIX_FMT_H264_NO_SC, SPA_VIDEO_FORMAT_ENCODED, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_H264 }, - {V4L2_PIX_FMT_H264_MVC, SPA_VIDEO_FORMAT_ENCODED, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_H264 }, - {V4L2_PIX_FMT_H263, SPA_VIDEO_FORMAT_ENCODED, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_H263 }, - {V4L2_PIX_FMT_MPEG1, SPA_VIDEO_FORMAT_ENCODED, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_MPEG1 }, - {V4L2_PIX_FMT_MPEG2, SPA_VIDEO_FORMAT_ENCODED, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_MPEG2 }, - {V4L2_PIX_FMT_MPEG4, SPA_VIDEO_FORMAT_ENCODED, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_MPEG4 }, - {V4L2_PIX_FMT_XVID, SPA_VIDEO_FORMAT_ENCODED, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_XVID }, - {V4L2_PIX_FMT_VC1_ANNEX_G, SPA_VIDEO_FORMAT_ENCODED, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_VC1 }, - {V4L2_PIX_FMT_VC1_ANNEX_L, SPA_VIDEO_FORMAT_ENCODED, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_VC1 }, - {V4L2_PIX_FMT_VP8, SPA_VIDEO_FORMAT_ENCODED, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_VP8 }, + { V4L2_PIX_FMT_MJPEG, SPA_VIDEO_FORMAT_ENCODED, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_MJPG }, + { V4L2_PIX_FMT_JPEG, SPA_VIDEO_FORMAT_ENCODED, SPA_MEDIA_TYPE_IMAGE, SPA_MEDIA_SUBTYPE_JPEG }, + { V4L2_PIX_FMT_PJPG, SPA_VIDEO_FORMAT_UNKNOWN, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_RAW }, + { V4L2_PIX_FMT_DV, SPA_VIDEO_FORMAT_ENCODED, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_DV }, + { V4L2_PIX_FMT_MPEG, SPA_VIDEO_FORMAT_ENCODED, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_MPEGTS }, + { V4L2_PIX_FMT_H264, SPA_VIDEO_FORMAT_ENCODED, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_H264 }, + { V4L2_PIX_FMT_H264_NO_SC, SPA_VIDEO_FORMAT_ENCODED, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_H264 }, + { V4L2_PIX_FMT_H264_MVC, SPA_VIDEO_FORMAT_ENCODED, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_H264 }, + { V4L2_PIX_FMT_H263, SPA_VIDEO_FORMAT_ENCODED, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_H263 }, + { V4L2_PIX_FMT_MPEG1, SPA_VIDEO_FORMAT_ENCODED, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_MPEG1 }, + { V4L2_PIX_FMT_MPEG2, SPA_VIDEO_FORMAT_ENCODED, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_MPEG2 }, + { V4L2_PIX_FMT_MPEG4, SPA_VIDEO_FORMAT_ENCODED, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_MPEG4 }, + { V4L2_PIX_FMT_XVID, SPA_VIDEO_FORMAT_ENCODED, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_XVID }, + { V4L2_PIX_FMT_VC1_ANNEX_G, SPA_VIDEO_FORMAT_ENCODED, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_VC1 }, + { V4L2_PIX_FMT_VC1_ANNEX_L, SPA_VIDEO_FORMAT_ENCODED, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_VC1 }, + { V4L2_PIX_FMT_VP8, SPA_VIDEO_FORMAT_ENCODED, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_VP8 }, /* Vendor-specific formats */ - {V4L2_PIX_FMT_WNVA, SPA_VIDEO_FORMAT_UNKNOWN, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_RAW }, - {V4L2_PIX_FMT_SN9C10X, SPA_VIDEO_FORMAT_UNKNOWN, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_RAW }, - {V4L2_PIX_FMT_PWC1, SPA_VIDEO_FORMAT_UNKNOWN, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_RAW }, - {V4L2_PIX_FMT_PWC2, SPA_VIDEO_FORMAT_UNKNOWN, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_RAW }, + { V4L2_PIX_FMT_WNVA, SPA_VIDEO_FORMAT_UNKNOWN, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_RAW }, + { V4L2_PIX_FMT_SN9C10X, SPA_VIDEO_FORMAT_UNKNOWN, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_RAW }, + { V4L2_PIX_FMT_PWC1, SPA_VIDEO_FORMAT_UNKNOWN, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_RAW }, + { V4L2_PIX_FMT_PWC2, SPA_VIDEO_FORMAT_UNKNOWN, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_RAW }, }; static const FormatInfo * @@ -280,15 +280,33 @@ video_format_to_format_info (SpaVideoFormat format) } #endif +static const FormatInfo * +find_format_info_by_media_type (SpaMediaType type, + SpaMediaSubType subtype, + SpaVideoFormat format, + int startidx) +{ + int i; + + for (i = startidx; i < SPA_N_ELEMENTS (format_info); i++) { + if ((format_info[i].media_type == type) && + (format_info[i].media_subtype == subtype) && + (format == SPA_VIDEO_FORMAT_UNKNOWN || format_info[i].format == format)) + return &format_info[i]; + } + return NULL; +} + #define FOURCC_ARGS(f) (f)&0x7f,((f)>>8)&0x7f,((f)>>16)&0x7f,((f)>>24)&0x7f static SpaResult -spa_v4l2_enum_format (SpaV4l2Source *this, SpaFormat **format, void **cookie) +spa_v4l2_enum_format (SpaV4l2Source *this, SpaFormat **format, const SpaFormat *filter, void **cookie) { SpaV4l2State *state = &this->state[0]; int res, i, pi; V4l2Format *fmt; const FormatInfo *info; + SpaVideoFormat video_format; if (spa_v4l2_open (this) < 0) return SPA_RESULT_ERROR; @@ -306,15 +324,47 @@ spa_v4l2_enum_format (SpaV4l2Source *this, SpaFormat **format, void **cookie) *cookie = state; } + again: if (state->next_fmtdesc) { - if ((res = xioctl (state->fd, VIDIOC_ENUM_FMT, &state->fmtdesc)) < 0) { - if (errno != EINVAL) - perror ("VIDIOC_ENUM_FMT"); - return SPA_RESULT_ENUM_END; + if (filter) { + SpaPropValue val; + + if (state->fmtdesc.index == 1) + return SPA_RESULT_ENUM_END; + + video_format = SPA_VIDEO_FORMAT_UNKNOWN; + if ((filter->media_type == SPA_MEDIA_TYPE_VIDEO)) { + if (filter->media_subtype == SPA_MEDIA_SUBTYPE_RAW) { + if (spa_props_get_prop (&filter->props, + spa_props_index_for_id (&filter->props, SPA_PROP_ID_VIDEO_FORMAT), + &val) >= 0) { + video_format = *((SpaVideoFormat *)val.value); + } + } else { + video_format = SPA_VIDEO_FORMAT_ENCODED; + } + } else if ((filter->media_type == SPA_MEDIA_TYPE_IMAGE)) { + video_format = SPA_VIDEO_FORMAT_ENCODED; + } else + return SPA_RESULT_ENUM_END; + + info = find_format_info_by_media_type (filter->media_type, + filter->media_subtype, + video_format, + 0); + if (info == NULL) + return SPA_RESULT_ENUM_END; + + state->fmtdesc.pixelformat = info->fourcc; + } else { + if ((res = xioctl (state->fd, VIDIOC_ENUM_FMT, &state->fmtdesc)) < 0) { + if (errno != EINVAL) + perror ("VIDIOC_ENUM_FMT"); + return SPA_RESULT_ENUM_END; + } } state->next_fmtdesc = false; - state->frmsize.index = 0; state->frmsize.pixel_format = state->fmtdesc.pixelformat; state->next_frmsize = true; @@ -354,23 +404,23 @@ again: fmt->fmt.props.unset_mask = 0; if (info->media_subtype == SPA_MEDIA_SUBTYPE_RAW) { - spa_video_raw_fill_prop_info (&fmt->infos[pi], - SPA_PROP_ID_VIDEO_FORMAT, - offsetof (V4l2Format, format)); + spa_prop_info_fill_video (&fmt->infos[pi], + SPA_PROP_ID_VIDEO_FORMAT, + offsetof (V4l2Format, format)); fmt->format = info->format; pi = ++fmt->fmt.props.n_prop_info; } - spa_video_raw_fill_prop_info (&fmt->infos[pi], - SPA_PROP_ID_VIDEO_SIZE, - offsetof (V4l2Format, size)); + spa_prop_info_fill_video (&fmt->infos[pi], + SPA_PROP_ID_VIDEO_SIZE, + offsetof (V4l2Format, size)); fmt->size.width = state->frmsize.discrete.width; fmt->size.height = state->frmsize.discrete.height; pi = ++fmt->fmt.props.n_prop_info; - spa_video_raw_fill_prop_info (&fmt->infos[pi], - SPA_PROP_ID_VIDEO_FRAMERATE, - offsetof (V4l2Format, framerate)); + spa_prop_info_fill_video (&fmt->infos[pi], + SPA_PROP_ID_VIDEO_FRAMERATE, + offsetof (V4l2Format, framerate)); fmt->infos[pi].range_type = SPA_PROP_RANGE_TYPE_ENUM; fmt->infos[pi].range_values = fmt->ranges; fmt->infos[pi].n_range_values = 0; @@ -417,21 +467,16 @@ spa_v4l2_set_format (SpaV4l2Source *this, V4l2Format *f, bool try_only) struct v4l2_format reqfmt, fmt; struct v4l2_streamparm streamparm; const FormatInfo *info = NULL; - int i; CLEAR (fmt); CLEAR (streamparm); fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - for (i = 0; i < SPA_N_ELEMENTS (format_info); i++) { - if (format_info[i].media_type == f->fmt.media_type && - format_info[i].media_subtype == f->fmt.media_subtype && - format_info[i].format == f->format) { - info = &format_info[i]; - break; - } - } + info = find_format_info_by_media_type (f->fmt.media_type, + f->fmt.media_subtype, + f->format, + 0); if (info == NULL) return -1; diff --git a/spa/plugins/volume/volume.c b/spa/plugins/volume/volume.c index e4f61df96..07d5e70d9 100644 --- a/spa/plugins/volume/volume.c +++ b/spa/plugins/volume/volume.c @@ -75,18 +75,18 @@ enum { static const SpaPropInfo prop_info[] = { - { PROP_ID_VOLUME, "volume", "The Volume factor", + { PROP_ID_VOLUME, offsetof (SpaVolumeProps, volume), + "volume", "The Volume factor", SPA_PROP_FLAG_READWRITE, SPA_PROP_TYPE_DOUBLE, sizeof (double), SPA_PROP_RANGE_TYPE_MIN_MAX, 2, volume_range, - NULL, - offsetof (SpaVolumeProps, volume) }, - { PROP_ID_MUTE, "mute", "Mute", + NULL }, + { PROP_ID_MUTE, offsetof (SpaVolumeProps, mute), + "mute", "Mute", SPA_PROP_FLAG_READWRITE, SPA_PROP_TYPE_BOOL, sizeof (bool), SPA_PROP_RANGE_TYPE_NONE, 0, NULL, - NULL, - offsetof (SpaVolumeProps, mute) }, + NULL }, }; static void diff --git a/spa/plugins/xv/xv-sink.c b/spa/plugins/xv/xv-sink.c index 4044af5a4..ecd882fd6 100644 --- a/spa/plugins/xv/xv-sink.c +++ b/spa/plugins/xv/xv-sink.c @@ -76,7 +76,7 @@ struct _SpaXvSink { SpaEventCallback event_cb; void *user_data; - SpaVideoRawFormat raw_format[2]; + SpaFormatVideo format[2]; SpaFormat *current_format; SpaXvState state; @@ -97,24 +97,24 @@ enum { static const SpaPropInfo prop_info[] = { - { PROP_ID_DEVICE, "device", "Xv device location", + { PROP_ID_DEVICE, offsetof (SpaXvSinkProps, device), + "device", "Xv device location", SPA_PROP_FLAG_READWRITE, SPA_PROP_TYPE_STRING, 63, SPA_PROP_RANGE_TYPE_NONE, 0, NULL, - NULL, - offsetof (SpaXvSinkProps, device) }, - { PROP_ID_DEVICE_NAME, "device-name", "Human-readable name of the device", + NULL }, + { PROP_ID_DEVICE_NAME, offsetof (SpaXvSinkProps, device_name), + "device-name", "Human-readable name of the device", SPA_PROP_FLAG_READABLE, SPA_PROP_TYPE_STRING, 127, SPA_PROP_RANGE_TYPE_NONE, 0, NULL, - NULL, - offsetof (SpaXvSinkProps, device_name) }, - { PROP_ID_DEVICE_FD, "device-fd", "Device file descriptor", + NULL }, + { PROP_ID_DEVICE_FD, offsetof (SpaXvSinkProps, device_fd), + "device-fd", "Device file descriptor", SPA_PROP_FLAG_READABLE, SPA_PROP_TYPE_UINT32, sizeof (uint32_t), SPA_PROP_RANGE_TYPE_NONE, 0, NULL, - NULL, - offsetof (SpaXvSinkProps, device_fd) }, + NULL }, }; static SpaResult @@ -308,12 +308,14 @@ spa_xv_sink_node_port_enum_formats (SpaNode *node, switch (index) { case 0: - spa_video_raw_format_init (&this->raw_format[0]); + spa_format_video_init (SPA_MEDIA_TYPE_VIDEO, + SPA_MEDIA_SUBTYPE_RAW, + &this->format[0]); break; default: return SPA_RESULT_ENUM_END; } - *format = &this->raw_format[0].format; + *format = &this->format[0].format; *(int*)state = ++index; return SPA_RESULT_OK; @@ -345,12 +347,12 @@ spa_xv_sink_node_port_set_format (SpaNode *node, 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_format_video_parse (format, &this->format[0]) < 0)) return res; - f = &this->raw_format[0].format; - tf = &this->raw_format[1].format; - fs = sizeof (SpaVideoRawFormat); + f = &this->format[0].format; + tf = &this->format[1].format; + fs = sizeof (SpaVideoFormat); } else return SPA_RESULT_INVALID_MEDIA_TYPE; } else diff --git a/spa/tests/test-v4l2.c b/spa/tests/test-v4l2.c index eb51b6ba2..b1f1d0428 100644 --- a/spa/tests/test-v4l2.c +++ b/spa/tests/test-v4l2.c @@ -318,20 +318,20 @@ negotiate_formats (AppData *data) f.fmt.props.n_prop_info = 3; f.fmt.props.prop_info = f.infos; - spa_video_raw_fill_prop_info (&f.infos[0], - SPA_PROP_ID_VIDEO_FORMAT, - offsetof (VideoFormat, format)); + spa_prop_info_fill_video (&f.infos[0], + SPA_PROP_ID_VIDEO_FORMAT, + offsetof (VideoFormat, format)); f.format = SPA_VIDEO_FORMAT_YUY2; - spa_video_raw_fill_prop_info (&f.infos[1], - SPA_PROP_ID_VIDEO_SIZE, - offsetof (VideoFormat, size)); + spa_prop_info_fill_video (&f.infos[1], + SPA_PROP_ID_VIDEO_SIZE, + offsetof (VideoFormat, size)); f.size.width = 320; f.size.height = 240; - spa_video_raw_fill_prop_info (&f.infos[2], - SPA_PROP_ID_VIDEO_FRAMERATE, - offsetof (VideoFormat, framerate)); + spa_prop_info_fill_video (&f.infos[2], + SPA_PROP_ID_VIDEO_FRAMERATE, + offsetof (VideoFormat, framerate)); f.framerate.num = 25; f.framerate.denom = 1; #endif