From 403bdc4dafe89a463f3d93b9a389a1010ca5ff16 Mon Sep 17 00:00:00 2001 From: Narr the Reg Date: Tue, 28 Jun 2022 19:35:51 -0500 Subject: [PATCH] yuzu: Add webcam support and rebase to latest master --- src/common/settings.h | 4 ++-- src/core/hle/service/hid/errors.h | 4 ++-- src/core/hle/service/hid/irs.cpp | 2 +- src/core/hle/service/hid/irs.h | 2 +- src/yuzu/bootmanager.cpp | 19 ++++++++++++---- src/yuzu/bootmanager.h | 2 ++ src/yuzu/configuration/configure_camera.cpp | 24 +++++++++++++++------ src/yuzu/configuration/configure_camera.h | 2 ++ 8 files changed, 43 insertions(+), 16 deletions(-) diff --git a/src/common/settings.h b/src/common/settings.h index 20959ec89..1079cf8cb 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -503,8 +503,8 @@ struct Values { Setting enable_ring_controller{true, "enable_ring_controller"}; RingconRaw ringcon_analogs; - BasicSetting enable_ir_sensor{false, "enable_ir_sensor"}; - BasicSetting ir_sensor_device{"auto", "ir_sensor_device"}; + Setting enable_ir_sensor{false, "enable_ir_sensor"}; + Setting ir_sensor_device{"auto", "ir_sensor_device"}; // Data Storage Setting use_virtual_sd{true, "use_virtual_sd"}; diff --git a/src/core/hle/service/hid/errors.h b/src/core/hle/service/hid/errors.h index accc2b646..4613a4e60 100644 --- a/src/core/hle/service/hid/errors.h +++ b/src/core/hle/service/hid/errors.h @@ -22,7 +22,7 @@ constexpr Result NpadNotConnected{ErrorModule::HID, 710}; namespace Service::IRS { -constexpr ResultCode InvalidProcessorState{ErrorModule::Irsensor, 78}; -constexpr ResultCode InvalidIrCameraHandle{ErrorModule::Irsensor, 204}; +constexpr Result InvalidProcessorState{ErrorModule::Irsensor, 78}; +constexpr Result InvalidIrCameraHandle{ErrorModule::Irsensor, 204}; } // namespace Service::IRS diff --git a/src/core/hle/service/hid/irs.cpp b/src/core/hle/service/hid/irs.cpp index b6e7c0792..d5107e41f 100644 --- a/src/core/hle/service/hid/irs.cpp +++ b/src/core/hle/service/hid/irs.cpp @@ -529,7 +529,7 @@ void IRS::ActivateIrsensorWithFunctionLevel(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } -ResultCode IRS::IsIrCameraHandleValid(const Core::IrSensor::IrCameraHandle& camera_handle) const { +Result IRS::IsIrCameraHandleValid(const Core::IrSensor::IrCameraHandle& camera_handle) const { if (camera_handle.npad_id > static_cast(NpadIdTypeToIndex(Core::HID::NpadIdType::Handheld))) { return InvalidIrCameraHandle; diff --git a/src/core/hle/service/hid/irs.h b/src/core/hle/service/hid/irs.h index 516620b4d..2e6115c73 100644 --- a/src/core/hle/service/hid/irs.h +++ b/src/core/hle/service/hid/irs.h @@ -57,7 +57,7 @@ private: void StopImageProcessorAsync(Kernel::HLERequestContext& ctx); void ActivateIrsensorWithFunctionLevel(Kernel::HLERequestContext& ctx); - ResultCode IsIrCameraHandleValid(const Core::IrSensor::IrCameraHandle& camera_handle) const; + Result IsIrCameraHandleValid(const Core::IrSensor::IrCameraHandle& camera_handle) const; Core::IrSensor::DeviceFormat& GetIrCameraSharedMemoryDeviceEntry( const Core::IrSensor::IrCameraHandle& camera_handle); diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp index 774085809..0ee3820a2 100644 --- a/src/yuzu/bootmanager.cpp +++ b/src/yuzu/bootmanager.cpp @@ -830,6 +830,10 @@ void GRenderWindow::InitializeCamera() { camera->unload(); camera->setCaptureMode(QCamera::CaptureViewfinder); camera->load(); + camera->start(); + + pending_camera_snapshots = 0; + is_virtual_camera = false; camera_timer = std::make_unique(); connect(camera_timer.get(), &QTimer::timeout, [this] { RequestCameraCapture(); }); @@ -851,11 +855,17 @@ void GRenderWindow::RequestCameraCapture() { return; } - // Idealy one should only call capture but Qt refuses to take a second capture without - // stopping the camera - camera->stop(); - camera->start(); + // If the camera doesn't capture, test for virtual cameras + if (pending_camera_snapshots > 5) { + is_virtual_camera = true; + } + // Virtual cameras like obs need to reset the camera every capture + if (is_virtual_camera) { + camera->stop(); + camera->start(); + } + pending_camera_snapshots++; camera_capture->capture(); } @@ -870,6 +880,7 @@ void GRenderWindow::OnCameraCapture(int requestId, const QImage& img) { camera_data.resize(camera_width * camera_height); std::memcpy(camera_data.data(), converted.bits(), camera_width * camera_height * sizeof(u32)); input_subsystem->GetCamera()->SetCameraData(camera_width, camera_height, camera_data); + pending_camera_snapshots = 0; } bool GRenderWindow::event(QEvent* event) { diff --git a/src/yuzu/bootmanager.h b/src/yuzu/bootmanager.h index 346201768..b4781e697 100644 --- a/src/yuzu/bootmanager.h +++ b/src/yuzu/bootmanager.h @@ -240,6 +240,8 @@ private: bool first_frame = false; InputCommon::TasInput::TasState last_tas_state; + bool is_virtual_camera; + int pending_camera_snapshots; std::unique_ptr camera; std::unique_ptr camera_capture; std::unique_ptr camera_timer; diff --git a/src/yuzu/configuration/configure_camera.cpp b/src/yuzu/configuration/configure_camera.cpp index 97febb33c..73cdcf3f2 100644 --- a/src/yuzu/configuration/configure_camera.cpp +++ b/src/yuzu/configuration/configure_camera.cpp @@ -39,8 +39,8 @@ void ConfigureCamera::PreviewCamera() { for (const QCameraInfo& cameraInfo : cameras) { if (input_devices[index] == cameraInfo.deviceName().toStdString() || input_devices[index] == "Auto") { - LOG_ERROR(Frontend, "Selected Camera {} {}", cameraInfo.description().toStdString(), - cameraInfo.deviceName().toStdString()); + LOG_INFO(Frontend, "Selected Camera {} {}", cameraInfo.description().toStdString(), + cameraInfo.deviceName().toStdString()); camera = std::make_unique(cameraInfo); camera_found = true; break; @@ -62,12 +62,23 @@ void ConfigureCamera::PreviewCamera() { camera->unload(); camera->setCaptureMode(QCamera::CaptureViewfinder); camera->load(); + camera->start(); + + pending_snapshots = 0; + is_virtual_camera = false; camera_timer = std::make_unique(); connect(camera_timer.get(), &QTimer::timeout, [this] { - camera->stop(); - camera->start(); - + // If the camera doesn't capture, test for virtual cameras + if (pending_snapshots > 5) { + is_virtual_camera = true; + } + // Virtual cameras like obs need to reset the camera every capture + if (is_virtual_camera) { + camera->stop(); + camera->start(); + } + pending_snapshots++; camera_capture->capture(); }); @@ -75,10 +86,11 @@ void ConfigureCamera::PreviewCamera() { } void ConfigureCamera::DisplayCapturedFrame(int requestId, const QImage& img) { - LOG_ERROR(Frontend, "ImageCaptured {} {}", img.width(), img.height()); + LOG_INFO(Frontend, "ImageCaptured {} {}", img.width(), img.height()); const auto converted = img.scaled(320, 240, Qt::AspectRatioMode::IgnoreAspectRatio, Qt::TransformationMode::SmoothTransformation); ui->preview_box->setPixmap(QPixmap::fromImage(converted)); + pending_snapshots = 0; } void ConfigureCamera::changeEvent(QEvent* event) { diff --git a/src/yuzu/configuration/configure_camera.h b/src/yuzu/configuration/configure_camera.h index af7551c03..db9833b5c 100644 --- a/src/yuzu/configuration/configure_camera.h +++ b/src/yuzu/configuration/configure_camera.h @@ -44,6 +44,8 @@ private: InputCommon::InputSubsystem* input_subsystem; + bool is_virtual_camera; + int pending_snapshots; std::unique_ptr camera; std::unique_ptr camera_capture; std::unique_ptr camera_timer;