mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-01 22:58:50 -04:00
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:
parent
dd1fbef28f
commit
ac5d22ec79
26 changed files with 638 additions and 199 deletions
|
|
@ -166,6 +166,7 @@ pinosgstsource = gst/gsttmpfileallocator.h gst/gsttmpfileallocator.c
|
||||||
pinosinclude_HEADERS = \
|
pinosinclude_HEADERS = \
|
||||||
client/context.h \
|
client/context.h \
|
||||||
client/enumtypes.h \
|
client/enumtypes.h \
|
||||||
|
client/format.h \
|
||||||
client/introspect.h \
|
client/introspect.h \
|
||||||
client/mainloop.h \
|
client/mainloop.h \
|
||||||
client/pinos.h \
|
client/pinos.h \
|
||||||
|
|
@ -180,6 +181,7 @@ lib_LTLIBRARIES = \
|
||||||
libpinos_@PINOS_MAJORMINOR@_la_SOURCES = \
|
libpinos_@PINOS_MAJORMINOR@_la_SOURCES = \
|
||||||
client/context.h client/context.c \
|
client/context.h client/context.c \
|
||||||
client/enumtypes.h client/enumtypes.c \
|
client/enumtypes.h client/enumtypes.c \
|
||||||
|
client/format.h client/format.c \
|
||||||
client/introspect.h client/introspect.c \
|
client/introspect.h client/introspect.c \
|
||||||
client/mainloop.h client/mainloop.c \
|
client/mainloop.h client/mainloop.c \
|
||||||
client/properties.h client/properties.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_CFLAGS = $(AM_CFLAGS) $(GST_CFLAGS)
|
||||||
libpinos_@PINOS_MAJORMINOR@_la_LDFLAGS = $(AM_LDFLAGS) -avoid-version
|
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 #
|
# Daemon core library #
|
||||||
|
|
@ -235,6 +237,7 @@ plugin_LTLIBRARIES = libgstpinos.la
|
||||||
libgstpinos_la_SOURCES = \
|
libgstpinos_la_SOURCES = \
|
||||||
gst/gstburstcache.c \
|
gst/gstburstcache.c \
|
||||||
gst/gstpinos.c \
|
gst/gstpinos.c \
|
||||||
|
gst/gstpinosformat.c \
|
||||||
gst/gstpinosdeviceprovider.c \
|
gst/gstpinosdeviceprovider.c \
|
||||||
gst/gstpinossrc.c \
|
gst/gstpinossrc.c \
|
||||||
gst/gstpinossink.c
|
gst/gstpinossink.c
|
||||||
|
|
@ -253,6 +256,7 @@ libgstpinos_la_LIBTOOLFLAGS = $(GST_PLUGIN_LIBTOOLFLAGS)
|
||||||
noinst_HEADERS = gst/gstburstcache.h gst/gstpinossrc.h \
|
noinst_HEADERS = gst/gstburstcache.h gst/gstpinossrc.h \
|
||||||
gst/gstpinossocketsink.h gst/gstpinosportsink.h \
|
gst/gstpinossocketsink.h gst/gstpinosportsink.h \
|
||||||
gst/gstpinosportsrc.h \
|
gst/gstpinosportsrc.h \
|
||||||
|
gst/gstpinosformat.h \
|
||||||
gst/gstpinossink.h gst/gstpinospay.h \
|
gst/gstpinossink.h gst/gstpinospay.h \
|
||||||
gst/gstpinosdepay.h gst/gstpinosdeviceprovider.h
|
gst/gstpinosdepay.h gst/gstpinosdeviceprovider.h
|
||||||
|
|
||||||
|
|
|
||||||
44
pinos/client/format.c
Normal file
44
pinos/client/format.c
Normal 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
37
pinos/client/format.h
Normal 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__ */
|
||||||
|
|
@ -21,6 +21,10 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/mman.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/gio.h>
|
||||||
#include <gio/gunixfdlist.h>
|
#include <gio/gunixfdlist.h>
|
||||||
#include <gio/gunixfdmessage.h>
|
#include <gio/gunixfdmessage.h>
|
||||||
|
|
@ -30,11 +34,8 @@
|
||||||
#include "pinos/client/context.h"
|
#include "pinos/client/context.h"
|
||||||
#include "pinos/client/stream.h"
|
#include "pinos/client/stream.h"
|
||||||
#include "pinos/client/enumtypes.h"
|
#include "pinos/client/enumtypes.h"
|
||||||
|
#include "pinos/client/format.h"
|
||||||
#include "pinos/client/private.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_BUFFER_SIZE 1024
|
||||||
#define MAX_FDS 16
|
#define MAX_FDS 16
|
||||||
|
|
@ -70,10 +71,11 @@ struct _PinosStreamPrivate
|
||||||
|
|
||||||
PinosDirection direction;
|
PinosDirection direction;
|
||||||
gchar *path;
|
gchar *path;
|
||||||
GBytes *possible_formats;
|
|
||||||
PinosStreamFlags flags;
|
|
||||||
|
|
||||||
GBytes *format;
|
GPtrArray *possible_formats;
|
||||||
|
SpaFormat *format;
|
||||||
|
|
||||||
|
PinosStreamFlags flags;
|
||||||
|
|
||||||
GDBusProxy *node;
|
GDBusProxy *node;
|
||||||
gboolean disconnecting;
|
gboolean disconnecting;
|
||||||
|
|
@ -188,7 +190,7 @@ pinos_stream_set_property (GObject *_object,
|
||||||
|
|
||||||
case PROP_FORMAT:
|
case PROP_FORMAT:
|
||||||
if (priv->format)
|
if (priv->format)
|
||||||
g_bytes_unref (priv->format);
|
spa_format_unref (priv->format);
|
||||||
priv->format = g_value_dup_boxed (value);
|
priv->format = g_value_dup_boxed (value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
@ -279,9 +281,9 @@ pinos_stream_finalize (GObject * object)
|
||||||
g_clear_object (&priv->node);
|
g_clear_object (&priv->node);
|
||||||
|
|
||||||
if (priv->possible_formats)
|
if (priv->possible_formats)
|
||||||
g_bytes_unref (priv->possible_formats);
|
g_ptr_array_unref (priv->possible_formats);
|
||||||
if (priv->format)
|
if (priv->format)
|
||||||
g_bytes_unref (priv->format);
|
spa_format_unref (priv->format);
|
||||||
|
|
||||||
g_free (priv->path);
|
g_free (priv->path);
|
||||||
g_clear_error (&priv->error);
|
g_clear_error (&priv->error);
|
||||||
|
|
@ -375,7 +377,7 @@ pinos_stream_class_init (PinosStreamClass * klass)
|
||||||
g_param_spec_boxed ("possible-formats",
|
g_param_spec_boxed ("possible-formats",
|
||||||
"Possible Formats",
|
"Possible Formats",
|
||||||
"The possbile formats of the stream",
|
"The possbile formats of the stream",
|
||||||
G_TYPE_BYTES,
|
G_TYPE_PTR_ARRAY,
|
||||||
G_PARAM_READABLE |
|
G_PARAM_READABLE |
|
||||||
G_PARAM_STATIC_STRINGS));
|
G_PARAM_STATIC_STRINGS));
|
||||||
/**
|
/**
|
||||||
|
|
@ -388,7 +390,7 @@ pinos_stream_class_init (PinosStreamClass * klass)
|
||||||
g_param_spec_boxed ("format",
|
g_param_spec_boxed ("format",
|
||||||
"Format",
|
"Format",
|
||||||
"The format of the stream",
|
"The format of the stream",
|
||||||
G_TYPE_BYTES,
|
SPA_TYPE_FORMAT,
|
||||||
G_PARAM_READWRITE |
|
G_PARAM_READWRITE |
|
||||||
G_PARAM_STATIC_STRINGS));
|
G_PARAM_STATIC_STRINGS));
|
||||||
/**
|
/**
|
||||||
|
|
@ -584,23 +586,17 @@ parse_control (PinosStream *stream,
|
||||||
SpaControlBuilder builder;
|
SpaControlBuilder builder;
|
||||||
SpaControl control;
|
SpaControl control;
|
||||||
SpaControlCmdStateChange sc;
|
SpaControlCmdStateChange sc;
|
||||||
guint8 buffer[1024];
|
guint8 buffer[64];
|
||||||
const gchar *str;
|
|
||||||
|
|
||||||
if (spa_control_iter_parse_cmd (&it, &p) < 0)
|
if (spa_control_iter_parse_cmd (&it, &p) < 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (priv->format)
|
if (priv->format)
|
||||||
g_bytes_unref (priv->format);
|
spa_format_unref (priv->format);
|
||||||
str = "video/x-raw,"
|
priv->format = p.format;
|
||||||
" 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 (p.format);
|
spa_debug_format (p.format);
|
||||||
|
g_object_notify (G_OBJECT (stream), "format");
|
||||||
|
|
||||||
/* FIXME send update port status */
|
/* FIXME send update port status */
|
||||||
|
|
||||||
|
|
@ -650,12 +646,17 @@ parse_control (PinosStream *stream,
|
||||||
if (fd == -1)
|
if (fd == -1)
|
||||||
break;
|
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 = spa_memory_import (&p.mem);
|
||||||
mem->flags = p.flags;
|
if (mem->fd == -1) {
|
||||||
mem->fd = fd;
|
g_debug ("add mem %d,%d, %d, %d", p.mem.pool_id, p.mem.id, fd, p.flags);
|
||||||
mem->ptr = NULL;
|
mem->flags = p.flags;
|
||||||
mem->size = p.size;
|
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;
|
break;
|
||||||
}
|
}
|
||||||
case SPA_CONTROL_CMD_REMOVE_MEM:
|
case SPA_CONTROL_CMD_REMOVE_MEM:
|
||||||
|
|
@ -681,13 +682,13 @@ parse_control (PinosStream *stream,
|
||||||
if (spa_control_iter_parse_cmd (&it, &p) < 0)
|
if (spa_control_iter_parse_cmd (&it, &p) < 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
g_debug ("add buffer %d", p.buffer_id);
|
g_debug ("add buffer %d, %d", p.buffer_id, p.mem.mem.id);
|
||||||
mem = spa_memory_find (&p.mem);
|
mem = spa_memory_find (&p.mem.mem);
|
||||||
bid.cleanup = false;
|
bid.cleanup = false;
|
||||||
bid.id = p.buffer_id;
|
bid.id = p.buffer_id;
|
||||||
bid.offset = p.offset;
|
bid.offset = p.mem.offset;
|
||||||
bid.size = p.size;
|
bid.size = p.mem.size;
|
||||||
bid.buf = SPA_MEMBER (spa_memory_ensure_ptr (mem), p.offset, SpaBuffer);
|
bid.buf = SPA_MEMBER (spa_memory_ensure_ptr (mem), p.mem.offset, SpaBuffer);
|
||||||
|
|
||||||
g_array_append_val (priv->buffer_ids, bid);
|
g_array_append_val (priv->buffer_ids, bid);
|
||||||
break;
|
break;
|
||||||
|
|
@ -957,7 +958,7 @@ do_connect (PinosStream *stream)
|
||||||
g_variant_builder_open (&b, G_VARIANT_TYPE ("(uusa{sv}s)"));
|
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", priv->direction);
|
||||||
g_variant_builder_add (&b, "u", 0);
|
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_value (&b, pinos_properties_to_variant (priv->properties));
|
||||||
g_variant_builder_add (&b, "s", priv->path == NULL ? "" : priv->path);
|
g_variant_builder_add (&b, "s", priv->path == NULL ? "" : priv->path);
|
||||||
g_variant_builder_close (&b);
|
g_variant_builder_close (&b);
|
||||||
|
|
@ -983,7 +984,7 @@ do_connect (PinosStream *stream)
|
||||||
* @direction: the stream direction
|
* @direction: the stream direction
|
||||||
* @port_path: the port path to connect to or %NULL to get the default port
|
* @port_path: the port path to connect to or %NULL to get the default port
|
||||||
* @flags: a #PinosStreamFlags
|
* @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.
|
* Connect @stream for input or output on @port_path.
|
||||||
*
|
*
|
||||||
|
|
@ -994,7 +995,7 @@ pinos_stream_connect (PinosStream *stream,
|
||||||
PinosDirection direction,
|
PinosDirection direction,
|
||||||
const gchar *port_path,
|
const gchar *port_path,
|
||||||
PinosStreamFlags flags,
|
PinosStreamFlags flags,
|
||||||
GBytes *possible_formats)
|
GPtrArray *possible_formats)
|
||||||
{
|
{
|
||||||
PinosStreamPrivate *priv;
|
PinosStreamPrivate *priv;
|
||||||
PinosContext *context;
|
PinosContext *context;
|
||||||
|
|
@ -1011,7 +1012,7 @@ pinos_stream_connect (PinosStream *stream,
|
||||||
g_free (priv->path);
|
g_free (priv->path);
|
||||||
priv->path = g_strdup (port_path);
|
priv->path = g_strdup (port_path);
|
||||||
if (priv->possible_formats)
|
if (priv->possible_formats)
|
||||||
g_bytes_unref (priv->possible_formats);
|
g_ptr_array_unref (priv->possible_formats);
|
||||||
priv->flags = flags;
|
priv->flags = flags;
|
||||||
priv->possible_formats = possible_formats;
|
priv->possible_formats = possible_formats;
|
||||||
|
|
||||||
|
|
@ -1067,7 +1068,7 @@ do_start (PinosStream *stream)
|
||||||
/**
|
/**
|
||||||
* pinos_stream_start:
|
* pinos_stream_start:
|
||||||
* @stream: a #PinosStream
|
* @stream: a #PinosStream
|
||||||
* @format: (transfer full): a #GBytes with format
|
* @format: (transfer full): a #SpaFormat with format
|
||||||
* @mode: a #PinosStreamMode
|
* @mode: a #PinosStreamMode
|
||||||
*
|
*
|
||||||
* Start capturing from @stream in @format.
|
* Start capturing from @stream in @format.
|
||||||
|
|
@ -1083,7 +1084,7 @@ do_start (PinosStream *stream)
|
||||||
*/
|
*/
|
||||||
gboolean
|
gboolean
|
||||||
pinos_stream_start (PinosStream *stream,
|
pinos_stream_start (PinosStream *stream,
|
||||||
GBytes *format,
|
SpaFormat *format,
|
||||||
PinosStreamMode mode)
|
PinosStreamMode mode)
|
||||||
{
|
{
|
||||||
PinosStreamPrivate *priv;
|
PinosStreamPrivate *priv;
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@
|
||||||
#include <glib-object.h>
|
#include <glib-object.h>
|
||||||
|
|
||||||
#include <spa/include/spa/buffer.h>
|
#include <spa/include/spa/buffer.h>
|
||||||
|
#include <spa/include/spa/format.h>
|
||||||
|
|
||||||
#include <pinos/client/context.h>
|
#include <pinos/client/context.h>
|
||||||
|
|
||||||
|
|
@ -99,11 +100,11 @@ gboolean pinos_stream_connect (PinosStream *stream,
|
||||||
PinosDirection direction,
|
PinosDirection direction,
|
||||||
const gchar *port_path,
|
const gchar *port_path,
|
||||||
PinosStreamFlags flags,
|
PinosStreamFlags flags,
|
||||||
GBytes *possible_formats);
|
GPtrArray *possible_formats);
|
||||||
gboolean pinos_stream_disconnect (PinosStream *stream);
|
gboolean pinos_stream_disconnect (PinosStream *stream);
|
||||||
|
|
||||||
gboolean pinos_stream_start (PinosStream *stream,
|
gboolean pinos_stream_start (PinosStream *stream,
|
||||||
GBytes *format,
|
SpaFormat *format,
|
||||||
PinosStreamMode mode);
|
PinosStreamMode mode);
|
||||||
gboolean pinos_stream_stop (PinosStream *stream);
|
gboolean pinos_stream_stop (PinosStream *stream);
|
||||||
|
|
||||||
|
|
|
||||||
170
pinos/gst/gstpinosformat.c
Normal file
170
pinos/gst/gstpinosformat.c
Normal 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;
|
||||||
|
}
|
||||||
36
pinos/gst/gstpinosformat.h
Normal file
36
pinos/gst/gstpinosformat.h
Normal 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
|
||||||
|
|
@ -46,6 +46,7 @@
|
||||||
#include <spa/include/spa/buffer.h>
|
#include <spa/include/spa/buffer.h>
|
||||||
|
|
||||||
#include "gsttmpfileallocator.h"
|
#include "gsttmpfileallocator.h"
|
||||||
|
#include "gstpinosformat.h"
|
||||||
|
|
||||||
|
|
||||||
GST_DEBUG_CATEGORY_STATIC (pinos_sink_debug);
|
GST_DEBUG_CATEGORY_STATIC (pinos_sink_debug);
|
||||||
|
|
@ -412,15 +413,17 @@ static gboolean
|
||||||
gst_pinos_sink_setcaps (GstBaseSink * bsink, GstCaps * caps)
|
gst_pinos_sink_setcaps (GstBaseSink * bsink, GstCaps * caps)
|
||||||
{
|
{
|
||||||
GstPinosSink *pinossink;
|
GstPinosSink *pinossink;
|
||||||
gchar *str;
|
GPtrArray *possible;
|
||||||
GBytes *format;
|
SpaFormat *format;
|
||||||
PinosStreamState state;
|
PinosStreamState state;
|
||||||
gboolean res = FALSE;
|
gboolean res = FALSE;
|
||||||
|
|
||||||
pinossink = GST_PINOS_SINK (bsink);
|
pinossink = GST_PINOS_SINK (bsink);
|
||||||
|
|
||||||
str = gst_caps_to_string (caps);
|
format = gst_caps_to_format (caps, 0);
|
||||||
format = g_bytes_new_take (str, strlen (str) + 1);
|
possible = g_ptr_array_new ();
|
||||||
|
spa_format_ref (format);
|
||||||
|
g_ptr_array_insert (possible, -1, format);
|
||||||
|
|
||||||
pinos_main_loop_lock (pinossink->loop);
|
pinos_main_loop_lock (pinossink->loop);
|
||||||
state = pinos_stream_get_state (pinossink->stream);
|
state = pinos_stream_get_state (pinossink->stream);
|
||||||
|
|
@ -438,7 +441,7 @@ gst_pinos_sink_setcaps (GstBaseSink * bsink, GstCaps * caps)
|
||||||
PINOS_DIRECTION_OUTPUT,
|
PINOS_DIRECTION_OUTPUT,
|
||||||
pinossink->path,
|
pinossink->path,
|
||||||
flags,
|
flags,
|
||||||
g_bytes_ref (format));
|
possible);
|
||||||
|
|
||||||
while (TRUE) {
|
while (TRUE) {
|
||||||
state = pinos_stream_get_state (pinossink->stream);
|
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) {
|
if (state != PINOS_STREAM_STATE_STREAMING) {
|
||||||
res = pinos_stream_start (pinossink->stream,
|
res = pinos_stream_start (pinossink->stream,
|
||||||
g_bytes_ref (format),
|
format,
|
||||||
PINOS_STREAM_MODE_BUFFER);
|
PINOS_STREAM_MODE_BUFFER);
|
||||||
|
|
||||||
while (TRUE) {
|
while (TRUE) {
|
||||||
|
|
@ -471,7 +474,6 @@ gst_pinos_sink_setcaps (GstBaseSink * bsink, GstCaps * caps)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pinos_main_loop_unlock (pinossink->loop);
|
pinos_main_loop_unlock (pinossink->loop);
|
||||||
g_bytes_unref (format);
|
|
||||||
|
|
||||||
pinossink->negotiated = res;
|
pinossink->negotiated = res;
|
||||||
|
|
||||||
|
|
@ -481,7 +483,7 @@ start_error:
|
||||||
{
|
{
|
||||||
GST_ERROR ("could not start stream");
|
GST_ERROR ("could not start stream");
|
||||||
pinos_main_loop_unlock (pinossink->loop);
|
pinos_main_loop_unlock (pinossink->loop);
|
||||||
g_bytes_unref (format);
|
spa_format_unref (format);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -517,10 +519,10 @@ gst_pinos_sink_render (GstBaseSink * bsink, GstBuffer * buffer)
|
||||||
|
|
||||||
b = g_slice_new (SinkBuffer);
|
b = g_slice_new (SinkBuffer);
|
||||||
b->buffer.id = pinos_fd_manager_get_id (pinossink->fdmanager);
|
b->buffer.id = pinos_fd_manager_get_id (pinossink->fdmanager);
|
||||||
b->buffer.mem.pool_id = SPA_ID_INVALID;
|
b->buffer.mem.mem.pool_id = SPA_ID_INVALID;
|
||||||
b->buffer.mem.id = SPA_ID_INVALID;
|
b->buffer.mem.mem.id = SPA_ID_INVALID;
|
||||||
b->buffer.offset = 0;
|
b->buffer.mem.offset = 0;
|
||||||
b->buffer.size = sizeof (SinkBuffer);
|
b->buffer.mem.size = sizeof (SinkBuffer);
|
||||||
b->buffer.n_metas = 1;
|
b->buffer.n_metas = 1;
|
||||||
b->buffer.metas = offsetof (SinkBuffer, metas);
|
b->buffer.metas = offsetof (SinkBuffer, metas);
|
||||||
b->buffer.n_datas = 1;
|
b->buffer.n_datas = 1;
|
||||||
|
|
@ -564,10 +566,10 @@ gst_pinos_sink_render (GstBaseSink * bsink, GstBuffer * buffer)
|
||||||
b->mem = mem;
|
b->mem = mem;
|
||||||
b->fd = gst_fd_memory_get_fd (mem);
|
b->fd = gst_fd_memory_get_fd (mem);
|
||||||
|
|
||||||
b->datas[0].mem.pool_id = SPA_ID_INVALID;
|
b->datas[0].mem.mem.pool_id = SPA_ID_INVALID;
|
||||||
b->datas[0].mem.id = SPA_ID_INVALID;
|
b->datas[0].mem.mem.id = SPA_ID_INVALID;
|
||||||
b->datas[0].offset = mem->offset;
|
b->datas[0].mem.offset = mem->offset;
|
||||||
b->datas[0].size = mem->size;
|
b->datas[0].mem.size = mem->size;
|
||||||
b->datas[0].stride = 0;
|
b->datas[0].stride = 0;
|
||||||
|
|
||||||
if (!(res = pinos_stream_send_buffer (pinossink->stream, &b->buffer)))
|
if (!(res = pinos_stream_send_buffer (pinossink->stream, &b->buffer)))
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
#include "gstpinossrc.h"
|
#include "gstpinossrc.h"
|
||||||
|
#include "gstpinosformat.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
@ -388,19 +389,19 @@ on_new_buffer (GObject *gobject,
|
||||||
SpaData *d = &SPA_BUFFER_DATAS (b)[i];
|
SpaData *d = &SPA_BUFFER_DATAS (b)[i];
|
||||||
SpaMemory *mem;
|
SpaMemory *mem;
|
||||||
|
|
||||||
mem = spa_memory_find (&d->mem);
|
mem = spa_memory_find (&d->mem.mem);
|
||||||
|
|
||||||
if (mem->fd) {
|
if (mem->fd) {
|
||||||
GstMemory *fdmem = NULL;
|
GstMemory *fdmem = NULL;
|
||||||
|
|
||||||
fdmem = gst_fd_allocator_alloc (pinossrc->fd_allocator, dup (mem->fd),
|
fdmem = gst_fd_allocator_alloc (pinossrc->fd_allocator, dup (mem->fd),
|
||||||
d->offset + d->size, GST_FD_MEMORY_FLAG_NONE);
|
d->mem.offset + d->mem.size, GST_FD_MEMORY_FLAG_NONE);
|
||||||
gst_memory_resize (fdmem, d->offset, d->size);
|
gst_memory_resize (fdmem, d->mem.offset, d->mem.size);
|
||||||
gst_buffer_append_memory (buf, fdmem);
|
gst_buffer_append_memory (buf, fdmem);
|
||||||
} else {
|
} else {
|
||||||
gst_buffer_append_memory (buf,
|
gst_buffer_append_memory (buf,
|
||||||
gst_memory_new_wrapped (0, mem->ptr, mem->size, d->offset,
|
gst_memory_new_wrapped (0, mem->ptr, mem->size, d->mem.offset,
|
||||||
d->size, NULL, NULL));
|
d->mem.size, NULL, NULL));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -485,15 +486,14 @@ parse_stream_properties (GstPinosSrc *pinossrc, PinosProperties *props)
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_pinos_src_stream_start (GstPinosSrc *pinossrc, GstCaps * caps)
|
gst_pinos_src_stream_start (GstPinosSrc *pinossrc, GstCaps * caps)
|
||||||
{
|
{
|
||||||
gchar *str;
|
SpaFormat *format;
|
||||||
GBytes *format = NULL;
|
|
||||||
gboolean res;
|
gboolean res;
|
||||||
PinosProperties *props;
|
PinosProperties *props;
|
||||||
|
|
||||||
if (caps) {
|
if (caps)
|
||||||
str = gst_caps_to_string (caps);
|
format = gst_caps_to_format (caps, 0);
|
||||||
format = g_bytes_new_take (str, strlen (str) + 1);
|
else
|
||||||
}
|
format = NULL;
|
||||||
|
|
||||||
pinos_main_loop_lock (pinossrc->loop);
|
pinos_main_loop_lock (pinossrc->loop);
|
||||||
res = pinos_stream_start (pinossrc->stream, format, PINOS_STREAM_MODE_BUFFER);
|
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);
|
pinos_main_loop_unlock (pinossrc->loop);
|
||||||
|
|
||||||
if (format) {
|
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);
|
gst_base_src_set_caps (GST_BASE_SRC (pinossrc), caps);
|
||||||
g_bytes_unref (format);
|
spa_format_unref (format);
|
||||||
}
|
}
|
||||||
|
|
||||||
parse_stream_properties (pinossrc, props);
|
parse_stream_properties (pinossrc, props);
|
||||||
|
|
@ -555,8 +555,7 @@ gst_pinos_src_negotiate (GstBaseSrc * basesrc)
|
||||||
GstCaps *caps = NULL;
|
GstCaps *caps = NULL;
|
||||||
GstCaps *peercaps = NULL;
|
GstCaps *peercaps = NULL;
|
||||||
gboolean result = FALSE;
|
gboolean result = FALSE;
|
||||||
GBytes *possible;
|
GPtrArray *possible;
|
||||||
gchar *str;
|
|
||||||
|
|
||||||
/* first see what is possible on our source pad */
|
/* first see what is possible on our source pad */
|
||||||
thiscaps = gst_pad_query_caps (GST_BASE_SRC_PAD (basesrc), NULL);
|
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);
|
GST_DEBUG_OBJECT (basesrc, "have common caps: %" GST_PTR_FORMAT, caps);
|
||||||
|
|
||||||
/* open a connection with these caps */
|
/* open a connection with these caps */
|
||||||
str = gst_caps_to_string (caps);
|
possible = gst_caps_to_format_all (caps);
|
||||||
possible = g_bytes_new_take (str, strlen (str) + 1);
|
|
||||||
|
|
||||||
/* first disconnect */
|
/* first disconnect */
|
||||||
pinos_main_loop_lock (pinossrc->loop);
|
pinos_main_loop_lock (pinossrc->loop);
|
||||||
|
|
@ -600,7 +598,7 @@ gst_pinos_src_negotiate (GstBaseSrc * basesrc)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (state == PINOS_STREAM_STATE_ERROR) {
|
if (state == PINOS_STREAM_STATE_ERROR) {
|
||||||
g_bytes_unref (possible);
|
g_ptr_array_unref (possible);
|
||||||
goto connect_error;
|
goto connect_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -672,12 +670,12 @@ on_format_notify (GObject *gobject,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
GstPinosSrc *pinossrc = user_data;
|
GstPinosSrc *pinossrc = user_data;
|
||||||
GBytes *format;
|
SpaFormat *format;
|
||||||
GstCaps *caps;
|
GstCaps *caps;
|
||||||
|
|
||||||
g_object_get (gobject, "format", &format, NULL);
|
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_base_src_set_caps (GST_BASE_SRC (pinossrc), caps);
|
||||||
gst_caps_unref (caps);
|
gst_caps_unref (caps);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -444,10 +444,10 @@ on_received_buffer (PinosPort *port,
|
||||||
uint8_t *data;
|
uint8_t *data;
|
||||||
size_t size, towrite, total;
|
size_t size, towrite, total;
|
||||||
|
|
||||||
mem = spa_memory_find (&d[i].mem);
|
mem = spa_memory_find (&d[i].mem.mem);
|
||||||
|
|
||||||
size = d[i].size;
|
size = d[i].mem.size;
|
||||||
data = (guint8*)mem->ptr + d[i].offset;
|
data = SPA_MEMBER (mem->ptr, d[i].mem.offset, uint8_t);
|
||||||
|
|
||||||
pinos_ringbuffer_get_write_areas (priv->ringbuffer, areas);
|
pinos_ringbuffer_get_write_areas (priv->ringbuffer, areas);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -269,8 +269,8 @@ do_negotiate (PinosLink *this)
|
||||||
value.type = SPA_PROP_TYPE_RECTANGLE;
|
value.type = SPA_PROP_TYPE_RECTANGLE;
|
||||||
value.size = sizeof (SpaRectangle);
|
value.size = sizeof (SpaRectangle);
|
||||||
value.value = ▭
|
value.value = ▭
|
||||||
rect.width = 320;
|
rect.width = 640;
|
||||||
rect.height = 240;
|
rect.height = 480;
|
||||||
if ((res = spa_props_set_prop (props, spa_props_index_for_id (props, SPA_PROP_ID_VIDEO_SIZE), &value)) < 0)
|
if ((res = spa_props_set_prop (props, spa_props_index_for_id (props, SPA_PROP_ID_VIDEO_SIZE), &value)) < 0)
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -81,17 +81,14 @@ on_stream_notify (GObject *gobject,
|
||||||
|
|
||||||
case PINOS_STREAM_STATE_READY:
|
case PINOS_STREAM_STATE_READY:
|
||||||
{
|
{
|
||||||
GBytes *possible, *format;
|
GPtrArray *possible;
|
||||||
GstCaps *caps;
|
SpaFormat *format;
|
||||||
GstStructure *structure;
|
|
||||||
gchar *str;
|
|
||||||
|
|
||||||
g_object_get (s, "possible-formats", &possible, NULL);
|
g_object_get (s, "possible-formats", &possible, NULL);
|
||||||
|
|
||||||
caps = gst_caps_from_string (g_bytes_get_data (possible, NULL));
|
format = g_ptr_array_index (possible, 0);
|
||||||
|
|
||||||
structure = gst_caps_get_structure (caps, 0);
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
/* set some reasonable defaults */
|
/* set some reasonable defaults */
|
||||||
if (gst_structure_has_field (structure, "width"))
|
if (gst_structure_has_field (structure, "width"))
|
||||||
gst_structure_fixate_field_nearest_int (structure, "width", 320);
|
gst_structure_fixate_field_nearest_int (structure, "width", 320);
|
||||||
|
|
@ -104,8 +101,9 @@ on_stream_notify (GObject *gobject,
|
||||||
caps = gst_caps_fixate (caps);
|
caps = gst_caps_fixate (caps);
|
||||||
str = gst_caps_to_string (caps);
|
str = gst_caps_to_string (caps);
|
||||||
gst_caps_unref (caps);
|
gst_caps_unref (caps);
|
||||||
|
|
||||||
format = g_bytes_new_static (str, strlen (str) + 1);
|
format = g_bytes_new_static (str, strlen (str) + 1);
|
||||||
|
#endif
|
||||||
|
|
||||||
pinos_stream_start (s, format, PINOS_STREAM_MODE_SOCKET);
|
pinos_stream_start (s, format, PINOS_STREAM_MODE_SOCKET);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -136,14 +134,14 @@ on_state_notify (GObject *gobject,
|
||||||
case PINOS_CONTEXT_STATE_CONNECTED:
|
case PINOS_CONTEXT_STATE_CONNECTED:
|
||||||
{
|
{
|
||||||
PinosStream *stream;
|
PinosStream *stream;
|
||||||
GBytes *format;
|
GPtrArray *possible;
|
||||||
|
|
||||||
stream = pinos_stream_new (c, "test", NULL);
|
stream = pinos_stream_new (c, "test", NULL);
|
||||||
g_signal_connect (stream, "notify::state", (GCallback) on_stream_notify, stream);
|
g_signal_connect (stream, "notify::state", (GCallback) on_stream_notify, stream);
|
||||||
g_signal_connect (stream, "notify::socket", (GCallback) on_socket_notify, stream);
|
g_signal_connect (stream, "notify::socket", (GCallback) on_socket_notify, stream);
|
||||||
|
|
||||||
format = g_bytes_new_static (ANY_CAPS, strlen (ANY_CAPS) + 1);
|
possible = NULL;
|
||||||
pinos_stream_connect (stream, PINOS_DIRECTION_OUTPUT, NULL, 0, format);
|
pinos_stream_connect (stream, PINOS_DIRECTION_OUTPUT, NULL, 0, possible);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
|
|
||||||
|
|
@ -102,37 +102,29 @@ typedef struct {
|
||||||
/**
|
/**
|
||||||
* SpaData:
|
* SpaData:
|
||||||
* @mem: reference to the memory to use
|
* @mem: reference to the memory to use
|
||||||
* @offset: ofset in memory
|
|
||||||
* @size: size of memory
|
|
||||||
* @stride: stride of memory if applicable
|
* @stride: stride of memory if applicable
|
||||||
*/
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
SpaMemoryRef mem;
|
SpaMemoryChunk mem;
|
||||||
off_t offset;
|
ssize_t stride;
|
||||||
size_t size;
|
|
||||||
size_t stride;
|
|
||||||
} SpaData;
|
} SpaData;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SpaBuffer:
|
* SpaBuffer:
|
||||||
* @id: buffer id
|
* @id: buffer id
|
||||||
* @mem: reference to the memory for this buffer
|
* @mem: reference to the memory for this buffer
|
||||||
* @offset: offset inside memory
|
|
||||||
* @size: of of memory
|
|
||||||
* @n_metas: number of metadata
|
* @n_metas: number of metadata
|
||||||
* @metas: offset of array of @n_metas metadata
|
* @metas: offset of array of @n_metas metadata
|
||||||
* @n_datas: number of data pointers
|
* @n_datas: number of data pointers
|
||||||
* @datas: offset of array of @n_datas data pointers
|
* @datas: offset of array of @n_datas data pointers
|
||||||
*/
|
*/
|
||||||
struct _SpaBuffer {
|
struct _SpaBuffer {
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
SpaMemoryRef mem;
|
SpaMemoryChunk mem;
|
||||||
off_t offset;
|
unsigned int n_metas;
|
||||||
size_t size;
|
off_t metas;
|
||||||
unsigned int n_metas;
|
unsigned int n_datas;
|
||||||
off_t metas;
|
off_t datas;
|
||||||
unsigned int n_datas;
|
|
||||||
off_t datas;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define SPA_BUFFER_METAS(b) (SPA_MEMBER ((b), (b)->metas, SpaMeta))
|
#define SPA_BUFFER_METAS(b) (SPA_MEMBER ((b), (b)->metas, SpaMeta))
|
||||||
|
|
|
||||||
|
|
@ -91,8 +91,8 @@ typedef enum {
|
||||||
/* SPA_CONTROL_CMD_NODE_UPDATE */
|
/* SPA_CONTROL_CMD_NODE_UPDATE */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t change_mask;
|
uint32_t change_mask;
|
||||||
uint32_t max_input_ports;
|
unsigned int max_input_ports;
|
||||||
uint32_t max_output_ports;
|
unsigned int max_output_ports;
|
||||||
const SpaProps *props;
|
const SpaProps *props;
|
||||||
} SpaControlCmdNodeUpdate;
|
} SpaControlCmdNodeUpdate;
|
||||||
|
|
||||||
|
|
@ -100,8 +100,8 @@ typedef struct {
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t port_id;
|
uint32_t port_id;
|
||||||
uint32_t change_mask;
|
uint32_t change_mask;
|
||||||
uint32_t direction;
|
SpaDirection direction;
|
||||||
uint32_t n_possible_formats;
|
unsigned int n_possible_formats;
|
||||||
const SpaFormat **possible_formats;
|
const SpaFormat **possible_formats;
|
||||||
const SpaProps *props;
|
const SpaProps *props;
|
||||||
const SpaPortInfo *info;
|
const SpaPortInfo *info;
|
||||||
|
|
@ -132,8 +132,8 @@ typedef struct {
|
||||||
|
|
||||||
/* SPA_CONTROL_CMD_ADD_PORT */
|
/* SPA_CONTROL_CMD_ADD_PORT */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t port_id;
|
uint32_t port_id;
|
||||||
uint32_t direction;
|
SpaDirection direction;
|
||||||
} SpaControlCmdAddPort;
|
} SpaControlCmdAddPort;
|
||||||
|
|
||||||
/* SPA_CONTROL_CMD_REMOVE_PORT */
|
/* SPA_CONTROL_CMD_REMOVE_PORT */
|
||||||
|
|
@ -152,7 +152,7 @@ typedef struct {
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t port_id;
|
uint32_t port_id;
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
uint32_t size;
|
size_t size;
|
||||||
void *value;
|
void *value;
|
||||||
} SpaControlCmdSetProperty;
|
} SpaControlCmdSetProperty;
|
||||||
|
|
||||||
|
|
@ -164,24 +164,22 @@ typedef struct {
|
||||||
uint32_t port_id;
|
uint32_t port_id;
|
||||||
SpaMemoryRef mem;
|
SpaMemoryRef mem;
|
||||||
uint32_t mem_type;
|
uint32_t mem_type;
|
||||||
uint32_t fd_index;
|
unsigned int fd_index;
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
uint64_t size;
|
size_t size;
|
||||||
} SpaControlCmdAddMem;
|
} SpaControlCmdAddMem;
|
||||||
|
|
||||||
/* SPA_CONTROL_CMD_REMOVE_MEM */
|
/* SPA_CONTROL_CMD_REMOVE_MEM */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t port_id;
|
uint32_t port_id;
|
||||||
SpaMemoryRef mem;
|
SpaMemoryRef mem;
|
||||||
} SpaControlCmdRemoveMem;
|
} SpaControlCmdRemoveMem;
|
||||||
|
|
||||||
/* SPA_CONTROL_CMD_ADD_BUFFER */
|
/* SPA_CONTROL_CMD_ADD_BUFFER */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t port_id;
|
uint32_t port_id;
|
||||||
uint32_t buffer_id;
|
uint32_t buffer_id;
|
||||||
SpaMemoryRef mem;
|
SpaMemoryChunk mem;
|
||||||
off_t offset;
|
|
||||||
size_t size;
|
|
||||||
} SpaControlCmdAddBuffer;
|
} SpaControlCmdAddBuffer;
|
||||||
|
|
||||||
/* SPA_CONTROL_CMD_REMOVE_BUFFER */
|
/* SPA_CONTROL_CMD_REMOVE_BUFFER */
|
||||||
|
|
@ -194,16 +192,16 @@ typedef struct {
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t port_id;
|
uint32_t port_id;
|
||||||
uint32_t buffer_id;
|
uint32_t buffer_id;
|
||||||
uint64_t offset;
|
off_t offset;
|
||||||
uint64_t size;
|
size_t size;
|
||||||
} SpaControlCmdProcessBuffer;
|
} SpaControlCmdProcessBuffer;
|
||||||
|
|
||||||
/* SPA_CONTROL_CMD_REUSE_BUFFER */
|
/* SPA_CONTROL_CMD_REUSE_BUFFER */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t port_id;
|
uint32_t port_id;
|
||||||
uint32_t buffer_id;
|
uint32_t buffer_id;
|
||||||
uint64_t offset;
|
off_t offset;
|
||||||
uint64_t size;
|
size_t size;
|
||||||
} SpaControlCmdReuseBuffer;
|
} SpaControlCmdReuseBuffer;
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -221,7 +219,8 @@ SpaResult spa_control_iter_next (SpaControlIter *iter);
|
||||||
SpaResult spa_control_iter_end (SpaControlIter *iter);
|
SpaResult spa_control_iter_end (SpaControlIter *iter);
|
||||||
|
|
||||||
SpaControlCmd spa_control_iter_get_cmd (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,
|
SpaResult spa_control_iter_parse_cmd (SpaControlIter *iter,
|
||||||
void *command);
|
void *command);
|
||||||
|
|
|
||||||
|
|
@ -62,22 +62,34 @@ typedef enum {
|
||||||
* @media_type: media type
|
* @media_type: media type
|
||||||
* @media_subtype: subtype
|
* @media_subtype: subtype
|
||||||
* @mem: memory reference
|
* @mem: memory reference
|
||||||
|
* @offset: offset in memory
|
||||||
|
* @size: size in memory
|
||||||
*/
|
*/
|
||||||
struct _SpaFormat {
|
struct _SpaFormat {
|
||||||
SpaProps props;
|
SpaProps props;
|
||||||
SpaMediaType media_type;
|
SpaMediaType media_type;
|
||||||
SpaMediaSubType media_subtype;
|
SpaMediaSubType media_subtype;
|
||||||
SpaMemoryRef mem;
|
SpaMemoryChunk mem;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define spa_format_ref(f) spa_memory_ref(&(f)->mem)
|
static inline void
|
||||||
#define spa_format_unref(f) spa_memory_unref(&(f)->mem)
|
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 {
|
typedef enum {
|
||||||
SPA_PROP_ID_INVALID = 0,
|
SPA_PROP_ID_INVALID = 0,
|
||||||
SPA_PROP_ID_MEDIA_CUSTOM_START = 200,
|
SPA_PROP_ID_MEDIA_CUSTOM_START = 200,
|
||||||
} SpaFormatProps;
|
} SpaFormatProps;
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} /* extern "C" */
|
} /* extern "C" */
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ extern "C" {
|
||||||
|
|
||||||
typedef struct _SpaMemory SpaMemory;
|
typedef struct _SpaMemory SpaMemory;
|
||||||
typedef struct _SpaMemoryRef SpaMemoryRef;
|
typedef struct _SpaMemoryRef SpaMemoryRef;
|
||||||
|
typedef struct _SpaMemoryChunk SpaMemoryChunk;
|
||||||
typedef struct _SpaMemoryPool SpaMemoryPool;
|
typedef struct _SpaMemoryPool SpaMemoryPool;
|
||||||
|
|
||||||
#include <spa/defs.h>
|
#include <spa/defs.h>
|
||||||
|
|
@ -48,12 +49,27 @@ typedef enum {
|
||||||
* SpaMemoryRef:
|
* SpaMemoryRef:
|
||||||
* @pool_id: the pool id
|
* @pool_id: the pool id
|
||||||
* @id: mem_id
|
* @id: mem_id
|
||||||
|
*
|
||||||
|
* A reference to a block of memory
|
||||||
*/
|
*/
|
||||||
struct _SpaMemoryRef {
|
struct _SpaMemoryRef {
|
||||||
uint32_t pool_id;
|
uint32_t pool_id;
|
||||||
uint32_t 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:
|
* SpaMemory:
|
||||||
* @refcount: a refcount
|
* @refcount: a refcount
|
||||||
|
|
|
||||||
|
|
@ -353,7 +353,9 @@ iter_parse_set_format (struct stack_iter *si, SpaControlCmdSetFormat *cmd)
|
||||||
cmd->port_id = *p++;
|
cmd->port_id = *p++;
|
||||||
mem = spa_memory_alloc_size (SPA_MEMORY_POOL_LOCAL, p, si->size - 4);
|
mem = spa_memory_alloc_size (SPA_MEMORY_POOL_LOCAL, p, si->size - 4);
|
||||||
cmd->format = spa_memory_ensure_ptr (mem);
|
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 = (SpaProps *) &cmd->format->props;
|
||||||
tp->prop_info = SPA_MEMBER (tp, SPA_PTR_TO_INT (tp->prop_info), SpaPropInfo);
|
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 = SPA_MEMBER (tf, offsetof (SpaFormat, props), SpaProps);
|
||||||
tp->n_prop_info = sp->n_prop_info;
|
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 */
|
/* 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++) {
|
for (i = 0; i < tp->n_prop_info; i++) {
|
||||||
memcpy (pi, &sp->prop_info[i], sizeof (SpaPropInfo));
|
memcpy (pi, &sp->prop_info[i], sizeof (SpaPropInfo));
|
||||||
pi->mask_offset = sizeof (SpaFormat);
|
pi->mask_offset = sizeof (SpaFormat);
|
||||||
|
|
|
||||||
|
|
@ -92,10 +92,10 @@ spa_debug_buffer (const SpaBuffer *buffer)
|
||||||
|
|
||||||
fprintf (stderr, "SpaBuffer %p:\n", buffer);
|
fprintf (stderr, "SpaBuffer %p:\n", buffer);
|
||||||
fprintf (stderr, " id: %08X\n", buffer->id);
|
fprintf (stderr, " id: %08X\n", buffer->id);
|
||||||
fprintf (stderr, " pool_id: %08X\n", buffer->mem.pool_id);
|
fprintf (stderr, " pool_id: %08X\n", buffer->mem.mem.pool_id);
|
||||||
fprintf (stderr, " mem_id: %08X\n", buffer->mem.id);
|
fprintf (stderr, " mem_id: %08X\n", buffer->mem.mem.id);
|
||||||
fprintf (stderr, " offset: %zd\n", buffer->offset);
|
fprintf (stderr, " offset: %zd\n", buffer->mem.offset);
|
||||||
fprintf (stderr, " size: %zd\n", buffer->size);
|
fprintf (stderr, " size: %zd\n", buffer->mem.size);
|
||||||
fprintf (stderr, " n_metas: %u (offset %zd)\n", buffer->n_metas, buffer->metas);
|
fprintf (stderr, " n_metas: %u (offset %zd)\n", buffer->n_metas, buffer->metas);
|
||||||
for (i = 0; i < buffer->n_metas; i++) {
|
for (i = 0; i < buffer->n_metas; i++) {
|
||||||
SpaMeta *m = &SPA_BUFFER_METAS (buffer)[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];
|
SpaData *d = &SPA_BUFFER_DATAS (buffer)[i];
|
||||||
SpaMemory *mem;
|
SpaMemory *mem;
|
||||||
|
|
||||||
mem = spa_memory_find (&d->mem);
|
mem = spa_memory_find (&d->mem.mem);
|
||||||
fprintf (stderr, " data %d: (memory %p)\n", i, mem);
|
fprintf (stderr, " data %d: (memory %p)\n", i, mem);
|
||||||
if (mem) {
|
if (mem) {
|
||||||
fprintf (stderr, " pool_id: %u\n", mem->mem.pool_id);
|
fprintf (stderr, " pool_id: %u\n", mem->mem.pool_id);
|
||||||
|
|
@ -142,8 +142,8 @@ spa_debug_buffer (const SpaBuffer *buffer)
|
||||||
} else {
|
} else {
|
||||||
fprintf (stderr, " invalid memory reference\n");
|
fprintf (stderr, " invalid memory reference\n");
|
||||||
}
|
}
|
||||||
fprintf (stderr, " offset: %zd\n", d->offset);
|
fprintf (stderr, " offset: %zd\n", d->mem.offset);
|
||||||
fprintf (stderr, " size: %zd\n", d->size);
|
fprintf (stderr, " size: %zd\n", d->mem.size);
|
||||||
fprintf (stderr, " stride: %zd\n", d->stride);
|
fprintf (stderr, " stride: %zd\n", d->stride);
|
||||||
}
|
}
|
||||||
return SPA_RESULT_OK;
|
return SPA_RESULT_OK;
|
||||||
|
|
|
||||||
40
spa/lib/format.c
Normal file
40
spa/lib/format.c
Normal 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
59
spa/lib/memfd-wrappers.h
Normal 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
|
||||||
|
|
@ -29,6 +29,7 @@
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
|
||||||
#include "spa/memory.h"
|
#include "spa/memory.h"
|
||||||
|
#include "memfd-wrappers.h"
|
||||||
|
|
||||||
#define MAX_POOLS 16
|
#define MAX_POOLS 16
|
||||||
#define MAX_MEMORIES 1024
|
#define MAX_MEMORIES 1024
|
||||||
|
|
@ -144,17 +145,23 @@ SpaMemory *
|
||||||
spa_memory_alloc_with_fd (uint32_t pool_id, void *data, size_t size)
|
spa_memory_alloc_with_fd (uint32_t pool_id, void *data, size_t size)
|
||||||
{
|
{
|
||||||
SpaMemory *mem;
|
SpaMemory *mem;
|
||||||
char filename[] = "/dev/shm/spa-tmpfile.XXXXXX";
|
|
||||||
|
|
||||||
if (!(mem = spa_memory_alloc (pool_id)))
|
if (!(mem = spa_memory_alloc (pool_id)))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
mem->fd = mkostemp (filename, O_CLOEXEC);
|
#if 0
|
||||||
if (mem->fd == -1) {
|
{
|
||||||
fprintf (stderr, "Failed to create temporary file: %s\n", strerror (errno));
|
char filename[] = "/dev/shm/spa-tmpfile.XXXXXX";
|
||||||
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;
|
||||||
|
}
|
||||||
|
unlink (filename);
|
||||||
}
|
}
|
||||||
unlink (filename);
|
#else
|
||||||
|
mem->fd = memfd_create ("spa-memfd", MFD_CLOEXEC | MFD_ALLOW_SEALING);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (data) {
|
if (data) {
|
||||||
if (write (mem->fd, data, size) != (ssize_t) size) {
|
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;
|
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->flags = SPA_MEMORY_FLAG_READWRITE;
|
||||||
mem->size = size;
|
mem->size = size;
|
||||||
|
|
@ -209,6 +228,8 @@ spa_memory_import (SpaMemoryRef *ref)
|
||||||
mem->mem = *ref;
|
mem->mem = *ref;
|
||||||
mem->ptr = NULL;
|
mem->ptr = NULL;
|
||||||
mem->fd = -1;
|
mem->fd = -1;
|
||||||
|
} else {
|
||||||
|
mem->refcount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return mem;
|
return mem;
|
||||||
|
|
@ -236,6 +257,9 @@ spa_memory_free (SpaMemory *mem)
|
||||||
if (mem->ptr)
|
if (mem->ptr)
|
||||||
munmap (mem->ptr, mem->size);
|
munmap (mem->ptr, mem->size);
|
||||||
close (mem->fd);
|
close (mem->fd);
|
||||||
|
} else {
|
||||||
|
if (mem->ptr)
|
||||||
|
free (mem->ptr);
|
||||||
}
|
}
|
||||||
pool = &pools[mem->mem.pool_id];
|
pool = &pools[mem->mem.pool_id];
|
||||||
pool->free_mem[pool->n_free] = mem->mem.id;
|
pool->free_mem[pool->n_free] = mem->mem.id;
|
||||||
|
|
|
||||||
|
|
@ -550,7 +550,7 @@ spa_audiomixer_node_port_push_input (SpaNode *node,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
this->ports[idx].buffer = buffer;
|
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_index = 0;
|
||||||
this->ports[idx].buffer_offset = 0;
|
this->ports[idx].buffer_offset = 0;
|
||||||
this->port_queued++;
|
this->port_queued++;
|
||||||
|
|
@ -597,14 +597,14 @@ add_port_data (SpaAudioMixer *this, SpaBuffer *out, SpaAudioMixerPort *port)
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
if (op == NULL) {
|
if (op == NULL) {
|
||||||
mem = spa_memory_find (&odatas[oi].mem);
|
mem = spa_memory_find (&odatas[oi].mem.mem);
|
||||||
op = (uint8_t*)mem->ptr + odatas[oi].offset;
|
op = (uint8_t*)mem->ptr + odatas[oi].mem.offset;
|
||||||
os = odatas[oi].size;
|
os = odatas[oi].mem.size;
|
||||||
}
|
}
|
||||||
if (ip == NULL) {
|
if (ip == NULL) {
|
||||||
mem = spa_memory_find (&idatas[port->buffer_index].mem);
|
mem = spa_memory_find (&idatas[port->buffer_index].mem.mem);
|
||||||
ip = (uint8_t*)mem->ptr + odatas[oi].offset;
|
ip = (uint8_t*)mem->ptr + odatas[oi].mem.offset;
|
||||||
is = idatas[port->buffer_index].size;
|
is = idatas[port->buffer_index].mem.size;
|
||||||
ip += port->buffer_offset;
|
ip += port->buffer_offset;
|
||||||
is -= port->buffer_offset;
|
is -= port->buffer_offset;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,9 +28,10 @@
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
|
||||||
#include <spa/node.h>
|
|
||||||
#include <spa/memory.h>
|
|
||||||
#include <spa/control.h>
|
#include <spa/control.h>
|
||||||
|
#include <spa/debug.h>
|
||||||
|
#include <spa/memory.h>
|
||||||
|
#include <spa/node.h>
|
||||||
|
|
||||||
#define MAX_INPUTS 64
|
#define MAX_INPUTS 64
|
||||||
#define MAX_OUTPUTS 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);
|
spa_control_builder_init_into (&builder, buf, sizeof (buf), NULL, 0);
|
||||||
sf.port_id = port_id;
|
sf.port_id = port_id;
|
||||||
sf.format = (SpaFormat *) format;
|
sf.format = (SpaFormat *) format;
|
||||||
|
|
||||||
|
spa_debug_format (sf.format);
|
||||||
|
|
||||||
spa_control_builder_add_cmd (&builder, SPA_CONTROL_CMD_SET_FORMAT, &sf);
|
spa_control_builder_add_cmd (&builder, SPA_CONTROL_CMD_SET_FORMAT, &sf);
|
||||||
spa_control_builder_end (&builder, &control);
|
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));
|
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);
|
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 = spa_memory_ensure_ptr (bmem);
|
||||||
b->mem = bmem->mem;
|
b->mem.mem = bmem->mem;
|
||||||
b->offset = 0;
|
b->mem.offset = 0;
|
||||||
} else {
|
} else {
|
||||||
bmem = spa_memory_find (&buffer->mem);
|
bmem = spa_memory_find (&buffer->mem.mem);
|
||||||
b = buffer;
|
b = buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -586,7 +590,7 @@ add_buffer (SpaProxy *this, uint32_t port_id, SpaBuffer *buffer)
|
||||||
SpaData *d = &SPA_BUFFER_DATAS (b)[i];
|
SpaData *d = &SPA_BUFFER_DATAS (b)[i];
|
||||||
SpaMemory *mem;
|
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);
|
fprintf (stderr, "proxy %p: error invalid memory\n", this);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -601,9 +605,9 @@ add_buffer (SpaProxy *this, uint32_t port_id, SpaBuffer *buffer)
|
||||||
}
|
}
|
||||||
ab.port_id = port_id;
|
ab.port_id = port_id;
|
||||||
ab.buffer_id = b->id;
|
ab.buffer_id = b->id;
|
||||||
ab.mem = bmem->mem;
|
ab.mem.mem = bmem->mem;
|
||||||
ab.offset = b->offset;
|
ab.mem.offset = b->mem.offset;
|
||||||
ab.size = b->size;
|
ab.mem.size = b->mem.size;
|
||||||
spa_control_builder_add_cmd (&builder, SPA_CONTROL_CMD_ADD_BUFFER, &ab);
|
spa_control_builder_add_cmd (&builder, SPA_CONTROL_CMD_ADD_BUFFER, &ab);
|
||||||
|
|
||||||
spa_control_builder_end (&builder, &control);
|
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;
|
rb.buffer_id = buffer->id;
|
||||||
spa_control_builder_add_cmd (&builder, SPA_CONTROL_CMD_REMOVE_BUFFER, &rb);
|
spa_control_builder_add_cmd (&builder, SPA_CONTROL_CMD_REMOVE_BUFFER, &rb);
|
||||||
rm.port_id = port_id;
|
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);
|
spa_control_builder_add_cmd (&builder, SPA_CONTROL_CMD_REMOVE_MEM, &rm);
|
||||||
|
|
||||||
for (i = 0; i < buffer->n_datas; i++) {
|
for (i = 0; i < buffer->n_datas; i++) {
|
||||||
SpaData *d = &SPA_BUFFER_DATAS (buffer)[i];
|
SpaData *d = &SPA_BUFFER_DATAS (buffer)[i];
|
||||||
|
|
||||||
rm.port_id = port_id;
|
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_add_cmd (&builder, SPA_CONTROL_CMD_REMOVE_MEM, &rm);
|
||||||
}
|
}
|
||||||
spa_control_builder_end (&builder, &control);
|
spa_control_builder_end (&builder, &control);
|
||||||
|
|
|
||||||
|
|
@ -537,16 +537,16 @@ spa_v4l2_import_buffers (SpaV4l2Source *this, SpaBuffer **buffers, uint32_t n_bu
|
||||||
SpaData *d = SPA_BUFFER_DATAS (buffers[i]);
|
SpaData *d = SPA_BUFFER_DATAS (buffers[i]);
|
||||||
|
|
||||||
b = &state->alloc_buffers[i];
|
b = &state->alloc_buffers[i];
|
||||||
b->buffer.mem = state->alloc_mem->mem;
|
b->buffer.mem.mem = state->alloc_mem->mem;
|
||||||
b->buffer.offset = sizeof (V4l2Buffer) * i;
|
b->buffer.mem.offset = sizeof (V4l2Buffer) * i;
|
||||||
b->buffer.size = sizeof (V4l2Buffer);
|
b->buffer.mem.size = sizeof (V4l2Buffer);
|
||||||
b->buffer.id = SPA_ID_INVALID;
|
b->buffer.id = SPA_ID_INVALID;
|
||||||
b->outbuf = buffers[i];
|
b->outbuf = buffers[i];
|
||||||
b->outstanding = true;
|
b->outstanding = true;
|
||||||
|
|
||||||
fprintf (stderr, "import buffer %p\n", buffers[i]);
|
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))) {
|
if (!(mem = spa_memory_find (mem_ref))) {
|
||||||
fprintf (stderr, "invalid memory on buffer %p\n", buffers[i]);
|
fprintf (stderr, "invalid memory on buffer %p\n", buffers[i]);
|
||||||
continue;
|
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.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||||
b->v4l2_buffer.memory = state->memtype;
|
b->v4l2_buffer.memory = state->memtype;
|
||||||
b->v4l2_buffer.index = i;
|
b->v4l2_buffer.index = i;
|
||||||
b->v4l2_buffer.m.userptr = (unsigned long) ((uint8_t*)mem->ptr + d[0].offset);
|
b->v4l2_buffer.m.userptr = (unsigned long) ((uint8_t*)mem->ptr + d[0].mem.offset);
|
||||||
b->v4l2_buffer.length = d[0].size;
|
b->v4l2_buffer.length = d[0].mem.size;
|
||||||
|
|
||||||
spa_v4l2_buffer_recycle (this, buffers[i]->id);
|
spa_v4l2_buffer_recycle (this, buffers[i]->id);
|
||||||
}
|
}
|
||||||
|
|
@ -625,9 +625,9 @@ mmap_init (SpaV4l2Source *this,
|
||||||
|
|
||||||
b = &state->alloc_buffers[i];
|
b = &state->alloc_buffers[i];
|
||||||
b->buffer.id = i;
|
b->buffer.id = i;
|
||||||
b->buffer.mem = state->alloc_mem->mem;
|
b->buffer.mem.mem = state->alloc_mem->mem;
|
||||||
b->buffer.offset = sizeof (V4l2Buffer) * i;
|
b->buffer.mem.offset = sizeof (V4l2Buffer) * i;
|
||||||
b->buffer.size = sizeof (V4l2Buffer);
|
b->buffer.mem.size = sizeof (V4l2Buffer);
|
||||||
|
|
||||||
buffers[i] = &b->buffer;
|
buffers[i] = &b->buffer;
|
||||||
|
|
||||||
|
|
@ -648,9 +648,9 @@ mmap_init (SpaV4l2Source *this,
|
||||||
mem = spa_memory_alloc (SPA_MEMORY_POOL_SHARED);
|
mem = spa_memory_alloc (SPA_MEMORY_POOL_SHARED);
|
||||||
mem->flags = SPA_MEMORY_FLAG_READABLE;
|
mem->flags = SPA_MEMORY_FLAG_READABLE;
|
||||||
mem->size = buf.length;
|
mem->size = buf.length;
|
||||||
b->datas[0].mem = mem->mem;
|
b->datas[0].mem.mem = mem->mem;
|
||||||
b->datas[0].offset = 0;
|
b->datas[0].mem.offset = 0;
|
||||||
b->datas[0].size = buf.length;
|
b->datas[0].mem.size = buf.length;
|
||||||
b->datas[0].stride = state->fmt.fmt.pix.bytesperline;
|
b->datas[0].stride = state->fmt.fmt.pix.bytesperline;
|
||||||
|
|
||||||
if (state->export_buf) {
|
if (state->export_buf) {
|
||||||
|
|
@ -797,7 +797,7 @@ spa_v4l2_stop (SpaV4l2Source *this)
|
||||||
fprintf (stderr, "queueing outstanding buffer %p\n", b);
|
fprintf (stderr, "queueing outstanding buffer %p\n", b);
|
||||||
spa_v4l2_buffer_recycle (this, i);
|
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) {
|
if (state->export_buf) {
|
||||||
close (mem->fd);
|
close (mem->fd);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -583,13 +583,13 @@ spa_volume_node_port_pull_output (SpaNode *node,
|
||||||
sd = &SPA_BUFFER_DATAS (sbuf)[si];
|
sd = &SPA_BUFFER_DATAS (sbuf)[si];
|
||||||
dd = &SPA_BUFFER_DATAS (dbuf)[di];
|
dd = &SPA_BUFFER_DATAS (dbuf)[di];
|
||||||
|
|
||||||
sm = spa_memory_find (&sd->mem);
|
sm = spa_memory_find (&sd->mem.mem);
|
||||||
dm = spa_memory_find (&dd->mem);
|
dm = spa_memory_find (&dd->mem.mem);
|
||||||
|
|
||||||
src = (uint16_t*) ((uint8_t*)sm->ptr + sd->offset + soff);
|
src = (uint16_t*) ((uint8_t*)sm->ptr + sd->mem.offset + soff);
|
||||||
dst = (uint16_t*) ((uint8_t*)dm->ptr + dd->offset + doff);
|
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);
|
n_samples = n_bytes / sizeof (uint16_t);
|
||||||
|
|
||||||
for (i = 0; i < n_samples; i++)
|
for (i = 0; i < n_samples; i++)
|
||||||
|
|
@ -598,11 +598,11 @@ spa_volume_node_port_pull_output (SpaNode *node,
|
||||||
soff += n_bytes;
|
soff += n_bytes;
|
||||||
doff += n_bytes;
|
doff += n_bytes;
|
||||||
|
|
||||||
if (soff >= sd->size) {
|
if (soff >= sd->mem.size) {
|
||||||
si++;
|
si++;
|
||||||
soff = 0;
|
soff = 0;
|
||||||
}
|
}
|
||||||
if (doff >= dd->size) {
|
if (doff >= dd->mem.size) {
|
||||||
di++;
|
di++;
|
||||||
doff = 0;
|
doff = 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -150,19 +150,19 @@ on_source_event (SpaNode *node, SpaEvent *event, void *user_data)
|
||||||
fprintf (stderr, "Couldn't lock texture: %s\n", SDL_GetError());
|
fprintf (stderr, "Couldn't lock texture: %s\n", SDL_GetError());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mem = spa_memory_find (&datas[0].mem);
|
mem = spa_memory_find (&datas[0].mem.mem);
|
||||||
mem->ptr = sdata;
|
mem->ptr = sdata;
|
||||||
mem->type = "sysmem";
|
mem->type = "sysmem";
|
||||||
mem->size = sstride * 240;
|
mem->size = sstride * 240;
|
||||||
|
|
||||||
datas[0].size = sstride * 240;
|
datas[0].mem.size = sstride * 240;
|
||||||
datas[0].stride = sstride;
|
datas[0].stride = sstride;
|
||||||
} else {
|
} else {
|
||||||
if (SDL_LockTexture (data->texture, NULL, &ddata, &dstride) < 0) {
|
if (SDL_LockTexture (data->texture, NULL, &ddata, &dstride) < 0) {
|
||||||
fprintf (stderr, "Couldn't lock texture: %s\n", SDL_GetError());
|
fprintf (stderr, "Couldn't lock texture: %s\n", SDL_GetError());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mem = spa_memory_find (&datas[0].mem);
|
mem = spa_memory_find (&datas[0].mem.mem);
|
||||||
|
|
||||||
sdata = spa_memory_ensure_ptr (mem);
|
sdata = spa_memory_ensure_ptr (mem);
|
||||||
sstride = datas[0].stride;
|
sstride = datas[0].stride;
|
||||||
|
|
@ -252,10 +252,10 @@ alloc_buffers (AppData *data)
|
||||||
}
|
}
|
||||||
|
|
||||||
b->buffer.id = i;
|
b->buffer.id = i;
|
||||||
b->buffer.mem.pool_id = SPA_ID_INVALID;
|
b->buffer.mem.mem.pool_id = SPA_ID_INVALID;
|
||||||
b->buffer.mem.id = SPA_ID_INVALID;
|
b->buffer.mem.mem.id = SPA_ID_INVALID;
|
||||||
b->buffer.offset = 0;
|
b->buffer.mem.offset = 0;
|
||||||
b->buffer.size = sizeof (SDLBuffer);
|
b->buffer.mem.size = sizeof (SDLBuffer);
|
||||||
b->buffer.n_metas = 2;
|
b->buffer.n_metas = 2;
|
||||||
b->buffer.metas = offsetof (SDLBuffer, metas);
|
b->buffer.metas = offsetof (SDLBuffer, metas);
|
||||||
b->buffer.n_datas = 1;
|
b->buffer.n_datas = 1;
|
||||||
|
|
@ -282,9 +282,9 @@ alloc_buffers (AppData *data)
|
||||||
mem->ptr = ptr;
|
mem->ptr = ptr;
|
||||||
mem->size = stride * 240;
|
mem->size = stride * 240;
|
||||||
|
|
||||||
b->datas[0].mem = mem->mem;
|
b->datas[0].mem.mem = mem->mem;
|
||||||
b->datas[0].offset = 0;
|
b->datas[0].mem.offset = 0;
|
||||||
b->datas[0].size = mem->size;
|
b->datas[0].mem.size = mem->size;
|
||||||
b->datas[0].stride = stride;
|
b->datas[0].stride = stride;
|
||||||
}
|
}
|
||||||
data->n_buffers = MAX_BUFFERS;
|
data->n_buffers = MAX_BUFFERS;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue