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;