From: Mathieu Duponchelle Date: Sat, 7 Sep 2019 02:28:46 +0000 (+0200) Subject: examples: add device provider example X-Git-Tag: 1.19.3~511^2~914 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=dd556ccf3d5b05c0e0b03398b62617e311797085;p=platform%2Fupstream%2Fgstreamer.git examples: add device provider example --- diff --git a/tests/examples/device-provider/example-device-provider.c b/tests/examples/device-provider/example-device-provider.c new file mode 100644 index 0000000..77cdc6f --- /dev/null +++ b/tests/examples/device-provider/example-device-provider.c @@ -0,0 +1,331 @@ +/* + * Copyright (C) 2019 Mathieu Duponchelle + * + * 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. + */ + +/* Simple device provider example. + * + * Usage: + * + * GST_PLUGIN_PATH=$GST_PLUGIN_PATH:/path/to/libexample_device_provider.so/folder gst-device-monitor-1.0 -f + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#define NEW_DEVICE_INTERVAL 1 /* seconds */ + +#define EXAMPLE_TYPE_DEVICE_PROVIDER example_device_provider_get_type() +#define EXAMPLE_DEVICE_PROVIDER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),EXAMPLE_TYPE_DEVICE_PROVIDER,ExampleDeviceProvider)) + +typedef struct _ExampleDeviceProvider ExampleDeviceProvider; +typedef struct _ExampleDeviceProviderClass ExampleDeviceProviderClass; + +struct _ExampleDeviceProviderClass +{ + GstDeviceProviderClass parent_class; +}; + +/** + * Our device provider instance. + * + * @factory: the videotestsrc factory + * @patterns: When started, the list of videotestsrc pattern + * (as strings) to iterate through when adding new devices, + * eg "smpte", "snow", ... + * @timeout_id: When started, we will add a new device every + * %NEW_DEVICE_INTERVAL seconds + */ +struct _ExampleDeviceProvider +{ + GstDeviceProvider parent; + GstElementFactory *factory; + GList *patterns; + guint timeout_id; +}; + +static GType example_device_provider_get_type (void); + +G_DEFINE_TYPE (ExampleDeviceProvider, example_device_provider, + GST_TYPE_DEVICE_PROVIDER); + +#define EXAMPLE_TYPE_DEVICE example_device_get_type() +#define EXAMPLE_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),EXAMPLE_TYPE_DEVICE,ExampleDevice)) + +typedef struct _ExampleDevice ExampleDevice; +typedef struct _ExampleDeviceClass ExampleDeviceClass; + +struct _ExampleDeviceClass +{ + GstDeviceClass parent_class; +}; + +/* Our example device, it simply exposes a videotestsrc with a specific + * pattern. + */ +struct _ExampleDevice +{ + GstDevice parent; + + gchar *pattern; + GstElementFactory *factory; +}; + +static GType example_device_get_type (void); + +G_DEFINE_TYPE (ExampleDevice, example_device, GST_TYPE_DEVICE); + +static void +example_device_init (ExampleDevice * self) +{ +} + +static void +example_device_finalize (GObject * object) +{ + ExampleDevice *self = EXAMPLE_DEVICE (object); + + g_free (self->pattern); + + G_OBJECT_CLASS (example_device_parent_class)->finalize (object); +} + +static void +example_device_dispose (GObject * object) +{ + ExampleDevice *self = EXAMPLE_DEVICE (object); + + gst_object_replace ((GstObject **) & self->factory, NULL); + + G_OBJECT_CLASS (example_device_parent_class)->dispose (object); +} + +static GstElement * +example_device_create_element (GstDevice * device, const gchar * name) +{ + ExampleDevice *self = EXAMPLE_DEVICE (device); + GstElement *ret; + + ret = gst_element_factory_create (self->factory, name); + + gst_util_set_object_arg (G_OBJECT (ret), "pattern", self->pattern); + + return ret; +} + +static void +example_device_class_init (ExampleDeviceClass * klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GstDeviceClass *gst_device_class = GST_DEVICE_CLASS (klass); + + gobject_class->finalize = GST_DEBUG_FUNCPTR (example_device_finalize); + gobject_class->dispose = GST_DEBUG_FUNCPTR (example_device_dispose); + + gst_device_class->create_element = + GST_DEBUG_FUNCPTR (example_device_create_element); +} + +static GstDevice * +example_device_new (GstElementFactory * factory, const gchar * pattern) +{ + GstDevice *ret; + gchar *display_name; + GstCaps *caps; + const GList *templates; + + templates = gst_element_factory_get_static_pad_templates (factory); + caps = gst_static_pad_template_get_caps ((GstStaticPadTemplate *) + templates->data); + + display_name = g_strdup_printf ("example-device-%s", pattern); + + ret = GST_DEVICE (g_object_new (EXAMPLE_TYPE_DEVICE, + "display-name", display_name, + "device-class", "Video/Source", "caps", caps, NULL)); + + g_free (display_name); + gst_caps_unref (caps); + + EXAMPLE_DEVICE (ret)->pattern = g_strdup (pattern); + EXAMPLE_DEVICE (ret)->factory = + GST_ELEMENT_FACTORY (gst_object_ref (factory)); + + return ret; +} + +static void +example_device_provider_init (ExampleDeviceProvider * self) +{ + self->factory = gst_element_factory_find ("videotestsrc"); + + /* Ensure we can introspect the factory */ + gst_object_unref (gst_plugin_feature_load (GST_PLUGIN_FEATURE + (self->factory))); + +} + +/* Called when gst_device_provider_get_devices() is called on a provider that + * hasn't been started, or doesn't implement #GstDeviceProvider.start(). + * + * In that case, let's return a single example device, with a snow pattern. + */ +static GList * +example_device_provider_probe (GstDeviceProvider * provider) +{ + ExampleDeviceProvider *self = EXAMPLE_DEVICE_PROVIDER (provider); + GList *ret = NULL; + + ret = g_list_prepend (ret, example_device_new (self->factory, "snow")); + + return ret; +} + +static gboolean +example_device_provider_next_device (ExampleDeviceProvider * self) +{ + GstDevice *device; + gboolean ret = G_SOURCE_CONTINUE; + + if (!self->patterns) + goto no_more_patterns; + + device = example_device_new (self->factory, (gchar *) self->patterns->data); + gst_device_provider_device_add (GST_DEVICE_PROVIDER (self), device); + g_free (self->patterns->data); + self->patterns = g_list_delete_link (self->patterns, self->patterns); + +done: + return ret; + +no_more_patterns: + GST_DEBUG_OBJECT (self, "Went through all videotestsrc patterns!"); + ret = G_SOURCE_REMOVE; + goto done; +} + +/* Start adding devices every %NEW_DEVICE_INTERVAL seconds. + * We will stop once we have consumed all the available videotestsrc + * patterns, or when our #GstDeviceProvider.stop() implementation is + * called. + */ +static gboolean +example_device_provider_start (GstDeviceProvider * provider) +{ + ExampleDeviceProvider *self = EXAMPLE_DEVICE_PROVIDER (provider); + GType element_type; + GTypeClass *element_class; + GParamSpec *pspec; + GEnumClass *value_class; + guint i; + + g_assert (!self->timeout_id); + + element_type = gst_element_factory_get_element_type (self->factory); + element_class = (GTypeClass *) g_type_class_ref (element_type); + pspec = + g_object_class_find_property ((GObjectClass *) element_class, "pattern"); + value_class = (GEnumClass *) g_type_class_ref (pspec->value_type); + + for (i = 0; i < value_class->n_values; i++) { + GEnumValue *val = &value_class->values[i]; + + self->patterns = g_list_append (self->patterns, g_strdup (val->value_nick)); + } + + g_type_class_unref (value_class); + g_type_class_unref (element_class); + + self->timeout_id = + g_timeout_add_seconds (NEW_DEVICE_INTERVAL, + (GSourceFunc) example_device_provider_next_device, self); + + return TRUE; +} + +/* Simply stop adding devices by removing our timeout. */ +static void +example_device_provider_stop (GstDeviceProvider * provider) +{ + ExampleDeviceProvider *self = EXAMPLE_DEVICE_PROVIDER (provider); + + g_assert (self->timeout_id); + + if (self->patterns) { + g_list_free_full (self->patterns, g_free); + self->patterns = NULL; + } + + g_source_remove (self->timeout_id); + self->timeout_id = 0; +} + +static void +example_device_provider_dispose (GObject * object) +{ + ExampleDeviceProvider *self = EXAMPLE_DEVICE_PROVIDER (object); + + gst_object_replace ((GstObject **) & self->factory, NULL); + + G_OBJECT_CLASS (example_device_provider_parent_class)->dispose (object); +} + +static void +example_device_provider_finalize (GObject * object) +{ + ExampleDeviceProvider *self = EXAMPLE_DEVICE_PROVIDER (object); + + if (self->patterns) + g_list_free_full (self->patterns, g_free); + + G_OBJECT_CLASS (example_device_provider_parent_class)->finalize (object); +} + +static void +example_device_provider_class_init (ExampleDeviceProviderClass * klass) +{ + GstDeviceProviderClass *dm_class = GST_DEVICE_PROVIDER_CLASS (klass); + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->dispose = GST_DEBUG_FUNCPTR (example_device_provider_dispose); + gobject_class->finalize = + GST_DEBUG_FUNCPTR (example_device_provider_finalize); + + dm_class->probe = GST_DEBUG_FUNCPTR (example_device_provider_probe); + dm_class->start = GST_DEBUG_FUNCPTR (example_device_provider_start); + dm_class->stop = GST_DEBUG_FUNCPTR (example_device_provider_stop); + + gst_device_provider_class_set_static_metadata (dm_class, + "Example Device Provider", "Source/Video", + "List and provides example source devices", + "Mathieu Duponchelle "); +} + +static gboolean +plugin_init (GstPlugin * plugin) +{ + return gst_device_provider_register (plugin, "exampledeviceprovider", + GST_RANK_PRIMARY, EXAMPLE_TYPE_DEVICE_PROVIDER); +} + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + example_device_provider, + "Example device provider", + plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) diff --git a/tests/examples/device-provider/meson.build b/tests/examples/device-provider/meson.build new file mode 100644 index 0000000..b96d561 --- /dev/null +++ b/tests/examples/device-provider/meson.build @@ -0,0 +1,6 @@ +library('example_device_provider', 'example-device-provider.c', + include_directories: [configinc], + c_args : gst_plugins_base_args, + install: false, + dependencies: [gst_dep], +) diff --git a/tests/examples/meson.build b/tests/examples/meson.build index 44d28e2..0cfc839 100644 --- a/tests/examples/meson.build +++ b/tests/examples/meson.build @@ -1,6 +1,7 @@ subdir('app') subdir('audio') subdir('compositor') +subdir('device-provider') subdir('dynamic') subdir('decodebin_next') subdir('encoding')