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
qwasmmediacapturesession.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
5
6#include "mediacapture/qwasmimagecapture_p.h"
11
12#include <QtMultimedia/qaudiodevice.h>
13#include <QtMultimedia/private/qcapturablewindow_p.h>
14#include <QtMultimedia/private/qplatformaudioinput_p.h>
15#include <QtMultimedia/private/qplatformcapturablewindows_p.h>
16#include <QtMultimedia/private/qplatformmediaintegration_p.h>
17#include <QtMultimedia/private/qwasmmediadevices_p.h>
18#include <QtCore/quuid.h>
19
20Q_LOGGING_CATEGORY(qWasmMediaCaptureSession, "qt.multimedia.wasm.capturesession")
21
22QWasmMediaCaptureSession::QWasmMediaCaptureSession() :
23 QPlatformMediaCaptureSession()
24{
25}
26
28
30{
31 return m_camera;
32}
33
34void QWasmMediaCaptureSession::setCamera(QPlatformCamera *camera)
35{
36 if (!camera) {
37 if (m_camera == nullptr)
38 return;
39 m_camera->setActive(false);
40 m_camera = nullptr;
41 } else {
42 QWasmCamera *wasmCamera = static_cast<QWasmCamera *>(camera);
43 if (m_camera == wasmCamera)
44 return;
45 m_camera = wasmCamera;
46 m_camera->setCaptureSession(this);
47 }
48 Q_EMIT cameraChanged();
49}
50
52{
53 return m_imageCapture;
54}
55
56void QWasmMediaCaptureSession::setImageCapture(QPlatformImageCapture *imageCapture)
57{
58 if (m_imageCapture == imageCapture)
59 return;
60
61 if (m_imageCapture)
62 m_imageCapture->setCaptureSession(nullptr);
63
64 m_imageCapture = static_cast<QWasmImageCapture *>(imageCapture);
65
66 if (m_imageCapture) {
67 m_imageCapture->setCaptureSession(this);
68
69 if (m_camera && m_camera->isActive())
70 m_imageCapture->setReadyForCapture(true);
71
72 Q_EMIT imageCaptureChanged();
73 }
74}
75
77{
78 return m_mediaRecorder;
79}
80
81void QWasmMediaCaptureSession::setMediaRecorder(QPlatformMediaRecorder *mediaRecorder)
82{
83 if (m_mediaRecorder == mediaRecorder)
84 return;
85
86 if (m_mediaRecorder)
87 m_mediaRecorder->setCaptureSession(nullptr);
88
89 m_mediaRecorder = static_cast<QWasmMediaRecorder *>(mediaRecorder);
90
91 if (m_mediaRecorder)
92 m_mediaRecorder->setCaptureSession(this);
93}
94
95void QWasmMediaCaptureSession::setAudioInput(QPlatformAudioInput *input)
96{
97 if (m_audioInput == input)
98 return;
99
100 m_needsAudio = (bool)input;
101 m_audioInput = input;
102}
103
105{
106 return m_needsAudio;
107}
108
110{
111 if (!sink || m_wasmSink == sink)
112 return;
113 m_wasmSink = sink;
114}
115
116void QWasmMediaCaptureSession::setAudioOutput(QPlatformAudioOutput *output)
117{
118 if (m_audioOutput == output)
119 return;
120 m_audioOutput = output;
121}
122
124{
125 if (m_imageCapture)
126 m_imageCapture->setReadyForCapture(ready);
127}
128
130{
131 return m_screenCapture;
132}
133
134void QWasmMediaCaptureSession::setScreenCapture(QPlatformSurfaceCapture *surfaceCapture)
135{
136 m_screenCapture = surfaceCapture;
137 if (surfaceCapture == nullptr) {
138 // clear stuff
139 m_displaySurface = "";
140 if (m_videoOutput && !m_videoOutput->currentVideoElement().isUndefined()) {
141 m_videoOutput->stop();
142 m_videoOutput->removeCurrentVideoElement();
143 }
144 m_mediaCaptureStream = emscripten::val::undefined();
145 } else {
146 m_displaySurface = "browser";
147 QWasmScreenCapture *wasmScreenCapture =
148 static_cast<QWasmScreenCapture *>(m_screenCapture);
149 wasmScreenCapture->setCaptureSession(this);
150 }
151}
152
154{
155 return m_windowCapture;
156}
157
158void QWasmMediaCaptureSession::setWindowCapture(QPlatformSurfaceCapture *surfaceCapture)
159{
160 m_windowCapture = surfaceCapture;
161
162 if (surfaceCapture == nullptr) {
163 // clear stuff
164 m_displaySurface = "";
165 if (m_videoOutput && !m_videoOutput->currentVideoElement().isUndefined()) {
166 m_videoOutput->stop();
167 m_videoOutput->removeCurrentVideoElement();
168 }
169 return;
170 } else {
171 // is window capture window or monitor ?
172 m_displaySurface = "window";
173 QWasmWindowCapture *wasmWindowCapture =
174 static_cast<QWasmWindowCapture *>(m_windowCapture);
175 wasmWindowCapture->setCaptureSession(this);
176 }
177}
178
180{
181 m_displaySurface = surfacetype;
182 if (surfacetype.empty()) {
183 // Jane, stop this crazy thing!
184 if (m_videoOutput && !m_videoOutput->currentVideoElement().isUndefined()) {
185 m_videoOutput->stop();
186 m_videoOutput->removeCurrentVideoElement();
187 }
188 m_mediaCaptureStream = emscripten::val::undefined();
189 return;
190 }
191 emscripten::val navigator = emscripten::val::global("navigator");
192 emscripten::val mediaDevices = navigator["mediaDevices"];
193
194 if (mediaDevices.isNull() || mediaDevices.isUndefined()) {
195 qWarning() << "No media devices found";
196 return;
197 }
198 m_videoOutput = std::make_unique<QWasmVideoOutput>();
199 m_videoOutput->setVideoMode(QWasmVideoOutput::SurfaceCapture);
200
201 m_videoOutput->setSurface(m_wasmSink);
202
203 emscripten::val constraints = emscripten::val::object();
204 emscripten::val videoConstraint = emscripten::val::object();
205 emscripten::val audioConstraint = emscripten::val::object();
206
207 videoConstraint.set("displaySurface", m_displaySurface);
208 videoConstraint.set("resizeMode", std::string("crop-and-scale"));
209
210 constraints.set("monitorTypeSurfaces", surfacetype == "window" ?
211 std::string("exclude") : std::string("include")); // whole monitor
212
213 constraints.set("surfaceSwitching", std::string("exclude"));
214 constraints.set("selfBrowserSurface", "include"); // mirror effect
215
216 constraints.set("logicalSurface", true);
217
218 audioConstraint.set("systemAudio", true);
219
220 constraints.set("video", videoConstraint);
221 constraints.set("audio", audioConstraint);
222
223 // will ask for permissions!
224 qstdweb::PromiseCallbacks getDisplayMediaCallback{
225 // default
226 .thenFunc =
227 [this](emscripten::val stream) {
228 qCDebug(qWasmMediaCaptureSession) << "getDisplayMediaSuccess"
229 << m_displaySurface;
230 if (stream.isUndefined() || stream.isNull()) {
231 qWarning() << "No media stream found error";
232 return;
233 }
234 m_mediaCaptureStream = stream;
235
236 // new Video element
237 constexpr QSize initialSize(0, 0);
238 constexpr QRect initialRect(QPoint(0, 0), initialSize);
239 QUuid videoElementId = QUuid::createUuid();
240
241 m_videoOutput->createVideoElement(m_displaySurface + "_capture_"
242 + videoElementId.toString(QUuid::WithoutBraces).toStdString()); // videoElementId
243 m_videoOutput->doElementCallbacks();
244 m_videoOutput->updateVideoElementGeometry(initialRect);
245
246 // set video element src to this
247 if (m_displaySurface == "window") {
248
249 QWasmWindowCapture *wasmWindowCapture =
250 static_cast<QWasmWindowCapture *>(m_windowCapture);
251 wasmWindowCapture->setVideoOutput(m_videoOutput.get());
252
253 QUuid uid(QString::fromStdString(stream["id"].as<std::string>()));
254
255 m_capuredWindows.push_back(QCapturableWindowPrivate::create(
256 static_cast<QCapturableWindowPrivate::Id>(uid.toByteArray().toLong()),
257 QString::fromStdString(stream["id"].as<std::string>())));
258
259 wasmWindowCapture->setVideoStream(stream);
260 Q_EMIT windowCaptureChanged();
261 } else {
262
263 QWasmScreenCapture *wasmScreenCapture =
264 static_cast<QWasmScreenCapture *>(m_screenCapture);
265 wasmScreenCapture->setVideoOutput(m_videoOutput.get());
266
267 wasmScreenCapture->setVideoStream(stream);
268 Q_EMIT screenCaptureChanged();
269 }
270 },
271 .catchFunc =
272 [](emscripten::val error) {
273 qCDebug(qWasmMediaCaptureSession)
274 << "getDisplayMedia fail"
275 << QString::fromStdString(error["name"].as<std::string>())
276 << QString::fromStdString(error["message"].as<std::string>());
277
278 // permission denied or error
279 // "NotAllowedError "Permission Denied"
280 },
281 .finallyFunc = {}
282 };
283
284 qstdweb::Promise::make(mediaDevices, QStringLiteral("getDisplayMedia"),
285 std::move(getDisplayMediaCallback), constraints);
286}
void setActive(bool active) override
bool isActive() const override
void setReadyForCapture(bool isReady)
void setMediaRecorder(QPlatformMediaRecorder *recorder) override
void setAudioInput(QPlatformAudioInput *input) override
void setScreenCapture(QPlatformSurfaceCapture *) override
QPlatformSurfaceCapture * screenCapture() override
void setAudioOutput(QPlatformAudioOutput *output) override
QPlatformImageCapture * imageCapture() override
QPlatformMediaRecorder * mediaRecorder() override
QPlatformSurfaceCapture * windowCapture() override
void setImageCapture(QPlatformImageCapture *imageCapture) override
void setWindowCapture(QPlatformSurfaceCapture *) override
void setCamera(QPlatformCamera *camera) override
~QWasmMediaCaptureSession() override
void setVideoPreview(QVideoSink *sink) override
QPlatformCamera * camera() override
void setVideoSource(std::string surfacetype)
QWasmMediaRecorder(QMediaRecorder *parent)
void setVideoOutput(QWasmVideoOutput *output)
void setVideoOutput(QWasmVideoOutput *object)
Q_LOGGING_CATEGORY(lcEventDispatcher, "qt.eventdispatcher")