From ab0537305f770ded65d4482719a8470b1be16369 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Thu, 11 Aug 2016 11:20:12 +0200 Subject: [PATCH] handle set_format with existing format If one calls set-format with the current format, we return success Remove some unused utils now Work on cleanup of buffers --- pinos/Makefile.am | 1 - pinos/server/client-node.c | 1 - pinos/server/link.c | 12 ++++- pinos/server/node.c | 2 +- pinos/server/port.c | 1 - pinos/server/utils.c | 84 ---------------------------------- pinos/server/utils.h | 31 ------------- spa/plugins/v4l2/v4l2-source.c | 15 ++++-- spa/plugins/v4l2/v4l2-utils.c | 78 +++++++++++++++++++++++-------- 9 files changed, 82 insertions(+), 143 deletions(-) delete mode 100644 pinos/server/utils.c delete mode 100644 pinos/server/utils.h diff --git a/pinos/Makefile.am b/pinos/Makefile.am index dc5eb7ffd..42c17055c 100644 --- a/pinos/Makefile.am +++ b/pinos/Makefile.am @@ -212,7 +212,6 @@ libpinoscore_@PINOS_MAJORMINOR@_la_SOURCES = \ server/node.c server/node.h \ server/port.c server/port.h \ server/node-factory.c server/node-factory.h \ - server/utils.c server/utils.h \ modules/gst/gst-manager.c modules/gst/gst-manager.h \ modules/gst/gst-source.c modules/gst/gst-source.h \ modules/gst/gst-sink.c modules/gst/gst-sink.h \ diff --git a/pinos/server/client-node.c b/pinos/server/client-node.c index f6a23a654..2a465f830 100644 --- a/pinos/server/client-node.c +++ b/pinos/server/client-node.c @@ -37,7 +37,6 @@ #include "pinos/server/daemon.h" #include "pinos/server/client-node.h" -#include "pinos/server/utils.h" #include "pinos/server/link.h" #include "pinos/dbus/org-pinos.h" diff --git a/pinos/server/link.c b/pinos/server/link.c index 5571b735e..86e56d65e 100644 --- a/pinos/server/link.c +++ b/pinos/server/link.c @@ -267,12 +267,22 @@ do_allocation (PinosLink *this) { PinosLinkPrivate *priv = this->priv; SpaResult res; + const SpaPortInfo *iinfo, *oinfo; g_debug ("link %p: doing alloc buffers", this); + /* find out what's possible */ + if ((res = spa_node_port_get_info (priv->output_node, priv->output_port, &oinfo)) < 0) { + g_warning ("error get port info: %d", res); + return res; + } + if ((res = spa_node_port_get_info (priv->input_node, priv->input_port, &iinfo)) < 0) { + g_warning ("error get port info: %d", res); + return res; + } priv->n_buffers = 16; if ((res = spa_node_port_alloc_buffers (priv->output_node, priv->output_port, - NULL, 0, + iinfo->params, iinfo->n_params, priv->buffers, &priv->n_buffers)) < 0) { g_warning ("error alloc buffers: %d", res); return res; diff --git a/pinos/server/node.c b/pinos/server/node.c index d33393d85..b111d46d9 100644 --- a/pinos/server/node.c +++ b/pinos/server/node.c @@ -105,7 +105,7 @@ node_add_port (PinosNode *node, "id", id, NULL); if (port) { - g_hash_table_insert (priv->ports, GUINT_TO_POINTER (id), port); + g_hash_table_insert (priv->ports, GUINT_TO_POINTER (port->id), port); g_signal_connect (port, "remove", (GCallback) do_remove_port, node); g_signal_emit (node, signals[SIGNAL_PORT_ADDED], 0, port); } diff --git a/pinos/server/port.c b/pinos/server/port.c index 761bdd5f3..a4c2e3b8a 100644 --- a/pinos/server/port.c +++ b/pinos/server/port.c @@ -26,7 +26,6 @@ #include "pinos/server/port.h" #include "pinos/server/node.h" -#include "pinos/server/utils.h" #define PINOS_PORT_GET_PRIVATE(obj) \ (G_TYPE_INSTANCE_GET_PRIVATE ((obj), PINOS_TYPE_PORT, PinosPortPrivate)) diff --git a/pinos/server/utils.c b/pinos/server/utils.c deleted file mode 100644 index 13b62093f..000000000 --- a/pinos/server/utils.c +++ /dev/null @@ -1,84 +0,0 @@ -/* Pinos - * Copyright (C) 2015 Wim Taymans - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include - -#include -#include - -#include "pinos/server/utils.h" - -GBytes * -pinos_format_filter (GBytes *format, - GBytes *filter, - GError **error) -{ - GstCaps *tmp, *caps, *cfilter; - gchar *str; - GBytes *res; - - if (filter) { - cfilter = gst_caps_from_string (g_bytes_get_data (filter, NULL)); - if (cfilter == NULL) - goto invalid_filter; - } else { - cfilter = NULL; - } - - if (format) - caps = gst_caps_from_string (g_bytes_get_data (format, NULL)); - else - caps = gst_caps_new_any (); - - if (caps && cfilter) { - tmp = gst_caps_intersect_full (caps, cfilter, GST_CAPS_INTERSECT_FIRST); - gst_caps_take (&caps, tmp); - } - g_clear_pointer (&cfilter, gst_caps_unref); - - if (caps == NULL || gst_caps_is_empty (caps)) - goto no_format; - - str = gst_caps_to_string (caps); - gst_caps_unref (caps); - res = g_bytes_new_take (str, strlen (str) + 1); - - return res; - -invalid_filter: - { - g_set_error (error, - G_IO_ERROR, - G_IO_ERROR_INVALID_ARGUMENT, - "Invalid filter received"); - return NULL; - } -no_format: - { - g_set_error (error, - G_IO_ERROR, - G_IO_ERROR_NOT_FOUND, - "No compatible format found"); - if (cfilter) - gst_caps_unref (cfilter); - if (caps) - gst_caps_unref (caps); - return NULL; - } -} diff --git a/pinos/server/utils.h b/pinos/server/utils.h deleted file mode 100644 index 2119770d0..000000000 --- a/pinos/server/utils.h +++ /dev/null @@ -1,31 +0,0 @@ -/* Pinos - * Copyright (C) 2015 Wim Taymans - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef __PINOS_UTILS_H__ -#define __PINOS_UTILS_H__ - -#include - -G_BEGIN_DECLS - -GBytes * pinos_format_filter (GBytes *format1, GBytes *format2, GError **error); - -G_END_DECLS - -#endif /* __PINOS_UTILS_H__ */ diff --git a/spa/plugins/v4l2/v4l2-source.c b/spa/plugins/v4l2/v4l2-source.c index 937f19827..efb2c81b4 100644 --- a/spa/plugins/v4l2/v4l2-source.c +++ b/spa/plugins/v4l2/v4l2-source.c @@ -91,7 +91,7 @@ typedef struct { void *cookie; V4l2Format format[2]; - SpaFormat *current_format; + V4l2Format *current_format; int fd; bool opened; @@ -412,12 +412,21 @@ spa_v4l2_source_node_port_set_format (SpaNode *node, f = (V4l2Format*)format; } + if (state->current_format) { + if (f->fmt.media_type == state->current_format->fmt.media_type && + f->fmt.media_subtype == state->current_format->fmt.media_subtype && + f->format == state->current_format->format && + f->size.width == state->current_format->size.width && + f->size.height == state->current_format->size.height) + return SPA_RESULT_OK; + } + if (spa_v4l2_set_format (this, f, flags & SPA_PORT_FORMAT_FLAG_TEST_ONLY) < 0) return SPA_RESULT_INVALID_MEDIA_TYPE; if (!(flags & SPA_PORT_FORMAT_FLAG_TEST_ONLY)) { memcpy (tf, f, fs); - state->current_format = &tf->fmt; + state->current_format = tf; } return SPA_RESULT_OK; @@ -444,7 +453,7 @@ spa_v4l2_source_node_port_get_format (SpaNode *node, if (state->current_format == NULL) return SPA_RESULT_NO_FORMAT; - *format = state->current_format; + *format = &state->current_format->fmt; return SPA_RESULT_OK; } diff --git a/spa/plugins/v4l2/v4l2-utils.c b/spa/plugins/v4l2/v4l2-utils.c index eec789ac4..071ef67cd 100644 --- a/spa/plugins/v4l2/v4l2-utils.c +++ b/spa/plugins/v4l2/v4l2-utils.c @@ -325,7 +325,11 @@ again: i = ++state->frmival.index; } fmt->infos[pi].n_range_values = i; - fmt->fmt.props.unset_mask |= 1 << pi; + if (i == 1) { + fmt->framerate = fmt->framerates[0]; + } else { + fmt->fmt.props.unset_mask |= 1 << pi; + } pi = ++fmt->fmt.props.n_prop_info; *format = &state->format[0].fmt; @@ -488,6 +492,9 @@ spa_v4l2_buffer_recycle (SpaV4l2Source *this, uint32_t buffer_id) SpaV4l2State *state = &this->state[0]; V4l2Buffer *b = &state->alloc_buffers[buffer_id]; + if (!b->outstanding) + return; + b->outstanding = false; if (xioctl (state->fd, VIDIOC_QBUF, &b->v4l2_buffer) < 0) { @@ -495,6 +502,38 @@ spa_v4l2_buffer_recycle (SpaV4l2Source *this, uint32_t buffer_id) } } +static void +clear_buffers (SpaV4l2Source *this) +{ + SpaV4l2State *state = &this->state[0]; + int i; + + if (!state->have_buffers) + return; + + for (i = 0; i < state->reqbuf.count; i++) { + V4l2Buffer *b; + SpaMemory *mem; + + b = &state->alloc_buffers[i]; + if (b->outstanding) { + fprintf (stderr, "queueing outstanding buffer %p\n", b); + spa_v4l2_buffer_recycle (this, i); + } + mem = spa_memory_find (&b->datas[0].mem.mem); + if (state->export_buf) { + close (mem->fd); + } else { + munmap (mem->ptr, mem->size); + } + spa_memory_unref (&mem->mem); + } + if (state->alloc_mem) + spa_memory_unref (&state->alloc_mem->mem); + + state->have_buffers = false; +} + static SpaResult spa_v4l2_import_buffers (SpaV4l2Source *this, SpaBuffer **buffers, uint32_t n_buffers) { @@ -502,6 +541,11 @@ spa_v4l2_import_buffers (SpaV4l2Source *this, SpaBuffer **buffers, uint32_t n_bu struct v4l2_requestbuffers reqbuf; int i; + if (buffers == NULL) { + clear_buffers (this); + return SPA_RESULT_OK; + } + state->memtype = V4L2_MEMORY_USERPTR; CLEAR(reqbuf); @@ -715,6 +759,18 @@ spa_v4l2_alloc_buffers (SpaV4l2Source *this, { SpaResult res; SpaV4l2State *state = &this->state[0]; + unsigned int i; + + if (state->have_buffers) { + if (*n_buffers < state->reqbuf.count) + return SPA_RESULT_NO_BUFFERS; + + *n_buffers = state->reqbuf.count; + for (i = 0; i < state->reqbuf.count; i++) { + buffers[i] = &state->alloc_buffers[i].buffer; + } + return SPA_RESULT_OK; + } if (state->cap.capabilities & V4L2_CAP_STREAMING) { if ((res = mmap_init (this, params, n_params, buffers, n_buffers)) < 0) @@ -774,7 +830,6 @@ spa_v4l2_stop (SpaV4l2Source *this) SpaV4l2State *state = &this->state[0]; enum v4l2_buf_type type; SpaEvent event; - int i; if (!state->opened) return SPA_RESULT_OK; @@ -785,24 +840,7 @@ spa_v4l2_stop (SpaV4l2Source *this) return SPA_RESULT_ERROR; } - for (i = 0; i < state->reqbuf.count; i++) { - V4l2Buffer *b; - SpaMemory *mem; - - b = &state->alloc_buffers[i]; - if (b->outstanding) { - fprintf (stderr, "queueing outstanding buffer %p\n", b); - spa_v4l2_buffer_recycle (this, i); - } - mem = spa_memory_find (&b->datas[0].mem.mem); - if (state->export_buf) { - close (mem->fd); - } else { - munmap (mem->ptr, mem->size); - } - spa_memory_unref (&mem->mem); - } - state->have_buffers = false; + clear_buffers (this); event.type = SPA_EVENT_TYPE_REMOVE_POLL; event.port_id = 0;