mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-30 13:41:48 +00:00
v4l2src: optional support for device probing with gudev
Enumerate v4l2 devices using gudev if available. Fixes bug #583640.
This commit is contained in:
parent
91ad86c0f9
commit
946c20a8ba
3 changed files with 106 additions and 8 deletions
23
configure.ac
23
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],
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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_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
|
||||
gst_v4l2_class_probe_devices (GstElementClass * klass, gboolean check,
|
||||
GList ** klass_devices)
|
||||
{
|
||||
static gboolean init = FALSE;
|
||||
static GList *devices = NULL;
|
||||
|
||||
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);
|
||||
|
|
Loading…
Reference in a new issue