#include #include #include #include #include #include #include #include #include #include #include "ipc.h" #include "visionipc.h" typedef struct VisionPacketWire { int type; VisionPacketData d; } VisionPacketWire; int vipc_connect() { return ipc_connect(VIPC_SOCKET_PATH); } int vipc_recv(int fd, VisionPacket *out_p) { VisionPacketWire p = {0}; VisionPacket p2 = {0}; int ret = ipc_sendrecv_with_fds(false, fd, &p, sizeof(p), (int*)p2.fds, VIPC_MAX_FDS, &p2.num_fds); if (ret < 0) { printf("vipc_recv err: %s\n", strerror(errno)); } else { p2.type = p.type; p2.d = p.d; *out_p = p2; } //printf("%d = vipc_recv(%d, %d): %d %d %d %zu\n", ret, fd, p2.num_fds, out_p->d.stream_bufs.type, out_p->d.stream_bufs.width, out_p->d.stream_bufs.height, out_p->d.stream_bufs.buf_len); return ret; } int vipc_send(int fd, const VisionPacket *p2) { assert(p2->num_fds <= VIPC_MAX_FDS); VisionPacketWire p = { .type = p2->type, .d = p2->d, }; int ret = ipc_sendrecv_with_fds(true, fd, (void*)&p, sizeof(p), (int*)p2->fds, p2->num_fds, NULL); //printf("%d = vipc_send(%d, %d): %d %d %d %zu\n", ret, fd, p2->num_fds, p2->d.stream_bufs.type, p2->d.stream_bufs.width, p2->d.stream_bufs.height, p2->d.stream_bufs.buf_len); return ret; } void vipc_bufs_load(VIPCBuf *bufs, const VisionStreamBufs *stream_bufs, int num_fds, const int* fds) { for (int i=0; ibuf_len; bufs[i].addr = mmap(NULL, bufs[i].len, PROT_READ | PROT_WRITE, MAP_SHARED, bufs[i].fd, 0); // printf("b %d %zu -> %p\n", bufs[i].fd, bufs[i].len, bufs[i].addr); assert(bufs[i].addr != MAP_FAILED); } } int visionstream_init(VisionStream *s, VisionStreamType type, bool tbuffer, VisionStreamBufs *out_bufs_info) { int err; memset(s, 0, sizeof(*s)); s->last_idx = -1; s->ipc_fd = vipc_connect(); if (s->ipc_fd < 0) return -1; VisionPacket p = { .type = VIPC_STREAM_SUBSCRIBE, .d = { .stream_sub = { .type = type, .tbuffer = tbuffer, }, }, }; err = vipc_send(s->ipc_fd, &p); if (err < 0) { close(s->ipc_fd); return -1; } VisionPacket rp; err = vipc_recv(s->ipc_fd, &rp); if (err <= 0) { close(s->ipc_fd); return -1; } assert(rp.type == VIPC_STREAM_BUFS); assert(rp.d.stream_bufs.type == type); s->bufs_info = rp.d.stream_bufs; s->num_bufs = rp.num_fds; s->bufs = calloc(s->num_bufs, sizeof(VIPCBuf)); assert(s->bufs); vipc_bufs_load(s->bufs, &rp.d.stream_bufs, s->num_bufs, rp.fds); if (out_bufs_info) { *out_bufs_info = s->bufs_info; } return 0; } void visionstream_release(VisionStream *s) { int err; if (s->last_idx >= 0) { VisionPacket rep = { .type = VIPC_STREAM_RELEASE, .d = { .stream_rel = { .type = s->last_type, .idx = s->last_idx, }} }; err = vipc_send(s->ipc_fd, &rep); s->last_idx = -1; } } VIPCBuf* visionstream_get(VisionStream *s, VIPCBufExtra *out_extra) { int err; VisionPacket rp; err = vipc_recv(s->ipc_fd, &rp); if (err <= 0) { return NULL; } assert(rp.type == VIPC_STREAM_ACQUIRE); if (s->last_idx >= 0) { VisionPacket rep = { .type = VIPC_STREAM_RELEASE, .d = { .stream_rel = { .type = s->last_type, .idx = s->last_idx, }} }; err = vipc_send(s->ipc_fd, &rep); if (err <= 0) { return NULL; } } s->last_type = rp.d.stream_acq.type; s->last_idx = rp.d.stream_acq.idx; assert(s->last_idx < s->num_bufs); if (out_extra) { *out_extra = rp.d.stream_acq.extra; } return &s->bufs[s->last_idx]; } void visionstream_destroy(VisionStream *s) { int err; if (s->last_idx >= 0) { VisionPacket rep = { .type = VIPC_STREAM_RELEASE, .d = { .stream_rel = { .type = s->last_type, .idx = s->last_idx, }} }; err = vipc_send(s->ipc_fd, &rep); s->last_idx = -1; } for (int i=0; inum_bufs; i++) { if (s->bufs[i].addr) { munmap(s->bufs[i].addr, s->bufs[i].len); s->bufs[i].addr = NULL; close(s->bufs[i].fd); } } if (s->bufs) free(s->bufs); close(s->ipc_fd); }