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.
89 lines
2.5 KiB
89 lines
2.5 KiB
#include "tools/replay/camera.h"
|
|
#include "tools/replay/util.h"
|
|
|
|
#include <cassert>
|
|
|
|
CameraServer::CameraServer(std::pair<int, int> camera_size[MAX_CAMERAS]) {
|
|
for (int i = 0; i < MAX_CAMERAS; ++i) {
|
|
std::tie(cameras_[i].width, cameras_[i].height) = camera_size[i];
|
|
}
|
|
startVipcServer();
|
|
}
|
|
|
|
CameraServer::~CameraServer() {
|
|
for (auto &cam : cameras_) {
|
|
if (cam.thread.joinable()) {
|
|
cam.queue.push({});
|
|
cam.thread.join();
|
|
}
|
|
}
|
|
vipc_server_.reset(nullptr);
|
|
}
|
|
|
|
void CameraServer::startVipcServer() {
|
|
vipc_server_.reset(new VisionIpcServer("camerad"));
|
|
for (auto &cam : cameras_) {
|
|
if (cam.width > 0 && cam.height > 0) {
|
|
rInfo("camera[%d] frame size %dx%d", cam.type, cam.width, cam.height);
|
|
vipc_server_->create_buffers(cam.stream_type, YUV_BUFFER_COUNT, false, cam.width, cam.height);
|
|
if (!cam.thread.joinable()) {
|
|
cam.thread = std::thread(&CameraServer::cameraThread, this, std::ref(cam));
|
|
}
|
|
}
|
|
}
|
|
vipc_server_->start_listener();
|
|
}
|
|
|
|
void CameraServer::cameraThread(Camera &cam) {
|
|
auto read_frame = [&](FrameReader *fr, int frame_id) {
|
|
VisionBuf *yuv_buf = vipc_server_->get_buffer(cam.stream_type);
|
|
assert(yuv_buf);
|
|
bool ret = fr->get(frame_id, (uint8_t *)yuv_buf->addr);
|
|
return ret ? yuv_buf : nullptr;
|
|
};
|
|
|
|
while (true) {
|
|
const auto [fr, eidx] = cam.queue.pop();
|
|
if (!fr) break;
|
|
|
|
const int id = eidx.getSegmentId();
|
|
bool prefetched = (id == cam.cached_id && eidx.getSegmentNum() == cam.cached_seg);
|
|
auto yuv = prefetched ? cam.cached_buf : read_frame(fr, id);
|
|
if (yuv) {
|
|
VisionIpcBufExtra extra = {
|
|
.frame_id = eidx.getFrameId(),
|
|
.timestamp_sof = eidx.getTimestampSof(),
|
|
.timestamp_eof = eidx.getTimestampEof(),
|
|
};
|
|
yuv->set_frame_id(eidx.getFrameId());
|
|
vipc_server_->send(yuv, &extra);
|
|
} else {
|
|
rError("camera[%d] failed to get frame: %lu", cam.type, eidx.getSegmentId());
|
|
}
|
|
|
|
cam.cached_id = id + 1;
|
|
cam.cached_seg = eidx.getSegmentNum();
|
|
cam.cached_buf = read_frame(fr, cam.cached_id);
|
|
|
|
--publishing_;
|
|
}
|
|
}
|
|
|
|
void CameraServer::pushFrame(CameraType type, FrameReader *fr, const cereal::EncodeIndex::Reader &eidx) {
|
|
auto &cam = cameras_[type];
|
|
if (cam.width != fr->width || cam.height != fr->height) {
|
|
cam.width = fr->width;
|
|
cam.height = fr->height;
|
|
waitForSent();
|
|
startVipcServer();
|
|
}
|
|
|
|
++publishing_;
|
|
cam.queue.push({fr, eidx});
|
|
}
|
|
|
|
void CameraServer::waitForSent() {
|
|
while (publishing_ > 0) {
|
|
std::this_thread::yield();
|
|
}
|
|
}
|
|
|