openpilot is an open source driver assistance system. openpilot performs the functions of Automated Lane Centering and Adaptive Cruise Control for over 200 supported car makes and models.
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.

133 lines
3.8 KiB

#include "selfdrive/ui/replay/filereader.h"
5 years ago
#include <bzlib.h>
5 years ago
#include <QtNetwork>
static bool decompressBZ2(std::vector<uint8_t> &dest, const char srcData[], size_t srcSize,
size_t outputSizeIncrement = 0x100000U) {
bz_stream strm = {};
int ret = BZ2_bzDecompressInit(&strm, 0, 0);
assert(ret == BZ_OK);
strm.next_in = const_cast<char *>(srcData);
strm.avail_in = srcSize;
do {
strm.next_out = (char *)&dest[strm.total_out_lo32];
strm.avail_out = dest.size() - strm.total_out_lo32;
ret = BZ2_bzDecompress(&strm);
if (ret == BZ_OK && strm.avail_in > 0 && strm.avail_out == 0) {
dest.resize(dest.size() + outputSizeIncrement);
}
} while (ret == BZ_OK);
5 years ago
BZ2_bzDecompressEnd(&strm);
dest.resize(strm.total_out_lo32);
return ret == BZ_STREAM_END;
5 years ago
}
// class FileReader
5 years ago
FileReader::FileReader(const QString &fn, QObject *parent) : url_(fn), QObject(parent) {}
5 years ago
void FileReader::read() {
if (url_.isLocalFile()) {
QFile file(url_.toLocalFile());
if (file.open(QIODevice::ReadOnly)) {
emit finished(file.readAll());
} else {
emit failed(QString("Failed to read file %1").arg(url_.toString()));
}
5 years ago
} else {
startHttpRequest();
5 years ago
}
}
void FileReader::startHttpRequest() {
QNetworkAccessManager *qnam = new QNetworkAccessManager(this);
QNetworkRequest request(url_);
request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
reply_ = qnam->get(request);
connect(reply_, &QNetworkReply::finished, [=]() {
if (!reply_->error()) {
emit finished(reply_->readAll());
} else {
emit failed(reply_->errorString());
}
reply_->deleteLater();
reply_ = nullptr;
});
5 years ago
}
void FileReader::abort() {
if (reply_) reply_->abort();
5 years ago
}
// class LogReader
5 years ago
LogReader::LogReader(const QString &file, QObject *parent) : QObject(parent) {
file_reader_ = new FileReader(file);
file_reader_->moveToThread(&thread_);
connect(&thread_, &QThread::started, file_reader_, &FileReader::read);
connect(&thread_, &QThread::finished, file_reader_, &FileReader::deleteLater);
connect(file_reader_, &FileReader::finished, [=](const QByteArray &dat) {
parseEvents(dat);
});
connect(file_reader_, &FileReader::failed, [=](const QString &err) {
qDebug() << err;
});
thread_.start();
5 years ago
}
LogReader::~LogReader() {
// wait until thread is finished.
exit_ = true;
file_reader_->abort();
thread_.quit();
thread_.wait();
// clear events
for (auto e : events) {
delete e;
}
}
void LogReader::parseEvents(const QByteArray &dat) {
raw_.resize(1024 * 1024 * 64);
if (!decompressBZ2(raw_, dat.data(), dat.size())) {
qWarning() << "bz2 decompress failed";
}
5 years ago
auto insertEidx = [&](CameraType type, const cereal::EncodeIndex::Reader &e) {
eidx[type][e.getFrameId()] = {e.getSegmentNum(), e.getSegmentId()};
};
5 years ago
valid_ = true;
kj::ArrayPtr<const capnp::word> words((const capnp::word *)raw_.data(), raw_.size() / sizeof(capnp::word));
while (!exit_ && words.size() > 0) {
try {
std::unique_ptr<Event> evt = std::make_unique<Event>(words);
switch (evt->which) {
case cereal::Event::ROAD_ENCODE_IDX:
insertEidx(RoadCam, evt->event.getRoadEncodeIdx());
break;
case cereal::Event::DRIVER_ENCODE_IDX:
insertEidx(DriverCam, evt->event.getDriverEncodeIdx());
break;
case cereal::Event::WIDE_ROAD_ENCODE_IDX:
insertEidx(WideRoadCam, evt->event.getWideRoadEncodeIdx());
break;
default:
break;
5 years ago
}
words = kj::arrayPtr(evt->reader.getEnd(), words.end());
events.insert(evt->mono_time, evt.release());
} catch (const kj::Exception &e) {
valid_ = false;
5 years ago
break;
}
}
if (!exit_) {
emit finished(valid_);
5 years ago
}
}