rpcsx/rpcs3qt-legacy/camera_settings_dialog.cpp

285 lines
9.3 KiB
C++
Raw Normal View History

2021-10-22 16:58:55 +02:00
#include "stdafx.h"
#include "camera_settings_dialog.h"
#include "ui_camera_settings_dialog.h"
2025-02-25 18:52:08 +01:00
#include "permissions.h"
2021-10-22 16:58:55 +02:00
#include "Emu/Io/camera_config.h"
2021-05-22 10:42:05 +02:00
#include <QCameraDevice>
#include <QMediaDevices>
2021-10-22 16:58:55 +02:00
#include <QMessageBox>
#include <QPushButton>
LOG_CHANNEL(camera_log, "Camera");
template <>
2021-05-22 10:42:05 +02:00
void fmt_class_string<QVideoFrameFormat::PixelFormat>::format(std::string& out, u64 arg)
2021-10-22 16:58:55 +02:00
{
2021-05-22 10:42:05 +02:00
format_enum(out, arg, [](QVideoFrameFormat::PixelFormat value)
2021-10-22 16:58:55 +02:00
{
switch (value)
{
case QVideoFrameFormat::Format_ARGB8888: return "ARGB8888";
case QVideoFrameFormat::Format_ARGB8888_Premultiplied: return "ARGB8888_Premultiplied";
case QVideoFrameFormat::Format_XRGB8888: return "XRGB8888";
case QVideoFrameFormat::Format_BGRA8888: return "BGRA8888";
case QVideoFrameFormat::Format_BGRA8888_Premultiplied: return "BGRA8888_Premultiplied";
case QVideoFrameFormat::Format_BGRX8888: return "BGRX8888";
case QVideoFrameFormat::Format_ABGR8888: return "ABGR8888";
case QVideoFrameFormat::Format_XBGR8888: return "XBGR8888";
case QVideoFrameFormat::Format_RGBA8888: return "RGBA8888";
case QVideoFrameFormat::Format_RGBX8888: return "RGBX8888";
case QVideoFrameFormat::Format_AYUV: return "AYUV";
case QVideoFrameFormat::Format_AYUV_Premultiplied: return "AYUV_Premultiplied";
case QVideoFrameFormat::Format_YUV420P: return "YUV420P";
case QVideoFrameFormat::Format_YUV422P: return "YUV422P";
case QVideoFrameFormat::Format_YV12: return "YV12";
case QVideoFrameFormat::Format_UYVY: return "UYVY";
case QVideoFrameFormat::Format_YUYV: return "YUYV";
case QVideoFrameFormat::Format_NV12: return "NV12";
case QVideoFrameFormat::Format_NV21: return "NV21";
case QVideoFrameFormat::Format_IMC1: return "IMC1";
case QVideoFrameFormat::Format_IMC2: return "IMC2";
case QVideoFrameFormat::Format_IMC3: return "IMC3";
case QVideoFrameFormat::Format_IMC4: return "IMC4";
case QVideoFrameFormat::Format_Y8: return "Y8";
case QVideoFrameFormat::Format_Y16: return "Y16";
case QVideoFrameFormat::Format_P010: return "P010";
case QVideoFrameFormat::Format_P016: return "P016";
case QVideoFrameFormat::Format_SamplerExternalOES: return "SamplerExternalOES";
case QVideoFrameFormat::Format_Jpeg: return "Jpeg";
case QVideoFrameFormat::Format_SamplerRect: return "SamplerRect";
default: return unknown;
}
});
2021-10-22 16:58:55 +02:00
}
2021-05-22 10:42:05 +02:00
Q_DECLARE_METATYPE(QCameraDevice);
2021-10-22 16:58:55 +02:00
camera_settings_dialog::camera_settings_dialog(QWidget* parent)
: QDialog(parent), ui(new Ui::camera_settings_dialog)
2021-10-22 16:58:55 +02:00
{
ui->setupUi(this);
load_config();
2021-05-22 10:42:05 +02:00
for (const QCameraDevice& camera_info : QMediaDevices::videoInputs())
2021-10-22 16:58:55 +02:00
{
if (camera_info.isNull())
continue;
2021-10-22 16:58:55 +02:00
ui->combo_camera->addItem(camera_info.description(), QVariant::fromValue(camera_info));
camera_log.notice("Found camera: '%s'", camera_info.description());
2021-10-22 16:58:55 +02:00
}
connect(ui->combo_camera, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &camera_settings_dialog::handle_camera_change);
connect(ui->combo_settings, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &camera_settings_dialog::handle_settings_change);
connect(ui->buttonBox, &QDialogButtonBox::clicked, [this](QAbstractButton* button)
{
if (button == ui->buttonBox->button(QDialogButtonBox::Save))
{
save_config();
accept();
}
else if (button == ui->buttonBox->button(QDialogButtonBox::Apply))
{
save_config();
}
});
2021-10-22 16:58:55 +02:00
if (ui->combo_camera->count() == 0)
{
ui->combo_camera->setEnabled(false);
ui->combo_settings->setEnabled(false);
ui->buttonBox->button(QDialogButtonBox::Save)->setEnabled(false);
ui->buttonBox->button(QDialogButtonBox::Apply)->setEnabled(false);
}
else
{
// TODO: show camera ID somewhere
ui->combo_camera->setCurrentIndex(0);
}
}
camera_settings_dialog::~camera_settings_dialog()
{
}
void camera_settings_dialog::handle_camera_change(int index)
{
2021-05-22 10:42:05 +02:00
if (index < 0 || !ui->combo_camera->itemData(index).canConvert<QCameraDevice>())
2021-10-22 16:58:55 +02:00
{
ui->combo_settings->clear();
return;
}
2021-05-22 10:42:05 +02:00
const QCameraDevice camera_info = ui->combo_camera->itemData(index).value<QCameraDevice>();
2021-10-22 16:58:55 +02:00
if (camera_info.isNull())
{
ui->combo_settings->clear();
return;
}
m_camera.reset(new QCamera(camera_info));
2021-05-22 10:42:05 +02:00
m_media_capture_session.reset(new QMediaCaptureSession(nullptr));
m_media_capture_session->setCamera(m_camera.get());
m_media_capture_session->setVideoSink(ui->videoWidget->videoSink());
2021-10-22 16:58:55 +02:00
if (!m_camera->isAvailable())
{
ui->combo_settings->clear();
QMessageBox::warning(this, tr("Camera not available"), tr("The selected camera is not available.\nIt might be blocked by another application."));
return;
}
ui->combo_settings->blockSignals(true);
ui->combo_settings->clear();
2021-05-22 10:42:05 +02:00
QList<QCameraFormat> settings = camera_info.videoFormats();
std::sort(settings.begin(), settings.end(), [](const QCameraFormat& l, const QCameraFormat& r) -> bool
{
if (l.resolution().width() > r.resolution().width())
return true;
if (l.resolution().width() < r.resolution().width())
return false;
if (l.resolution().height() > r.resolution().height())
return true;
if (l.resolution().height() < r.resolution().height())
return false;
if (l.minFrameRate() > r.minFrameRate())
return true;
if (l.minFrameRate() < r.minFrameRate())
return false;
if (l.maxFrameRate() > r.maxFrameRate())
return true;
if (l.maxFrameRate() < r.maxFrameRate())
return false;
if (l.pixelFormat() > r.pixelFormat())
return true;
if (l.pixelFormat() < r.pixelFormat())
return false;
return false;
});
2021-10-22 16:58:55 +02:00
2021-05-22 10:42:05 +02:00
for (const QCameraFormat& setting : settings)
2021-10-22 16:58:55 +02:00
{
if (setting.isNull())
continue;
2021-05-22 10:42:05 +02:00
const QString description = tr("%0x%1, %2-%3 FPS, Format=%4")
.arg(setting.resolution().width())
.arg(setting.resolution().height())
.arg(setting.minFrameRate())
.arg(setting.maxFrameRate())
.arg(QString::fromStdString(fmt::format("%s", setting.pixelFormat())));
2021-10-22 16:58:55 +02:00
ui->combo_settings->addItem(description, QVariant::fromValue(setting));
}
ui->combo_settings->blockSignals(false);
if (ui->combo_settings->count() == 0)
{
ui->combo_settings->setEnabled(false);
}
else
{
// Load selected settings from config file
int index = 0;
bool success = false;
2021-05-22 10:42:05 +02:00
const std::string key = camera_info.id().toStdString();
2021-10-22 16:58:55 +02:00
cfg_camera::camera_setting cfg_setting = g_cfg_camera.get_camera_setting(key, success);
if (success)
{
camera_log.notice("Found config entry for camera \"%s\"", key);
// Select matching drowdown entry
const double epsilon = 0.001;
for (int i = 0; i < ui->combo_settings->count(); i++)
{
2021-05-22 10:42:05 +02:00
const QCameraFormat tmp = ui->combo_settings->itemData(i).value<QCameraFormat>();
if (tmp.resolution().width() == cfg_setting.width &&
tmp.resolution().height() == cfg_setting.height &&
tmp.minFrameRate() >= (cfg_setting.min_fps - epsilon) &&
tmp.minFrameRate() <= (cfg_setting.min_fps + epsilon) &&
tmp.maxFrameRate() >= (cfg_setting.max_fps - epsilon) &&
tmp.maxFrameRate() <= (cfg_setting.max_fps + epsilon) &&
tmp.pixelFormat() == static_cast<QVideoFrameFormat::PixelFormat>(cfg_setting.format))
2021-10-22 16:58:55 +02:00
{
index = i;
break;
}
}
}
ui->combo_settings->setCurrentIndex(std::max<int>(0, index));
ui->combo_settings->setEnabled(true);
// Update config to match user interface outcome
2021-05-22 10:42:05 +02:00
const QCameraFormat setting = ui->combo_settings->currentData().value<QCameraFormat>();
2021-10-22 16:58:55 +02:00
cfg_setting.width = setting.resolution().width();
cfg_setting.height = setting.resolution().height();
2021-05-22 10:42:05 +02:00
cfg_setting.min_fps = setting.minFrameRate();
cfg_setting.max_fps = setting.maxFrameRate();
2021-10-22 16:58:55 +02:00
cfg_setting.format = static_cast<int>(setting.pixelFormat());
g_cfg_camera.set_camera_setting(key, cfg_setting);
}
}
void camera_settings_dialog::handle_settings_change(int index)
{
if (!m_camera)
{
return;
}
if (!m_camera->isAvailable())
{
QMessageBox::warning(this, tr("Camera not available"), tr("The selected camera is not available.\nIt might be blocked by another application."));
return;
}
if (!gui::utils::check_camera_permission(this, [this, index]()
{
handle_settings_change(index);
},
[this]()
{
QMessageBox::warning(this, tr("Camera permissions denied!"), tr("RPCS3 has no permissions to access cameras on this device."));
}))
2023-11-04 22:14:03 +01:00
{
return;
}
2021-05-22 10:42:05 +02:00
if (index >= 0 && ui->combo_settings->itemData(index).canConvert<QCameraFormat>() && ui->combo_camera->currentData().canConvert<QCameraDevice>())
2021-10-22 16:58:55 +02:00
{
2021-05-22 10:42:05 +02:00
const QCameraFormat setting = ui->combo_settings->itemData(index).value<QCameraFormat>();
2021-10-22 16:58:55 +02:00
if (!setting.isNull())
{
2021-05-22 10:42:05 +02:00
m_camera->setCameraFormat(setting);
2021-10-22 16:58:55 +02:00
}
cfg_camera::camera_setting cfg_setting;
cfg_setting.width = setting.resolution().width();
cfg_setting.height = setting.resolution().height();
2021-05-22 10:42:05 +02:00
cfg_setting.min_fps = setting.minFrameRate();
cfg_setting.max_fps = setting.maxFrameRate();
2021-10-22 16:58:55 +02:00
cfg_setting.format = static_cast<int>(setting.pixelFormat());
2021-05-22 10:42:05 +02:00
g_cfg_camera.set_camera_setting(ui->combo_camera->currentData().value<QCameraDevice>().id().toStdString(), cfg_setting);
2021-10-22 16:58:55 +02:00
}
m_camera->start();
}
void camera_settings_dialog::load_config()
{
if (!g_cfg_camera.load())
{
camera_log.notice("Could not load camera config. Using defaults.");
}
}
void camera_settings_dialog::save_config()
{
g_cfg_camera.save();
}