begin work on the CameraManager

This commit is contained in:
Arisotura 2022-04-29 12:07:11 +02:00 committed by Nadia Holmquist Pedersen
parent 16d0b05fb5
commit 7d453effb2
7 changed files with 227 additions and 91 deletions

View File

@ -20,6 +20,7 @@
#include <string.h>
#include "DSi.h"
#include "DSi_Camera.h"
#include "Platform.h"
namespace DSi_CamModule
@ -33,10 +34,6 @@ u16 Cnt;
u32 CropStart, CropEnd;
/*u8 FrameBuffer[640*480*4];
u32 FrameLength;
u32 TransferPos;*/
// pixel data buffer holds a maximum of 512 words, regardless of how long scanlines are
u32 DataBuffer[512];
u32 BufferReadPos, BufferWritePos;
@ -77,9 +74,6 @@ void Reset()
CropStart = 0;
CropEnd = 0;
/*memset(FrameBuffer, 0, 640*480*4);
TransferPos = 0;
FrameLength = 256*192*2;*/ // TODO: make it check frame size, data type, etc
memset(DataBuffer, 0, 512*sizeof(u32));
BufferReadPos = 0;
BufferWritePos = 0;
@ -495,6 +489,8 @@ void Camera::StartTransfer()
FrameReadMode = 0;
FrameFormat = 0;
}
Platform::Camera_CaptureFrame(Num, FrameBuffer, 640, 480, true);
}
bool Camera::TransferDone()
@ -687,18 +683,30 @@ void Camera::I2C_WriteReg(u16 addr, u16 val)
return;
case 0x0016:
ClocksCnt = val;
printf("ClocksCnt=%04X\n", val);
//printf("ClocksCnt=%04X\n", val);
return;
case 0x0018:
// TODO: this shouldn't be instant, but uh
val &= 0x003F;
val |= ((val & 0x0001) << 14);
StandbyCnt = val;
printf("CAM%d STBCNT=%04X (%04X)\n", Num, StandbyCnt, val);
{
bool wasactive = IsActivated();
// TODO: this shouldn't be instant, but uh
val &= 0x003F;
val |= ((val & 0x0001) << 14);
StandbyCnt = val;
//printf("CAM%d STBCNT=%04X (%04X)\n", Num, StandbyCnt, val);
bool isactive = IsActivated();
if (isactive && !wasactive) Platform::Camera_Start(Num);
else if (wasactive && !isactive) Platform::Camera_Stop(Num);
}
return;
case 0x001A:
MiscCnt = val & 0x0B7B;
printf("CAM%d MISCCNT=%04X (%04X)\n", Num, MiscCnt, val);
{
bool wasactive = IsActivated();
MiscCnt = val & 0x0B7B;
//printf("CAM%d MISCCNT=%04X (%04X)\n", Num, MiscCnt, val);
bool isactive = IsActivated();
if (isactive && !wasactive) Platform::Camera_Start(Num);
else if (wasactive && !isactive) Platform::Camera_Stop(Num);
}
return;
case 0x098C:

View File

@ -144,6 +144,8 @@ void Mutex_Lock(Mutex* mutex);
void Mutex_Unlock(Mutex* mutex);
bool Mutex_TryLock(Mutex* mutex);
void Sleep(u64 usecs);
// functions called when the NDS or GBA save files need to be written back to storage
// savedata and savelen are always the entire save memory buffer and its full length
@ -166,7 +168,15 @@ void LAN_DeInit();
int LAN_SendPacket(u8* data, int len);
int LAN_RecvPacket(u8* data);
void Sleep(u64 usecs);
// interface for camera emulation
// camera numbers:
// 0 = DSi outer camera
// 1 = DSi inner camera
// other values reserved for future camera addon emulation
void Camera_Start(int num);
void Camera_Stop(int num);
void Camera_CaptureFrame(int num, u32* frame, int width, int height, bool yuv);
}

View File

