|
|
|
@ -1,12 +1,13 @@ |
|
|
|
|
#include "tools/replay/camera.h" |
|
|
|
|
|
|
|
|
|
#include <capnp/dynamic.h> |
|
|
|
|
|
|
|
|
|
#include <cassert> |
|
|
|
|
|
|
|
|
|
#include "third_party/linux/include/msm_media_info.h" |
|
|
|
|
#include "tools/replay/util.h" |
|
|
|
|
|
|
|
|
|
const int BUFFER_COUNT = 40; |
|
|
|
|
|
|
|
|
|
std::tuple<size_t, size_t, size_t> get_nv12_info(int width, int height) { |
|
|
|
|
int nv12_width = VENUS_Y_STRIDE(COLOR_FMT_NV12, width); |
|
|
|
|
int nv12_height = VENUS_Y_SCANLINES(COLOR_FMT_NV12, height); |
|
|
|
@ -36,10 +37,12 @@ CameraServer::~CameraServer() { |
|
|
|
|
void CameraServer::startVipcServer() { |
|
|
|
|
vipc_server_.reset(new VisionIpcServer("camerad")); |
|
|
|
|
for (auto &cam : cameras_) { |
|
|
|
|
cam.cached_buf.clear(); |
|
|
|
|
|
|
|
|
|
if (cam.width > 0 && cam.height > 0) { |
|
|
|
|
rInfo("camera[%d] frame size %dx%d", cam.type, cam.width, cam.height); |
|
|
|
|
auto [nv12_width, nv12_height, nv12_buffer_size] = get_nv12_info(cam.width, cam.height); |
|
|
|
|
vipc_server_->create_buffers_with_sizes(cam.stream_type, YUV_BUFFER_COUNT, false, cam.width, cam.height, |
|
|
|
|
vipc_server_->create_buffers_with_sizes(cam.stream_type, BUFFER_COUNT, false, cam.width, cam.height, |
|
|
|
|
nv12_buffer_size, nv12_width, nv12_width * nv12_height); |
|
|
|
|
if (!cam.thread.joinable()) { |
|
|
|
|
cam.thread = std::thread(&CameraServer::cameraThread, this, std::ref(cam)); |
|
|
|
@ -50,13 +53,6 @@ void CameraServer::startVipcServer() { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
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, yuv_buf); |
|
|
|
|
return ret ? yuv_buf : nullptr; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
while (true) { |
|
|
|
|
const auto [fr, event] = cam.queue.pop(); |
|
|
|
|
if (!fr) break; |
|
|
|
@ -66,29 +62,41 @@ void CameraServer::cameraThread(Camera &cam) { |
|
|
|
|
auto eidx = capnp::AnyStruct::Reader(evt).getPointerSection()[0].getAs<cereal::EncodeIndex>(); |
|
|
|
|
if (eidx.getType() != cereal::EncodeIndex::Type::FULL_H_E_V_C) continue; |
|
|
|
|
|
|
|
|
|
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) { |
|
|
|
|
int segment_id = eidx.getSegmentId(); |
|
|
|
|
uint32_t frame_id = eidx.getFrameId(); |
|
|
|
|
if (auto yuv = getFrame(cam, fr, segment_id, frame_id)) { |
|
|
|
|
VisionIpcBufExtra extra = { |
|
|
|
|
.frame_id = eidx.getFrameId(), |
|
|
|
|
.frame_id = frame_id, |
|
|
|
|
.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()); |
|
|
|
|
rError("camera[%d] failed to get frame: %lu", cam.type, segment_id); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
cam.cached_id = id + 1; |
|
|
|
|
cam.cached_seg = eidx.getSegmentNum(); |
|
|
|
|
cam.cached_buf = read_frame(fr, cam.cached_id); |
|
|
|
|
// Prefetch the next frame
|
|
|
|
|
getFrame(cam, fr, segment_id + 1, frame_id + 1); |
|
|
|
|
|
|
|
|
|
--publishing_; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
VisionBuf *CameraServer::getFrame(Camera &cam, FrameReader *fr, int32_t segment_id, uint32_t frame_id) { |
|
|
|
|
// Check if the frame is cached
|
|
|
|
|
auto buf_it = std::find_if(cam.cached_buf.begin(), cam.cached_buf.end(), |
|
|
|
|
[frame_id](VisionBuf *buf) { return buf->get_frame_id() == frame_id; }); |
|
|
|
|
if (buf_it != cam.cached_buf.end()) return *buf_it; |
|
|
|
|
|
|
|
|
|
VisionBuf *yuv_buf = vipc_server_->get_buffer(cam.stream_type); |
|
|
|
|
if (fr->get(segment_id, yuv_buf)) { |
|
|
|
|
yuv_buf->set_frame_id(frame_id); |
|
|
|
|
cam.cached_buf.insert(yuv_buf); |
|
|
|
|
return yuv_buf; |
|
|
|
|
} |
|
|
|
|
return nullptr; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void CameraServer::pushFrame(CameraType type, FrameReader *fr, const Event *event) { |
|
|
|
|
auto &cam = cameras_[type]; |
|
|
|
|
if (cam.width != fr->width || cam.height != fr->height) { |
|
|
|
|