mirror of
https://github.com/cemu-project/Cemu.git
synced 2026-04-21 07:41:27 -06:00
Init CameraManager on open, deinit on close
And buffer allocation and deallocation occur on init and deinit
This commit is contained in:
parent
6ee1e1e3e4
commit
aa3c852560
@ -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);
|
||||
|
||||
@ -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()
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user