summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFilippo Argiolas <filippo.argiolas@gmail.com>2009-07-03 08:38:43 +0200
committerFilippo Argiolas <filippo.argiolas@gmail.com>2009-07-13 16:16:05 +0200
commit946c20a8ba9d5266b45378c38f2882352c65b79d (patch)
tree0b5a1b8137deed471b1680978f4663c720f5ab40
parent91ad86c0f951e72a25265e7f16e50725a1ea546e (diff)
v4l2src: optional support for device probing with gudev
Enumerate v4l2 devices using gudev if available. Fixes bug #583640.
-rw-r--r--configure.ac23
-rw-r--r--sys/v4l2/Makefile.am6
-rw-r--r--sys/v4l2/gstv4l2object.c85
3 files changed, 106 insertions, 8 deletions
diff --git a/configure.ac b/configure.ac
index fb9bbf891..c43d77073 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 ed9c3ec30..20ec54867 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 d848ccf33..b9a18cc07 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);