@ -15,3 +15,123 @@
You should have received a copy of the GNU General Public License along
with melonDS. If not, see http://www.gnu.org/licenses/.
*/
#include "CameraManager.h"
CameraFrameDumper::CameraFrameDumper(QObject* parent) : QAbstractVideoSurface(parent)
{
}
bool CameraFrameDumper::present(const QVideoFrame& _frame)
{
QVideoFrame frame(_frame);
if (!frame.map(QAbstractVideoBuffer::ReadOnly))
return false;
printf("FRAMEZORZ!! %d %d %d\n", frame.pixelFormat(), frame.isMapped(), frame.isReadable());
//NDS::CamInputFrame(0, (u32*)frame.bits(), frame.width(), frame.height(), false);
frame.unmap();
return true;
}
QList<QVideoFrame::PixelFormat> CameraFrameDumper::supportedPixelFormats(QAbstractVideoBuffer::HandleType type) const
{
QList<QVideoFrame::PixelFormat> ret;
ret.append(QVideoFrame::Format_RGB32);
ret.append(QVideoFrame::Format_YUYV);
return ret;
}
CameraManager::CameraManager(int num, int width, int height, bool yuv)
{
Num = num;
FrameWidth = width;
FrameHeight = height;
FrameFormatYUV = yuv;
int fbsize = FrameWidth * FrameHeight;
if (yuv) fbsize /= 2;
FrameBuffer = new u32[fbsize];
InputType = -1;
Init();
}
CameraManager::~CameraManager()
{
DeInit();
// save settings here?
delete[] FrameBuffer;
}
void CameraManager::Init()
{
if (InputType != -1)
DeInit();
// TODO: load settings from config!!
InputType = 0;
{
// fill the framebuffer with black
int total = FrameWidth * FrameHeight;
u32 fill = 0;
if (FrameFormatYUV)
{
total /= 2;
fill = 0x80008000;
}
for (int i = 0; i < total; i++)
FrameBuffer[i] = fill;
}
if (InputType == 1)
{
// still image
//
}
}
void CameraManager::DeInit()
{
InputType = -1;
}
void CameraManager::Start()
{
//
}
void CameraManager::Stop()
{
//
}
void CameraManager::CaptureFrame(u32* frame, int width, int height, bool yuv)
{
FrameMutex.lock();
if (width == FrameWidth && height == FrameHeight && yuv == FrameFormatYUV)
{
int len = width * height;
if (yuv) len /= 2;
memcpy(frame, FrameBuffer, len * sizeof(u32));
}
else
{
//
}
FrameMutex.unlock();
}

View File

@ -22,5 +22,47 @@
#include <QCamera>
#include <QCameraInfo>
#include <QAbstractVideoSurface>
#include <QVideoSurfaceFormat>
#include <QMutex>
#include "types.h"
class CameraFrameDumper : public QAbstractVideoSurface
{
Q_OBJECT
public:
CameraFrameDumper(QObject* parent = nullptr);
bool present(const QVideoFrame& frame) override;
QList<QVideoFrame::PixelFormat> supportedPixelFormats(QAbstractVideoBuffer::HandleType type = QAbstractVideoBuffer::NoHandle) const override;
};
class CameraManager
{
public:
CameraManager(int num, int width, int height, bool yuv);
~CameraManager();
void Init();
void DeInit();
void Start();
void Stop();
void CaptureFrame(u32* frame, int width, int height, bool yuv);
private:
int Num;
int InputType;
QString ImagePath;
QString CamDeviceName;
int FrameWidth, FrameHeight;
bool FrameFormatYUV;
u32* FrameBuffer;
QMutex FrameMutex;
};
#endif // CAMERAMANAGER_H

View File

@ -53,6 +53,7 @@
#include "Platform.h"
#include "Config.h"
#include "ROMManager.h"
#include "CameraManager.h"
#include "LAN_Socket.h"
#include "LAN_PCap.h"
#include <string>
@ -66,6 +67,8 @@ std::string EmuDirectory;
void emuStop();
extern CameraManager* camManager[2];
namespace Platform
{
@ -372,6 +375,11 @@ bool Mutex_TryLock(Mutex* mutex)
return ((QMutex*) mutex)->try_lock();
}
void Sleep(u64 usecs)
{
QThread::usleep(usecs);
}
void WriteNDSSave(const u8* savedata, u32 savelen, u32 writeoffset, u32 writelen)
{
@ -529,7 +537,6 @@ int MP_RecvPacket(u8* data, bool block)
}
bool LAN_Init()
{
if (Config::DirectLAN)
@ -573,9 +580,20 @@ int LAN_RecvPacket(u8* data)
return LAN_Socket::RecvPacket(data);
}
void Sleep(u64 usecs)
void Camera_Start(int num)
{
QThread::usleep(usecs);
return camManager[num]->Start();
}
void Camera_Stop(int num)
{
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);
}
}

