[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.
This commit is contained in:
Peter Johnson
2020-06-13 20:51:46 -07:00
committed by GitHub
parent 1557a4c3b0
commit 11fb0a4cb7

View File

@@ -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<UsbCameraInfo> 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;