v4l2src: optional support for device probing with gudev

Enumerate v4l2 devices using gudev if available.

Fixes bug #583640.
This commit is contained in:
Filippo Argiolas 2009-07-03 08:38:43 +02:00
parent 91ad86c0f9
commit 946c20a8ba
3 changed files with 106 additions and 8 deletions

View file

@ -508,6 +508,29 @@ return 0;
fi 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 # Make libv4l2 non-automagic
AC_ARG_WITH([libv4l2], AC_ARG_WITH([libv4l2],
AC_HELP_STRING([--with-libv4l2], AC_HELP_STRING([--with-libv4l2],

View file

@ -23,7 +23,8 @@ libgstvideo4linux2_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) \
$(GST_BASE_CFLAGS) \ $(GST_BASE_CFLAGS) \
$(GST_CFLAGS) \ $(GST_CFLAGS) \
$(X_CFLAGS) \ $(X_CFLAGS) \
$(LIBV4L2_CFLAGS) $(LIBV4L2_CFLAGS) \
$(GUDEV_CFLAGS)
libgstvideo4linux2_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) libgstvideo4linux2_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
libgstvideo4linux2_la_LIBTOOLFLAGS = --tag=disable-static libgstvideo4linux2_la_LIBTOOLFLAGS = --tag=disable-static
@ -33,7 +34,8 @@ libgstvideo4linux2_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) \
-lgstinterfaces-$(GST_MAJORMINOR) \ -lgstinterfaces-$(GST_MAJORMINOR) \
$(GST_LIBS) \ $(GST_LIBS) \
$(xv_libs) \ $(xv_libs) \
$(LIBV4L2_LIBS) $(LIBV4L2_LIBS) \
$(GUDEV_LIBS)
noinst_HEADERS = gstv4l2object.h v4l2_calls.h \ noinst_HEADERS = gstv4l2object.h v4l2_calls.h \
gstv4l2src.h v4l2src_calls.h \ gstv4l2src.h v4l2src_calls.h \

View file

@ -28,6 +28,10 @@
#include <unistd.h> #include <unistd.h>
#include <string.h> #include <string.h>
#ifdef HAVE_GUDEV
#include <gudev/gudev.h>
#endif
#include "v4l2_calls.h" #include "v4l2_calls.h"
#include "gstv4l2tuner.h" #include "gstv4l2tuner.h"
#if 0 /* overlay is still not implemented #ifdef HAVE_XVIDEO */ #if 0 /* overlay is still not implemented #ifdef HAVE_XVIDEO */
@ -49,6 +53,9 @@ enum
V4L2_STD_OBJECT_PROPS, V4L2_STD_OBJECT_PROPS,
}; };
GST_DEBUG_CATEGORY_EXTERN (v4l2src_debug);
#define GST_CAT_DEFAULT v4l2src_debug
const GList * const GList *
gst_v4l2_probe_get_properties (GstPropertyProbe * probe) gst_v4l2_probe_get_properties (GstPropertyProbe * probe)
{ {
@ -68,21 +75,77 @@ gst_v4l2_probe_get_properties (GstPropertyProbe * probe)
return list; return list;
} }
static gboolean init = FALSE;
static GList *devices = NULL;
#ifdef HAVE_GUDEV
static gboolean
gst_v4l2_class_probe_devices_with_udev (GstElementClass * klass, gboolean check,
GList ** klass_devices)
{
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 static gboolean
gst_v4l2_class_probe_devices (GstElementClass * klass, gboolean check, gst_v4l2_class_probe_devices (GstElementClass * klass, gboolean check,
GList ** klass_devices) GList ** klass_devices)
{ {
static gboolean init = FALSE;
static GList *devices = NULL;
if (!check) { if (!check) {
const gchar *dev_base[] = { "/dev/video", "/dev/v4l2/video", NULL }; const gchar *dev_base[] = { "/dev/video", "/dev/v4l2/video", NULL };
gint base, n, fd; gint base, n, fd;
while (devices) { while (devices) {
GList *item = devices; gchar *device = devices->data;
gchar *device = item->data;
devices = g_list_remove (devices, device); devices = g_list_remove (devices, device);
g_free (device); g_free (device);
} }
@ -134,7 +197,12 @@ gst_v4l2_probe_probe_property (GstPropertyProbe * probe,
switch (prop_id) { switch (prop_id) {
case PROP_DEVICE: 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); gst_v4l2_class_probe_devices (klass, FALSE, klass_devices);
#endif /* HAVE_GUDEV */
break; break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec);
@ -151,7 +219,12 @@ gst_v4l2_probe_needs_probe (GstPropertyProbe * probe,
switch (prop_id) { switch (prop_id) {
case PROP_DEVICE: 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); ret = !gst_v4l2_class_probe_devices (klass, TRUE, klass_devices);
#endif /* HAVE_GUDEV */
break; break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec);