From 0f29d71a7db24f620d61aa92e376e974d6769d22 Mon Sep 17 00:00:00 2001 From: Filippo Argiolas Date: Fri, 3 Jul 2009 11:38:01 +0200 Subject: [PATCH] v4lsrc: optional support for device probing with gudev Enumerate v4l devices using gudev if available. Fixes bug #583640. --- configure.ac | 23 +++++++++++++ sys/v4l/Makefile.am | 6 ++-- sys/v4l/gstv4lelement.c | 87 +++++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 108 insertions(+), 8 deletions(-) diff --git a/configure.ac b/configure.ac index da8f539..5b9c84f 100644 --- a/configure.ac +++ b/configure.ac @@ -436,6 +436,29 @@ AG_GST_CHECK_FEATURE(GST_V4L, [Video 4 Linux], video4linux, [ fi ]) +# Optional gudev for device probing +AC_ARG_WITH([gudev], + AC_HELP_STRING([--with-gudev], + [device detection with gudev]), + [], + [with_gudev=check]) +if test x$HAVE_GST_V4L = xyes; then + if test x$with_gudev != xno; then + PKG_CHECK_MODULES(GUDEV, [ gudev-1.0 >= 143 ], + [ have_gudev=yes + AC_DEFINE(HAVE_GUDEV, 1, + [Whether gudev is available for device detection]) + AC_DEFINE([G_UDEV_API_IS_SUBJECT_TO_CHANGE], 1, [I know the API is subject to change.]) + ], [ + have_gudev=no + ]) + else + have_gudev=no + fi +fi +AC_SUBST(GUDEV_CFLAGS) +AC_SUBST(GUDEV_LIBS) + dnl *** ext plug-ins *** dnl keep this list sorted alphabetically ! diff --git a/sys/v4l/Makefile.am b/sys/v4l/Makefile.am index fc10694..688ec96 100644 --- a/sys/v4l/Makefile.am +++ b/sys/v4l/Makefile.am @@ -22,10 +22,12 @@ libgstvideo4linux_la_SOURCES = \ # gstv4lmjpegsink.c v4lmjpegsink_calls.c libgstvideo4linux_la_CFLAGS = \ - $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) $(X_CFLAGS) + $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) $(X_CFLAGS) \ + $(GUDEV_CFLAGS) libgstvideo4linux_la_LIBADD = \ $(top_builddir)/gst-libs/gst/interfaces/libgstinterfaces-$(GST_MAJORMINOR).la \ - $(GST_BASE_LIBS) $(GST_LIBS) $(xv_libs) + $(GST_BASE_LIBS) $(GST_LIBS) $(xv_libs) \ + $(GUDEV_LIBS) libgstvideo4linux_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) libgstvideo4linux_la_LIBTOOLFLAGS = --tag=disable-static diff --git a/sys/v4l/gstv4lelement.c b/sys/v4l/gstv4lelement.c index f536aaa..81a76d4 100644 --- a/sys/v4l/gstv4lelement.c +++ b/sys/v4l/gstv4lelement.c @@ -32,6 +32,10 @@ #include +#ifdef HAVE_GUDEV +#include +#endif + #include "v4l_calls.h" #include "gstv4ltuner.h" #ifdef HAVE_XVIDEO @@ -48,6 +52,8 @@ enum PROP_FLAGS }; +GST_DEBUG_CATEGORY (v4lelement_debug); +#define GST_CAT_DEFAULT v4lelement_debug static void gst_v4lelement_init_interfaces (GType type); @@ -108,20 +114,76 @@ gst_v4l_probe_get_properties (GstPropertyProbe * probe) return list; } +static gboolean init = FALSE; +static GList *devices = NULL; + +#ifdef HAVE_GUDEV static gboolean -gst_v4l_class_probe_devices (GstV4lElementClass * klass, gboolean check) +gst_v4l_class_probe_devices_with_udev (GstV4lElementClass * klass, + gboolean check) { - static gboolean init = FALSE; - static GList *devices = NULL; + GUdevClient *client; + GList *item; + + if (!check) { + while (devices) { + gchar *device = devices->data; + devices = g_list_remove (devices, device); + g_free (device); + } + + GST_INFO ("Enumerating video4linux devices from udev"); + client = g_udev_client_new (NULL); + if (!client) { + GST_WARNING ("Failed to initialize gudev client"); + goto finish; + } + + item = g_udev_client_query_by_subsystem (client, "video4linux"); + while (item) { + GUdevDevice *device = item->data; + gchar *devnode = g_strdup (g_udev_device_get_device_file (device)); + gint api = g_udev_device_get_property_as_int (device, "ID_V4L_VERSION"); + GST_INFO ("Found new device: %s, API: %d", devnode, api); + /* Append v4l1 devices only. If api is 0 probably v4l_id has + been stripped out of the current udev installation, append + anyway */ + if (api == 0) { + GST_WARNING + ("Couldn't retrieve ID_V4L_VERSION, silly udev installation?"); + } + if ((api == 1 || api == 0)) { + devices = g_list_append (devices, devnode); + } else { + g_free (devnode); + } + g_object_unref (device); + item = item->next; + } + g_list_free (item); + init = TRUE; + } + +finish: + if (client) { + g_object_unref (client); + } + + klass->devices = devices; + + return init; +} +#endif /* HAVE_GUDEV */ +static gboolean +gst_v4l_class_probe_devices (GstV4lElementClass * klass, gboolean check) +{ if (!check) { gchar *dev_base[] = { "/dev/video", "/dev/v4l/video", NULL }; gint base, n, fd; while (devices) { - GList *item = devices; - gchar *device = item->data; - + gchar *device = devices->data; devices = g_list_remove (devices, device); g_free (device); } @@ -163,7 +225,12 @@ gst_v4l_probe_probe_property (GstPropertyProbe * probe, switch (prop_id) { case PROP_DEVICE: +#ifdef HAVE_GUDEV + if (!gst_v4l_class_probe_devices_with_udev (klass, FALSE)) + gst_v4l_class_probe_devices (klass, FALSE); +#else /* !HAVE_GUDEV */ gst_v4l_class_probe_devices (klass, FALSE); +#endif /* HAVE_GUDEV */ break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec); @@ -180,6 +247,11 @@ gst_v4l_probe_needs_probe (GstPropertyProbe * probe, switch (prop_id) { case PROP_DEVICE: +#ifdef HAVE_GUDEV + ret = !gst_v4l_class_probe_devices_with_udev (klass, FALSE); +#else /* !HAVE_GUDEV */ + ret = !gst_v4l_class_probe_devices (klass, TRUE); +#endif /* HAVE_GUDEV */ ret = !gst_v4l_class_probe_devices (klass, TRUE); break; default: @@ -319,6 +391,9 @@ gst_v4lelement_base_init (gpointer g_class) GstV4lElementClass *klass = GST_V4LELEMENT_CLASS (g_class); klass->devices = NULL; + + GST_DEBUG_CATEGORY_INIT (v4lelement_debug, "v4lelement", 0, + "V4L Base Class debug"); } static void -- 2.7.4