diff options
| -rw-r--r-- | configure.ac | 23 | ||||
| -rw-r--r-- | sys/v4l2/Makefile.am | 6 | ||||
| -rw-r--r-- | sys/v4l2/gstv4l2object.c | 85 | 
3 files changed, 106 insertions, 8 deletions
diff --git a/configure.ac b/configure.ac index fb9bbf89..c43d7707 100644 --- a/configure.ac +++ b/configure.ac @@ -508,6 +508,29 @@ return 0;    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_V4L2 = 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) +  # Make libv4l2 non-automagic  AC_ARG_WITH([libv4l2],    AC_HELP_STRING([--with-libv4l2], diff --git a/sys/v4l2/Makefile.am b/sys/v4l2/Makefile.am index ed9c3ec3..20ec5486 100644 --- a/sys/v4l2/Makefile.am +++ b/sys/v4l2/Makefile.am @@ -23,7 +23,8 @@ libgstvideo4linux2_la_CFLAGS =   $(GST_PLUGINS_BASE_CFLAGS) \  				 $(GST_BASE_CFLAGS) \  				 $(GST_CFLAGS) \  				 $(X_CFLAGS) \ -				 $(LIBV4L2_CFLAGS) +				 $(LIBV4L2_CFLAGS) \ +				 $(GUDEV_CFLAGS)  libgstvideo4linux2_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)  libgstvideo4linux2_la_LIBTOOLFLAGS = --tag=disable-static @@ -33,7 +34,8 @@ libgstvideo4linux2_la_LIBADD =   $(GST_PLUGINS_BASE_LIBS) \  				 -lgstinterfaces-$(GST_MAJORMINOR) \  				 $(GST_LIBS) \  				 $(xv_libs) \ -				 $(LIBV4L2_LIBS) +				 $(LIBV4L2_LIBS) \ +				 $(GUDEV_LIBS)  noinst_HEADERS = gstv4l2object.h v4l2_calls.h \  		 gstv4l2src.h v4l2src_calls.h \ diff --git a/sys/v4l2/gstv4l2object.c b/sys/v4l2/gstv4l2object.c index d848ccf3..b9a18cc0 100644 --- a/sys/v4l2/gstv4l2object.c +++ b/sys/v4l2/gstv4l2object.c @@ -28,6 +28,10 @@  #include <unistd.h>  #include <string.h> +#ifdef HAVE_GUDEV +#include <gudev/gudev.h> +#endif +  #include "v4l2_calls.h"  #include "gstv4l2tuner.h"  #if 0                           /* overlay is still not implemented #ifdef HAVE_XVIDEO */ @@ -49,6 +53,9 @@ enum    V4L2_STD_OBJECT_PROPS,  }; +GST_DEBUG_CATEGORY_EXTERN (v4l2src_debug); +#define GST_CAT_DEFAULT v4l2src_debug +  const GList *  gst_v4l2_probe_get_properties (GstPropertyProbe * probe)  { @@ -68,21 +75,77 @@ gst_v4l2_probe_get_properties (GstPropertyProbe * probe)    return list;  } +static gboolean init = FALSE; +static GList *devices = NULL; + +#ifdef HAVE_GUDEV  static gboolean -gst_v4l2_class_probe_devices (GstElementClass * klass, gboolean check, +gst_v4l2_class_probe_devices_with_udev (GstElementClass * klass, gboolean check,      GList ** klass_devices)  { -  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 v4l2 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 == 2 || 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_v4l2_class_probe_devices (GstElementClass * klass, gboolean check, +    GList ** klass_devices) +{ +  if (!check) {      const gchar *dev_base[] = { "/dev/video", "/dev/v4l2/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);      } @@ -134,7 +197,12 @@ gst_v4l2_probe_probe_property (GstPropertyProbe * probe,    switch (prop_id) {      case PROP_DEVICE: +#ifdef HAVE_GUDEV +      if (!gst_v4l2_class_probe_devices_with_udev (klass, FALSE, klass_devices)) +        gst_v4l2_class_probe_devices (klass, FALSE, klass_devices); +#else /* !HAVE_GUDEV */        gst_v4l2_class_probe_devices (klass, FALSE, klass_devices); +#endif /* HAVE_GUDEV */        break;      default:        G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec); @@ -151,7 +219,12 @@ gst_v4l2_probe_needs_probe (GstPropertyProbe * probe,    switch (prop_id) {      case PROP_DEVICE: +#ifdef HAVE_GUDEV +      ret = +          !gst_v4l2_class_probe_devices_with_udev (klass, FALSE, klass_devices); +#else /* !HAVE_GUDEV */        ret = !gst_v4l2_class_probe_devices (klass, TRUE, klass_devices); +#endif /* HAVE_GUDEV */        break;      default:        G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec);  | 