View File

@ -86,6 +86,7 @@
#include "ROMManager.h"
#include "ArchiveUtil.h"
#include "CameraManager.h"
// TODO: uniform variable spelling
@ -112,6 +113,8 @@ u32 micExtBufferWritePos;
u32 micWavLength;
s16* micWavBuffer;
CameraManager* camManager[2];
const struct { int id; float ratio; const char* label; } aspectRatios[] =
{
{ 0, 1, "4:3 (native)" },
@ -325,57 +328,6 @@ void micProcess()
}
void camOpen()
{
//
}
void camClose()
{
//
}
void camProcess()
{
//
}
CameraFrameDumper::CameraFrameDumper(QObject* parent) : QAbstractVideoSurface(parent)
{
printf("BAKA!!\n");
}
/*CameraFrameDumper::~CameraFrameDumper()
{
printf("SAYONARA\n");
}*/
bool CameraFrameDumper::present(const QVideoFrame& _frame)
{
//printf("FRAMEZORZ!! %d %d %d\n", frame.pixelFormat(), frame.isMapped(), frame.isReadable());
QVideoFrame frame(_frame);
if (!frame.map(QAbstractVideoBuffer::ReadOnly))
return false;
printf("FRAMEZORZ!! %d %d %d\n", frame.pixelFormat(), frame.isMapped(), frame.isReadable());
NDS::CamInputFrame(0, (u32*)frame.bits(), frame.width(), frame.height(), false);
frame.unmap();
return true;
}
QList<QVideoFrame::PixelFormat> CameraFrameDumper::supportedPixelFormats(QAbstractVideoBuffer::HandleType type) const
{
QList<QVideoFrame::PixelFormat> ret;
printf("PENIS. %d\n", type);
ret.append(QVideoFrame::Format_RGB32);
ret.append(QVideoFrame::Format_YUYV);
return ret;
}
EmuThread::EmuThread(QObject* parent) : QThread(parent)
{
EmuStatus = 0;
@ -436,7 +388,7 @@ void EmuThread::deinitOpenGL()
delete oglContext;
delete oglSurface;
}
#include <QVideoSurfaceFormat>
void EmuThread::run()
{
bool hasOGL = mainWindow->hasOGL;
@ -604,9 +556,6 @@ printf("PROULON\n");
OSD::AddMessage(0, lid ? "Lid closed" : "Lid opened");
}
// camera input test
//NDS::CamInputFrame(0, (u32*)testimg_conv.bits(), testimg_conv.width(), testimg_conv.height(), true);
// microphone input
micProcess();
@ -3257,11 +3206,13 @@ int main(int argc, char** argv)
micDevice = 0;
memset(micExtBuffer, 0, sizeof(micExtBuffer));
micExtBufferWritePos = 0;
micWavBuffer = nullptr;
camManager[0] = new CameraManager(0, 640, 480, true);
camManager[1] = new CameraManager(1, 640, 480, true);
ROMManager::EnableCheats(Config::EnableCheats != 0);
Frontend::Init_Audio(audioFreq);
@ -3312,6 +3263,9 @@ int main(int argc, char** argv)
if (micWavBuffer) delete[] micWavBuffer;
delete camManager[0];
delete camManager[1];
Config::Save();
SDL_Quit();

View File

@ -36,24 +36,8 @@
#include <QOpenGLFunctions_3_2_Core>
#include <QOpenGLShaderProgram>
#include <QCamera>
#include <QCameraInfo>
#include <QAbstractVideoSurface>
#include "FrontendUtil.h"
class CameraFrameDumper : public QAbstractVideoSurface
{
Q_OBJECT
public:
CameraFrameDumper(QObject* parent = nullptr);
//~CameraFrameDumper();
bool present(const QVideoFrame& frame) override;
QList<QVideoFrame::PixelFormat> supportedPixelFormats(QAbstractVideoBuffer::HandleType type = QAbstractVideoBuffer::NoHandle) const override;
};
class EmuThread : public QThread
{
Q_OBJECT