Skip to content

Commit 65be002

Browse files
committed
fix seek cross-boundary
1 parent 589f789 commit 65be002

File tree

3 files changed

+69
-70
lines changed

3 files changed

+69
-70
lines changed

selfdrive/ui/replay/replay.cc

+5-1
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,10 @@ void Replay::mergeSegments(int cur_seg, int end_idx) {
178178
return std::find(segments_merged_.begin(), segments_merged_.end(), cur_seg) != segments_merged_.end();
179179
});
180180
delete prev_events;
181+
} else {
182+
updateEvents([&]() {
183+
return !segments_merged_.empty();
184+
});
181185
}
182186

183187
// free segments out of current semgnt window.
@@ -195,14 +199,14 @@ void Replay::stream() {
195199
std::unique_lock lk(lock_);
196200

197201
while (true) {
198-
qDebug() << "waiting for events...";
199202
stream_cv_.wait(lk, [=]() { return exit_ || (events_updated_ && !paused_); });
200203
events_updated_ = false;
201204
if (exit_) break;
202205

203206
Event cur_event(cur_which, cur_mono_time_);
204207
auto eit = std::upper_bound(events_->begin(), events_->end(), &cur_event, Event::lessThan());
205208
if (eit == events_->end()) {
209+
qDebug() << "waiting for events...";
206210
continue;
207211
}
208212

selfdrive/ui/replay/route.cc

+1-1
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ Route::Route(const QString &route) : route_(route) {}
120120

121121
bool Route::load() {
122122
QEventLoop loop;
123-
auto onError = [&loop](const QString &err) { qInfo() << err; };
123+
auto onError = [&loop](const QString &err) { loop.quit(); };
124124

125125
bool ret = false;
126126
HttpRequest http(nullptr, !Hardware::PC());

selfdrive/ui/replay/tests/test_replay.cc

+63-68
Original file line numberDiff line numberDiff line change
@@ -29,27 +29,27 @@ const char *stream_url = "https://commadataci.blob.core.windows.net/openpilotci/
2929
// }
3030
// }
3131

32-
// std::string sha_256(const QString &dat) {
33-
// return QString(QCryptographicHash::hash(dat.toUtf8(), QCryptographicHash::Sha256).toHex()).toStdString();
34-
// }
32+
std::string sha_256(const QString &dat) {
33+
return QString(QCryptographicHash::hash(dat.toUtf8(), QCryptographicHash::Sha256).toHex()).toStdString();
34+
}
3535

36-
// TEST_CASE("httpMultiPartDownload") {
37-
// char filename[] = "/tmp/XXXXXX";
38-
// int fd = mkstemp(filename);
39-
// REQUIRE(fd != -1);
40-
// close(fd);
41-
42-
// SECTION("http 200") {
43-
// REQUIRE(httpMultiPartDownload(stream_url, filename, 5));
44-
// std::string content = util::read_file(filename);
45-
// REQUIRE(content.size() == 37495242);
46-
// std::string checksum = sha_256(QString::fromStdString(content));
47-
// REQUIRE(checksum == "d8ff81560ce7ed6f16d5fb5a6d6dd13aba06c8080c62cfe768327914318744c4");
48-
// }
49-
// SECTION("http 404") {
50-
// REQUIRE(httpMultiPartDownload(util::string_format("%s_abc", stream_url), filename, 5) == false);
51-
// }
52-
// }
36+
TEST_CASE("httpMultiPartDownload") {
37+
char filename[] = "/tmp/XXXXXX";
38+
int fd = mkstemp(filename);
39+
REQUIRE(fd != -1);
40+
close(fd);
41+
42+
SECTION("http 200") {
43+
REQUIRE(httpMultiPartDownload(stream_url, filename, 5));
44+
std::string content = util::read_file(filename);
45+
REQUIRE(content.size() == 37495242);
46+
std::string checksum = sha_256(QString::fromStdString(content));
47+
REQUIRE(checksum == "d8ff81560ce7ed6f16d5fb5a6d6dd13aba06c8080c62cfe768327914318744c4");
48+
}
49+
SECTION("http 404") {
50+
REQUIRE(httpMultiPartDownload(util::string_format("%s_abc", stream_url), filename, 5) == false);
51+
}
52+
}
5353

5454
int random_int(int min, int max) {
5555
std::random_device dev;
@@ -73,35 +73,34 @@ bool is_events_ordered(const std::vector<Event *> &events) {
7373
}
7474

7575
const QString DEMO_ROUTE = "4cf7a6ad03080c90|2021-09-29--13-46-36";
76-
// Route demo_route(DEMO_ROUTE);
77-
78-
// TEST_CASE("Segment") {
79-
// REQUIRE(demo_route.load());
80-
// REQUIRE(demo_route.size() == 121);
81-
82-
// QEventLoop loop;
83-
// Segment segment(0, demo_route.at(0), false, false);
84-
// REQUIRE(segment.isValid() == true);
85-
// REQUIRE(segment.isLoaded() == false);
86-
// QObject::connect(&segment, &Segment::loadFinished, [&]() {
87-
// REQUIRE(segment.isLoaded() == true);
88-
// REQUIRE(segment.log != nullptr);
89-
// REQUIRE(segment.log->events.size() > 0);
90-
// REQUIRE(is_events_ordered(segment.log->events));
91-
// REQUIRE(segment.frames[RoadCam] != nullptr);
92-
// REQUIRE(segment.frames[RoadCam]->getFrameCount() > 0);
93-
// REQUIRE(segment.frames[DriverCam] == nullptr);
94-
// REQUIRE(segment.frames[WideRoadCam] == nullptr);
95-
// loop.quit();
96-
// });
97-
// loop.exec();
98-
// }
76+
77+
TEST_CASE("Segment") {
78+
Route demo_route(DEMO_ROUTE);
79+
REQUIRE(demo_route.load());
80+
REQUIRE(demo_route.size() == 121);
81+
82+
QEventLoop loop;
83+
Segment segment(0, demo_route.at(0), false, false);
84+
REQUIRE(segment.isValid() == true);
85+
REQUIRE(segment.isLoaded() == false);
86+
QObject::connect(&segment, &Segment::loadFinished, [&]() {
87+
REQUIRE(segment.isLoaded() == true);
88+
REQUIRE(segment.log != nullptr);
89+
REQUIRE(segment.log->events.size() > 0);
90+
REQUIRE(is_events_ordered(segment.log->events));
91+
REQUIRE(segment.frames[RoadCam] != nullptr);
92+
REQUIRE(segment.frames[RoadCam]->getFrameCount() > 0);
93+
REQUIRE(segment.frames[DriverCam] == nullptr);
94+
REQUIRE(segment.frames[WideRoadCam] == nullptr);
95+
loop.quit();
96+
});
97+
loop.exec();
98+
}
9999

100100
// helper class for unit tests
101101
class TestReplay : public Replay {
102102
public:
103-
TestReplay(const QString &route) : Replay(route, {}, {}) {
104-
}
103+
TestReplay(const QString &route) : Replay(route, {}, {}) {}
105104
void test_seek();
106105

107106
protected:
@@ -118,49 +117,46 @@ void TestReplay::testSeekTo(int seek_to, int invalid_segment) {
118117

119118
// verify result
120119
INFO("seek to [" << seek_to << "s segment " << seek_to / 60 << "]");
121-
INFO("events size " << events_->size());
122-
// INFO("mono" << (cur_mono_time_ - route_start_ts_) / 1e9);
123120
REQUIRE(is_events_ordered(*events_));
124121
REQUIRE(uint64_t(route_start_ts_ + seek_to * 1e9) == cur_mono_time_);
125122
REQUIRE(!events_->empty());
126123
Event cur_event(cereal::Event::Which::INIT_DATA, cur_mono_time_);
127124
auto eit = std::upper_bound(events_->begin(), events_->end(), &cur_event, Event::lessThan());
128-
125+
129126
REQUIRE(eit != events_->end());
130127
const int seek_to_segment = seek_to / 60;
131-
const int real_segment = int(((*eit)->mono_time - route_start_ts_) / 60 / 1e9);
132-
INFO("event [" << ((*eit)->mono_time - route_start_ts_) / 1e9 << "s segment " << real_segment << "]");
128+
current_segment_ = int(((*eit)->mono_time - route_start_ts_) / 60 / 1e9);
129+
INFO("event [" << ((*eit)->mono_time - route_start_ts_) / 1e9 << "s segment " << current_segment_ << "]");
133130
REQUIRE((*eit)->mono_time >= seek_to * 1e9 + route_start_ts_);
134131
if (seek_to_segment != invalid_segment) {
135-
REQUIRE(real_segment == seek_to_segment); // in the same segment
132+
REQUIRE(current_segment_ == seek_to_segment); // in the same segment
136133
} else {
137-
// skipped invalid_segment
138-
REQUIRE(real_segment == seek_to_segment + 1);
139-
134+
// has invalid_segment
135+
if (current_segment_ == seek_to_segment) {
136+
// seek cross-boundary. e.g. seek_to 60s, but the first segment end at 60.021.
137+
REQUIRE(std::nearbyint(((*eit)->mono_time - route_start_ts_)/1e9) == seek_to);
138+
} else {
139+
REQUIRE(current_segment_ == seek_to_segment + 1);
140+
}
140141
}
141142
}
142143

143144
void TestReplay::test_seek() {
144145
QEventLoop loop;
145146

146-
REQUIRE(load());
147-
// // limit the segment count to 5
148-
// REQUIRE(route_->size() >= 5);
149-
// segments_.resize(5);
150-
151147
std::thread thread = std::thread([&]() {
152148
// random seek 500 times in first 3 good segments
153149
for (int i = 0; i < 200; ++i) {
154150
testSeekTo(random_int(0, 60 * 3 - 1));
155151
}
156152

157-
// make segment 1 invalid
158-
// segments_[1]->valid_ = segments_[1]->loaded_ = false;
159-
// queueSegment();
160-
// // random seek 200 times
161-
// for (int i = 0; i < 200; ++i) {
162-
// testSeekTo(random_int(0, 60 * 3 - 1), 1);
163-
// }
153+
// random seek 200 times in first 3 segments.segment 1 is invalid.
154+
// invalid segmen 1
155+
segments_[1]->valid_ = segments_[1]->loaded_ = false;
156+
queueSegment();
157+
for (int i = 0; i < 200; ++i) {
158+
testSeekTo(random_int(0, 60 * 3 - 1), 1);
159+
}
164160

165161
loop.quit();
166162
});
@@ -171,7 +167,6 @@ void TestReplay::test_seek() {
171167

172168
TEST_CASE("Replay") {
173169
TestReplay replay(DEMO_ROUTE);
174-
// REQUIRE(replay.load());
175-
// modify the route
170+
REQUIRE(replay.load());
176171
replay.test_seek();
177172
}

0 commit comments

Comments
 (0)