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 --- v4l2++/inc/v4l2++/helpers.h | 60 ++++++++++++++++++ v4l2++/inc/v4l2++/pixelformats.h | 111 ++++++++++++++++++++++++++++++++++ v4l2++/inc/v4l2++/videodevice.h | 127 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 298 insertions(+) create mode 100644 v4l2++/inc/v4l2++/helpers.h create mode 100644 v4l2++/inc/v4l2++/pixelformats.h create mode 100644 v4l2++/inc/v4l2++/videodevice.h (limited to 'v4l2++/inc') diff --git a/v4l2++/inc/v4l2++/helpers.h b/v4l2++/inc/v4l2++/helpers.h new file mode 100644 index 0000000..b5c3284 --- /dev/null +++ b/v4l2++/inc/v4l2++/helpers.h @@ -0,0 +1,60 @@ +#pragma once + +#include + +#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) + +#define unlikely(x) __builtin_expect(!!(x), 0) + +/* __STRING(x) is a glibcism (i.e. not standard), which happens to also + * be available in uClibc. However, musl does not define it. Do it here. + */ +#ifndef __STRING +#define __STRING(x) #x +#endif + +#define ASSERT(x) \ + if (unlikely(!(x))) { \ + fprintf(stderr, "%s:%d: %s: ASSERT(%s) failed\n", __FILE__, __LINE__, __PRETTY_FUNCTION__, __STRING(x)); \ + abort(); \ + } + +#define FAIL(fmt, ...) \ + do { \ + fprintf(stderr, "%s:%d: %s:\n" fmt "\n", __FILE__, __LINE__, __PRETTY_FUNCTION__, ##__VA_ARGS__); \ + abort(); \ + } while (0) + +#define FAIL_IF(x, format, ...) \ + if (unlikely(x)) { \ + fprintf(stderr, "%s:%d: %s:\n" format "\n", __FILE__, __LINE__, __PRETTY_FUNCTION__, ##__VA_ARGS__); \ + abort(); \ + } + +#define EXIT(fmt, ...) \ + do { \ + fprintf(stderr, fmt "\n", ##__VA_ARGS__); \ + exit(-1); \ + } while (0) + +#define EXIT_IF(x, fmt, ...) \ + if (unlikely(x)) { \ + fprintf(stderr, fmt "\n", ##__VA_ARGS__); \ + exit(-1); \ + } + +void __my_throw(const char* file, int line, const char* funcname, const char* cond, fmt::string_view format, fmt::format_args args); + +template +void _my_throw(const char* file, int line, const char* funcname, const char* cond, const S& format, Args&&... args) +{ + __my_throw(file, line, funcname, cond, format, fmt::make_format_args(args...)); +} + +#define THROW(format, ...) \ + _my_throw(__FILE__, __LINE__, __PRETTY_FUNCTION__, nullptr, format, ##__VA_ARGS__); + +#define THROW_IF(x, format, ...) \ + if (unlikely(x)) { \ + _my_throw(__FILE__, __LINE__, __PRETTY_FUNCTION__, #x, format, ##__VA_ARGS__); \ + } diff --git a/v4l2++/inc/v4l2++/pixelformats.h b/v4l2++/inc/v4l2++/pixelformats.h new file mode 100644 index 0000000..609ff4f --- /dev/null +++ b/v4l2++/inc/v4l2++/pixelformats.h @@ -0,0 +1,111 @@ +#pragma once + +#include +#include +#include + +namespace v4l2 +{ + +constexpr uint32_t MakeFourCC(const char* fourcc) +{ + return fourcc[0] | (fourcc[1] << 8) | (fourcc[2] << 16) | (fourcc[3] << 24); +} + +enum class PixelFormat : uint32_t { + Undefined = 0, + + NV12 = MakeFourCC("NV12"), + NV21 = MakeFourCC("NV21"), + NV16 = MakeFourCC("NV16"), + NV61 = MakeFourCC("NV61"), + + YUV420 = MakeFourCC("YU12"), + YVU420 = MakeFourCC("YV12"), + YUV422 = MakeFourCC("YU16"), + YVU422 = MakeFourCC("YV16"), + YUV444 = MakeFourCC("YU24"), + YVU444 = MakeFourCC("YV24"), + + UYVY = MakeFourCC("UYVY"), + YUYV = MakeFourCC("YUYV"), + YVYU = MakeFourCC("YVYU"), + VYUY = MakeFourCC("VYUY"), + + XRGB8888 = MakeFourCC("XR24"), + XBGR8888 = MakeFourCC("XB24"), + RGBX8888 = MakeFourCC("RX24"), + BGRX8888 = MakeFourCC("BX24"), + + ARGB8888 = MakeFourCC("AR24"), + ABGR8888 = MakeFourCC("AB24"), + RGBA8888 = MakeFourCC("RA24"), + BGRA8888 = MakeFourCC("BA24"), + + RGB888 = MakeFourCC("RG24"), + BGR888 = MakeFourCC("BG24"), + + RGB332 = MakeFourCC("RGB8"), + + RGB565 = MakeFourCC("RG16"), + BGR565 = MakeFourCC("BG16"), + + XRGB4444 = MakeFourCC("XR12"), + XRGB1555 = MakeFourCC("XR15"), + + ARGB4444 = MakeFourCC("AR12"), + ARGB1555 = MakeFourCC("AR15"), + + XRGB2101010 = MakeFourCC("XR30"), + XBGR2101010 = MakeFourCC("XB30"), + RGBX1010102 = MakeFourCC("RX30"), + BGRX1010102 = MakeFourCC("BX30"), + + ARGB2101010 = MakeFourCC("AR30"), + ABGR2101010 = MakeFourCC("AB30"), + RGBA1010102 = MakeFourCC("RA30"), + BGRA1010102 = MakeFourCC("BA30"), + + SBGGR12 = MakeFourCC("BG12"), + SRGGB12 = MakeFourCC("RG12"), + + META_8 = MakeFourCC("ME08"), + META_16 = MakeFourCC("ME16"), +}; + +static inline PixelFormat FourCCToPixelFormat(const std::string& fourcc) +{ + return (PixelFormat)MakeFourCC(fourcc.c_str()); +} + +static inline std::string PixelFormatToFourCC(PixelFormat f) +{ + char buf[5] = { (char)(((uint32_t)f >> 0) & 0xff), + (char)(((uint32_t)f >> 8) & 0xff), + (char)(((uint32_t)f >> 16) & 0xff), + (char)(((uint32_t)f >> 24) & 0xff), + 0 }; + return std::string(buf); +} + +enum class PixelColorType { + RGB, + YUV, + RAW, +}; + +struct PixelFormatPlaneInfo { + uint8_t bitspp; + uint8_t xsub; + uint8_t ysub; +}; + +struct PixelFormatInfo { + PixelColorType type; + uint8_t num_planes; + struct PixelFormatPlaneInfo planes[4]; +}; + +const struct PixelFormatInfo& get_pixel_format_info(PixelFormat format); + +} // namespace kms diff --git a/v4l2++/inc/v4l2++/videodevice.h b/v4l2++/inc/v4l2++/videodevice.h new file mode 100644 index 0000000..bdb290e --- /dev/null +++ b/v4l2++/inc/v4l2++/videodevice.h @@ -0,0 +1,127 @@ +#pragma once + +#include +#include +#include +#include + +namespace v4l2 +{ + +class VideoStreamer; +class MetaStreamer; + +enum class VideoMemoryType +{ + MMAP, + DMABUF, +}; + +class VideoBuffer +{ +public: + VideoMemoryType m_mem_type; + uint32_t m_index; + uint32_t m_length; + int m_fd; + uint32_t m_offset; + PixelFormat m_format; +}; + +class VideoDevice +{ +public: + struct VideoFrameSize { + uint32_t min_w, max_w, step_w; + uint32_t min_h, max_h, step_h; + }; + + VideoDevice(const std::string& dev); + VideoDevice(int fd); + ~VideoDevice(); + + VideoDevice(const VideoDevice& other) = delete; + VideoDevice& operator=(const VideoDevice& other) = delete; + + VideoStreamer* get_capture_streamer(); + VideoStreamer* get_output_streamer(); + MetaStreamer* get_meta_capture_streamer(); + + std::vector> get_discrete_frame_sizes(PixelFormat fmt); + VideoFrameSize get_frame_sizes(PixelFormat fmt); + + int fd() const { return m_fd; } + bool has_capture() const { return m_has_capture; } + bool has_output() const { return m_has_output; } + bool has_m2m() const { return m_has_m2m; } + + static std::vector get_capture_devices(); + static std::vector get_m2m_devices(); + +private: + int m_fd; + + bool m_has_capture = false; + bool m_has_mplane_capture = false; + + bool m_has_output = false; + bool m_has_mplane_output = false; + + bool m_has_m2m = false; + bool m_has_mplane_m2m = false; + + bool m_has_meta_capture = false; + + std::unique_ptr m_capture_streamer; + std::unique_ptr m_output_streamer; + std::unique_ptr m_meta_capture_streamer; +}; + +class VideoStreamer +{ +public: + enum class StreamerType { + CaptureSingle, + CaptureMulti, + OutputSingle, + OutputMulti, + CaptureMeta, + OutputMeta, + }; + + VideoStreamer(int fd, StreamerType type); + virtual ~VideoStreamer() { } + + std::vector get_ports(); + void set_port(uint32_t index); + + std::vector get_formats(); + int get_format(PixelFormat& fmt, uint32_t& width, uint32_t& height); + void set_format(PixelFormat fmt, uint32_t width, uint32_t height); + void get_selection(uint32_t& left, uint32_t& top, uint32_t& width, uint32_t& height); + void set_selection(uint32_t& left, uint32_t& top, uint32_t& width, uint32_t& height); + void set_queue_size(uint32_t queue_size, VideoMemoryType mem_type); + void queue(VideoBuffer& fb); + VideoBuffer dequeue(); + void stream_on(); + void stream_off(); + + int fd() const { return m_fd; } + +protected: + int m_fd; + StreamerType m_type; + VideoMemoryType m_mem_type; + std::vector m_fbs; +}; + + +class MetaStreamer : public VideoStreamer +{ +public: + MetaStreamer(int fd, VideoStreamer::StreamerType type); + + void set_format(PixelFormat fmt, uint32_t size); +}; + +} -- cgit v1.2.3