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
qwindowsvideodevices.cpp
Go to the documentation of this file.
1
// Copyright (C) 2022 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
"qwindowsvideodevices_p.h"
5
6
#
include
<
QtCore
/
quuid
.
h
>
7
#
include
<
QtCore
/
private
/
qcomptr_p
.
h
>
8
#
include
<
QtCore
/
private
/
qfunctions_win_p
.
h
>
9
#
include
<
QtMultimedia
/
private
/
qcameradevice_p
.
h
>
10
#
include
<
QtMultimedia
/
private
/
qcomtaskresource_p
.
h
>
11
#
include
<
QtMultimedia
/
private
/
qwindowsmultimediautils_p
.
h
>
12
13
#
include
<
dbt
.
h
>
14
15
#
include
<
mfapi
.
h
>
16
#
include
<
mfidl
.
h
>
17
#
include
<
mfreadwrite
.
h
>
18
#
include
<
mferror
.
h
>
19
#
include
<
ks
.
h
>
20
21
// MinGW-13.1 workaround
22
#
ifndef
KSCATEGORY_SENSOR_CAMERA
23
static
constexpr
GUID KSCATEGORY_SENSOR_CAMERA = {
24
0x24e552d7, 0x6523, 0x47f7, { 0xa6, 0x47, 0xd3, 0x46, 0x5b, 0xf1, 0xf5, 0xca }
25
};
26
#
endif
27
28
QT_BEGIN_NAMESPACE
29
30
namespace
{
31
32
LRESULT QT_WIN_CALLBACK deviceNotificationWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
33
{
34
if
(message == WM_DEVICECHANGE) {
35
auto
b = (PDEV_BROADCAST_HDR)lParam;
36
if
(b && b->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) {
37
auto
wmd =
reinterpret_cast
<QWindowsVideoDevices *>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
38
if
(wmd) {
39
if
(wParam == DBT_DEVICEARRIVAL || wParam == DBT_DEVICEREMOVECOMPLETE) {
40
wmd->onVideoInputsChanged();
41
}
42
}
43
}
44
}
45
46
return
1;
47
}
48
49
LPCWSTR
getWindowsClassName
()
50
{
51
// each Qt instance should have its own window class name to prevent name clashes when multiple
52
// qt instances are used in the same process.
53
// appending a uuid is good enough to ensure that.
54
static
const
std::wstring singleton =
55
QString(QStringLiteral(
"QWindowsMediaDevicesMessageWindow_"
)
56
+ QUuid::createUuid().toString())
57
.toStdWString();
58
Q_ASSERT(singleton.size() < 256 &&
"The maximum length for lpszClassName is 256"
);
59
return
singleton.c_str();
60
}
61
62
HWND
createMessageOnlyWindow
()
63
{
64
WNDCLASSEX wx = {};
65
wx.cbSize =
sizeof
(WNDCLASSEX);
66
wx.lpfnWndProc = deviceNotificationWndProc;
67
wx.hInstance = GetModuleHandle(
nullptr
);
68
wx.lpszClassName = getWindowsClassName();
69
70
if
(!RegisterClassEx(&wx))
71
return
nullptr
;
72
73
auto
hwnd = CreateWindowEx(0, getWindowsClassName(), TEXT(
"Message"
), 0, 0, 0, 0, 0,
74
HWND_MESSAGE,
nullptr
,
nullptr
,
nullptr
);
75
if
(!hwnd) {
76
UnregisterClass(getWindowsClassName(), GetModuleHandle(
nullptr
));
77
return
nullptr
;
78
}
79
80
return
hwnd;
81
}
82
83
}
// namespace
84
85
QWindowsVideoDevices
::QWindowsVideoDevices(QPlatformMediaIntegration *integration)
86
: QPlatformVideoDevices(integration)
87
{
88
qt_win_ensureComInitializedOnThisThread();
89
90
m_videoDeviceMsgWindow = createMessageOnlyWindow();
91
if
(m_videoDeviceMsgWindow) {
92
SetWindowLongPtr(m_videoDeviceMsgWindow, GWLP_USERDATA, (LONG_PTR)
this
);
93
94
DEV_BROADCAST_DEVICEINTERFACE di = {};
95
di.dbcc_size =
sizeof
(di);
96
di.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
97
di.dbcc_classguid = KSCATEGORY_VIDEO_CAMERA;
98
99
m_videoDeviceNotification =
100
RegisterDeviceNotification(m_videoDeviceMsgWindow, &di, DEVICE_NOTIFY_WINDOW_HANDLE);
101
if
(!m_videoDeviceNotification) {
102
DestroyWindow(m_videoDeviceMsgWindow);
103
m_videoDeviceMsgWindow =
nullptr
;
104
105
UnregisterClass(getWindowsClassName(), GetModuleHandle(
nullptr
));
106
}
107
}
108
109
if
(!m_videoDeviceNotification) {
110
qWarning() <<
"Video device change notification disabled"
;
111
}
112
}
113
114
QWindowsVideoDevices
::~
QWindowsVideoDevices
()
115
{
116
if
(m_videoDeviceNotification) {
117
UnregisterDeviceNotification(m_videoDeviceNotification);
118
}
119
120
if
(m_videoDeviceMsgWindow) {
121
DestroyWindow(m_videoDeviceMsgWindow);
122
UnregisterClass(getWindowsClassName(), GetModuleHandle(
nullptr
));
123
}
124
}
125
126
static
QString
getString
(IMFActivate *device,
const
IID &id)
127
{
128
QComTaskResource<WCHAR> str;
129
UINT32 length = 0;
130
HRESULT hr = device->GetAllocatedString(id, str.address(), &length);
131
if
(SUCCEEDED(hr)) {
132
return
QString::fromWCharArray(str.get());
133
}
else
{
134
return
{};
135
}
136
}
137
138
static
std
::
optional
<
QCameraDevice
>
createCameraDevice
(
const
QWindowsMediaFoundation &wmf,
139
IMFActivate *device)
140
{
141
auto
info = std::make_unique<QCameraDevicePrivate>();
142
info->description = getString(device, MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME);
143
info->id = getString(device, MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK).toUtf8();
144
145
ComPtr<IMFMediaSource> source;
146
HRESULT hr = device->ActivateObject(IID_PPV_ARGS(source.GetAddressOf()));
147
if
(FAILED(hr))
148
return
{};
149
150
ComPtr<IMFSourceReader> reader;
151
hr = wmf.mfCreateSourceReaderFromMediaSource(source.Get(), NULL, reader.GetAddressOf());
152
if
(FAILED(hr))
153
return
{};
154
155
QList<QSize> photoResolutions;
156
QList<QCameraFormat> videoFormats;
157
for
(DWORD i = 0;; ++i) {
158
// Loop through the supported formats for the video device
159
ComPtr<IMFMediaType> mediaFormat;
160
hr = reader->GetNativeMediaType((DWORD)MF_SOURCE_READER_FIRST_VIDEO_STREAM, i,
161
mediaFormat.GetAddressOf());
162
if
(FAILED(hr))
163
break
;
164
165
auto
maybeCamera = QWMF::cameraFormatFromMediaType(mediaFormat.Get());
166
if
(maybeCamera) {
167
videoFormats << *maybeCamera;
168
photoResolutions << maybeCamera->resolution();
169
}
170
}
171
172
info->videoFormats = videoFormats;
173
info->photoResolutions = photoResolutions;
174
return
info.release()->create();
175
}
176
177
static
QList
<
QCameraDevice
>
readCameraDevices
(
const
QWindowsMediaFoundation &wmf,
178
IMFAttributes *attr)
179
{
180
QList<QCameraDevice> cameras;
181
UINT32 count = 0;
182
IMFActivate **devicesRaw =
nullptr
;
183
HRESULT hr = wmf.mfEnumDeviceSources(attr, &devicesRaw, &count);
184
if
(SUCCEEDED(hr)) {
185
QComTaskResource<IMFActivate *[], QComDeleter> devices(devicesRaw, count);
186
187
for
(UINT32 i = 0; i < count; i++) {
188
IMFActivate *device = devices[i];
189
if
(device) {
190
auto
maybeCamera = createCameraDevice(wmf, device);
191
if
(maybeCamera)
192
cameras << *maybeCamera;
193
}
194
}
195
}
196
return
cameras;
197
}
198
199
QList
<
QCameraDevice
>
QWindowsVideoDevices
::
findVideoInputs
()
const
200
{
201
if
(!m_wmf)
202
return
{};
203
204
QList<QCameraDevice> cameras;
205
206
ComPtr<IMFAttributes> attr;
207
HRESULT hr = m_wmf->mfCreateAttributes(attr.GetAddressOf(), 2);
208
if
(FAILED(hr))
209
return
{};
210
211
hr = attr->SetGUID(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE,
212
MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID);
213
if
(SUCCEEDED(hr)) {
214
cameras << readCameraDevices(*m_wmf, attr.Get());
215
216
hr = attr->SetGUID(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_CATEGORY,
217
KSCATEGORY_SENSOR_CAMERA);
218
if
(SUCCEEDED(hr))
219
cameras << readCameraDevices(*m_wmf, attr.Get());
220
}
221
222
return
cameras;
223
}
224
225
QT_END_NAMESPACE
QWindowsVideoDevices
Definition
qwindowsvideodevices_p.h:26
QWindowsVideoDevices::~QWindowsVideoDevices
Q_MULTIMEDIA_EXPORT ~QWindowsVideoDevices()
Definition
qwindowsvideodevices.cpp:114
QWindowsVideoDevices::findVideoInputs
QList< QCameraDevice > findVideoInputs() const override
Definition
qwindowsvideodevices.cpp:199
QT_BEGIN_NAMESPACE::createMessageOnlyWindow
HWND createMessageOnlyWindow()
Definition
qwindowsvideodevices.cpp:62
QT_BEGIN_NAMESPACE::getWindowsClassName
LPCWSTR getWindowsClassName()
Definition
qwindowsvideodevices.cpp:49
getString
static QString getString(IMFActivate *device, const IID &id)
Definition
qwindowsvideodevices.cpp:126
readCameraDevices
static QList< QCameraDevice > readCameraDevices(const QWindowsMediaFoundation &wmf, IMFAttributes *attr)
Definition
qwindowsvideodevices.cpp:177
createCameraDevice
static std::optional< QCameraDevice > createCameraDevice(const QWindowsMediaFoundation &wmf, IMFActivate *device)
Definition
qwindowsvideodevices.cpp:138
qtmultimedia
src
multimedia
windows
qwindowsvideodevices.cpp
Generated on
for Qt by
1.18.0