|  |  | @ -1,12 +1,13 @@ | 
			
		
	
		
		
			
				
					
					|  |  |  | #include "tools/replay/camera.h" |  |  |  | #include "tools/replay/camera.h" | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | #include <capnp/dynamic.h> |  |  |  | #include <capnp/dynamic.h> | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | #include <cassert> |  |  |  | #include <cassert> | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | #include "third_party/linux/include/msm_media_info.h" |  |  |  | #include "third_party/linux/include/msm_media_info.h" | 
			
		
	
		
		
			
				
					
					|  |  |  | #include "tools/replay/util.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) { |  |  |  | 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_width = VENUS_Y_STRIDE(COLOR_FMT_NV12, width); | 
			
		
	
		
		
			
				
					
					|  |  |  |   int nv12_height = VENUS_Y_SCANLINES(COLOR_FMT_NV12, height); |  |  |  |   int nv12_height = VENUS_Y_SCANLINES(COLOR_FMT_NV12, height); | 
			
		
	
	
		
		
			
				
					|  |  | @ -36,10 +37,12 @@ CameraServer::~CameraServer() { | 
			
		
	
		
		
			
				
					
					|  |  |  | void CameraServer::startVipcServer() { |  |  |  | void CameraServer::startVipcServer() { | 
			
		
	
		
		
			
				
					
					|  |  |  |   vipc_server_.reset(new VisionIpcServer("camerad")); |  |  |  |   vipc_server_.reset(new VisionIpcServer("camerad")); | 
			
		
	
		
		
			
				
					
					|  |  |  |   for (auto &cam : cameras_) { |  |  |  |   for (auto &cam : cameras_) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     cam.cached_buf.clear(); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     if (cam.width > 0 && cam.height > 0) { |  |  |  |     if (cam.width > 0 && cam.height > 0) { | 
			
		
	
		
		
			
				
					
					|  |  |  |       rInfo("camera[%d] frame size %dx%d", cam.type, cam.width, cam.height); |  |  |  |       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); |  |  |  |       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); |  |  |  |                                               nv12_buffer_size, nv12_width, nv12_width * nv12_height); | 
			
		
	
		
		
			
				
					
					|  |  |  |       if (!cam.thread.joinable()) { |  |  |  |       if (!cam.thread.joinable()) { | 
			
		
	
		
		
			
				
					
					|  |  |  |         cam.thread = std::thread(&CameraServer::cameraThread, this, std::ref(cam)); |  |  |  |         cam.thread = std::thread(&CameraServer::cameraThread, this, std::ref(cam)); | 
			
		
	
	
		
		
			
				
					|  |  | @ -50,13 +53,6 @@ void CameraServer::startVipcServer() { | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | void CameraServer::cameraThread(Camera &cam) { |  |  |  | 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) { |  |  |  |   while (true) { | 
			
		
	
		
		
			
				
					
					|  |  |  |     const auto [fr, event] = cam.queue.pop(); |  |  |  |     const auto [fr, event] = cam.queue.pop(); | 
			
		
	
		
		
			
				
					
					|  |  |  |     if (!fr) break; |  |  |  |     if (!fr) break; | 
			
		
	
	
		
		
			
				
					|  |  | @ -66,29 +62,41 @@ void CameraServer::cameraThread(Camera &cam) { | 
			
		
	
		
		
			
				
					
					|  |  |  |     auto eidx = capnp::AnyStruct::Reader(evt).getPointerSection()[0].getAs<cereal::EncodeIndex>(); |  |  |  |     auto eidx = capnp::AnyStruct::Reader(evt).getPointerSection()[0].getAs<cereal::EncodeIndex>(); | 
			
		
	
		
		
			
				
					
					|  |  |  |     if (eidx.getType() != cereal::EncodeIndex::Type::FULL_H_E_V_C) continue; |  |  |  |     if (eidx.getType() != cereal::EncodeIndex::Type::FULL_H_E_V_C) continue; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     const int id = eidx.getSegmentId(); |  |  |  |     int segment_id = eidx.getSegmentId(); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     bool prefetched = (id == cam.cached_id && eidx.getSegmentNum() == cam.cached_seg); |  |  |  |     uint32_t frame_id = eidx.getFrameId(); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     auto yuv = prefetched ? cam.cached_buf : read_frame(fr, id); |  |  |  |     if (auto yuv = getFrame(cam, fr, segment_id, frame_id)) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     if (yuv) { |  |  |  |  | 
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |       VisionIpcBufExtra extra = { |  |  |  |       VisionIpcBufExtra extra = { | 
			
		
	
		
		
			
				
					
					|  |  |  |           .frame_id = eidx.getFrameId(), |  |  |  |           .frame_id = frame_id, | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |           .timestamp_sof = eidx.getTimestampSof(), |  |  |  |           .timestamp_sof = eidx.getTimestampSof(), | 
			
		
	
		
		
			
				
					
					|  |  |  |           .timestamp_eof = eidx.getTimestampEof(), |  |  |  |           .timestamp_eof = eidx.getTimestampEof(), | 
			
		
	
		
		
			
				
					
					|  |  |  |       }; |  |  |  |       }; | 
			
		
	
		
		
			
				
					
					|  |  |  |       yuv->set_frame_id(eidx.getFrameId()); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |       vipc_server_->send(yuv, &extra); |  |  |  |       vipc_server_->send(yuv, &extra); | 
			
		
	
		
		
			
				
					
					|  |  |  |     } else { |  |  |  |     } 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; |  |  |  |     // Prefetch the next frame
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     cam.cached_seg = eidx.getSegmentNum(); |  |  |  |     getFrame(cam, fr, segment_id + 1, frame_id + 1); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     cam.cached_buf = read_frame(fr, cam.cached_id); |  |  |  |  | 
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     --publishing_; |  |  |  |     --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) { |  |  |  | void CameraServer::pushFrame(CameraType type, FrameReader *fr, const Event *event) { | 
			
		
	
		
		
			
				
					
					|  |  |  |   auto &cam = cameras_[type]; |  |  |  |   auto &cam = cameras_[type]; | 
			
		
	
		
		
			
				
					
					|  |  |  |   if (cam.width != fr->width || cam.height != fr->height) { |  |  |  |   if (cam.width != fr->width || cam.height != fr->height) { | 
			
		
	
	
		
		
			
				
					|  |  | 
 |