From ea2c4f8be962e86c2a162bd768ebcb8bc5d13da1 Mon Sep 17 00:00:00 2001 From: Trey Moen Date: Mon, 24 Mar 2025 23:16:39 -0700 Subject: [PATCH] wip not working --- selfdrive/ui/qt/onroad/onroad_home.cc | 2 +- selfdrive/ui/qt/onroad/onroad_home.h | 6 ++- tools/clip/.gitignore | 3 ++ tools/clip/application.cc | 78 +++++++++++++++++++++------ tools/clip/application.h | 9 ++-- tools/clip/main.cc | 11 ++-- tools/clip/recorder/ffmpeg.cc | 6 +-- tools/clip/recorder/ffmpeg.h | 2 +- tools/clip/recorder/widget.cc | 6 +-- tools/clip/recorder/widget.h | 2 +- tools/replay/replay.cc | 2 - tools/replay/seg_mgr.h | 2 +- 12 files changed, 88 insertions(+), 41 deletions(-) diff --git a/selfdrive/ui/qt/onroad/onroad_home.cc b/selfdrive/ui/qt/onroad/onroad_home.cc index f7df0431c6..e2c45f4f52 100644 --- a/selfdrive/ui/qt/onroad/onroad_home.cc +++ b/selfdrive/ui/qt/onroad/onroad_home.cc @@ -56,7 +56,7 @@ void OnroadWindow::updateState(const UIState &s) { update(); } - emit drewOnroadFrame(std::make_shared(std::move(grab()))); + emit redrew(); } void OnroadWindow::offroadTransition(bool offroad) { diff --git a/selfdrive/ui/qt/onroad/onroad_home.h b/selfdrive/ui/qt/onroad/onroad_home.h index 86c33aaa2f..78267aa48b 100644 --- a/selfdrive/ui/qt/onroad/onroad_home.h +++ b/selfdrive/ui/qt/onroad/onroad_home.h @@ -10,15 +10,17 @@ public: OnroadWindow(QWidget* parent = 0); signals: - void drewOnroadFrame(const std::shared_ptr &frame); + void redrew(); private: - void paintEvent(QPaintEvent *event); OnroadAlerts *alerts; AnnotatedCameraWidget *nvg; QColor bg = bg_colors[STATUS_DISENGAGED]; QHBoxLayout* split; +protected: + void paintEvent(QPaintEvent *event) override; + private slots: void offroadTransition(bool offroad); void updateState(const UIState &s); diff --git a/tools/clip/.gitignore b/tools/clip/.gitignore index e3bd6ea9a7..0f3ebdfd58 100644 --- a/tools/clip/.gitignore +++ b/tools/clip/.gitignore @@ -1 +1,4 @@ +moc_* +*.moc + clip \ No newline at end of file diff --git a/tools/clip/application.cc b/tools/clip/application.cc index 5d1fbfc53c..9a655bcdbd 100644 --- a/tools/clip/application.cc +++ b/tools/clip/application.cc @@ -7,12 +7,53 @@ #include "recorder/widget.h" -Application::Application(int argc, char *argv[]) { +Application::Application(int argc, char *argv[], QObject *parent) : QObject(parent) { initApp(argc, argv); app = new QApplication(argc, argv); - QString outputFile = "/Users/trey/Desktop/out.mp4"; + QCommandLineParser parser; + parser.setApplicationDescription("Clip your ride!"); + parser.addHelpOption(); + + const QCommandLineOption start({"s", "start"}, "start time", "start"); + parser.addOption(start); + + const QCommandLineOption output({"o", "output"}, "output file", "output"); + parser.addOption(output); + + parser.addPositionalArgument("route", "route string"); + + parser.process(*app); + + int startTime = 0; + if (parser.isSet(start)) { + bool ok; + int parsed = parser.value(start).toInt(&ok); + if (!ok) { + qDebug() << "start time must be an integer\n"; + fprintf(stderr, "%s", parser.helpText().toStdString().c_str()); + exit(1); + } + startTime = parsed; + } + + if (!parser.isSet(output)) { + qDebug() << "output is required\n"; + fprintf(stderr, "%s", parser.helpText().toStdString().c_str()); + exit(1); + } + QString outputFile = parser.value(output); + + QString route; + QStringList positionalArgs = parser.positionalArguments(); + if (!positionalArgs.isEmpty()) { + route = positionalArgs.at(0); + } else { + qDebug() << "No file specified\n"; + fprintf(stderr, "%s", parser.helpText().toStdString().c_str()); + exit(1); + } QTranslator translator; QString translation_file = QString::fromStdString(Params().get("LanguageSetting")); @@ -25,10 +66,14 @@ Application::Application(int argc, char *argv[]) { window = new OnroadWindow(); recorderThread = new QThread; - recorder = new Recorder; + recorder = new Recorder(outputFile.toStdString()); recorder->moveToThread(recorderThread); QObject::connect(recorderThread, &QThread::finished, recorder, &QObject::deleteLater); - QObject::connect(window, &OnroadWindow::drewOnroadFrame, recorder, &Recorder::saveFrame, Qt::QueuedConnection); + + QObject::connect(window, &OnroadWindow::redrew, this, [&]() { + recorder->saveFrame(std::make_shared(std::move(window->grab()))); + }, Qt::DirectConnection); + QObject::connect(app, &QCoreApplication::aboutToQuit, recorderThread, &QThread::quit); window->setAttribute(Qt::WA_DontShowOnScreen); @@ -37,29 +82,28 @@ Application::Application(int argc, char *argv[]) { recorderThread->start(); // Initialize and start replay - initReplay(); - replayThread = QThread::create([this] { startReplay(); }); + initReplay(route.toStdString()); + replayThread = QThread::create([this, startTime] { startReplay(startTime); }); replayThread->start(); } -void Application::initReplay() { +void Application::initReplay(const std::string& route) { std::vector allow; std::vector block; - replay = std::make_unique("a2a0ccea32023010|2023-07-27--13-01-19", allow, block, nullptr, - REPLAY_FLAG_NONE); - replay->setSegmentCacheLimit(10); + replay = std::make_unique(route, allow, block, nullptr, REPLAY_FLAG_NONE); + replay->setSegmentCacheLimit(1); } -void Application::startReplay() { +void Application::startReplay(int start) { if (!replay || !replay->load()) { qWarning() << "Failed to load replay"; - return; + QApplication::instance()->quit(); } qInfo() << "Replay started."; replayRunning = true; - replay->setEndSeconds(120); - replay->start(60); + replay->setEndSeconds(start + 60); + replay->start(start + 2); replay->waitUntilEnd(); qInfo() << "Replay ended."; replayRunning = false; @@ -83,10 +127,10 @@ Application::~Application() { } int Application::exec() const { - std::this_thread::sleep_for(std::chrono::seconds(3)); + // TODO: modify Replay to block until all OnroadWindow required messages have been broadcast at least once + std::this_thread::sleep_for(std::chrono::seconds(5)); setMainWindow(window); - app->exec(); - return 0; + return app->exec(); } diff --git a/tools/clip/application.h b/tools/clip/application.h index 3e906d8f26..74a28a4e84 100644 --- a/tools/clip/application.h +++ b/tools/clip/application.h @@ -6,16 +6,17 @@ #include "recorder/widget.h" -class Application { +class Application : public QObject { + Q_OBJECT public: - Application(int argc, char* argv[]); + Application(int argc, char* argv[], QObject *parent = nullptr); ~Application(); int exec() const; void close() const; private: - void initReplay(); - void startReplay(); + void initReplay(const std::string& route); + void startReplay(int start = 0); QApplication *app; QThread *recorderThread = nullptr; diff --git a/tools/clip/main.cc b/tools/clip/main.cc index e917a46aff..04ee55d167 100644 --- a/tools/clip/main.cc +++ b/tools/clip/main.cc @@ -2,11 +2,10 @@ #include "application.h" int main(int argc, char *argv[]) { +#ifdef __APPLE__ + // With all sockets opened, we might hit the default limit of 256 on macOS + util::set_file_descriptor_limit(1024); +#endif Application a(argc, argv); - - if (a.exec()) { - std::cerr << "Failed to start app." << std::endl; - } - - return 0; + return a.exec(); } \ No newline at end of file diff --git a/tools/clip/recorder/ffmpeg.cc b/tools/clip/recorder/ffmpeg.cc index b1979a932f..9225780713 100644 --- a/tools/clip/recorder/ffmpeg.cc +++ b/tools/clip/recorder/ffmpeg.cc @@ -1,9 +1,9 @@ #include "tools/clip/recorder/ffmpeg.h" #include -FFmpegEncoder::FFmpegEncoder(const QString& outputFile, int width, int height, int fps) { +FFmpegEncoder::FFmpegEncoder(const std::string& outputFile, int width, int height, int fps) { // Allocate output context - if (avformat_alloc_output_context2(&format_ctx, nullptr, nullptr, outputFile.toStdString().c_str()) < 0) { + if (avformat_alloc_output_context2(&format_ctx, nullptr, nullptr, outputFile.c_str()) < 0) { return; } @@ -60,7 +60,7 @@ FFmpegEncoder::FFmpegEncoder(const QString& outputFile, int width, int height, i // Open output file if (!(format_ctx->oformat->flags & AVFMT_NOFILE)) { - if (avio_open(&format_ctx->pb, outputFile.toStdString().c_str(), AVIO_FLAG_WRITE) < 0) { + if (avio_open(&format_ctx->pb, outputFile.c_str(), AVIO_FLAG_WRITE) < 0) { return; } } diff --git a/tools/clip/recorder/ffmpeg.h b/tools/clip/recorder/ffmpeg.h index 0927839c60..39901dfd9c 100644 --- a/tools/clip/recorder/ffmpeg.h +++ b/tools/clip/recorder/ffmpeg.h @@ -11,7 +11,7 @@ extern "C" { class FFmpegEncoder { public: - FFmpegEncoder(const QString& outputFile, int width, int height, int fps); + FFmpegEncoder(const std::string& outputFile, int width, int height, int fps); ~FFmpegEncoder(); bool writeFrame(const QImage& image); diff --git a/tools/clip/recorder/widget.cc b/tools/clip/recorder/widget.cc index 5d8ad78850..861809d22d 100644 --- a/tools/clip/recorder/widget.cc +++ b/tools/clip/recorder/widget.cc @@ -2,8 +2,8 @@ #include "tools/clip/recorder/ffmpeg.h" -Recorder::Recorder(QObject *parent) : QObject(parent) { - encoder = new FFmpegEncoder("/Users/trey/Desktop/out.mp4", DEVICE_SCREEN_SIZE.width(), DEVICE_SCREEN_SIZE.height(), UI_FREQ); +Recorder::Recorder(const std::string& outputFile, QObject *parent) : QObject(parent) { + encoder = new FFmpegEncoder(outputFile, DEVICE_SCREEN_SIZE.width(), DEVICE_SCREEN_SIZE.height(), UI_FREQ); } Recorder::~Recorder() { @@ -12,7 +12,7 @@ Recorder::~Recorder() { void Recorder::saveFrame(const std::shared_ptr &frame) { QMutexLocker locker(&mutex); - frameQueue.enqueue(frame); // Add frame to queue + frameQueue.enqueue(frame); if (!isProcessing) { isProcessing = true; QMetaObject::invokeMethod(this, &Recorder::processQueue, Qt::QueuedConnection); diff --git a/tools/clip/recorder/widget.h b/tools/clip/recorder/widget.h index fcb7dcbd26..4f5a97a5fd 100644 --- a/tools/clip/recorder/widget.h +++ b/tools/clip/recorder/widget.h @@ -12,7 +12,7 @@ class Recorder : public QObject { Q_OBJECT public: - Recorder(QObject *parent = nullptr); + Recorder(const std::string& outputFile, QObject *parent = nullptr); ~Recorder() override; public slots: diff --git a/tools/replay/replay.cc b/tools/replay/replay.cc index 618d3cc958..0a7ca8910e 100644 --- a/tools/replay/replay.cc +++ b/tools/replay/replay.cc @@ -215,8 +215,6 @@ void Replay::startStream(const std::shared_ptr segment) { } void Replay::publishMessage(const Event *e) { - if (event_filter_ && event_filter_(e)) return; - if (!sm_) { auto bytes = e->data.asBytes(); int ret = pm_->send(sockets_[e->which], (capnp::byte *)bytes.begin(), bytes.size()); diff --git a/tools/replay/seg_mgr.h b/tools/replay/seg_mgr.h index 17dea041ed..9158e41618 100644 --- a/tools/replay/seg_mgr.h +++ b/tools/replay/seg_mgr.h @@ -20,7 +20,7 @@ public: bool isSegmentLoaded(int n) const { return segments.find(n) != segments.end(); } }; - SegmentManager(const std::string &route_name, uint32_t flags, const std::string &data_dir = "/tmp/clip") + SegmentManager(const std::string &route_name, uint32_t flags, const std::string &data_dir = "") : flags_(flags), route_(route_name, data_dir), event_data_(std::make_shared()) {} ~SegmentManager();