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.
 
 
 
 
 
 

132 lines
3.8 KiB

#include "selfdrive/ui/replay/filereader.h"
#include <bzlib.h>
#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);
BZ2_bzDecompressEnd(&strm);
dest.resize(strm.total_out_lo32);
return ret == BZ_STREAM_END;
}
// class FileReader
FileReader::FileReader(const QString &fn, QObject *parent) : url_(fn), QObject(parent) {}
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()));
}
} else {
startHttpRequest();
}
}
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;
});
}
void FileReader::abort() {
if (reply_) reply_->abort();
}
// class LogReader
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();
}
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";
}
auto insertEidx = [&](CameraType type, const cereal::EncodeIndex::Reader &e) {
eidx[type][e.getFrameId()] = {e.getSegmentNum(), e.getSegmentId()};
};
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;
}
words = kj::arrayPtr(evt->reader.getEnd(), words.end());
events.insert(evt->mono_time, evt.release());
} catch (const kj::Exception &e) {
valid_ = false;
break;
}
}
if (!exit_) {
emit finished(valid_);
}
}