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 if (m_camera && m_camera->isActive())
71 m_imageCapture->setReadyForCapture(true);
72
73 emit imageCaptureChanged();
74 }
75}
76
78{
79 return m_mediaRecorder;
80}
81
82void QWasmMediaCaptureSession::setMediaRecorder(QPlatformMediaRecorder *mediaRecorder)
83{
84 if (m_mediaRecorder == mediaRecorder)
85 return;
86
87 if (m_mediaRecorder)
88 m_mediaRecorder->setCaptureSession(nullptr);
89
90 m_mediaRecorder = static_cast<QWasmMediaRecorder *>(mediaRecorder);
91
92 if (m_mediaRecorder)
93 m_mediaRecorder->setCaptureSession(this);
94}
95
96void QWasmMediaCaptureSession::setAudioInput(QPlatformAudioInput *input)
97{
98 if (m_audioInput == input)
99 return;
100
101 m_needsAudio = (bool)input;
102 m_audioInput = input;
103}
104
106{
107 return m_needsAudio;
108}
109
111{
112 if (!sink || m_wasmSink == sink)
113 return;
114 m_wasmSink = sink;
115}
116
117void QWasmMediaCaptureSession::setAudioOutput(QPlatformAudioOutput *output)
118{
119 if (m_audioOutput == output)
120 return;
121 m_audioOutput = output;
122}
123
125{
126 if (m_imageCapture)
127 m_imageCapture->setReadyForCapture(ready);
128}
129
131{
132 return m_screenCapture;
133}
134
135void QWasmMediaCaptureSession::setScreenCapture(QPlatformSurfaceCapture *surfaceCapture)
136{
137 m_screenCapture = surfaceCapture;
138 if (surfaceCapture == nullptr) {
139 // clear stuff
140 m_displaySurface = "";
141 if (m_videoOutput && !m_videoOutput->currentVideoElement().isUndefined()) {
142 m_videoOutput->stop();
143 m_videoOutput->removeCurrentVideoElement();
144 }
145 m_mediaCaptureStream = emscripten::val::undefined();
146 } else {
147 m_displaySurface = "browser";
148 QWasmScreenCapture *wasmScreenCapture =
149 static_cast<QWasmScreenCapture *>(m_screenCapture);
150 wasmScreenCapture->setCaptureSession(this);
151 }
152}
153
155{
156 return m_windowCapture;
157}
158
159void QWasmMediaCaptureSession::setWindowCapture(QPlatformSurfaceCapture *surfaceCapture)
160{
161 m_windowCapture = surfaceCapture;
162
163 if (surfaceCapture == nullptr) {
164 // clear stuff
165 m_displaySurface = "";
166 if (m_videoOutput && !m_videoOutput->currentVideoElement().isUndefined()) {
167 m_videoOutput->stop();
168 m_videoOutput->removeCurrentVideoElement();
169 }
170 return;
171 } else {
172 // is window capture window or monitor ?
173 m_displaySurface = "window";
174 QWasmWindowCapture *wasmWindowCapture =
175 static_cast<QWasmWindowCapture *>(m_windowCapture);
176 wasmWindowCapture->setCaptureSession(this);
177 }
178}
179
180void QWasmMediaCaptureSession::setVideoSource(std::string surfacetype)
181{
182 m_displaySurface = surfacetype;
183 if (surfacetype.empty()) {
184 // Jane, stop this crazy thing!
185 if (m_videoOutput && !m_videoOutput->currentVideoElement().isUndefined()) {
186 m_videoOutput->stop();
187 m_videoOutput->removeCurrentVideoElement();
188 }
189 m_mediaCaptureStream = emscripten::val::undefined();
190 return;
191 }
192 emscripten::val navigator = emscripten::val::global("navigator");
193 emscripten::val mediaDevices = navigator["mediaDevices"];
194
195 if (mediaDevices.isNull() || mediaDevices.isUndefined()) {
196 qWarning() << "No media devices found";
197 return;
198 }
199 m_videoOutput = std::make_unique<QWasmVideoOutput>();
200 m_videoOutput->setVideoMode(QWasmVideoOutput::SurfaceCapture);
201
202 m_videoOutput->setSurface(m_wasmSink);
203
204 emscripten::val constraints = emscripten::val::object();
205 emscripten::val videoConstraint = emscripten::val::object();
206 emscripten::val audioConstraint = emscripten::val::object();
207
208 videoConstraint.set("displaySurface", m_displaySurface);
209 videoConstraint.set("resizeMode", std::string("crop-and-scale"));
210
211 constraints.set("monitorTypeSurfaces", surfacetype == "window" ?
212 std::string("exclude") : std::string("include")); // whole monitor
213
214 constraints.set("surfaceSwitching", std::string("exclude"));
215 constraints.set("selfBrowserSurface", "include"); // mirror effect
216
217 constraints.set("logicalSurface", true);
218
219 audioConstraint.set("systemAudio", true);
220
221 constraints.set("video", videoConstraint);
222 constraints.set("audio", audioConstraint);
223
224 // will ask for permissions!
225 qstdweb::PromiseCallbacks getDisplayMediaCallback{
226 // default
227 .thenFunc =
228 [this](emscripten::val stream) {
229 qCDebug(qWasmMediaCaptureSession) << "getDisplayMediaSuccess"
230 << m_displaySurface;
231 if (stream.isUndefined() || stream.isNull()) {
232 qWarning() << "No media stream found error";
233 return;
234 }
235 m_mediaCaptureStream = stream;
236
237 // new Video element
238 constexpr QSize initialSize(0, 0);
239 constexpr QRect initialRect(QPoint(0, 0), initialSize);
240 QUuid videoElementId = QUuid::createUuid();
241
242 m_videoOutput->createVideoElement(m_displaySurface + "_capture_"
243 + videoElementId.toString(QUuid::WithoutBraces).toStdString()); // videoElementId
244 m_videoOutput->doElementCallbacks();
245 m_videoOutput->createOffscreenElement(initialSize);
246 m_videoOutput->updateVideoElementGeometry(initialRect);
247
248 // set video element src to this
249 if (m_displaySurface == "window") {
250
251 QWasmWindowCapture *wasmWindowCapture =
252 static_cast<QWasmWindowCapture *>(m_windowCapture);
253 wasmWindowCapture->setVideoOutput(m_videoOutput.get());
254
255 QUuid uid(QString::fromStdString(stream["id"].as<std::string>()));
256
257 m_capuredWindows.push_back(QCapturableWindowPrivate::create(
258 static_cast<QCapturableWindowPrivate::Id>(uid.toByteArray().toLong()),
259 QString::fromStdString(stream["id"].as<std::string>())));
260
261 wasmWindowCapture->setVideoStream(stream);
262 emit windowCaptureChanged();
263 } else {
264
265 QWasmScreenCapture *wasmScreenCapture =
266 static_cast<QWasmScreenCapture *>(m_screenCapture);
267 wasmScreenCapture->setVideoOutput(m_videoOutput.get());
268
269 wasmScreenCapture->setVideoStream(stream);
270 emit screenCaptureChanged();
271 }
272 },
273 .catchFunc =
274 [](emscripten::val error) {
275 qCDebug(qWasmMediaCaptureSession)
276 << "getDisplayMedia fail"
277 << QString::fromStdString(error["name"].as<std::string>())
278 << QString::fromStdString(error["message"].as<std::string>());
279
280 // permission denied or error
281 // "NotAllowedError "Permission Denied"
282 }
283 };
284
285 qstdweb::Promise::make(mediaDevices, QStringLiteral("getDisplayMedia"),
286 std::move(getDisplayMediaCallback), constraints);
287}
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")