From 7c91aa7fdb08ca41ff35e2c126647eec7ad30225 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Sun, 8 May 2022 16:32:29 +0200 Subject: [PATCH] get more shit done --- src/frontend/qt_sdl/CameraManager.cpp | 176 ++++++++++--------- src/frontend/qt_sdl/CameraManager.h | 50 +++--- src/frontend/qt_sdl/CameraSettingsDialog.cpp | 90 +++++++++- src/frontend/qt_sdl/CameraSettingsDialog.h | 36 +++- src/frontend/qt_sdl/CameraSettingsDialog.ui | 8 +- src/frontend/qt_sdl/Config.cpp | 13 ++ src/frontend/qt_sdl/Config.h | 10 ++ src/frontend/qt_sdl/Platform.cpp | 6 +- 8 files changed, 268 insertions(+), 121 deletions(-) diff --git a/src/frontend/qt_sdl/CameraManager.cpp b/src/frontend/qt_sdl/CameraManager.cpp index 82aaf277..1f1ec4fe 100644 --- a/src/frontend/qt_sdl/CameraManager.cpp +++ b/src/frontend/qt_sdl/CameraManager.cpp @@ -17,11 +17,12 @@ */ #include "CameraManager.h" +#include "Config.h" CameraFrameDumper::CameraFrameDumper(QObject* parent) : QAbstractVideoSurface(parent) { - CamList.append((CameraManager*)parent); + camList.append((CameraManager*)parent); } bool CameraFrameDumper::present(const QVideoFrame& _frame) @@ -32,8 +33,8 @@ bool CameraFrameDumper::present(const QVideoFrame& _frame) if (!frame.isReadable()) return false; - for (CameraManager* cam : CamList) - cam->FeedFrame((u32*)frame.bits(), frame.width(), frame.height(), frame.pixelFormat() == QVideoFrame::Format_YUYV); + for (CameraManager* cam : camList) + cam->feedFrame((u32*)frame.bits(), frame.width(), frame.height(), frame.pixelFormat() == QVideoFrame::Format_YUYV); frame.unmap(); @@ -53,216 +54,219 @@ QList CameraFrameDumper::supportedPixelFormats(QAbstra CameraManager::CameraManager(int num, int width, int height, bool yuv) : QObject() { - Num = num; + this->num = num; + + startNum = 0; // QCamera needs to be controlled from the UI thread, hence this - connect(this, SIGNAL(CamStartSignal()), this, SLOT(CamStart())); - connect(this, SIGNAL(CamStopSignal()), this, SLOT(CamStop())); + connect(this, SIGNAL(camStartSignal()), this, SLOT(camStart())); + connect(this, SIGNAL(camStopSignal()), this, SLOT(camStop())); - FrameWidth = width; - FrameHeight = height; - FrameFormatYUV = yuv; + frameWidth = width; + frameHeight = height; + frameFormatYUV = yuv; - int fbsize = FrameWidth * FrameHeight; + int fbsize = frameWidth * frameHeight; if (yuv) fbsize /= 2; - FrameBuffer = new u32[fbsize]; + frameBuffer = new u32[fbsize]; - InputType = -1; - Init(); + inputType = -1; + init(); } CameraManager::~CameraManager() { - DeInit(); + deInit(); // save settings here? - delete[] FrameBuffer; + delete[] frameBuffer; } -void CameraManager::Init() +void CameraManager::init() { - if (InputType != -1) - DeInit(); + if (inputType != -1) + deInit(); - // TODO: load settings from config!! - InputType = 0; - InputType = 1; - ImagePath = "test.jpg"; - if(Num==0) - { - InputType = 2; - const QList cameras = QCameraInfo::availableCameras(); - CamDeviceName = cameras[0].deviceName(); - } + startNum = 0; + + inputType = Config::Camera[num].InputType; + imagePath = QString::fromStdString(Config::Camera[num].ImagePath); + camDeviceName = QString::fromStdString(Config::Camera[num].CamDeviceName); { // fill the framebuffer with black - int total = FrameWidth * FrameHeight; + int total = frameWidth * frameHeight; u32 fill = 0; - if (FrameFormatYUV) + if (frameFormatYUV) { total /= 2; fill = 0x80008000; } for (int i = 0; i < total; i++) - FrameBuffer[i] = fill; + frameBuffer[i] = fill; } - if (InputType == 1) + if (inputType == 1) { // still image - QImage img(ImagePath); + QImage img(imagePath); if (!img.isNull()) { QImage imgconv = img.convertToFormat(QImage::Format_RGB32); - if (FrameFormatYUV) + if (frameFormatYUV) { - CopyFrame_RGBtoYUV((u32*)img.bits(), img.width(), img.height(), - FrameBuffer, FrameWidth, FrameHeight); + copyFrame_RGBtoYUV((u32*)img.bits(), img.width(), img.height(), + frameBuffer, frameWidth, frameHeight); } else { - CopyFrame_Straight((u32*)img.bits(), img.width(), img.height(), - FrameBuffer, FrameWidth, FrameHeight, + copyFrame_Straight((u32*)img.bits(), img.width(), img.height(), + frameBuffer, frameWidth, frameHeight, false); } } } - else if (InputType == 2) + else if (inputType == 2) { // physical camera - CamDevice = new QCamera(CamDeviceName.toUtf8()); - CamDumper = new CameraFrameDumper(this); - CamDevice->setViewfinder(CamDumper); + camDevice = new QCamera(camDeviceName.toUtf8()); + camDumper = new CameraFrameDumper(this); + camDevice->setViewfinder(camDumper); - /*CamDevice->load(); + /*camDevice->load(); QCameraViewfinderSettings settings; - auto resolutions = CamDevice->supportedViewfinderResolutions(); + auto resolutions = camDevice->supportedViewfinderResolutions(); for (auto& res : resolutions) { printf("RESOLUTION: %d x %d\n", res.width(), res.height()); } - CamDevice->unload();*/ + camDevice->unload();*/ QCameraViewfinderSettings settings; settings.setResolution(640, 480); settings.setPixelFormat(QVideoFrame::Format_YUYV); - CamDevice->setViewfinderSettings(settings); + camDevice->setViewfinderSettings(settings); } } -void CameraManager::DeInit() +void CameraManager::deInit() { - if (InputType == 2) + if (inputType == 2) { - CamDevice->stop(); - delete CamDevice; - delete CamDumper; + camDevice->stop(); + delete camDevice; + delete camDumper; } - InputType = -1; + inputType = -1; } -void CameraManager::Start() +void CameraManager::start() { - if (InputType == 2) + startNum++; + if (startNum > 1) return; + + if (inputType == 2) { - emit CamStartSignal(); + emit camStartSignal(); } } -void CameraManager::Stop() +void CameraManager::stop() { - if (InputType == 2) + startNum--; + if (startNum > 0) return; + + if (inputType == 2) { - emit CamStopSignal(); + emit camStopSignal(); } } -void CameraManager::CamStart() +void CameraManager::camStart() { - CamDevice->start(); + camDevice->start(); } -void CameraManager::CamStop() +void CameraManager::camStop() { - CamDevice->stop(); + camDevice->stop(); } -void CameraManager::CaptureFrame(u32* frame, int width, int height, bool yuv) +void CameraManager::captureFrame(u32* frame, int width, int height, bool yuv) { - FrameMutex.lock(); + frameMutex.lock(); - if (width == FrameWidth && height == FrameHeight && yuv == FrameFormatYUV) + if (width == frameWidth && height == frameHeight && yuv == frameFormatYUV) { int len = width * height; if (yuv) len /= 2; - memcpy(frame, FrameBuffer, len * sizeof(u32)); + memcpy(frame, frameBuffer, len * sizeof(u32)); } else { - if (yuv == FrameFormatYUV) + if (yuv == frameFormatYUV) { - CopyFrame_Straight(FrameBuffer, FrameWidth, FrameHeight, + copyFrame_Straight(frameBuffer, frameWidth, frameHeight, frame, width, height, yuv); } else if (yuv) { - CopyFrame_RGBtoYUV(FrameBuffer, FrameWidth, FrameHeight, + copyFrame_RGBtoYUV(frameBuffer, frameWidth, frameHeight, frame, width, height); } else { - CopyFrame_YUVtoRGB(FrameBuffer, FrameWidth, FrameHeight, + copyFrame_YUVtoRGB(frameBuffer, frameWidth, frameHeight, frame, width, height); } } - FrameMutex.unlock(); + frameMutex.unlock(); } -void CameraManager::FeedFrame(u32* frame, int width, int height, bool yuv) +void CameraManager::feedFrame(u32* frame, int width, int height, bool yuv) { - FrameMutex.lock(); + frameMutex.lock(); - if (width == FrameWidth && height == FrameHeight && yuv == FrameFormatYUV) + if (width == frameWidth && height == frameHeight && yuv == frameFormatYUV) { int len = width * height; if (yuv) len /= 2; - memcpy(FrameBuffer, frame, len * sizeof(u32)); + memcpy(frameBuffer, frame, len * sizeof(u32)); } else { - if (yuv == FrameFormatYUV) + if (yuv == frameFormatYUV) { - CopyFrame_Straight(frame, width, height, - FrameBuffer, FrameWidth, FrameHeight, + copyFrame_Straight(frame, width, height, + frameBuffer, frameWidth, frameHeight, yuv); } else if (yuv) { - CopyFrame_RGBtoYUV(frame, width, height, - FrameBuffer, FrameWidth, FrameHeight); + copyFrame_RGBtoYUV(frame, width, height, + frameBuffer, frameWidth, frameHeight); } else { - CopyFrame_YUVtoRGB(frame, width, height, - FrameBuffer, FrameWidth, FrameHeight); + copyFrame_YUVtoRGB(frame, width, height, + frameBuffer, frameWidth, frameHeight); } } - FrameMutex.unlock(); + frameMutex.unlock(); } -void CameraManager::CopyFrame_Straight(u32* src, int swidth, int sheight, u32* dst, int dwidth, int dheight, bool yuv) +void CameraManager::copyFrame_Straight(u32* src, int swidth, int sheight, u32* dst, int dwidth, int dheight, bool yuv) { if (yuv) { @@ -283,7 +287,7 @@ void CameraManager::CopyFrame_Straight(u32* src, int swidth, int sheight, u32* d } } -void CameraManager::CopyFrame_RGBtoYUV(u32* src, int swidth, int sheight, u32* dst, int dwidth, int dheight) +void CameraManager::copyFrame_RGBtoYUV(u32* src, int swidth, int sheight, u32* dst, int dwidth, int dheight) { for (int dy = 0; dy < dheight; dy++) { @@ -330,7 +334,7 @@ void CameraManager::CopyFrame_RGBtoYUV(u32* src, int swidth, int sheight, u32* d } } -void CameraManager::CopyFrame_YUVtoRGB(u32* src, int swidth, int sheight, u32* dst, int dwidth, int dheight) +void CameraManager::copyFrame_YUVtoRGB(u32* src, int swidth, int sheight, u32* dst, int dwidth, int dheight) { for (int dy = 0; dy < dheight; dy++) { diff --git a/src/frontend/qt_sdl/CameraManager.h b/src/frontend/qt_sdl/CameraManager.h index 3b26d9cb..53688068 100644 --- a/src/frontend/qt_sdl/CameraManager.h +++ b/src/frontend/qt_sdl/CameraManager.h @@ -40,7 +40,7 @@ public: QList supportedPixelFormats(QAbstractVideoBuffer::HandleType type = QAbstractVideoBuffer::NoHandle) const override; private: - QList CamList; + QList camList; }; class CameraManager : public QObject @@ -51,42 +51,44 @@ public: CameraManager(int num, int width, int height, bool yuv); ~CameraManager(); - void Init(); - void DeInit(); + void init(); + void deInit(); - void Start(); - void Stop(); + void start(); + void stop(); - void CaptureFrame(u32* frame, int width, int height, bool yuv); + void captureFrame(u32* frame, int width, int height, bool yuv); - void FeedFrame(u32* frame, int width, int height, bool yuv); + void feedFrame(u32* frame, int width, int height, bool yuv); signals: - void CamStartSignal(); - void CamStopSignal(); + void camStartSignal(); + void camStopSignal(); private slots: - void CamStart(); - void CamStop(); + void camStart(); + void camStop(); private: - int Num; + int num; - int InputType; - QString ImagePath; - QString CamDeviceName; + int startNum; - QCamera* CamDevice; - CameraFrameDumper* CamDumper; + int inputType; + QString imagePath; + QString camDeviceName; - int FrameWidth, FrameHeight; - bool FrameFormatYUV; - u32* FrameBuffer; - QMutex FrameMutex; + QCamera* camDevice; + CameraFrameDumper* camDumper; - void CopyFrame_Straight(u32* src, int swidth, int sheight, u32* dst, int dwidth, int dheight, bool yuv); - void CopyFrame_RGBtoYUV(u32* src, int swidth, int sheight, u32* dst, int dwidth, int dheight); - void CopyFrame_YUVtoRGB(u32* src, int swidth, int sheight, u32* dst, int dwidth, int dheight); + int frameWidth, frameHeight; + bool frameFormatYUV; + u32* frameBuffer; + QMutex frameMutex; + + void copyFrame_Straight(u32* src, int swidth, int sheight, u32* dst, int dwidth, int dheight, bool yuv); + void copyFrame_RGBtoYUV(u32* src, int swidth, int sheight, u32* dst, int dwidth, int dheight); + void copyFrame_YUVtoRGB(u32* src, int swidth, int sheight, u32* dst, int dwidth, int dheight); }; #endif // CAMERAMANAGER_H diff --git a/src/frontend/qt_sdl/CameraSettingsDialog.cpp b/src/frontend/qt_sdl/CameraSettingsDialog.cpp index 5d8c1e3d..6804f12d 100644 --- a/src/frontend/qt_sdl/CameraSettingsDialog.cpp +++ b/src/frontend/qt_sdl/CameraSettingsDialog.cpp @@ -18,6 +18,8 @@ #include #include +#include +#include #include "types.h" #include "Platform.h" @@ -31,13 +33,79 @@ CameraSettingsDialog* CameraSettingsDialog::currentDlg = nullptr; extern std::string EmuDirectory; +extern CameraManager* camManager[2]; + + +CameraPreviewPanel::CameraPreviewPanel(QWidget* parent) : QWidget(parent) +{ + currentCam = nullptr; + updateTimer = startTimer(50); +} + +CameraPreviewPanel::~CameraPreviewPanel() +{ + killTimer(updateTimer); +} + +void CameraPreviewPanel::paintEvent(QPaintEvent* event) +{ + QPainter painter(this); + + if (!currentCam) + { + painter.fillRect(event->rect(), QColor::fromRgb(0, 0, 0)); + return; + } + + QImage picture(256, 192, QImage::Format_RGB32); + currentCam->captureFrame((u32*)picture.bits(), 256, 192, false); + painter.drawImage(0, 0, picture); +} + CameraSettingsDialog::CameraSettingsDialog(QWidget* parent) : QDialog(parent), ui(new Ui::CameraSettingsDialog) { + previewPanel = nullptr; + currentCam = nullptr; + ui->setupUi(this); setAttribute(Qt::WA_DeleteOnClose); - // + ui->cbCameraSel->addItem("DSi outer camera"); + ui->cbCameraSel->addItem("DSi inner camera"); + + const QList cameras = QCameraInfo::availableCameras(); + for (const QCameraInfo &cameraInfo : cameras) + { + QString name = cameraInfo.description(); + QCamera::Position pos = cameraInfo.position(); + if (pos != QCamera::UnspecifiedPosition) + { + name += " ("; + if (pos == QCamera::FrontFace) + name += "inner camera"; + else if (pos == QCamera::BackFace) + name += "outer camera"; + name += ")"; + } + + ui->cbPhysicalCamera->addItem(name, cameraInfo.deviceName()); + } + + grpInputType = new QButtonGroup(this); + grpInputType->addButton(ui->rbPictureNone, 0); + grpInputType->addButton(ui->rbPictureImg, 1); + grpInputType->addButton(ui->rbPictureCamera, 2); + connect(grpInputType, SIGNAL(buttonClicked(int)), this, SLOT(onChangeInputType(int))); + + previewPanel = new CameraPreviewPanel(this); + QVBoxLayout* previewLayout = new QVBoxLayout(); + previewLayout->addWidget(previewPanel); + ui->grpPreview->setLayout(previewLayout); + previewPanel->setMinimumSize(256, 192); + previewPanel->setMaximumSize(256, 192); + + on_cbCameraSel_currentIndexChanged(ui->cbCameraSel->currentIndex()); } CameraSettingsDialog::~CameraSettingsDialog() @@ -60,4 +128,22 @@ void CameraSettingsDialog::on_CameraSettingsDialog_rejected() closeDlg(); } -// +void CameraSettingsDialog::on_cbCameraSel_currentIndexChanged(int id) +{ + if (!previewPanel) return; + + if (currentCam) + { + currentCam->stop(); + } + + currentCam = camManager[id]; + previewPanel->setCurrentCam(currentCam); + + currentCam->start(); +} + +void CameraSettingsDialog::onChangeInputType(int type) +{ + printf("INPUT = %d\n", type); +} diff --git a/src/frontend/qt_sdl/CameraSettingsDialog.h b/src/frontend/qt_sdl/CameraSettingsDialog.h index ccd7f04a..2afd336d 100644 --- a/src/frontend/qt_sdl/CameraSettingsDialog.h +++ b/src/frontend/qt_sdl/CameraSettingsDialog.h @@ -22,9 +22,36 @@ #include #include +#include "CameraManager.h" + namespace Ui { class CameraSettingsDialog; } class CameraSettingsDialog; +class CameraPreviewPanel : public QWidget +{ + Q_OBJECT + +public: + CameraPreviewPanel(QWidget* parent); + ~CameraPreviewPanel(); + + void setCurrentCam(CameraManager* cam) + { + currentCam = cam; + } + +protected: + void paintEvent(QPaintEvent* event) override; + void timerEvent(QTimerEvent* event) override + { + repaint(); + } + +private: + int updateTimer; + CameraManager* currentCam; +}; + class CameraSettingsDialog : public QDialog { Q_OBJECT @@ -58,12 +85,17 @@ private slots: void on_CameraSettingsDialog_accepted(); void on_CameraSettingsDialog_rejected(); - // + void on_cbCameraSel_currentIndexChanged(int id); + + void onChangeInputType(int type); private: Ui::CameraSettingsDialog* ui; - // + QButtonGroup* grpInputType; + + CameraPreviewPanel* previewPanel; + CameraManager* currentCam; }; #endif // CAMERASETTINGSDIALOG_H diff --git a/src/frontend/qt_sdl/CameraSettingsDialog.ui b/src/frontend/qt_sdl/CameraSettingsDialog.ui index 2a4a0ae3..a8749672 100644 --- a/src/frontend/qt_sdl/CameraSettingsDialog.ui +++ b/src/frontend/qt_sdl/CameraSettingsDialog.ui @@ -6,8 +6,8 @@ 0 0 - 607 - 455 + 605 + 341 @@ -89,9 +89,9 @@ - + - SHITPISS + Flip horizontally diff --git a/src/frontend/qt_sdl/Config.cpp b/src/frontend/qt_sdl/Config.cpp index 7a0ec698..ac04b5da 100644 --- a/src/frontend/qt_sdl/Config.cpp +++ b/src/frontend/qt_sdl/Config.cpp @@ -139,6 +139,8 @@ bool DSBatteryLevelOkay; int DSiBatteryLevel; bool DSiBatteryCharging; +CameraConfig Camera[2]; + const char* kConfigFile = "melonDS.ini"; @@ -313,6 +315,17 @@ ConfigEntry ConfigFile[] = {"DSiBatteryLevel", 0, &DSiBatteryLevel, 0xF}, {"DSiBatteryCharging", 1, &DSiBatteryCharging, true}, + // TODO!! + // we need a more elegant way to deal with this + {"Camera0_InputType", 0, &Camera[0].InputType, 0}, + {"Camera0_ImagePath", 2, &Camera[0].ImagePath, (std::string)""}, + {"Camera0_CamDeviceName", 2, &Camera[0].CamDeviceName, (std::string)""}, + {"Camera0_XFlip", 1, &Camera[0].XFlip, false}, + {"Camera1_InputType", 0, &Camera[1].InputType, 0}, + {"Camera1_ImagePath", 2, &Camera[1].ImagePath, (std::string)""}, + {"Camera1_CamDeviceName", 2, &Camera[1].CamDeviceName, (std::string)""}, + {"Camera1_XFlip", 1, &Camera[1].XFlip, false}, + {"", -1, nullptr, 0} }; diff --git a/src/frontend/qt_sdl/Config.h b/src/frontend/qt_sdl/Config.h index f2f8ddcd..7a0b0ca0 100644 --- a/src/frontend/qt_sdl/Config.h +++ b/src/frontend/qt_sdl/Config.h @@ -60,6 +60,14 @@ struct ConfigEntry std::variant Default; }; +struct CameraConfig +{ + int InputType; // 0=blank 1=image 2=camera + std::string ImagePath; + std::string CamDeviceName; + bool XFlip; +}; + extern int KeyMapping[12]; extern int JoyMapping[12]; @@ -173,6 +181,8 @@ extern bool DSBatteryLevelOkay; extern int DSiBatteryLevel; extern bool DSiBatteryCharging; +extern CameraConfig Camera[2]; + void Load(); void Save(); diff --git a/src/frontend/qt_sdl/Platform.cpp b/src/frontend/qt_sdl/Platform.cpp index d031e3b4..2a3dde55 100644 --- a/src/frontend/qt_sdl/Platform.cpp +++ b/src/frontend/qt_sdl/Platform.cpp @@ -583,17 +583,17 @@ int LAN_RecvPacket(u8* data) void Camera_Start(int num) { - return camManager[num]->Start(); + return camManager[num]->start(); } void Camera_Stop(int num) { - return camManager[num]->Stop(); + return camManager[num]->stop(); } void Camera_CaptureFrame(int num, u32* frame, int width, int height, bool yuv) { - return camManager[num]->CaptureFrame(frame, width, height, yuv); + return camManager[num]->captureFrame(frame, width, height, yuv); } }