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
|
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],
|
||||||
|
|
|
@ -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 \
|
||||||
|
|
|
@ -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);
|
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;
|
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);
|
||||||
|
|
Loading…
Reference in a new issue