Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qv4l2cameradevices.cpp
Go to the documentation of this file.
1// Copyright (C) 2023 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
5
6#include <QtMultimedia/private/qcameradevice_p.h>
7#include <QtMultimedia/private/qmultimediautils_p.h>
8#include <QtMultimedia/private/qv4l2camera_p.h>
9#include <QtMultimedia/private/qv4l2filedescriptor_p.h>
10#include <QtCore/qdebug.h>
11#include <QtCore/qdir.h>
12#include <QtCore/qfile.h>
13#include <QtCore/qloggingcategory.h>
14#include <QtCore/private/qcore_unix_p.h>
15
16#include <linux/videodev2.h>
17
18QT_BEGIN_NAMESPACE
19
20namespace QtV4L2 {
21
22Q_STATIC_LOGGING_CATEGORY(qLcV4L2CameraDevices, "qt.multimedia.v4l2.cameradevices");
23
24static bool areCamerasEqual(QSpan<const QCameraDevice> a, QSpan<const QCameraDevice> b)
25{
26 auto areCamerasDataEqual = [](const QCameraDevice &a, const QCameraDevice &b) {
27 Q_ASSERT(QCameraDevicePrivate::handle(a));
28 Q_ASSERT(QCameraDevicePrivate::handle(b));
29 return *QCameraDevicePrivate::handle(a) == *QCameraDevicePrivate::handle(b);
30 };
31
32 return std::equal(a.cbegin(), a.cend(), b.cbegin(), b.cend(), areCamerasDataEqual);
33}
34
43
48
54
56{
57 using namespace QtMultimediaPrivate;
58
60
61 QDir dir(QLatin1String("/dev"));
62 const auto devices = dir.entryList(QDir::System);
63
64 bool first = true;
65
66 for (auto device : devices) {
67 // qCDebug(qLcV4L2Camera) << "device:" << device;
68 if (!device.startsWith(QLatin1String("video")))
69 continue;
70
72 const int fd = open(file.constData(), O_RDONLY);
73 if (fd < 0)
74 continue;
75
76 auto fileCloseGuard = qScopeGuard([fd]() {
77 close(fd);
78 });
79
81
82 struct v4l2_capability cap;
83 if (qt_safe_ioctl(fd, VIDIOC_QUERYCAP, &cap) < 0)
84 continue;
85
86 if (cap.device_caps & V4L2_CAP_META_CAPTURE)
87 continue;
88 if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE))
89 continue;
90 if (!(cap.capabilities & V4L2_CAP_STREAMING))
91 continue;
92
94
95 camera->id = file;
96 camera->description = QString::fromUtf8((const char *)cap.card);
97 qCDebug(qLcV4L2CameraDevices) << "found camera" << camera->id << camera->description;
98
100
101 while (!qt_safe_ioctl(fd, VIDIOC_ENUM_FMT, &formatDesc)) {
104
107 continue;
108 }
109
110 qCDebug(qLcV4L2CameraDevices) << "frame sizes:";
113
114 while (!qt_safe_ioctl(fd, VIDIOC_ENUM_FRAMESIZES, &frameSize)) {
118 } else {
123 }
124
125 for (auto resolution : resolutions) {
126 float min = 1e10;
127 float max = 0;
129 const float rate = float(discreteFrameRate.denominator)
131 if (rate > max)
132 max = rate;
133 if (rate < min)
134 min = rate;
135 };
136
141
142 while (!qt_safe_ioctl(fd, VIDIOC_ENUM_FRAMEINTERVALS, &frameInterval)) {
145 } else {
148 }
150 }
151
153
154 if (min <= max) {
162 }
163 }
165 }
167 }
168
170 continue;
171
172 // first camera is default
173 camera->isDefault = std::exchange(first, false);
174
176 }
177
179 return false;
180
182 return true;
183}
184
185} // namespace QtV4L2
186
187QT_END_NAMESPACE
188
189#include "moc_qv4l2cameradevices_p.cpp"
Q_STATIC_LOGGING_CATEGORY(qLcV4L2Camera, "qt.multimedia.v4l2.camera")
static bool areCamerasEqual(QSpan< const QCameraDevice > a, QSpan< const QCameraDevice > b)