You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
110 lines
4.6 KiB
110 lines
4.6 KiB
#pragma once
|
|
|
|
#include <algorithm>
|
|
#include <functional>
|
|
#include <memory>
|
|
#include <mutex>
|
|
#include <optional>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include "tools/replay/camera.h"
|
|
#include "tools/replay/seg_mgr.h"
|
|
#include "tools/replay/timeline.h"
|
|
|
|
#define DEMO_ROUTE "a2a0ccea32023010|2023-07-27--13-01-19"
|
|
|
|
enum REPLAY_FLAGS {
|
|
REPLAY_FLAG_NONE = 0x0000,
|
|
REPLAY_FLAG_DCAM = 0x0002,
|
|
REPLAY_FLAG_ECAM = 0x0004,
|
|
REPLAY_FLAG_NO_LOOP = 0x0010,
|
|
REPLAY_FLAG_NO_FILE_CACHE = 0x0020,
|
|
REPLAY_FLAG_QCAMERA = 0x0040,
|
|
REPLAY_FLAG_NO_HW_DECODER = 0x0100,
|
|
REPLAY_FLAG_NO_VIPC = 0x0400,
|
|
REPLAY_FLAG_ALL_SERVICES = 0x0800,
|
|
};
|
|
|
|
class Replay {
|
|
public:
|
|
Replay(const std::string &route, std::vector<std::string> allow, std::vector<std::string> block, SubMaster *sm = nullptr,
|
|
uint32_t flags = REPLAY_FLAG_NONE, const std::string &data_dir = "");
|
|
~Replay();
|
|
bool load();
|
|
RouteLoadError lastRouteError() const { return route().lastError(); }
|
|
void start(int seconds = 0) { seekTo(min_seconds_ + seconds, false); }
|
|
void pause(bool pause);
|
|
void seekToFlag(FindFlag flag);
|
|
void seekTo(double seconds, bool relative);
|
|
inline bool isPaused() const { return user_paused_; }
|
|
inline int segmentCacheLimit() const { return seg_mgr_->segment_cache_limit_; }
|
|
inline void setSegmentCacheLimit(int n) { seg_mgr_->segment_cache_limit_ = std::max(MIN_SEGMENTS_CACHE, n); }
|
|
inline bool hasFlag(REPLAY_FLAGS flag) const { return flags_ & flag; }
|
|
void setLoop(bool loop) { loop ? flags_ &= ~REPLAY_FLAG_NO_LOOP : flags_ |= REPLAY_FLAG_NO_LOOP; }
|
|
bool loop() const { return !(flags_ & REPLAY_FLAG_NO_LOOP); }
|
|
const Route &route() const { return seg_mgr_->route_; }
|
|
inline double currentSeconds() const { return double(cur_mono_time_ - route_start_ts_) / 1e9; }
|
|
inline std::time_t routeDateTime() const { return route_date_time_; }
|
|
inline uint64_t routeStartNanos() const { return route_start_ts_; }
|
|
inline double toSeconds(uint64_t mono_time) const { return (mono_time - route_start_ts_) / 1e9; }
|
|
inline double minSeconds() const { return min_seconds_; }
|
|
inline double maxSeconds() const { return max_seconds_; }
|
|
inline void setSpeed(float speed) { speed_ = speed; }
|
|
inline float getSpeed() const { return speed_; }
|
|
inline const std::string &carFingerprint() const { return car_fingerprint_; }
|
|
inline const std::shared_ptr<std::vector<Timeline::Entry>> getTimeline() const { return timeline_.getEntries(); }
|
|
inline const std::optional<Timeline::Entry> findAlertAtTime(double sec) const { return timeline_.findAlertAtTime(sec); }
|
|
const std::shared_ptr<SegmentManager::EventData> getEventData() const { return seg_mgr_->getEventData(); }
|
|
void installEventFilter(std::function<bool(const Event *)> filter) { event_filter_ = filter; }
|
|
|
|
// Event callback functions
|
|
std::function<void()> onSegmentsMerged = nullptr;
|
|
std::function<void(double)> onSeeking = nullptr;
|
|
std::function<void(double)> onSeekedTo = nullptr;
|
|
std::function<void(std::shared_ptr<LogReader>)> onQLogLoaded = nullptr;
|
|
|
|
private:
|
|
void setupServices(const std::vector<std::string> &allow, const std::vector<std::string> &block);
|
|
void setupSegmentManager(bool has_filters);
|
|
void startStream(const std::shared_ptr<Segment> segment);
|
|
void streamThread();
|
|
void handleSegmentMerge();
|
|
void interruptStream(const std::function<bool()>& update_fn);
|
|
std::vector<Event>::const_iterator publishEvents(std::vector<Event>::const_iterator first,
|
|
std::vector<Event>::const_iterator last);
|
|
void publishMessage(const Event *e);
|
|
void publishFrame(const Event *e);
|
|
void checkSeekProgress();
|
|
|
|
std::unique_ptr<SegmentManager> seg_mgr_;
|
|
Timeline timeline_;
|
|
|
|
pthread_t stream_thread_id = 0;
|
|
std::thread stream_thread_;
|
|
std::mutex stream_lock_;
|
|
bool user_paused_ = false;
|
|
std::condition_variable stream_cv_;
|
|
std::atomic<int> current_segment_ = 0;
|
|
std::atomic<double> seeking_to_ = -1.0;
|
|
std::atomic<bool> exit_ = false;
|
|
std::atomic<bool> interrupt_requested_ = false;
|
|
bool events_ready_ = false;
|
|
std::time_t route_date_time_;
|
|
uint64_t route_start_ts_ = 0;
|
|
std::atomic<uint64_t> cur_mono_time_ = 0;
|
|
cereal::Event::Which cur_which_ = cereal::Event::Which::INIT_DATA;
|
|
double min_seconds_ = 0;
|
|
double max_seconds_ = 0;
|
|
SubMaster *sm_ = nullptr;
|
|
std::unique_ptr<PubMaster> pm_;
|
|
std::vector<const char*> sockets_;
|
|
std::unique_ptr<CameraServer> camera_server_;
|
|
std::atomic<uint32_t> flags_ = REPLAY_FLAG_NONE;
|
|
|
|
std::string car_fingerprint_;
|
|
std::atomic<float> speed_ = 1.0;
|
|
std::function<bool(const Event *)> event_filter_ = nullptr;
|
|
|
|
std::shared_ptr<SegmentManager::EventData> event_data_ = std::make_shared<SegmentManager::EventData>();
|
|
};
|
|
|