get more shit done

This commit is contained in:
Arisotura 2022-05-08 16:32:29 +02:00 committed by Nadia Holmquist Pedersen
parent 1884db5e42
commit 7c91aa7fdb
8 changed files with 268 additions and 121 deletions

View File

@ -17,11 +17,12 @@
*/ */
#include "CameraManager.h" #include "CameraManager.h"
#include "Config.h"
CameraFrameDumper::CameraFrameDumper(QObject* parent) : QAbstractVideoSurface(parent) CameraFrameDumper::CameraFrameDumper(QObject* parent) : QAbstractVideoSurface(parent)
{ {
CamList.append((CameraManager*)parent); camList.append((CameraManager*)parent);
} }
bool CameraFrameDumper::present(const QVideoFrame& _frame) bool CameraFrameDumper::present(const QVideoFrame& _frame)
@ -32,8 +33,8 @@ bool CameraFrameDumper::present(const QVideoFrame& _frame)
if (!frame.isReadable()) if (!frame.isReadable())
return false; return false;
for (CameraManager* cam : CamList) for (CameraManager* cam : camList)
cam->FeedFrame((u32*)frame.bits(), frame.width(), frame.height(), frame.pixelFormat() == QVideoFrame::Format_YUYV); cam->feedFrame((u32*)frame.bits(), frame.width(), frame.height(), frame.pixelFormat() == QVideoFrame::Format_YUYV);
frame.unmap(); frame.unmap();
@ -53,216 +54,219 @@ QList<QVideoFrame::PixelFormat> CameraFrameDumper::supportedPixelFormats(QAbstra
CameraManager::CameraManager(int num, int width, int height, bool yuv) : QObject() 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 // QCamera needs to be controlled from the UI thread, hence this
connect(this, SIGNAL(CamStartSignal()), this, SLOT(CamStart())); connect(this, SIGNAL(camStartSignal()), this, SLOT(camStart()));
connect(this, SIGNAL(CamStopSignal()), this, SLOT(CamStop())); connect(this, SIGNAL(camStopSignal()), this, SLOT(camStop()));
FrameWidth = width; frameWidth = width;
FrameHeight = height; frameHeight = height;
FrameFormatYUV = yuv; frameFormatYUV = yuv;
int fbsize = FrameWidth * FrameHeight; int fbsize = frameWidth * frameHeight;
if (yuv) fbsize /= 2; if (yuv) fbsize /= 2;
FrameBuffer = new u32[fbsize]; frameBuffer = new u32[fbsize];
InputType = -1; inputType = -1;
Init(); init();
} }
CameraManager::~CameraManager() CameraManager::~CameraManager()
{ {
DeInit(); deInit();
// save settings here? // save settings here?
delete[] FrameBuffer; delete[] frameBuffer;
} }
void CameraManager::Init() void CameraManager::init()
{ {
if (InputType != -1) if (inputType != -1)
DeInit(); deInit();
// TODO: load settings from config!! startNum = 0;
InputType = 0;
InputType = 1; inputType = Config::Camera[num].InputType;
ImagePath = "test.jpg"; imagePath = QString::fromStdString(Config::Camera[num].ImagePath);
if(Num==0) camDeviceName = QString::fromStdString(Config::Camera[num].CamDeviceName);
{
InputType = 2;
const QList<QCameraInfo> cameras = QCameraInfo::availableCameras();
CamDeviceName = cameras[0].deviceName();
}
{ {
// fill the framebuffer with black // fill the framebuffer with black
int total = FrameWidth * FrameHeight; int total = frameWidth * frameHeight;
u32 fill = 0; u32 fill = 0;
if (FrameFormatYUV) if (frameFormatYUV)
{ {
total /= 2; total /= 2;
fill = 0x80008000; fill = 0x80008000;
} }
for (int i = 0; i < total; i++) for (int i = 0; i < total; i++)
FrameBuffer[i] = fill; frameBuffer[i] = fill;
} }
if (InputType == 1) if (inputType == 1)
{ {
// still image // still image
QImage img(ImagePath); QImage img(imagePath);
if (!img.isNull()) if (!img.isNull())
{ {
QImage imgconv = img.convertToFormat(QImage::Format_RGB32); QImage imgconv = img.convertToFormat(QImage::Format_RGB32);
if (FrameFormatYUV) if (frameFormatYUV)
{ {
CopyFrame_RGBtoYUV((u32*)img.bits(), img.width(), img.height(), copyFrame_RGBtoYUV((u32*)img.bits(), img.width(), img.height(),
FrameBuffer, FrameWidth, FrameHeight); frameBuffer, frameWidth, frameHeight);
} }
else else
{ {
CopyFrame_Straight((u32*)img.bits(), img.width(), img.height(), copyFrame_Straight((u32*)img.bits(), img.width(), img.height(),
FrameBuffer, FrameWidth, FrameHeight, frameBuffer, frameWidth, frameHeight,
false); false);
} }
} }
} }
else if (InputType == 2) else if (inputType == 2)
{ {
// physical camera // physical camera
CamDevice = new QCamera(CamDeviceName.toUtf8()); camDevice = new QCamera(camDeviceName.toUtf8());
CamDumper = new CameraFrameDumper(this); camDumper = new CameraFrameDumper(this);
CamDevice->setViewfinder(CamDumper); camDevice->setViewfinder(camDumper);
/*CamDevice->load(); /*camDevice->load();
QCameraViewfinderSettings settings; QCameraViewfinderSettings settings;
auto resolutions = CamDevice->supportedViewfinderResolutions(); auto resolutions = camDevice->supportedViewfinderResolutions();
for (auto& res : resolutions) for (auto& res : resolutions)
{ {
printf("RESOLUTION: %d x %d\n", res.width(), res.height()); printf("RESOLUTION: %d x %d\n", res.width(), res.height());
} }
CamDevice->unload();*/ camDevice->unload();*/
QCameraViewfinderSettings settings; QCameraViewfinderSettings settings;
settings.setResolution(640, 480); settings.setResolution(640, 480);
settings.setPixelFormat(QVideoFrame::Format_YUYV); 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(); camDevice->stop();
delete CamDevice; delete camDevice;
delete CamDumper; 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; int len = width * height;
if (yuv) len /= 2; if (yuv) len /= 2;
memcpy(frame, FrameBuffer, len * sizeof(u32)); memcpy(frame, frameBuffer, len * sizeof(u32));
} }
else else
{ {
if (yuv == FrameFormatYUV) if (yuv == frameFormatYUV)
{ {
CopyFrame_Straight(FrameBuffer, FrameWidth, FrameHeight, copyFrame_Straight(frameBuffer, frameWidth, frameHeight,
frame, width, height, frame, width, height,
yuv); yuv);
} }
else if (yuv) else if (yuv)
{ {
CopyFrame_RGBtoYUV(FrameBuffer, FrameWidth, FrameHeight, copyFrame_RGBtoYUV(frameBuffer, frameWidth, frameHeight,
frame, width, height); frame, width, height);
} }
else else
{ {
CopyFrame_YUVtoRGB(FrameBuffer, FrameWidth, FrameHeight, copyFrame_YUVtoRGB(frameBuffer, frameWidth, frameHeight,
frame, width, height); 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; int len = width * height;
if (yuv) len /= 2; if (yuv) len /= 2;
memcpy(FrameBuffer, frame, len * sizeof(u32)); memcpy(frameBuffer, frame, len * sizeof(u32));
} }
else else
{ {
if (yuv == FrameFormatYUV) if (yuv == frameFormatYUV)
{ {
CopyFrame_Straight(frame, width, height, copyFrame_Straight(frame, width, height,
FrameBuffer, FrameWidth, FrameHeight, frameBuffer, frameWidth, frameHeight,
yuv); yuv);
} }
else if (yuv) else if (yuv)
{ {
CopyFrame_RGBtoYUV(frame, width, height, copyFrame_RGBtoYUV(frame, width, height,
FrameBuffer, FrameWidth, FrameHeight); frameBuffer, frameWidth, frameHeight);
} }
else else
{ {
CopyFrame_YUVtoRGB(frame, width, height, copyFrame_YUVtoRGB(frame, width, height,
FrameBuffer, FrameWidth, FrameHeight); 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) 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++) 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++) for (int dy = 0; dy < dheight; dy++)
{ {

View File

@ -40,7 +40,7 @@ public:
QList<QVideoFrame::PixelFormat> supportedPixelFormats(QAbstractVideoBuffer::HandleType type = QAbstractVideoBuffer::NoHandle) const override; QList<QVideoFrame::PixelFormat> supportedPixelFormats(QAbstractVideoBuffer::HandleType type = QAbstractVideoBuffer::NoHandle) const override;
private: private:
QList<CameraManager*> CamList; QList<CameraManager*> camList;
}; };
class CameraManager : public QObject class CameraManager : public QObject
@ -51,42 +51,44 @@ public:
CameraManager(int num, int width, int height, bool yuv); CameraManager(int num, int width, int height, bool yuv);
~CameraManager(); ~CameraManager();
void Init(); void init();
void DeInit(); void deInit();
void Start(); void start();
void Stop(); 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: signals:
void CamStartSignal(); void camStartSignal();
void CamStopSignal(); void camStopSignal();
private slots: private slots:
void CamStart(); void camStart();
void CamStop(); void camStop();
private: private:
int Num; int num;
int InputType; int startNum;
QString ImagePath;
QString CamDeviceName;
QCamera* CamDevice; int inputType;
CameraFrameDumper* CamDumper; QString imagePath;
QString camDeviceName;
int FrameWidth, FrameHeight; QCamera* camDevice;
bool FrameFormatYUV; CameraFrameDumper* camDumper;
u32* FrameBuffer;
QMutex FrameMutex;
void CopyFrame_Straight(u32* src, int swidth, int sheight, u32* dst, int dwidth, int dheight, bool yuv); int frameWidth, frameHeight;
void CopyFrame_RGBtoYUV(u32* src, int swidth, int sheight, u32* dst, int dwidth, int dheight); bool frameFormatYUV;
void CopyFrame_YUVtoRGB(u32* src, int swidth, int sheight, u32* dst, int dwidth, int dheight); 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 #endif // CAMERAMANAGER_H

View File

@ -18,6 +18,8 @@
#include <stdio.h> #include <stdio.h>
#include <QFileDialog> #include <QFileDialog>
#include <QPaintEvent>
#include <QPainter>
#include "types.h" #include "types.h"
#include "Platform.h" #include "Platform.h"
@ -31,13 +33,79 @@ CameraSettingsDialog* CameraSettingsDialog::currentDlg = nullptr;
extern std::string EmuDirectory; 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) CameraSettingsDialog::CameraSettingsDialog(QWidget* parent) : QDialog(parent), ui(new Ui::CameraSettingsDialog)
{ {
previewPanel = nullptr;
currentCam = nullptr;
ui->setupUi(this); ui->setupUi(this);
setAttribute(Qt::WA_DeleteOnClose); setAttribute(Qt::WA_DeleteOnClose);
// ui->cbCameraSel->addItem("DSi outer camera");
ui->cbCameraSel->addItem("DSi inner camera");
const QList<QCameraInfo> 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() CameraSettingsDialog::~CameraSettingsDialog()
@ -60,4 +128,22 @@ void CameraSettingsDialog::on_CameraSettingsDialog_rejected()
closeDlg(); 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);
}

View File

@ -22,9 +22,36 @@
#include <QDialog> #include <QDialog>
#include <QButtonGroup> #include <QButtonGroup>
#include "CameraManager.h"
namespace Ui { class CameraSettingsDialog; } namespace Ui { class CameraSettingsDialog; }
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 class CameraSettingsDialog : public QDialog
{ {
Q_OBJECT Q_OBJECT
@ -58,12 +85,17 @@ private slots:
void on_CameraSettingsDialog_accepted(); void on_CameraSettingsDialog_accepted();
void on_CameraSettingsDialog_rejected(); void on_CameraSettingsDialog_rejected();
// void on_cbCameraSel_currentIndexChanged(int id);
void onChangeInputType(int type);
private: private:
Ui::CameraSettingsDialog* ui; Ui::CameraSettingsDialog* ui;
// QButtonGroup* grpInputType;
CameraPreviewPanel* previewPanel;
CameraManager* currentCam;
}; };
#endif // CAMERASETTINGSDIALOG_H #endif // CAMERASETTINGSDIALOG_H

View File

@ -6,8 +6,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>607</width> <width>605</width>
<height>455</height> <height>341</height>
</rect> </rect>
</property> </property>
<property name="sizePolicy"> <property name="sizePolicy">
@ -89,9 +89,9 @@
</property> </property>
<layout class="QGridLayout" name="gridLayout_4"> <layout class="QGridLayout" name="gridLayout_4">
<item row="0" column="0"> <item row="0" column="0">
<widget class="QLabel" name="label_2"> <widget class="QCheckBox" name="chkFlipPicture">
<property name="text"> <property name="text">
<string>SHITPISS</string> <string>Flip horizontally</string>
</property> </property>
</widget> </widget>
</item> </item>

View File

@ -139,6 +139,8 @@ bool DSBatteryLevelOkay;
int DSiBatteryLevel; int DSiBatteryLevel;
bool DSiBatteryCharging; bool DSiBatteryCharging;
CameraConfig Camera[2];
const char* kConfigFile = "melonDS.ini"; const char* kConfigFile = "melonDS.ini";
@ -313,6 +315,17 @@ ConfigEntry ConfigFile[] =
{"DSiBatteryLevel", 0, &DSiBatteryLevel, 0xF}, {"DSiBatteryLevel", 0, &DSiBatteryLevel, 0xF},
{"DSiBatteryCharging", 1, &DSiBatteryCharging, true}, {"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} {"", -1, nullptr, 0}
}; };

View File

@ -60,6 +60,14 @@ struct ConfigEntry
std::variant<int, bool, std::string> Default; std::variant<int, bool, std::string> 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 KeyMapping[12];
extern int JoyMapping[12]; extern int JoyMapping[12];
@ -173,6 +181,8 @@ extern bool DSBatteryLevelOkay;
extern int DSiBatteryLevel; extern int DSiBatteryLevel;
extern bool DSiBatteryCharging; extern bool DSiBatteryCharging;
extern CameraConfig Camera[2];
void Load(); void Load();
void Save(); void Save();

View File

@ -583,17 +583,17 @@ int LAN_RecvPacket(u8* data)
void Camera_Start(int num) void Camera_Start(int num)
{ {
return camManager[num]->Start(); return camManager[num]->start();
} }
void Camera_Stop(int num) 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) 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);
} }
} }