diff --git a/pinos/Makefile.am b/pinos/Makefile.am index d06a18eb3..09196ce0d 100644 --- a/pinos/Makefile.am +++ b/pinos/Makefile.am @@ -161,8 +161,6 @@ pinos_monitor_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) # Client library # ################################### -pinosgstsource = gst/gsttmpfileallocator.h gst/gsttmpfileallocator.c - pinosinclude_HEADERS = \ client/context.h \ client/enumtypes.h \ @@ -189,13 +187,11 @@ libpinos_@PINOS_MAJORMINOR@_la_SOURCES = \ client/pinos.c client/pinos.h \ client/fdmanager.c client/fdmanager.h \ client/ringbuffer.c client/ringbuffer.h \ - client/subscribe.c client/subscribe.h \ - $(pinosgstsource) + client/subscribe.c client/subscribe.h - -libpinos_@PINOS_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS) $(GST_CFLAGS) +libpinos_@PINOS_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS) libpinos_@PINOS_MAJORMINOR@_la_LDFLAGS = $(AM_LDFLAGS) -avoid-version -libpinos_@PINOS_MAJORMINOR@_la_LIBADD = $(AM_LIBADD) $(LTLIBICONV) $(GST_LIBS) $(GST_BASE_LIBS) -lgstvideo-1.0 -lgstaudio-1.0 +libpinos_@PINOS_MAJORMINOR@_la_LIBADD = $(AM_LIBADD) $(LTLIBICONV) ################################### # Daemon core library # @@ -241,24 +237,16 @@ libgstpinos_la_SOURCES = \ gst/gstpinossrc.c \ gst/gstpinossink.c \ gst/gstpinospool.c - #gst/gstpinosdepay.c - #gst/gstpinosportsrc.c - #gst/gstpinosportsink.c - #gst/gstpinossocketsink.c - #gst/gstpinospay.c libgstpinos_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) $(GLIB_CFLAGS) libgstpinos_la_LDFLAGS = $(AM_LDFLAGS) $(GST_PLUGIN_LDFLAGS) -libgstpinos_la_LIBADD = $(GST_BASE_LIBS) $(GST_LIBS) $(GLIB_LIBS) $(LIBM) -lgstvideo-1.0 \ +libgstpinos_la_LIBADD = $(GST_BASE_LIBS) $(GST_LIBS) $(GLIB_LIBS) $(LIBM) -lgstvideo-1.0 -lgstaudio-1.0 \ libpinos-@PINOS_MAJORMINOR@.la libpinoscore-@PINOS_MAJORMINOR@.la $(AM_LIBADD) libgstpinos_la_LIBTOOLFLAGS = $(GST_PLUGIN_LIBTOOLFLAGS) noinst_HEADERS = gst/gstburstcache.h gst/gstpinossrc.h \ - gst/gstpinossocketsink.h gst/gstpinosportsink.h \ - gst/gstpinosportsrc.h \ gst/gstpinosformat.h \ - gst/gstpinossink.h gst/gstpinospay.h \ - gst/gstpinosdepay.h gst/gstpinosdeviceprovider.h + gst/gstpinossink.h gst/gstpinosdeviceprovider.h ################################### # Some minor stuff # diff --git a/pinos/client/pinos.c b/pinos/client/pinos.c index c12e47aa7..23a58e928 100644 --- a/pinos/client/pinos.c +++ b/pinos/client/pinos.c @@ -17,7 +17,7 @@ * Boston, MA 02110-1301, USA. */ -#include +#include #include "pinos/client/pinos.h" #include "spa/include/spa/memory.h" @@ -33,7 +33,6 @@ void pinos_init (int *argc, char **argv[]) { - gst_init (argc, argv); spa_memory_init (); } diff --git a/pinos/client/stream.c b/pinos/client/stream.c index abfe0537b..d6577b733 100644 --- a/pinos/client/stream.c +++ b/pinos/client/stream.c @@ -769,7 +769,7 @@ parse_control (PinosStream *stream, stream_set_state (stream, PINOS_STREAM_STATE_STREAMING, NULL); break; } - case SPA_CONTROL_CMD_STOP: + case SPA_CONTROL_CMD_PAUSE: { SpaControlBuilder builder; SpaControl control; @@ -1292,7 +1292,7 @@ do_stop (PinosStream *stream) SpaControlBuilder builder; control_builder_init (stream, &builder); - spa_control_builder_add_cmd (&builder, SPA_CONTROL_CMD_STOP, NULL); + spa_control_builder_add_cmd (&builder, SPA_CONTROL_CMD_PAUSE, NULL); g_object_unref (stream); return FALSE; diff --git a/pinos/gst/gstpinos.c b/pinos/gst/gstpinos.c index 4c1f4a66c..9b2750a64 100644 --- a/pinos/gst/gstpinos.c +++ b/pinos/gst/gstpinos.c @@ -32,14 +32,9 @@ #include "config.h" #endif -//#include "gstpinossocketsink.h" -#include "gstpinosportsink.h" -#include "gstpinosportsrc.h" #include "gstpinossrc.h" #include "gstpinossink.h" #include "gstpinosdeviceprovider.h" -#include "gstpinospay.h" -#include "gstpinosdepay.h" GST_DEBUG_CATEGORY (pinos_debug); @@ -48,20 +43,10 @@ plugin_init (GstPlugin * plugin) { pinos_init (NULL, NULL); -// gst_element_register (plugin, "pinospay", GST_RANK_NONE, - // GST_TYPE_PINOS_PAY); - // gst_element_register (plugin, "pinosdepay", GST_RANK_NONE, - // GST_TYPE_PINOS_DEPAY); gst_element_register (plugin, "pinossrc", GST_RANK_PRIMARY + 1, GST_TYPE_PINOS_SRC); gst_element_register (plugin, "pinossink", GST_RANK_NONE, GST_TYPE_PINOS_SINK); - // gst_element_register (plugin, "pinossocketsink", GST_RANK_NONE, - // GST_TYPE_PINOS_SOCKET_SINK); - // gst_element_register (plugin, "pinosportsink", GST_RANK_NONE, - // GST_TYPE_PINOS_PORT_SINK); -// gst_element_register (plugin, "pinosportsrc", GST_RANK_NONE, -// GST_TYPE_PINOS_PORT_SRC); if (!gst_device_provider_register (plugin, "pinosdeviceprovider", GST_RANK_PRIMARY + 1, GST_TYPE_PINOS_DEVICE_PROVIDER)) diff --git a/pinos/gst/gstpinosdepay.c b/pinos/gst/gstpinosdepay.c deleted file mode 100644 index 1c70681c7..000000000 --- a/pinos/gst/gstpinosdepay.c +++ /dev/null @@ -1,409 +0,0 @@ -/* GStreamer - * Copyright (C) 2014 William Manley - * (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 Street, Suite 500, - * Boston, MA 02110-1335, USA. - */ -/** - * SECTION:element-gstpinosdepay - * - * The pinosdepay element does FIXME stuff. - * - * - * Example launch line - * |[ - * gst-launch -v fakesrc ! pinosdepay ! FIXME ! fakesink - * ]| - * FIXME Describe what the pipeline does. - * - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "gstpinosdepay.h" -#include - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include - -GST_DEBUG_CATEGORY_STATIC (gst_pinos_depay_debug_category); -#define GST_CAT_DEFAULT gst_pinos_depay_debug_category - -static GQuark fdids_quark; - -enum -{ - PROP_0, - PROP_CAPS, -}; - -/* pad templates */ -static GstStaticPadTemplate gst_pinos_depay_src_template = -GST_STATIC_PAD_TEMPLATE ("src", - GST_PAD_SRC, - GST_PAD_ALWAYS, - GST_STATIC_CAPS_ANY); - -static GstStaticPadTemplate gst_pinos_depay_sink_template = -GST_STATIC_PAD_TEMPLATE ("sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS ("application/x-pinos")); - - -/* class initialization */ -G_DEFINE_TYPE (GstPinosDepay, gst_pinos_depay, GST_TYPE_ELEMENT); - -static gboolean -gst_pinos_depay_sink_event (GstPad * pad, GstObject * parent, GstEvent * event) -{ - GstPinosDepay *depay = GST_PINOS_DEPAY (parent); - gboolean res = FALSE; - - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_SEGMENT: - { - GstSegment segment; - - gst_segment_init (&segment, GST_FORMAT_TIME); - - res = gst_pad_push_event (depay->srcpad, gst_event_new_segment (&segment)); - break; - } - case GST_EVENT_CAPS: - { - GstCaps *caps; - GstStructure *str; - - gst_event_parse_caps (event, &caps); - str = gst_caps_get_structure (caps, 0); - depay->pinos_input = gst_structure_has_name (str, "application/x-pinos"); - gst_event_unref (event); - - res = gst_pad_push_event (depay->srcpad, gst_event_new_caps (depay->caps)); - break; - } - default: - res = gst_pad_event_default (pad, parent, event); - break; - } - return res; -} - -static void -reuse_fds (GstPinosDepay *this, GstBuffer *buffer) -{ - GArray *fdids; - guint i; - PinosBufferBuilder b; - PinosPacketReuseMem r; - PinosBuffer pbuf; - gsize size; - gpointer data; - GstBuffer *outbuf; - GstEvent *ev; - - fdids = gst_mini_object_steal_qdata (GST_MINI_OBJECT_CAST (buffer), - fdids_quark); - if (fdids == NULL) - return; - - pinos_buffer_builder_init (&b); - - for (i = 0; i < fdids->len; i++) { - r.id = g_array_index (fdids, guint32, i); - GST_LOG ("reuse mem id %d", r.id); - pinos_buffer_builder_add_reuse_mem (&b, &r); - } - pinos_buffer_builder_end (&b, &pbuf); - g_array_unref (fdids); - - data = pinos_buffer_steal_data (&pbuf, &size); - - outbuf = gst_buffer_new_wrapped (data, size); - ev = gst_event_new_custom (GST_EVENT_CUSTOM_UPSTREAM, - gst_structure_new ("GstNetworkMessage", - "object", G_TYPE_OBJECT, this, - "buffer", GST_TYPE_BUFFER, outbuf, NULL)); - gst_buffer_unref (outbuf); - - gst_pad_push_event (this->sinkpad, ev); - g_object_unref (this); -} - -static GstFlowReturn -gst_pinos_depay_chain (GstPad *pad, GstObject * parent, GstBuffer * buffer) -{ - GstPinosDepay *depay = GST_PINOS_DEPAY (parent); - GstBuffer *outbuf = NULL; - GstMapInfo info; - PinosBuffer pbuf; - PinosBufferIter it; - GstNetControlMessageMeta * meta; - GError *err = NULL; - GArray *fdids = NULL; - GUnixFDList *fds = NULL; - - meta = ((GstNetControlMessageMeta*) gst_buffer_get_meta ( - buffer, GST_NET_CONTROL_MESSAGE_META_API_TYPE)); - if (meta) { - if (G_IS_UNIX_FD_MESSAGE (meta->message)) { - fds = g_unix_fd_message_get_fd_list (G_UNIX_FD_MESSAGE (meta->message)); - } - } - - gst_buffer_map (buffer, &info, GST_MAP_READ); - pinos_buffer_init_data (&pbuf, info.data, info.size, NULL, 0); - - pinos_buffer_iter_init (&it, &pbuf); - while (pinos_buffer_iter_next (&it)) { - switch (pinos_buffer_iter_get_type (&it)) { - case PINOS_PACKET_TYPE_HEADER: - { - PinosPacketHeader hdr; - - if (!pinos_buffer_iter_parse_header (&it, &hdr)) - goto error; - - if (outbuf == NULL) - outbuf = gst_buffer_new (); - - GST_INFO ("pts %" G_GUINT64_FORMAT ", dts_offset %"G_GUINT64_FORMAT, hdr.pts, hdr.dts_offset); - -#if 0 - if (GST_CLOCK_TIME_IS_VALID (hdr.pts)) { - GST_BUFFER_PTS (outbuf) = hdr.pts; - if (GST_BUFFER_PTS (outbuf) + hdr.dts_offset > 0) - GST_BUFFER_DTS (outbuf) = GST_BUFFER_PTS (outbuf) + hdr.dts_offset; - } -#endif - GST_BUFFER_OFFSET (outbuf) = hdr.seq; - break; - } - case PINOS_PACKET_TYPE_ADD_MEM: - { - GstMemory *fdmem = NULL; - PinosPacketAddMem p; - int fd; - - if (!pinos_buffer_iter_parse_add_mem (&it, &p)) - goto error; - - fd = g_unix_fd_list_get (fds, p.fd_index, &err); - if (fd == -1) - goto error; - - fdmem = gst_fd_allocator_alloc (depay->fd_allocator, fd, - p.offset + p.size, GST_FD_MEMORY_FLAG_NONE); - gst_memory_resize (fdmem, p.offset, p.size); - - g_hash_table_insert (depay->mem_ids, GINT_TO_POINTER (p.id), fdmem); - break; - } - case PINOS_PACKET_TYPE_REMOVE_MEM: - { - PinosPacketRemoveMem p; - - if (!pinos_buffer_iter_parse_remove_mem (&it, &p)) - goto error; - - g_hash_table_remove (depay->mem_ids, GINT_TO_POINTER (p.id)); - break; - } - case PINOS_PACKET_TYPE_PROCESS_MEM: - { - GstMemory *fdmem = NULL; - PinosPacketProcessMem p; - - if (!pinos_buffer_iter_parse_process_mem (&it, &p)) - goto error; - - fdmem = g_hash_table_lookup (depay->mem_ids, GINT_TO_POINTER (p.id)); - if (fdmem == NULL) - goto error; - - if (outbuf == NULL) - outbuf = gst_buffer_new (); - - fdmem = gst_memory_share (fdmem, p.offset, p.size); - gst_buffer_append_memory (outbuf, fdmem); - - if (fdids == NULL) - fdids = g_array_new (FALSE, FALSE, sizeof (guint32)); - - GST_LOG ("track fd index %d", p.id); - g_array_append_val (fdids, p.id); - break; - } - case PINOS_PACKET_TYPE_FORMAT_CHANGE: - { - PinosPacketFormatChange change; - GstCaps *caps; - - if (!pinos_buffer_iter_parse_format_change (&it, &change)) - goto error; - GST_DEBUG ("got format change %d %s", change.id, change.format); - - caps = gst_caps_from_string (change.format); - if (caps) { - gst_caps_take (&depay->caps, caps); - gst_pad_push_event (depay->srcpad, gst_event_new_caps (depay->caps)); - } - break; - } - default: - break; - } - } - pinos_buffer_iter_init (&it, &pbuf); - pinos_buffer_unref (&pbuf); - gst_buffer_unmap (buffer, &info); - gst_buffer_unref (buffer); - - if (outbuf) { - if (fdids != NULL) { - gst_mini_object_set_qdata (GST_MINI_OBJECT_CAST (outbuf), - fdids_quark, fdids, NULL); - gst_mini_object_weak_ref (GST_MINI_OBJECT_CAST (outbuf), - (GstMiniObjectNotify) reuse_fds, g_object_ref (depay)); - } - return gst_pad_push (depay->srcpad, outbuf); - } - else - return GST_FLOW_OK; - -error: - { - GST_ELEMENT_ERROR (depay, RESOURCE, SETTINGS, (NULL), - ("can't get fd: %s", err->message)); - g_clear_error (&err); - gst_buffer_unref (outbuf); - return GST_FLOW_ERROR; - } -} - -static void -gst_pinos_depay_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstPinosDepay *depay = GST_PINOS_DEPAY (object); - - switch (prop_id) { - case PROP_CAPS: - { - const GstCaps *caps; - - caps = gst_value_get_caps (value); - gst_caps_replace (&depay->caps, (GstCaps *)caps); - break; - } - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gst_pinos_depay_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec) -{ - GstPinosDepay *depay = GST_PINOS_DEPAY (object); - - switch (prop_id) { - case PROP_CAPS: - gst_value_set_caps (value, depay->caps); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gst_pinos_depay_finalize (GObject * object) -{ - GstPinosDepay *depay = GST_PINOS_DEPAY (object); - - GST_DEBUG_OBJECT (depay, "finalize"); - - gst_caps_replace (&depay->caps, NULL); - g_object_unref (depay->fd_allocator); - g_hash_table_unref (depay->mem_ids); - - G_OBJECT_CLASS (gst_pinos_depay_parent_class)->finalize (object); -} - -static void -gst_pinos_depay_class_init (GstPinosDepayClass * klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - GstElementClass *element_class = - GST_ELEMENT_CLASS (klass); - - gobject_class->finalize = gst_pinos_depay_finalize; - gobject_class->set_property = gst_pinos_depay_set_property; - gobject_class->get_property = gst_pinos_depay_get_property; - - g_object_class_install_property (gobject_class, PROP_CAPS, - g_param_spec_boxed ("caps", "Caps", - "The caps of the source pad", GST_TYPE_CAPS, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - /* Setting up pads and setting metadata should be moved to - base_class_init if you intend to subclass this class. */ - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&gst_pinos_depay_src_template)); - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&gst_pinos_depay_sink_template)); - - gst_element_class_set_static_metadata (element_class, - "Pinos Deplayloder", "Generic", - "Pinos Depayloader for zero-copy IPC via Pinos", - "Wim Taymans "); - - GST_DEBUG_CATEGORY_INIT (gst_pinos_depay_debug_category, "pinosdepay", 0, - "debug category for pinosdepay element"); - - fdids_quark = g_quark_from_static_string ("GstPinosDepayFDIds"); -} - -static void -gst_pinos_depay_init (GstPinosDepay * depay) -{ - depay->srcpad = gst_pad_new_from_static_template (&gst_pinos_depay_src_template, "src"); - gst_element_add_pad (GST_ELEMENT (depay), depay->srcpad); - - depay->sinkpad = gst_pad_new_from_static_template (&gst_pinos_depay_sink_template, "sink"); - gst_pad_set_chain_function (depay->sinkpad, gst_pinos_depay_chain); - gst_pad_set_event_function (depay->sinkpad, gst_pinos_depay_sink_event); - gst_element_add_pad (GST_ELEMENT (depay), depay->sinkpad); - - depay->fd_allocator = gst_fd_allocator_new (); - depay->mem_ids = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, (GDestroyNotify) gst_memory_unref); -} diff --git a/pinos/gst/gstpinosdepay.h b/pinos/gst/gstpinosdepay.h deleted file mode 100644 index 8eb97338e..000000000 --- a/pinos/gst/gstpinosdepay.h +++ /dev/null @@ -1,58 +0,0 @@ -/* GStreamer - * Copyright (C) 2014 William Manley - * 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 _GST_PINOS_DEPAY_H_ -#define _GST_PINOS_DEPAY_H_ - -#include - -G_BEGIN_DECLS - -#define GST_TYPE_PINOS_DEPAY (gst_pinos_depay_get_type()) -#define GST_PINOS_DEPAY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_PINOS_DEPAY,GstPinosDepay)) -#define GST_PINOS_DEPAY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_PINOS_DEPAY,GstPinosDepayClass)) -#define GST_IS_PINOS_DEPAY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_PINOS_DEPAY)) -#define GST_IS_PINOS_DEPAY_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_PINOS_DEPAY)) - -typedef struct _GstPinosDepay GstPinosDepay; -typedef struct _GstPinosDepayClass GstPinosDepayClass; - -struct _GstPinosDepay -{ - GstElement parent; - - GstCaps *caps; - gboolean pinos_input; - - GstPad *srcpad, *sinkpad; - GstAllocator *fd_allocator; - GHashTable *mem_ids; -}; - -struct _GstPinosDepayClass -{ - GstElementClass parent_class; -}; - -GType gst_pinos_depay_get_type (void); - -G_END_DECLS - -#endif diff --git a/pinos/gst/gstpinospay.c b/pinos/gst/gstpinospay.c deleted file mode 100644 index de4a2afb4..000000000 --- a/pinos/gst/gstpinospay.c +++ /dev/null @@ -1,615 +0,0 @@ -/* GStreamer - * Copyright (C) 2014 William Manley - * - * 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 Street, Suite 500, - * Boston, MA 02110-1335, USA. - */ -/** - * SECTION:element-gstpinospay - * - * The pinospay element converts regular GStreamer buffers into the format - * expected by Pinos. - * - * - * Example launch line - * |[ - * gst-launch-1.0 -v videotestsrc ! video/x-raw,format=RGB,width=1920,height=1080 \ - * ! pinospay ! fdsink fd=1 \ - * | gst-launch-1.0 fdsrc fd=0 ! fddepay \ - * ! video/x-raw,format=RGB,width=1920,height=1080 ! autovideosink - * ]| - * Video frames are created in the first gst-launch-1.0 process and displayed - * by the second with no copying. - * - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include -#include "gstpinospay.h" -#include "gsttmpfileallocator.h" - -#include -#include - -#include - -#include -#include -#include - -GST_DEBUG_CATEGORY_STATIC (gst_pinos_pay_debug_category); -#define GST_CAT_DEFAULT gst_pinos_pay_debug_category - -static GQuark fdids_quark; -static GQuark orig_buffer_quark; - -/* prototypes */ - -/* pad templates */ -static GstStaticPadTemplate gst_pinos_pay_src_template = -GST_STATIC_PAD_TEMPLATE ("src", - GST_PAD_SRC, - GST_PAD_ALWAYS, - GST_STATIC_CAPS ("application/x-pinos")); - -static GstStaticPadTemplate gst_pinos_pay_sink_template = -GST_STATIC_PAD_TEMPLATE ("sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS_ANY); - -/* class initialization */ - -G_DEFINE_TYPE_WITH_CODE (GstPinosPay, gst_pinos_pay, GST_TYPE_ELEMENT, - GST_DEBUG_CATEGORY_INIT (gst_pinos_pay_debug_category, "pinospay", 0, - "debug category for pinospay element")); - -/* propose allocation query parameters for input buffers */ -static gboolean -gst_pinos_pay_query (GstPad * pad, GstObject * parent, GstQuery * query) -{ - GstPinosPay *pay = GST_PINOS_PAY (parent); - gboolean res = FALSE; - - switch (GST_QUERY_TYPE (query)) { - case GST_QUERY_ALLOCATION: - { - GST_DEBUG_OBJECT (pay, "propose_allocation"); - gst_query_add_allocation_param (query, pay->allocator, NULL); - res = TRUE; - break; - } - default: - res = gst_pad_query_default (pad, parent, query); - break; - } - return res; -} - -static gboolean -do_allocation (GstPinosPay *pay, GstCaps *caps) -{ - GstQuery *query; - - GST_DEBUG_OBJECT (pay, "doing allocation query"); - query = gst_query_new_allocation (caps, TRUE); - if (!gst_pad_peer_query (pay->srcpad, query)) { - /* not a problem, just debug a little */ - GST_DEBUG_OBJECT (pay, "peer ALLOCATION query failed"); - } - if (!gst_query_find_allocation_meta (query, - GST_NET_CONTROL_MESSAGE_META_API_TYPE, NULL)) - goto no_meta; - - gst_query_unref (query); - - return TRUE; - - /* ERRORS */ -no_meta: - { - GST_ELEMENT_ERROR (pay, STREAM, FORMAT, - ("Incompatible downstream element"), - ("The downstream element does not handle control-message metadata API")); - gst_query_unref (query); - return FALSE; - } -} - -static gboolean -gst_pinos_pay_sink_event (GstPad * pad, GstObject * parent, GstEvent * event) -{ - GstPinosPay *pay = GST_PINOS_PAY (parent); - gboolean res = FALSE; - - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_CAPS: - { - GstCaps *caps; - GstStructure *str; - - gst_event_parse_caps (event, &caps); - str = gst_caps_get_structure (caps, 0); - pay->pinos_input = gst_structure_has_name (str, "application/x-pinos"); - gst_event_unref (event); - - caps = gst_caps_new_empty_simple ("application/x-pinos"); - res = gst_pad_push_event (pay->srcpad, gst_event_new_caps (caps)); - gst_caps_unref (caps); - - if (res) - /* now negotiate the allocation */ - res = do_allocation (pay, caps); - break; - } - default: - res = gst_pad_event_default (pad, parent, event); - break; - } - return res; -} - -static void -client_buffer_sent (GstPinosPay *pay, GstBuffer *buffer, - GObject *obj) -{ - GArray *fdids; - guint i; - const gchar *client_path; - - fdids = gst_mini_object_get_qdata (GST_MINI_OBJECT_CAST (buffer), fdids_quark); - if (fdids == NULL) - return; - - /* get the client path of this socket */ - client_path = g_object_get_data (obj, "pinos-client-path"); - if (client_path == NULL) - return; - - for (i = 0; i < fdids->len; i++) { - gint id = g_array_index (fdids, guint32, i); - /* now store the id/client-path/buffer in the fdmanager */ - GST_LOG ("fd index %d, client %s increment refcount of buffer %p", id, client_path, buffer); - pinos_fd_manager_add (pay->fdmanager, - client_path, id, - gst_buffer_ref (buffer), - (GDestroyNotify) gst_buffer_unref); - } -} - -static void -client_buffer_received (GstPinosPay *pay, GstBuffer *buffer, - GObject *obj) -{ - PinosBuffer pbuf; - PinosBufferIter it; - PinosBufferBuilder b; - GstMapInfo info; - const gchar *client_path; - gboolean have_out = FALSE; - - client_path = g_object_get_data (obj, "pinos-client-path"); - if (client_path == NULL) - return; - - if (pay->pinos_input) { - pinos_buffer_builder_init (&b); - } - - gst_buffer_map (buffer, &info, GST_MAP_READ); - pinos_buffer_init_data (&pbuf, info.data, info.size, NULL, 0); - pinos_buffer_iter_init (&it, &pbuf); - while (pinos_buffer_iter_next (&it)) { - switch (pinos_buffer_iter_get_type (&it)) { - case PINOS_PACKET_TYPE_REUSE_MEM: - { - PinosPacketReuseMem p; - gint id; - - if (!pinos_buffer_iter_parse_reuse_mem (&it, &p)) - continue; - - id = p.id; - - GST_LOG ("fd index %d for client %s is reused", id, client_path); - pinos_fd_manager_remove (pay->fdmanager, client_path, id); - break; - } - case PINOS_PACKET_TYPE_REFRESH_REQUEST: - { - PinosPacketRefreshRequest p; - - if (!pinos_buffer_iter_parse_refresh_request (&it, &p)) - continue; - - GST_LOG ("refresh request"); - if (!pay->pinos_input) { - gst_pad_push_event (pay->sinkpad, - gst_video_event_new_upstream_force_key_unit (p.pts, - p.request_type == 1, 0)); - } else { - pinos_buffer_builder_add_refresh_request (&b, &p); - have_out = TRUE; - } - break; - } - default: - break; - } - } - pinos_buffer_iter_end (&it); - pinos_buffer_unref (&pbuf); - gst_buffer_unmap (buffer, &info); - - if (pay->pinos_input) { - GstBuffer *outbuf; - GstEvent *ev; - gsize size; - gpointer data; - - if (have_out) { - pinos_buffer_builder_end (&b, &pbuf); - - data = pinos_buffer_steal_data (&pbuf, &size); - - outbuf = gst_buffer_new_wrapped (data, size); - ev = gst_event_new_custom (GST_EVENT_CUSTOM_UPSTREAM, - gst_structure_new ("GstNetworkMessage", - "object", G_TYPE_OBJECT, pay, - "buffer", GST_TYPE_BUFFER, outbuf, NULL)); - gst_buffer_unref (outbuf); - - gst_pad_push_event (pay->sinkpad, ev); - } else { - pinos_buffer_builder_clear (&b); - } - } -} - -static gboolean -gst_pinos_pay_src_event (GstPad * pad, GstObject * parent, GstEvent * event) -{ - GstPinosPay *pay = GST_PINOS_PAY (parent); - gboolean res = FALSE; - - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_CUSTOM_UPSTREAM: - { - if (gst_event_has_name (event, "GstNetworkMessageDispatched")) { - const GstStructure *str = gst_event_get_structure (event); - GstBuffer *buf; - GObject *obj; - - gst_structure_get (str, "object", G_TYPE_OBJECT, &obj, - "buffer", GST_TYPE_BUFFER, &buf, NULL); - - client_buffer_sent (pay, buf, obj); - gst_buffer_unref (buf); - g_object_unref (obj); - } - else if (gst_event_has_name (event, "GstNetworkMessage")) { - const GstStructure *str = gst_event_get_structure (event); - GstBuffer *buf; - GObject *obj; - - gst_structure_get (str, "object", G_TYPE_OBJECT, &obj, - "buffer", GST_TYPE_BUFFER, &buf, NULL); - - client_buffer_received (pay, buf, obj); - gst_buffer_unref (buf); - g_object_unref (obj); - - } - res = TRUE; - gst_event_unref (event); - break; - } - default: - res = gst_pad_event_default (pad, parent, event); - break; - } - return res; -} - -static GstMemory * -gst_pinos_pay_get_fd_memory (GstPinosPay * tmpfilepay, GstBuffer * buffer, gboolean *tmpfile) -{ - GstMemory *mem = NULL; - - if (gst_buffer_n_memory (buffer) == 1 - && gst_is_fd_memory (gst_buffer_peek_memory (buffer, 0))) { - mem = gst_buffer_get_memory (buffer, 0); - *tmpfile = gst_is_tmpfile_memory (mem); - } else { - GstMapInfo info; - GstAllocationParams params = {0, 0, 0, 0, { NULL, }}; - gsize size = gst_buffer_get_size (buffer); - GST_INFO_OBJECT (tmpfilepay, "Buffer cannot be payloaded without copying"); - mem = gst_allocator_alloc (tmpfilepay->allocator, size, ¶ms); - if (!gst_memory_map (mem, &info, GST_MAP_WRITE)) - return NULL; - gst_buffer_extract (buffer, 0, info.data, size); - gst_memory_unmap (mem, &info); - *tmpfile = TRUE; - } - return mem; -} - -static void -release_fds (GstPinosPay *pay, GstBuffer *buffer) -{ - GArray *fdids; - guint i; - PinosBufferBuilder b; - PinosPacketReuseMem r; - PinosBuffer pbuf; - gsize size; - gpointer data; - GstBuffer *outbuf; - GstEvent *ev; - - fdids = gst_mini_object_steal_qdata (GST_MINI_OBJECT_CAST (buffer), - fdids_quark); - if (fdids == NULL) - return; - - pinos_buffer_builder_init (&b); - - for (i = 0; i < fdids->len; i++) { - r.id = g_array_index (fdids, guint32, i); - GST_LOG ("release fd index %d", r.id); - pinos_buffer_builder_add_reuse_mem (&b, &r); - } - pinos_buffer_builder_end (&b, &pbuf); - g_array_unref (fdids); - - data = pinos_buffer_steal_data (&pbuf, &size); - - outbuf = gst_buffer_new_wrapped (data, size); - ev = gst_event_new_custom (GST_EVENT_CUSTOM_UPSTREAM, - gst_structure_new ("GstNetworkMessage", - "object", G_TYPE_OBJECT, pay, - "buffer", GST_TYPE_BUFFER, outbuf, NULL)); - gst_buffer_unref (outbuf); - - gst_pad_push_event (pay->sinkpad, ev); - g_object_unref (pay); -} - -static GstFlowReturn -gst_pinos_pay_chain_pinos (GstPinosPay *pay, GstBuffer * buffer) -{ - GstMapInfo info; - PinosBuffer pbuf; - PinosBufferIter it; - GArray *fdids = NULL; - - gst_buffer_map (buffer, &info, GST_MAP_READ); - pinos_buffer_init_data (&pbuf, info.data, info.size, NULL, 0); - pinos_buffer_iter_init (&it, &pbuf); - while (pinos_buffer_iter_next (&it)) { - switch (pinos_buffer_iter_get_type (&it)) { - case PINOS_PACKET_TYPE_PROCESS_MEM: - { - PinosPacketProcessMem p; - - if (!pinos_buffer_iter_parse_process_mem (&it, &p)) - continue; - - if (fdids == NULL) - fdids = g_array_new (FALSE, FALSE, sizeof (guint32)); - - GST_LOG ("track fd index %d", p.id); - g_array_append_val (fdids, p.id); - break; - } - case PINOS_PACKET_TYPE_FORMAT_CHANGE: - { - PinosPacketFormatChange p; - GstCaps * caps; - - if (!pinos_buffer_iter_parse_format_change (&it, &p)) - continue; - - caps = gst_caps_from_string (p.format); - - gst_element_post_message (GST_ELEMENT (pay), - gst_message_new_element (GST_OBJECT (pay), - gst_structure_new ("PinosPayloaderFormatChange", - "format", GST_TYPE_CAPS, caps, NULL))); - gst_caps_unref (caps); - break; - } - default: - break; - } - } - pinos_buffer_iter_end (&it); - pinos_buffer_unref (&pbuf); - gst_buffer_unmap (buffer, &info); - - if (fdids != NULL) { - gst_mini_object_set_qdata (GST_MINI_OBJECT_CAST (buffer), - fdids_quark, fdids, NULL); - gst_mini_object_weak_ref (GST_MINI_OBJECT_CAST (buffer), - (GstMiniObjectNotify) release_fds, g_object_ref (pay)); - } - - return gst_pad_push (pay->srcpad, buffer); -} - -static GstFlowReturn -gst_pinos_pay_chain_other (GstPinosPay *pay, GstBuffer * buffer) -{ - GstMemory *fdmem = NULL; - GError *err = NULL; - GstBuffer *outbuf; - PinosBuffer pbuf; - PinosBufferBuilder builder; - PinosPacketHeader hdr; - PinosPacketAddMem am; - PinosPacketProcessMem p; - PinosPacketRemoveMem rm; - gsize size; - gpointer data; - GSocketControlMessage *msg; - gboolean tmpfile = TRUE; - gint *fds, n_fds, i; - - hdr.flags = 0; - hdr.seq = GST_BUFFER_OFFSET (buffer); - hdr.pts = GST_BUFFER_PTS (buffer) + GST_ELEMENT_CAST (pay)->base_time; - hdr.dts_offset = 0; - - pinos_buffer_builder_init (&builder); - pinos_buffer_builder_add_header (&builder, &hdr); - - msg = g_unix_fd_message_new (); - - fdmem = gst_pinos_pay_get_fd_memory (pay, buffer, &tmpfile); - - am.id = pinos_fd_manager_get_id (pay->fdmanager); - am.fd_index = pinos_buffer_builder_add_fd (&builder, gst_fd_memory_get_fd (fdmem)); - am.offset = 0; - am.size = fdmem->size; - p.id = am.id; - p.offset = fdmem->offset; - p.size = fdmem->size; - rm.id = am.id; - pinos_buffer_builder_add_add_mem (&builder, &am); - pinos_buffer_builder_add_process_mem (&builder, &p); - pinos_buffer_builder_add_remove_mem (&builder, &rm); - pinos_buffer_builder_end (&builder, &pbuf); - - 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); - GST_BUFFER_DTS (outbuf) = GST_BUFFER_DTS (buffer); - GST_BUFFER_DURATION (outbuf) = GST_BUFFER_DURATION (buffer); - GST_BUFFER_OFFSET (outbuf) = GST_BUFFER_OFFSET (buffer); - GST_BUFFER_OFFSET_END (outbuf) = GST_BUFFER_OFFSET_END (buffer); - - msg = g_unix_fd_message_new (); - for (i = 0; i < n_fds; i++) { - if (!g_unix_fd_message_append_fd (G_UNIX_FD_MESSAGE (msg), fds[i], &err)) - goto add_fd_failed; - } - gst_buffer_add_net_control_message_meta (outbuf, msg); - g_object_unref (msg); - g_free (fds); - - gst_memory_unref(fdmem); - fdmem = NULL; - - if (!tmpfile) { - GArray *fdids; - /* we are using the original buffer fd in the control message, we need - * to make sure it is not reused before everyone is finished with it. - * We tag the output buffer with the array of fds in it and the original - * buffer (to keep it alive). All clients that receive the fd will - * increment outbuf refcount, all clients that do release-fd on the fd - * will decrease the refcount again. */ - fdids = g_array_new (FALSE, FALSE, sizeof (guint32)); - g_array_append_val (fdids, p.id); - gst_mini_object_set_qdata (GST_MINI_OBJECT_CAST (outbuf), - fdids_quark, fdids, (GDestroyNotify) g_array_unref); - gst_mini_object_set_qdata (GST_MINI_OBJECT_CAST (outbuf), - orig_buffer_quark, buffer, (GDestroyNotify) gst_buffer_unref); - } else { - gst_buffer_unref (buffer); - } - - return gst_pad_push (pay->srcpad, outbuf); - - /* ERRORS */ -add_fd_failed: - { - GST_WARNING_OBJECT (pay, "Adding fd failed: %s", err->message); - gst_object_unref(msg); - g_clear_error (&err); - - return GST_FLOW_ERROR; - } -} - -static GstFlowReturn -gst_pinos_pay_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer) -{ - GstPinosPay *pay = GST_PINOS_PAY (parent); - - if (pay->pinos_input) - return gst_pinos_pay_chain_pinos (pay, buffer); - else - return gst_pinos_pay_chain_other (pay, buffer); -} -static void -gst_pinos_pay_finalize (GObject * object) -{ - GstPinosPay *pay = GST_PINOS_PAY (object); - - GST_DEBUG_OBJECT (pay, "finalize"); - - g_object_unref (pay->allocator); - g_object_unref (pay->fdmanager); - - G_OBJECT_CLASS (gst_pinos_pay_parent_class)->finalize (object); -} - -static void -gst_pinos_pay_init (GstPinosPay * pay) -{ - pay->srcpad = gst_pad_new_from_static_template (&gst_pinos_pay_src_template, "src"); - gst_pad_set_event_function (pay->srcpad, gst_pinos_pay_src_event); - gst_element_add_pad (GST_ELEMENT (pay), pay->srcpad); - - pay->sinkpad = gst_pad_new_from_static_template (&gst_pinos_pay_sink_template, "sink"); - gst_pad_set_chain_function (pay->sinkpad, gst_pinos_pay_chain); - gst_pad_set_event_function (pay->sinkpad, gst_pinos_pay_sink_event); - gst_pad_set_query_function (pay->sinkpad, gst_pinos_pay_query); - gst_element_add_pad (GST_ELEMENT (pay), pay->sinkpad); - - pay->allocator = gst_tmpfile_allocator_new (); - pay->fdmanager = pinos_fd_manager_get (PINOS_FD_MANAGER_DEFAULT); -} - -static void -gst_pinos_pay_class_init (GstPinosPayClass * klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - GstElementClass *element_class = GST_ELEMENT_CLASS (klass); - - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&gst_pinos_pay_src_template)); - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&gst_pinos_pay_sink_template)); - - gst_element_class_set_static_metadata (element_class, - "Pinos Payloader", "Generic", - "Pinos Payloader for zero-copy IPC with Pinos", - "Wim Taymans "); - - gobject_class->finalize = gst_pinos_pay_finalize; - - fdids_quark = g_quark_from_static_string ("GstPinosPayFDIds"); - orig_buffer_quark = g_quark_from_static_string ("GstPinosPayOrigBuffer"); -} diff --git a/pinos/gst/gstpinospay.h b/pinos/gst/gstpinospay.h deleted file mode 100644 index 713211952..000000000 --- a/pinos/gst/gstpinospay.h +++ /dev/null @@ -1,60 +0,0 @@ -/* GStreamer - * Copyright (C) 2014 William Manley - * (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 _GST_PINOS_PAY_H_ -#define _GST_PINOS_PAY_H_ - -#include - -#include - -G_BEGIN_DECLS - -#define GST_TYPE_PINOS_PAY (gst_pinos_pay_get_type()) -#define GST_PINOS_PAY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_PINOS_PAY,GstPinosPay)) -#define GST_PINOS_PAY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_PINOS_PAY,GstPinosPayClass)) -#define GST_IS_PINOS_PAY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_PINOS_PAY)) -#define GST_IS_PINOS_PAY_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_PINOS_PAY)) - -typedef struct _GstPinosPay GstPinosPay; -typedef struct _GstPinosPayClass GstPinosPayClass; - -struct _GstPinosPay -{ - GstElement parent; - - gboolean pinos_input; - GstPad *srcpad, *sinkpad; - - GstAllocator *allocator; - - PinosFdManager *fdmanager; -}; - -struct _GstPinosPayClass -{ - GstElementClass parent_class; -}; - -GType gst_pinos_pay_get_type (void); - -G_END_DECLS - -#endif /* _GST_PINOS_PAY_H_ */ diff --git a/pinos/gst/gstpinosportsink.c b/pinos/gst/gstpinosportsink.c deleted file mode 100644 index 94d7fb7a3..000000000 --- a/pinos/gst/gstpinosportsink.c +++ /dev/null @@ -1,402 +0,0 @@ -/* GStreamer - * Copyright (C) <2016> Wim Taymans - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -/** - * SECTION:element-pinosportsink - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include -#include -#include - -#include - -#include -#include -#include - -#include "gstpinosportsink.h" -#include "gsttmpfileallocator.h" - -GST_DEBUG_CATEGORY_STATIC (pinos_port_sink_debug); -#define GST_CAT_DEFAULT pinos_port_sink_debug - -static GstStaticPadTemplate gst_pinos_port_sink_template = -GST_STATIC_PAD_TEMPLATE ("sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS_ANY - ); - -enum -{ - PROP_0, - PROP_PORT, -}; - -#define gst_pinos_port_sink_parent_class parent_class -G_DEFINE_TYPE (GstPinosPortSink, gst_pinos_port_sink, GST_TYPE_BASE_SINK); - -static gboolean -gst_pinos_port_sink_propose_allocation (GstBaseSink * bsink, GstQuery * query) -{ - GstPinosPortSink *this = GST_PINOS_PORT_SINK (bsink); - - gst_query_add_allocation_param (query, this->allocator, NULL); - gst_query_add_allocation_meta (query, GST_NET_CONTROL_MESSAGE_META_API_TYPE, - NULL); - - return TRUE; -} - -static gboolean -on_received_buffer (PinosPort *port, PinosBuffer *pbuf, GError **error, gpointer user_data) -{ - GstPinosPortSink *this = user_data; - GstEvent *ev; - PinosBufferIter it; - PinosBufferBuilder b; - gboolean have_out = FALSE; - guint8 buffer[1024]; - gint fds[8]; - - if (this->pinos_input) { - pinos_buffer_builder_init_into (&b, buffer, 1024, fds, 8); - } - - 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: - { - PinosPacketRefreshRequest p; - - if (!pinos_buffer_iter_parse_refresh_request (&it, &p)) - continue; - - GST_LOG ("refresh request"); - if (!this->pinos_input) { - gst_pad_push_event (GST_BASE_SINK_PAD (this), - gst_video_event_new_upstream_force_key_unit (p.pts, - p.request_type == 1, 0)); - } else { - pinos_buffer_builder_add_refresh_request (&b, &p); - have_out = TRUE; - } - break; - } - default: - break; - } - } - pinos_buffer_iter_end (&it); - - if (this->pinos_input) { - GstBuffer *outbuf; - gsize size; - gpointer data; - - if (have_out) { - pinos_buffer_builder_end (&b, pbuf); - - data = pinos_buffer_steal_data (pbuf, &size); - - outbuf = gst_buffer_new_wrapped (data, size); - ev = gst_event_new_custom (GST_EVENT_CUSTOM_UPSTREAM, - gst_structure_new ("GstNetworkMessage", - "object", G_TYPE_OBJECT, this, - "buffer", GST_TYPE_BUFFER, outbuf, NULL)); - gst_buffer_unref (outbuf); - - gst_pad_push_event (GST_BASE_SINK_PAD (this), ev); - } else { - pinos_buffer_builder_clear (&b); - } - } - return TRUE; -} - -static void -set_port (GstPinosPortSink *this, PinosPort *port) -{ - if (this->port) - g_object_unref (this->port); - this->port = port; - - pinos_port_set_received_buffer_cb (port, on_received_buffer, this, NULL); -} - -static void -gst_pinos_port_sink_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstPinosPortSink *this = GST_PINOS_PORT_SINK (object); - - switch (prop_id) { - case PROP_PORT: - set_port (this, g_value_dup_object (value)); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gst_pinos_port_sink_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec) -{ - GstPinosPortSink *this = GST_PINOS_PORT_SINK (object); - - switch (prop_id) { - case PROP_PORT: - g_value_set_object (value, this->port); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static GstCaps * -gst_pinos_port_sink_getcaps (GstBaseSink * bsink, GstCaps * filter) -{ - GstPinosPortSink *this = GST_PINOS_PORT_SINK (bsink); - GBytes *filt, *formats; - gchar *cstr; - GstCaps *result; - - if (filter) { - cstr = gst_caps_to_string (filter); - filt = g_bytes_new_take (cstr, strlen (cstr) + 1); - } else { - filt = NULL; - } - - formats = pinos_port_filter_formats (this->port, filt, NULL); - - if (filt) - g_bytes_unref (filt); - - if (formats) { - result = gst_caps_from_string (g_bytes_get_data (formats, NULL)); - g_bytes_unref (formats); - } else { - result = gst_caps_new_empty (); - } - - return result; -} - -static gboolean -gst_pinos_port_sink_setcaps (GstBaseSink * bsink, GstCaps * caps) -{ - GstPinosPortSink *this = GST_PINOS_PORT_SINK (bsink); - GstStructure *str; - gchar *cstr; - - str = gst_caps_get_structure (caps, 0); - this->pinos_input = gst_structure_has_name (str, "application/x-pinos"); - if (!this->pinos_input) { - GError *error = NULL; - PinosBufferBuilder builder; - PinosBuffer pbuf; - PinosPacketFormatChange fc; - guint8 buffer[1024]; - - pinos_buffer_builder_init_into (&builder, buffer, 1024, NULL, 0); - 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_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); -} - -static GstFlowReturn -gst_pinos_port_sink_render_pinos (GstPinosPortSink * this, GstBuffer * buffer) -{ - GstMapInfo info; - PinosBuffer pbuf; - GError *error = NULL; - - gst_buffer_map (buffer, &info, GST_MAP_READ); - pinos_buffer_init_data (&pbuf, info.data, info.size, NULL, 0); - - 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; -} - -static GstMemory * -gst_pinos_port_sink_get_fd_memory (GstPinosPortSink * this, GstBuffer * buffer, gboolean *tmpfile) -{ - GstMemory *mem = NULL; - - if (gst_buffer_n_memory (buffer) == 1 - && gst_is_fd_memory (gst_buffer_peek_memory (buffer, 0))) { - mem = gst_buffer_get_memory (buffer, 0); - *tmpfile = gst_is_tmpfile_memory (mem); - } else { - GstMapInfo info; - GstAllocationParams params = {0, 0, 0, 0, { NULL, }}; - gsize size = gst_buffer_get_size (buffer); - GST_INFO_OBJECT (this, "Buffer cannot be sent without copying"); - mem = gst_allocator_alloc (this->allocator, size, ¶ms); - if (!gst_memory_map (mem, &info, GST_MAP_WRITE)) - return NULL; - gst_buffer_extract (buffer, 0, info.data, size); - gst_memory_unmap (mem, &info); - *tmpfile = TRUE; - } - return mem; -} - -static GstFlowReturn -gst_pinos_port_sink_render_other (GstPinosPortSink * this, GstBuffer * buffer) -{ - GstMemory *fdmem = NULL; - GError *error = NULL; - PinosBuffer pbuf; - PinosBufferBuilder builder; - PinosPacketHeader hdr; - PinosPacketAddMem am; - PinosPacketProcessMem p; - PinosPacketRemoveMem rm; - gboolean tmpfile = TRUE; - guint8 send_buffer[1024]; - gint send_fds[8]; - - 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_into (&builder, send_buffer, 1024, send_fds, 8); - pinos_buffer_builder_add_header (&builder, &hdr); - - fdmem = gst_pinos_port_sink_get_fd_memory (this, buffer, &tmpfile); - am.id = pinos_fd_manager_get_id (this->fdmanager); - am.fd_index = pinos_buffer_builder_add_fd (&builder, gst_fd_memory_get_fd (fdmem)); - am.offset = 0; - am.size = fdmem->size + fdmem->offset; - p.id = am.id; - p.offset = fdmem->offset; - p.size = fdmem->size; - rm.id = am.id; - pinos_buffer_builder_add_add_mem (&builder, &am); - pinos_buffer_builder_add_process_mem (&builder, &p); - pinos_buffer_builder_add_remove_mem (&builder, &rm); - pinos_buffer_builder_end (&builder, &pbuf); - - GST_LOG ("send %d %"G_GUINT64_FORMAT" %"G_GUINT64_FORMAT" %"G_GUINT64_FORMAT, - p.id, hdr.pts, GST_BUFFER_PTS (buffer), GST_ELEMENT_CAST (this)->base_time); - - if (!pinos_port_send_buffer (this->port, &pbuf, &error)) { - 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); - - return GST_FLOW_OK; -} - -static GstFlowReturn -gst_pinos_port_sink_render (GstBaseSink * bsink, GstBuffer * buffer) -{ - GstPinosPortSink *this = GST_PINOS_PORT_SINK (bsink); - - if (this->pinos_input) - return gst_pinos_port_sink_render_pinos (this, buffer); - else - return gst_pinos_port_sink_render_other (this, buffer); -} - -static void -gst_pinos_port_sink_finalize (GObject * object) -{ - G_OBJECT_CLASS (parent_class)->finalize (object); -} - -static void -gst_pinos_port_sink_class_init (GstPinosPortSinkClass * klass) -{ - GObjectClass *gobject_class; - GstElementClass *gstelement_class; - GstBaseSinkClass *gstbasesink_class; - - gobject_class = (GObjectClass *) klass; - gstelement_class = (GstElementClass *) klass; - gstbasesink_class = (GstBaseSinkClass *) klass; - - gobject_class->finalize = gst_pinos_port_sink_finalize; - gobject_class->set_property = gst_pinos_port_sink_set_property; - gobject_class->get_property = gst_pinos_port_sink_get_property; - - g_object_class_install_property (gobject_class, PROP_PORT, - g_param_spec_object ("port", "Port", - "The pinos port object", PINOS_TYPE_PORT, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - gst_element_class_set_static_metadata (gstelement_class, - "Pinos Port sink", "Sink/Video", - "Send data to pinos port", "Wim Taymans "); - - gst_element_class_add_pad_template (gstelement_class, - gst_static_pad_template_get (&gst_pinos_port_sink_template)); - - gstbasesink_class->get_caps = gst_pinos_port_sink_getcaps; - gstbasesink_class->set_caps = gst_pinos_port_sink_setcaps; - gstbasesink_class->propose_allocation = gst_pinos_port_sink_propose_allocation; - gstbasesink_class->render = gst_pinos_port_sink_render; - - GST_DEBUG_CATEGORY_INIT (pinos_port_sink_debug, "pinosportsink", 0, - "Pinos Socket Sink"); -} - -static void -gst_pinos_port_sink_init (GstPinosPortSink * this) -{ - this->allocator = gst_tmpfile_allocator_new (); - this->fdmanager = pinos_fd_manager_get (PINOS_FD_MANAGER_DEFAULT); -} diff --git a/pinos/gst/gstpinosportsink.h b/pinos/gst/gstpinosportsink.h deleted file mode 100644 index 108e20165..000000000 --- a/pinos/gst/gstpinosportsink.h +++ /dev/null @@ -1,66 +0,0 @@ -/* GStreamer - * Copyright (C) <2016> Wim Taymans - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef __GST_PINOS_PORT_SINK_H__ -#define __GST_PINOS_PORT_SINK_H__ - -#include - -#include -#include - -#include -#include - -G_BEGIN_DECLS - -#define GST_TYPE_PINOS_PORT_SINK (gst_pinos_port_sink_get_type()) -#define GST_PINOS_PORT_SINK(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_PINOS_PORT_SINK,GstPinosPortSink)) -#define GST_PINOS_PORT_SINK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_PINOS_PORT_SINK,GstPinosPortSinkClass)) -#define GST_IS_PINOS_PORT_SINK(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_PINOS_PORT_SINK)) -#define GST_IS_PINOS_PORT_SINK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_PINOS_PORT_SINK)) -#define GST_PINOS_PORT_SINK_CAST(obj) ((GstPinosPortSink *) (obj)) - -typedef struct _GstPinosPortSink GstPinosPortSink; -typedef struct _GstPinosPortSinkClass GstPinosPortSinkClass; - -/** - * GstPinosPortSink: - * - * Opaque data structure. - */ -struct _GstPinosPortSink { - GstBaseSink element; - - gboolean pinos_input; - GstAllocator *allocator; - - PinosPort *port; - PinosFdManager *fdmanager; -}; - -struct _GstPinosPortSinkClass { - GstBaseSinkClass parent_class; -}; - -GType gst_pinos_port_sink_get_type (void); - -G_END_DECLS - -#endif /* __GST_PINOS_PORT_SINK_H__ */ diff --git a/pinos/gst/gstpinosportsrc.c b/pinos/gst/gstpinosportsrc.c deleted file mode 100644 index 4aac43b0c..000000000 --- a/pinos/gst/gstpinosportsrc.c +++ /dev/null @@ -1,649 +0,0 @@ -/* GStreamer - * 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. - */ - -/** - * SECTION:element-pinosportsrc - * - * - * Example launch line - * |[ - * gst-launch -v pinosportsrc ! videoconvert ! ximagesink - * ]| Shows pinos output in an X window. - * - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif -#include "gstpinosportsrc.h" - -#include -#include -#include -#include -#include - -#include -#include -#include -#include - - -static GQuark process_mem_data_quark; - -GST_DEBUG_CATEGORY_STATIC (pinos_port_src_debug); -#define GST_CAT_DEFAULT pinos_port_src_debug - -enum -{ - PROP_0, - PROP_PORT, -}; - - -#define PINOSS_VIDEO_CAPS GST_VIDEO_CAPS_MAKE (GST_VIDEO_FORMATS_ALL) - -static GstStaticPadTemplate gst_pinos_port_src_template = -GST_STATIC_PAD_TEMPLATE ("src", - GST_PAD_SRC, - GST_PAD_ALWAYS, - GST_STATIC_CAPS_ANY - ); - -#define gst_pinos_port_src_parent_class parent_class -G_DEFINE_TYPE (GstPinosPortSrc, gst_pinos_port_src, GST_TYPE_PUSH_SRC); - -static GstStateChangeReturn -gst_pinos_port_src_change_state (GstElement * element, GstStateChange transition); - -static GstCaps *gst_pinos_port_src_getcaps (GstBaseSrc * bsrc, GstCaps * filter); - -static GstFlowReturn gst_pinos_port_src_create (GstPushSrc * psrc, - GstBuffer ** buffer); -static gboolean gst_pinos_port_src_start (GstBaseSrc * basesrc); -static gboolean gst_pinos_port_src_stop (GstBaseSrc * basesrc); -static gboolean gst_pinos_port_src_event (GstBaseSrc * src, GstEvent * event); -static gboolean gst_pinos_port_src_query (GstBaseSrc * src, GstQuery * query); - -typedef struct { - GstPinosPortSrc *src; - PinosPacketProcessMem p; -} ProcessMemData; - -static void -process_mem_data_destroy (gpointer user_data) -{ - ProcessMemData *data = user_data; - GstPinosPortSrc *this = data->src; - PinosBufferBuilder b; - PinosPacketReuseMem r; - PinosBuffer pbuf; - - r.id = data->p.id; - - GST_DEBUG_OBJECT (this, "destroy %d", r.id); - - pinos_buffer_builder_init (&b); - pinos_buffer_builder_add_reuse_mem (&b, &r); - pinos_buffer_builder_end (&b, &pbuf); - - pinos_port_send_buffer (this->port, &pbuf, NULL); - pinos_buffer_unref (&pbuf); - - gst_object_unref (this); - g_slice_free (ProcessMemData, data); -} - -static gboolean -on_received_buffer (PinosPort *port, - PinosBuffer *pbuf, - GError **error, - gpointer user_data) -{ - GstPinosPortSrc *this = user_data; - PinosBufferIter it; - GstBuffer *buf = NULL; - - GST_LOG_OBJECT (this, "got new buffer"); - - pinos_buffer_iter_init (&it, pbuf); - while (pinos_buffer_iter_next (&it)) { - switch (pinos_buffer_iter_get_type (&it)) { - case PINOS_PACKET_TYPE_HEADER: - { - PinosPacketHeader hdr; - - if (!pinos_buffer_iter_parse_header (&it, &hdr)) - break; - - if (buf == NULL) - buf = gst_buffer_new (); - - GST_INFO ("pts %" G_GUINT64_FORMAT ", dts_offset %"G_GUINT64_FORMAT, hdr.pts, hdr.dts_offset); - - if (GST_CLOCK_TIME_IS_VALID (hdr.pts)) { - GST_BUFFER_PTS (buf) = hdr.pts; - if (GST_BUFFER_PTS (buf) + hdr.dts_offset > 0) - GST_BUFFER_DTS (buf) = GST_BUFFER_PTS (buf) + hdr.dts_offset; - } - GST_BUFFER_OFFSET (buf) = hdr.seq; - break; - } - case PINOS_PACKET_TYPE_ADD_MEM: - { - GstMemory *fdmem = NULL; - PinosPacketAddMem p; - int fd; - - if (!pinos_buffer_iter_parse_add_mem (&it, &p)) - break; - - fd = pinos_buffer_get_fd (pbuf, p.fd_index); - if (fd == -1) - break; - - fdmem = gst_fd_allocator_alloc (this->fd_allocator, dup (fd), - p.offset + p.size, GST_FD_MEMORY_FLAG_NONE); - gst_memory_resize (fdmem, p.offset, p.size); - - g_hash_table_insert (this->mem_ids, GINT_TO_POINTER (p.id), fdmem); - break; - } - case PINOS_PACKET_TYPE_REMOVE_MEM: - { - PinosPacketRemoveMem p; - - if (!pinos_buffer_iter_parse_remove_mem (&it, &p)) - break; - - g_hash_table_remove (this->mem_ids, GINT_TO_POINTER (p.id)); - break; - } - case PINOS_PACKET_TYPE_PROCESS_MEM: - { - GstMemory *fdmem = NULL; - ProcessMemData data; - - if (!pinos_buffer_iter_parse_process_mem (&it, &data.p)) - break; - - if (!(fdmem = g_hash_table_lookup (this->mem_ids, GINT_TO_POINTER (data.p.id)))) - break; - - if (buf == NULL) - buf = gst_buffer_new (); - - fdmem = gst_memory_share (fdmem, data.p.offset, data.p.size); - gst_buffer_append_memory (buf, fdmem); - - data.src = gst_object_ref (this); - gst_mini_object_set_qdata (GST_MINI_OBJECT_CAST (fdmem), - process_mem_data_quark, - g_slice_dup (ProcessMemData, &data), - process_mem_data_destroy); - break; - } - case PINOS_PACKET_TYPE_FORMAT_CHANGE: - { - PinosPacketFormatChange change; - GstCaps *caps; - - if (!pinos_buffer_iter_parse_format_change (&it, &change)) - break; - GST_DEBUG ("got format change %d %s", change.id, change.format); - - caps = gst_caps_from_string (change.format); - gst_base_src_set_caps (GST_BASE_SRC (this), caps); - gst_caps_unref (caps); - break; - } - default: - break; - } - } - pinos_buffer_iter_end (&it); - - if (buf) { - g_queue_push_tail (&this->queue, buf); - g_cond_signal (&this->cond); - } - - return TRUE; -} - -static void -set_port (GstPinosPortSrc *this, PinosPort *port) -{ - g_debug ("set port %p", port); - - if (this->port) - g_object_unref (this->port); - this->port = port; - - pinos_port_set_received_buffer_cb (port, on_received_buffer, this, NULL); -} - -static void -gst_pinos_port_src_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstPinosPortSrc *this = GST_PINOS_PORT_SRC (object); - - switch (prop_id) { - case PROP_PORT: - set_port (this, g_value_dup_object (value)); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gst_pinos_port_src_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec) -{ - GstPinosPortSrc *this = GST_PINOS_PORT_SRC (object); - - switch (prop_id) { - case PROP_PORT: - g_value_set_object (value, this->port); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static GstClock * -gst_pinos_port_src_provide_clock (GstElement * elem) -{ - GstPinosPortSrc *this = GST_PINOS_PORT_SRC (elem); - GstClock *clock; - - GST_OBJECT_LOCK (this); - if (!GST_OBJECT_FLAG_IS_SET (this, GST_ELEMENT_FLAG_PROVIDE_CLOCK)) - goto clock_disabled; - - if (this->clock) - clock = GST_CLOCK_CAST (gst_object_ref (this->clock)); - else - clock = NULL; - GST_OBJECT_UNLOCK (this); - - return clock; - - /* ERRORS */ -clock_disabled: - { - GST_DEBUG_OBJECT (this, "clock provide disabled"); - GST_OBJECT_UNLOCK (this); - return NULL; - } -} - -static gboolean -gst_pinos_port_src_unlock (GstBaseSrc * basesrc) -{ - GstPinosPortSrc *this = GST_PINOS_PORT_SRC (basesrc); - - GST_DEBUG_OBJECT (this, "setting flushing"); - - GST_OBJECT_LOCK (this); - this->flushing = TRUE; - g_cond_signal (&this->cond); - GST_OBJECT_UNLOCK (this); - - return TRUE; -} - -static gboolean -gst_pinos_port_src_unlock_stop (GstBaseSrc * basesrc) -{ - GstPinosPortSrc *this = GST_PINOS_PORT_SRC (basesrc); - - GST_DEBUG_OBJECT (this, "unsetting flushing"); - this->flushing = FALSE; - - return TRUE; -} - -static void -gst_pinos_port_src_finalize (GObject * object) -{ - GstPinosPortSrc *this = GST_PINOS_PORT_SRC (object); - - g_queue_foreach (&this->queue, (GFunc) gst_mini_object_unref, NULL); - g_queue_clear (&this->queue); - g_cond_clear (&this->cond); - g_object_unref (this->fd_allocator); - g_object_unref (this->port); - if (this->clock) - gst_object_unref (this->clock); - g_hash_table_unref (this->mem_ids); - - G_OBJECT_CLASS (parent_class)->finalize (object); -} - -static void -gst_pinos_port_src_class_init (GstPinosPortSrcClass * klass) -{ - GObjectClass *gobject_class; - GstElementClass *gstelement_class; - GstBaseSrcClass *gstbasesrc_class; - GstPushSrcClass *gstpushsrc_class; - - gobject_class = (GObjectClass *) klass; - gstelement_class = (GstElementClass *) klass; - gstbasesrc_class = (GstBaseSrcClass *) klass; - gstpushsrc_class = (GstPushSrcClass *) klass; - - gobject_class->finalize = gst_pinos_port_src_finalize; - gobject_class->set_property = gst_pinos_port_src_set_property; - gobject_class->get_property = gst_pinos_port_src_get_property; - - g_object_class_install_property (gobject_class, PROP_PORT, - g_param_spec_object ("port", "Port", - "The pinos port object", - PINOS_TYPE_PORT, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - - gstelement_class->provide_clock = gst_pinos_port_src_provide_clock; - gstelement_class->change_state = gst_pinos_port_src_change_state; - - gst_element_class_set_static_metadata (gstelement_class, - "Pinos source", "Source/Video", - "Uses pinos to create video", "Wim Taymans "); - - gst_element_class_add_pad_template (gstelement_class, - gst_static_pad_template_get (&gst_pinos_port_src_template)); - - gstbasesrc_class->get_caps = gst_pinos_port_src_getcaps; - gstbasesrc_class->unlock = gst_pinos_port_src_unlock; - gstbasesrc_class->unlock_stop = gst_pinos_port_src_unlock_stop; - gstbasesrc_class->start = gst_pinos_port_src_start; - gstbasesrc_class->stop = gst_pinos_port_src_stop; - gstbasesrc_class->event = gst_pinos_port_src_event; - gstbasesrc_class->query = gst_pinos_port_src_query; - gstpushsrc_class->create = gst_pinos_port_src_create; - - GST_DEBUG_CATEGORY_INIT (pinos_port_src_debug, "pinosportsrc", 0, - "Pinos Source"); - - process_mem_data_quark = g_quark_from_static_string ("GstPinosPortSrcProcessMemQuark"); -} - -static void -gst_pinos_port_src_init (GstPinosPortSrc * src) -{ - /* we operate in time */ - gst_base_src_set_format (GST_BASE_SRC (src), GST_FORMAT_TIME); - - GST_OBJECT_FLAG_SET (src, GST_ELEMENT_FLAG_PROVIDE_CLOCK); - - g_cond_init (&src->cond); - g_queue_init (&src->queue); - - src->fd_allocator = gst_fd_allocator_new (); - src->mem_ids = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, (GDestroyNotify) gst_memory_unref); -} - -static void -parse_stream_properties (GstPinosPortSrc *this, PinosProperties *props) -{ - const gchar *var; - - var = pinos_properties_get (props, "pinos.latency.is-live"); - this->is_live = var ? (atoi (var) == 1) : FALSE; - gst_base_src_set_live (GST_BASE_SRC (this), this->is_live); - - var = pinos_properties_get (props, "pinos.latency.min"); - this->min_latency = var ? (GstClockTime) atoi (var) : 0; - - var = pinos_properties_get (props, "pinos.latency.max"); - this->max_latency = var ? (GstClockTime) atoi (var) : GST_CLOCK_TIME_NONE; - - var = pinos_properties_get (props, "pinos.clock.type"); - if (var != NULL) { - GST_DEBUG_OBJECT (this, "got clock type %s", var); - if (strcmp (var, "gst.net.time.provider") == 0) { - const gchar *address; - gint port; - GstClockTime base_time; - - address = pinos_properties_get (props, "pinos.clock.address"); - port = atoi (pinos_properties_get (props, "pinos.clock.port")); - base_time = atoll (pinos_properties_get (props, "pinos.clock.base-time")); - - GST_DEBUG_OBJECT (this, "making net clock for %s:%d %" G_GUINT64_FORMAT, address, port, base_time); - if (this->clock) - gst_object_unref (this->clock); - this->clock = gst_net_client_clock_new ("pinosclock", address, port, base_time); - - gst_element_post_message (GST_ELEMENT_CAST (this), - gst_message_new_clock_provide (GST_OBJECT_CAST (this), - this->clock, TRUE)); - } - } -} - -static GstCaps * -gst_pinos_port_src_getcaps (GstBaseSrc * bsrc, GstCaps * filter) -{ - GstPinosPortSrc *this = GST_PINOS_PORT_SRC (bsrc); - GBytes *format; - GstCaps *caps = NULL; - - GST_DEBUG ("getting caps"); - - g_object_get (this->port, "format", &format, NULL); - if (format) { - 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); - } - return caps; -} - -static gboolean -gst_pinos_port_src_event (GstBaseSrc * src, GstEvent * event) -{ - gboolean res = FALSE; - GstPinosPortSrc *this; - - this = GST_PINOS_PORT_SRC (src); - - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_CUSTOM_UPSTREAM: - if (gst_video_event_is_force_key_unit (event)) { - GstClockTime running_time; - gboolean all_headers; - guint count; - PinosPacketRefreshRequest refresh; - PinosBufferBuilder b; - PinosBuffer pbuf; - - gst_video_event_parse_upstream_force_key_unit (event, - &running_time, &all_headers, &count); - - 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_DEBUG_OBJECT (this, "send refresh request"); - pinos_port_send_buffer (this->port, &pbuf, NULL); - pinos_buffer_unref (&pbuf); - res = TRUE; - } else { - res = GST_BASE_SRC_CLASS (parent_class)->event (src, event); - } - break; - default: - res = GST_BASE_SRC_CLASS (parent_class)->event (src, event); - break; - } - return res; -} - -static gboolean -gst_pinos_port_src_query (GstBaseSrc * src, GstQuery * query) -{ - gboolean res = FALSE; - GstPinosPortSrc *this; - - this = GST_PINOS_PORT_SRC (src); - - switch (GST_QUERY_TYPE (query)) { - case GST_QUERY_LATENCY: - gst_query_set_latency (query, this->is_live, this->min_latency, this->max_latency); - res = TRUE; - break; - default: - res = GST_BASE_SRC_CLASS (parent_class)->query (src, query); - break; - } - return res; -} - -static GstFlowReturn -gst_pinos_port_src_create (GstPushSrc * psrc, GstBuffer ** buffer) -{ - GstPinosPortSrc *this; - GstClockTime pts, dts, base_time; - - this = GST_PINOS_PORT_SRC (psrc); - - GST_OBJECT_LOCK (this); - while (TRUE) { - if (this->flushing) - goto streaming_stopped; - - *buffer = g_queue_pop_head (&this->queue); - if (*buffer != NULL) - break; - - g_cond_wait (&this->cond, GST_OBJECT_GET_LOCK (this)); - } - GST_OBJECT_UNLOCK (this); - - base_time = GST_ELEMENT_CAST (psrc)->base_time; - pts = GST_BUFFER_PTS (*buffer); - dts = GST_BUFFER_DTS (*buffer); - - if (GST_CLOCK_TIME_IS_VALID (pts)) - pts = (pts >= base_time ? pts - base_time : 0); - if (GST_CLOCK_TIME_IS_VALID (dts)) - dts = (dts >= base_time ? dts - base_time : 0); - - GST_INFO ("pts %" G_GUINT64_FORMAT ", dts %"G_GUINT64_FORMAT - ", base-time %"GST_TIME_FORMAT" -> %"GST_TIME_FORMAT", %"GST_TIME_FORMAT, - GST_BUFFER_PTS (*buffer), GST_BUFFER_DTS (*buffer), GST_TIME_ARGS (base_time), - GST_TIME_ARGS (pts), GST_TIME_ARGS (dts)); - - GST_BUFFER_PTS (*buffer) = pts; - GST_BUFFER_DTS (*buffer) = dts; - - return GST_FLOW_OK; - -streaming_stopped: - { - GST_OBJECT_UNLOCK (this); - return GST_FLOW_FLUSHING; - } -} - -static gboolean -gst_pinos_port_src_start (GstBaseSrc * basesrc) -{ - PinosProperties *props; - GstPinosPortSrc *this; - - this = GST_PINOS_PORT_SRC (basesrc); - - props = pinos_port_get_properties (this->port); - if (props) - parse_stream_properties (this, props); - - return TRUE; -} - -static void -clear_queue (GstPinosPortSrc *this) -{ - g_queue_foreach (&this->queue, (GFunc) gst_mini_object_unref, NULL); - g_queue_clear (&this->queue); -} - -static gboolean -gst_pinos_port_src_stop (GstBaseSrc * basesrc) -{ - GstPinosPortSrc *this; - - this = GST_PINOS_PORT_SRC (basesrc); - - clear_queue (this); - - return TRUE; -} - -static GstStateChangeReturn -gst_pinos_port_src_change_state (GstElement * element, GstStateChange transition) -{ - GstStateChangeReturn ret; - - switch (transition) { - case GST_STATE_CHANGE_NULL_TO_READY: - break; - case GST_STATE_CHANGE_READY_TO_PAUSED: - break; - case GST_STATE_CHANGE_PAUSED_TO_PLAYING: - /* uncork and start recording */ - break; - case GST_STATE_CHANGE_PLAYING_TO_PAUSED: - /* stop recording ASAP by corking */ - break; - default: - break; - } - - ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); - - switch (transition) { - case GST_STATE_CHANGE_READY_TO_PAUSED: - if (gst_base_src_is_live (GST_BASE_SRC (element))) - ret = GST_STATE_CHANGE_NO_PREROLL; - break; - case GST_STATE_CHANGE_PLAYING_TO_PAUSED: - break; - case GST_STATE_CHANGE_PAUSED_TO_READY: - break; - case GST_STATE_CHANGE_READY_TO_NULL: - break; - default: - break; - } - return ret; -} diff --git a/pinos/gst/gstpinosportsrc.h b/pinos/gst/gstpinosportsrc.h deleted file mode 100644 index a7f04c1ee..000000000 --- a/pinos/gst/gstpinosportsrc.h +++ /dev/null @@ -1,82 +0,0 @@ -/* GStreamer - * 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 __GST_PINOS_PORT_SRC_H__ -#define __GST_PINOS_PORT_SRC_H__ - -#include -#include - -#include -#include - -G_BEGIN_DECLS - -#define GST_TYPE_PINOS_PORT_SRC \ - (gst_pinos_port_src_get_type()) -#define GST_PINOS_PORT_SRC(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_PINOS_PORT_SRC,GstPinosPortSrc)) -#define GST_PINOS_PORT_SRC_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_PINOS_PORT_SRC,GstPinosPortSrcClass)) -#define GST_IS_PINOS_PORT_SRC(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_PINOS_PORT_SRC)) -#define GST_IS_PINOS_PORT_SRC_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_PINOS_PORT_SRC)) -#define GST_PINOS_PORT_SRC_CAST(obj) \ - ((GstPinosPortSrc *) (obj)) - -typedef struct _GstPinosPortSrc GstPinosPortSrc; -typedef struct _GstPinosPortSrcClass GstPinosPortSrcClass; - -/** - * GstPinosPortSrc: - * - * Opaque data structure. - */ -struct _GstPinosPortSrc { - GstPushSrc element; - - /*< private >*/ - PinosPort *port; - - gboolean negotiated; - gboolean flushing; - gboolean started; - - gboolean is_live; - GstClockTime min_latency; - GstClockTime max_latency; - GstClock *clock; - - GstAllocator *fd_allocator; - GHashTable *mem_ids; - - GQueue queue; - GCond cond; -}; - -struct _GstPinosPortSrcClass { - GstPushSrcClass parent_class; -}; - -GType gst_pinos_port_src_get_type (void); - -G_END_DECLS - -#endif /* __GST_PINOS_PORT_SRC_H__ */ diff --git a/pinos/gst/gstpinossink.c b/pinos/gst/gstpinossink.c index d95eded3e..d24c1fe48 100644 --- a/pinos/gst/gstpinossink.c +++ b/pinos/gst/gstpinossink.c @@ -45,7 +45,6 @@ #include -#include "gsttmpfileallocator.h" #include "gstpinosformat.h" static GQuark process_mem_data_quark; @@ -216,7 +215,7 @@ gst_pinos_sink_class_init (GstPinosSinkClass * klass) static void gst_pinos_sink_init (GstPinosSink * sink) { - sink->allocator = gst_tmpfile_allocator_new (); + sink->allocator = gst_fd_allocator_new (); sink->pool = gst_pinos_pool_new (); sink->client_name = pinos_client_name(); sink->mode = DEFAULT_PROP_MODE; diff --git a/pinos/gst/gstpinossocketsink.c b/pinos/gst/gstpinossocketsink.c deleted file mode 100644 index 7c3a85607..000000000 --- a/pinos/gst/gstpinossocketsink.c +++ /dev/null @@ -1,904 +0,0 @@ -/* GStreamer - * Copyright (C) <2016> Wim Taymans - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -/** - * SECTION:element-pinossocketsink - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include -#include -#include - -#include - -#include -#include -#include - -#include "gstpinossocketsink.h" -#include "gsttmpfileallocator.h" - -typedef struct _MyReader MyReader; -typedef struct _MySource MySource; - -struct _MyReader { - GstBurstCacheReader reader; - GSocket *socket; - MySource *source; - guint id; -}; - -struct _MySource { - GSource source; - GIOCondition condition; - gpointer tag; - MyReader *reader; -}; - -typedef gboolean (*MyReaderSourceFunc) (MyReader *reader, GIOCondition condition, gpointer user_data); - -static gboolean -mysource_dispatch (GSource *source, - GSourceFunc callback, - gpointer user_data) -{ - MyReaderSourceFunc func = (MyReaderSourceFunc)callback; - MySource *mysource = (MySource *)source; - MyReader *myreader = mysource->reader; - guint events; - gboolean ret; - - events = g_source_query_unix_fd (source, mysource->tag); - - ret = (*func) (myreader, events, user_data); - - return ret; -} - -static GSourceFuncs mysource_funcs = -{ - NULL, NULL, /* check, prepare */ - mysource_dispatch, - NULL, /* finalize */ - NULL, - NULL, -}; - -static GQuark fdids_quark; -static GQuark orig_buffer_quark; - -GST_DEBUG_CATEGORY_STATIC (pinos_socket_sink_debug); -#define GST_CAT_DEFAULT pinos_socket_sink_debug - -static GstStaticPadTemplate gst_pinos_socket_sink_template = -GST_STATIC_PAD_TEMPLATE ("sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS_ANY - ); - -enum -{ - PROP_0, - - PROP_NUM_HANDLES, -}; - -/* PinosSocketSink signals and args */ -enum -{ - /* methods */ - SIGNAL_ADD, - SIGNAL_REMOVE, - - LAST_SIGNAL -}; - -static guint gst_pinos_socket_sink_signals[LAST_SIGNAL] = { 0 }; - -#define gst_pinos_socket_sink_parent_class parent_class -G_DEFINE_TYPE (GstPinosSocketSink, gst_pinos_socket_sink, GST_TYPE_BASE_SINK); - -static gboolean -gst_pinos_socket_sink_propose_allocation (GstBaseSink * bsink, GstQuery * query) -{ - GstPinosSocketSink *this = GST_PINOS_SOCKET_SINK (bsink); - - gst_query_add_allocation_param (query, this->allocator, NULL); - gst_query_add_allocation_meta (query, GST_NET_CONTROL_MESSAGE_META_API_TYPE, - NULL); - - return TRUE; -} - -static void -gst_pinos_socket_sink_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - switch (prop_id) { - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gst_pinos_socket_sink_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec) -{ - GstPinosSocketSink *this = GST_PINOS_SOCKET_SINK (object); - - switch (prop_id) { - case PROP_NUM_HANDLES: - g_value_set_uint (value, g_hash_table_size (this->hash)); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static gboolean -gst_pinos_socket_sink_setcaps (GstBaseSink * bsink, GstCaps * caps) -{ - GstPinosSocketSink *this = GST_PINOS_SOCKET_SINK (bsink); - GstStructure *str; - - str = gst_caps_get_structure (caps, 0); - this->pinos_input = gst_structure_has_name (str, "application/x-pinos"); - - return GST_BASE_SINK_CLASS (parent_class)->set_caps (bsink, caps); -} - -static void -reuse_fds (GstPinosSocketSink *this, GstBuffer *buffer) -{ - GArray *fdids; - guint i; - PinosBufferBuilder b; - PinosPacketReuseMem r; - PinosBuffer pbuf; - gsize size; - gpointer data; - GstBuffer *outbuf; - GstEvent *ev; - - fdids = gst_mini_object_steal_qdata (GST_MINI_OBJECT_CAST (buffer), - fdids_quark); - if (fdids == NULL) - return; - - pinos_buffer_builder_init (&b); - - for (i = 0; i < fdids->len; i++) { - r.id = g_array_index (fdids, guint32, i); - GST_LOG ("reuse fd index %d", r.id); - pinos_buffer_builder_add_reuse_mem (&b, &r); - } - pinos_buffer_builder_end (&b, &pbuf); - g_array_unref (fdids); - - data = pinos_buffer_steal_data (&pbuf, &size); - - outbuf = gst_buffer_new_wrapped (data, size); - ev = gst_event_new_custom (GST_EVENT_CUSTOM_UPSTREAM, - gst_structure_new ("GstNetworkMessage", - "object", G_TYPE_OBJECT, this, - "buffer", GST_TYPE_BUFFER, outbuf, NULL)); - gst_buffer_unref (outbuf); - - gst_pad_push_event (GST_BASE_SINK_PAD (this), ev); - g_object_unref (this); -} - -static GstFlowReturn -gst_pinos_socket_sink_render_pinos (GstPinosSocketSink * this, GstBuffer * buffer) -{ - GstMapInfo info; - PinosBuffer pbuf; - PinosBufferIter it; - GArray *fdids = NULL; - - gst_buffer_map (buffer, &info, GST_MAP_READ); - pinos_buffer_init_data (&pbuf, info.data, info.size, NULL, 0); - pinos_buffer_iter_init (&it, &pbuf); - while (pinos_buffer_iter_next (&it)) { - switch (pinos_buffer_iter_get_type (&it)) { - case PINOS_PACKET_TYPE_PROCESS_MEM: - { - PinosPacketProcessMem p; - - if (!pinos_buffer_iter_parse_process_mem (&it, &p)) - continue; - - if (fdids == NULL) - fdids = g_array_new (FALSE, FALSE, sizeof (guint32)); - - GST_LOG ("track fd id %d", p.id); - g_array_append_val (fdids, p.id); - break; - } - case PINOS_PACKET_TYPE_FORMAT_CHANGE: - { - PinosPacketFormatChange p; - GstCaps * caps; - - if (!pinos_buffer_iter_parse_format_change (&it, &p)) - continue; - - caps = gst_caps_from_string (p.format); - - gst_element_post_message (GST_ELEMENT (this), - gst_message_new_element (GST_OBJECT (this), - gst_structure_new ("PinosPayloaderFormatChange", - "format", GST_TYPE_CAPS, caps, NULL))); - gst_caps_unref (caps); - break; - } - default: - break; - } - } - pinos_buffer_iter_end (&it); - pinos_buffer_unref (&pbuf); - gst_buffer_unmap (buffer, &info); - - if (fdids != NULL) { - gst_mini_object_set_qdata (GST_MINI_OBJECT_CAST (buffer), - fdids_quark, fdids, NULL); - gst_mini_object_weak_ref (GST_MINI_OBJECT_CAST (buffer), - (GstMiniObjectNotify) reuse_fds, g_object_ref (this)); - } - gst_burst_cache_queue_buffer (this->cache, gst_buffer_ref (buffer)); - - return GST_FLOW_OK; -} - -static GstMemory * -gst_pinos_socket_sink_get_fd_memory (GstPinosSocketSink * this, GstBuffer * buffer, gboolean *tmpfile) -{ - GstMemory *mem = NULL; - - if (gst_buffer_n_memory (buffer) == 1 - && gst_is_fd_memory (gst_buffer_peek_memory (buffer, 0))) { - mem = gst_buffer_get_memory (buffer, 0); - *tmpfile = gst_is_tmpfile_memory (mem); - } else { - GstMapInfo info; - GstAllocationParams params = {0, 0, 0, 0, { NULL, }}; - gsize size = gst_buffer_get_size (buffer); - GST_INFO_OBJECT (this, "Buffer cannot be sent without copying"); - mem = gst_allocator_alloc (this->allocator, size, ¶ms); - if (!gst_memory_map (mem, &info, GST_MAP_WRITE)) - return NULL; - gst_buffer_extract (buffer, 0, info.data, size); - gst_memory_unmap (mem, &info); - *tmpfile = TRUE; - } - return mem; -} - -static GstFlowReturn -gst_pinos_socket_sink_render_other (GstPinosSocketSink * this, GstBuffer * buffer) -{ - GstMemory *fdmem = NULL; - GError *err = NULL; - GstBuffer *outbuf; - PinosBuffer pbuf; - PinosBufferBuilder builder; - PinosPacketHeader hdr; - PinosPacketAddMem am; - PinosPacketProcessMem p; - PinosPacketRemoveMem rm; - gsize size; - gpointer data; - GSocketControlMessage *msg; - gboolean tmpfile = TRUE; - gint *fds, n_fds, i; - - 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_buffer_builder_add_header (&builder, &hdr); - - fdmem = gst_pinos_socket_sink_get_fd_memory (this, buffer, &tmpfile); - - am.id = pinos_fd_manager_get_id (this->fdmanager); - am.fd_index = pinos_buffer_builder_add_fd (&builder, gst_fd_memory_get_fd (fdmem)); - am.offset = 0; - am.size = fdmem->size; - p.id = am.id; - p.offset = fdmem->offset; - p.size = fdmem->size; - rm.id = am.id; - pinos_buffer_builder_add_add_mem (&builder, &am); - pinos_buffer_builder_add_process_mem (&builder, &p); - pinos_buffer_builder_add_remove_mem (&builder, &rm); - pinos_buffer_builder_end (&builder, &pbuf); - - GST_LOG ("send %d %"G_GUINT64_FORMAT" %"G_GUINT64_FORMAT" %"G_GUINT64_FORMAT, - p.id, hdr.pts, GST_BUFFER_PTS (buffer), GST_ELEMENT_CAST (this)->base_time); - - 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); - GST_BUFFER_DTS (outbuf) = GST_BUFFER_DTS (buffer); - GST_BUFFER_DURATION (outbuf) = GST_BUFFER_DURATION (buffer); - GST_BUFFER_OFFSET (outbuf) = GST_BUFFER_OFFSET (buffer); - GST_BUFFER_OFFSET_END (outbuf) = GST_BUFFER_OFFSET_END (buffer); - - msg = g_unix_fd_message_new (); - for (i = 0; i < n_fds; i++) { - if (!g_unix_fd_message_append_fd (G_UNIX_FD_MESSAGE (msg), fds[i], &err)) - goto add_fd_failed; - } - gst_buffer_add_net_control_message_meta (outbuf, msg); - g_object_unref (msg); - g_free (fds); - - gst_memory_unref(fdmem); - fdmem = NULL; - - if (!tmpfile) { - GArray *fdids; - /* we are using the original buffer fd in the control message, we need - * to make sure it is not reused before everyone is finished with it. - * We tag the output buffer with the array of fds in it and the original - * buffer (to keep it alive). All clients that receive the fd will - * increment outbuf refcount, all clients that do release-fd on the fd - * will decrease the refcount again. */ - fdids = g_array_new (FALSE, FALSE, sizeof (guint32)); - g_array_append_val (fdids, p.id); - gst_mini_object_set_qdata (GST_MINI_OBJECT_CAST (outbuf), - fdids_quark, fdids, (GDestroyNotify) g_array_unref); - gst_mini_object_set_qdata (GST_MINI_OBJECT_CAST (outbuf), - orig_buffer_quark, gst_buffer_ref (buffer), (GDestroyNotify) gst_buffer_unref); - } - - gst_burst_cache_queue_buffer (this->cache, outbuf); - - return GST_FLOW_OK; - - /* ERRORS */ -add_fd_failed: - { - GST_WARNING_OBJECT (this, "Adding fd failed: %s", err->message); - gst_memory_unref(fdmem); - g_clear_error (&err); - - return GST_FLOW_ERROR; - } -} - -static GstFlowReturn -gst_pinos_socket_sink_render (GstBaseSink * bsink, GstBuffer * buffer) -{ - GstPinosSocketSink *this = GST_PINOS_SOCKET_SINK (bsink); - - if (this->pinos_input) - return gst_pinos_socket_sink_render_pinos (this, buffer); - else - return gst_pinos_socket_sink_render_other (this, buffer); -} - -static gboolean -gst_pinos_socket_sink_start (GstBaseSink * basesink) -{ - return TRUE; -} - -static gboolean -gst_pinos_socket_sink_stop (GstBaseSink * basesink) -{ - return TRUE; -} - -static gpointer -socketsink_loop (GstPinosSocketSink * this) -{ - g_main_loop_run (this->loop); - return NULL; -} - -static gboolean -gst_pinos_socket_sink_open (GstPinosSocketSink * this) -{ - GError *error = NULL; - - this->context = g_main_context_new (); - this->loop = g_main_loop_new (this->context, TRUE); - GST_DEBUG ("context %p, loop %p", this->context, this->loop); - - this->thread = g_thread_try_new ("PinosSocketSink", - (GThreadFunc) socketsink_loop, - this, - &error); - if (this->thread == NULL) - goto thread_error; - - return TRUE; - - /* ERRORS */ -thread_error: - { - GST_ELEMENT_ERROR (this, RESOURCE, FAILED, - ("Failed to start mainloop thread: %s", error->message), (NULL)); - g_clear_error (&error); - g_clear_pointer (&this->loop, g_main_loop_unref); - g_clear_pointer (&this->context, g_main_context_unref); - return FALSE; - } -} - -static gboolean -gst_pinos_socket_sink_close (GstPinosSocketSink * this) -{ - gst_burst_cache_remove_buffers (this->cache); - - GST_DEBUG ("context %p, loop %p", this->context, this->loop); - g_main_loop_quit (this->loop); - g_thread_join (this->thread); - this->thread = NULL; - g_clear_pointer (&this->loop, g_main_loop_unref); - g_clear_pointer (&this->context, g_main_context_unref); - g_hash_table_remove_all (this->hash); - - return TRUE; -} - -static GstStateChangeReturn -gst_pinos_socket_sink_change_state (GstElement * element, GstStateChange transition) -{ - GstStateChangeReturn ret; - GstPinosSocketSink *this = GST_PINOS_SOCKET_SINK_CAST (element); - - switch (transition) { - case GST_STATE_CHANGE_NULL_TO_READY: - if (!gst_pinos_socket_sink_open (this)) - goto open_failed; - break; - case GST_STATE_CHANGE_READY_TO_PAUSED: - break; - case GST_STATE_CHANGE_PAUSED_TO_PLAYING: - break; - case GST_STATE_CHANGE_PLAYING_TO_PAUSED: - break; - default: - break; - } - - ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); - - switch (transition) { - case GST_STATE_CHANGE_PLAYING_TO_PAUSED: - break; - case GST_STATE_CHANGE_PAUSED_TO_READY: - break; - case GST_STATE_CHANGE_READY_TO_NULL: - gst_pinos_socket_sink_close (this); - break; - default: - break; - } - return ret; - - /* ERRORS */ -open_failed: - { - return GST_STATE_CHANGE_FAILURE; - } -} - -static void -myreader_receive_buffer (GstPinosSocketSink *this, MyReader *myreader) -{ - MySource *mysource = myreader->source; - gssize navail, nread, maxmem; - GstEvent *ev; - gchar *mem; - PinosBuffer pbuf; - PinosBufferIter it; - PinosBufferBuilder b; - const gchar *client_path; - gboolean have_out = FALSE; - - navail = g_socket_get_available_bytes (myreader->socket); - maxmem = MAX (navail, 1); - mem = g_malloc (maxmem); - nread = g_socket_receive (myreader->socket, mem, maxmem, NULL, NULL); - - if (nread <= 0) { - GST_DEBUG ("client closed"); - mysource->condition &= ~G_IO_IN; - g_source_modify_unix_fd ((GSource *)mysource, mysource->tag, mysource->condition); - g_free (mem); - return; - } - - client_path = g_object_get_data (G_OBJECT (myreader->socket), "pinos-client-path"); - if (client_path == NULL) - return; - - if (this->pinos_input) { - pinos_buffer_builder_init (&b); - } - - pinos_buffer_init_data (&pbuf, mem, maxmem, NULL, 0); - pinos_buffer_iter_init (&it, &pbuf); - while (pinos_buffer_iter_next (&it)) { - switch (pinos_buffer_iter_get_type (&it)) { - case PINOS_PACKET_TYPE_REUSE_MEM: - { - PinosPacketReuseMem p; - gint id; - - if (!pinos_buffer_iter_parse_reuse_mem (&it, &p)) - continue; - - id = p.id; - - GST_LOG ("fd id %d for client %s is reused", id, client_path); - pinos_fd_manager_remove (this->fdmanager, client_path, id); - break; - } - case PINOS_PACKET_TYPE_REFRESH_REQUEST: - { - PinosPacketRefreshRequest p; - - if (!pinos_buffer_iter_parse_refresh_request (&it, &p)) - continue; - - GST_LOG ("refresh request"); - if (!this->pinos_input) { - gst_pad_push_event (GST_BASE_SINK_PAD (this), - gst_video_event_new_upstream_force_key_unit (p.pts, - p.request_type == 1, 0)); - } else { - pinos_buffer_builder_add_refresh_request (&b, &p); - have_out = TRUE; - } - break; - } - default: - break; - } - } - pinos_buffer_iter_end (&it); - pinos_buffer_unref (&pbuf); - g_free (mem); - - if (this->pinos_input) { - GstBuffer *outbuf; - gsize size; - gpointer data; - - if (have_out) { - pinos_buffer_builder_end (&b, &pbuf); - - data = pinos_buffer_steal_data (&pbuf, &size); - - outbuf = gst_buffer_new_wrapped (data, size); - ev = gst_event_new_custom (GST_EVENT_CUSTOM_UPSTREAM, - gst_structure_new ("GstNetworkMessage", - "object", G_TYPE_OBJECT, this, - "buffer", GST_TYPE_BUFFER, outbuf, NULL)); - gst_buffer_unref (outbuf); - - gst_pad_push_event (GST_BASE_SINK_PAD (this), ev); - } else { - pinos_buffer_builder_clear (&b); - } - } -} - -static void -myreader_callback (GstBurstCache *cache, - GstBurstCacheReader *reader, - gpointer user_data) -{ - MyReader *myreader = (MyReader *) reader; - MySource *mysource = myreader->source; - - GST_LOG ("%p: callback", reader); - mysource->condition |= G_IO_OUT; - g_source_modify_unix_fd ((GSource *)mysource, mysource->tag, mysource->condition); -} - -#define VEC_MAX 8 -#define CMSG_MAX 255 - -static void -myreader_send_buffer (GstPinosSocketSink *this, MyReader *myreader, GstBuffer *buf) -{ - GstMapInfo maps[VEC_MAX]; - GOutputVector vec[VEC_MAX]; - GSocketControlMessage *cmsgs[CMSG_MAX]; - guint i, mem_len; - gpointer iter_state = NULL; - GstMeta *meta; - gsize msg_count = 0; - gssize wrote; - - mem_len = MIN (gst_buffer_n_memory (buf), VEC_MAX); - - for (i = 0; i < mem_len; i++) { - GstMapInfo map = { 0 }; - GstMemory *mem = gst_buffer_peek_memory (buf, i); - - if (!gst_memory_map (mem, &map, GST_MAP_READ)) - g_error ("Unable to map memory %p. This should never happen.", mem); - - vec[i].buffer = map.data; - vec[i].size = map.size; - - maps[i] = map; - } - while ((meta = gst_buffer_iterate_meta (buf, &iter_state)) != NULL - && msg_count < CMSG_MAX) { - if (meta->info->api == GST_NET_CONTROL_MESSAGE_META_API_TYPE) - cmsgs[msg_count++] = ((GstNetControlMessageMeta *) meta)->message; - } - - wrote = g_socket_send_message (myreader->socket, NULL, vec, mem_len, cmsgs, msg_count, 0, - NULL, NULL); - - for (i = 0; i < mem_len; i++) - gst_memory_unmap (maps[i].memory, &maps[i]); - - if (wrote < 0) { - GST_DEBUG_OBJECT (this, "error sending to reader"); - } else { - GArray *fdids; - const gchar *client_path; - - fdids = gst_mini_object_get_qdata (GST_MINI_OBJECT_CAST (buf), fdids_quark); - if (fdids == NULL) - return; - - /* get the client path of this socket */ - client_path = g_object_get_data (G_OBJECT (myreader->socket), "pinos-client-path"); - if (client_path == NULL) - return; - - for (i = 0; i < fdids->len; i++) { - gint id = g_array_index (fdids, guint32, i); - /* now store the id/client-path/buffer in the fdmanager */ - GST_LOG ("fd index %d, client %s increment refcount of buffer %p", id, client_path, buf); - pinos_fd_manager_add (this->fdmanager, - client_path, id, - gst_buffer_ref (buf), - (GDestroyNotify) gst_buffer_unref); - } - } -} - -static gboolean -myreader_source_func (GstBurstCacheReader *reader, GIOCondition condition, gpointer user_data) -{ - GstPinosSocketSink *this = user_data; - MyReader *myreader = (MyReader *) reader; - MySource *mysource = myreader->source; - - GST_LOG ("%p: io condition %d", reader, condition); - - if (condition & (G_IO_HUP | G_IO_ERR)) { - GST_DEBUG ("client error"); - return FALSE; - } - if (condition & G_IO_IN) { - myreader_receive_buffer (this, myreader); - } - if (condition & G_IO_OUT) { - GstBuffer *buf = NULL; - GstBurstCacheResult res; - - res = gst_burst_cache_get_buffer (this->cache, reader, &buf); - - switch (res) { - case GST_BURST_CACHE_RESULT_ERROR: - break; - case GST_BURST_CACHE_RESULT_OK: - break; - case GST_BURST_CACHE_RESULT_WAIT: - mysource->condition &= ~G_IO_OUT; - g_source_modify_unix_fd ((GSource *)mysource, mysource->tag, mysource->condition); - break; - case GST_BURST_CACHE_RESULT_EOS: - gst_burst_cache_remove_reader (this->cache, reader, FALSE); - break; - } - if (buf) { - myreader_send_buffer (this, myreader, buf); - gst_buffer_unref (buf); - } - } - - return TRUE; -} - -static void -myreader_destroy (MyReader *myreader) -{ - gst_burst_cache_reader_destroy ((GstBurstCacheReader *)myreader); - g_clear_object (&myreader->socket); - g_source_destroy ((GSource*) myreader->source); - myreader->id = 0; -} - -static void -gst_pinos_socket_sink_add (GstPinosSocketSink * this, GSocket *socket) -{ - GstBurstCacheReader *reader; - MyReader *myreader; - MySource *mysource; - int fd; - - fd = g_socket_get_fd (socket); - - if (g_hash_table_lookup (this->hash, GINT_TO_POINTER (fd))) - return; - - reader = gst_burst_cache_reader_new (this->cache, - (GstBurstCacheReaderCallback) myreader_callback, - this, - NULL); - - reader->hook.destroy = (GDestroyNotify) myreader_destroy; - myreader = (MyReader *)reader; - myreader->socket = g_object_ref (socket); - - mysource = (MySource*) g_source_new (&mysource_funcs, sizeof (MySource)); - mysource->reader = myreader; - mysource->condition = G_IO_IN; - mysource->tag = g_source_add_unix_fd ((GSource*)mysource, fd, mysource->condition); - - myreader->source = mysource; - g_source_set_callback ((GSource*)mysource, - (GSourceFunc) myreader_source_func, - this, NULL); - myreader->id = g_source_attach ((GSource*)mysource, this->context); - - g_hash_table_insert (this->hash, GINT_TO_POINTER (fd), reader); - - gst_burst_cache_add_reader (this->cache, reader); -} - -static void -gst_pinos_socket_sink_remove (GstPinosSocketSink * this, GSocket *socket, gboolean drain) -{ - GstBurstCacheReader *reader; - MyReader *myreader; - int fd; - - fd = g_socket_get_fd (socket); - - myreader = g_hash_table_lookup (this->hash, GINT_TO_POINTER (fd)); - if (myreader == NULL) - return; - - g_hash_table_remove (this->hash, GINT_TO_POINTER (fd)); - - reader = (GstBurstCacheReader *) myreader; - gst_burst_cache_remove_reader (this->cache, reader, drain); -} - -static void -gst_pinos_socket_sink_finalize (GObject * object) -{ - GstPinosSocketSink *this = GST_PINOS_SOCKET_SINK (object); - - g_clear_pointer (&this->hash, g_hash_table_unref); - g_clear_pointer (&this->cache, g_object_unref); - - G_OBJECT_CLASS (parent_class)->finalize (object); -} - -static void -gst_pinos_socket_sink_class_init (GstPinosSocketSinkClass * klass) -{ - GObjectClass *gobject_class; - GstElementClass *gstelement_class; - GstBaseSinkClass *gstbasesink_class; - - gobject_class = (GObjectClass *) klass; - gstelement_class = (GstElementClass *) klass; - gstbasesink_class = (GstBaseSinkClass *) klass; - - gobject_class->finalize = gst_pinos_socket_sink_finalize; - gobject_class->set_property = gst_pinos_socket_sink_set_property; - gobject_class->get_property = gst_pinos_socket_sink_get_property; - - g_object_class_install_property (gobject_class, PROP_NUM_HANDLES, - g_param_spec_uint ("num-handles", "Number of handles", - "The current number of client handles", - 0, G_MAXUINT, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); - - gstelement_class->change_state = gst_pinos_socket_sink_change_state; - - /** - * GstPinosSocketSink::add: - * @gstpinossocketsink: the pinossocketsink element to emit this signal on - * @socket: the socket to add to pinossocketsink - * - * Hand the given open file descriptor to pinossocketsink to write to. - */ - gst_pinos_socket_sink_signals[SIGNAL_ADD] = - g_signal_new ("add", G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, - G_STRUCT_OFFSET (GstPinosSocketSinkClass, add), NULL, NULL, - g_cclosure_marshal_generic, G_TYPE_NONE, 1, G_TYPE_SOCKET); - - /** - * GstPinosSocketSink::remove: - * @gstpinossocketsink: the pinossocketsink element to emit this signal on - * @socket: the socket to remove from pinossocketsink - * @drain: if pending data should be written first. - * - * Remove the given open file descriptor from pinossocketsink. - */ - gst_pinos_socket_sink_signals[SIGNAL_REMOVE] = - g_signal_new ("remove", G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, - G_STRUCT_OFFSET (GstPinosSocketSinkClass, remove), NULL, NULL, - g_cclosure_marshal_generic, G_TYPE_NONE, 2, G_TYPE_SOCKET, G_TYPE_BOOLEAN); - - gst_element_class_set_static_metadata (gstelement_class, - "Pinos FD sink", "Sink/Video", - "Send data to pinos clients", "Wim Taymans "); - - gst_element_class_add_pad_template (gstelement_class, - gst_static_pad_template_get (&gst_pinos_socket_sink_template)); - - gstbasesink_class->set_caps = gst_pinos_socket_sink_setcaps; - gstbasesink_class->propose_allocation = gst_pinos_socket_sink_propose_allocation; - gstbasesink_class->start = gst_pinos_socket_sink_start; - gstbasesink_class->stop = gst_pinos_socket_sink_stop; - gstbasesink_class->render = gst_pinos_socket_sink_render; - - klass->add = GST_DEBUG_FUNCPTR (gst_pinos_socket_sink_add); - klass->remove = GST_DEBUG_FUNCPTR (gst_pinos_socket_sink_remove); - - fdids_quark = g_quark_from_static_string ("GstPinosSocketSinkFDIds"); - orig_buffer_quark = g_quark_from_static_string ("GstPinosSocketSinkOrigBuffer"); - - GST_DEBUG_CATEGORY_INIT (pinos_socket_sink_debug, "pinossocketsink", 0, - "Pinos Socket Sink"); -} - -static void -gst_pinos_socket_sink_init (GstPinosSocketSink * this) -{ - this->hash = g_hash_table_new (g_direct_hash, g_direct_equal); - this->cache = gst_burst_cache_new (sizeof (MyReader)); - this->allocator = gst_tmpfile_allocator_new (); - this->fdmanager = pinos_fd_manager_get (PINOS_FD_MANAGER_DEFAULT); -} diff --git a/pinos/gst/gstpinossocketsink.h b/pinos/gst/gstpinossocketsink.h deleted file mode 100644 index e890b5002..000000000 --- a/pinos/gst/gstpinossocketsink.h +++ /dev/null @@ -1,74 +0,0 @@ -/* GStreamer - * Copyright (C) <2016> Wim Taymans - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef __GST_PINOS_SOCKET_SINK_H__ -#define __GST_PINOS_SOCKET_SINK_H__ - -#include - -#include - -#include -#include -#include - -G_BEGIN_DECLS - -#define GST_TYPE_PINOS_SOCKET_SINK (gst_pinos_socket_sink_get_type()) -#define GST_PINOS_SOCKET_SINK(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_PINOS_SOCKET_SINK,GstPinosSocketSink)) -#define GST_PINOS_SOCKET_SINK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_PINOS_SOCKET_SINK,GstPinosSocketSinkClass)) -#define GST_IS_PINOS_SOCKET_SINK(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_PINOS_SOCKET_SINK)) -#define GST_IS_PINOS_SOCKET_SINK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_PINOS_SOCKET_SINK)) -#define GST_PINOS_SOCKET_SINK_CAST(obj) ((GstPinosSocketSink *) (obj)) - -typedef struct _GstPinosSocketSink GstPinosSocketSink; -typedef struct _GstPinosSocketSinkClass GstPinosSocketSinkClass; - -/** - * GstPinosSocketSink: - * - * Opaque data structure. - */ -struct _GstPinosSocketSink { - GstBaseSink element; - - gboolean pinos_input; - GstAllocator *allocator; - - GstBurstCache *cache; - GHashTable *hash; - GThread *thread; - GMainLoop *loop; - GMainContext *context; - - PinosFdManager *fdmanager; -}; - -struct _GstPinosSocketSinkClass { - GstBaseSinkClass parent_class; - - void (*add) (GstPinosSocketSink *sink, GSocket *socket); - void (*remove) (GstPinosSocketSink *sink, GSocket *socket, gboolean drain); -}; - -GType gst_pinos_socket_sink_get_type (void); - -G_END_DECLS - -#endif /* __GST_PINOS_SOCKET_SINK_H__ */ diff --git a/pinos/gst/gsttmpfileallocator.c b/pinos/gst/gsttmpfileallocator.c deleted file mode 100644 index 0ee45de63..000000000 --- a/pinos/gst/gsttmpfileallocator.c +++ /dev/null @@ -1,144 +0,0 @@ -/* GStreamer - * Copyright (C) 2014 William Manley - * - * 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. - */ - -#define _GNU_SOURCE - -#include "gsttmpfileallocator.h" -#include - -#include -#include -#include -#include - -#define PAGE_ALIGN 4095 - -#define GST_TYPE_TMPFILE_ALLOCATOR (gst_tmpfile_allocator_get_type ()) - -typedef struct -{ - GstFdAllocator parent; -} GstTmpFileAllocator; - -typedef struct -{ - GstFdAllocatorClass parent_class; -} GstTmpFileAllocatorClass; - -GType gst_tmpfile_allocator_get_type (void); -G_DEFINE_TYPE (GstTmpFileAllocator, gst_tmpfile_allocator, GST_TYPE_FD_ALLOCATOR); - -static int -tmpfile_create (GstTmpFileAllocator * allocator, gsize size) -{ - char filename[] = "/dev/shm/tmpfilepay.XXXXXX"; - int fd, result; - - GST_DEBUG_OBJECT (allocator, "tmpfile_create"); - - fd = mkostemp (filename, O_CLOEXEC); - if (fd == -1) { - GST_WARNING_OBJECT (allocator, "Failed to create temporary file: %s", - strerror (errno)); - return -1; - } - unlink (filename); - - result = ftruncate (fd, size); - if (result == -1) { - GST_WARNING_OBJECT (allocator, "Failed to resize temporary file: %s", - strerror (errno)); - close (fd); - return -1; - } - - return fd; -} - - -inline static gsize -pad (gsize off, gsize align) -{ - return (off + align) / (align + 1) * (align + 1); -} - -static GstMemory * -gst_tmpfile_allocator_alloc (GstAllocator * allocator, gsize size, - GstAllocationParams * params) -{ - GstTmpFileAllocator *alloc = (GstTmpFileAllocator *) allocator; - GstMemory *mem; - int fd; - gsize maxsize; - - g_return_val_if_fail (params != NULL, NULL); - - maxsize = - pad (size + pad (params->prefix, params->align) + params->padding, - PAGE_ALIGN); - - fd = tmpfile_create (alloc, maxsize); - if (fd < 0) - return NULL; - - mem = gst_fd_allocator_alloc (allocator, fd, maxsize, GST_FD_MEMORY_FLAG_NONE); - gst_memory_resize (mem, pad (params->prefix, params->align), size); - - return mem; -} - -static void -gst_tmpfile_allocator_class_init (GstTmpFileAllocatorClass * klass) -{ - GstAllocatorClass *allocator_class; - - allocator_class = (GstAllocatorClass *) klass; - - allocator_class->alloc = gst_tmpfile_allocator_alloc; -} - -static void -gst_tmpfile_allocator_init (GstTmpFileAllocator * allocator) -{ - GstAllocator *alloc = GST_ALLOCATOR_CAST (allocator); - - alloc->mem_type = GST_ALLOCATOR_TMPFILE; - - GST_OBJECT_FLAG_UNSET (allocator, GST_ALLOCATOR_FLAG_CUSTOM_ALLOC); -} - -GstAllocator * -gst_tmpfile_allocator_new (void) -{ - return g_object_new (GST_TYPE_TMPFILE_ALLOCATOR, NULL); -} - -gint -gst_tmpfile_memory_get_fd (GstMemory * mem) -{ - g_return_val_if_fail (gst_is_tmpfile_memory (mem), -1); - - return gst_fd_memory_get_fd (mem); -} - -gboolean -gst_is_tmpfile_memory (GstMemory * mem) -{ - return gst_memory_is_type (mem, GST_ALLOCATOR_TMPFILE); -} diff --git a/pinos/gst/gsttmpfileallocator.h b/pinos/gst/gsttmpfileallocator.h deleted file mode 100644 index 7636893ca..000000000 --- a/pinos/gst/gsttmpfileallocator.h +++ /dev/null @@ -1,37 +0,0 @@ -/* GStreamer - * Copyright (C) 2014 William Manley - * - * 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_TMPFILE_ALLOCATOR_H_ -#define _GST_TMPFILE_ALLOCATOR_H_ - -#include - -G_BEGIN_DECLS - -#define GST_ALLOCATOR_TMPFILE "tmpfile" - - -/* Allocator that allocates memory from a file stored on a tmpfs */ -GstAllocator* gst_tmpfile_allocator_new (void); - -gint gst_tmpfile_memory_get_fd (GstMemory * mem); -gboolean gst_is_tmpfile_memory (GstMemory * mem); - -G_END_DECLS -#endif /* _GST_TMPFILE_ALLOCATOR_H_ */ diff --git a/pinos/modules/spa/spa-alsa-sink.c b/pinos/modules/spa/spa-alsa-sink.c index 0b7887517..90b4e6017 100644 --- a/pinos/modules/spa/spa-alsa-sink.c +++ b/pinos/modules/spa/spa-alsa-sink.c @@ -266,7 +266,7 @@ stop_pipeline (PinosSpaAlsaSink *sink) pthread_join (priv->thread, NULL); } - cmd.type = SPA_COMMAND_STOP; + cmd.type = SPA_COMMAND_PAUSE; if ((res = spa_node_send_command (node->node, &cmd)) < 0) g_debug ("got error %d", res); } diff --git a/pinos/modules/spa/spa-v4l2-source.c b/pinos/modules/spa/spa-v4l2-source.c index 08e3fc1de..3ad44c341 100644 --- a/pinos/modules/spa/spa-v4l2-source.c +++ b/pinos/modules/spa/spa-v4l2-source.c @@ -238,7 +238,7 @@ stop_pipeline (PinosSpaV4l2Source *this) pthread_join (priv->thread, NULL); } - cmd.type = SPA_COMMAND_STOP; + cmd.type = SPA_COMMAND_PAUSE; if ((res = spa_node_send_command (node->node, &cmd)) < 0) g_debug ("got error %d", res); } diff --git a/pinos/server/link.c b/pinos/server/link.c index 2f8bdc9a8..8f3a75ba6 100644 --- a/pinos/server/link.c +++ b/pinos/server/link.c @@ -252,6 +252,8 @@ again: } spa_debug_format (format); + spa_format_fixate (format); + if ((res = spa_node_port_set_format (priv->output_node, priv->output_port, 0, format)) < 0) { g_warning ("error set format output: %d", res); return res; @@ -383,13 +385,13 @@ do_start (PinosLink *this) } static SpaResult -do_stop (PinosLink *this) +do_pause (PinosLink *this) { PinosLinkPrivate *priv = this->priv; SpaCommand cmd; SpaResult res; - cmd.type = SPA_COMMAND_STOP; + cmd.type = SPA_COMMAND_PAUSE; if ((res = spa_node_send_command (priv->input_node, &cmd)) < 0) g_warning ("got error %d", res); if ((res = spa_node_send_command (priv->output_node, &cmd)) < 0) @@ -476,7 +478,7 @@ on_deactivate (PinosPort *port, gpointer user_data) else pinos_port_deactivate (priv->input); - do_stop (this); + do_pause (this); return TRUE; } diff --git a/pinos/tools/pinos-monitor.c b/pinos/tools/pinos-monitor.c index 42157d871..eed4add94 100644 --- a/pinos/tools/pinos-monitor.c +++ b/pinos/tools/pinos-monitor.c @@ -17,8 +17,6 @@ * Boston, MA 02110-1301, USA. */ -#include - #include static GMainLoop *loop; diff --git a/spa/include/spa/command.h b/spa/include/spa/command.h index 18aa04eca..70206b97b 100644 --- a/spa/include/spa/command.h +++ b/spa/include/spa/command.h @@ -30,8 +30,8 @@ typedef struct _SpaCommand SpaCommand; typedef enum { SPA_COMMAND_INVALID = 0, + SPA_COMMAND_PAUSE, SPA_COMMAND_START, - SPA_COMMAND_STOP, SPA_COMMAND_FLUSH, SPA_COMMAND_DRAIN, SPA_COMMAND_MARKER, diff --git a/spa/include/spa/control.h b/spa/include/spa/control.h index 8c8b90bdc..4d980354f 100644 --- a/spa/include/spa/control.h +++ b/spa/include/spa/control.h @@ -75,7 +75,7 @@ typedef enum { SPA_CONTROL_CMD_SET_PROPERTY = 35, SPA_CONTROL_CMD_START = 36, - SPA_CONTROL_CMD_STOP = 37, + SPA_CONTROL_CMD_PAUSE = 37, /* both */ SPA_CONTROL_CMD_ADD_MEM = 64, diff --git a/spa/include/spa/format.h b/spa/include/spa/format.h index f52d60e68..85496aa9b 100644 --- a/spa/include/spa/format.h +++ b/spa/include/spa/format.h @@ -89,6 +89,8 @@ typedef enum { SPA_PROP_ID_MEDIA_CUSTOM_START = 200, } SpaFormatProps; +SpaResult spa_format_fixate (SpaFormat *format); + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/spa/include/spa/props.h b/spa/include/spa/props.h index 87429e87c..180b5aedd 100644 --- a/spa/include/spa/props.h +++ b/spa/include/spa/props.h @@ -119,8 +119,6 @@ typedef struct { * @flags: property flags * @type: property type * @max_size: maximum size of property value - * @default_size: size of default value - * @default_value: default value of property * @range_type: type of the range values * @n_range_values: number of elements in @range_values * @range_values: array of possible values @@ -134,8 +132,6 @@ typedef struct { SpaPropFlags flags; SpaPropType type; size_t maxsize; - size_t default_size; - const void *default_value; SpaPropRangeType range_type; unsigned int n_range_values; const SpaPropRangeInfo *range_values; diff --git a/spa/lib/audio-raw.c b/spa/lib/audio-raw.c index d1828b750..560de9677 100644 --- a/spa/lib/audio-raw.c +++ b/spa/lib/audio-raw.c @@ -140,49 +140,42 @@ static const SpaPropInfo raw_format_prop_info[] = { SPA_PROP_ID_AUDIO_FORMAT, "format", "The media format", SPA_PROP_FLAG_READWRITE, SPA_PROP_TYPE_UINT32, sizeof (uint32_t), - sizeof (uint32_t), &default_info.format, SPA_PROP_RANGE_TYPE_ENUM, SPA_N_ELEMENTS (format_format_range), format_format_range, NULL, offsetof (SpaAudioRawFormat, info.format) }, { SPA_PROP_ID_AUDIO_FLAGS, "flags", "Sample Flags", SPA_PROP_FLAG_READWRITE, SPA_PROP_TYPE_UINT32, sizeof (uint32_t), - sizeof (uint32_t), &default_info.flags, SPA_PROP_RANGE_TYPE_FLAGS, SPA_N_ELEMENTS (flags_range), flags_range, NULL, offsetof (SpaAudioRawFormat, info.flags) }, { SPA_PROP_ID_AUDIO_LAYOUT, "layout", "Sample Layout", SPA_PROP_FLAG_READWRITE, SPA_PROP_TYPE_UINT32, sizeof (uint32_t), - sizeof (uint32_t), &default_info.layout, SPA_PROP_RANGE_TYPE_ENUM, SPA_N_ELEMENTS (layouts_range), layouts_range, NULL, offsetof (SpaAudioRawFormat, info.layout) }, { SPA_PROP_ID_AUDIO_RATE, "rate", "Audio sample rate", SPA_PROP_FLAG_READWRITE, SPA_PROP_TYPE_UINT32, sizeof (uint32_t), - sizeof (uint32_t), &default_info.rate, SPA_PROP_RANGE_TYPE_MIN_MAX, 2, uint32_range, NULL, offsetof (SpaAudioRawFormat, info.rate) }, { SPA_PROP_ID_AUDIO_CHANNELS, "channels", "Audio channels", SPA_PROP_FLAG_READWRITE, SPA_PROP_TYPE_UINT32, sizeof (uint32_t), - sizeof (uint32_t), &default_info.channels, SPA_PROP_RANGE_TYPE_MIN_MAX, 2, uint32_range, NULL, offsetof (SpaAudioRawFormat, info.channels) }, { SPA_PROP_ID_AUDIO_CHANNEL_MASK, "channel-mask", "Audio channel mask", SPA_PROP_FLAG_READWRITE, SPA_PROP_TYPE_BITMASK, sizeof (uint32_t), - sizeof (uint32_t), &default_info.channel_mask, SPA_PROP_RANGE_TYPE_NONE, 0, NULL, NULL, offsetof (SpaAudioRawFormat, info.channel_mask) }, { SPA_PROP_ID_AUDIO_RAW_INFO, "info", "the SpaAudioRawInfo structure", SPA_PROP_FLAG_READWRITE, SPA_PROP_TYPE_POINTER, sizeof (SpaAudioRawInfo), - 0, NULL, SPA_PROP_RANGE_TYPE_NONE, 0, NULL, NULL, offsetof (SpaAudioRawFormat, info) }, diff --git a/spa/lib/control.c b/spa/lib/control.c index f2339923e..4b12755bf 100644 --- a/spa/lib/control.c +++ b/spa/lib/control.c @@ -358,8 +358,6 @@ parse_props (SpaMemory *mem, void *p, off_t offset) pi->name = SPA_MEMBER (tp, SPA_PTR_TO_INT (pi->name), char); if (pi->description) pi->description = SPA_MEMBER (tp, SPA_PTR_TO_INT (pi->description), char); - if (pi->default_value) - pi->default_value = SPA_MEMBER (tp, SPA_PTR_TO_INT (pi->default_value), void); if (pi->range_values) pi->range_values = SPA_MEMBER (tp, SPA_PTR_TO_INT (pi->range_values), SpaPropRangeInfo); @@ -528,7 +526,7 @@ spa_control_iter_parse_cmd (SpaControlIter *iter, break; case SPA_CONTROL_CMD_START: - case SPA_CONTROL_CMD_STOP: + case SPA_CONTROL_CMD_PAUSE: break; /* bidirectional */ @@ -814,8 +812,8 @@ calc_props_len (const SpaProps *props) len += sizeof (SpaPropInfo); len += pi->name ? strlen (pi->name) + 1 : 0; len += pi->description ? strlen (pi->description) + 1 : 0; - /* for the value and the default value */ - len += pi->maxsize + pi->default_size; + /* for the value */ + len += pi->maxsize; for (j = 0; j < pi->n_range_values; j++) { ri = (SpaPropRangeInfo *)&pi->range_values[j]; len += sizeof (SpaPropRangeInfo); @@ -879,13 +877,6 @@ write_props (void *p, const SpaProps *props, off_t offset) } else { pi->description = 0; } - if (pi->default_value) { - memcpy (p, pi->default_value, pi->default_size); - pi->default_value = SPA_INT_TO_PTR (SPA_PTRDIFF (p, tp)); - p += pi->default_size; - } else { - pi->default_value = 0; - } for (j = 0; j < pi->n_range_values; j++) { if (ri->name) { slen = strlen (ri->name) + 1; @@ -1157,7 +1148,7 @@ spa_control_builder_add_cmd (SpaControlBuilder *builder, break; case SPA_CONTROL_CMD_START: - case SPA_CONTROL_CMD_STOP: + case SPA_CONTROL_CMD_PAUSE: p = builder_add_cmd (sb, cmd, 0); break; diff --git a/spa/lib/debug.c b/spa/lib/debug.c index a0b582b55..a29f16146 100644 --- a/spa/lib/debug.c +++ b/spa/lib/debug.c @@ -328,12 +328,6 @@ spa_debug_props (const SpaProps *props, bool print_ranges) fprintf (stderr, "%-23.23s %s. ", "", prop_type_names[info->type].CCName); - fprintf (stderr, "Default: "); - if (info->default_value) - print_value (info, info->default_size, info->default_value); - else - fprintf (stderr, "None"); - res = spa_props_get_prop (props, i, &value); fprintf (stderr, ". Current: "); diff --git a/spa/lib/format.c b/spa/lib/format.c index e3b898bda..e8e08cfac 100644 --- a/spa/lib/format.c +++ b/spa/lib/format.c @@ -27,10 +27,53 @@ 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; } + +SpaResult +spa_format_fixate (SpaFormat *format) +{ + unsigned int i, j; + SpaProps *props; + uint32_t mask; + + if (format == NULL) + return SPA_RESULT_INVALID_ARGUMENTS; + + props = &format->props; + mask = props->unset_mask; + + for (i = 0; i < props->n_prop_info; i++) { + if (mask & 1) { + const SpaPropInfo *pi = &props->prop_info[i]; + + switch (pi->range_type) { + case SPA_PROP_RANGE_TYPE_NONE: + break; + case SPA_PROP_RANGE_TYPE_MIN_MAX: + break; + case SPA_PROP_RANGE_TYPE_STEP: + break; + case SPA_PROP_RANGE_TYPE_ENUM: + { + for (j = 0; j < pi->n_range_values; j++) { + const SpaPropRangeInfo *ri = &pi->range_values[j]; + memcpy (SPA_MEMBER (props, pi->offset, void), ri->value, ri->size); + props->unset_mask &= ~(1 << i); + break; + } + break; + } + case SPA_PROP_RANGE_TYPE_FLAGS: + break; + default: + break; + } + } + mask >>= 1; + } + return SPA_RESULT_OK; +} diff --git a/spa/lib/meson.build b/spa/lib/meson.build index 35c3ed46c..8b80922e3 100644 --- a/spa/lib/meson.build +++ b/spa/lib/meson.build @@ -2,6 +2,7 @@ spalib_sources = ['audio-raw.c', 'buffer.c', 'control.c', 'debug.c', + 'format.c', 'memory.c', 'props.c', 'ringbuffer.c', diff --git a/spa/lib/video-raw.c b/spa/lib/video-raw.c index fc48b25cd..5ed1458b4 100644 --- a/spa/lib/video-raw.c +++ b/spa/lib/video-raw.c @@ -376,105 +376,90 @@ static const SpaPropInfo raw_format_prop_info[] = { SPA_PROP_ID_VIDEO_FORMAT, "format", "The media format", SPA_PROP_FLAG_READWRITE, SPA_PROP_TYPE_UINT32, sizeof (uint32_t), - sizeof (uint32_t), &default_info.format, SPA_PROP_RANGE_TYPE_ENUM, SPA_N_ELEMENTS (format_range), format_range, NULL, offsetof (SpaVideoRawFormat, info.format) }, { SPA_PROP_ID_VIDEO_SIZE, "size", "Video size", SPA_PROP_FLAG_READWRITE, SPA_PROP_TYPE_RECTANGLE, sizeof (SpaRectangle), - sizeof (SpaRectangle), &default_info.size, SPA_PROP_RANGE_TYPE_MIN_MAX, 2, size_range, NULL, offsetof (SpaVideoRawFormat, info.size) }, { SPA_PROP_ID_VIDEO_FRAMERATE, "framerate", "Video framerate", SPA_PROP_FLAG_READWRITE, SPA_PROP_TYPE_FRACTION, sizeof (SpaFraction), - sizeof (SpaFraction), &default_info.framerate, SPA_PROP_RANGE_TYPE_MIN_MAX, 2, framerate_range, NULL, offsetof (SpaVideoRawFormat, info.framerate) }, { SPA_PROP_ID_VIDEO_MAX_FRAMERATE, "max-framerate", "Video max framerate", SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL, SPA_PROP_TYPE_FRACTION, sizeof (SpaFraction), - sizeof (SpaFraction), &default_info.max_framerate, SPA_PROP_RANGE_TYPE_MIN_MAX, 2, framerate_range, NULL, offsetof (SpaVideoRawFormat, info.max_framerate) }, { SPA_PROP_ID_VIDEO_VIEWS, "views", "Video number of views", SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL, SPA_PROP_TYPE_UINT32, sizeof (uint32_t), - sizeof (uint32_t), &default_info.views, SPA_PROP_RANGE_TYPE_MIN_MAX, 2, uint32_range, NULL, offsetof (SpaVideoRawFormat, info.views) }, { SPA_PROP_ID_VIDEO_INTERLACE_MODE, "interlace-mode", "Interlace mode", SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL, SPA_PROP_TYPE_UINT32, sizeof (uint32_t), - sizeof (uint32_t), &default_info.interlace_mode, SPA_PROP_RANGE_TYPE_ENUM, SPA_N_ELEMENTS (interlace_mode_range), interlace_mode_range, NULL, offsetof (SpaVideoRawFormat, info.interlace_mode) }, { SPA_PROP_ID_VIDEO_PIXEL_ASPECT_RATIO, "pixel-aspect-ratio", "Video pixel aspect ratio", SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL, SPA_PROP_TYPE_FRACTION, sizeof (SpaFraction), - sizeof (SpaFraction), &default_info.pixel_aspect_ratio, SPA_PROP_RANGE_TYPE_MIN_MAX, 2, framerate_range, NULL, offsetof (SpaVideoRawFormat, info.pixel_aspect_ratio) }, { SPA_PROP_ID_VIDEO_MULTIVIEW_MODE, "multiview-mode", "Multiview mode", SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL, SPA_PROP_TYPE_UINT32, sizeof (uint32_t), - sizeof (uint32_t), &default_info.multiview_mode, SPA_PROP_RANGE_TYPE_ENUM, SPA_N_ELEMENTS (multiview_mode_range), multiview_mode_range, NULL, offsetof (SpaVideoRawFormat, info.multiview_mode) }, { SPA_PROP_ID_VIDEO_MULTIVIEW_FLAGS, "multiview-flags", "Multiview flags", SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL, SPA_PROP_TYPE_UINT32, sizeof (uint32_t), - sizeof (uint32_t), &default_info.multiview_flags, SPA_PROP_RANGE_TYPE_FLAGS, SPA_N_ELEMENTS (multiview_flags_range), multiview_flags_range, NULL, offsetof (SpaVideoRawFormat, info.multiview_flags) }, { SPA_PROP_ID_VIDEO_CHROMA_SITE, "chroma-site", "Chroma site", SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL, SPA_PROP_TYPE_UINT32, sizeof (uint32_t), - sizeof (uint32_t), &default_info.chroma_site, SPA_PROP_RANGE_TYPE_FLAGS, SPA_N_ELEMENTS (chroma_site_range), chroma_site_range, NULL, offsetof (SpaVideoRawFormat, info.chroma_site) }, { SPA_PROP_ID_VIDEO_COLOR_RANGE, "color-range", "Color range", SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL, SPA_PROP_TYPE_UINT32, sizeof (uint32_t), - sizeof (uint32_t), &default_info.color_range, SPA_PROP_RANGE_TYPE_ENUM, SPA_N_ELEMENTS (color_range_range), color_range_range, NULL, offsetof (SpaVideoRawFormat, info.color_range) }, { SPA_PROP_ID_VIDEO_COLOR_MATRIX, "color-matrix", "Color matrix", SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL, SPA_PROP_TYPE_UINT32, sizeof (uint32_t), - sizeof (uint32_t), &default_info.color_matrix, SPA_PROP_RANGE_TYPE_ENUM, SPA_N_ELEMENTS (color_matrix_range), color_matrix_range, NULL, offsetof (SpaVideoRawFormat, info.color_matrix) }, { SPA_PROP_ID_VIDEO_TRANSFER_FUNCTION, "transfer-function", "Transfer function", SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL, SPA_PROP_TYPE_UINT32, sizeof (uint32_t), - sizeof (uint32_t), &default_info.transfer_function, SPA_PROP_RANGE_TYPE_ENUM, SPA_N_ELEMENTS (transfer_function_range), transfer_function_range, NULL, offsetof (SpaVideoRawFormat, info.transfer_function) }, { SPA_PROP_ID_VIDEO_COLOR_PRIMARIES, "color-primaries", "Color primaries", SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL, SPA_PROP_TYPE_UINT32, sizeof (uint32_t), - sizeof (uint32_t), &default_info.color_primaries, SPA_PROP_RANGE_TYPE_ENUM, SPA_N_ELEMENTS (color_primaries_range), color_primaries_range, NULL, offsetof (SpaVideoRawFormat, info.color_primaries) }, { SPA_PROP_ID_VIDEO_RAW_INFO, "info", "the SpaVideoRawInfo structure", SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL, SPA_PROP_TYPE_POINTER, sizeof (SpaVideoRawInfo), - 0, NULL, SPA_PROP_RANGE_TYPE_NONE, 0, NULL, NULL, offsetof (SpaVideoRawFormat, info) }, diff --git a/spa/plugins/alsa/alsa-sink.c b/spa/plugins/alsa/alsa-sink.c index f4162eb20..d0141cc30 100644 --- a/spa/plugins/alsa/alsa-sink.c +++ b/spa/plugins/alsa/alsa-sink.c @@ -126,42 +126,36 @@ static const SpaPropInfo prop_info[] = { PROP_ID_DEVICE, "device", "ALSA device, as defined in an asound configuration file", SPA_PROP_FLAG_READWRITE, SPA_PROP_TYPE_STRING, 63, - strlen (default_device)+1, default_device, SPA_PROP_RANGE_TYPE_NONE, 0, NULL, NULL, offsetof (SpaALSASinkProps, device) }, { PROP_ID_DEVICE_NAME, "device-name", "Human-readable name of the sound device", SPA_PROP_FLAG_READABLE, SPA_PROP_TYPE_STRING, 127, - 0, NULL, SPA_PROP_RANGE_TYPE_NONE, 0, NULL, NULL, offsetof (SpaALSASinkProps, device_name) }, { PROP_ID_CARD_NAME, "card-name", "Human-readable name of the sound card", SPA_PROP_FLAG_READABLE, SPA_PROP_TYPE_STRING, 127, - 0, NULL, SPA_PROP_RANGE_TYPE_NONE, 0, NULL, NULL, offsetof (SpaALSASinkProps, card_name) }, { PROP_ID_BUFFER_TIME, "buffer-time", "The total size of the buffer in time", SPA_PROP_FLAG_READWRITE, SPA_PROP_TYPE_UINT32, sizeof (uint32_t), - sizeof (uint32_t), &default_buffer_time, SPA_PROP_RANGE_TYPE_MIN_MAX, 2, uint32_range, NULL, offsetof (SpaALSASinkProps, buffer_time) }, { PROP_ID_PERIOD_TIME, "period-time", "The size of a period in time", SPA_PROP_FLAG_READWRITE, SPA_PROP_TYPE_UINT32, sizeof (uint32_t), - sizeof (uint32_t), &default_period_time, SPA_PROP_RANGE_TYPE_MIN_MAX, 2, uint32_range, NULL, offsetof (SpaALSASinkProps, period_time) }, { PROP_ID_PERIOD_EVENT, "period-event", "Generate an event each period", SPA_PROP_FLAG_READWRITE, SPA_PROP_TYPE_BOOL, sizeof (bool), - sizeof (bool), &default_period_event, SPA_PROP_RANGE_TYPE_NONE, 0, NULL, NULL, offsetof (SpaALSASinkProps, period_event) }, @@ -239,7 +233,7 @@ spa_alsa_sink_node_send_command (SpaNode *node, this->event_cb (node, &event, this->user_data); } break; - case SPA_COMMAND_STOP: + case SPA_COMMAND_PAUSE: spa_alsa_stop (this); if (this->event_cb) { @@ -250,7 +244,7 @@ spa_alsa_sink_node_send_command (SpaNode *node, event.port_id = -1; event.data = ≻ event.size = sizeof (sc); - sc.state = SPA_NODE_STATE_STREAMING; + sc.state = SPA_NODE_STATE_PAUSED; this->event_cb (node, &event, this->user_data); } diff --git a/spa/plugins/audiomixer/audiomixer.c b/spa/plugins/audiomixer/audiomixer.c index f5d89f288..813a6002a 100644 --- a/spa/plugins/audiomixer/audiomixer.c +++ b/spa/plugins/audiomixer/audiomixer.c @@ -161,7 +161,7 @@ spa_audiomixer_node_send_command (SpaNode *node, } break; - case SPA_COMMAND_STOP: + case SPA_COMMAND_PAUSE: if (this->event_cb) { SpaEvent event; SpaEventStateChange sc; diff --git a/spa/plugins/audiotestsrc/audiotestsrc.c b/spa/plugins/audiotestsrc/audiotestsrc.c index b228a67c1..0a1606109 100644 --- a/spa/plugins/audiotestsrc/audiotestsrc.c +++ b/spa/plugins/audiotestsrc/audiotestsrc.c @@ -87,21 +87,18 @@ static const SpaPropInfo prop_info[] = { PROP_ID_WAVE, "wave", "Oscillator waveform", SPA_PROP_FLAG_READWRITE, SPA_PROP_TYPE_UINT32, sizeof (uint32_t), - sizeof (uint32_t), &default_wave, SPA_PROP_RANGE_TYPE_ENUM, SPA_N_ELEMENTS (wave_range), wave_range, NULL, offsetof (SpaAudioTestSrcProps, wave) }, { PROP_ID_FREQ, "freq", "Frequency of test signal. The sample rate needs to be at least 4 times higher", SPA_PROP_FLAG_READWRITE, SPA_PROP_TYPE_DOUBLE, sizeof (double), - sizeof (double), &default_freq, SPA_PROP_RANGE_TYPE_MIN_MAX, 2, freq_range, NULL, offsetof (SpaAudioTestSrcProps, freq) }, { PROP_ID_VOLUME, "volume", "The Volume factor", SPA_PROP_FLAG_READWRITE, SPA_PROP_TYPE_DOUBLE, sizeof (double), - sizeof (double), &default_volume, SPA_PROP_RANGE_TYPE_MIN_MAX, 2, volume_range, NULL, offsetof (SpaAudioTestSrcProps, volume) }, @@ -185,7 +182,7 @@ spa_audiotestsrc_node_send_command (SpaNode *node, } break; - case SPA_COMMAND_STOP: + case SPA_COMMAND_PAUSE: if (this->event_cb) { SpaEvent event; SpaEventStateChange sc; diff --git a/spa/plugins/ffmpeg/ffmpeg-dec.c b/spa/plugins/ffmpeg/ffmpeg-dec.c index d46b21e77..7ad3d33d5 100644 --- a/spa/plugins/ffmpeg/ffmpeg-dec.c +++ b/spa/plugins/ffmpeg/ffmpeg-dec.c @@ -156,7 +156,7 @@ spa_ffmpeg_dec_node_send_command (SpaNode *node, this->event_cb (node, &event, this->user_data); } break; - case SPA_COMMAND_STOP: + case SPA_COMMAND_PAUSE: if (this->event_cb) { SpaEvent event; SpaEventStateChange sc; diff --git a/spa/plugins/ffmpeg/ffmpeg-enc.c b/spa/plugins/ffmpeg/ffmpeg-enc.c index a06dbe24f..ecfeebac9 100644 --- a/spa/plugins/ffmpeg/ffmpeg-enc.c +++ b/spa/plugins/ffmpeg/ffmpeg-enc.c @@ -156,7 +156,7 @@ spa_ffmpeg_enc_node_send_command (SpaNode *node, this->event_cb (node, &event, this->user_data); } break; - case SPA_COMMAND_STOP: + case SPA_COMMAND_PAUSE: if (this->event_cb) { SpaEvent event; SpaEventStateChange sc; diff --git a/spa/plugins/remote/proxy.c b/spa/plugins/remote/proxy.c index 326f81c87..81b770f34 100644 --- a/spa/plugins/remote/proxy.c +++ b/spa/plugins/remote/proxy.c @@ -91,7 +91,6 @@ static const SpaPropInfo prop_info[PROP_ID_LAST] = { PROP_ID_SOCKET, "socket", "The Socket factor", SPA_PROP_FLAG_READWRITE, SPA_PROP_TYPE_INT, sizeof (int), - sizeof (int), NULL, SPA_PROP_RANGE_TYPE_NONE, 0, NULL, NULL, offsetof (SpaProxyProps, socketfd) }, @@ -234,7 +233,7 @@ spa_proxy_node_send_command (SpaNode *node, break; } - case SPA_COMMAND_STOP: + case SPA_COMMAND_PAUSE: { SpaControlBuilder builder; SpaControl control; @@ -242,7 +241,7 @@ spa_proxy_node_send_command (SpaNode *node, /* send start */ spa_control_builder_init_into (&builder, buf, sizeof (buf), NULL, 0); - spa_control_builder_add_cmd (&builder, SPA_CONTROL_CMD_STOP, NULL); + spa_control_builder_add_cmd (&builder, SPA_CONTROL_CMD_PAUSE, NULL); spa_control_builder_end (&builder, &control); if ((res = spa_control_write (&control, this->fds[0].fd)) < 0) @@ -342,13 +341,16 @@ do_update_port (SpaProxy *this, SpaEvent event; SpaProxyPort *port; SpaEventPortAdded pa; + unsigned int i; port = &this->ports[pu->port_id]; - if (pu->change_mask & SPA_CONTROL_CMD_PORT_UPDATE_POSSIBLE_FORMATS) { port->n_formats = pu->n_possible_formats; port->formats = pu->possible_formats; + + for (i = 0; i < port->n_formats; i++) + spa_debug_format (port->formats[i]); } if (pu->change_mask & SPA_CONTROL_CMD_PORT_UPDATE_PROPS) { @@ -969,7 +971,7 @@ parse_control (SpaProxy *this, case SPA_CONTROL_CMD_SET_FORMAT: case SPA_CONTROL_CMD_SET_PROPERTY: case SPA_CONTROL_CMD_START: - case SPA_CONTROL_CMD_STOP: + case SPA_CONTROL_CMD_PAUSE: fprintf (stderr, "proxy %p: got unexpected control %d\n", this, cmd); break; diff --git a/spa/plugins/v4l2/v4l2-source.c b/spa/plugins/v4l2/v4l2-source.c index c702eb2da..da7d40a68 100644 --- a/spa/plugins/v4l2/v4l2-source.c +++ b/spa/plugins/v4l2/v4l2-source.c @@ -142,21 +142,18 @@ static const SpaPropInfo prop_info[] = { PROP_ID_DEVICE, "device", "V4l2 device location", SPA_PROP_FLAG_READWRITE, SPA_PROP_TYPE_STRING, 63, - strlen (default_device)+1, default_device, SPA_PROP_RANGE_TYPE_NONE, 0, NULL, NULL, offsetof (SpaV4l2SourceProps, device) }, { PROP_ID_DEVICE_NAME, "device-name", "Human-readable name of the device", SPA_PROP_FLAG_READABLE, SPA_PROP_TYPE_STRING, 127, - 0, NULL, SPA_PROP_RANGE_TYPE_NONE, 0, NULL, NULL, offsetof (SpaV4l2SourceProps, device_name) }, { PROP_ID_DEVICE_FD, "device-fd", "Device file descriptor", SPA_PROP_FLAG_READABLE, SPA_PROP_TYPE_UINT32, sizeof (uint32_t), - 0, NULL, SPA_PROP_RANGE_TYPE_NONE, 0, NULL, NULL, offsetof (SpaV4l2SourceProps, device_fd) }, @@ -237,7 +234,7 @@ spa_v4l2_source_node_send_command (SpaNode *node, send_state_change (this, SPA_NODE_STATE_STREAMING); break; - case SPA_COMMAND_STOP: + case SPA_COMMAND_PAUSE: spa_v4l2_stop (this); send_state_change (this, SPA_NODE_STATE_PAUSED); diff --git a/spa/plugins/v4l2/v4l2-utils.c b/spa/plugins/v4l2/v4l2-utils.c index 95baa21af..b428d684c 100644 --- a/spa/plugins/v4l2/v4l2-utils.c +++ b/spa/plugins/v4l2/v4l2-utils.c @@ -385,13 +385,13 @@ spa_v4l2_set_format (SpaV4l2Source *this, V4l2Format *f, bool try_only) fmt.fmt.pix.field = V4L2_FIELD_ANY; fmt.fmt.pix.width = f->size.width; fmt.fmt.pix.height = f->size.height; - streamparm.parm.capture.timeperframe.numerator = f->framerate.denom; - streamparm.parm.capture.timeperframe.denominator = f->framerate.num; + streamparm.parm.capture.timeperframe.numerator = f->framerate.num; + streamparm.parm.capture.timeperframe.denominator = f->framerate.denom; fprintf (stderr, "set %08x %dx%d %d/%d\n", fmt.fmt.pix.pixelformat, fmt.fmt.pix.width, fmt.fmt.pix.height, - streamparm.parm.capture.timeperframe.denominator, - streamparm.parm.capture.timeperframe.numerator); + streamparm.parm.capture.timeperframe.numerator, + streamparm.parm.capture.timeperframe.denominator); reqfmt = fmt; @@ -407,6 +407,11 @@ spa_v4l2_set_format (SpaV4l2Source *this, V4l2Format *f, bool try_only) if (xioctl (state->fd, VIDIOC_S_PARM, &streamparm) < 0) perror ("VIDIOC_S_PARM"); + fprintf (stderr, "got %08x %dx%d %d/%d\n", fmt.fmt.pix.pixelformat, + fmt.fmt.pix.width, fmt.fmt.pix.height, + streamparm.parm.capture.timeperframe.numerator, + streamparm.parm.capture.timeperframe.denominator); + if (reqfmt.fmt.pix.pixelformat != fmt.fmt.pix.pixelformat || reqfmt.fmt.pix.width != fmt.fmt.pix.width || reqfmt.fmt.pix.height != fmt.fmt.pix.height) diff --git a/spa/plugins/volume/volume.c b/spa/plugins/volume/volume.c index 742a18d6a..e4f61df96 100644 --- a/spa/plugins/volume/volume.c +++ b/spa/plugins/volume/volume.c @@ -78,14 +78,12 @@ static const SpaPropInfo prop_info[] = { PROP_ID_VOLUME, "volume", "The Volume factor", SPA_PROP_FLAG_READWRITE, SPA_PROP_TYPE_DOUBLE, sizeof (double), - sizeof (double), &default_volume, SPA_PROP_RANGE_TYPE_MIN_MAX, 2, volume_range, NULL, offsetof (SpaVolumeProps, volume) }, { PROP_ID_MUTE, "mute", "Mute", SPA_PROP_FLAG_READWRITE, SPA_PROP_TYPE_BOOL, sizeof (bool), - sizeof (bool), &default_mute, SPA_PROP_RANGE_TYPE_NONE, 0, NULL, NULL, offsetof (SpaVolumeProps, mute) }, @@ -168,7 +166,7 @@ spa_volume_node_send_command (SpaNode *node, } break; - case SPA_COMMAND_STOP: + case SPA_COMMAND_PAUSE: if (this->event_cb) { SpaEvent event; SpaEventStateChange sc; diff --git a/spa/plugins/xv/xv-sink.c b/spa/plugins/xv/xv-sink.c index 47988d792..4044af5a4 100644 --- a/spa/plugins/xv/xv-sink.c +++ b/spa/plugins/xv/xv-sink.c @@ -100,21 +100,18 @@ static const SpaPropInfo prop_info[] = { PROP_ID_DEVICE, "device", "Xv device location", SPA_PROP_FLAG_READWRITE, SPA_PROP_TYPE_STRING, 63, - strlen (default_device)+1, default_device, SPA_PROP_RANGE_TYPE_NONE, 0, NULL, NULL, offsetof (SpaXvSinkProps, device) }, { PROP_ID_DEVICE_NAME, "device-name", "Human-readable name of the device", SPA_PROP_FLAG_READABLE, SPA_PROP_TYPE_STRING, 127, - 0, NULL, SPA_PROP_RANGE_TYPE_NONE, 0, NULL, NULL, offsetof (SpaXvSinkProps, device_name) }, { PROP_ID_DEVICE_FD, "device-fd", "Device file descriptor", SPA_PROP_FLAG_READABLE, SPA_PROP_TYPE_UINT32, sizeof (uint32_t), - 0, NULL, SPA_PROP_RANGE_TYPE_NONE, 0, NULL, NULL, offsetof (SpaXvSinkProps, device_fd) }, @@ -192,7 +189,7 @@ spa_xv_sink_node_send_command (SpaNode *node, this->event_cb (node, &event, this->user_data); } break; - case SPA_COMMAND_STOP: + case SPA_COMMAND_PAUSE: spa_xv_stop (this); if (this->event_cb) { diff --git a/spa/tests/test-mixer.c b/spa/tests/test-mixer.c index 0cac28853..dbf3f9b4b 100644 --- a/spa/tests/test-mixer.c +++ b/spa/tests/test-mixer.c @@ -331,7 +331,7 @@ run_async_sink (AppData *data) pthread_join (data->thread, NULL); } - cmd.type = SPA_COMMAND_STOP; + cmd.type = SPA_COMMAND_PAUSE; if ((res = spa_node_send_command (data->sink, &cmd)) < 0) printf ("got error %d\n", res); } diff --git a/spa/tests/test-v4l2.c b/spa/tests/test-v4l2.c index 42bf9ed5a..eb51b6ba2 100644 --- a/spa/tests/test-v4l2.c +++ b/spa/tests/test-v4l2.c @@ -439,7 +439,7 @@ run_async_source (AppData *data) pthread_join (data->thread, NULL); } - cmd.type = SPA_COMMAND_STOP; + cmd.type = SPA_COMMAND_PAUSE; if ((res = spa_node_send_command (data->source, &cmd)) < 0) printf ("got error %d\n", res); }