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