mirror of
https://gitlab.freedesktop.org/pipewire/pipewire
synced 2024-10-14 20:02:38 +00:00
buffer: improve memory management
Add refcounting to buffers. Use static memory on ports for buffer input and output memory. Improve negotiation, let format and properties be negotiated on ports as the data passes. Improve some debug info.
This commit is contained in:
parent
4a5ed1e1f5
commit
0f67434ae8
|
@ -38,8 +38,8 @@ G_STATIC_ASSERT (sizeof (PinosStackBuffer) <= sizeof (PinosBuffer));
|
|||
*
|
||||
* Initialize @buffer with @data and @size and @fds and @n_fds.
|
||||
* The memory pointer to by @data and @fds becomes property of @buffer
|
||||
* and should not be freed or modified until pinos_buffer_clear() is
|
||||
* called.
|
||||
* and should not be freed or modified until all referenced to the buffer
|
||||
* are gone pinos_buffer_unref().
|
||||
*/
|
||||
void
|
||||
pinos_buffer_init_data (PinosBuffer *buffer,
|
||||
|
@ -50,7 +50,10 @@ pinos_buffer_init_data (PinosBuffer *buffer,
|
|||
{
|
||||
PinosStackBuffer *sb = PSB (buffer);
|
||||
|
||||
g_debug ("buffer %p: init", buffer);
|
||||
|
||||
sb->magic = PSB_MAGIC;
|
||||
sb->refcount = 1;
|
||||
sb->data = data;
|
||||
sb->size = size;
|
||||
sb->max_size = size;
|
||||
|
@ -61,20 +64,44 @@ pinos_buffer_init_data (PinosBuffer *buffer,
|
|||
sb->free_fds = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
pinos_buffer_clear (PinosBuffer *buffer)
|
||||
PinosBuffer *
|
||||
pinos_buffer_ref (PinosBuffer *buffer)
|
||||
{
|
||||
PinosStackBuffer *sb = PSB (buffer);
|
||||
|
||||
g_return_val_if_fail (is_valid_buffer (buffer), NULL);
|
||||
|
||||
g_debug ("buffer %p: ref %d -> %d", buffer, sb->refcount, sb->refcount+1);
|
||||
|
||||
sb->refcount++;
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
gboolean
|
||||
pinos_buffer_unref (PinosBuffer *buffer)
|
||||
{
|
||||
PinosStackBuffer *sb = PSB (buffer);
|
||||
gboolean res;
|
||||
gint i;
|
||||
|
||||
g_return_if_fail (is_valid_buffer (buffer));
|
||||
g_return_val_if_fail (is_valid_buffer (buffer), FALSE);
|
||||
|
||||
sb->magic = 0;
|
||||
g_free (sb->free_data);
|
||||
for (i = 0; i < sb->n_fds; i++)
|
||||
close (sb->fds[i]);
|
||||
g_free (sb->free_fds);
|
||||
sb->n_fds = 0;
|
||||
g_debug ("buffer %p: unref %d -> %d", buffer, sb->refcount, sb->refcount-1);
|
||||
|
||||
sb->refcount--;
|
||||
res = sb->refcount > 0;
|
||||
if (!res) {
|
||||
sb->magic = 0;
|
||||
g_free (sb->free_data);
|
||||
for (i = 0; i < sb->n_fds; i++) {
|
||||
g_debug ("%p: close %d %d", buffer, i, sb->fds[i]);
|
||||
close (sb->fds[i]);
|
||||
}
|
||||
g_free (sb->free_fds);
|
||||
sb->n_fds = 0;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -158,7 +185,8 @@ pinos_buffer_steal_data (PinosBuffer *buffer,
|
|||
PinosStackBuffer *sb = PSB (buffer);
|
||||
gpointer data;
|
||||
|
||||
g_return_val_if_fail (is_valid_buffer (buffer), 0);
|
||||
g_return_val_if_fail (is_valid_buffer (buffer), NULL);
|
||||
g_return_val_if_fail (sb->refcount == 1, NULL);
|
||||
|
||||
data = sb->data;
|
||||
if (size)
|
||||
|
@ -190,7 +218,8 @@ pinos_buffer_steal_fds (PinosBuffer *buffer,
|
|||
PinosStackBuffer *sb = PSB (buffer);
|
||||
gint *fds;
|
||||
|
||||
g_return_val_if_fail (is_valid_buffer (buffer), 0);
|
||||
g_return_val_if_fail (is_valid_buffer (buffer), NULL);
|
||||
g_return_val_if_fail (sb->refcount == 1, NULL);
|
||||
|
||||
fds = sb->fds;
|
||||
if (n_fds)
|
||||
|
@ -332,6 +361,22 @@ pinos_buffer_iter_next (PinosBufferIter *iter)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* pinos_buffer_iter_done:
|
||||
* @iter: a #PinosBufferIter
|
||||
*
|
||||
* End iterations on @iter.
|
||||
*/
|
||||
void
|
||||
pinos_buffer_iter_end (PinosBufferIter *iter)
|
||||
{
|
||||
struct stack_iter *si = PPSI (iter);
|
||||
|
||||
g_return_if_fail (is_valid_iter (iter));
|
||||
|
||||
si->magic = 0;
|
||||
}
|
||||
|
||||
PinosPacketType
|
||||
pinos_buffer_iter_get_type (PinosBufferIter *iter)
|
||||
{
|
||||
|
@ -408,6 +453,8 @@ pinos_buffer_builder_init_full (PinosBufferBuilder *builder,
|
|||
sb->buf.max_size = sizeof (PinosStackHeader) + 128;
|
||||
sb->buf.data = g_malloc (sb->buf.max_size);
|
||||
sb->buf.free_data = sb->buf.data;
|
||||
g_warning ("builder %p: realloc buffer memory %"G_GSIZE_FORMAT" -> %"G_GSIZE_FORMAT,
|
||||
builder, max_data, sb->buf.max_size);
|
||||
} else {
|
||||
sb->buf.max_size = max_data;
|
||||
sb->buf.data = data;
|
||||
|
@ -493,6 +540,7 @@ pinos_buffer_builder_end (PinosBufferBuilder *builder,
|
|||
sb->sh->length = sb->buf.size - sizeof (PinosStackHeader);
|
||||
|
||||
sbuf->magic = PSB_MAGIC;
|
||||
sbuf->refcount = 1;
|
||||
sbuf->data = sb->buf.data;
|
||||
sbuf->size = sb->buf.size;
|
||||
sbuf->max_size = sb->buf.max_size;
|
||||
|
@ -502,6 +550,8 @@ pinos_buffer_builder_end (PinosBufferBuilder *builder,
|
|||
sbuf->n_fds = sb->buf.n_fds;
|
||||
sbuf->max_fds = sb->buf.max_fds;
|
||||
sbuf->free_fds = sb->buf.free_fds;
|
||||
|
||||
g_debug ("builder %p: buffer %p init", builder, buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -524,8 +574,11 @@ pinos_buffer_builder_add_fd (PinosBufferBuilder *builder,
|
|||
g_return_val_if_fail (fd > 0, -1);
|
||||
|
||||
if (sb->buf.n_fds >= sb->buf.max_fds) {
|
||||
sb->buf.max_fds += 8;
|
||||
sb->buf.free_fds = g_realloc (sb->buf.free_fds, sb->buf.max_fds * sizeof (int));
|
||||
gint new_size = sb->buf.max_fds + 8;
|
||||
g_warning ("builder %p: realloc buffer fds %d -> %d",
|
||||
builder, sb->buf.max_fds, new_size);
|
||||
sb->buf.max_fds = new_size;
|
||||
sb->buf.free_fds = g_realloc (sb->buf.free_fds, new_size * sizeof (int));
|
||||
sb->buf.fds = sb->buf.free_fds;
|
||||
}
|
||||
index = sb->buf.n_fds;
|
||||
|
@ -539,8 +592,11 @@ static gpointer
|
|||
builder_ensure_size (struct stack_builder *sb, gsize size)
|
||||
{
|
||||
if (sb->buf.size + size > sb->buf.max_size) {
|
||||
sb->buf.max_size = sb->buf.size + MAX (size, 1024);
|
||||
sb->buf.free_data = g_realloc (sb->buf.free_data, sb->buf.max_size);
|
||||
gsize new_size = sb->buf.size + MAX (size, 1024);
|
||||
g_warning ("builder %p: realloc buffer memory %"G_GSIZE_FORMAT" -> %"G_GSIZE_FORMAT,
|
||||
sb, sb->buf.max_size, new_size);
|
||||
sb->buf.max_size = new_size;
|
||||
sb->buf.free_data = g_realloc (sb->buf.free_data, new_size);
|
||||
sb->sh = sb->buf.data = sb->buf.free_data;
|
||||
}
|
||||
return (guint8 *) sb->buf.data + sb->buf.size;
|
||||
|
|
|
@ -55,7 +55,8 @@ void pinos_buffer_init_data (PinosBuffer *buffer,
|
|||
gint *fds,
|
||||
gint n_fds);
|
||||
|
||||
void pinos_buffer_clear (PinosBuffer *buffer);
|
||||
PinosBuffer * pinos_buffer_ref (PinosBuffer *buffer);
|
||||
gboolean pinos_buffer_unref (PinosBuffer *buffer);
|
||||
|
||||
guint32 pinos_buffer_get_version (PinosBuffer *buffer);
|
||||
PinosBufferFlags pinos_buffer_get_flags (PinosBuffer *buffer);
|
||||
|
@ -109,6 +110,7 @@ void pinos_buffer_iter_init_full (PinosBufferIter *iter,
|
|||
#define pinos_buffer_iter_init(i,b) pinos_buffer_iter_init_full(i,b, PINOS_BUFFER_VERSION);
|
||||
|
||||
gboolean pinos_buffer_iter_next (PinosBufferIter *iter);
|
||||
void pinos_buffer_iter_end (PinosBufferIter *iter);
|
||||
|
||||
PinosPacketType pinos_buffer_iter_get_type (PinosBufferIter *iter);
|
||||
gpointer pinos_buffer_iter_get_data (PinosBufferIter *iter, gsize *size);
|
||||
|
|
|
@ -159,6 +159,8 @@ create_failed:
|
|||
g_warning ("failed to create port: %s", error->message);
|
||||
g_task_return_error (task, error);
|
||||
g_object_unref (task);
|
||||
if (ret)
|
||||
g_variant_unref (ret);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -221,9 +223,9 @@ client_node_remove_port (PinosNode *node,
|
|||
|
||||
static void
|
||||
pinos_client_node_get_property (GObject *_object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
PinosClientNode *node = PINOS_CLIENT_NODE (_object);
|
||||
PinosClientNodePrivate *priv = node->priv;
|
||||
|
|
|
@ -100,23 +100,21 @@ proxy_g_properties_changed (GDBusProxy *_proxy,
|
|||
gpointer data;
|
||||
GBytes *bytes;
|
||||
|
||||
g_debug ("changed %s", key);
|
||||
|
||||
variant = g_dbus_proxy_get_cached_property (_proxy, key);
|
||||
if (variant == NULL)
|
||||
continue;
|
||||
|
||||
if (strcmp (key, "Format") == 0) {
|
||||
if (strcmp (key, "PossibleFormats") == 0) {
|
||||
data = g_variant_dup_string (variant, &size);
|
||||
bytes = g_bytes_new_take (data, size);
|
||||
g_object_set (port, "format", bytes, NULL);
|
||||
g_object_set (port, "possible-formats", bytes, NULL);
|
||||
g_bytes_unref (bytes);
|
||||
}
|
||||
g_variant_unref (variant);
|
||||
}
|
||||
g_variant_iter_free (iter);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void
|
||||
proxy_set_property_cb (GDBusProxy *proxy,
|
||||
GAsyncResult *res,
|
||||
|
@ -144,23 +142,11 @@ on_property_notify (GObject *obj,
|
|||
const gchar *prop_name = NULL;
|
||||
GVariant *variant;
|
||||
|
||||
g_debug ("update %s", pspec ? g_param_spec_get_name (pspec) : "NULL");
|
||||
|
||||
if (pspec == NULL || strcmp (g_param_spec_get_name (pspec), "properties") == 0) {
|
||||
PinosProperties *props = pinos_port_get_properties (port);
|
||||
prop_name = "Properties";
|
||||
variant = props ? pinos_properties_to_variant (props) : NULL;
|
||||
}
|
||||
if (pspec == NULL || strcmp (g_param_spec_get_name (pspec), "possible-formats") == 0) {
|
||||
GBytes *bytes = pinos_port_get_possible_formats (port);
|
||||
prop_name = "PossibleFormats";
|
||||
variant = bytes ? g_variant_new_string (g_bytes_get_data (bytes, NULL)) : NULL;
|
||||
}
|
||||
if (pspec == NULL || strcmp (g_param_spec_get_name (pspec), "format") == 0) {
|
||||
GBytes *bytes = pinos_port_get_format (port);
|
||||
prop_name = "Format";
|
||||
variant = bytes ? g_variant_new_string (g_bytes_get_data (bytes, NULL)) : NULL;
|
||||
}
|
||||
if (prop_name) {
|
||||
g_dbus_proxy_call (G_DBUS_PROXY (priv->proxy),
|
||||
"org.freedesktop.DBus.Properties.Set",
|
||||
|
@ -173,11 +159,8 @@ on_property_notify (GObject *obj,
|
|||
NULL,
|
||||
(GAsyncReadyCallback) proxy_set_property_cb,
|
||||
port);
|
||||
if (variant)
|
||||
g_variant_unref (variant);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
pinos_client_port_constructed (GObject * object)
|
||||
|
@ -190,6 +173,7 @@ pinos_client_port_constructed (GObject * object)
|
|||
"g-properties-changed",
|
||||
(GCallback) proxy_g_properties_changed,
|
||||
port);
|
||||
g_signal_connect (port, "notify", (GCallback) on_property_notify, port);
|
||||
|
||||
G_OBJECT_CLASS (pinos_client_port_parent_class)->constructed (object);
|
||||
}
|
||||
|
|
|
@ -36,6 +36,15 @@
|
|||
#define PINOS_PORT_GET_PRIVATE(obj) \
|
||||
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), PINOS_TYPE_PORT, PinosPortPrivate))
|
||||
|
||||
#if 0
|
||||
#define PINOS_DEBUG_TRANSPORT(format,args...) g_debug(format,##args)
|
||||
#else
|
||||
#define PINOS_DEBUG_TRANSPORT(format,args...)
|
||||
#endif
|
||||
|
||||
#define MAX_BUFFER_SIZE 1024
|
||||
#define MAX_FDS 16
|
||||
|
||||
struct _PinosPortPrivate
|
||||
{
|
||||
PinosNode *node;
|
||||
|
@ -49,7 +58,12 @@ struct _PinosPortPrivate
|
|||
|
||||
GSource *socket_source;
|
||||
|
||||
PinosBuffer net_buffer;
|
||||
PinosBuffer recv_buffer;
|
||||
guint8 recv_data[MAX_BUFFER_SIZE];
|
||||
gint recv_fds[MAX_FDS];
|
||||
|
||||
guint8 send_data[MAX_BUFFER_SIZE];
|
||||
gint send_fds[MAX_FDS];
|
||||
|
||||
PinosBuffer *buffer;
|
||||
PinosPort *peers[16];
|
||||
|
@ -367,7 +381,6 @@ pinos_port_link (PinosPort *source, PinosPort *destination)
|
|||
|
||||
source->priv->peers[source->priv->n_peers++] = destination;
|
||||
destination->priv->peers[destination->priv->n_peers++] = source;
|
||||
g_object_set (destination, "format", source->priv->format, NULL);
|
||||
|
||||
g_debug ("port %p: linked to %p", source, destination);
|
||||
g_signal_emit (source, signals[SIGNAL_LINKED], 0, destination);
|
||||
|
@ -444,27 +457,31 @@ pinos_port_get_n_links (PinosPort *port)
|
|||
return port->priv->n_peers;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
read_buffer (GSocket *socket,
|
||||
PinosBuffer *buffer,
|
||||
static PinosBuffer *
|
||||
read_buffer (PinosPort *port,
|
||||
GError **error)
|
||||
{
|
||||
PinosPortPrivate *priv = port->priv;
|
||||
gssize len;
|
||||
GInputVector ivec;
|
||||
PinosStackHeader *hdr;
|
||||
GSocketControlMessage **messages = NULL;
|
||||
PinosStackBuffer *sb = (PinosStackBuffer *) buffer;
|
||||
PinosStackBuffer *sb = (PinosStackBuffer *) &priv->recv_buffer;
|
||||
gint num_messages = 0;
|
||||
gint flags = 0;
|
||||
gsize need;
|
||||
gint i;
|
||||
|
||||
need = sizeof (PinosStackHeader);
|
||||
g_assert (sb->refcount == 0);
|
||||
|
||||
if (sb->max_size < need) {
|
||||
sb->max_size = need;
|
||||
sb->data = sb->free_data = g_realloc (sb->free_data, need);
|
||||
}
|
||||
sb->data = priv->recv_data;
|
||||
sb->max_size = MAX_BUFFER_SIZE;
|
||||
sb->size = 0;
|
||||
sb->free_data = NULL;
|
||||
sb->fds = priv->recv_fds;
|
||||
sb->max_fds = MAX_FDS;
|
||||
sb->n_fds = 0;
|
||||
sb->free_fds = NULL;
|
||||
|
||||
hdr = sb->data;
|
||||
|
||||
|
@ -472,7 +489,7 @@ read_buffer (GSocket *socket,
|
|||
ivec.buffer = hdr;
|
||||
ivec.size = sizeof (PinosStackHeader);
|
||||
|
||||
len = g_socket_receive_message (socket,
|
||||
len = g_socket_receive_message (priv->sockets[0],
|
||||
NULL,
|
||||
&ivec,
|
||||
1,
|
||||
|
@ -482,14 +499,15 @@ read_buffer (GSocket *socket,
|
|||
NULL,
|
||||
error);
|
||||
if (len == -1)
|
||||
return FALSE;
|
||||
return NULL;
|
||||
|
||||
g_assert (len == sizeof (PinosStackHeader));
|
||||
|
||||
/* now we know the total length */
|
||||
need += hdr->length;
|
||||
need = sizeof (PinosStackHeader) + hdr->length;
|
||||
|
||||
if (sb->max_size < need) {
|
||||
g_warning ("port %p: realloc receive memory %" G_GSIZE_FORMAT" -> %" G_GSIZE_FORMAT, port, sb->max_size, need);
|
||||
sb->max_size = need;
|
||||
hdr = sb->data = sb->free_data = g_realloc (sb->free_data, need);
|
||||
}
|
||||
|
@ -497,18 +515,19 @@ read_buffer (GSocket *socket,
|
|||
|
||||
if (hdr->length > 0) {
|
||||
/* read data */
|
||||
len = g_socket_receive (socket,
|
||||
len = g_socket_receive (priv->sockets[0],
|
||||
(gchar *)sb->data + sizeof (PinosStackHeader),
|
||||
hdr->length,
|
||||
NULL,
|
||||
error);
|
||||
if (len == -1)
|
||||
return FALSE;
|
||||
return NULL;
|
||||
|
||||
g_assert (len == hdr->length);
|
||||
}
|
||||
|
||||
if (sb->max_fds < num_messages) {
|
||||
g_warning ("port %p: realloc receive fds %d -> %d", port, sb->max_fds, num_messages);
|
||||
sb->max_fds = num_messages;
|
||||
sb->fds = sb->free_fds = g_realloc (sb->free_fds, num_messages * sizeof (int));
|
||||
}
|
||||
|
@ -524,14 +543,18 @@ read_buffer (GSocket *socket,
|
|||
fds = g_unix_fd_message_steal_fds (G_UNIX_FD_MESSAGE (msg), &n_fds);
|
||||
for (j = 0; j < n_fds; j++)
|
||||
sb->fds[i] = fds[i];
|
||||
sb->n_fds = n_fds;
|
||||
g_free (fds);
|
||||
g_object_unref (msg);
|
||||
}
|
||||
g_free (messages);
|
||||
|
||||
sb->refcount = 1;
|
||||
sb->magic = PSB_MAGIC;
|
||||
|
||||
return TRUE;
|
||||
g_debug ("port %p: buffer %p init", &priv->recv_buffer, sb);
|
||||
|
||||
return &priv->recv_buffer;
|
||||
}
|
||||
|
||||
|
||||
|
@ -593,6 +616,73 @@ send_error:
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
parse_control_buffer (PinosPort *port, PinosBuffer *buffer)
|
||||
{
|
||||
PinosPortPrivate *priv = port->priv;
|
||||
PinosBufferIter it;
|
||||
|
||||
pinos_buffer_iter_init (&it, buffer);
|
||||
while (pinos_buffer_iter_next (&it)) {
|
||||
switch (pinos_buffer_iter_get_type (&it)) {
|
||||
case PINOS_PACKET_TYPE_FORMAT_CHANGE:
|
||||
{
|
||||
PinosPacketFormatChange change;
|
||||
|
||||
if (!pinos_buffer_iter_parse_format_change (&it, &change))
|
||||
continue;
|
||||
|
||||
if (priv->format)
|
||||
g_bytes_unref (priv->format);
|
||||
priv->format = g_bytes_new (change.format, strlen (change.format) + 1);
|
||||
g_object_notify (G_OBJECT (port), "format");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
pinos_port_receive_buffer (PinosPort *port,
|
||||
PinosBuffer *buffer,
|
||||
GError **error)
|
||||
{
|
||||
PinosPortPrivate *priv = port->priv;
|
||||
gboolean res;
|
||||
|
||||
if (priv->buffer)
|
||||
goto buffer_queued;
|
||||
|
||||
PINOS_DEBUG_TRANSPORT ("port %p: receive buffer %p", port, buffer);
|
||||
if (pinos_buffer_get_flags (buffer) & PINOS_BUFFER_FLAG_CONTROL)
|
||||
parse_control_buffer (port, buffer);
|
||||
|
||||
if (priv->sockets[0]) {
|
||||
PINOS_DEBUG_TRANSPORT ("port %p: write buffer %p", port, buffer);
|
||||
res = write_buffer (priv->sockets[0], buffer, error);
|
||||
}
|
||||
else {
|
||||
res = TRUE;
|
||||
priv->buffer = buffer;
|
||||
if (priv->received_buffer_cb)
|
||||
priv->received_buffer_cb (port, priv->received_buffer_data);
|
||||
priv->buffer = NULL;
|
||||
}
|
||||
|
||||
return res;
|
||||
|
||||
/* ERRORS */
|
||||
buffer_queued:
|
||||
{
|
||||
g_set_error (error,
|
||||
G_IO_ERROR,
|
||||
G_IO_ERROR_NOT_FOUND,
|
||||
"buffer was already queued on port");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
on_socket_condition (GSocket *socket,
|
||||
|
@ -605,27 +695,42 @@ on_socket_condition (GSocket *socket,
|
|||
|
||||
switch (condition) {
|
||||
case G_IO_IN:
|
||||
if (!read_buffer (socket, &priv->net_buffer, &error))
|
||||
goto read_failed;
|
||||
g_debug ("port %p: received buffer", port);
|
||||
{
|
||||
gint i;
|
||||
PinosBuffer *buffer;
|
||||
|
||||
if (priv->direction == PINOS_DIRECTION_INPUT) {
|
||||
priv->buffer = &priv->net_buffer;
|
||||
if (priv->received_buffer_cb)
|
||||
priv->received_buffer_cb (port, priv->received_buffer_data);
|
||||
} else {
|
||||
gint i;
|
||||
for (i = 0; i < priv->n_peers; i++) {
|
||||
PinosPort *peer = priv->peers[i];
|
||||
if (peer == NULL)
|
||||
continue;
|
||||
buffer = read_buffer (port, &error);
|
||||
if (buffer == NULL) {
|
||||
g_warning ("port %p: failed to read buffer: %s", port, error->message);
|
||||
g_clear_error (&error);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
g_debug ("port %p: send buffer %p to peer %p", port, &priv->net_buffer, peer);
|
||||
if (!pinos_port_receive_buffer (peer, &priv->net_buffer, &error))
|
||||
goto read_failed;
|
||||
if (pinos_buffer_get_flags (buffer) & PINOS_BUFFER_FLAG_CONTROL)
|
||||
parse_control_buffer (port, buffer);
|
||||
|
||||
PINOS_DEBUG_TRANSPORT ("port %p: read buffer %p", port, buffer);
|
||||
|
||||
if (priv->received_buffer_cb) {
|
||||
PINOS_DEBUG_TRANSPORT ("port %p: notify buffer %p", port, buffer);
|
||||
priv->buffer = buffer;
|
||||
priv->received_buffer_cb (port, priv->received_buffer_data);
|
||||
priv->buffer = NULL;
|
||||
}
|
||||
PINOS_DEBUG_TRANSPORT ("port %p: send to peer buffer %p", port, buffer);
|
||||
for (i = 0; i < priv->n_peers; i++) {
|
||||
PinosPort *peer = priv->peers[i];
|
||||
if (peer == NULL)
|
||||
continue;
|
||||
|
||||
if (!pinos_port_receive_buffer (peer, buffer, &error)) {
|
||||
g_warning ("peer %p: failed to receive buffer: %s", peer, error->message);
|
||||
g_clear_error (&error);
|
||||
}
|
||||
}
|
||||
g_assert (pinos_buffer_unref (buffer) == FALSE);
|
||||
break;
|
||||
}
|
||||
|
||||
case G_IO_OUT:
|
||||
g_warning ("can do IO OUT\n");
|
||||
|
@ -635,13 +740,6 @@ on_socket_condition (GSocket *socket,
|
|||
break;
|
||||
}
|
||||
return TRUE;
|
||||
|
||||
read_failed:
|
||||
{
|
||||
g_warning ("failed to read buffer: %s", error->message);
|
||||
g_clear_error (&error);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -669,62 +767,11 @@ unhandle_socket (PinosPort *port)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* pinos_port_recieve_buffer:
|
||||
* @port: a #PinosPort
|
||||
* @buffer: a #PinosBuffer
|
||||
* @error: a #GError or %NULL
|
||||
*
|
||||
* Receive a buffer on @port.
|
||||
*
|
||||
* Returns: %TRUE if the buffer could be accepted. %FALSE if port
|
||||
* already has an unconsumed buffer.
|
||||
*/
|
||||
gboolean
|
||||
pinos_port_receive_buffer (PinosPort *port,
|
||||
PinosBuffer *buffer,
|
||||
GError **error)
|
||||
{
|
||||
PinosPortPrivate *priv;
|
||||
gboolean res;
|
||||
|
||||
g_return_val_if_fail (PINOS_IS_PORT (port), FALSE);
|
||||
priv = port->priv;
|
||||
|
||||
if (priv->buffer)
|
||||
goto buffer_queued;
|
||||
|
||||
if (priv->sockets[0]) {
|
||||
g_debug ("port %p: receive buffer %p write to socket", port, buffer);
|
||||
res = write_buffer (priv->sockets[0], buffer, error);
|
||||
}
|
||||
else {
|
||||
g_debug ("port %p: receive buffer %p signal", port, buffer);
|
||||
res = TRUE;
|
||||
priv->buffer = buffer;
|
||||
if (priv->received_buffer_cb)
|
||||
priv->received_buffer_cb (port, priv->received_buffer_data);
|
||||
}
|
||||
|
||||
return res;
|
||||
|
||||
/* ERRORS */
|
||||
buffer_queued:
|
||||
{
|
||||
g_set_error (error,
|
||||
G_IO_ERROR,
|
||||
G_IO_ERROR_NOT_FOUND,
|
||||
"buffer was already queued on port");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* pinos_port_peek_buffer:
|
||||
* @port: a #PinosPort
|
||||
*
|
||||
* Check if there is a buffer on @port and peek it without dequeueing it
|
||||
* from the port.
|
||||
* Peek the buffer on @port.
|
||||
*
|
||||
* Returns: a #PinosBuffer or %NULL when no buffer has arrived on the pad.
|
||||
*/
|
||||
|
@ -739,27 +786,18 @@ pinos_port_peek_buffer (PinosPort *port)
|
|||
return priv->buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* pinos_port_get_buffer:
|
||||
* @port: a #PinosPort
|
||||
*
|
||||
* Get the buffer on @port. The buffer will no longer be queued on the port.
|
||||
*
|
||||
* Returns: a #PinosBuffer or %NULL when no buffer has arrived on the pad.
|
||||
*/
|
||||
PinosBuffer *
|
||||
pinos_port_get_buffer (PinosPort *port)
|
||||
void
|
||||
pinos_port_buffer_builder_init (PinosPort *port,
|
||||
PinosBufferBuilder *builder)
|
||||
{
|
||||
PinosPortPrivate *priv;
|
||||
PinosBuffer *res;
|
||||
|
||||
g_return_val_if_fail (PINOS_IS_PORT (port), NULL);
|
||||
g_return_if_fail (PINOS_IS_PORT (port));
|
||||
priv = port->priv;
|
||||
|
||||
res = priv->buffer;
|
||||
priv->buffer = NULL;
|
||||
|
||||
return res;
|
||||
pinos_buffer_builder_init_into (builder,
|
||||
priv->send_data, MAX_BUFFER_SIZE,
|
||||
priv->send_fds, MAX_FDS);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -785,15 +823,18 @@ pinos_port_send_buffer (PinosPort *port,
|
|||
g_return_val_if_fail (PINOS_IS_PORT (port), FALSE);
|
||||
priv = port->priv;
|
||||
|
||||
if (priv->direction == PINOS_DIRECTION_OUTPUT && priv->sockets[0]) {
|
||||
g_debug ("port %p: send buffer %p write to socket", port, buffer);
|
||||
if (pinos_buffer_get_flags (buffer) & PINOS_BUFFER_FLAG_CONTROL)
|
||||
parse_control_buffer (port, buffer);
|
||||
|
||||
PINOS_DEBUG_TRANSPORT ("port %p: send buffer %p", port, buffer);
|
||||
if (priv->sockets[0]) {
|
||||
PINOS_DEBUG_TRANSPORT ("port %p: write buffer %p", port, buffer);
|
||||
res = write_buffer (priv->sockets[0], buffer, error);
|
||||
}
|
||||
for (i = 0; i < priv->n_peers; i++) {
|
||||
peer = priv->peers[i];
|
||||
if (peer == NULL)
|
||||
continue;
|
||||
g_debug ("port %p: send buffer %p to peer %p", port, buffer, peer);
|
||||
res = pinos_port_receive_buffer (peer, buffer, error);
|
||||
}
|
||||
return res;
|
||||
|
@ -853,80 +894,6 @@ create_failed:
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
set_format (PinosPort *port, GBytes *format)
|
||||
{
|
||||
PinosPortPrivate *priv = port->priv;
|
||||
|
||||
if (priv->format)
|
||||
g_bytes_unref (priv->format);
|
||||
priv->format = format;
|
||||
|
||||
g_debug ("port %p: set format", port);
|
||||
if (priv->direction == PINOS_DIRECTION_OUTPUT) {
|
||||
gint i;
|
||||
|
||||
for (i = 0; i < priv->n_peers; i++) {
|
||||
PinosPort *peer = priv->peers[i];
|
||||
if (peer == NULL)
|
||||
continue;
|
||||
set_format (peer, g_bytes_ref (format));
|
||||
g_object_notify (G_OBJECT (peer), "format");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* pinos_port_update_format:
|
||||
* @port: a #PinosPort
|
||||
* @format: a new format
|
||||
* @error: a #GError or %NULL
|
||||
*
|
||||
* Update the format on @port.
|
||||
*
|
||||
* Returns: %TRUE on succes, @error is set when %FALSE is returned.
|
||||
*/
|
||||
gboolean
|
||||
pinos_port_update_format (PinosPort *port, GBytes *format, GError **error)
|
||||
{
|
||||
PinosPortPrivate *priv;
|
||||
gboolean res = TRUE;
|
||||
|
||||
g_return_val_if_fail (PINOS_IS_PORT (port), FALSE);
|
||||
priv = port->priv;
|
||||
|
||||
if (priv->format)
|
||||
g_bytes_unref (priv->format);
|
||||
priv->format = format;
|
||||
|
||||
g_debug ("port %p: update format", port);
|
||||
if (priv->direction == PINOS_DIRECTION_INPUT && priv->sockets[0]) {
|
||||
PinosBufferBuilder builder;
|
||||
PinosBuffer pbuf;
|
||||
PinosPacketFormatChange fc;
|
||||
|
||||
pinos_buffer_builder_init (&builder);
|
||||
fc.id = 0;
|
||||
fc.format = g_bytes_get_data (format, NULL);
|
||||
pinos_buffer_builder_add_format_change (&builder, &fc);
|
||||
pinos_buffer_builder_end (&builder, &pbuf);
|
||||
|
||||
g_debug ("port %p: send format message %s", port, fc.format);
|
||||
res = write_buffer (priv->sockets[0], &pbuf, error);
|
||||
pinos_buffer_clear (&pbuf);
|
||||
} else if (priv->direction == PINOS_DIRECTION_OUTPUT) {
|
||||
gint i;
|
||||
|
||||
for (i = 0; i < priv->n_peers; i++) {
|
||||
PinosPort *peer = priv->peers[i];
|
||||
if (peer == NULL)
|
||||
continue;
|
||||
res = pinos_port_update_format (peer, g_bytes_ref (format), error);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static void
|
||||
pinos_port_get_property (GObject *_object,
|
||||
guint prop_id,
|
||||
|
@ -983,7 +950,6 @@ pinos_port_set_property (GObject *_object,
|
|||
switch (prop_id) {
|
||||
case PROP_NODE:
|
||||
priv->node = g_value_get_object (value);
|
||||
g_debug ("port %p: set node %p %d", port, priv->node, G_OBJECT (priv->node)->ref_count);
|
||||
break;
|
||||
|
||||
case PROP_SOCKET:
|
||||
|
@ -1005,7 +971,9 @@ pinos_port_set_property (GObject *_object,
|
|||
break;
|
||||
|
||||
case PROP_FORMAT:
|
||||
set_format (port, g_value_dup_boxed (value));
|
||||
if (priv->format)
|
||||
g_bytes_unref (priv->format);
|
||||
priv->format = g_value_dup_boxed (value);
|
||||
break;
|
||||
|
||||
case PROP_PROPERTIES:
|
||||
|
@ -1026,8 +994,8 @@ pinos_port_constructed (GObject * object)
|
|||
PinosPort *port = PINOS_PORT (object);
|
||||
PinosPortPrivate *priv = port->priv;
|
||||
|
||||
g_debug ("port %p: %s port constructed, node %p %d",
|
||||
port, pinos_direction_as_string (priv->direction), priv->node, G_OBJECT (priv->node)->ref_count);
|
||||
g_debug ("port %p: %s port constructed, node %p",
|
||||
port, pinos_direction_as_string (priv->direction), priv->node);
|
||||
|
||||
if (priv->sockets[0])
|
||||
handle_socket (port, priv->sockets[0]);
|
||||
|
@ -1141,7 +1109,7 @@ pinos_port_class_init (PinosPortClass * klass)
|
|||
"The format of the port",
|
||||
G_TYPE_BYTES,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT |
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
|
||||
g_object_class_install_property (gobject_class,
|
||||
|
@ -1151,7 +1119,7 @@ pinos_port_class_init (PinosPortClass * klass)
|
|||
"The properties of the port",
|
||||
PINOS_TYPE_PROPERTIES,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT |
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
|
||||
|
||||
|
|
|
@ -84,9 +84,6 @@ PinosProperties * pinos_port_get_properties (PinosPort *port);
|
|||
GBytes * pinos_port_filter_formats (PinosPort *port,
|
||||
GBytes *filter,
|
||||
GError **error);
|
||||
gboolean pinos_port_update_format (PinosPort *port,
|
||||
GBytes *format,
|
||||
GError **error);
|
||||
|
||||
GSocket * pinos_port_get_socket_pair (PinosPort *port,
|
||||
GError **error);
|
||||
|
@ -97,11 +94,10 @@ gboolean pinos_port_unlink (PinosPort *source,
|
|||
PinosPort *destination);
|
||||
gint pinos_port_get_n_links (PinosPort *port);
|
||||
|
||||
gboolean pinos_port_receive_buffer (PinosPort *port,
|
||||
PinosBuffer *buffer,
|
||||
GError **error);
|
||||
PinosBuffer * pinos_port_peek_buffer (PinosPort *port);
|
||||
PinosBuffer * pinos_port_get_buffer (PinosPort *port);
|
||||
|
||||
void pinos_port_buffer_builder_init (PinosPort *port,
|
||||
PinosBufferBuilder *builder);
|
||||
|
||||
gboolean pinos_port_send_buffer (PinosPort *port,
|
||||
PinosBuffer *buffer,
|
||||
|
|
|
@ -73,6 +73,7 @@ typedef struct {
|
|||
gint max_fds;
|
||||
gpointer free_fds;
|
||||
gsize magic;
|
||||
gint refcount;
|
||||
} PinosStackBuffer;
|
||||
|
||||
#define PSB(b) ((PinosStackBuffer *) (b))
|
||||
|
|
|
@ -148,7 +148,6 @@ pinos_stream_set_property (GObject *_object,
|
|||
if (priv->format)
|
||||
g_bytes_unref (priv->format);
|
||||
priv->format = g_value_dup_boxed (value);
|
||||
g_object_set (priv->port, "format", priv->format, NULL);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -479,7 +478,6 @@ on_received_buffer (PinosPort *port,
|
|||
{
|
||||
PinosStream *stream = user_data;
|
||||
|
||||
g_debug ("buffer received");
|
||||
g_signal_emit (stream, signals[SIGNAL_NEW_BUFFER], 0, NULL);
|
||||
}
|
||||
|
||||
|
@ -824,30 +822,45 @@ pinos_stream_disconnect (PinosStream *stream)
|
|||
}
|
||||
|
||||
/**
|
||||
* pinos_stream_get_buffer:
|
||||
* pinos_stream_peek_buffer:
|
||||
* @stream: a #PinosStream
|
||||
* @buffer: a #PinosBuffer
|
||||
*
|
||||
* Get the next buffer from @stream. This function should be called from
|
||||
* Get the current buffer from @stream. This function should be called from
|
||||
* the new-buffer signal callback.
|
||||
*
|
||||
* Returns: %TRUE when @buffer contains valid information
|
||||
* Returns: a #PinosBuffer or %NULL when there is no buffer.
|
||||
*/
|
||||
gboolean
|
||||
pinos_stream_get_buffer (PinosStream *stream,
|
||||
PinosBuffer **buffer)
|
||||
PinosBuffer *
|
||||
pinos_stream_peek_buffer (PinosStream *stream)
|
||||
{
|
||||
PinosStreamPrivate *priv;
|
||||
|
||||
g_return_val_if_fail (PINOS_IS_STREAM (stream), FALSE);
|
||||
g_return_val_if_fail (buffer != NULL, FALSE);
|
||||
|
||||
priv = stream->priv;
|
||||
//g_return_val_if_fail (priv->state == PINOS_STREAM_STATE_STREAMING, FALSE);
|
||||
|
||||
*buffer = pinos_port_get_buffer (priv->port);
|
||||
return pinos_port_peek_buffer (priv->port);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
/**
|
||||
* pinos_stream_buffer_builder_init:
|
||||
* @stream: a #PinosStream
|
||||
* @builder: a #PinosBufferBuilder
|
||||
*
|
||||
* Get a #PinosBufferBuilder for @stream.
|
||||
*
|
||||
* Returns: a #PinosBuffer or %NULL when there is no buffer.
|
||||
*/
|
||||
void
|
||||
pinos_stream_buffer_builder_init (PinosStream *stream, PinosBufferBuilder *builder)
|
||||
{
|
||||
PinosStreamPrivate *priv;
|
||||
|
||||
g_return_if_fail (PINOS_IS_STREAM (stream));
|
||||
priv = stream->priv;
|
||||
|
||||
pinos_port_buffer_builder_init (priv->port, builder);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -106,8 +106,9 @@ gboolean pinos_stream_start (PinosStream *stream,
|
|||
PinosStreamMode mode);
|
||||
gboolean pinos_stream_stop (PinosStream *stream);
|
||||
|
||||
gboolean pinos_stream_get_buffer (PinosStream *stream,
|
||||
PinosBuffer **buffer);
|
||||
PinosBuffer * pinos_stream_peek_buffer (PinosStream *stream);
|
||||
void pinos_stream_buffer_builder_init (PinosStream *stream,
|
||||
PinosBufferBuilder *builder);
|
||||
gboolean pinos_stream_send_buffer (PinosStream *stream,
|
||||
PinosBuffer *buffer);
|
||||
|
||||
|
|
|
@ -145,9 +145,9 @@
|
|||
<property name='Properties' type='a{sv}' access='read' />
|
||||
<!-- PossibleFormats:
|
||||
|
||||
The all possible formats of this port.
|
||||
The possible formats of this port.
|
||||
-->
|
||||
<property name='PossibleFormats' type='s' access='read' />
|
||||
<property name='PossibleFormats' type='s' access='readwrite' />
|
||||
<!-- Format: the current streaming format -->
|
||||
<property name='Format' type='s' access='read' />
|
||||
|
||||
|
|
|
@ -251,7 +251,8 @@ gst_pinos_depay_chain (GstPad *pad, GstObject * parent, GstBuffer * buffer)
|
|||
break;
|
||||
}
|
||||
}
|
||||
pinos_buffer_clear (&pbuf);
|
||||
pinos_buffer_iter_init (&it, &pbuf);
|
||||
pinos_buffer_unref (&pbuf);
|
||||
gst_buffer_unmap (buffer, &info);
|
||||
gst_buffer_unref (buffer);
|
||||
|
||||
|
|
|
@ -254,8 +254,9 @@ client_buffer_received (GstPinosPay *pay, GstBuffer *buffer,
|
|||
break;
|
||||
}
|
||||
}
|
||||
pinos_buffer_iter_end (&it);
|
||||
pinos_buffer_unref (&pbuf);
|
||||
gst_buffer_unmap (buffer, &info);
|
||||
pinos_buffer_clear (&pbuf);
|
||||
|
||||
if (pay->pinos_input) {
|
||||
GstBuffer *outbuf;
|
||||
|
@ -440,8 +441,9 @@ gst_pinos_pay_chain_pinos (GstPinosPay *pay, GstBuffer * buffer)
|
|||
break;
|
||||
}
|
||||
}
|
||||
pinos_buffer_iter_end (&it);
|
||||
pinos_buffer_unref (&pbuf);
|
||||
gst_buffer_unmap (buffer, &info);
|
||||
pinos_buffer_clear (&pbuf);
|
||||
|
||||
if (fdids != NULL) {
|
||||
gst_mini_object_set_qdata (GST_MINI_OBJECT_CAST (buffer),
|
||||
|
@ -490,6 +492,7 @@ gst_pinos_pay_chain_other (GstPinosPay *pay, GstBuffer * buffer)
|
|||
|
||||
data = pinos_buffer_steal_data (&pbuf, &size);
|
||||
fds = pinos_buffer_steal_fds (&pbuf, &n_fds);
|
||||
pinos_buffer_unref (&pbuf);
|
||||
|
||||
outbuf = gst_buffer_new_wrapped (data, size);
|
||||
GST_BUFFER_PTS (outbuf) = GST_BUFFER_PTS (buffer);
|
||||
|
|
|
@ -84,7 +84,7 @@ on_received_buffer (PinosPort *port, gpointer user_data)
|
|||
PinosBufferBuilder b;
|
||||
gboolean have_out = FALSE;
|
||||
|
||||
pbuf = pinos_port_get_buffer (port);
|
||||
pbuf = pinos_port_peek_buffer (port);
|
||||
|
||||
if (this->pinos_input) {
|
||||
pinos_buffer_builder_init (&b);
|
||||
|
@ -93,7 +93,7 @@ on_received_buffer (PinosPort *port, gpointer user_data)
|
|||
pinos_buffer_iter_init (&it, pbuf);
|
||||
while (pinos_buffer_iter_next (&it)) {
|
||||
switch (pinos_buffer_iter_get_type (&it)) {
|
||||
case PINOS_PACKET_TYPE_REFRESH_REQUEST:
|
||||
case PINOS_PACKET_TYPE_REFRESH_REQUEST:
|
||||
{
|
||||
PinosPacketRefreshRequest p;
|
||||
|
||||
|
@ -115,7 +115,7 @@ on_received_buffer (PinosPort *port, gpointer user_data)
|
|||
break;
|
||||
}
|
||||
}
|
||||
pinos_buffer_clear (pbuf);
|
||||
pinos_buffer_iter_end (&it);
|
||||
|
||||
if (this->pinos_input) {
|
||||
GstBuffer *outbuf;
|
||||
|
@ -225,16 +225,23 @@ gst_pinos_port_sink_setcaps (GstBaseSink * bsink, GstCaps * caps)
|
|||
str = gst_caps_get_structure (caps, 0);
|
||||
this->pinos_input = gst_structure_has_name (str, "application/x-pinos");
|
||||
if (!this->pinos_input) {
|
||||
GBytes *format;
|
||||
GError *error = NULL;
|
||||
PinosBufferBuilder builder;
|
||||
PinosBuffer pbuf;
|
||||
PinosPacketFormatChange fc;
|
||||
|
||||
cstr = gst_caps_to_string (caps);
|
||||
format = g_bytes_new_take (cstr, strlen (cstr) + 1);
|
||||
pinos_port_buffer_builder_init (this->port, &builder);
|
||||
fc.id = 0;
|
||||
fc.format = cstr = gst_caps_to_string (caps);
|
||||
pinos_buffer_builder_add_format_change (&builder, &fc);
|
||||
pinos_buffer_builder_end (&builder, &pbuf);
|
||||
g_free (cstr);
|
||||
|
||||
if (!pinos_port_update_format (this->port, format, &error)) {
|
||||
GST_WARNING ("update failed: %s", error->message);
|
||||
if (!pinos_port_send_buffer (this->port, &pbuf, &error)) {
|
||||
GST_WARNING ("format update failed: %s", error->message);
|
||||
g_clear_error (&error);
|
||||
}
|
||||
pinos_buffer_unref (&pbuf);
|
||||
}
|
||||
|
||||
return GST_BASE_SINK_CLASS (parent_class)->set_caps (bsink, caps);
|
||||
|
@ -249,12 +256,13 @@ gst_pinos_port_sink_render_pinos (GstPinosPortSink * this, GstBuffer * buffer)
|
|||
|
||||
gst_buffer_map (buffer, &info, GST_MAP_READ);
|
||||
pinos_buffer_init_data (&pbuf, info.data, info.size, NULL, 0);
|
||||
gst_buffer_unmap (buffer, &info);
|
||||
|
||||
if (!pinos_port_send_buffer (this->port, &pbuf, &error)) {
|
||||
GST_WARNING ("send failed: %s", error->message);
|
||||
g_clear_error (&error);
|
||||
}
|
||||
gst_buffer_unmap (buffer, &info);
|
||||
pinos_buffer_unref (&pbuf);
|
||||
|
||||
return GST_FLOW_OK;
|
||||
}
|
||||
|
@ -293,17 +301,19 @@ gst_pinos_port_sink_render_other (GstPinosPortSink * this, GstBuffer * buffer)
|
|||
PinosPacketHeader hdr;
|
||||
PinosPacketFDPayload p;
|
||||
gboolean tmpfile = TRUE;
|
||||
gint fd;
|
||||
|
||||
hdr.flags = 0;
|
||||
hdr.seq = GST_BUFFER_OFFSET (buffer);
|
||||
hdr.pts = GST_BUFFER_PTS (buffer) + GST_ELEMENT_CAST (this)->base_time;
|
||||
hdr.dts_offset = 0;
|
||||
|
||||
pinos_buffer_builder_init (&builder);
|
||||
pinos_port_buffer_builder_init (this->port, &builder);
|
||||
pinos_buffer_builder_add_header (&builder, &hdr);
|
||||
|
||||
fdmem = gst_pinos_port_sink_get_fd_memory (this, buffer, &tmpfile);
|
||||
p.fd_index = pinos_buffer_builder_add_fd (&builder, gst_fd_memory_get_fd (fdmem));
|
||||
fd = gst_fd_memory_get_fd (fdmem);
|
||||
p.fd_index = pinos_buffer_builder_add_fd (&builder, fd);
|
||||
p.id = pinos_fd_manager_get_id (this->fdmanager);
|
||||
p.offset = fdmem->offset;
|
||||
p.size = fdmem->size;
|
||||
|
@ -318,6 +328,8 @@ gst_pinos_port_sink_render_other (GstPinosPortSink * this, GstBuffer * buffer)
|
|||
GST_WARNING ("send failed: %s", error->message);
|
||||
g_clear_error (&error);
|
||||
}
|
||||
pinos_buffer_steal_fds (&pbuf, NULL);
|
||||
pinos_buffer_unref (&pbuf);
|
||||
|
||||
gst_memory_unref(fdmem);
|
||||
|
||||
|
|
|
@ -99,12 +99,12 @@ fdpayload_data_destroy (gpointer user_data)
|
|||
|
||||
GST_DEBUG_OBJECT (this, "destroy %d", r.id);
|
||||
|
||||
pinos_buffer_builder_init (&b);
|
||||
pinos_port_buffer_builder_init (this->port, &b);
|
||||
pinos_buffer_builder_add_release_fd_payload (&b, &r);
|
||||
pinos_buffer_builder_end (&b, &pbuf);
|
||||
|
||||
pinos_port_send_buffer (this->port, &pbuf, NULL);
|
||||
pinos_buffer_clear (&pbuf);
|
||||
pinos_buffer_unref (&pbuf);
|
||||
|
||||
gst_object_unref (this);
|
||||
g_slice_free (FDPayloadData, data);
|
||||
|
@ -120,7 +120,7 @@ on_received_buffer (PinosPort *port,
|
|||
GstBuffer *buf = NULL;
|
||||
|
||||
GST_LOG_OBJECT (this, "got new buffer");
|
||||
pbuf = pinos_port_get_buffer (port);
|
||||
pbuf = pinos_port_peek_buffer (port);
|
||||
|
||||
pinos_buffer_iter_init (&it, pbuf);
|
||||
while (pinos_buffer_iter_next (&it)) {
|
||||
|
@ -130,7 +130,7 @@ on_received_buffer (PinosPort *port,
|
|||
PinosPacketHeader hdr;
|
||||
|
||||
if (!pinos_buffer_iter_parse_header (&it, &hdr))
|
||||
goto parse_failed;
|
||||
break;
|
||||
|
||||
if (buf == NULL)
|
||||
buf = gst_buffer_new ();
|
||||
|
@ -152,17 +152,17 @@ on_received_buffer (PinosPort *port,
|
|||
int fd;
|
||||
|
||||
if (!pinos_buffer_iter_parse_fd_payload (&it, &data.p))
|
||||
goto parse_failed;
|
||||
break;
|
||||
|
||||
GST_DEBUG ("got fd payload id %d", data.p.id);
|
||||
fd = pinos_buffer_get_fd (pbuf, data.p.fd_index);
|
||||
if (fd == -1)
|
||||
goto no_fds;
|
||||
break;
|
||||
|
||||
if (buf == NULL)
|
||||
buf = gst_buffer_new ();
|
||||
|
||||
fdmem = gst_fd_allocator_alloc (this->fd_allocator, fd,
|
||||
fdmem = gst_fd_allocator_alloc (this->fd_allocator, dup (fd),
|
||||
data.p.offset + data.p.size, GST_FD_MEMORY_FLAG_NONE);
|
||||
gst_memory_resize (fdmem, data.p.offset, data.p.size);
|
||||
gst_buffer_append_memory (buf, fdmem);
|
||||
|
@ -180,7 +180,7 @@ on_received_buffer (PinosPort *port,
|
|||
GstCaps *caps;
|
||||
|
||||
if (!pinos_buffer_iter_parse_format_change (&it, &change))
|
||||
goto parse_failed;
|
||||
break;
|
||||
GST_DEBUG ("got format change %d %s", change.id, change.format);
|
||||
|
||||
caps = gst_caps_from_string (change.format);
|
||||
|
@ -192,27 +192,14 @@ on_received_buffer (PinosPort *port,
|
|||
break;
|
||||
}
|
||||
}
|
||||
pinos_buffer_iter_end (&it);
|
||||
|
||||
if (buf) {
|
||||
g_queue_push_tail (&this->queue, buf);
|
||||
g_cond_signal (&this->cond);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
/* ERRORS */
|
||||
parse_failed:
|
||||
{
|
||||
gst_buffer_unref (buf);
|
||||
GST_ELEMENT_ERROR (this, RESOURCE, FAILED, ("buffer parse failure"), (NULL));
|
||||
return;
|
||||
}
|
||||
no_fds:
|
||||
{
|
||||
gst_buffer_unref (buf);
|
||||
GST_ELEMENT_ERROR (this, RESOURCE, FAILED, ("fd not found in buffer"), (NULL));
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -443,7 +430,7 @@ gst_pinos_port_src_getcaps (GstBaseSrc * bsrc, GstCaps * filter)
|
|||
|
||||
g_object_get (this->port, "format", &format, NULL);
|
||||
if (format) {
|
||||
GST_DEBUG ("have format %s", g_bytes_get_data (format, NULL));
|
||||
GST_DEBUG ("have format %s", (gchar *)g_bytes_get_data (format, NULL));
|
||||
caps = gst_caps_from_string (g_bytes_get_data (format, NULL));
|
||||
g_bytes_unref (format);
|
||||
}
|
||||
|
@ -475,13 +462,13 @@ gst_pinos_port_src_event (GstBaseSrc * src, GstEvent * event)
|
|||
refresh.request_type = all_headers ? 1 : 0;
|
||||
refresh.pts = running_time;
|
||||
|
||||
pinos_buffer_builder_init (&b);
|
||||
pinos_port_buffer_builder_init (this->port, &b);
|
||||
pinos_buffer_builder_add_refresh_request (&b, &refresh);
|
||||
pinos_buffer_builder_end (&b, &pbuf);
|
||||
|
||||
GST_DEBUG_OBJECT (this, "send refresh request");
|
||||
pinos_port_send_buffer (this->port, &pbuf, NULL);
|
||||
pinos_buffer_clear (&pbuf);
|
||||
pinos_buffer_unref (&pbuf);
|
||||
res = TRUE;
|
||||
} else {
|
||||
res = GST_BASE_SRC_CLASS (parent_class)->event (src, event);
|
||||
|
|
|
@ -412,6 +412,7 @@ gst_pinos_sink_render (GstBaseSink * bsink, GstBuffer * buffer)
|
|||
gsize size;
|
||||
GError *err = NULL;
|
||||
gboolean tmpfile, res;
|
||||
int fd;
|
||||
|
||||
pinossink = GST_PINOS_SINK (bsink);
|
||||
|
||||
|
@ -455,7 +456,8 @@ gst_pinos_sink_render (GstBaseSink * bsink, GstBuffer * buffer)
|
|||
pinos_buffer_builder_init (&builder);
|
||||
pinos_buffer_builder_add_header (&builder, &hdr);
|
||||
|
||||
p.fd_index = pinos_buffer_builder_add_fd (&builder, gst_fd_memory_get_fd (mem), &err);
|
||||
fd = gst_fd_memory_get_fd (mem);
|
||||
p.fd_index = pinos_buffer_builder_add_fd (&builder, fd, &err);
|
||||
if (p.fd_index == -1)
|
||||
goto add_fd_failed;
|
||||
p.id = pinossink->id_counter++;
|
||||
|
@ -464,15 +466,17 @@ gst_pinos_sink_render (GstBaseSink * bsink, GstBuffer * buffer)
|
|||
pinos_buffer_builder_add_fd_payload (&builder, &p);
|
||||
pinos_buffer_builder_end (&builder, &pbuf);
|
||||
|
||||
gst_memory_unref (mem);
|
||||
|
||||
pinos_main_loop_lock (pinossink->loop);
|
||||
if (pinos_stream_get_state (pinossink->stream) != PINOS_STREAM_STATE_STREAMING)
|
||||
goto streaming_error;
|
||||
res = pinos_stream_send_buffer (pinossink->stream, &pbuf);
|
||||
pinos_buffer_steal_fds (&pbuf, NULL);
|
||||
pinos_buffer_clear (&pbuf);
|
||||
pinos_main_loop_unlock (pinossink->loop);
|
||||
|
||||
gst_memory_unref (mem);
|
||||
|
||||
if (res && !tmpfile) {
|
||||
/* keep the buffer around until we get the release fd message */
|
||||
g_hash_table_insert (pinossink->fdids, GINT_TO_POINTER (p.id), gst_buffer_ref (buffer));
|
||||
|
|
|
@ -337,7 +337,7 @@ on_new_buffer (GObject *gobject,
|
|||
return;
|
||||
}
|
||||
|
||||
if (!pinos_stream_get_buffer (pinossink->stream, &pbuf)) {
|
||||
if (!(pbuf = pinos_stream_peek_buffer (pinossink->stream))) {
|
||||
g_warning ("failed to capture buffer");
|
||||
return;
|
||||
}
|
||||
|
@ -373,6 +373,7 @@ on_new_buffer (GObject *gobject,
|
|||
break;
|
||||
}
|
||||
}
|
||||
pinos_buffer_iter_end (&it);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -471,7 +472,7 @@ gst_pinos_sink_setcaps (GstBaseSink * bsink, GstCaps * caps)
|
|||
PinosPacketFormatChange change;
|
||||
PinosBuffer pbuf;
|
||||
|
||||
pinos_buffer_builder_init (&builder);
|
||||
pinos_stream_buffer_builder_init (pinossink->stream, &builder);
|
||||
|
||||
change.id = 1;
|
||||
change.format = g_bytes_get_data (format, NULL);
|
||||
|
@ -480,7 +481,7 @@ gst_pinos_sink_setcaps (GstBaseSink * bsink, GstCaps * caps)
|
|||
|
||||
g_debug ("sending format");
|
||||
res = pinos_stream_send_buffer (pinossink->stream, &pbuf);
|
||||
pinos_buffer_clear (&pbuf);
|
||||
pinos_buffer_unref (&pbuf);
|
||||
}
|
||||
|
||||
pinos_main_loop_unlock (pinossink->loop);
|
||||
|
@ -552,10 +553,14 @@ gst_pinos_sink_render (GstBaseSink * bsink, GstBuffer * buffer)
|
|||
tmpfile = TRUE;
|
||||
}
|
||||
|
||||
pinos_buffer_builder_init (&builder);
|
||||
pinos_main_loop_lock (pinossink->loop);
|
||||
if (pinos_stream_get_state (pinossink->stream) != PINOS_STREAM_STATE_STREAMING)
|
||||
goto streaming_error;
|
||||
|
||||
pinos_stream_buffer_builder_init (pinossink->stream, &builder);
|
||||
pinos_buffer_builder_add_header (&builder, &hdr);
|
||||
|
||||
fd = dup (gst_fd_memory_get_fd (mem));
|
||||
fd = gst_fd_memory_get_fd (mem);
|
||||
p.fd_index = pinos_buffer_builder_add_fd (&builder, fd);
|
||||
p.id = pinossink->id_counter++;
|
||||
p.offset = 0;
|
||||
|
@ -565,11 +570,9 @@ gst_pinos_sink_render (GstBaseSink * bsink, GstBuffer * buffer)
|
|||
|
||||
GST_LOG ("sending fd index %d %d %d", p.id, p.fd_index, fd);
|
||||
|
||||
pinos_main_loop_lock (pinossink->loop);
|
||||
if (pinos_stream_get_state (pinossink->stream) != PINOS_STREAM_STATE_STREAMING)
|
||||
goto streaming_error;
|
||||
res = pinos_stream_send_buffer (pinossink->stream, &pbuf);
|
||||
pinos_buffer_clear (&pbuf);
|
||||
pinos_buffer_steal_fds (&pbuf, NULL);
|
||||
pinos_buffer_unref (&pbuf);
|
||||
pinos_main_loop_unlock (pinossink->loop);
|
||||
|
||||
gst_memory_unref (mem);
|
||||
|
|
|
@ -262,8 +262,9 @@ gst_pinos_socket_sink_render_pinos (GstPinosSocketSink * this, GstBuffer * buffe
|
|||
break;
|
||||
}
|
||||
}
|
||||
pinos_buffer_iter_end (&it);
|
||||
pinos_buffer_unref (&pbuf);
|
||||
gst_buffer_unmap (buffer, &info);
|
||||
pinos_buffer_clear (&pbuf);
|
||||
|
||||
if (fdids != NULL) {
|
||||
gst_mini_object_set_qdata (GST_MINI_OBJECT_CAST (buffer),
|
||||
|
@ -338,6 +339,7 @@ gst_pinos_socket_sink_render_other (GstPinosSocketSink * this, GstBuffer * buffe
|
|||
|
||||
data = pinos_buffer_steal_data (&pbuf, &size);
|
||||
fds = pinos_buffer_steal_fds (&pbuf, &n_fds);
|
||||
pinos_buffer_unref (&pbuf);
|
||||
|
||||
outbuf = gst_buffer_new_wrapped (data, size);
|
||||
GST_BUFFER_PTS (outbuf) = GST_BUFFER_PTS (buffer);
|
||||
|
@ -582,7 +584,8 @@ myreader_receive_buffer (GstPinosSocketSink *this, MyReader *myreader)
|
|||
break;
|
||||
}
|
||||
}
|
||||
pinos_buffer_clear (&pbuf);
|
||||
pinos_buffer_iter_end (&it);
|
||||
pinos_buffer_unref (&pbuf);
|
||||
g_free (mem);
|
||||
|
||||
if (this->pinos_input) {
|
||||
|
|
|
@ -332,19 +332,18 @@ fdpayload_data_destroy (gpointer user_data)
|
|||
|
||||
GST_DEBUG_OBJECT (pinossrc, "destroy %d", r.id);
|
||||
|
||||
pinos_buffer_builder_init (&b);
|
||||
pinos_buffer_builder_add_release_fd_payload (&b, &r);
|
||||
pinos_buffer_builder_end (&b, &pbuf);
|
||||
|
||||
GST_OBJECT_LOCK (pinossrc);
|
||||
if (pinossrc->stream_state == PINOS_STREAM_STATE_STREAMING) {
|
||||
pinos_stream_buffer_builder_init (pinossrc->stream, &b);
|
||||
pinos_buffer_builder_add_release_fd_payload (&b, &r);
|
||||
pinos_buffer_builder_end (&b, &pbuf);
|
||||
|
||||
GST_DEBUG_OBJECT (pinossrc, "send release-fd for %d", r.id);
|
||||
pinos_stream_send_buffer (pinossrc->stream, &pbuf);
|
||||
pinos_buffer_unref (&pbuf);
|
||||
}
|
||||
GST_OBJECT_UNLOCK (pinossrc);
|
||||
|
||||
pinos_buffer_clear (&pbuf);
|
||||
|
||||
gst_object_unref (pinossrc);
|
||||
g_slice_free (FDPayloadData, data);
|
||||
}
|
||||
|
@ -359,7 +358,7 @@ on_new_buffer (GObject *gobject,
|
|||
GstBuffer *buf = NULL;
|
||||
|
||||
GST_LOG_OBJECT (pinossrc, "got new buffer");
|
||||
if (!pinos_stream_get_buffer (pinossrc->stream, &pbuf)) {
|
||||
if (!(pbuf = pinos_stream_peek_buffer (pinossrc->stream))) {
|
||||
g_warning ("failed to capture buffer");
|
||||
return;
|
||||
}
|
||||
|
@ -404,7 +403,7 @@ on_new_buffer (GObject *gobject,
|
|||
if (buf == NULL)
|
||||
buf = gst_buffer_new ();
|
||||
|
||||
fdmem = gst_fd_allocator_alloc (pinossrc->fd_allocator, fd,
|
||||
fdmem = gst_fd_allocator_alloc (pinossrc->fd_allocator, dup (fd),
|
||||
data.p.offset + data.p.size, GST_FD_MEMORY_FLAG_NONE);
|
||||
gst_memory_resize (fdmem, data.p.offset, data.p.size);
|
||||
gst_buffer_append_memory (buf, fdmem);
|
||||
|
@ -434,6 +433,7 @@ on_new_buffer (GObject *gobject,
|
|||
break;
|
||||
}
|
||||
}
|
||||
pinos_buffer_iter_end (&it);
|
||||
|
||||
if (buf) {
|
||||
g_queue_push_tail (&pinossrc->queue, buf);
|
||||
|
@ -445,6 +445,8 @@ on_new_buffer (GObject *gobject,
|
|||
/* ERRORS */
|
||||
parse_failed:
|
||||
{
|
||||
pinos_buffer_iter_end (&it);
|
||||
pinos_buffer_unref (pbuf);
|
||||
gst_buffer_unref (buf);
|
||||
GST_ELEMENT_ERROR (pinossrc, RESOURCE, FAILED, ("buffer parse failure"), (NULL));
|
||||
pinos_main_loop_signal (pinossrc->loop, FALSE);
|
||||
|
@ -452,6 +454,8 @@ parse_failed:
|
|||
}
|
||||
no_fds:
|
||||
{
|
||||
pinos_buffer_iter_end (&it);
|
||||
pinos_buffer_unref (pbuf);
|
||||
gst_buffer_unref (buf);
|
||||
GST_ELEMENT_ERROR (pinossrc, RESOURCE, FAILED, ("fd not found in buffer"), (NULL));
|
||||
pinos_main_loop_signal (pinossrc->loop, FALSE);
|
||||
|
@ -745,12 +749,13 @@ gst_pinos_src_event (GstBaseSrc * src, GstEvent * event)
|
|||
gst_video_event_parse_upstream_force_key_unit (event,
|
||||
&running_time, &all_headers, &count);
|
||||
|
||||
pinos_buffer_builder_init (&b);
|
||||
|
||||
refresh.last_id = 0;
|
||||
refresh.request_type = all_headers ? 1 : 0;
|
||||
refresh.pts = running_time;
|
||||
|
||||
pinos_buffer_builder_init (&b);
|
||||
pinos_buffer_builder_add_refresh_request (&b, &refresh);
|
||||
|
||||
pinos_buffer_builder_end (&b, &pbuf);
|
||||
|
||||
GST_OBJECT_LOCK (pinossrc);
|
||||
|
@ -760,7 +765,7 @@ gst_pinos_src_event (GstBaseSrc * src, GstEvent * event)
|
|||
}
|
||||
GST_OBJECT_UNLOCK (pinossrc);
|
||||
|
||||
pinos_buffer_clear (&pbuf);
|
||||
pinos_buffer_unref (&pbuf);
|
||||
res = TRUE;
|
||||
} else {
|
||||
res = GST_BASE_SRC_CLASS (parent_class)->event (src, event);
|
||||
|
|
|
@ -391,9 +391,9 @@ pinos_daemon_remove_node (PinosDaemon *daemon,
|
|||
*
|
||||
* Find the best port in @daemon that matches the given parameters.
|
||||
*
|
||||
* Returns: a #PinosServerPort or %NULL when no port could be found.
|
||||
* Returns: a #PinosPort or %NULL when no port could be found.
|
||||
*/
|
||||
PinosServerPort *
|
||||
PinosPort *
|
||||
pinos_daemon_find_port (PinosDaemon *daemon,
|
||||
PinosDirection direction,
|
||||
const gchar *name,
|
||||
|
@ -417,7 +417,7 @@ pinos_daemon_find_port (PinosDaemon *daemon,
|
|||
|
||||
/* we found the node */
|
||||
if (have_name && g_str_has_suffix (pinos_server_node_get_object_path (n), name)) {
|
||||
g_debug ("name \"%s\" matches node %s", name, pinos_server_node_get_object_path (n));
|
||||
g_debug ("name \"%s\" matches node %p", name, n);
|
||||
node_found = TRUE;
|
||||
}
|
||||
|
||||
|
@ -433,22 +433,15 @@ pinos_daemon_find_port (PinosDaemon *daemon,
|
|||
if (have_name && !node_found) {
|
||||
if (!g_str_has_suffix (pinos_server_port_get_object_path (p), name))
|
||||
continue;
|
||||
g_debug ("name \"%s\" matches port %s", name, pinos_server_port_get_object_path (p));
|
||||
g_debug ("name \"%s\" matches port %p", name, p);
|
||||
best = p;
|
||||
node_found = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
g_debug ("port %s with filter %s",
|
||||
pinos_server_port_get_object_path (p),
|
||||
format_filter ? (gchar*)g_bytes_get_data (format_filter, NULL) : "ANY");
|
||||
|
||||
format = pinos_port_filter_formats (PINOS_PORT (p), format_filter, NULL);
|
||||
if (format != NULL) {
|
||||
g_debug ("port %s with format %s matches filter %s",
|
||||
pinos_server_port_get_object_path (p),
|
||||
(gchar*)g_bytes_get_data (format, NULL),
|
||||
format_filter ? (gchar*)g_bytes_get_data (format_filter, NULL) : "ANY");
|
||||
g_debug ("port %p matches filter", p);
|
||||
g_bytes_unref (format);
|
||||
best = p;
|
||||
node_found = TRUE;
|
||||
|
@ -464,7 +457,7 @@ pinos_daemon_find_port (PinosDaemon *daemon,
|
|||
G_IO_ERROR_NOT_FOUND,
|
||||
"No matching Port found");
|
||||
}
|
||||
return best;
|
||||
return PINOS_PORT (best);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -75,7 +75,7 @@ void pinos_daemon_unexport (PinosDaemon *daemon, const gch
|
|||
void pinos_daemon_add_node (PinosDaemon *daemon, PinosServerNode *node);
|
||||
void pinos_daemon_remove_node (PinosDaemon *daemon, PinosServerNode *node);
|
||||
|
||||
PinosServerPort * pinos_daemon_find_port (PinosDaemon *daemon,
|
||||
PinosPort * pinos_daemon_find_port (PinosDaemon *daemon,
|
||||
PinosDirection direction,
|
||||
const gchar *name,
|
||||
PinosProperties *props,
|
||||
|
|
|
@ -164,7 +164,7 @@ on_property_notify (GObject *obj,
|
|||
PinosPort *port = PINOS_PORT (obj);
|
||||
PinosServerPortPrivate *priv = PINOS_SERVER_PORT (port)->priv;
|
||||
|
||||
g_debug ("update %s", pspec ? g_param_spec_get_name (pspec) : "NULL");
|
||||
g_debug ("port %p: update %s", port, pspec ? g_param_spec_get_name (pspec) : "NULL");
|
||||
|
||||
if (pspec == NULL || strcmp (g_param_spec_get_name (pspec), "node") == 0) {
|
||||
PinosServerNode *node = PINOS_SERVER_NODE (pinos_port_get_node (port));
|
||||
|
|
Loading…
Reference in a new issue