mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-21 01:01:43 +00:00
[cscore] Sink: add ability to get most recent frame instead of waiting (#7572)
This allows more control over frame dropping.
This commit is contained in:
@@ -63,6 +63,11 @@ uint64_t RawSinkImpl::GrabFrame(WPI_RawFrame& image) {
|
||||
}
|
||||
|
||||
uint64_t RawSinkImpl::GrabFrame(WPI_RawFrame& image, double timeout) {
|
||||
return GrabFrame(image, timeout, 0);
|
||||
}
|
||||
|
||||
uint64_t RawSinkImpl::GrabFrame(WPI_RawFrame& image, double timeout,
|
||||
uint64_t lastFrameTime) {
|
||||
SetEnabled(true);
|
||||
|
||||
auto source = GetSource();
|
||||
@@ -72,7 +77,7 @@ uint64_t RawSinkImpl::GrabFrame(WPI_RawFrame& image, double timeout) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto frame = source->GetNextFrame(timeout); // blocks
|
||||
auto frame = source->GetNextFrame(timeout, lastFrameTime); // blocks
|
||||
if (!frame) {
|
||||
// Bad frame; sleep for 20 ms so we don't consume all processor time.
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(20));
|
||||
@@ -183,6 +188,18 @@ uint64_t GrabSinkFrameTimeout(CS_Sink sink, WPI_RawFrame& image, double timeout,
|
||||
return static_cast<RawSinkImpl&>(*data->sink).GrabFrame(image, timeout);
|
||||
}
|
||||
|
||||
uint64_t GrabSinkFrameTimeoutLastTime(CS_Sink sink, WPI_RawFrame& image,
|
||||
double timeout, uint64_t lastFrameTime,
|
||||
CS_Status* status) {
|
||||
auto data = Instance::GetInstance().GetSink(sink);
|
||||
if (!data || (data->kind & SinkMask) == 0) {
|
||||
*status = CS_INVALID_HANDLE;
|
||||
return 0;
|
||||
}
|
||||
return static_cast<RawSinkImpl&>(*data->sink)
|
||||
.GrabFrame(image, timeout, lastFrameTime);
|
||||
}
|
||||
|
||||
} // namespace cs
|
||||
|
||||
extern "C" {
|
||||
@@ -209,4 +226,13 @@ uint64_t CS_GrabRawSinkFrameTimeout(CS_Sink sink, struct WPI_RawFrame* image,
|
||||
return cs::GrabSinkFrameTimeout(sink, *image, timeout, status);
|
||||
}
|
||||
|
||||
uint64_t CS_GrabRawSinkFrameTimeoutWithFrameTime(CS_Sink sink,
|
||||
struct WPI_RawFrame* image,
|
||||
double timeout,
|
||||
uint64_t lastFrameTime,
|
||||
CS_Status* status) {
|
||||
return cs::GrabSinkFrameTimeoutLastTime(sink, *image, timeout, lastFrameTime,
|
||||
status);
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
||||
@@ -34,10 +34,15 @@ class RawSinkImpl : public SinkImpl {
|
||||
|
||||
uint64_t GrabFrame(WPI_RawFrame& frame);
|
||||
uint64_t GrabFrame(WPI_RawFrame& frame, double timeout);
|
||||
// Wait for a frame with a time other than lastFrameTime
|
||||
uint64_t GrabFrame(WPI_RawFrame& frame, double timeout,
|
||||
uint64_t lastFrameTime);
|
||||
|
||||
private:
|
||||
void ThreadMain();
|
||||
|
||||
// Copies the image from incomingFrame into rawFrame, converting where
|
||||
// necessary to the resolution of rawFrame
|
||||
uint64_t GrabFrameImpl(WPI_RawFrame& rawFrame, Frame& incomingFrame);
|
||||
|
||||
std::atomic_bool m_active; // set to false to terminate threads
|
||||
|
||||
@@ -84,12 +84,17 @@ Frame SourceImpl::GetNextFrame() {
|
||||
return m_frame;
|
||||
}
|
||||
|
||||
Frame SourceImpl::GetNextFrame(double timeout) {
|
||||
Frame SourceImpl::GetNextFrame(double timeout, Frame::Time lastFrameTime) {
|
||||
std::unique_lock lock{m_frameMutex};
|
||||
auto oldTime = m_frame.GetTime();
|
||||
|
||||
if (lastFrameTime == 0) {
|
||||
lastFrameTime = m_frame.GetTime();
|
||||
}
|
||||
|
||||
// Wait unitl m_frame has a timestamp other than lastFrameTime
|
||||
if (!m_frameCv.wait_for(
|
||||
lock, std::chrono::milliseconds(static_cast<int>(timeout * 1000)),
|
||||
[=, this] { return m_frame.GetTime() != oldTime; })) {
|
||||
[=, this] { return m_frame.GetTime() != lastFrameTime; })) {
|
||||
m_frame = Frame{*this, "timed out getting frame", wpi::Now()};
|
||||
}
|
||||
return m_frame;
|
||||
|
||||
@@ -98,7 +98,8 @@ class SourceImpl : public PropertyContainer {
|
||||
|
||||
// Blocking function that waits for the next frame and returns it (with
|
||||
// timeout in seconds). If timeout expires, returns empty frame.
|
||||
Frame GetNextFrame(double timeout);
|
||||
// If lastFrameTime==0, uses m_frame.GetTime() for lastFrameTime
|
||||
Frame GetNextFrame(double timeout, Frame::Time lastFrameTime = 0);
|
||||
|
||||
// Force a wakeup of all GetNextFrame() callers by sending an empty frame.
|
||||
void Wakeup();
|
||||
|
||||
Reference in New Issue
Block a user