From ac5d22ec79be75c203c1a4375ea95f450ebadab3 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Fri, 5 Aug 2016 16:39:26 +0200 Subject: [PATCH] Work on negotiation Add helpers to convert between pinos and gstreamer formats. Use pinos formats in the API. Work on removing some hardcoded stuff and instead use the real format from the pinos server. Use memfd and sealing. --- pinos/Makefile.am | 6 +- pinos/client/format.c | 44 +++++++ pinos/client/format.h | 37 ++++++ pinos/client/stream.c | 79 ++++++------- pinos/client/stream.h | 5 +- pinos/gst/gstpinosformat.c | 170 ++++++++++++++++++++++++++++ pinos/gst/gstpinosformat.h | 36 ++++++ pinos/gst/gstpinossink.c | 34 +++--- pinos/gst/gstpinossrc.c | 38 +++---- pinos/modules/spa/spa-alsa-sink.c | 6 +- pinos/server/link.c | 4 +- pinos/tests/test-client.c | 20 ++-- spa/include/spa/buffer.h | 24 ++-- spa/include/spa/control.h | 39 ++++--- spa/include/spa/format.h | 18 ++- spa/include/spa/memory.h | 16 +++ spa/lib/control.c | 8 +- spa/lib/debug.c | 14 +-- spa/lib/format.c | 40 +++++++ spa/lib/memfd-wrappers.h | 59 ++++++++++ spa/lib/memory.c | 36 +++++- spa/plugins/audiomixer/audiomixer.c | 14 +-- spa/plugins/remote/proxy.c | 30 ++--- spa/plugins/v4l2/v4l2-utils.c | 26 ++--- spa/plugins/volume/volume.c | 14 +-- spa/tests/test-v4l2.c | 20 ++-- 26 files changed, 638 insertions(+), 199 deletions(-) create mode 100644 pinos/client/format.c create mode 100644 pinos/client/format.h create mode 100644 pinos/gst/gstpinosformat.c create mode 100644 pinos/gst/gstpinosformat.h create mode 100644 spa/lib/format.c create mode 100644 spa/lib/memfd-wrappers.h diff --git a/pinos/Makefile.am b/pinos/Makefile.am index 8c32f9376..dc5eb7ffd 100644 --- a/pinos/Makefile.am +++ b/pinos/Makefile.am @@ -166,6 +166,7 @@ pinosgstsource = gst/gsttmpfileallocator.h gst/gsttmpfileallocator.c pinosinclude_HEADERS = \ client/context.h \ client/enumtypes.h \ + client/format.h \ client/introspect.h \ client/mainloop.h \ client/pinos.h \ @@ -180,6 +181,7 @@ lib_LTLIBRARIES = \ libpinos_@PINOS_MAJORMINOR@_la_SOURCES = \ client/context.h client/context.c \ client/enumtypes.h client/enumtypes.c \ + client/format.h client/format.c \ client/introspect.h client/introspect.c \ client/mainloop.h client/mainloop.c \ client/properties.h client/properties.c \ @@ -193,7 +195,7 @@ libpinos_@PINOS_MAJORMINOR@_la_SOURCES = \ libpinos_@PINOS_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS) $(GST_CFLAGS) libpinos_@PINOS_MAJORMINOR@_la_LDFLAGS = $(AM_LDFLAGS) -avoid-version -libpinos_@PINOS_MAJORMINOR@_la_LIBADD = $(AM_LIBADD) $(LTLIBICONV) $(GST_LIBS) $(GST_BASE_LIBS) -lgstvideo-1.0 +libpinos_@PINOS_MAJORMINOR@_la_LIBADD = $(AM_LIBADD) $(LTLIBICONV) $(GST_LIBS) $(GST_BASE_LIBS) -lgstvideo-1.0 -lgstaudio-1.0 ################################### # Daemon core library # @@ -235,6 +237,7 @@ plugin_LTLIBRARIES = libgstpinos.la libgstpinos_la_SOURCES = \ gst/gstburstcache.c \ gst/gstpinos.c \ + gst/gstpinosformat.c \ gst/gstpinosdeviceprovider.c \ gst/gstpinossrc.c \ gst/gstpinossink.c @@ -253,6 +256,7 @@ libgstpinos_la_LIBTOOLFLAGS = $(GST_PLUGIN_LIBTOOLFLAGS) noinst_HEADERS = gst/gstburstcache.h gst/gstpinossrc.h \ gst/gstpinossocketsink.h gst/gstpinosportsink.h \ gst/gstpinosportsrc.h \ + gst/gstpinosformat.h \ gst/gstpinossink.h gst/gstpinospay.h \ gst/gstpinosdepay.h gst/gstpinosdeviceprovider.h diff --git a/pinos/client/format.c b/pinos/client/format.c new file mode 100644 index 000000000..51ef95f89 --- /dev/null +++ b/pinos/client/format.c @@ -0,0 +1,44 @@ +/* Pinos + * Copyright (C) 2015 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. + */ + +#include + +static SpaFormat * +format_copy (SpaFormat *format) +{ + SpaMemory *mem; + + if (format == NULL) + return NULL; + + mem = spa_memory_alloc_size (format->mem.mem.pool_id, format, format->mem.size); + + return spa_memory_ensure_ptr (mem); +} + +static void +format_free (SpaFormat *format) +{ + g_return_if_fail (format != NULL); + + spa_memory_unref (&format->mem.mem); +} + +G_DEFINE_BOXED_TYPE (SpaFormat, spa_format, + format_copy, format_free); diff --git a/pinos/client/format.h b/pinos/client/format.h new file mode 100644 index 000000000..3a7909d56 --- /dev/null +++ b/pinos/client/format.h @@ -0,0 +1,37 @@ +/* Pinos + * Copyright (C) 2015 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 __PINOS_FORMAT_H__ +#define __PINOS_FORMAT_H__ + +#include + +#include + +G_BEGIN_DECLS + +#define SPA_TYPE_FORMAT (spa_format_get_type()) + +GType spa_format_get_type (void); + + + +G_END_DECLS + +#endif /* __PINOS_FORMAT_H__ */ diff --git a/pinos/client/stream.c b/pinos/client/stream.c index 649489881..d2fb70b1b 100644 --- a/pinos/client/stream.c +++ b/pinos/client/stream.c @@ -21,6 +21,10 @@ #include #include +#include "spa/include/spa/control.h" +#include "spa/include/spa/debug.h" +#include "spa/include/spa/memory.h" + #include #include #include @@ -30,11 +34,8 @@ #include "pinos/client/context.h" #include "pinos/client/stream.h" #include "pinos/client/enumtypes.h" - +#include "pinos/client/format.h" #include "pinos/client/private.h" -#include "spa/include/spa/control.h" -#include "spa/include/spa/debug.h" -#include "spa/include/spa/memory.h" #define MAX_BUFFER_SIZE 1024 #define MAX_FDS 16 @@ -70,10 +71,11 @@ struct _PinosStreamPrivate PinosDirection direction; gchar *path; - GBytes *possible_formats; - PinosStreamFlags flags; - GBytes *format; + GPtrArray *possible_formats; + SpaFormat *format; + + PinosStreamFlags flags; GDBusProxy *node; gboolean disconnecting; @@ -188,7 +190,7 @@ pinos_stream_set_property (GObject *_object, case PROP_FORMAT: if (priv->format) - g_bytes_unref (priv->format); + spa_format_unref (priv->format); priv->format = g_value_dup_boxed (value); break; @@ -279,9 +281,9 @@ pinos_stream_finalize (GObject * object) g_clear_object (&priv->node); if (priv->possible_formats) - g_bytes_unref (priv->possible_formats); + g_ptr_array_unref (priv->possible_formats); if (priv->format) - g_bytes_unref (priv->format); + spa_format_unref (priv->format); g_free (priv->path); g_clear_error (&priv->error); @@ -375,7 +377,7 @@ pinos_stream_class_init (PinosStreamClass * klass) g_param_spec_boxed ("possible-formats", "Possible Formats", "The possbile formats of the stream", - G_TYPE_BYTES, + G_TYPE_PTR_ARRAY, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); /** @@ -388,7 +390,7 @@ pinos_stream_class_init (PinosStreamClass * klass) g_param_spec_boxed ("format", "Format", "The format of the stream", - G_TYPE_BYTES, + SPA_TYPE_FORMAT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); /** @@ -584,23 +586,17 @@ parse_control (PinosStream *stream, SpaControlBuilder builder; SpaControl control; SpaControlCmdStateChange sc; - guint8 buffer[1024]; - const gchar *str; + guint8 buffer[64]; if (spa_control_iter_parse_cmd (&it, &p) < 0) break; if (priv->format) - g_bytes_unref (priv->format); - str = "video/x-raw," - " format=(string)YUY2," - " width=(int)320," - " height=(int)240," - " framerate=(fraction)30/1"; - priv->format = g_bytes_new_static (str, strlen (str)+1); - g_object_notify (G_OBJECT (stream), "format"); + spa_format_unref (priv->format); + priv->format = p.format; - spa_format_unref (p.format); + spa_debug_format (p.format); + g_object_notify (G_OBJECT (stream), "format"); /* FIXME send update port status */ @@ -650,12 +646,17 @@ parse_control (PinosStream *stream, if (fd == -1) break; - g_debug ("add mem %d,%d, %d, %d", p.mem.pool_id, p.mem.id, fd, p.flags); mem = spa_memory_import (&p.mem); - mem->flags = p.flags; - mem->fd = fd; - mem->ptr = NULL; - mem->size = p.size; + if (mem->fd == -1) { + g_debug ("add mem %d,%d, %d, %d", p.mem.pool_id, p.mem.id, fd, p.flags); + mem->flags = p.flags; + mem->fd = fd; + mem->ptr = NULL; + mem->size = p.size; + } else { + g_debug ("duplicated mem %d,%d, %d, %d", p.mem.pool_id, p.mem.id, fd, p.flags); + close (fd); + } break; } case SPA_CONTROL_CMD_REMOVE_MEM: @@ -681,13 +682,13 @@ parse_control (PinosStream *stream, if (spa_control_iter_parse_cmd (&it, &p) < 0) break; - g_debug ("add buffer %d", p.buffer_id); - mem = spa_memory_find (&p.mem); + 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.offset; - bid.size = p.size; - bid.buf = SPA_MEMBER (spa_memory_ensure_ptr (mem), p.offset, SpaBuffer); + bid.offset = p.mem.offset; + bid.size = p.mem.size; + bid.buf = SPA_MEMBER (spa_memory_ensure_ptr (mem), p.mem.offset, SpaBuffer); g_array_append_val (priv->buffer_ids, bid); break; @@ -957,7 +958,7 @@ do_connect (PinosStream *stream) g_variant_builder_open (&b, G_VARIANT_TYPE ("(uusa{sv}s)")); g_variant_builder_add (&b, "u", priv->direction); g_variant_builder_add (&b, "u", 0); - g_variant_builder_add (&b, "s", g_bytes_get_data (priv->possible_formats, NULL)); + g_variant_builder_add (&b, "s", ""); g_variant_builder_add_value (&b, pinos_properties_to_variant (priv->properties)); g_variant_builder_add (&b, "s", priv->path == NULL ? "" : priv->path); g_variant_builder_close (&b); @@ -983,7 +984,7 @@ do_connect (PinosStream *stream) * @direction: the stream direction * @port_path: the port path to connect to or %NULL to get the default port * @flags: a #PinosStreamFlags - * @possible_formats: (transfer full): a #GBytes with possible accepted formats + * @possible_formats: (transfer full): a #GPtrArray with possible accepted formats * * Connect @stream for input or output on @port_path. * @@ -994,7 +995,7 @@ pinos_stream_connect (PinosStream *stream, PinosDirection direction, const gchar *port_path, PinosStreamFlags flags, - GBytes *possible_formats) + GPtrArray *possible_formats) { PinosStreamPrivate *priv; PinosContext *context; @@ -1011,7 +1012,7 @@ pinos_stream_connect (PinosStream *stream, g_free (priv->path); priv->path = g_strdup (port_path); if (priv->possible_formats) - g_bytes_unref (priv->possible_formats); + g_ptr_array_unref (priv->possible_formats); priv->flags = flags; priv->possible_formats = possible_formats; @@ -1067,7 +1068,7 @@ do_start (PinosStream *stream) /** * pinos_stream_start: * @stream: a #PinosStream - * @format: (transfer full): a #GBytes with format + * @format: (transfer full): a #SpaFormat with format * @mode: a #PinosStreamMode * * Start capturing from @stream in @format. @@ -1083,7 +1084,7 @@ do_start (PinosStream *stream) */ gboolean pinos_stream_start (PinosStream *stream, - GBytes *format, + SpaFormat *format, PinosStreamMode mode) { PinosStreamPrivate *priv; diff --git a/pinos/client/stream.h b/pinos/client/stream.h index ef34979a9..87d50d603 100644 --- a/pinos/client/stream.h +++ b/pinos/client/stream.h @@ -23,6 +23,7 @@ #include #include +#include #include @@ -99,11 +100,11 @@ gboolean pinos_stream_connect (PinosStream *stream, PinosDirection direction, const gchar *port_path, PinosStreamFlags flags, - GBytes *possible_formats); + GPtrArray *possible_formats); gboolean pinos_stream_disconnect (PinosStream *stream); gboolean pinos_stream_start (PinosStream *stream, - GBytes *format, + SpaFormat *format, PinosStreamMode mode); gboolean pinos_stream_stop (PinosStream *stream); diff --git a/pinos/gst/gstpinosformat.c b/pinos/gst/gstpinosformat.c new file mode 100644 index 000000000..54eafff96 --- /dev/null +++ b/pinos/gst/gstpinosformat.c @@ -0,0 +1,170 @@ +/* GStreamer + * 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. + */ + +#include +#include +#include + +#include +#include +#include + +#include "gstpinosformat.h" + +static SpaFormat * +convert_1 (GstCapsFeatures *cf, GstStructure *cs) +{ + SpaMemory *mem; + SpaFormat *res = NULL; + const gchar *s; + int i; + + if (gst_structure_has_name (cs, "video/x-raw")) { + SpaVideoRawFormat *f; + + mem = spa_memory_alloc_size (SPA_MEMORY_POOL_LOCAL, NULL, sizeof (SpaVideoRawFormat)); + f = spa_memory_ensure_ptr (mem); + f->format.mem.mem = mem->mem; + f->format.mem.offset = 0; + f->format.mem.size = mem->size; + + spa_video_raw_format_init (f); + + if (!(s = gst_structure_get_string (cs, "format"))) + goto done; + f->info.format = gst_video_format_from_string (s); + if (!gst_structure_get_int (cs, "width", &i)) + goto done; + f->info.size.width = i; + if (!gst_structure_get_int (cs, "height", &i)) + goto done; + f->info.size.height = i; + f->unset_mask = 0; + + res = &f->format; + } else if (gst_structure_has_name (cs, "audio/x-raw")) { + SpaAudioRawFormat *f; + + mem = spa_memory_alloc_size (SPA_MEMORY_POOL_LOCAL, NULL, sizeof (SpaAudioRawFormat)); + f = spa_memory_ensure_ptr (mem); + f->format.mem.mem = mem->mem; + f->format.mem.offset = 0; + f->format.mem.size = mem->size; + + spa_audio_raw_format_init (f); + + if (!(s = gst_structure_get_string (cs, "format"))) + goto done; + f->info.format = gst_audio_format_from_string (s); + if (!(s = gst_structure_get_string (cs, "layout"))) + goto done; + f->info.layout = 0; + if (!gst_structure_get_int (cs, "rate", &i)) + goto done; + f->info.rate = i; + if (!gst_structure_get_int (cs, "channels", &i)) + goto done; + f->info.channels = i; + f->unset_mask = 0; + + res = &f->format; + } + +done: + return res; +} + +SpaFormat * +gst_caps_to_format (GstCaps *caps, guint index) +{ + GstCapsFeatures *f; + GstStructure *s; + SpaFormat *res; + + g_return_val_if_fail (GST_IS_CAPS (caps), NULL); + g_return_val_if_fail (gst_caps_is_fixed (caps), NULL); + + f = gst_caps_get_features (caps, index); + s = gst_caps_get_structure (caps, index); + + res = convert_1 (f, s); + + return res; +} + +static gboolean +foreach_func (GstCapsFeatures *features, + GstStructure *structure, + GPtrArray *array) +{ + SpaFormat *fmt; + + if ((fmt = convert_1 (features, structure))) + g_ptr_array_insert (array, -1, fmt); + + return TRUE; +} + + +GPtrArray * +gst_caps_to_format_all (GstCaps *caps) +{ + GPtrArray *res; + + res = g_ptr_array_new_full (gst_caps_get_size (caps), + (GDestroyNotify)spa_format_unref); + + gst_caps_foreach (caps, (GstCapsForeachFunc) foreach_func, res); + + return res; +} + +GstCaps * +gst_caps_from_format (SpaFormat *format) +{ + GstCaps *res = NULL; + + if (format->media_type == SPA_MEDIA_TYPE_VIDEO) { + 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, + NULL); + } + } else if (format->media_type == SPA_MEDIA_TYPE_AUDIO) { + if (format->media_subtype == SPA_MEDIA_SUBTYPE_RAW) { + SpaAudioRawFormat f; + + spa_audio_raw_format_parse (format, &f); + + res = gst_caps_new_simple ("audio/x-raw", + "format", G_TYPE_STRING, gst_audio_format_to_string (f.info.format), + "layout", G_TYPE_STRING, "interleaved", + "rate", G_TYPE_INT, f.info.rate, + "channels", G_TYPE_INT, f.info.channels, + NULL); + } + } + return res; +} diff --git a/pinos/gst/gstpinosformat.h b/pinos/gst/gstpinosformat.h new file mode 100644 index 000000000..62e57f1ac --- /dev/null +++ b/pinos/gst/gstpinosformat.h @@ -0,0 +1,36 @@ +/* GStreamer + * 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 _GST_PINOS_FORMAT_H_ +#define _GST_PINOS_FORMAT_H_ + +#include + +#include + +G_BEGIN_DECLS + +SpaFormat * gst_caps_to_format (GstCaps *caps, guint index); +GPtrArray * gst_caps_to_format_all (GstCaps *caps); + +GstCaps * gst_caps_from_format (SpaFormat *format); + +G_END_DECLS + +#endif diff --git a/pinos/gst/gstpinossink.c b/pinos/gst/gstpinossink.c index 8405fb947..928a5a2a0 100644 --- a/pinos/gst/gstpinossink.c +++ b/pinos/gst/gstpinossink.c @@ -46,6 +46,7 @@ #include #include "gsttmpfileallocator.h" +#include "gstpinosformat.h" GST_DEBUG_CATEGORY_STATIC (pinos_sink_debug); @@ -412,15 +413,17 @@ static gboolean gst_pinos_sink_setcaps (GstBaseSink * bsink, GstCaps * caps) { GstPinosSink *pinossink; - gchar *str; - GBytes *format; + GPtrArray *possible; + SpaFormat *format; PinosStreamState state; gboolean res = FALSE; pinossink = GST_PINOS_SINK (bsink); - str = gst_caps_to_string (caps); - format = g_bytes_new_take (str, strlen (str) + 1); + format = gst_caps_to_format (caps, 0); + possible = g_ptr_array_new (); + spa_format_ref (format); + g_ptr_array_insert (possible, -1, format); pinos_main_loop_lock (pinossink->loop); state = pinos_stream_get_state (pinossink->stream); @@ -438,7 +441,7 @@ gst_pinos_sink_setcaps (GstBaseSink * bsink, GstCaps * caps) PINOS_DIRECTION_OUTPUT, pinossink->path, flags, - g_bytes_ref (format)); + possible); while (TRUE) { state = pinos_stream_get_state (pinossink->stream); @@ -455,7 +458,7 @@ gst_pinos_sink_setcaps (GstBaseSink * bsink, GstCaps * caps) if (state != PINOS_STREAM_STATE_STREAMING) { res = pinos_stream_start (pinossink->stream, - g_bytes_ref (format), + format, PINOS_STREAM_MODE_BUFFER); while (TRUE) { @@ -471,7 +474,6 @@ gst_pinos_sink_setcaps (GstBaseSink * bsink, GstCaps * caps) } } pinos_main_loop_unlock (pinossink->loop); - g_bytes_unref (format); pinossink->negotiated = res; @@ -481,7 +483,7 @@ start_error: { GST_ERROR ("could not start stream"); pinos_main_loop_unlock (pinossink->loop); - g_bytes_unref (format); + spa_format_unref (format); return FALSE; } } @@ -517,10 +519,10 @@ gst_pinos_sink_render (GstBaseSink * bsink, GstBuffer * buffer) b = g_slice_new (SinkBuffer); b->buffer.id = pinos_fd_manager_get_id (pinossink->fdmanager); - b->buffer.mem.pool_id = SPA_ID_INVALID; - b->buffer.mem.id = SPA_ID_INVALID; - b->buffer.offset = 0; - b->buffer.size = sizeof (SinkBuffer); + b->buffer.mem.mem.pool_id = SPA_ID_INVALID; + b->buffer.mem.mem.id = SPA_ID_INVALID; + b->buffer.mem.offset = 0; + b->buffer.mem.size = sizeof (SinkBuffer); b->buffer.n_metas = 1; b->buffer.metas = offsetof (SinkBuffer, metas); b->buffer.n_datas = 1; @@ -564,10 +566,10 @@ gst_pinos_sink_render (GstBaseSink * bsink, GstBuffer * buffer) b->mem = mem; b->fd = gst_fd_memory_get_fd (mem); - b->datas[0].mem.pool_id = SPA_ID_INVALID; - b->datas[0].mem.id = SPA_ID_INVALID; - b->datas[0].offset = mem->offset; - b->datas[0].size = mem->size; + b->datas[0].mem.mem.pool_id = SPA_ID_INVALID; + b->datas[0].mem.mem.id = SPA_ID_INVALID; + b->datas[0].mem.offset = mem->offset; + b->datas[0].mem.size = mem->size; b->datas[0].stride = 0; if (!(res = pinos_stream_send_buffer (pinossink->stream, &b->buffer))) diff --git a/pinos/gst/gstpinossrc.c b/pinos/gst/gstpinossrc.c index d35bebfe7..41eeae503 100644 --- a/pinos/gst/gstpinossrc.c +++ b/pinos/gst/gstpinossrc.c @@ -32,6 +32,7 @@ #include "config.h" #endif #include "gstpinossrc.h" +#include "gstpinosformat.h" #include #include @@ -388,19 +389,19 @@ on_new_buffer (GObject *gobject, SpaData *d = &SPA_BUFFER_DATAS (b)[i]; SpaMemory *mem; - mem = spa_memory_find (&d->mem); + mem = spa_memory_find (&d->mem.mem); if (mem->fd) { GstMemory *fdmem = NULL; fdmem = gst_fd_allocator_alloc (pinossrc->fd_allocator, dup (mem->fd), - d->offset + d->size, GST_FD_MEMORY_FLAG_NONE); - gst_memory_resize (fdmem, d->offset, d->size); + d->mem.offset + d->mem.size, GST_FD_MEMORY_FLAG_NONE); + gst_memory_resize (fdmem, d->mem.offset, d->mem.size); gst_buffer_append_memory (buf, fdmem); } else { gst_buffer_append_memory (buf, - gst_memory_new_wrapped (0, mem->ptr, mem->size, d->offset, - d->size, NULL, NULL)); + gst_memory_new_wrapped (0, mem->ptr, mem->size, d->mem.offset, + d->mem.size, NULL, NULL)); } } @@ -485,15 +486,14 @@ parse_stream_properties (GstPinosSrc *pinossrc, PinosProperties *props) static gboolean gst_pinos_src_stream_start (GstPinosSrc *pinossrc, GstCaps * caps) { - gchar *str; - GBytes *format = NULL; + SpaFormat *format; gboolean res; PinosProperties *props; - if (caps) { - str = gst_caps_to_string (caps); - format = g_bytes_new_take (str, strlen (str) + 1); - } + if (caps) + format = gst_caps_to_format (caps, 0); + else + format = NULL; pinos_main_loop_lock (pinossrc->loop); res = pinos_stream_start (pinossrc->stream, format, PINOS_STREAM_MODE_BUFFER); @@ -515,9 +515,9 @@ gst_pinos_src_stream_start (GstPinosSrc *pinossrc, GstCaps * caps) pinos_main_loop_unlock (pinossrc->loop); if (format) { - caps = gst_caps_from_string (g_bytes_get_data (format, NULL)); + caps = gst_caps_from_format (format); gst_base_src_set_caps (GST_BASE_SRC (pinossrc), caps); - g_bytes_unref (format); + spa_format_unref (format); } parse_stream_properties (pinossrc, props); @@ -555,8 +555,7 @@ gst_pinos_src_negotiate (GstBaseSrc * basesrc) GstCaps *caps = NULL; GstCaps *peercaps = NULL; gboolean result = FALSE; - GBytes *possible; - gchar *str; + GPtrArray *possible; /* first see what is possible on our source pad */ thiscaps = gst_pad_query_caps (GST_BASE_SRC_PAD (basesrc), NULL); @@ -585,8 +584,7 @@ gst_pinos_src_negotiate (GstBaseSrc * basesrc) GST_DEBUG_OBJECT (basesrc, "have common caps: %" GST_PTR_FORMAT, caps); /* open a connection with these caps */ - str = gst_caps_to_string (caps); - possible = g_bytes_new_take (str, strlen (str) + 1); + possible = gst_caps_to_format_all (caps); /* first disconnect */ pinos_main_loop_lock (pinossrc->loop); @@ -600,7 +598,7 @@ gst_pinos_src_negotiate (GstBaseSrc * basesrc) break; if (state == PINOS_STREAM_STATE_ERROR) { - g_bytes_unref (possible); + g_ptr_array_unref (possible); goto connect_error; } @@ -672,12 +670,12 @@ on_format_notify (GObject *gobject, gpointer user_data) { GstPinosSrc *pinossrc = user_data; - GBytes *format; + SpaFormat *format; GstCaps *caps; g_object_get (gobject, "format", &format, NULL); - caps = gst_caps_from_string (g_bytes_get_data (format, NULL)); + caps = gst_caps_from_format (format); gst_base_src_set_caps (GST_BASE_SRC (pinossrc), caps); gst_caps_unref (caps); } diff --git a/pinos/modules/spa/spa-alsa-sink.c b/pinos/modules/spa/spa-alsa-sink.c index 713da46e5..7dc72c574 100644 --- a/pinos/modules/spa/spa-alsa-sink.c +++ b/pinos/modules/spa/spa-alsa-sink.c @@ -444,10 +444,10 @@ on_received_buffer (PinosPort *port, uint8_t *data; size_t size, towrite, total; - mem = spa_memory_find (&d[i].mem); + mem = spa_memory_find (&d[i].mem.mem); - size = d[i].size; - data = (guint8*)mem->ptr + d[i].offset; + size = d[i].mem.size; + data = SPA_MEMBER (mem->ptr, d[i].mem.offset, uint8_t); pinos_ringbuffer_get_write_areas (priv->ringbuffer, areas); diff --git a/pinos/server/link.c b/pinos/server/link.c index f24ade9d2..11fc8765b 100644 --- a/pinos/server/link.c +++ b/pinos/server/link.c @@ -269,8 +269,8 @@ do_negotiate (PinosLink *this) value.type = SPA_PROP_TYPE_RECTANGLE; value.size = sizeof (SpaRectangle); value.value = ▭ - rect.width = 320; - rect.height = 240; + rect.width = 640; + rect.height = 480; if ((res = spa_props_set_prop (props, spa_props_index_for_id (props, SPA_PROP_ID_VIDEO_SIZE), &value)) < 0) return res; diff --git a/pinos/tests/test-client.c b/pinos/tests/test-client.c index 56409d9f7..570dfc329 100644 --- a/pinos/tests/test-client.c +++ b/pinos/tests/test-client.c @@ -81,17 +81,14 @@ on_stream_notify (GObject *gobject, case PINOS_STREAM_STATE_READY: { - GBytes *possible, *format; - GstCaps *caps; - GstStructure *structure; - gchar *str; + GPtrArray *possible; + SpaFormat *format; g_object_get (s, "possible-formats", &possible, NULL); - caps = gst_caps_from_string (g_bytes_get_data (possible, NULL)); - - structure = gst_caps_get_structure (caps, 0); + format = g_ptr_array_index (possible, 0); +#if 0 /* set some reasonable defaults */ if (gst_structure_has_field (structure, "width")) gst_structure_fixate_field_nearest_int (structure, "width", 320); @@ -104,8 +101,9 @@ on_stream_notify (GObject *gobject, caps = gst_caps_fixate (caps); str = gst_caps_to_string (caps); gst_caps_unref (caps); - format = g_bytes_new_static (str, strlen (str) + 1); +#endif + pinos_stream_start (s, format, PINOS_STREAM_MODE_SOCKET); break; } @@ -136,14 +134,14 @@ on_state_notify (GObject *gobject, case PINOS_CONTEXT_STATE_CONNECTED: { PinosStream *stream; - GBytes *format; + GPtrArray *possible; stream = pinos_stream_new (c, "test", NULL); g_signal_connect (stream, "notify::state", (GCallback) on_stream_notify, stream); g_signal_connect (stream, "notify::socket", (GCallback) on_socket_notify, stream); - format = g_bytes_new_static (ANY_CAPS, strlen (ANY_CAPS) + 1); - pinos_stream_connect (stream, PINOS_DIRECTION_OUTPUT, NULL, 0, format); + possible = NULL; + pinos_stream_connect (stream, PINOS_DIRECTION_OUTPUT, NULL, 0, possible); break; } default: diff --git a/spa/include/spa/buffer.h b/spa/include/spa/buffer.h index f8bc70b5f..36292359e 100644 --- a/spa/include/spa/buffer.h +++ b/spa/include/spa/buffer.h @@ -102,37 +102,29 @@ typedef struct { /** * SpaData: * @mem: reference to the memory to use - * @offset: ofset in memory - * @size: size of memory * @stride: stride of memory if applicable */ typedef struct { - SpaMemoryRef mem; - off_t offset; - size_t size; - size_t stride; + SpaMemoryChunk mem; + ssize_t stride; } SpaData; /** * SpaBuffer: * @id: buffer id * @mem: reference to the memory for this buffer - * @offset: offset inside memory - * @size: of of memory * @n_metas: number of metadata * @metas: offset of array of @n_metas metadata * @n_datas: number of data pointers * @datas: offset of array of @n_datas data pointers */ struct _SpaBuffer { - uint32_t id; - SpaMemoryRef mem; - off_t offset; - size_t size; - unsigned int n_metas; - off_t metas; - unsigned int n_datas; - off_t datas; + uint32_t id; + SpaMemoryChunk mem; + unsigned int n_metas; + off_t metas; + unsigned int n_datas; + off_t datas; }; #define SPA_BUFFER_METAS(b) (SPA_MEMBER ((b), (b)->metas, SpaMeta)) diff --git a/spa/include/spa/control.h b/spa/include/spa/control.h index 04c9357ac..b4c52264c 100644 --- a/spa/include/spa/control.h +++ b/spa/include/spa/control.h @@ -91,8 +91,8 @@ typedef enum { /* SPA_CONTROL_CMD_NODE_UPDATE */ typedef struct { uint32_t change_mask; - uint32_t max_input_ports; - uint32_t max_output_ports; + unsigned int max_input_ports; + unsigned int max_output_ports; const SpaProps *props; } SpaControlCmdNodeUpdate; @@ -100,8 +100,8 @@ typedef struct { typedef struct { uint32_t port_id; uint32_t change_mask; - uint32_t direction; - uint32_t n_possible_formats; + SpaDirection direction; + unsigned int n_possible_formats; const SpaFormat **possible_formats; const SpaProps *props; const SpaPortInfo *info; @@ -132,8 +132,8 @@ typedef struct { /* SPA_CONTROL_CMD_ADD_PORT */ typedef struct { - uint32_t port_id; - uint32_t direction; + uint32_t port_id; + SpaDirection direction; } SpaControlCmdAddPort; /* SPA_CONTROL_CMD_REMOVE_PORT */ @@ -152,7 +152,7 @@ typedef struct { typedef struct { uint32_t port_id; uint32_t id; - uint32_t size; + size_t size; void *value; } SpaControlCmdSetProperty; @@ -164,24 +164,22 @@ typedef struct { uint32_t port_id; SpaMemoryRef mem; uint32_t mem_type; - uint32_t fd_index; + unsigned int fd_index; uint32_t flags; - uint64_t size; + size_t size; } SpaControlCmdAddMem; /* SPA_CONTROL_CMD_REMOVE_MEM */ typedef struct { - uint32_t port_id; + uint32_t port_id; SpaMemoryRef mem; } SpaControlCmdRemoveMem; /* SPA_CONTROL_CMD_ADD_BUFFER */ typedef struct { - uint32_t port_id; - uint32_t buffer_id; - SpaMemoryRef mem; - off_t offset; - size_t size; + uint32_t port_id; + uint32_t buffer_id; + SpaMemoryChunk mem; } SpaControlCmdAddBuffer; /* SPA_CONTROL_CMD_REMOVE_BUFFER */ @@ -194,16 +192,16 @@ typedef struct { typedef struct { uint32_t port_id; uint32_t buffer_id; - uint64_t offset; - uint64_t size; + off_t offset; + size_t size; } SpaControlCmdProcessBuffer; /* SPA_CONTROL_CMD_REUSE_BUFFER */ typedef struct { uint32_t port_id; uint32_t buffer_id; - uint64_t offset; - uint64_t size; + off_t offset; + size_t size; } SpaControlCmdReuseBuffer; @@ -221,7 +219,8 @@ SpaResult spa_control_iter_next (SpaControlIter *iter); SpaResult spa_control_iter_end (SpaControlIter *iter); SpaControlCmd spa_control_iter_get_cmd (SpaControlIter *iter); -void * spa_control_iter_get_data (SpaControlIter *iter, size_t *size); +void * spa_control_iter_get_data (SpaControlIter *iter, + size_t *size); SpaResult spa_control_iter_parse_cmd (SpaControlIter *iter, void *command); diff --git a/spa/include/spa/format.h b/spa/include/spa/format.h index 8f8a44a47..e6f0ea083 100644 --- a/spa/include/spa/format.h +++ b/spa/include/spa/format.h @@ -62,22 +62,34 @@ typedef enum { * @media_type: media type * @media_subtype: subtype * @mem: memory reference + * @offset: offset in memory + * @size: size in memory */ struct _SpaFormat { SpaProps props; SpaMediaType media_type; SpaMediaSubType media_subtype; - SpaMemoryRef mem; + SpaMemoryChunk mem; }; -#define spa_format_ref(f) spa_memory_ref(&(f)->mem) -#define spa_format_unref(f) spa_memory_unref(&(f)->mem) +static inline void +spa_format_ref (SpaFormat *format) +{ + spa_memory_ref (&format->mem.mem); +} + +static inline void +spa_format_unref (SpaFormat *format) +{ + spa_memory_unref (&format->mem.mem); +} typedef enum { SPA_PROP_ID_INVALID = 0, SPA_PROP_ID_MEDIA_CUSTOM_START = 200, } SpaFormatProps; + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/spa/include/spa/memory.h b/spa/include/spa/memory.h index 13f1e32e7..751012023 100644 --- a/spa/include/spa/memory.h +++ b/spa/include/spa/memory.h @@ -26,6 +26,7 @@ extern "C" { typedef struct _SpaMemory SpaMemory; typedef struct _SpaMemoryRef SpaMemoryRef; +typedef struct _SpaMemoryChunk SpaMemoryChunk; typedef struct _SpaMemoryPool SpaMemoryPool; #include @@ -48,12 +49,27 @@ typedef enum { * SpaMemoryRef: * @pool_id: the pool id * @id: mem_id + * + * A reference to a block of memory */ struct _SpaMemoryRef { uint32_t pool_id; uint32_t id; }; +/** + * SpaMemoryChunk: + * @mem: the memory + * @offset: the offset in the memory + * @size: the size in the memory + * + * A reference to a part of memory + */ +struct _SpaMemoryChunk { + SpaMemoryRef mem; + off_t offset; + size_t size; +}; /** * SpaMemory: * @refcount: a refcount diff --git a/spa/lib/control.c b/spa/lib/control.c index e0399c2fa..3eb77d8c7 100644 --- a/spa/lib/control.c +++ b/spa/lib/control.c @@ -353,7 +353,9 @@ iter_parse_set_format (struct stack_iter *si, SpaControlCmdSetFormat *cmd) cmd->port_id = *p++; mem = spa_memory_alloc_size (SPA_MEMORY_POOL_LOCAL, p, si->size - 4); cmd->format = spa_memory_ensure_ptr (mem); - cmd->format->mem = mem->mem; + cmd->format->mem.mem = mem->mem; + cmd->format->mem.offset = 0; + cmd->format->mem.size = mem->size; tp = (SpaProps *) &cmd->format->props; tp->prop_info = SPA_MEMBER (tp, SPA_PTR_TO_INT (tp->prop_info), SpaPropInfo); @@ -763,10 +765,10 @@ builder_add_set_format (struct stack_builder *sb, SpaControlCmdSetFormat *sf) tp = SPA_MEMBER (tf, offsetof (SpaFormat, props), SpaProps); tp->n_prop_info = sp->n_prop_info; - tp->prop_info = SPA_INT_TO_PTR (sizeof (SpaProps) + sizeof (uint32_t)); + tp->prop_info = SPA_INT_TO_PTR (sizeof (SpaFormat) + sizeof (uint32_t)); /* write propinfo array, adjust offset of mask */ - bpi = pi = (SpaPropInfo *) ((uint8_t *)tp + sizeof (SpaProps) + sizeof (uint32_t)); + bpi = pi = (SpaPropInfo *) ((uint8_t *)tp + sizeof (SpaFormat) + sizeof (uint32_t)); for (i = 0; i < tp->n_prop_info; i++) { memcpy (pi, &sp->prop_info[i], sizeof (SpaPropInfo)); pi->mask_offset = sizeof (SpaFormat); diff --git a/spa/lib/debug.c b/spa/lib/debug.c index e96d875ab..704c16b0d 100644 --- a/spa/lib/debug.c +++ b/spa/lib/debug.c @@ -92,10 +92,10 @@ spa_debug_buffer (const SpaBuffer *buffer) fprintf (stderr, "SpaBuffer %p:\n", buffer); fprintf (stderr, " id: %08X\n", buffer->id); - fprintf (stderr, " pool_id: %08X\n", buffer->mem.pool_id); - fprintf (stderr, " mem_id: %08X\n", buffer->mem.id); - fprintf (stderr, " offset: %zd\n", buffer->offset); - fprintf (stderr, " size: %zd\n", buffer->size); + fprintf (stderr, " pool_id: %08X\n", buffer->mem.mem.pool_id); + fprintf (stderr, " mem_id: %08X\n", buffer->mem.mem.id); + fprintf (stderr, " offset: %zd\n", buffer->mem.offset); + fprintf (stderr, " size: %zd\n", buffer->mem.size); fprintf (stderr, " n_metas: %u (offset %zd)\n", buffer->n_metas, buffer->metas); for (i = 0; i < buffer->n_metas; i++) { SpaMeta *m = &SPA_BUFFER_METAS (buffer)[i]; @@ -129,7 +129,7 @@ spa_debug_buffer (const SpaBuffer *buffer) SpaData *d = &SPA_BUFFER_DATAS (buffer)[i]; SpaMemory *mem; - mem = spa_memory_find (&d->mem); + mem = spa_memory_find (&d->mem.mem); fprintf (stderr, " data %d: (memory %p)\n", i, mem); if (mem) { fprintf (stderr, " pool_id: %u\n", mem->mem.pool_id); @@ -142,8 +142,8 @@ spa_debug_buffer (const SpaBuffer *buffer) } else { fprintf (stderr, " invalid memory reference\n"); } - fprintf (stderr, " offset: %zd\n", d->offset); - fprintf (stderr, " size: %zd\n", d->size); + fprintf (stderr, " offset: %zd\n", d->mem.offset); + fprintf (stderr, " size: %zd\n", d->mem.size); fprintf (stderr, " stride: %zd\n", d->stride); } return SPA_RESULT_OK; diff --git a/spa/lib/format.c b/spa/lib/format.c new file mode 100644 index 000000000..acc70d9f9 --- /dev/null +++ b/spa/lib/format.c @@ -0,0 +1,40 @@ +/* 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. + */ + +#include +#include +#include +#include + +#include + +SpaResult +spa_format_to_string (const SpaFormat *format, char **result) +{ + SpaResult res; + + if (format == NULL || result == NULL) + return SPA_RESULT_INVALID_ARGUMENTS; + + + + + + return SPA_RESULT_OK; +} diff --git a/spa/lib/memfd-wrappers.h b/spa/lib/memfd-wrappers.h new file mode 100644 index 000000000..8d6ac8b2a --- /dev/null +++ b/spa/lib/memfd-wrappers.h @@ -0,0 +1,59 @@ +/* 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. + */ + +#include +#include + +/* + * No glibc wrappers exist for memfd_create(2), so provide our own. + * + * Also define memfd fcntl sealing macros. While they are already + * defined in the kernel header file , that file as + * a whole conflicts with the original glibc header . + */ + +static inline int memfd_create(const char *name, unsigned int flags) { + return syscall(SYS_memfd_create, name, flags); +} + +/* memfd_create(2) flags */ + +#ifndef MFD_CLOEXEC +#define MFD_CLOEXEC 0x0001U +#endif + +#ifndef MFD_ALLOW_SEALING +#define MFD_ALLOW_SEALING 0x0002U +#endif + +/* fcntl() seals-related flags */ + +#ifndef F_LINUX_SPECIFIC_BASE +#define F_LINUX_SPECIFIC_BASE 1024 +#endif + +#ifndef F_ADD_SEALS +#define F_ADD_SEALS (F_LINUX_SPECIFIC_BASE + 9) +#define F_GET_SEALS (F_LINUX_SPECIFIC_BASE + 10) + +#define F_SEAL_SEAL 0x0001 /* prevent further seals from being set */ +#define F_SEAL_SHRINK 0x0002 /* prevent file from shrinking */ +#define F_SEAL_GROW 0x0004 /* prevent file from growing */ +#define F_SEAL_WRITE 0x0008 /* prevent writes */ +#endif diff --git a/spa/lib/memory.c b/spa/lib/memory.c index a9de29a62..371e20220 100644 --- a/spa/lib/memory.c +++ b/spa/lib/memory.c @@ -29,6 +29,7 @@ #include #include "spa/memory.h" +#include "memfd-wrappers.h" #define MAX_POOLS 16 #define MAX_MEMORIES 1024 @@ -144,17 +145,23 @@ SpaMemory * spa_memory_alloc_with_fd (uint32_t pool_id, void *data, size_t size) { SpaMemory *mem; - char filename[] = "/dev/shm/spa-tmpfile.XXXXXX"; if (!(mem = spa_memory_alloc (pool_id))) return NULL; - mem->fd = mkostemp (filename, O_CLOEXEC); - if (mem->fd == -1) { - fprintf (stderr, "Failed to create temporary file: %s\n", strerror (errno)); - return NULL; +#if 0 + { + char filename[] = "/dev/shm/spa-tmpfile.XXXXXX"; + mem->fd = mkostemp (filename, O_CLOEXEC); + if (mem->fd == -1) { + fprintf (stderr, "Failed to create temporary file: %s\n", strerror (errno)); + return NULL; + } + unlink (filename); } - unlink (filename); +#else + mem->fd = memfd_create ("spa-memfd", MFD_CLOEXEC | MFD_ALLOW_SEALING); +#endif if (data) { if (write (mem->fd, data, size) != (ssize_t) size) { @@ -169,6 +176,18 @@ spa_memory_alloc_with_fd (uint32_t pool_id, void *data, size_t size) return NULL; } } +#if 1 + { + unsigned int seals; + + seals = F_SEAL_GROW | F_SEAL_SHRINK | F_SEAL_SEAL; + if (fcntl (mem->fd, F_ADD_SEALS, seals) == -1) { + fprintf (stderr, "Failed to write data: %s\n", strerror (errno)); + close (mem->fd); + return NULL; + } + } +#endif mem->flags = SPA_MEMORY_FLAG_READWRITE; mem->size = size; @@ -209,6 +228,8 @@ spa_memory_import (SpaMemoryRef *ref) mem->mem = *ref; mem->ptr = NULL; mem->fd = -1; + } else { + mem->refcount++; } return mem; @@ -236,6 +257,9 @@ spa_memory_free (SpaMemory *mem) if (mem->ptr) munmap (mem->ptr, mem->size); close (mem->fd); + } else { + if (mem->ptr) + free (mem->ptr); } pool = &pools[mem->mem.pool_id]; pool->free_mem[pool->n_free] = mem->mem.id; diff --git a/spa/plugins/audiomixer/audiomixer.c b/spa/plugins/audiomixer/audiomixer.c index 40a9fc77c..d0c92bcbc 100644 --- a/spa/plugins/audiomixer/audiomixer.c +++ b/spa/plugins/audiomixer/audiomixer.c @@ -550,7 +550,7 @@ spa_audiomixer_node_port_push_input (SpaNode *node, continue; } this->ports[idx].buffer = buffer; - this->ports[idx].buffer_queued = buffer->size; + this->ports[idx].buffer_queued = buffer->mem.size; this->ports[idx].buffer_index = 0; this->ports[idx].buffer_offset = 0; this->port_queued++; @@ -597,14 +597,14 @@ add_port_data (SpaAudioMixer *this, SpaBuffer *out, SpaAudioMixerPort *port) while (true) { if (op == NULL) { - mem = spa_memory_find (&odatas[oi].mem); - op = (uint8_t*)mem->ptr + odatas[oi].offset; - os = odatas[oi].size; + mem = spa_memory_find (&odatas[oi].mem.mem); + op = (uint8_t*)mem->ptr + odatas[oi].mem.offset; + os = odatas[oi].mem.size; } if (ip == NULL) { - mem = spa_memory_find (&idatas[port->buffer_index].mem); - ip = (uint8_t*)mem->ptr + odatas[oi].offset; - is = idatas[port->buffer_index].size; + mem = spa_memory_find (&idatas[port->buffer_index].mem.mem); + ip = (uint8_t*)mem->ptr + odatas[oi].mem.offset; + is = idatas[port->buffer_index].mem.size; ip += port->buffer_offset; is -= port->buffer_offset; } diff --git a/spa/plugins/remote/proxy.c b/spa/plugins/remote/proxy.c index 527bb147c..39e13d674 100644 --- a/spa/plugins/remote/proxy.c +++ b/spa/plugins/remote/proxy.c @@ -28,9 +28,10 @@ #include -#include -#include #include +#include +#include +#include #define MAX_INPUTS 64 #define MAX_OUTPUTS 64 @@ -443,6 +444,9 @@ spa_proxy_node_port_set_format (SpaNode *node, spa_control_builder_init_into (&builder, buf, sizeof (buf), NULL, 0); sf.port_id = port_id; sf.format = (SpaFormat *) format; + + spa_debug_format (sf.format); + spa_control_builder_add_cmd (&builder, SPA_CONTROL_CMD_SET_FORMAT, &sf); spa_control_builder_end (&builder, &control); @@ -563,14 +567,14 @@ add_buffer (SpaProxy *this, uint32_t port_id, SpaBuffer *buffer) spa_control_builder_init_into (&builder, buf, sizeof (buf), fds, sizeof (fds)); - if (buffer->mem.id == SPA_ID_INVALID) { + if (buffer->mem.mem.id == SPA_ID_INVALID) { fprintf (stderr, "proxy %p: alloc buffer space\n", this); - bmem = spa_memory_alloc_with_fd (SPA_MEMORY_POOL_SHARED, buffer, buffer->size); + bmem = spa_memory_alloc_with_fd (SPA_MEMORY_POOL_SHARED, buffer, buffer->mem.size); b = spa_memory_ensure_ptr (bmem); - b->mem = bmem->mem; - b->offset = 0; + b->mem.mem = bmem->mem; + b->mem.offset = 0; } else { - bmem = spa_memory_find (&buffer->mem); + bmem = spa_memory_find (&buffer->mem.mem); b = buffer; } @@ -586,7 +590,7 @@ add_buffer (SpaProxy *this, uint32_t port_id, SpaBuffer *buffer) SpaData *d = &SPA_BUFFER_DATAS (b)[i]; SpaMemory *mem; - if (!(mem = spa_memory_find (&d->mem))) { + if (!(mem = spa_memory_find (&d->mem.mem))) { fprintf (stderr, "proxy %p: error invalid memory\n", this); continue; } @@ -601,9 +605,9 @@ add_buffer (SpaProxy *this, uint32_t port_id, SpaBuffer *buffer) } ab.port_id = port_id; ab.buffer_id = b->id; - ab.mem = bmem->mem; - ab.offset = b->offset; - ab.size = b->size; + 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); spa_control_builder_end (&builder, &control); @@ -632,14 +636,14 @@ remove_buffer (SpaProxy *this, uint32_t port_id, SpaBuffer *buffer) 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; + 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; + rm.mem = d->mem.mem; spa_control_builder_add_cmd (&builder, SPA_CONTROL_CMD_REMOVE_MEM, &rm); } spa_control_builder_end (&builder, &control); diff --git a/spa/plugins/v4l2/v4l2-utils.c b/spa/plugins/v4l2/v4l2-utils.c index ca476bebe..d49c858db 100644 --- a/spa/plugins/v4l2/v4l2-utils.c +++ b/spa/plugins/v4l2/v4l2-utils.c @@ -537,16 +537,16 @@ spa_v4l2_import_buffers (SpaV4l2Source *this, SpaBuffer **buffers, uint32_t n_bu SpaData *d = SPA_BUFFER_DATAS (buffers[i]); b = &state->alloc_buffers[i]; - b->buffer.mem = state->alloc_mem->mem; - b->buffer.offset = sizeof (V4l2Buffer) * i; - b->buffer.size = sizeof (V4l2Buffer); + b->buffer.mem.mem = state->alloc_mem->mem; + b->buffer.mem.offset = sizeof (V4l2Buffer) * i; + b->buffer.mem.size = sizeof (V4l2Buffer); b->buffer.id = SPA_ID_INVALID; b->outbuf = buffers[i]; b->outstanding = true; fprintf (stderr, "import buffer %p\n", buffers[i]); - mem_ref = &SPA_BUFFER_DATAS (buffers[i])[0].mem; + mem_ref = &SPA_BUFFER_DATAS (buffers[i])[0].mem.mem; if (!(mem = spa_memory_find (mem_ref))) { fprintf (stderr, "invalid memory on buffer %p\n", buffers[i]); continue; @@ -556,8 +556,8 @@ spa_v4l2_import_buffers (SpaV4l2Source *this, SpaBuffer **buffers, uint32_t n_bu 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) ((uint8_t*)mem->ptr + d[0].offset); - b->v4l2_buffer.length = d[0].size; + b->v4l2_buffer.m.userptr = (unsigned long) ((uint8_t*)mem->ptr + d[0].mem.offset); + b->v4l2_buffer.length = d[0].mem.size; spa_v4l2_buffer_recycle (this, buffers[i]->id); } @@ -625,9 +625,9 @@ mmap_init (SpaV4l2Source *this, b = &state->alloc_buffers[i]; b->buffer.id = i; - b->buffer.mem = state->alloc_mem->mem; - b->buffer.offset = sizeof (V4l2Buffer) * i; - b->buffer.size = sizeof (V4l2Buffer); + b->buffer.mem.mem = state->alloc_mem->mem; + b->buffer.mem.offset = sizeof (V4l2Buffer) * i; + b->buffer.mem.size = sizeof (V4l2Buffer); buffers[i] = &b->buffer; @@ -648,9 +648,9 @@ mmap_init (SpaV4l2Source *this, mem = spa_memory_alloc (SPA_MEMORY_POOL_SHARED); mem->flags = SPA_MEMORY_FLAG_READABLE; mem->size = buf.length; - b->datas[0].mem = mem->mem; - b->datas[0].offset = 0; - b->datas[0].size = buf.length; + b->datas[0].mem.mem = mem->mem; + b->datas[0].mem.offset = 0; + b->datas[0].mem.size = buf.length; b->datas[0].stride = state->fmt.fmt.pix.bytesperline; if (state->export_buf) { @@ -797,7 +797,7 @@ spa_v4l2_stop (SpaV4l2Source *this) fprintf (stderr, "queueing outstanding buffer %p\n", b); spa_v4l2_buffer_recycle (this, i); } - mem = spa_memory_find (&b->datas[0].mem); + mem = spa_memory_find (&b->datas[0].mem.mem); if (state->export_buf) { close (mem->fd); } else { diff --git a/spa/plugins/volume/volume.c b/spa/plugins/volume/volume.c index 9dec16fcc..26e4779df 100644 --- a/spa/plugins/volume/volume.c +++ b/spa/plugins/volume/volume.c @@ -583,13 +583,13 @@ spa_volume_node_port_pull_output (SpaNode *node, sd = &SPA_BUFFER_DATAS (sbuf)[si]; dd = &SPA_BUFFER_DATAS (dbuf)[di]; - sm = spa_memory_find (&sd->mem); - dm = spa_memory_find (&dd->mem); + sm = spa_memory_find (&sd->mem.mem); + dm = spa_memory_find (&dd->mem.mem); - src = (uint16_t*) ((uint8_t*)sm->ptr + sd->offset + soff); - dst = (uint16_t*) ((uint8_t*)dm->ptr + dd->offset + doff); + src = (uint16_t*) ((uint8_t*)sm->ptr + sd->mem.offset + soff); + dst = (uint16_t*) ((uint8_t*)dm->ptr + dd->mem.offset + doff); - n_bytes = SPA_MIN (sd->size - soff, dd->size - doff); + n_bytes = SPA_MIN (sd->mem.size - soff, dd->mem.size - doff); n_samples = n_bytes / sizeof (uint16_t); for (i = 0; i < n_samples; i++) @@ -598,11 +598,11 @@ spa_volume_node_port_pull_output (SpaNode *node, soff += n_bytes; doff += n_bytes; - if (soff >= sd->size) { + if (soff >= sd->mem.size) { si++; soff = 0; } - if (doff >= dd->size) { + if (doff >= dd->mem.size) { di++; doff = 0; } diff --git a/spa/tests/test-v4l2.c b/spa/tests/test-v4l2.c index da83a9208..dc9d71d2f 100644 --- a/spa/tests/test-v4l2.c +++ b/spa/tests/test-v4l2.c @@ -150,19 +150,19 @@ on_source_event (SpaNode *node, SpaEvent *event, void *user_data) fprintf (stderr, "Couldn't lock texture: %s\n", SDL_GetError()); return; } - mem = spa_memory_find (&datas[0].mem); + mem = spa_memory_find (&datas[0].mem.mem); mem->ptr = sdata; mem->type = "sysmem"; mem->size = sstride * 240; - datas[0].size = sstride * 240; + datas[0].mem.size = sstride * 240; datas[0].stride = sstride; } else { if (SDL_LockTexture (data->texture, NULL, &ddata, &dstride) < 0) { fprintf (stderr, "Couldn't lock texture: %s\n", SDL_GetError()); return; } - mem = spa_memory_find (&datas[0].mem); + mem = spa_memory_find (&datas[0].mem.mem); sdata = spa_memory_ensure_ptr (mem); sstride = datas[0].stride; @@ -252,10 +252,10 @@ alloc_buffers (AppData *data) } b->buffer.id = i; - b->buffer.mem.pool_id = SPA_ID_INVALID; - b->buffer.mem.id = SPA_ID_INVALID; - b->buffer.offset = 0; - b->buffer.size = sizeof (SDLBuffer); + b->buffer.mem.mem.pool_id = SPA_ID_INVALID; + b->buffer.mem.mem.id = SPA_ID_INVALID; + b->buffer.mem.offset = 0; + b->buffer.mem.size = sizeof (SDLBuffer); b->buffer.n_metas = 2; b->buffer.metas = offsetof (SDLBuffer, metas); b->buffer.n_datas = 1; @@ -282,9 +282,9 @@ alloc_buffers (AppData *data) mem->ptr = ptr; mem->size = stride * 240; - b->datas[0].mem = mem->mem; - b->datas[0].offset = 0; - b->datas[0].size = mem->size; + b->datas[0].mem.mem = mem->mem; + b->datas[0].mem.offset = 0; + b->datas[0].mem.size = mem->size; b->datas[0].stride = stride; } data->n_buffers = MAX_BUFFERS;