mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-26 01:51:41 +00:00
cscore: Add connection strategy to sources (#1252)
By default, sources automatically manage their connection based on whether any sinks are connected. This change allows the user to keep a connection open or force it closed regardless of the number of connected sinks.
This commit is contained in:
@@ -69,13 +69,12 @@ void HttpCameraImpl::StreamThreadMain() {
|
||||
// sleep between retries
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(250));
|
||||
|
||||
// disconnect if no one is listening
|
||||
if (m_numSinksEnabled == 0) {
|
||||
// disconnect if not enabled
|
||||
if (!IsEnabled()) {
|
||||
std::unique_lock<wpi::mutex> lock(m_mutex);
|
||||
if (m_streamConn) m_streamConn->stream->close();
|
||||
// Wait for a sink to enable
|
||||
m_sinkEnabledCond.wait(
|
||||
lock, [=] { return !m_active || m_numSinksEnabled != 0; });
|
||||
// Wait for enable
|
||||
m_sinkEnabledCond.wait(lock, [=] { return !m_active || IsEnabled(); });
|
||||
if (!m_active) return;
|
||||
}
|
||||
|
||||
@@ -185,8 +184,8 @@ void HttpCameraImpl::DeviceStream(wpi::raw_istream& is,
|
||||
int numErrors = 0;
|
||||
|
||||
// streaming loop
|
||||
while (m_active && !is.has_error() && m_numSinksEnabled > 0 &&
|
||||
numErrors < 3 && !m_streamSettingsUpdated) {
|
||||
while (m_active && !is.has_error() && IsEnabled() && numErrors < 3 &&
|
||||
!m_streamSettingsUpdated) {
|
||||
if (!FindMultipartBoundary(is, boundary, nullptr)) break;
|
||||
|
||||
// Read the next two characters after the boundary (normally \r\n)
|
||||
|
||||
@@ -41,6 +41,15 @@ class SourceImpl : public PropertyContainer {
|
||||
void SetDescription(const wpi::Twine& description);
|
||||
wpi::StringRef GetDescription(wpi::SmallVectorImpl<char>& buf) const;
|
||||
|
||||
void SetConnectionStrategy(CS_ConnectionStrategy strategy) {
|
||||
m_strategy = static_cast<int>(strategy);
|
||||
}
|
||||
bool IsEnabled() const {
|
||||
return m_strategy == CS_CONNECTION_KEEP_OPEN ||
|
||||
(m_strategy == CS_CONNECTION_AUTO_MANAGE && m_numSinksEnabled > 0);
|
||||
}
|
||||
|
||||
// User-visible connection status
|
||||
void SetConnected(bool connected);
|
||||
bool IsConnected() const { return m_connected; }
|
||||
|
||||
@@ -130,7 +139,6 @@ class SourceImpl : public PropertyContainer {
|
||||
virtual void NumSinksEnabledChanged() = 0;
|
||||
|
||||
std::atomic_int m_numSinks{0};
|
||||
std::atomic_int m_numSinksEnabled{0};
|
||||
|
||||
protected:
|
||||
// Cached video modes (protected with m_mutex)
|
||||
@@ -146,6 +154,9 @@ class SourceImpl : public PropertyContainer {
|
||||
std::string m_name;
|
||||
std::string m_description;
|
||||
|
||||
std::atomic_int m_strategy{CS_CONNECTION_AUTO_MANAGE};
|
||||
std::atomic_int m_numSinksEnabled{0};
|
||||
|
||||
wpi::mutex m_frameMutex;
|
||||
wpi::condition_variable m_frameCv;
|
||||
|
||||
|
||||
@@ -309,10 +309,10 @@ void UsbCameraImpl::CameraThreadMain() {
|
||||
}
|
||||
}
|
||||
|
||||
// Turn off streaming if no one is listening, and turn it on if there is.
|
||||
if (m_streaming && m_numSinksEnabled == 0) {
|
||||
// Turn off streaming if not enabled, and turn it on if enabled
|
||||
if (m_streaming && !IsEnabled()) {
|
||||
DeviceStreamOff();
|
||||
} else if (!m_streaming && m_numSinksEnabled > 0) {
|
||||
} else if (!m_streaming && IsEnabled()) {
|
||||
DeviceStreamOn();
|
||||
}
|
||||
|
||||
|
||||
@@ -99,10 +99,20 @@ uint64_t CS_GetSourceLastFrameTime(CS_Source source, CS_Status* status) {
|
||||
return cs::GetSourceLastFrameTime(source, status);
|
||||
}
|
||||
|
||||
void CS_SetSourceConnectionStrategy(CS_Source source,
|
||||
CS_ConnectionStrategy strategy,
|
||||
CS_Status* status) {
|
||||
cs::SetSourceConnectionStrategy(source, strategy, status);
|
||||
}
|
||||
|
||||
CS_Bool CS_IsSourceConnected(CS_Source source, CS_Status* status) {
|
||||
return cs::IsSourceConnected(source, status);
|
||||
}
|
||||
|
||||
CS_Bool CS_IsSourceEnabled(CS_Source source, CS_Status* status) {
|
||||
return cs::IsSourceEnabled(source, status);
|
||||
}
|
||||
|
||||
CS_Property CS_GetSourceProperty(CS_Source source, const char* name,
|
||||
CS_Status* status) {
|
||||
return cs::GetSourceProperty(source, name, status);
|
||||
|
||||
@@ -222,6 +222,17 @@ uint64_t GetSourceLastFrameTime(CS_Source source, CS_Status* status) {
|
||||
return data->source->GetCurFrameTime();
|
||||
}
|
||||
|
||||
void SetSourceConnectionStrategy(CS_Source source,
|
||||
CS_ConnectionStrategy strategy,
|
||||
CS_Status* status) {
|
||||
auto data = Sources::GetInstance().Get(source);
|
||||
if (!data) {
|
||||
*status = CS_INVALID_HANDLE;
|
||||
return;
|
||||
}
|
||||
data->source->SetConnectionStrategy(strategy);
|
||||
}
|
||||
|
||||
bool IsSourceConnected(CS_Source source, CS_Status* status) {
|
||||
auto data = Sources::GetInstance().Get(source);
|
||||
if (!data) {
|
||||
@@ -231,6 +242,15 @@ bool IsSourceConnected(CS_Source source, CS_Status* status) {
|
||||
return data->source->IsConnected();
|
||||
}
|
||||
|
||||
bool IsSourceEnabled(CS_Source source, CS_Status* status) {
|
||||
auto data = Sources::GetInstance().Get(source);
|
||||
if (!data) {
|
||||
*status = CS_INVALID_HANDLE;
|
||||
return false;
|
||||
}
|
||||
return data->source->IsEnabled();
|
||||
}
|
||||
|
||||
CS_Property GetSourceProperty(CS_Source source, const wpi::Twine& name,
|
||||
CS_Status* status) {
|
||||
auto data = Sources::GetInstance().Get(source);
|
||||
|
||||
@@ -599,6 +599,21 @@ Java_edu_wpi_cscore_CameraServerJNI_getSourceLastFrameTime
|
||||
return val;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_cscore_CameraServerJNI
|
||||
* Method: setSourceConnectionStrategy
|
||||
* Signature: (II)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_edu_wpi_cscore_CameraServerJNI_setSourceConnectionStrategy
|
||||
(JNIEnv* env, jclass, jint source, jint strategy)
|
||||
{
|
||||
CS_Status status = 0;
|
||||
cs::SetSourceConnectionStrategy(
|
||||
source, static_cast<CS_ConnectionStrategy>(strategy), &status);
|
||||
CheckStatus(env, status);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_cscore_CameraServerJNI
|
||||
* Method: isSourceConnected
|
||||
@@ -614,6 +629,21 @@ Java_edu_wpi_cscore_CameraServerJNI_isSourceConnected
|
||||
return val;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_cscore_CameraServerJNI
|
||||
* Method: isSourceEnabled
|
||||
* Signature: (I)Z
|
||||
*/
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_edu_wpi_cscore_CameraServerJNI_isSourceEnabled
|
||||
(JNIEnv* env, jclass, jint source)
|
||||
{
|
||||
CS_Status status = 0;
|
||||
auto val = cs::IsSourceEnabled(source, &status);
|
||||
CheckStatus(env, status);
|
||||
return val;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_cscore_CameraServerJNI
|
||||
* Method: getSourceProperty
|
||||
|
||||
Reference in New Issue
Block a user