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>
14#include <common/qwasmvideooutput_p.h>
16#include <emscripten/val.h>
17#include <emscripten/bind.h>
18#include <emscripten/html5.h>
22#include <private/qstdweb_p.h>
27 : QPlatformCamera(camera),
28 m_cameraOutput(
new QWasmVideoOutput),
29 m_cameraIsReady(
false)
31 connect(
this, &QWasmCamera::cameraIsReady,
this, [
this]() {
32 m_cameraIsReady =
true;
33 if (m_cameraShouldStartActive) {
34 QTimer::singleShot(50,
this, [
this]() {
45 return m_cameraActive;
50 if (m_cameraActive == active)
52 if (!m_CaptureSession) {
53 updateError(QCamera::CameraError, QStringLiteral(
"video surface error"));
54 m_shouldBeActive =
true;
57 if (m_cameraActive && !active)
58 m_cameraOutput->stop();
60 m_shouldBeActive = active;
62 if (!m_cameraIsReady) {
63 m_cameraShouldStartActive =
true;
67 QVideoSink *sink = m_CaptureSession->videoSink();
69 qWarning() << Q_FUNC_INFO <<
"sink not ready";
73 m_cameraOutput->setSurface(m_CaptureSession->videoSink());
74 m_cameraActive = active;
75 m_shouldBeActive =
false;
78 updateCameraFeatures();
79 emit activeChanged(active);
80 if (m_CaptureSession->imageCapture()) {
82 m_readyChangedConnection = connect(cameraOutput(), &QWasmVideoOutput::readyChanged,
this, [
this] () {
83 m_CaptureSession->setReadyForCapture(
true);
87 if (!active && m_readyChangedConnection) {
88 QObject::disconnect(m_readyChangedConnection);
92 m_cameraOutput->start();
97 if (camera.id().isEmpty() || (m_cameraDev.id() == camera.id())) {
101 m_cameraOutput->setVideoMode(QWasmVideoOutput::Camera);
103 constexpr QSize initialSize(0, 0);
104 constexpr QRect initialRect(QPoint(0, 0), initialSize);
105 m_cameraOutput->createVideoElement(camera.id().toStdString());
106 m_cameraOutput->doElementCallbacks();
107 m_cameraOutput->createOffscreenElement(initialSize);
108 m_cameraOutput->updateVideoElementGeometry(initialRect);
110 const auto cameras = QMediaDevices::videoInputs();
112 if (std::find(cameras.begin(), cameras.end(), camera) != cameras.end()) {
113 m_cameraDev = camera;
114 createCamera(m_cameraDev);
115 emit cameraIsReady();
119 if (cameras.count() > 0) {
120 m_cameraDev = camera;
121 createCamera(m_cameraDev);
122 emit cameraIsReady();
124 updateError(QCamera::CameraError, QStringLiteral(
"Failed to find a camera"));
130 m_cameraFormat = format;
138 if (m_CaptureSession == captureSession)
141 m_CaptureSession = captureSession;
143 if (m_shouldBeActive)
149 if (!isFocusModeSupported(mode))
152 static constexpr std::string_view focusModeString =
"focusMode";
153 if (mode == QCamera::FocusModeManual)
154 m_cameraOutput->setDeviceSetting(focusModeString.data(), emscripten::val(
"manual"));
155 if (mode == QCamera::FocusModeAuto)
156 m_cameraOutput->setDeviceSetting(focusModeString.data(), emscripten::val(
"continuous"));
157 focusModeChanged(mode);
162 emscripten::val caps = m_cameraOutput->getDeviceCapabilities();
163 if (caps.isUndefined())
166 emscripten::val focusMode = caps[
"focusMode"];
167 if (focusMode.isUndefined())
170 std::vector<std::string> focalModes;
172 for (
int i = 0; i < focusMode[
"length"].as<
int>(); i++)
173 focalModes.push_back(focusMode[i].as<std::string>());
182 return std::find(focalModes.begin(), focalModes.end(),
"continuous") != focalModes.end()
183 || std::find(focalModes.begin(), focalModes.end(),
"single-shot")
185 case QCamera::FocusModeAutoNear:
186 case QCamera::FocusModeAutoFar:
187 case QCamera::FocusModeHyperfocal:
188 case QCamera::FocusModeInfinity:
191 found = std::find(focalModes.begin(), focalModes.end(),
"manual") != focalModes.end();
198 if (!isTorchModeSupported(mode))
201 if (m_wasmTorchMode == mode)
204 static constexpr std::string_view torchModeString =
"torchMode";
205 bool hasChanged =
false;
208 m_cameraOutput->setDeviceSetting(torchModeString.data(), emscripten::val(
false));
212 m_cameraOutput->setDeviceSetting(torchModeString.data(), emscripten::val(
true));
218 m_wasmTorchMode = mode;
220 torchModeChanged(m_wasmTorchMode);
225 if (!m_cameraIsReady)
228 emscripten::val caps = m_cameraOutput->getDeviceCapabilities();
229 if (caps.isUndefined())
232 emscripten::val exposureMode = caps[
"torch"];
233 if (exposureMode.isUndefined())
236 return (mode != QCamera::TorchAuto);
242 if (!isExposureModeSupported(mode))
245 if (m_wasmExposureMode == mode)
248 bool hasChanged =
false;
249 static constexpr std::string_view exposureModeString =
"exposureMode";
252 m_cameraOutput->setDeviceSetting(exposureModeString.data(), emscripten::val(
"manual"));
256 m_cameraOutput->setDeviceSetting(exposureModeString.data(), emscripten::val(
"continuous"));
264 m_wasmExposureMode = mode;
265 exposureModeChanged(m_wasmExposureMode);
271 if (!m_cameraIsReady)
274 emscripten::val caps = m_cameraOutput->getDeviceCapabilities();
275 if (caps.isUndefined())
278 emscripten::val exposureMode = caps[
"exposureMode"];
279 if (exposureMode.isUndefined())
282 std::vector<std::string> exposureModes;
284 for (
int i = 0; i < exposureMode[
"length"].as<
int>(); i++)
285 exposureModes.push_back(exposureMode[i].as<std::string>());
290 found = std::find(exposureModes.begin(), exposureModes.end(),
"continuous")
291 != exposureModes.end();
294 found = std::find(exposureModes.begin(), exposureModes.end(),
"manual")
295 != exposureModes.end();
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);
The QCamera class provides interface for system camera devices.
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")