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 <QtMultimedia/private/qv4l2formats_p.h>
11#include <QtCore/qdebug.h>
12#include <QtCore/qdir.h>
13#include <QtCore/qfile.h>
14#include <QtCore/qloggingcategory.h>
15#include <QtCore/private/qcore_unix_p.h>
16
17#include <linux/videodev2.h>
18
19QT_BEGIN_NAMESPACE
20
21namespace QtV4L2 {
22
23Q_STATIC_LOGGING_CATEGORY(qLcV4L2CameraDevices, "qt.multimedia.v4l2.cameradevices");
24
25static bool areCamerasEqual(QSpan<const QCameraDevice> a, QSpan<const QCameraDevice> b)
26{
27 auto areCamerasDataEqual = [](const QCameraDevice &a, const QCameraDevice &b) {
28 Q_ASSERT(QCameraDevicePrivate::handle(a));
29 Q_ASSERT(QCameraDevicePrivate::handle(b));
30 return *QCameraDevicePrivate::handle(a) == *QCameraDevicePrivate::handle(b);
31 };
32
33 return std::equal(a.cbegin(), a.cend(), b.cbegin(), b.cend(), areCamerasDataEqual);
34}
35
44
49
55
57{
58 using namespace QtMultimediaPrivate;
59
61
62 QDir dir(QLatin1String("/dev"));
63 const auto devices = dir.entryList(QDir::System);
64
65 bool first = true;
66
67 for (auto device : devices) {
68 // qCDebug(qLcV4L2Camera) << "device:" << device;
69 if (!device.startsWith(QLatin1String("video")))
70 continue;
71
73 const int fd = open(file.constData(), O_RDONLY);
74 if (fd < 0)
75 continue;
76
77 auto fileCloseGuard = qScopeGuard([fd]() {
78 close(fd);
79 });
80
82
83 struct v4l2_capability cap;
84 if (qt_safe_ioctl(fd, VIDIOC_QUERYCAP, &cap) < 0)
85 continue;
86
87 if (cap.device_caps & V4L2_CAP_META_CAPTURE)
88 continue;
89 if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE))
90 continue;
91 if (!(cap.capabilities & V4L2_CAP_STREAMING))
92 continue;
93
95
96 camera->id = file;
97 camera->description = QString::fromUtf8((const char *)cap.card);
98 qCDebug(qLcV4L2CameraDevices) << "found camera" << camera->id << camera->description;
99
101
102 while (!qt_safe_ioctl(fd, VIDIOC_ENUM_FMT, &formatDesc)) {
105
108 continue;
109 }
110
111 qCDebug(qLcV4L2CameraDevices) << "frame sizes:";
114
115 while (!qt_safe_ioctl(fd, VIDIOC_ENUM_FRAMESIZES, &frameSize)) {
119 } else {
124 }
125
126 for (auto resolution : resolutions) {
127 float min = 1e10;
128 float max = 0;
130 const float rate = float(discreteFrameRate.denominator)
132 if (rate > max)
133 max = rate;
134 if (rate < min)
135 min = rate;
136 };
137
142
143 while (!qt_safe_ioctl(fd, VIDIOC_ENUM_FRAMEINTERVALS, &frameInterval)) {
146 } else {
149 }
151 }
152
154
155 if (min <= max) {
163 }
164 }
166 }
168 }
169
171 continue;
172
173 // first camera is default
174 camera->isDefault = std::exchange(first, false);
175
177 }
178
180 return false;
181
183 return true;
184}
185
186} // namespace QtV4L2
187
188QT_END_NAMESPACE
189
190#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)