From dc406553ebade87ed95b6cc545598efedd67d49d Mon Sep 17 00:00:00 2001 From: Willem Melching Date: Tue, 9 Feb 2021 17:15:18 +0100 Subject: [PATCH] Cython wrapper for VisionIpc server (#117) * vipc cython wrapper * send some data * start listener * fix extra datatype --- SConscript | 3 +++ visionipc/.gitignore | 2 ++ visionipc/__init__.py | 0 visionipc/visionipc.pxd | 29 ++++++++++++++++++++++ visionipc/visionipc_pyx.pyx | 49 +++++++++++++++++++++++++++++++++++++ 5 files changed, 83 insertions(+) create mode 100644 visionipc/.gitignore create mode 100644 visionipc/__init__.py create mode 100644 visionipc/visionipc.pxd create mode 100644 visionipc/visionipc_pyx.pyx diff --git a/SConscript b/SConscript index ddc2fd4..100bd70 100644 --- a/SConscript +++ b/SConscript @@ -71,6 +71,9 @@ else: vipc_objects = env.SharedObject(vipc_sources) vipc = env.Library('visionipc', vipc_objects) +envCython.Program('visionipc/visionipc_pyx.so', 'visionipc/visionipc_pyx.pyx', LIBS=envCython["LIBS"]+["OpenCL", "zmq", vipc, messaging_lib]) + + if GetOption('test'): env.Program('messaging/test_runner', ['messaging/test_runner.cc', 'messaging/msgq_tests.cc'], LIBS=[messaging_lib]) env.Program('visionipc/test_runner', ['visionipc/test_runner.cc', 'visionipc/visionipc_tests.cc'], LIBS=[vipc, messaging_lib, 'zmq', 'pthread', 'OpenCL']) diff --git a/visionipc/.gitignore b/visionipc/.gitignore new file mode 100644 index 0000000..fa5a2b9 --- /dev/null +++ b/visionipc/.gitignore @@ -0,0 +1,2 @@ +visionipc_pyx.cpp +*.so diff --git a/visionipc/__init__.py b/visionipc/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/visionipc/visionipc.pxd b/visionipc/visionipc.pxd new file mode 100644 index 0000000..00a1776 --- /dev/null +++ b/visionipc/visionipc.pxd @@ -0,0 +1,29 @@ +# distutils: language = c++ +#cython: language_level=3 + +from libcpp.string cimport string +from libcpp.vector cimport vector +from libc.stdint cimport uint32_t, uint64_t +from libcpp cimport bool + +cdef extern from "visionbuf.h": + cdef enum VisionStreamType: + pass + + cdef cppclass VisionBuf: + void * addr + size_t len + +cdef extern from "visionipc.h": + struct VisionIpcBufExtra: + uint32_t frame_id + uint64_t timestamp_sof + uint64_t timestamp_eof + +cdef extern from "visionipc_server.h": + cdef cppclass VisionIpcServer: + VisionIpcServer(string, void*, void*) + void create_buffers(VisionStreamType, size_t, bool, size_t, size_t) + VisionBuf * get_buffer(VisionStreamType) + void send(VisionBuf *, VisionIpcBufExtra *, bool) + void start_listener() diff --git a/visionipc/visionipc_pyx.pyx b/visionipc/visionipc_pyx.pyx new file mode 100644 index 0000000..fb8eed0 --- /dev/null +++ b/visionipc/visionipc_pyx.pyx @@ -0,0 +1,49 @@ +# distutils: language = c++ +# cython: c_string_encoding=ascii, language_level=3 + +import sys +from libcpp.string cimport string +from libcpp cimport bool +from libc.string cimport memcpy +from libc.stdint cimport uint32_t, uint64_t + +from .visionipc cimport VisionIpcServer as cppVisionIpcServer +from .visionipc cimport VisionBuf as cppVisionBuf +from .visionipc cimport VisionIpcBufExtra + +cpdef enum VisionStreamType: + VISION_STREAM_RGB_BACK + VISION_STREAM_RGB_FRONT + VISION_STREAM_RGB_WIDE + VISION_STREAM_YUV_BACK + VISION_STREAM_YUV_FRONT + VISION_STREAM_YUV_WIDE + +cdef class VisionIpcServer: + cdef cppVisionIpcServer * server + + def __init__(self, string name): + self.server = new cppVisionIpcServer(name, NULL, NULL) + + def create_buffers(self, VisionStreamType tp, size_t num_buffers, bool rgb, size_t width, size_t height): + self.server.create_buffers(tp, num_buffers, rgb, width, height) + + def send(self, VisionStreamType tp, bytes data, uint32_t frame_id=0, uint64_t timestamp_sof=0, uint64_t timestamp_eof=0): + cdef cppVisionBuf * buf = self.server.get_buffer(tp) + + # Populate buffer + assert buf.len == len(data) + memcpy(buf.addr, data, len(data)) + + cdef VisionIpcBufExtra extra + extra.frame_id = frame_id + extra.timestamp_sof = timestamp_sof + extra.timestamp_eof = timestamp_eof + + self.server.send(buf, &extra, False) + + def start_listener(self): + self.server.start_listener() + + def __dealloc__(self): + del self.server