OpenEV
Extending OpenCV to event-based vision
Loading...
Searching...
No Matches
player.hpp
Go to the documentation of this file.
1
6#ifndef OPENEV_READERS_PLAYER_HPP
7#define OPENEV_READERS_PLAYER_HPP
8
12#include "openev/core/imu.hpp"
13#include "openev/core/types.hpp"
14#include <algorithm>
15#include <chrono>
16#include <cstddef>
17#include <opencv2/imgcodecs.hpp>
18#include <type_traits>
19#include <utility>
20
21namespace ev {
22[[maybe_unused]] constexpr bool USING_PLAYER_HPP = true;
23
25template <typename R, typename = void>
26struct has_frames_ : std::false_type {};
27template <typename R>
28struct has_frames_<R, std::void_t<decltype(std::declval<const R &>().frames())>> : std::true_type {};
29
30template <typename R, typename = void>
31struct has_imu_ : std::false_type {};
32template <typename R>
33struct has_imu_<R, std::void_t<decltype(std::declval<const R &>().imu())>> : std::true_type {};
35
41template <typename Reader>
42class Player_ {
43public:
48 explicit Player_(Reader &reader) : reader_{reader} {}
49
54 inline void setSpeed(const double speed) {
55 speed_ = speed;
56 }
57
62 [[nodiscard]] inline double speed() const {
63 return speed_;
64 }
65
70 inline void pause(const bool paused) {
71 paused_ = paused;
72 }
73
78 [[nodiscard]] inline bool isPaused() const {
79 return paused_;
80 }
81
86 inline void setLoop(const bool loop) {
87 loop_ = loop;
88 }
89
93 void restart() {
94 reader_.reset();
95 playhead_ = 0;
96 anchored_ = false;
97 frame_ = 0;
98 sample_ = 0;
99 finished_ = false;
100 loops_++;
101 }
102
107 [[nodiscard]] inline std::size_t loops() const {
108 return loops_;
109 }
110
115 [[nodiscard]] inline TimeType playhead() const {
116 return playhead_;
117 }
118
123 [[nodiscard]] inline bool isFinished() const {
124 return finished_;
125 }
126
131 void next(Queue &events) {
132 advance_(elapsed_(), events, nullptr, nullptr);
133 }
134
139 void next(Queue &events, StampedMatQueue &frames) {
140 advance_(elapsed_(), events, &frames, nullptr);
141 }
142
147 void next(Queue &events, StampedMatQueue &frames, ImuQueue &imus) {
148 advance_(elapsed_(), events, &frames, &imus);
149 }
150
151private:
152 static constexpr double SECONDS_TO_MICROSECONDS = 1e6;
153 static constexpr std::size_t BATCH = 256;
154
155 Reader &reader_;
156 std::chrono::steady_clock::time_point last_;
157 bool started_{false};
158 bool paused_{false};
159 bool loop_{true};
160 bool finished_{false};
161 bool anchored_{false};
162 double speed_{1.0};
163 TimeType playhead_{0};
164 std::size_t frame_{0};
165 std::size_t sample_{0};
166 std::size_t loops_{0};
167
168 [[nodiscard]] std::size_t batch_() const {
169 const std::size_t level = reader_.prefetchCapacity();
170 return level > 0 ? std::min(level, BATCH) : BATCH;
171 }
172
173 [[nodiscard]] TimeType elapsed_() {
174 const auto now = std::chrono::steady_clock::now();
175 const TimeType elapsed = started_ && !paused_ ? std::chrono::duration<double>(now - last_).count() * SECONDS_TO_MICROSECONDS * speed_ : 0;
176 last_ = now;
177 started_ = true;
178 return elapsed;
179 }
180
181protected:
183 void advance_(const TimeType time, Queue &events, StampedMatQueue *frames, ImuQueue *imus) {
184 if(finished_) {
185 return;
186 }
187 if(!anchored_) {
188 ConcurrentQueue *first = &reader_.events();
189 if(first->empty()) {
190 first = &reader_.events(batch_());
191 }
192 if(!first->empty()) {
193 playhead_ = first->front().t;
194 }
195 anchored_ = true;
196 }
197 playhead_ += time;
198
199 while(true) {
200 ConcurrentQueue *pending = &reader_.events();
201 if(pending->empty()) {
202 pending = &reader_.events(batch_());
203 }
204 ConcurrentQueue &queue = *pending;
205 if(queue.empty()) {
206 if(!loop_) {
207 finished_ = true;
208 break;
209 }
210 restart();
211 finished_ = reader_.events(batch_()).empty();
212 break;
213 }
214 const Event &e = queue.front();
215 if(e.t > playhead_) {
216 break;
217 }
218 events.push(e);
219 queue.pop();
220 }
221
222 if constexpr(has_frames_<Reader>::value) {
223 if(frames != nullptr) {
224 const auto &all = reader_.frames();
225 while(frame_ < all.size() && all[frame_].t <= playhead_) {
226 StampedMat frame;
227 cv::imread(all[frame_].path, cv::IMREAD_GRAYSCALE).copyTo(frame);
228 frame.t = all[frame_].t;
229 if(!frame.empty()) {
230 frames->push(frame);
231 }
232 frame_++;
233 }
234 }
235 }
236
237 if constexpr(has_imu_<Reader>::value) {
238 if(imus != nullptr) {
239 const auto &all = reader_.imu();
240 while(sample_ < all.size() && all[sample_].t <= playhead_) {
241 imus->push(all[sample_]);
242 sample_++;
243 }
244 }
245 }
246 }
248};
249
250} // namespace ev
251
252#endif // OPENEV_READERS_PLAYER_HPP
double speed() const
Get the playback speed.
Definition player.hpp:62
bool isFinished() const
Check if the reader ran out of events with setLoop(false).
Definition player.hpp:123
std::size_t loops() const
Number of times the playback has started again, either by restart() or by reaching the end.
Definition player.hpp:107
void pause(const bool paused)
Hold the playhead, so next() delivers nothing.
Definition player.hpp:70
void setSpeed(const double speed)
Set the playback speed.
Definition player.hpp:54
void next(Queue &events, StampedMatQueue &frames, ImuQueue &imus)
Definition player.hpp:147
void next(Queue &events, StampedMatQueue &frames)
Definition player.hpp:139
void setLoop(const bool loop)
Choose what happens when the reader runs out of events.
Definition player.hpp:86
Player_(Reader &reader)
Construct the player. The playback starts with the first call to next().
Definition player.hpp:48
void next(Queue &events)
Deliver what happened since the previous call.
Definition player.hpp:131
TimeType playhead() const
Current position of the playback, which starts at the timestamp of the first event.
Definition player.hpp:115
void restart()
Start again from the beginning.
Definition player.hpp:93
bool isPaused() const
Check if the playback is paused.
Definition player.hpp:78
Queue container for basic event structures, safe between a thread that pushes and a thread that pops.
ConcurrentQueuei ConcurrentQueue
Definition concurrent_queue.hpp:93
Timestamped images.
Inertial measurements.
Queue container for basic event structures.
Queuei Queue
Definition queue.hpp:40
Basic event-based vision structures based on OpenCV components.
Eventi Event
Definition types.hpp:262