#include #include #include "common/prefix.h" #include "tools/replay/consoleui.h" #include "tools/replay/replay.h" int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); const QStringList base_blacklist = {"uiDebug", "userFlag"}; const std::tuple flags[] = { {"dcam", REPLAY_FLAG_DCAM, "load driver camera"}, {"ecam", REPLAY_FLAG_ECAM, "load wide road camera"}, {"no-loop", REPLAY_FLAG_NO_LOOP, "stop at the end of the route"}, {"no-cache", REPLAY_FLAG_NO_FILE_CACHE, "turn off local cache"}, {"qcam", REPLAY_FLAG_QCAMERA, "load qcamera"}, {"no-hw-decoder", REPLAY_FLAG_NO_HW_DECODER, "disable HW video decoding"}, {"no-vipc", REPLAY_FLAG_NO_VIPC, "do not output video"}, {"all", REPLAY_FLAG_ALL_SERVICES, "do output all messages including " + base_blacklist.join(", ") + ". this may causes issues when used along with UI"} }; QCommandLineParser parser; parser.setApplicationDescription("Mock openpilot components by publishing logged messages."); parser.addHelpOption(); parser.addPositionalArgument("route", "the drive to replay. find your drives at connect.comma.ai"); parser.addOption({{"a", "allow"}, "whitelist of services to send", "allow"}); parser.addOption({{"b", "block"}, "blacklist of services to send", "block"}); parser.addOption({{"c", "cache"}, "cache segments in memory. default is 5", "n"}); parser.addOption({{"s", "start"}, "start from ", "seconds"}); parser.addOption({"demo", "use a demo route instead of providing your own"}); parser.addOption({"data_dir", "local directory with routes", "data_dir"}); parser.addOption({"prefix", "set OPENPILOT_PREFIX", "prefix"}); for (auto &[name, _, desc] : flags) { parser.addOption({name, desc}); } parser.process(app); const QStringList args = parser.positionalArguments(); if (args.empty() && !parser.isSet("demo")) { parser.showHelp(); } const QString route = args.empty() ? DEMO_ROUTE : args.first(); QStringList allow = parser.value("allow").isEmpty() ? QStringList{} : parser.value("allow").split(","); QStringList block = parser.value("block").isEmpty() ? QStringList{} : parser.value("block").split(","); uint32_t replay_flags = REPLAY_FLAG_NONE; for (const auto &[name, flag, _] : flags) { if (parser.isSet(name)) { replay_flags |= flag; } } std::unique_ptr op_prefix; auto prefix = parser.value("prefix"); if (!prefix.isEmpty()) { op_prefix.reset(new OpenpilotPrefix(prefix.toStdString())); } Replay *replay = new Replay(route, allow, block, base_blacklist, nullptr, replay_flags, parser.value("data_dir"), &app); if (!parser.value("c").isEmpty()) { replay->setSegmentCacheLimit(parser.value("c").toInt()); } if (!replay->load()) { return 0; } ConsoleUI console_ui(replay); replay->start(parser.value("start").toInt()); return app.exec(); }