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.
This commit is contained in:
Wim Taymans 2016-08-05 16:39:26 +02:00
parent dd1fbef28f
commit ac5d22ec79
26 changed files with 638 additions and 199 deletions

View file

@ -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

44
pinos/client/format.c Normal file
View file

@ -0,0 +1,44 @@
/* Pinos
* Copyright (C) 2015 Wim Taymans <wim.taymans@gmail.com>
*
* 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 <pinos/client/format.h>
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);

37
pinos/client/format.h Normal file
View file

@ -0,0 +1,37 @@
/* Pinos
* Copyright (C) 2015 Wim Taymans <wim.taymans@gmail.com>
*
* 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 <glib-object.h>
#include <spa/include/spa/format.h>
G_BEGIN_DECLS
#define SPA_TYPE_FORMAT (spa_format_get_type())
GType spa_format_get_type (void);
G_END_DECLS
#endif /* __PINOS_FORMAT_H__ */

View file

@ -21,6 +21,10 @@
#include <string.h>
#include <sys/mman.h>
#include "spa/include/spa/control.h"
#include "spa/include/spa/debug.h"
#include "spa/include/spa/memory.h"
#include <gio/gio.h>
#include <gio/gunixfdlist.h>
#include <gio/gunixfdmessage.h>
@ -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;

View file

@ -23,6 +23,7 @@
#include <glib-object.h>
#include <spa/include/spa/buffer.h>
#include <spa/include/spa/format.h>
#include <pinos/client/context.h>
@ -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);

170
pinos/gst/gstpinosformat.c Normal file
View file

@ -0,0 +1,170 @@
/* GStreamer
* Copyright (C) 2016 Wim Taymans <wim.taymans@gmail.com>
*
* 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 <gst/gst.h>
#include <gst/video/video.h>
#include <gst/audio/audio.h>
#include <spa/include/spa/video/format.h>
#include <spa/include/spa/audio/format.h>
#include <spa/include/spa/format.h>
#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;
}

View file

@ -0,0 +1,36 @@
/* GStreamer
* Copyright (C) 2016 Wim Taymans <wim.taymans@gmail.com>
*
* 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 <gst/gst.h>
#include <spa/include/spa/format.h>
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

View file

@ -46,6 +46,7 @@
#include <spa/include/spa/buffer.h>
#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)))

View file

@ -32,6 +32,7 @@
#include "config.h"
#endif
#include "gstpinossrc.h"
#include "gstpinosformat.h"
#include <string.h>
#include <stdlib.h>
@ -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);
}

View file

@ -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);

View file

@ -269,8 +269,8 @@ do_negotiate (PinosLink *this)
value.type = SPA_PROP_TYPE_RECTANGLE;
value.size = sizeof (SpaRectangle);
value.value = &rect;
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;

View file

@ -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:

View file

@ -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))

View file

@ -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);

View file

@ -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

View file

@ -26,6 +26,7 @@ extern "C" {
typedef struct _SpaMemory SpaMemory;
typedef struct _SpaMemoryRef SpaMemoryRef;
typedef struct _SpaMemoryChunk SpaMemoryChunk;
typedef struct _SpaMemoryPool SpaMemoryPool;
#include <spa/defs.h>
@ -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

View file

@ -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);

View file

@ -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;

40
spa/lib/format.c Normal file
View file

@ -0,0 +1,40 @@
/* Simple Plugin API
* Copyright (C) 2016 Wim Taymans <wim.taymans@gmail.com>
*
* 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 <stdint.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <spa/format.h>
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;
}

59
spa/lib/memfd-wrappers.h Normal file
View file

@ -0,0 +1,59 @@
/* Simple Plugin API
* Copyright (C) 2016 Wim Taymans <wim.taymans@gmail.com>
*
* 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 <sys/syscall.h>
#include <fcntl.h>
/*
* 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 <linux/fcntl.h>, that file as
* a whole conflicts with the original glibc header <fnctl.h>.
*/
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

View file

@ -29,6 +29,7 @@
#include <fcntl.h>
#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;

View file

@ -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;
}

View file

@ -28,9 +28,10 @@
#include <fcntl.h>
#include <spa/node.h>
#include <spa/memory.h>
#include <spa/control.h>
#include <spa/debug.h>
#include <spa/memory.h>
#include <spa/node.h>
#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);

View file

@ -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 {

View file

@ -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;
}

View file

@ -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;