diff --git a/cameraserver/src/main/native/cpp/cameraserver/CameraServer.cpp b/cameraserver/src/main/native/cpp/cameraserver/CameraServer.cpp index 2a839f1b07..cdd3ba9bad 100644 --- a/cameraserver/src/main/native/cpp/cameraserver/CameraServer.cpp +++ b/cameraserver/src/main/native/cpp/cameraserver/CameraServer.cpp @@ -7,8 +7,15 @@ #include "cameraserver/CameraServer.h" +#include +#include + +#include #include +#include #include +#include +#include #include #include "cameraserver/CameraServerShared.h" @@ -16,6 +23,28 @@ using namespace frc; +static constexpr char const* kPublishName = "/CameraPublisher"; + +struct CameraServer::Impl { + Impl(); + std::shared_ptr GetSourceTable(CS_Source source); + std::vector GetSinkStreamValues(CS_Sink sink); + std::vector GetSourceStreamValues(CS_Source source); + void UpdateStreamValues(); + + wpi::mutex m_mutex; + std::atomic m_defaultUsbDevice; + std::string m_primarySourceName; + wpi::StringMap m_sources; + wpi::StringMap m_sinks; + wpi::DenseMap> m_tables; + std::shared_ptr m_publishTable; + cs::VideoListener m_videoListener; + int m_tableListener; + int m_nextPort; + std::vector m_addresses; +}; + CameraServer* CameraServer::GetInstance() { static CameraServer instance; return &instance; @@ -61,13 +90,13 @@ static std::string MakeStreamValue(wpi::StringRef address, int port) { return rv; } -std::shared_ptr CameraServer::GetSourceTable( +std::shared_ptr CameraServer::Impl::GetSourceTable( CS_Source source) { std::lock_guard lock(m_mutex); return m_tables.lookup(source); } -std::vector CameraServer::GetSinkStreamValues(CS_Sink sink) { +std::vector CameraServer::Impl::GetSinkStreamValues(CS_Sink sink) { CS_Status status = 0; // Ignore all but MjpegServer @@ -96,7 +125,8 @@ std::vector CameraServer::GetSinkStreamValues(CS_Sink sink) { return values; } -std::vector CameraServer::GetSourceStreamValues(CS_Source source) { +std::vector CameraServer::Impl::GetSourceStreamValues( + CS_Source source) { CS_Status status = 0; // Ignore all but HttpCamera @@ -124,7 +154,7 @@ std::vector CameraServer::GetSourceStreamValues(CS_Source source) { return values; } -void CameraServer::UpdateStreamValues() { +void CameraServer::Impl::UpdateStreamValues() { std::lock_guard lock(m_mutex); // Over all the sinks... for (const auto& i : m_sinks) { @@ -254,7 +284,7 @@ static void PutSourcePropertyValue(nt::NetworkTable* table, } } -CameraServer::CameraServer() +CameraServer::Impl::Impl() : m_publishTable{nt::NetworkTableInstance::GetDefault().GetTable( kPublishName)}, m_nextPort(kBasePort) { @@ -432,9 +462,14 @@ CameraServer::CameraServer() }, NT_NOTIFY_IMMEDIATE | NT_NOTIFY_UPDATE); } + +CameraServer::CameraServer() : m_impl(new Impl) {} + +CameraServer::~CameraServer() {} + #ifdef __linux__ cs::UsbCamera CameraServer::StartAutomaticCapture() { - cs::UsbCamera camera = StartAutomaticCapture(m_defaultUsbDevice++); + cs::UsbCamera camera = StartAutomaticCapture(m_impl->m_defaultUsbDevice++); auto csShared = GetCameraServerShared(); csShared->ReportUsbCamera(camera.GetHandle()); return camera; @@ -536,13 +571,13 @@ cs::CvSink CameraServer::GetVideo() { cs::VideoSource source; { auto csShared = GetCameraServerShared(); - std::lock_guard lock(m_mutex); - if (m_primarySourceName.empty()) { + std::lock_guard lock(m_impl->m_mutex); + if (m_impl->m_primarySourceName.empty()) { csShared->SetCameraServerError("no camera available"); return cs::CvSink{}; } - auto it = m_sources.find(m_primarySourceName); - if (it == m_sources.end()) { + auto it = m_impl->m_sources.find(m_impl->m_primarySourceName); + if (it == m_impl->m_sources.end()) { csShared->SetCameraServerError("no camera available"); return cs::CvSink{}; } @@ -556,9 +591,9 @@ cs::CvSink CameraServer::GetVideo(const cs::VideoSource& camera) { name += camera.GetName(); { - std::lock_guard lock(m_mutex); - auto it = m_sinks.find(name); - if (it != m_sinks.end()) { + std::lock_guard lock(m_impl->m_mutex); + auto it = m_impl->m_sinks.find(name); + if (it != m_impl->m_sinks.end()) { auto kind = it->second.GetKind(); if (kind != cs::VideoSink::kCv) { wpi::SmallString<64> buf; @@ -581,9 +616,9 @@ cs::CvSink CameraServer::GetVideo(const cs::VideoSource& camera) { cs::CvSink CameraServer::GetVideo(wpi::StringRef name) { cs::VideoSource source; { - std::lock_guard lock(m_mutex); - auto it = m_sources.find(name); - if (it == m_sources.end()) { + std::lock_guard lock(m_impl->m_mutex); + auto it = m_impl->m_sources.find(name); + if (it == m_impl->m_sources.end()) { wpi::SmallString<64> buf; wpi::raw_svector_ostream err{buf}; err << "could not find camera " << name; @@ -606,8 +641,8 @@ cs::CvSource CameraServer::PutVideo(wpi::StringRef name, int width, cs::MjpegServer CameraServer::AddServer(wpi::StringRef name) { int port; { - std::lock_guard lock(m_mutex); - port = m_nextPort++; + std::lock_guard lock(m_impl->m_mutex); + port = m_impl->m_nextPort++; } return AddServer(name, port); } @@ -619,34 +654,34 @@ cs::MjpegServer CameraServer::AddServer(wpi::StringRef name, int port) { } void CameraServer::AddServer(const cs::VideoSink& server) { - std::lock_guard lock(m_mutex); - m_sinks.try_emplace(server.GetName(), server); + std::lock_guard lock(m_impl->m_mutex); + m_impl->m_sinks.try_emplace(server.GetName(), server); } void CameraServer::RemoveServer(wpi::StringRef name) { - std::lock_guard lock(m_mutex); - m_sinks.erase(name); + std::lock_guard lock(m_impl->m_mutex); + m_impl->m_sinks.erase(name); } cs::VideoSink CameraServer::GetServer() { wpi::SmallString<64> name; { - std::lock_guard lock(m_mutex); - if (m_primarySourceName.empty()) { + std::lock_guard lock(m_impl->m_mutex); + if (m_impl->m_primarySourceName.empty()) { auto csShared = GetCameraServerShared(); csShared->SetCameraServerError("no camera available"); return cs::VideoSink{}; } name = "serve_"; - name += m_primarySourceName; + name += m_impl->m_primarySourceName; } return GetServer(name); } cs::VideoSink CameraServer::GetServer(wpi::StringRef name) { - std::lock_guard lock(m_mutex); - auto it = m_sinks.find(name); - if (it == m_sinks.end()) { + std::lock_guard lock(m_impl->m_mutex); + auto it = m_impl->m_sinks.find(name); + if (it == m_impl->m_sinks.end()) { wpi::SmallString<64> buf; wpi::raw_svector_ostream err{buf}; err << "could not find server " << name; @@ -659,21 +694,21 @@ cs::VideoSink CameraServer::GetServer(wpi::StringRef name) { void CameraServer::AddCamera(const cs::VideoSource& camera) { std::string name = camera.GetName(); - std::lock_guard lock(m_mutex); - if (m_primarySourceName.empty()) m_primarySourceName = name; - m_sources.try_emplace(name, camera); + std::lock_guard lock(m_impl->m_mutex); + if (m_impl->m_primarySourceName.empty()) m_impl->m_primarySourceName = name; + m_impl->m_sources.try_emplace(name, camera); } void CameraServer::RemoveCamera(wpi::StringRef name) { - std::lock_guard lock(m_mutex); - m_sources.erase(name); + std::lock_guard lock(m_impl->m_mutex); + m_impl->m_sources.erase(name); } void CameraServer::SetSize(int size) { - std::lock_guard lock(m_mutex); - if (m_primarySourceName.empty()) return; - auto it = m_sources.find(m_primarySourceName); - if (it == m_sources.end()) return; + std::lock_guard lock(m_impl->m_mutex); + if (m_impl->m_primarySourceName.empty()) return; + auto it = m_impl->m_sources.find(m_impl->m_primarySourceName); + if (it == m_impl->m_sources.end()) return; if (size == kSize160x120) it->second.SetResolution(160, 120); else if (size == kSize320x240) diff --git a/cameraserver/src/main/native/include/cameraserver/CameraServer.h b/cameraserver/src/main/native/include/cameraserver/CameraServer.h index 6f842f5da1..82ef061e7f 100644 --- a/cameraserver/src/main/native/include/cameraserver/CameraServer.h +++ b/cameraserver/src/main/native/include/cameraserver/CameraServer.h @@ -9,16 +9,11 @@ #include -#include #include #include -#include -#include -#include -#include +#include #include -#include #include "cscore.h" @@ -285,25 +280,10 @@ class CameraServer { private: CameraServer(); + ~CameraServer(); - std::shared_ptr GetSourceTable(CS_Source source); - std::vector GetSinkStreamValues(CS_Sink sink); - std::vector GetSourceStreamValues(CS_Source source); - void UpdateStreamValues(); - - static constexpr char const* kPublishName = "/CameraPublisher"; - - wpi::mutex m_mutex; - std::atomic m_defaultUsbDevice; - std::string m_primarySourceName; - wpi::StringMap m_sources; - wpi::StringMap m_sinks; - wpi::DenseMap> m_tables; - std::shared_ptr m_publishTable; - cs::VideoListener m_videoListener; - int m_tableListener; - int m_nextPort; - std::vector m_addresses; + struct Impl; + std::unique_ptr m_impl; }; } // namespace frc