mirror of
https://github.com/cemu-project/Cemu.git
synced 2025-07-07 07:21:18 +12:00
Use an OSThread
for handling the callback
This commit is contained in:
parent
cd3dc74548
commit
154eacd85c
1 changed files with 50 additions and 52 deletions
|
@ -3,13 +3,13 @@
|
||||||
#include "camera.h"
|
#include "camera.h"
|
||||||
|
|
||||||
#include "Cafe/OS/RPL/rpl.h"
|
#include "Cafe/OS/RPL/rpl.h"
|
||||||
#include "Cafe/OS/libs/coreinit/coreinit_Alarm.h"
|
|
||||||
#include "Cafe/OS/libs/coreinit/coreinit_Time.h"
|
|
||||||
#include "Cafe/HW/Espresso/PPCCallback.h"
|
#include "Cafe/HW/Espresso/PPCCallback.h"
|
||||||
#include "util/helpers/helpers.h"
|
#include "util/helpers/helpers.h"
|
||||||
|
|
||||||
#include "util/helpers/ringbuffer.h"
|
#include "util/helpers/ringbuffer.h"
|
||||||
#include "camera/CameraManager.h"
|
#include "camera/CameraManager.h"
|
||||||
|
#include "Cafe/HW/Espresso/Const.h"
|
||||||
|
|
||||||
namespace camera
|
namespace camera
|
||||||
{
|
{
|
||||||
constexpr unsigned CAMERA_WIDTH = 640;
|
constexpr unsigned CAMERA_WIDTH = 640;
|
||||||
|
@ -103,59 +103,58 @@ namespace camera
|
||||||
bool initialized = false;
|
bool initialized = false;
|
||||||
bool shouldTriggerCallback = false;
|
bool shouldTriggerCallback = false;
|
||||||
std::atomic_bool isOpen = false;
|
std::atomic_bool isOpen = false;
|
||||||
|
std::atomic_bool isExiting = false;
|
||||||
|
bool isWorking = false;
|
||||||
|
unsigned fps = 30;
|
||||||
MEMPTR<void> eventCallback = nullptr;
|
MEMPTR<void> eventCallback = nullptr;
|
||||||
RingBuffer<MEMPTR<uint8_t>, 20> inTargetBuffers{};
|
RingBuffer<MEMPTR<uint8_t>, 20> inTargetBuffers{};
|
||||||
RingBuffer<MEMPTR<uint8_t>, 20> outTargetBuffers{};
|
RingBuffer<MEMPTR<uint8_t>, 20> outTargetBuffers{};
|
||||||
std::thread updateThread;
|
|
||||||
} s_instance;
|
} s_instance;
|
||||||
|
|
||||||
SysAllocator<CAMDecodeEventParam> s_cameraEventData;
|
SysAllocator<CAMDecodeEventParam> s_cameraEventData;
|
||||||
SysAllocator<coreinit::OSAlarm_t> s_cameraAlarm;
|
SysAllocator<OSThread_t> s_cameraWorkerThread;
|
||||||
|
SysAllocator<uint8, 1024 * 64> s_cameraWorkerThreadStack;
|
||||||
|
SysAllocator<coreinit::OSEvent> s_cameraOpenEvent;
|
||||||
|
|
||||||
void UpdateLoop()
|
void WorkerThread(PPCInterpreter_t*)
|
||||||
{
|
|
||||||
while (s_instance.isOpen)
|
|
||||||
{
|
|
||||||
{
|
|
||||||
std::scoped_lock lock(s_instance.mutex);
|
|
||||||
auto surfaceBuffer = s_instance.inTargetBuffers.Pop();
|
|
||||||
if (surfaceBuffer.IsNull())
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
CameraManager::instance().GetNV12Data(surfaceBuffer.GetPtr());
|
|
||||||
s_instance.outTargetBuffers.Push(surfaceBuffer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void AlarmCallback(PPCInterpreter_t*)
|
|
||||||
{
|
{
|
||||||
s_cameraEventData->type = CAMEventType::Decode;
|
s_cameraEventData->type = CAMEventType::Decode;
|
||||||
s_cameraEventData->channel = 0;
|
s_cameraEventData->channel = 0;
|
||||||
|
s_cameraEventData->data = nullptr;
|
||||||
|
s_cameraEventData->errored = false;
|
||||||
|
PPCCoreCallback(s_instance.eventCallback, s_cameraEventData.GetMPTR());
|
||||||
|
|
||||||
if (s_instance.shouldTriggerCallback)
|
while (!s_instance.isExiting)
|
||||||
{
|
{
|
||||||
s_instance.shouldTriggerCallback = false;
|
coreinit::OSWaitEvent(s_cameraOpenEvent);
|
||||||
s_cameraEventData->data = nullptr;
|
while (true)
|
||||||
s_cameraEventData->errored = false;
|
|
||||||
}
|
|
||||||
else if (s_instance.isOpen)
|
|
||||||
{
|
|
||||||
if (auto buffer = s_instance.outTargetBuffers.Pop())
|
|
||||||
{
|
{
|
||||||
s_cameraEventData->data = buffer;
|
if (!s_instance.isOpen || s_instance.isExiting)
|
||||||
s_cameraEventData->errored = false;
|
{
|
||||||
|
// Fill leftover buffers before stopping
|
||||||
|
if (!s_instance.inTargetBuffers.HasData())
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
s_cameraEventData->type = CAMEventType::Decode;
|
||||||
|
s_cameraEventData->channel = 0;
|
||||||
|
|
||||||
|
auto surfaceBuffer = s_instance.inTargetBuffers.Pop();
|
||||||
|
if (surfaceBuffer.IsNull())
|
||||||
|
{
|
||||||
|
s_cameraEventData->data = nullptr;
|
||||||
|
s_cameraEventData->errored = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CameraManager::instance().GetNV12Data(surfaceBuffer.GetPtr());
|
||||||
|
s_cameraEventData->data = surfaceBuffer;
|
||||||
|
s_cameraEventData->errored = false;
|
||||||
|
}
|
||||||
PPCCoreCallback(s_instance.eventCallback, s_cameraEventData.GetMPTR());
|
PPCCoreCallback(s_instance.eventCallback, s_cameraEventData.GetMPTR());
|
||||||
}
|
coreinit::OSSleepTicks(Espresso::TIMER_CLOCK / (s_instance.fps - 1));
|
||||||
else
|
|
||||||
{
|
|
||||||
s_cameraEventData->data = nullptr;
|
|
||||||
s_cameraEventData->errored = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
cemuLog_logDebug(LogType::Force, "Camera Worker Thread Exited");
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sint32 CAMGetMemReq(CAMImageInfo*)
|
sint32 CAMGetMemReq(CAMImageInfo*)
|
||||||
|
@ -179,7 +178,7 @@ namespace camera
|
||||||
*error = CAMStatus::DeviceInUse;
|
*error = CAMStatus::DeviceInUse;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!initInfo || !initInfo->workMemoryData ||
|
if (!initInfo || !initInfo->workMemoryData ||
|
||||||
!match_any_of(initInfo->forceDisplay, CAMForceDisplay::None, CAMForceDisplay::DRC) ||
|
!match_any_of(initInfo->forceDisplay, CAMForceDisplay::None, CAMForceDisplay::DRC) ||
|
||||||
!match_any_of(initInfo->fps, CAMFps::_15, CAMFps::_30) ||
|
!match_any_of(initInfo->fps, CAMFps::_15, CAMFps::_30) ||
|
||||||
|
@ -193,15 +192,15 @@ namespace camera
|
||||||
cemu_assert_debug(initInfo->workMemorySize != 0);
|
cemu_assert_debug(initInfo->workMemorySize != 0);
|
||||||
cemu_assert_debug(initInfo->imageInfo.type == CAMImageType::Default);
|
cemu_assert_debug(initInfo->imageInfo.type == CAMImageType::Default);
|
||||||
|
|
||||||
auto frameRate = initInfo->fps == CAMFps::_15 ? 15 : 30;
|
s_instance.fps = initInfo->fps == CAMFps::_15 ? 15 : 30;
|
||||||
s_instance.initialized = true;
|
s_instance.initialized = true;
|
||||||
s_instance.shouldTriggerCallback = true;
|
|
||||||
s_instance.eventCallback = initInfo->callback;
|
s_instance.eventCallback = initInfo->callback;
|
||||||
coreinit::OSCreateAlarm(s_cameraAlarm.GetPtr());
|
coreinit::OSInitEvent(s_cameraOpenEvent, coreinit::OSEvent::EVENT_STATE::STATE_NOT_SIGNALED, coreinit::OSEvent::EVENT_MODE::MODE_AUTO);
|
||||||
coreinit::OSSetPeriodicAlarm(s_cameraAlarm.GetPtr(),
|
coreinit::__OSCreateThreadType(
|
||||||
coreinit::OSGetTime(),
|
s_cameraWorkerThread, RPLLoader_MakePPCCallable(WorkerThread), 0, nullptr,
|
||||||
coreinit::EspressoTime::GetTimerClock() / frameRate,
|
s_cameraWorkerThreadStack.GetPtr() + s_cameraWorkerThreadStack.GetByteSize(), s_cameraWorkerThreadStack.GetByteSize(),
|
||||||
RPLLoader_MakePPCCallable(AlarmCallback));
|
0x10, initInfo->threadFlags & 7, OSThread_t::THREAD_TYPE::TYPE_DRIVER);
|
||||||
|
coreinit::OSResumeThread(s_cameraWorkerThread);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,7 +214,6 @@ namespace camera
|
||||||
return CAMStatus::Uninitialized;
|
return CAMStatus::Uninitialized;
|
||||||
s_instance.isOpen = false;
|
s_instance.isOpen = false;
|
||||||
}
|
}
|
||||||
s_instance.updateThread.join();
|
|
||||||
CameraManager::instance().Close();
|
CameraManager::instance().Close();
|
||||||
return CAMStatus::Success;
|
return CAMStatus::Success;
|
||||||
}
|
}
|
||||||
|
@ -231,10 +229,10 @@ namespace camera
|
||||||
return CAMStatus::DeviceInUse;
|
return CAMStatus::DeviceInUse;
|
||||||
if (!CameraManager::instance().Open(false))
|
if (!CameraManager::instance().Open(false))
|
||||||
return CAMStatus::UVCError;
|
return CAMStatus::UVCError;
|
||||||
|
s_instance.isOpen = true;
|
||||||
|
coreinit::OSSignalEvent(s_cameraOpenEvent);
|
||||||
s_instance.inTargetBuffers.Clear();
|
s_instance.inTargetBuffers.Clear();
|
||||||
s_instance.outTargetBuffers.Clear();
|
s_instance.outTargetBuffers.Clear();
|
||||||
s_instance.isOpen = true;
|
|
||||||
s_instance.updateThread = std::thread(UpdateLoop);
|
|
||||||
return CAMStatus::Success;
|
return CAMStatus::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -259,11 +257,11 @@ namespace camera
|
||||||
std::scoped_lock lock(s_instance.mutex);
|
std::scoped_lock lock(s_instance.mutex);
|
||||||
if (!s_instance.initialized)
|
if (!s_instance.initialized)
|
||||||
return;
|
return;
|
||||||
|
s_instance.isExiting = true;
|
||||||
if (s_instance.isOpen)
|
if (s_instance.isOpen)
|
||||||
CAMClose(camHandle);
|
CAMClose(camHandle);
|
||||||
|
coreinit::OSSignalEvent(s_cameraOpenEvent.GetPtr());
|
||||||
s_instance.initialized = false;
|
s_instance.initialized = false;
|
||||||
s_instance.shouldTriggerCallback = false;
|
|
||||||
coreinit::OSCancelAlarm(s_cameraAlarm);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void reset()
|
void reset()
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue