Init CameraManager on open, deinit on close

And buffer allocation and deallocation occur on init and deinit
This commit is contained in:
capitalistspz 2026-04-15 00:56:54 +01:00
parent 6ee1e1e3e4
commit aa3c852560
4 changed files with 59 additions and 54 deletions

View File

@ -190,7 +190,6 @@ namespace camera
*error = CAM_STATUS_INVALID_ARG;
return -1;
}
CameraManager::Init();
cemu_assert_debug(initInfo->forceDisplay != CAMForceDisplay::DRC);
cemu_assert_debug(initInfo->workMemorySize != 0);

View File

@ -17,8 +17,8 @@ namespace CameraManager
CapContext s_ctx;
std::optional<CapDeviceID> s_device;
std::optional<CapStream> s_stream;
std::array<uint8, CAMERA_RGB_BUFFER_SIZE> s_rgbBuffer;
std::array<uint8, CAMERA_NV12_BUFFER_SIZE> s_nv12Buffer;
uint8_t* s_rgbBuffer;
uint8_t* s_nv12Buffer;
int s_refCount = 0;
std::thread s_captureThread;
std::atomic_bool s_capturing = false;
@ -71,8 +71,8 @@ namespace CameraManager
{
s_mutex.lock();
if (s_stream && Cap_hasNewFrame(s_ctx, *s_stream) &&
Cap_captureFrame(s_ctx, *s_stream, s_rgbBuffer.data(), s_rgbBuffer.size()) == CAPRESULT_OK)
Rgb2Nv12(s_rgbBuffer.data(), CAMERA_WIDTH, CAMERA_HEIGHT, s_nv12Buffer.data(), CAMERA_PITCH);
Cap_captureFrame(s_ctx, *s_stream, s_rgbBuffer, CAMERA_RGB_BUFFER_SIZE) == CAPRESULT_OK)
Rgb2Nv12(s_rgbBuffer, CAMERA_WIDTH, CAMERA_HEIGHT, s_nv12Buffer, CAMERA_PITCH);
s_mutex.unlock();
std::this_thread::sleep_for(std::chrono::milliseconds(30));
}
@ -105,30 +105,49 @@ namespace CameraManager
void ResetBuffers()
{
std::ranges::fill(s_rgbBuffer, 0);
constexpr auto pixCount = CAMERA_HEIGHT * CAMERA_PITCH;
std::ranges::fill_n(s_nv12Buffer.begin(), pixCount, 16);
std::ranges::fill_n(s_nv12Buffer.begin() + pixCount, (pixCount / 2), 128);
std::fill_n(s_rgbBuffer, CAMERA_RGB_BUFFER_SIZE, 0);
constexpr static auto PIXEL_COUNT = CAMERA_HEIGHT * CAMERA_PITCH;
std::ranges::fill_n(s_nv12Buffer, PIXEL_COUNT, 16);
std::ranges::fill_n(s_nv12Buffer + PIXEL_COUNT, (PIXEL_COUNT / 2), 128);
}
std::vector<DeviceInfo> InternalEnumerateDevices()
{
std::vector<DeviceInfo> infos;
const auto deviceCount = Cap_getDeviceCount(s_ctx);
cemuLog_log(LogType::InputAPI, "Available video capture devices:");
for (CapDeviceID deviceNo = 0; deviceNo < deviceCount; ++deviceNo)
{
const auto uniqueId = Cap_getDeviceUniqueID(s_ctx, deviceNo);
const auto name = Cap_getDeviceName(s_ctx, deviceNo);
DeviceInfo info;
info.uniqueId = uniqueId;
if (name)
info.name = fmt::format("{}: {}", deviceNo, name);
else
info.name = fmt::format("{}: Unknown", deviceNo);
infos.push_back(info);
cemuLog_log(LogType::InputAPI, "{}", info.name);
}
return infos;
}
void Init()
{
{
std::scoped_lock lock(s_mutex);
if (s_running)
return;
s_running = true;
s_ctx = Cap_createContext();
Cap_setLogLevel(4);
Cap_installCustomLogFunction(CaptureLogFunction);
}
s_running = true;
s_ctx = Cap_createContext();
Cap_setLogLevel(4);
Cap_installCustomLogFunction(CaptureLogFunction);
s_rgbBuffer = new uint8[CAMERA_RGB_BUFFER_SIZE];
s_nv12Buffer = new uint8[CAMERA_NV12_BUFFER_SIZE];
s_captureThread = std::thread(&CaptureWorker);
const auto uniqueId = GetConfig().camera_id.GetValue();
if (!uniqueId.empty())
{
const auto devices = EnumerateDevices();
const auto devices = InternalEnumerateDevices();
for (CapDeviceID deviceId = 0; deviceId < devices.size(); ++deviceId)
{
if (devices[deviceId].uniqueId == uniqueId)
@ -147,38 +166,46 @@ namespace CameraManager
Cap_releaseContext(s_ctx);
s_running = false;
s_captureThread.join();
delete[] s_rgbBuffer;
delete[] s_nv12Buffer;
}
void FillNV12Buffer(std::span<uint8, CAMERA_NV12_BUFFER_SIZE> nv12Buffer)
{
std::scoped_lock lock(s_mutex);
std::ranges::copy(s_nv12Buffer, nv12Buffer.data());
std::ranges::copy_n(s_nv12Buffer, CAMERA_NV12_BUFFER_SIZE, nv12Buffer.data());
}
void FillRGBBuffer(std::span<uint8, CAMERA_RGB_BUFFER_SIZE> rgbBuffer)
{
std::scoped_lock lock(s_mutex);
std::ranges::copy(s_rgbBuffer, rgbBuffer.data());
std::ranges::copy_n(s_rgbBuffer, CAMERA_RGB_BUFFER_SIZE, rgbBuffer.data());
}
void SetDevice(uint32 deviceNo)
{
std::scoped_lock lock(s_mutex);
CloseStream();
if (deviceNo == DEVICE_NONE)
{
s_device = std::nullopt;
ResetBuffers();
return;
}
s_device = deviceNo;
if (s_refCount != 0)
OpenStream();
}
void ResetDevice()
{
std::scoped_lock lock(s_mutex);
CloseStream();
s_device = std::nullopt;
ResetBuffers();
}
void Open()
{
std::scoped_lock lock(s_mutex);
if (!s_running)
{
Init();
}
if (s_device && s_refCount == 0)
{
OpenStream();
@ -195,31 +222,13 @@ namespace CameraManager
if (s_refCount != 0)
return;
CloseStream();
Deinit();
}
std::vector<DeviceInfo> EnumerateDevices()
{
std::scoped_lock lock(s_mutex);
std::vector<DeviceInfo> infos;
const auto deviceCount = Cap_getDeviceCount(s_ctx);
cemuLog_log(LogType::InputAPI, "Available video capture devices:");
for (CapDeviceID deviceNo = 0; deviceNo < deviceCount; ++deviceNo)
{
const auto uniqueId = Cap_getDeviceUniqueID(s_ctx, deviceNo);
const auto name = Cap_getDeviceName(s_ctx, deviceNo);
DeviceInfo info;
info.uniqueId = uniqueId;
if (name)
info.name = fmt::format("{}: {}", deviceNo, name);
else
info.name = fmt::format("{}: Unknown", deviceNo);
infos.push_back(info);
cemuLog_log(LogType::InputAPI, "{}", info.name);
}
if (infos.empty())
cemuLog_log(LogType::InputAPI, "No available video capture devices");
return infos;
return InternalEnumerateDevices();
}
void SaveDevice()

View File

@ -18,10 +18,6 @@ namespace CameraManager
std::string name;
};
constexpr static uint32 DEVICE_NONE = std::numeric_limits<uint32>::max();
void Init();
void Deinit();
void Open();
void Close();
@ -29,6 +25,7 @@ namespace CameraManager
void FillRGBBuffer(std::span<uint8, CAMERA_RGB_BUFFER_SIZE> rgbBuffer);
void SetDevice(uint32 deviceNo);
void ResetDevice();
std::vector<DeviceInfo> EnumerateDevices();
void SaveDevice();
std::optional<uint32> GetCurrentDevice();

View File

@ -11,7 +11,6 @@ CameraSettingsWindow::CameraSettingsWindow(wxWindow* parent)
m_imageBitmap(CameraManager::CAMERA_WIDTH, CameraManager::CAMERA_HEIGHT, 24),
m_imageBuffer(CameraManager::CAMERA_RGB_BUFFER_SIZE)
{
CameraManager::Init();
CameraManager::Open();
auto* rootSizer = new wxBoxSizer(wxVERTICAL);
{
@ -51,7 +50,7 @@ void CameraSettingsWindow::OnSelectCameraChoice(wxCommandEvent&)
if (selection < 0)
return;
if (selection == 0)
CameraManager::SetDevice(CameraManager::DEVICE_NONE);
CameraManager::ResetDevice();
else
CameraManager::SetDevice(selection - 1);
}
@ -100,7 +99,8 @@ void CameraSettingsWindow::DrawImage(const wxPaintEvent&)
void CameraSettingsWindow::OnClose(wxCloseEvent& event)
{
CameraManager::Close();
m_imageUpdateTimer.Stop();
CameraManager::SaveDevice();
CameraManager::Close();
event.Skip();
}