Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Toggle main menu visibility
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
4
#
include
"qv4l2cameradevices_p.h"
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
19
QT_BEGIN_NAMESPACE
20
21
namespace
QtV4L2
{
22
23
Q_STATIC_LOGGING_CATEGORY
(
qLcV4L2CameraDevices
,
"qt.multimedia.v4l2.cameradevices"
);
24
25
static
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
36
QV4L2CameraDevices
::
QV4L2CameraDevices
(
QPlatformMediaIntegration
*
integration
)
37
:
QPlatformVideoDevices
(
integration
)
38
{
39
m_deviceWatcher
.
addPath
(
QLatin1String
(
"/dev"
));
40
connect
(&
m_deviceWatcher
, &
QFileSystemWatcher
::
directoryChanged
,
this
,
41
&
QV4L2CameraDevices
::
checkCameras
);
42
doCheckCameras
();
43
}
44
45
QList
<
QCameraDevice
>
QV4L2CameraDevices
::
findVideoInputs
()
const
46
{
47
return
m_cameras
;
48
}
49
50
void
QV4L2CameraDevices
::
checkCameras
()
51
{
52
if
(
doCheckCameras
())
53
onVideoInputsChanged
();
54
}
55
56
bool
QV4L2CameraDevices
::
doCheckCameras
()
57
{
58
using
namespace
QtMultimediaPrivate
;
59
60
QList
<
QCameraDevice
>
newCameras
;
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
72
QByteArray
file
=
QFile
::
encodeName
(
dir
.
filePath
(
device
));
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
81
v4l2_fmtdesc
formatDesc
= {};
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
94
auto
camera
=
std
::
make_unique
<
QCameraDevicePrivate
>();
95
96
camera
->
id
=
file
;
97
camera
->
description
=
QString
::
fromUtf8
((
const
char
*)
cap
.
card
);
98
qCDebug
(
qLcV4L2CameraDevices
) <<
"found camera"
<<
camera
->
id
<<
camera
->
description
;
99
100
formatDesc
.
type
=
V4L2_BUF_TYPE_VIDEO_CAPTURE
;
101
102
while
(!
qt_safe_ioctl
(
fd
, VIDIOC_ENUM_FMT, &
formatDesc
)) {
103
auto
pixelFmt
=
formatForV4L2Format
(
formatDesc
.
pixelformat
);
104
qCDebug
(
qLcV4L2CameraDevices
) <<
" "
<<
pixelFmt
;
105
106
if
(
pixelFmt
==
QVideoFrameFormat
::
Format_Invalid
) {
107
++
formatDesc
.
index
;
108
continue
;
109
}
110
111
qCDebug
(
qLcV4L2CameraDevices
) <<
"frame sizes:"
;
112
v4l2_frmsizeenum
frameSize
= {};
113
frameSize
.
pixel_format
=
formatDesc
.
pixelformat
;
114
115
while
(!
qt_safe_ioctl
(
fd
, VIDIOC_ENUM_FRAMESIZES, &
frameSize
)) {
116
QList
<
QSize
>
resolutions
;
117
if
(
frameSize
.
type
==
V4L2_FRMSIZE_TYPE_DISCRETE
) {
118
resolutions
.
append
(
QSize
(
frameSize
.
discrete
.
width
,
frameSize
.
discrete
.
height
));
119
}
else
{
120
resolutions
.
append
(
121
QSize
(
frameSize
.
stepwise
.
max_width
,
frameSize
.
stepwise
.
max_height
));
122
resolutions
.
append
(
123
QSize
(
frameSize
.
stepwise
.
min_width
,
frameSize
.
stepwise
.
min_height
));
124
}
125
126
for
(
auto
resolution
:
resolutions
) {
127
float
min
= 1e10;
128
float
max
= 0;
129
auto
updateMaxMinFrameRate
= [&
max
, &
min
](
auto
discreteFrameRate
) {
130
const
float
rate
=
float
(
discreteFrameRate
.
denominator
)
131
/
float
(
discreteFrameRate
.
numerator
);
132
if
(
rate
>
max
)
133
max
=
rate
;
134
if
(
rate
<
min
)
135
min
=
rate
;
136
};
137
138
v4l2_frmivalenum
frameInterval
= {};
139
frameInterval
.
pixel_format
=
formatDesc
.
pixelformat
;
140
frameInterval
.
width
=
resolution
.
width
();
141
frameInterval
.
height
=
resolution
.
height
();
142
143
while
(!
qt_safe_ioctl
(
fd
, VIDIOC_ENUM_FRAMEINTERVALS, &
frameInterval
)) {
144
if
(
frameInterval
.
type
==
V4L2_FRMIVAL_TYPE_DISCRETE
) {
145
updateMaxMinFrameRate
(
frameInterval
.
discrete
);
146
}
else
{
147
updateMaxMinFrameRate
(
frameInterval
.
stepwise
.
max
);
148
updateMaxMinFrameRate
(
frameInterval
.
stepwise
.
min
);
149
}
150
++
frameInterval
.
index
;
151
}
152
153
qCDebug
(
qLcV4L2CameraDevices
) <<
" "
<<
resolution
<<
min
<<
max
;
154
155
if
(
min
<=
max
) {
156
auto
fmt
=
std
::
make_unique
<
QCameraFormatPrivate
>();
157
fmt
->
pixelFormat
=
pixelFmt
;
158
fmt
->
resolution
=
resolution
;
159
fmt
->
minFrameRate
=
min
;
160
fmt
->
maxFrameRate
=
max
;
161
camera
->
videoFormats
.
append
(
fmt
.
release
()->
create
());
162
camera
->
photoResolutions
.
append
(
resolution
);
163
}
164
}
165
++
frameSize
.
index
;
166
}
167
++
formatDesc
.
index
;
168
}
169
170
if
(
camera
->
videoFormats
.
empty
())
171
continue
;
172
173
// first camera is default
174
camera
->
isDefault
=
std
::
exchange
(
first
,
false
);
175
176
newCameras
.
append
(
camera
.
release
()->
create
());
177
}
178
179
if
(
areCamerasEqual
(
m_cameras
,
newCameras
))
180
return
false
;
181
182
m_cameras
=
std
::
move
(
newCameras
);
183
return
true
;
184
}
185
186
}
// namespace QtV4L2
187
188
QT_END_NAMESPACE
189
190
#
include
"moc_qv4l2cameradevices_p.cpp"
QtV4L2
Definition
qv4l2camera.cpp:22
QtV4L2::Q_STATIC_LOGGING_CATEGORY
Q_STATIC_LOGGING_CATEGORY(qLcV4L2Camera, "qt.multimedia.v4l2.camera")
QtV4L2::areCamerasEqual
static bool areCamerasEqual(QSpan< const QCameraDevice > a, QSpan< const QCameraDevice > b)
Definition
qv4l2cameradevices.cpp:25
qtmultimedia
src
multimedia
v4l2
qv4l2cameradevices.cpp
Generated on
for Qt by
1.18.0