summaryrefslogtreecommitdiff
path: root/v4l2++/inc/v4l2++
diff options
context:
space:
mode:
Diffstat (limited to 'v4l2++/inc/v4l2++')
-rw-r--r--v4l2++/inc/v4l2++/helpers.h60
-rw-r--r--v4l2++/inc/v4l2++/pixelformats.h111
-rw-r--r--v4l2++/inc/v4l2++/videodevice.h127
3 files changed, 298 insertions, 0 deletions
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 <fmt/format.h>
+
+#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<typename S, typename... Args>
+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 <cstdint>
+#include <string>
+#include <stdexcept>
+
+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 <string>
+#include <memory>
+#include <vector>
+#include <v4l2++/pixelformats.h>
+
+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<std::tuple<uint32_t, uint32_t>> 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<std::string> get_capture_devices();
+ static std::vector<std::string> 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<VideoStreamer> m_capture_streamer;
+ std::unique_ptr<VideoStreamer> m_output_streamer;
+ std::unique_ptr<MetaStreamer> 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<std::string> get_ports();
+ void set_port(uint32_t index);
+
+ std::vector<PixelFormat> 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<bool> m_fbs;
+};
+
+
+class MetaStreamer : public VideoStreamer
+{
+public:
+ MetaStreamer(int fd, VideoStreamer::StreamerType type);
+
+ void set_format(PixelFormat fmt, uint32_t size);
+};
+
+}