From 2b1a8f48f3a414e565cefb809f3e6a7c6aa5f8a7 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Wed, 6 Oct 2021 10:26:00 +0300 Subject: Split V4L2 code into separate libs Create v4l2++ library and pyv4l2, which are independent from the rest of the kms++. Signed-off-by: Tomi Valkeinen --- py/meson.build | 4 ++ py/pykms/meson.build | 1 - py/pykms/pykms.cpp | 3 - py/pykms/pyvid.cpp | 46 --------------- py/pyv4l2/__init__.py | 5 ++ py/pyv4l2/meson.build | 38 +++++++++++++ py/pyv4l2/pyv4l2.cpp | 153 ++++++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 200 insertions(+), 50 deletions(-) delete mode 100644 py/pykms/pyvid.cpp create mode 100644 py/pyv4l2/__init__.py create mode 100644 py/pyv4l2/meson.build create mode 100644 py/pyv4l2/pyv4l2.cpp (limited to 'py') diff --git a/py/meson.build b/py/meson.build index 3130bf2..fcba3e5 100644 --- a/py/meson.build +++ b/py/meson.build @@ -1 +1,5 @@ subdir('pykms') + +if get_option('v4l2').enabled() + subdir('pyv4l2') +endif diff --git a/py/pykms/meson.build b/py/pykms/meson.build index e030ce8..db5cbd0 100644 --- a/py/pykms/meson.build +++ b/py/pykms/meson.build @@ -19,7 +19,6 @@ pykms_sources = files([ if get_option('utils') pykms_sources += files([ 'pykmsutil.cpp', - 'pyvid.cpp', ]) endif diff --git a/py/pykms/pykms.cpp b/py/pykms/pykms.cpp index b91a1a9..e9266a4 100644 --- a/py/pykms/pykms.cpp +++ b/py/pykms/pykms.cpp @@ -9,7 +9,6 @@ using namespace std; void init_pykmstest(py::module& m); void init_pykmsbase(py::module& m); -void init_pyvid(py::module& m); #if HAS_LIBDRM_OMAP void init_pykmsomap(py::module& m); @@ -21,8 +20,6 @@ PYBIND11_MODULE(pykms, m) init_pykmstest(m); - init_pyvid(m); - #if HAS_LIBDRM_OMAP init_pykmsomap(m); #endif diff --git a/py/pykms/pyvid.cpp b/py/pykms/pyvid.cpp deleted file mode 100644 index 54ad480..0000000 --- a/py/pykms/pyvid.cpp +++ /dev/null @@ -1,46 +0,0 @@ -#include -#include -#include -#include -#include - -namespace py = pybind11; - -using namespace kms; -using namespace std; - -void init_pyvid(py::module& m) -{ - py::class_(m, "VideoDevice") - .def(py::init()) - .def_property_readonly("fd", &VideoDevice::fd) - .def_property_readonly("has_capture", &VideoDevice::has_capture) - .def_property_readonly("has_output", &VideoDevice::has_output) - .def_property_readonly("has_m2m", &VideoDevice::has_m2m) - .def_property_readonly("capture_streamer", &VideoDevice::get_capture_streamer) - .def_property_readonly("output_streamer", &VideoDevice::get_output_streamer) - .def_property_readonly("discrete_frame_sizes", &VideoDevice::get_discrete_frame_sizes) - .def_property_readonly("frame_sizes", &VideoDevice::get_frame_sizes) - .def("get_capture_devices", &VideoDevice::get_capture_devices); - - py::class_(m, "VideoStreamer") - .def_property_readonly("fd", &VideoStreamer::fd) - .def_property_readonly("ports", &VideoStreamer::get_ports) - .def("set_port", &VideoStreamer::set_port) - .def_property_readonly("formats", &VideoStreamer::get_formats) - .def("set_format", &VideoStreamer::set_format) - .def("get_selection", [](VideoStreamer* self) { - uint32_t left, top, width, height; - self->get_selection(left, top, width, height); - return make_tuple(left, top, width, height); - }) - .def("set_selection", [](VideoStreamer* self, uint32_t left, uint32_t top, uint32_t width, uint32_t height) { - self->set_selection(left, top, width, height); - return make_tuple(left, top, width, height); - }) - .def("set_queue_size", &VideoStreamer::set_queue_size) - .def("queue", &VideoStreamer::queue) - .def("dequeue", &VideoStreamer::dequeue) - .def("stream_on", &VideoStreamer::stream_on) - .def("stream_off", &VideoStreamer::stream_off); -} diff --git a/py/pyv4l2/__init__.py b/py/pyv4l2/__init__.py new file mode 100644 index 0000000..02541c5 --- /dev/null +++ b/py/pyv4l2/__init__.py @@ -0,0 +1,5 @@ +from .pyv4l2 import * +from enum import Enum +import os +import struct + diff --git a/py/pyv4l2/meson.build b/py/pyv4l2/meson.build new file mode 100644 index 0000000..03b0dcc --- /dev/null +++ b/py/pyv4l2/meson.build @@ -0,0 +1,38 @@ +py3_dep = dependency('python3', required : get_option('pyv4l2')) + +if py3_dep.found() == false + subdir_done() +endif + +pybind11_dep = dependency('pybind11', fallback : ['pybind11', 'pybind11_dep'], + required : get_option('pyv4l2')) + +if pybind11_dep.found() == false + subdir_done() +endif + +pyv4l2_sources = files([ + 'pyv4l2.cpp', +]) + +pyv4l2_deps = [ + libv4l2xx_dep, + py3_dep, + pybind11_dep, +] + +pyv4l2_args = [ '-fvisibility=hidden' ] + +destdir = get_option('libdir') / 'python' + py3_dep.version() / 'site-packages/pyv4l2' + +pyv4l2 = shared_module('pyv4l2', + pyv4l2_sources, + install : true, + install_dir : destdir, + name_prefix : '', + dependencies : pyv4l2_deps, + cpp_args : pyv4l2_args) + +# Copy __init__.py to build dir so that we can run without installing +configure_file(input: '__init__.py', output: '__init__.py', copy: true, + install : true, install_dir : destdir) diff --git a/py/pyv4l2/pyv4l2.cpp b/py/pyv4l2/pyv4l2.cpp new file mode 100644 index 0000000..ec96835 --- /dev/null +++ b/py/pyv4l2/pyv4l2.cpp @@ -0,0 +1,153 @@ +#include +#include +#include +#include + +namespace py = pybind11; + +using namespace v4l2; +using namespace std; + +PYBIND11_MODULE(pyv4l2, m) +{ + py::class_(m, "VideoDevice") + .def(py::init()) + .def_property_readonly("fd", &VideoDevice::fd) + .def_property_readonly("has_capture", &VideoDevice::has_capture) + .def_property_readonly("has_output", &VideoDevice::has_output) + .def_property_readonly("has_m2m", &VideoDevice::has_m2m) + .def_property_readonly("capture_streamer", &VideoDevice::get_capture_streamer) + .def_property_readonly("output_streamer", &VideoDevice::get_output_streamer) + .def_property_readonly("meta_capture_streamer", &VideoDevice::get_meta_capture_streamer) + .def_property_readonly("discrete_frame_sizes", &VideoDevice::get_discrete_frame_sizes) + .def_property_readonly("frame_sizes", &VideoDevice::get_frame_sizes) + .def("get_capture_devices", &VideoDevice::get_capture_devices); + + py::enum_(m, "VideoMemoryType") + .value("MMAP", VideoMemoryType::MMAP) + .value("DMABUF", VideoMemoryType::DMABUF) + ; + + m.def("create_dmabuffer", [](int fd) { + VideoBuffer buf {}; + buf.m_mem_type = VideoMemoryType::DMABUF; + buf.m_fd = fd; + return buf; + }); + + m.def("create_mmapbuffer", []() { + VideoBuffer buf {}; + buf.m_mem_type = VideoMemoryType::MMAP; + return buf; + }); + + py::class_(m, "VideoBuffer") + .def_readonly("index", &VideoBuffer::m_index) + .def_readonly("offset", &VideoBuffer::m_offset) + .def_readonly("fd", &VideoBuffer::m_fd) + .def_readonly("length", &VideoBuffer::m_length) + ; + + py::class_(m, "VideoStreamer") + .def_property_readonly("fd", &VideoStreamer::fd) + .def_property_readonly("ports", &VideoStreamer::get_ports) + .def("set_port", &VideoStreamer::set_port) + .def_property_readonly("formats", &VideoStreamer::get_formats) + .def("get_format", [](VideoStreamer* self) { + PixelFormat fmt; + uint32_t w, h; + + int r = self->get_format(fmt, w, h); + if (r) + throw std::system_error(errno, std::generic_category(), "get_format failed"); + + return make_tuple(w, h, fmt); + }) + .def("set_format", &VideoStreamer::set_format) + .def("get_selection", [](VideoStreamer* self) { + uint32_t left, top, width, height; + self->get_selection(left, top, width, height); + return make_tuple(left, top, width, height); + }) + .def("set_selection", [](VideoStreamer* self, uint32_t left, uint32_t top, uint32_t width, uint32_t height) { + self->set_selection(left, top, width, height); + return make_tuple(left, top, width, height); + }) + .def("set_queue_size", &VideoStreamer::set_queue_size) + .def("queue", &VideoStreamer::queue) + .def("dequeue", &VideoStreamer::dequeue) + .def("stream_on", &VideoStreamer::stream_on) + .def("stream_off", &VideoStreamer::stream_off); + + py::class_(m, "MetaStreamer") + .def_property_readonly("fd", &MetaStreamer::fd) + .def("set_format", &MetaStreamer::set_format) + .def("set_queue_size", &MetaStreamer::set_queue_size) + .def("queue", &MetaStreamer::queue) + .def("dequeue", &MetaStreamer::dequeue) + .def("stream_on", &MetaStreamer::stream_on) + .def("stream_off", &MetaStreamer::stream_off); + + py::enum_(m, "PixelFormat") + .value("Undefined", PixelFormat::Undefined) + + .value("NV12", PixelFormat::NV12) + .value("NV21", PixelFormat::NV21) + .value("NV16", PixelFormat::NV16) + .value("NV61", PixelFormat::NV61) + + .value("YUV420", PixelFormat::YUV420) + .value("YVU420", PixelFormat::YVU420) + .value("YUV422", PixelFormat::YUV422) + .value("YVU422", PixelFormat::YVU422) + .value("YUV444", PixelFormat::YUV444) + .value("YVU444", PixelFormat::YVU444) + + .value("UYVY", PixelFormat::UYVY) + .value("YUYV", PixelFormat::YUYV) + .value("YVYU", PixelFormat::YVYU) + .value("VYUY", PixelFormat::VYUY) + + .value("XRGB8888", PixelFormat::XRGB8888) + .value("XBGR8888", PixelFormat::XBGR8888) + .value("RGBX8888", PixelFormat::RGBX8888) + .value("BGRX8888", PixelFormat::BGRX8888) + + .value("ARGB8888", PixelFormat::ARGB8888) + .value("ABGR8888", PixelFormat::ABGR8888) + .value("RGBA8888", PixelFormat::RGBA8888) + .value("BGRA8888", PixelFormat::BGRA8888) + + .value("RGB888", PixelFormat::RGB888) + .value("BGR888", PixelFormat::BGR888) + + .value("RGB332", PixelFormat::RGB332) + + .value("RGB565", PixelFormat::RGB565) + .value("BGR565", PixelFormat::BGR565) + + .value("XRGB4444", PixelFormat::XRGB4444) + .value("XRGB1555", PixelFormat::XRGB1555) + + .value("ARGB4444", PixelFormat::ARGB4444) + .value("ARGB1555", PixelFormat::ARGB1555) + + .value("XRGB2101010", PixelFormat::XRGB2101010) + .value("XBGR2101010", PixelFormat::XBGR2101010) + .value("RGBX1010102", PixelFormat::RGBX1010102) + .value("BGRX1010102", PixelFormat::BGRX1010102) + + .value("ARGB2101010", PixelFormat::ARGB2101010) + .value("ABGR2101010", PixelFormat::ABGR2101010) + .value("RGBA1010102", PixelFormat::RGBA1010102) + .value("BGRA1010102", PixelFormat::BGRA1010102) + + .value("SBGGR12", PixelFormat::SBGGR12) + .value("SRGGB12", PixelFormat::SRGGB12) + + .value("META_8", PixelFormat::META_8) + .value("META_16", PixelFormat::META_16); + + + m.def("fourcc_to_pixelformat", &FourCCToPixelFormat); +} -- cgit v1.2.3