Void Sentry
An AI-driven, real-time Sentry Turret platform leveraging asynchronous I/O and computer vision to deliver high-precision autonomous motion tracking on resource-constrained embedded hardware.
Loading...
Searching...
No Matches
frame_slots.h
Go to the documentation of this file.
1
11#pragma once
12
13#include <array>
14#include <cstddef>
15#include <cstdint>
16#include <optional>
17#include <utility>
18
19namespace frames
20{
21// One writing + one latest + two readers holding older frames. Up to three readers exist (two queued /stream sends
22// plus the detect task); if all three hold frames older than the latest, begin_write() finds no Free slot and the
23// new camera frame is dropped and counted in dropped_no_slot rather than rewriting a leased slot.
24constexpr size_t kSlotCount = 4;
25
26struct FrameMeta {
27 size_t length = 0;
28 uint16_t width = 0;
29 uint16_t height = 0;
30 uint32_t sequence = 0; // assigned by FrameSlots::publish()
31};
32
33enum class AbortReason : uint8_t { Oversize, Corrupt, CaptureFailed };
34
37{
38public:
39 virtual void release_slot(size_t slot) = 0;
40
41protected:
42 ~SlotReleaser() = default;
43};
44
47{
48public:
49 FrameLease(SlotReleaser& owner, size_t slot, const FrameMeta& meta) : owner_(&owner), slot_(slot), meta_(meta) {}
50
51 FrameLease(const FrameLease&) = delete;
52 FrameLease& operator=(const FrameLease&) = delete;
53
54 FrameLease(FrameLease&& other) noexcept
55 : owner_(std::exchange(other.owner_, nullptr)), slot_(other.slot_), meta_(other.meta_)
56 {
57 }
58
59 FrameLease& operator=(FrameLease&& other) noexcept
60 {
61 if (this != &other)
62 {
63 release();
64 owner_ = std::exchange(other.owner_, nullptr);
65 slot_ = other.slot_;
66 meta_ = other.meta_;
67 }
68 return *this;
69 }
70
71 ~FrameLease() { release(); }
72
73 void release()
74 {
75 if (owner_ != nullptr)
76 {
77 owner_->release_slot(slot_);
78 owner_ = nullptr;
79 }
80 }
81
82 size_t slot() const { return slot_; }
83 const FrameMeta& meta() const { return meta_; }
84 bool valid() const { return owner_ != nullptr; }
85
86private:
87 SlotReleaser* owner_;
88 size_t slot_;
89 FrameMeta meta_;
90};
91
93{
94public:
96 std::optional<size_t> begin_write()
97 {
98 for (size_t i = 0; i < kSlotCount; ++i)
99 {
100 if (slots_[i].state == State::Free)
101 {
102 slots_[i].state = State::Writing;
103 return i;
104 }
105 }
106 ++dropped_no_slot_;
107 return std::nullopt;
108 }
109
111 void publish(size_t slot, FrameMeta meta)
112 {
113 meta.sequence = ++sequence_;
114 slots_[slot].state = State::Published;
115 slots_[slot].meta = meta;
116 if (latest_ && *latest_ != slot && slots_[*latest_].readers == 0)
117 {
118 slots_[*latest_].state = State::Free;
119 }
120 latest_ = slot;
121 ++published_;
122 }
123
125 void abort_write(size_t slot, AbortReason reason)
126 {
127 slots_[slot].state = State::Free;
128 if (reason == AbortReason::Oversize)
129 {
130 ++dropped_oversize_;
131 } else if (reason == AbortReason::Corrupt)
132 {
133 ++dropped_corrupt_;
134 }
135 }
136
137 std::optional<FrameLease> acquire_latest() { return acquire_latest(*this); }
138
140 std::optional<FrameLease> acquire_latest(SlotReleaser& releaser)
141 {
142 if (!latest_)
143 {
144 return std::nullopt;
145 }
146 Slot& slot = slots_[*latest_];
147 ++slot.readers;
148 return FrameLease(releaser, *latest_, slot.meta);
149 }
150
151 void release_slot(size_t slot) override
152 {
153 Slot& s = slots_[slot];
154 if (s.readers > 0)
155 {
156 --s.readers;
157 }
158 if (s.readers == 0 && s.state == State::Published && latest_ != slot)
159 {
160 s.state = State::Free;
161 }
162 }
163
164 uint32_t frames_published() const { return published_; }
165 uint32_t frames_dropped_no_slot() const { return dropped_no_slot_; }
166 uint32_t frames_dropped_oversize() const { return dropped_oversize_; }
167 uint32_t frames_dropped_corrupt() const { return dropped_corrupt_; }
168
169private:
170 enum class State : uint8_t { Free, Writing, Published };
171
172 struct Slot {
173 State state = State::Free;
174 uint8_t readers = 0;
175 FrameMeta meta;
176 };
177
178 std::array<Slot, kSlotCount> slots_{};
179 std::optional<size_t> latest_;
180 uint32_t sequence_ = 0;
181 uint32_t published_ = 0;
182 uint32_t dropped_no_slot_ = 0;
183 uint32_t dropped_oversize_ = 0;
184 uint32_t dropped_corrupt_ = 0;
185};
186} // namespace frames
Move-only handle on a published frame. Releases its slot exactly once, on release() or destruction.
Definition frame_slots.h:47
Definition frame_slots.h:93
void abort_write(size_t slot, AbortReason reason)
Give up a slot taken by begin_write(). Oversize and Corrupt are counted.
Definition frame_slots.h:125
void publish(size_t slot, FrameMeta meta)
Make a written slot the latest frame. Assigns the next sequence number.
Definition frame_slots.h:111
std::optional< FrameLease > acquire_latest(SlotReleaser &releaser)
Lease the latest frame; the lease will call releaser.release_slot() when done.
Definition frame_slots.h:140
std::optional< size_t > begin_write()
A slot that is not latest, not leased and not being written; nullopt (and a counted drop) if none.
Definition frame_slots.h:96
Whatever a FrameLease must notify when it is released (FrameSlots natively, FrameStore on device).
Definition frame_slots.h:37
Definition frame_slots.h:26