mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-18 14:26:43 +00:00
v4lsrc: optional support for device probing with gudev
Enumerate v4l devices using gudev if available. Fixes bug #583640.
This commit is contained in:
parent
94baad7490
commit
0f29d71a7d
3 changed files with 108 additions and 8 deletions
23
configure.ac
23
configure.ac
|
@ -436,6 +436,29 @@ AG_GST_CHECK_FEATURE(GST_V4L, [Video 4 Linux], video4linux, [
|
||||||
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_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 *** ext plug-ins ***
|
||||||
dnl keep this list sorted alphabetically !
|
dnl keep this list sorted alphabetically !
|
||||||
|
|
||||||
|
|
|
@ -22,10 +22,12 @@ libgstvideo4linux_la_SOURCES = \
|
||||||
# gstv4lmjpegsink.c v4lmjpegsink_calls.c
|
# gstv4lmjpegsink.c v4lmjpegsink_calls.c
|
||||||
|
|
||||||
libgstvideo4linux_la_CFLAGS = \
|
libgstvideo4linux_la_CFLAGS = \
|
||||||
$(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) $(X_CFLAGS)
|
$(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) $(X_CFLAGS) \
|
||||||
|
$(GUDEV_CFLAGS)
|
||||||
libgstvideo4linux_la_LIBADD = \
|
libgstvideo4linux_la_LIBADD = \
|
||||||
$(top_builddir)/gst-libs/gst/interfaces/libgstinterfaces-$(GST_MAJORMINOR).la \
|
$(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_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
|
||||||
libgstvideo4linux_la_LIBTOOLFLAGS = --tag=disable-static
|
libgstvideo4linux_la_LIBTOOLFLAGS = --tag=disable-static
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,10 @@
|
||||||
|
|
||||||
#include <gst/interfaces/propertyprobe.h>
|
#include <gst/interfaces/propertyprobe.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_GUDEV
|
||||||
|
#include <gudev/gudev.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "v4l_calls.h"
|
#include "v4l_calls.h"
|
||||||
#include "gstv4ltuner.h"
|
#include "gstv4ltuner.h"
|
||||||
#ifdef HAVE_XVIDEO
|
#ifdef HAVE_XVIDEO
|
||||||
|
@ -48,6 +52,8 @@ enum
|
||||||
PROP_FLAGS
|
PROP_FLAGS
|
||||||
};
|
};
|
||||||
|
|
||||||
|
GST_DEBUG_CATEGORY (v4lelement_debug);
|
||||||
|
#define GST_CAT_DEFAULT v4lelement_debug
|
||||||
|
|
||||||
static void gst_v4lelement_init_interfaces (GType type);
|
static void gst_v4lelement_init_interfaces (GType type);
|
||||||
|
|
||||||
|
@ -108,20 +114,76 @@ gst_v4l_probe_get_properties (GstPropertyProbe * probe)
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean init = FALSE;
|
||||||
|
static GList *devices = NULL;
|
||||||
|
|
||||||
|
#ifdef HAVE_GUDEV
|
||||||
|
static gboolean
|
||||||
|
gst_v4l_class_probe_devices_with_udev (GstV4lElementClass * klass,
|
||||||
|
gboolean check)
|
||||||
|
{
|
||||||
|
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
|
static gboolean
|
||||||
gst_v4l_class_probe_devices (GstV4lElementClass * klass, gboolean check)
|
gst_v4l_class_probe_devices (GstV4lElementClass * klass, gboolean check)
|
||||||
{
|
{
|
||||||
static gboolean init = FALSE;
|
|
||||||
static GList *devices = NULL;
|
|
||||||
|
|
||||||
if (!check) {
|
if (!check) {
|
||||||
gchar *dev_base[] = { "/dev/video", "/dev/v4l/video", NULL };
|
gchar *dev_base[] = { "/dev/video", "/dev/v4l/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);
|
||||||
}
|
}
|
||||||
|
@ -163,7 +225,12 @@ gst_v4l_probe_probe_property (GstPropertyProbe * probe,
|
||||||
|
|
||||||
switch (prop_id) {
|
switch (prop_id) {
|
||||||
case PROP_DEVICE:
|
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);
|
gst_v4l_class_probe_devices (klass, FALSE);
|
||||||
|
#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);
|
||||||
|
@ -180,6 +247,11 @@ gst_v4l_probe_needs_probe (GstPropertyProbe * probe,
|
||||||
|
|
||||||
switch (prop_id) {
|
switch (prop_id) {
|
||||||
case PROP_DEVICE:
|
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);
|
ret = !gst_v4l_class_probe_devices (klass, TRUE);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -319,6 +391,9 @@ gst_v4lelement_base_init (gpointer g_class)
|
||||||
GstV4lElementClass *klass = GST_V4LELEMENT_CLASS (g_class);
|
GstV4lElementClass *klass = GST_V4LELEMENT_CLASS (g_class);
|
||||||
|
|
||||||
klass->devices = NULL;
|
klass->devices = NULL;
|
||||||
|
|
||||||
|
GST_DEBUG_CATEGORY_INIT (v4lelement_debug, "v4lelement", 0,
|
||||||
|
"V4L Base Class debug");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
Loading…
Reference in a new issue