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 "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<QVideoFrame::PixelFormat> 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<QCameraInfo> 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++)
{

View File

@ -40,7 +40,7 @@ public:
QList<QVideoFrame::PixelFormat> supportedPixelFormats(QAbstractVideoBuffer::HandleType type = QAbstractVideoBuffer::NoHandle) const override;
private:
QList<CameraManager*> CamList;
QList<CameraManager*> 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

View File

@ -18,6 +18,8 @@
#include <stdio.h>
#include <QFileDialog>
#include <QPaintEvent>
#include <QPainter>
#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<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()
@ -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);
}

View File

@ -22,9 +22,36 @@
#include <QDialog>
#include <QButtonGroup>
#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

View File

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

View File

@ -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}
};

View File

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

View File

@ -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);
}
}