diff --git a/Dockerfile b/Dockerfile index 38387ff..206329e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -37,7 +37,7 @@ ENV PATH="/root/.pyenv/bin:/root/.pyenv/shims:${PATH}" RUN pyenv install 3.8.5 && \ pyenv global 3.8.5 && \ pyenv rehash && \ - pip3 install --no-cache-dir pyyaml==5.1.2 Cython==0.29.14 scons==3.1.1 pycapnp==1.0.0 pre-commit==2.4.0 pylint==2.5.2 parameterized==0.7.4 coverage==5.1 + pip3 install --no-cache-dir pyyaml==5.1.2 Cython==0.29.14 scons==3.1.1 pycapnp==1.0.0 pre-commit==2.4.0 pylint==2.5.2 parameterized==0.7.4 coverage==5.1 numpy==1.21.1 WORKDIR /project/cereal/messaging RUN git clone https://github.com/catchorg/Catch2.git && \ diff --git a/SConstruct b/SConstruct index 8fecf84..8734312 100644 --- a/SConstruct +++ b/SConstruct @@ -2,6 +2,7 @@ import os import platform import subprocess import sysconfig +import numpy as np arch = subprocess.check_output(["uname", "-m"], encoding='utf8').rstrip() if platform.system() == "Darwin": @@ -59,6 +60,7 @@ env = Environment( Export('env', 'arch', 'common') envCython = env.Clone(LIBS=[]) +envCython["CPPPATH"] += [np.get_include()] envCython["CCFLAGS"] += ["-Wno-#warnings", "-Wno-deprecated-declarations"] if arch == "Darwin": envCython["LINKFLAGS"] = ["-bundle", "-undefined", "dynamic_lookup"] diff --git a/visionipc/visionipc.pxd b/visionipc/visionipc.pxd index 00a1776..554f812 100644 --- a/visionipc/visionipc.pxd +++ b/visionipc/visionipc.pxd @@ -13,6 +13,8 @@ cdef extern from "visionbuf.h": cdef cppclass VisionBuf: void * addr size_t len + size_t width + size_t height cdef extern from "visionipc.h": struct VisionIpcBufExtra: @@ -27,3 +29,9 @@ cdef extern from "visionipc_server.h": VisionBuf * get_buffer(VisionStreamType) void send(VisionBuf *, VisionIpcBufExtra *, bool) void start_listener() + +cdef extern from "visionipc_client.h": + cdef cppclass VisionIpcClient: + VisionIpcClient(string, VisionStreamType, bool, void*, void*) + VisionBuf * recv(VisionIpcBufExtra *, int) + bool connect(bool) diff --git a/visionipc/visionipc_pyx.pyx b/visionipc/visionipc_pyx.pyx index fb8eed0..e9c0556 100644 --- a/visionipc/visionipc_pyx.pyx +++ b/visionipc/visionipc_pyx.pyx @@ -2,12 +2,16 @@ # cython: c_string_encoding=ascii, language_level=3 import sys -from libcpp.string cimport string -from libcpp cimport bool +import numpy as np +cimport numpy as cnp +from cython.view cimport array from libc.string cimport memcpy from libc.stdint cimport uint32_t, uint64_t +from libcpp cimport bool +from libcpp.string cimport string from .visionipc cimport VisionIpcServer as cppVisionIpcServer +from .visionipc cimport VisionIpcClient as cppVisionIpcClient from .visionipc cimport VisionBuf as cppVisionBuf from .visionipc cimport VisionIpcBufExtra @@ -19,6 +23,7 @@ cpdef enum VisionStreamType: VISION_STREAM_YUV_FRONT VISION_STREAM_YUV_WIDE + cdef class VisionIpcServer: cdef cppVisionIpcServer * server @@ -47,3 +52,35 @@ cdef class VisionIpcServer: def __dealloc__(self): del self.server + + +cdef class VisionIpcClient: + cdef cppVisionBuf * buf + cdef cppVisionIpcClient * client + + def __cinit__(self, string name, VisionStreamType stream, bool conflate): + self.client = new cppVisionIpcClient(name, stream, conflate, NULL, NULL) + self.buf = NULL + + def __dealloc__(self): + del self.client + + @property + def width(self): + return 0 if not self.buf else self.buf.width + + @property + def height(self): + return 0 if not self.buf else self.buf.height + + def recv(self, int timeout_ms=100): + self.buf = self.client.recv(NULL, timeout_ms) + if not self.buf: + return None + cdef cnp.ndarray dat = np.empty(self.buf.len, dtype=np.uint8) + cdef char[:] dat_view = dat + memcpy(&dat_view[0], self.buf.addr, self.buf.len) + return dat + + def connect(self, bool blocking): + return self.client.connect(blocking)