From 11fb0a4cb7b71c93667b970c4019ecc3d324b3f5 Mon Sep 17 00:00:00 2001 From: Peter Johnson Date: Sat, 13 Jun 2020 20:51:46 -0700 Subject: [PATCH] [cscore] EnumerateUsbCameras(): Only list capture devices (#2532) Previously this would list ALL /dev/video* devices. In recent versions of Linux this leads to listing duplicate devices, as many USB cameras provide both a video device and a metadata device, and only the video device can actually be used for streaming. --- .../src/main/native/linux/UsbCameraImpl.cpp | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/cscore/src/main/native/linux/UsbCameraImpl.cpp b/cscore/src/main/native/linux/UsbCameraImpl.cpp index 83bff75c68..453a37243c 100644 --- a/cscore/src/main/native/linux/UsbCameraImpl.cpp +++ b/cscore/src/main/native/linux/UsbCameraImpl.cpp @@ -223,6 +223,25 @@ static bool GetDescriptionIoctl(const char* cpath, std::string* desc) { return true; } +static bool IsVideoCaptureDevice(const char* cpath) { + int fd = open(cpath, O_RDWR); + if (fd < 0) return false; + + struct v4l2_capability vcap; + std::memset(&vcap, 0, sizeof(vcap)); + if (DoIoctl(fd, VIDIOC_QUERYCAP, &vcap) < 0) { + close(fd); + return false; + } + close(fd); + + return (vcap.capabilities & V4L2_CAP_VIDEO_CAPTURE) != 0 && + (vcap.capabilities & V4L2_CAP_STREAMING) != 0 && + ((vcap.capabilities & V4L2_CAP_DEVICE_CAPS) == 0 || + ((vcap.device_caps & V4L2_CAP_VIDEO_CAPTURE) != 0 && + (vcap.device_caps & V4L2_CAP_STREAMING) != 0)); +} + static int GetDeviceNum(const char* cpath) { wpi::StringRef path{cpath}; std::string pathBuf; @@ -1453,6 +1472,8 @@ std::vector EnumerateUsbCameras(CS_Status* status) { path += fname; info.path = path.str(); + if (!IsVideoCaptureDevice(path.c_str())) continue; + info.name = GetDescriptionImpl(path.c_str()); if (info.name.empty()) continue;