mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-07-05 13:32:05 +08:00
cabana: remove the qlog parsing thread (#30319)
remove the qlog thread old-commit-hash: e287a5f1641ae93a31deaeb3c03c5fd27ed80759
This commit is contained in:
@@ -40,6 +40,7 @@ bool ReplayStream::loadRoute(const QString &route, const QString &data_dir, uint
|
||||
replay->installEventFilter(event_filter, this);
|
||||
QObject::connect(replay.get(), &Replay::seekedTo, this, &AbstractStream::seekedTo);
|
||||
QObject::connect(replay.get(), &Replay::segmentsMerged, this, &ReplayStream::mergeSegments);
|
||||
QObject::connect(replay.get(), &Replay::qLogLoaded, this, &ReplayStream::qLogLoaded, Qt::QueuedConnection);
|
||||
return replay->load();
|
||||
}
|
||||
|
||||
|
||||
@@ -32,6 +32,9 @@ public:
|
||||
inline const std::vector<std::tuple<double, double, TimelineType>> getTimeline() override { return replay->getTimeline(); }
|
||||
static AbstractOpenStreamWidget *widget(AbstractStream **stream);
|
||||
|
||||
signals:
|
||||
void qLogLoaded(int segnum, std::shared_ptr<LogReader> qlog);
|
||||
|
||||
private:
|
||||
void mergeSegments();
|
||||
std::unique_ptr<Replay> replay = nullptr;
|
||||
|
||||
+25
-52
@@ -1,8 +1,6 @@
|
||||
#include "tools/cabana/videowidget.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include <QButtonGroup>
|
||||
@@ -11,7 +9,6 @@
|
||||
#include <QPainter>
|
||||
#include <QStackedLayout>
|
||||
#include <QStyleOptionSlider>
|
||||
#include <QTimer>
|
||||
#include <QVBoxLayout>
|
||||
#include <QtConcurrent>
|
||||
|
||||
@@ -125,6 +122,7 @@ QWidget *VideoWidget::createCameraWidget() {
|
||||
QObject::connect(slider, &QSlider::valueChanged, [=](int value) { time_label->setText(utils::formatSeconds(slider->currentSecond())); });
|
||||
QObject::connect(slider, &Slider::updateMaximumTime, this, &VideoWidget::setMaximumTime, Qt::QueuedConnection);
|
||||
QObject::connect(cam_widget, &CameraWidget::clicked, []() { can->pause(!can->isPaused()); });
|
||||
QObject::connect(static_cast<ReplayStream*>(can), &ReplayStream::qLogLoaded, slider, &Slider::parseQLog);
|
||||
QObject::connect(can, &AbstractStream::updated, this, &VideoWidget::updateState);
|
||||
return w;
|
||||
}
|
||||
@@ -165,29 +163,9 @@ void VideoWidget::updatePlayBtnState() {
|
||||
|
||||
Slider::Slider(QWidget *parent) : thumbnail_label(parent), QSlider(Qt::Horizontal, parent) {
|
||||
setMouseTracking(true);
|
||||
auto timer = new QTimer(this);
|
||||
timer->callOnTimeout([this]() {
|
||||
timeline = can->getTimeline();
|
||||
std::sort(timeline.begin(), timeline.end(), [](auto &l, auto &r) { return std::get<2>(l) < std::get<2>(r); });
|
||||
update();
|
||||
});
|
||||
timer->start(2000);
|
||||
QObject::connect(can, &AbstractStream::eventsMerged, [this]() {
|
||||
if (!qlog_future) {
|
||||
qlog_future = std::make_unique<QFuture<void>>(QtConcurrent::run(this, &Slider::parseQLog));
|
||||
}
|
||||
});
|
||||
QObject::connect(qApp, &QApplication::aboutToQuit, [this]() {
|
||||
abort_parse_qlog = true;
|
||||
if (qlog_future && qlog_future->isRunning()) {
|
||||
qDebug() << "stopping thumbnail thread";
|
||||
qlog_future->waitForFinished();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
AlertInfo Slider::alertInfo(double seconds) {
|
||||
std::lock_guard lk(thumbnail_lock);
|
||||
uint64_t mono_time = (seconds + can->routeStartTime()) * 1e9;
|
||||
auto alert_it = alerts.lower_bound(mono_time);
|
||||
bool has_alert = (alert_it != alerts.end()) && ((alert_it->first - mono_time) <= 1e8);
|
||||
@@ -195,7 +173,6 @@ AlertInfo Slider::alertInfo(double seconds) {
|
||||
}
|
||||
|
||||
QPixmap Slider::thumbnail(double seconds) {
|
||||
std::lock_guard lk(thumbnail_lock);
|
||||
uint64_t mono_time = (seconds + can->routeStartTime()) * 1e9;
|
||||
auto it = thumbnails.lowerBound(mono_time);
|
||||
return it != thumbnails.end() ? it.value() : QPixmap();
|
||||
@@ -206,36 +183,32 @@ void Slider::setTimeRange(double min, double max) {
|
||||
setRange(min * factor, max * factor);
|
||||
}
|
||||
|
||||
void Slider::parseQLog() {
|
||||
const auto &segments = can->route()->segments();
|
||||
for (auto it = segments.rbegin(); it != segments.rend() && !abort_parse_qlog; ++it) {
|
||||
LogReader log;
|
||||
std::string qlog = it->second.qlog.toStdString();
|
||||
if (!qlog.empty() && log.load(qlog, &abort_parse_qlog, {cereal::Event::Which::THUMBNAIL, cereal::Event::Which::CONTROLS_STATE}, true, 0, 3)) {
|
||||
if (it == segments.rbegin() && !log.events.empty()) {
|
||||
double max_time = log.events.back()->mono_time / 1e9 - can->routeStartTime();
|
||||
emit updateMaximumTime(max_time);
|
||||
void Slider::parseQLog(int segnum, std::shared_ptr<LogReader> qlog) {
|
||||
const auto &segments = qobject_cast<ReplayStream *>(can)->route()->segments();
|
||||
if (segments.size() > 0 && segnum == segments.rbegin()->first && !qlog->events.empty()) {
|
||||
emit updateMaximumTime(qlog->events.back()->mono_time / 1e9 - can->routeStartTime());
|
||||
}
|
||||
|
||||
std::mutex mutex;
|
||||
QtConcurrent::blockingMap(qlog->events.cbegin(), qlog->events.cend(), [&mutex, this](const Event *e) {
|
||||
if (e->which == cereal::Event::Which::THUMBNAIL) {
|
||||
auto thumb = e->event.getThumbnail();
|
||||
auto data = thumb.getThumbnail();
|
||||
if (QPixmap pm; pm.loadFromData(data.begin(), data.size(), "jpeg")) {
|
||||
QPixmap scaled = pm.scaledToHeight(MIN_VIDEO_HEIGHT - THUMBNAIL_MARGIN * 2, Qt::SmoothTransformation);
|
||||
std::lock_guard lk(mutex);
|
||||
thumbnails[thumb.getTimestampEof()] = scaled;
|
||||
}
|
||||
for (auto ev = log.events.cbegin(); ev != log.events.cend() && !abort_parse_qlog; ++ev) {
|
||||
if ((*ev)->which == cereal::Event::Which::THUMBNAIL) {
|
||||
auto thumb = (*ev)->event.getThumbnail();
|
||||
auto data = thumb.getThumbnail();
|
||||
if (QPixmap pm; pm.loadFromData(data.begin(), data.size(), "jpeg")) {
|
||||
pm = pm.scaledToHeight(MIN_VIDEO_HEIGHT - THUMBNAIL_MARGIN * 2, Qt::SmoothTransformation);
|
||||
std::lock_guard lk(thumbnail_lock);
|
||||
thumbnails[thumb.getTimestampEof()] = pm;
|
||||
}
|
||||
} else if ((*ev)->which == cereal::Event::Which::CONTROLS_STATE) {
|
||||
auto cs = (*ev)->event.getControlsState();
|
||||
if (cs.getAlertType().size() > 0 && cs.getAlertText1().size() > 0 &&
|
||||
cs.getAlertSize() != cereal::ControlsState::AlertSize::NONE) {
|
||||
std::lock_guard lk(thumbnail_lock);
|
||||
alerts.emplace((*ev)->mono_time, AlertInfo{cs.getAlertStatus(), cs.getAlertText1().cStr(), cs.getAlertText2().cStr()});
|
||||
}
|
||||
}
|
||||
} else if (e->which == cereal::Event::Which::CONTROLS_STATE) {
|
||||
auto cs = e->event.getControlsState();
|
||||
if (cs.getAlertType().size() > 0 && cs.getAlertText1().size() > 0 &&
|
||||
cs.getAlertSize() != cereal::ControlsState::AlertSize::NONE) {
|
||||
std::lock_guard lk(mutex);
|
||||
alerts.emplace(e->mono_time, AlertInfo{cs.getAlertStatus(), cs.getAlertText1().cStr(), cs.getAlertText2().cStr()});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
update();
|
||||
}
|
||||
|
||||
void Slider::paintEvent(QPaintEvent *ev) {
|
||||
@@ -245,7 +218,7 @@ void Slider::paintEvent(QPaintEvent *ev) {
|
||||
double min = minimum() / factor;
|
||||
double max = maximum() / factor;
|
||||
|
||||
for (auto [begin, end, type] : timeline) {
|
||||
for (auto [begin, end, type] : qobject_cast<ReplayStream *>(can)->getTimeline()) {
|
||||
if (begin > max || end < min)
|
||||
continue;
|
||||
r.setLeft(((std::max(min, begin) - min) / (max - min)) * width());
|
||||
|
||||
@@ -1,19 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include <atomic>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
|
||||
#include <QFuture>
|
||||
#include <QLabel>
|
||||
#include <QSlider>
|
||||
#include <QToolButton>
|
||||
|
||||
#include "selfdrive/ui/qt/widgets/cameraview.h"
|
||||
#include "tools/cabana/streams/abstractstream.h"
|
||||
#include "tools/cabana/streams/replaystream.h"
|
||||
|
||||
struct AlertInfo {
|
||||
cereal::ControlsState::AlertStatus status;
|
||||
@@ -42,6 +37,7 @@ public:
|
||||
void setTimeRange(double min, double max);
|
||||
AlertInfo alertInfo(double sec);
|
||||
QPixmap thumbnail(double sec);
|
||||
void parseQLog(int segnum, std::shared_ptr<LogReader> qlog);
|
||||
|
||||
signals:
|
||||
void updateMaximumTime(double);
|
||||
@@ -51,15 +47,10 @@ private:
|
||||
void mouseMoveEvent(QMouseEvent *e) override;
|
||||
bool event(QEvent *event) override;
|
||||
void paintEvent(QPaintEvent *ev) override;
|
||||
void parseQLog();
|
||||
|
||||
const double factor = 1000.0;
|
||||
std::vector<std::tuple<double, double, TimelineType>> timeline;
|
||||
std::mutex thumbnail_lock;
|
||||
std::atomic<bool> abort_parse_qlog = false;
|
||||
QMap<uint64_t, QPixmap> thumbnails;
|
||||
std::map<uint64_t, AlertInfo> alerts;
|
||||
std::unique_ptr<QFuture<void>> qlog_future;
|
||||
InfoLabel thumbnail_label;
|
||||
};
|
||||
|
||||
|
||||
@@ -153,12 +153,10 @@ void Replay::buildTimeline() {
|
||||
|
||||
const auto &route_segments = route_->segments();
|
||||
for (auto it = route_segments.cbegin(); it != route_segments.cend() && !exit_; ++it) {
|
||||
LogReader log;
|
||||
if (!log.load(it->second.qlog.toStdString(), &exit_,
|
||||
{cereal::Event::Which::CONTROLS_STATE, cereal::Event::Which::USER_FLAG},
|
||||
!hasFlag(REPLAY_FLAG_NO_FILE_CACHE), 0, 3)) continue;
|
||||
std::shared_ptr<LogReader> log(new LogReader());
|
||||
if (!log->load(it->second.qlog.toStdString(), &exit_, {}, !hasFlag(REPLAY_FLAG_NO_FILE_CACHE), 0, 3)) continue;
|
||||
|
||||
for (const Event *e : log.events) {
|
||||
for (const Event *e : log->events) {
|
||||
if (e->which == cereal::Event::Which::CONTROLS_STATE) {
|
||||
auto cs = e->event.getControlsState();
|
||||
|
||||
@@ -186,6 +184,8 @@ void Replay::buildTimeline() {
|
||||
timeline.push_back({toSeconds(e->mono_time), toSeconds(e->mono_time), TimelineType::UserFlag});
|
||||
}
|
||||
}
|
||||
std::sort(timeline.begin(), timeline.end(), [](auto &l, auto &r) { return std::get<2>(l) < std::get<2>(r); });
|
||||
emit qLogLoaded(it->first, log);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@ enum class FindFlag {
|
||||
|
||||
enum class TimelineType { None, Engaged, AlertInfo, AlertWarning, AlertCritical, UserFlag };
|
||||
typedef bool (*replayEventFilter)(const Event *, void *);
|
||||
Q_DECLARE_METATYPE(std::shared_ptr<LogReader>);
|
||||
|
||||
class Replay : public QObject {
|
||||
Q_OBJECT
|
||||
@@ -91,6 +92,7 @@ signals:
|
||||
void streamStarted();
|
||||
void segmentsMerged();
|
||||
void seekedTo(double sec);
|
||||
void qLogLoaded(int segnum, std::shared_ptr<LogReader> qlog);
|
||||
|
||||
protected slots:
|
||||
void segmentLoadFinished(bool success);
|
||||
|
||||
Reference in New Issue
Block a user