6#include <qcameradevice.h>
7#include <private/qplatformvideosink_p.h>
8#include <private/qplatformvideodevices_p.h>
9#include <private/qmemoryvideobuffer_p.h>
10#include <private/qvideotexturehelper_p.h>
11#include <private/qwasmmediadevices_p.h>
12#include <QtMultimedia/private/qmultimedia_ranges_p.h>
15#include <common/qwasmvideooutput_p.h>
17#include <emscripten/val.h>
18#include <emscripten/bind.h>
19#include <emscripten/html5.h>
23#include <private/qstdweb_p.h>
27namespace ranges = QtMultimediaPrivate::ranges;
30 : QPlatformCamera(camera),
31 m_cameraOutput(
new QWasmVideoOutput),
32 m_cameraIsReady(
false)
34 connect(
this, &QWasmCamera::cameraIsReady,
this, [
this]() {
35 m_cameraIsReady =
true;
36 if (m_cameraShouldStartActive) {
37 QTimer::singleShot(50,
this, [
this]() {
48 return m_cameraActive;
53 if (m_cameraActive == active)
55 if (!m_CaptureSession) {
56 updateError(QCamera::CameraError, QStringLiteral(
"video surface error"));
57 m_shouldBeActive =
true;
60 if (m_cameraActive && !active)
61 m_cameraOutput->stop();
63 m_shouldBeActive = active;
65 if (!m_cameraIsReady) {
66 m_cameraShouldStartActive =
true;
70 QVideoSink *sink = m_CaptureSession->videoSink();
72 qWarning() << Q_FUNC_INFO <<
"sink not ready";
76 m_cameraOutput->setSurface(m_CaptureSession->videoSink());
77 m_cameraActive = active;
78 m_shouldBeActive =
false;
81 updateCameraFeatures();
82 emit activeChanged(active);
83 if (m_CaptureSession->imageCapture()) {
85 m_readyChangedConnection = connect(cameraOutput(), &QWasmVideoOutput::readyChanged,
this, [
this] () {
86 m_CaptureSession->setReadyForCapture(
true);
90 if (!active && m_readyChangedConnection) {
91 QObject::disconnect(m_readyChangedConnection);
95 m_cameraOutput->start();
100 if (camera.id().isEmpty() || (m_cameraDev.id() == camera.id())) {
104 m_cameraOutput->setVideoMode(QWasmVideoOutput::Camera);
106 constexpr QSize initialSize(0, 0);
107 constexpr QRect initialRect(QPoint(0, 0), initialSize);
108 m_cameraOutput->createVideoElement(camera.id().toStdString());
109 m_cameraOutput->doElementCallbacks();
110 m_cameraOutput->createOffscreenElement(initialSize);
111 m_cameraOutput->updateVideoElementGeometry(initialRect);
113 const auto cameras = QMediaDevices::videoInputs();
115 if (ranges::contains(cameras, camera)) {
116 m_cameraDev = camera;
117 createCamera(m_cameraDev);
118 emit cameraIsReady();
122 if (cameras.count() > 0) {
123 m_cameraDev = camera;
124 createCamera(m_cameraDev);
125 emit cameraIsReady();
127 updateError(QCamera::CameraError, QStringLiteral(
"Failed to find a camera"));
133 m_cameraFormat = format;
141 if (m_CaptureSession == captureSession)
144 m_CaptureSession = captureSession;
146 if (m_shouldBeActive)
152 if (!isFocusModeSupported(mode))
155 static constexpr std::string_view focusModeString =
"focusMode";
156 if (mode == QCamera::FocusModeManual)
157 m_cameraOutput->setDeviceSetting(focusModeString.data(), emscripten::val(
"manual"));
158 if (mode == QCamera::FocusModeAuto)
159 m_cameraOutput->setDeviceSetting(focusModeString.data(), emscripten::val(
"continuous"));
160 focusModeChanged(mode);
165 emscripten::val caps = m_cameraOutput->getDeviceCapabilities();
166 if (caps.isUndefined())
169 emscripten::val focusMode = caps[
"focusMode"];
170 if (focusMode.isUndefined())
173 std::vector<std::string> focalModes;
175 for (
int i = 0; i < focusMode[
"length"].as<
int>(); i++)
176 focalModes.push_back(focusMode[i].as<std::string>());
184 case QCamera::FocusModeAuto:
185 return ranges::contains(focalModes,
"continuous")
186 || ranges::contains(focalModes,
"single-shot");
187 case QCamera::FocusModeAutoNear:
188 case QCamera::FocusModeAutoFar:
189 case QCamera::FocusModeHyperfocal:
190 case QCamera::FocusModeInfinity:
192 case QCamera::FocusModeManual:
193 found = ranges::contains(focalModes,
"manual");
200 if (!isTorchModeSupported(mode))
203 if (m_wasmTorchMode == mode)
206 static constexpr std::string_view torchModeString =
"torchMode";
207 bool hasChanged =
false;
209 case QCamera::TorchOff:
210 m_cameraOutput->setDeviceSetting(torchModeString.data(), emscripten::val(
false));
213 case QCamera::TorchOn:
214 m_cameraOutput->setDeviceSetting(torchModeString.data(), emscripten::val(
true));
217 case QCamera::TorchAuto:
220 m_wasmTorchMode = mode;
222 torchModeChanged(m_wasmTorchMode);
227 if (!m_cameraIsReady)
230 emscripten::val caps = m_cameraOutput->getDeviceCapabilities();
231 if (caps.isUndefined())
234 emscripten::val exposureMode = caps[
"torch"];
235 if (exposureMode.isUndefined())
238 return (mode != QCamera::TorchAuto);
244 if (!isExposureModeSupported(mode))
247 if (m_wasmExposureMode == mode)
250 bool hasChanged =
false;
251 static constexpr std::string_view exposureModeString =
"exposureMode";
253 case QCamera::ExposureManual:
254 m_cameraOutput->setDeviceSetting(exposureModeString.data(), emscripten::val(
"manual"));
257 case QCamera::ExposureAuto:
258 m_cameraOutput->setDeviceSetting(exposureModeString.data(), emscripten::val(
"continuous"));
266 m_wasmExposureMode = mode;
267 exposureModeChanged(m_wasmExposureMode);
273 if (!m_cameraIsReady)
276 emscripten::val caps = m_cameraOutput->getDeviceCapabilities();
277 if (caps.isUndefined())
280 emscripten::val exposureMode = caps[
"exposureMode"];
281 if (exposureMode.isUndefined())
284 std::vector<std::string> exposureModes;
286 for (
int i = 0; i < exposureMode[
"length"].as<
int>(); i++)
287 exposureModes.push_back(exposureMode[i].as<std::string>());
291 case QCamera::ExposureAuto:
292 found = ranges::contains(exposureModes,
"continuous");
294 case QCamera::ExposureManual:
295 found = ranges::contains(exposureModes,
"manual");
306 if (!m_cameraIsReady)
309 emscripten::val caps = m_cameraOutput->getDeviceCapabilities();
310 if (caps.isUndefined())
313 emscripten::val exposureComp = caps[
"exposureCompensation"];
314 if (exposureComp.isUndefined())
316 if (m_wasmExposureCompensation == bias)
319 static constexpr std::string_view exposureCompensationModeString =
"exposureCompensation";
320 m_cameraOutput->setDeviceSetting(exposureCompensationModeString.data(), emscripten::val(bias));
321 m_wasmExposureCompensation = bias;
322 emit exposureCompensationChanged(m_wasmExposureCompensation);
327 if (m_wasmExposureTime == secs)
330 if (!m_cameraIsReady)
333 emscripten::val caps = m_cameraOutput->getDeviceCapabilities();
334 emscripten::val exposureTime = caps[
"exposureTime"];
335 if (exposureTime.isUndefined())
337 static constexpr std::string_view exposureTimeString =
"exposureTime";
338 m_cameraOutput->setDeviceSetting(exposureTimeString.data(), emscripten::val(secs));
339 m_wasmExposureTime = secs;
340 emit exposureTimeChanged(m_wasmExposureTime);
345 if (!m_cameraIsReady)
348 emscripten::val caps = m_cameraOutput->getDeviceCapabilities();
349 if (caps.isUndefined())
352 emscripten::val isoSpeed = caps[
"iso"];
353 if (isoSpeed.isUndefined())
356 return isoSpeed.as<
double>();
361 if (!m_cameraIsReady)
364 emscripten::val caps = m_cameraOutput->getDeviceCapabilities();
365 if (caps.isUndefined())
368 emscripten::val isoSpeed = caps[
"iso"];
369 if (isoSpeed.isUndefined())
371 if (m_wasmIsoSensitivity == sens)
373 static constexpr std::string_view isoString =
"iso";
374 m_cameraOutput->setDeviceSetting(isoString.data(), emscripten::val(sens));
375 m_wasmIsoSensitivity = sens;
376 emit isoSensitivityChanged(m_wasmIsoSensitivity);
381 if (!m_cameraIsReady)
384 emscripten::val caps = m_cameraOutput->getDeviceCapabilities();
385 if (caps.isUndefined())
388 emscripten::val whiteBalanceMode = caps[
"whiteBalanceMode"];
389 if (whiteBalanceMode.isUndefined())
392 if (mode == QCamera::WhiteBalanceAuto || mode == QCamera::WhiteBalanceManual)
400 if (!isWhiteBalanceModeSupported(mode))
403 if (m_wasmWhiteBalanceMode == mode)
406 bool hasChanged =
false;
407 static constexpr std::string_view whiteBalanceModeString =
"whiteBalanceMode";
409 case QCamera::WhiteBalanceAuto:
410 m_cameraOutput->setDeviceSetting(whiteBalanceModeString.data(), emscripten::val(
"auto"));
413 case QCamera::WhiteBalanceManual:
414 m_cameraOutput->setDeviceSetting(whiteBalanceModeString.data(), emscripten::val(
"manual"));
422 m_wasmWhiteBalanceMode = mode;
423 emit whiteBalanceModeChanged(m_wasmWhiteBalanceMode);
429 if (!m_cameraIsReady)
432 emscripten::val caps = m_cameraOutput->getDeviceCapabilities();
433 if (caps.isUndefined())
436 emscripten::val whiteBalanceMode = caps[
"colorTemperature"];
437 if (whiteBalanceMode.isUndefined())
439 if(m_wasmColorTemperature == temperature)
442 static constexpr std::string_view colorBalanceString =
"colorTemperature";
443 m_cameraOutput->setDeviceSetting(colorBalanceString.data(), emscripten::val(temperature));
444 m_wasmColorTemperature = temperature;
445 colorTemperatureChanged(m_wasmColorTemperature);
448void QWasmCamera::createCamera(
const QCameraDevice &camera)
450 m_cameraOutput->addCameraSourceElement(camera.id().toStdString());
455 if (!m_cameraIsReady)
458 emscripten::val caps = m_cameraOutput->getDeviceCapabilities();
459 if (caps.isUndefined())
462 QCamera::Features cameraFeatures;
464 if (!caps[
"colorTemperature"].isUndefined())
465 cameraFeatures |= QCamera::Feature::ColorTemperature;
467 if (!caps[
"exposureCompensation"].isUndefined())
468 cameraFeatures |= QCamera::Feature::ExposureCompensation;
470 if (!caps[
"iso"].isUndefined())
471 cameraFeatures |= QCamera::Feature::IsoSensitivity;
473 if (!caps[
"exposureTime"].isUndefined())
474 cameraFeatures |= QCamera::Feature::ManualExposureTime;
476 if (!caps[
"focusDistance"].isUndefined())
477 cameraFeatures |= QCamera::Feature::FocusDistance;
479 supportedFeaturesChanged(cameraFeatures);
bool isTorchModeSupported(QCamera::TorchMode mode) const override
void setManualExposureTime(float) override
void setExposureCompensation(float bias) override
void setColorTemperature(int temperature) override
int isoSensitivity() const override
void setWhiteBalanceMode(QCamera::WhiteBalanceMode mode) override
void setTorchMode(QCamera::TorchMode mode) override
bool isWhiteBalanceModeSupported(QCamera::WhiteBalanceMode mode) const override
void setExposureMode(QCamera::ExposureMode mode) override
bool setCameraFormat(const QCameraFormat &format) override
void setManualIsoSensitivity(int) override
void setFocusMode(QCamera::FocusMode mode) override
void setActive(bool active) override
bool isFocusModeSupported(QCamera::FocusMode mode) const override
bool isActive() const override
void setCaptureSession(QPlatformMediaCaptureSession *session) override
bool isExposureModeSupported(QCamera::ExposureMode mode) const override
Q_LOGGING_CATEGORY(lcEventDispatcher, "qt.eventdispatcher")