diff options
Diffstat (limited to 'src/libcamera/include/v4l2_videodevice.h')
-rw-r--r-- | src/libcamera/include/v4l2_videodevice.h | 189 |
1 files changed, 189 insertions, 0 deletions
diff --git a/src/libcamera/include/v4l2_videodevice.h b/src/libcamera/include/v4l2_videodevice.h new file mode 100644 index 00000000..89565880 --- /dev/null +++ b/src/libcamera/include/v4l2_videodevice.h @@ -0,0 +1,189 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2019, Google Inc. + * + * v4l2_videodevice.h - V4L2 Video Device + */ +#ifndef __LIBCAMERA_V4L2_VIDEODEVICE_H__ +#define __LIBCAMERA_V4L2_VIDEODEVICE_H__ + +#include <atomic> +#include <string> +#include <vector> + +#include <linux/videodev2.h> + +#include <libcamera/geometry.h> +#include <libcamera/signal.h> + +#include "formats.h" +#include "log.h" + +namespace libcamera { + +class Buffer; +class BufferPool; +class EventNotifier; +class MediaDevice; +class MediaEntity; + +struct V4L2Capability final : v4l2_capability { + const char *driver() const + { + return reinterpret_cast<const char *>(v4l2_capability::driver); + } + const char *card() const + { + return reinterpret_cast<const char *>(v4l2_capability::card); + } + const char *bus_info() const + { + return reinterpret_cast<const char *>(v4l2_capability::bus_info); + } + unsigned int device_caps() const + { + return capabilities & V4L2_CAP_DEVICE_CAPS + ? v4l2_capability::device_caps + : v4l2_capability::capabilities; + } + bool isMultiplanar() const + { + return device_caps() & (V4L2_CAP_VIDEO_CAPTURE_MPLANE | + V4L2_CAP_VIDEO_OUTPUT_MPLANE); + } + bool isCapture() const + { + return device_caps() & (V4L2_CAP_VIDEO_CAPTURE | + V4L2_CAP_VIDEO_CAPTURE_MPLANE | + V4L2_CAP_META_CAPTURE); + } + bool isOutput() const + { + return device_caps() & (V4L2_CAP_VIDEO_OUTPUT | + V4L2_CAP_VIDEO_OUTPUT_MPLANE | + V4L2_CAP_META_OUTPUT); + } + bool isVideo() const + { + return device_caps() & (V4L2_CAP_VIDEO_CAPTURE | + V4L2_CAP_VIDEO_CAPTURE_MPLANE | + V4L2_CAP_VIDEO_OUTPUT | + V4L2_CAP_VIDEO_OUTPUT_MPLANE); + } + bool isMeta() const + { + return device_caps() & (V4L2_CAP_META_CAPTURE | + V4L2_CAP_META_OUTPUT); + } + bool isVideoCapture() const + { + return isVideo() && isCapture(); + } + bool isVideoOutput() const + { + return isVideo() && isOutput(); + } + bool isMetaCapture() const + { + return isMeta() && isCapture(); + } + bool isMetaOutput() const + { + return isMeta() && isOutput(); + } + bool hasStreaming() const + { + return device_caps() & V4L2_CAP_STREAMING; + } +}; + +class V4L2DeviceFormat +{ +public: + uint32_t fourcc; + Size size; + + struct { + uint32_t size; + uint32_t bpl; + } planes[3]; + unsigned int planesCount; + + const std::string toString() const; +}; + +class V4L2VideoDevice : protected Loggable +{ +public: + explicit V4L2VideoDevice(const std::string &deviceNode); + explicit V4L2VideoDevice(const MediaEntity *entity); + V4L2VideoDevice(const V4L2VideoDevice &) = delete; + ~V4L2VideoDevice(); + + V4L2VideoDevice &operator=(const V4L2VideoDevice &) = delete; + + int open(); + bool isOpen() const; + void close(); + + const char *driverName() const { return caps_.driver(); } + const char *deviceName() const { return caps_.card(); } + const char *busName() const { return caps_.bus_info(); } + const std::string &deviceNode() const { return deviceNode_; } + + int getFormat(V4L2DeviceFormat *format); + int setFormat(V4L2DeviceFormat *format); + ImageFormats formats(); + + int exportBuffers(BufferPool *pool); + int importBuffers(BufferPool *pool); + int releaseBuffers(); + + int queueBuffer(Buffer *buffer); + Signal<Buffer *> bufferReady; + + int streamOn(); + int streamOff(); + + static V4L2VideoDevice *fromEntityName(const MediaDevice *media, + const std::string &entity); + +protected: + std::string logPrefix() const; + +private: + int getFormatMeta(V4L2DeviceFormat *format); + int setFormatMeta(V4L2DeviceFormat *format); + + int getFormatMultiplane(V4L2DeviceFormat *format); + int setFormatMultiplane(V4L2DeviceFormat *format); + + int getFormatSingleplane(V4L2DeviceFormat *format); + int setFormatSingleplane(V4L2DeviceFormat *format); + + int requestBuffers(unsigned int count); + int createPlane(Buffer *buffer, unsigned int plane, + unsigned int length); + + std::vector<unsigned int> enumPixelformats(); + std::vector<SizeRange> enumSizes(unsigned int pixelFormat); + + Buffer *dequeueBuffer(); + void bufferAvailable(EventNotifier *notifier); + + std::string deviceNode_; + int fd_; + V4L2Capability caps_; + + enum v4l2_buf_type bufferType_; + enum v4l2_memory memoryType_; + + BufferPool *bufferPool_; + std::atomic<unsigned int> queuedBuffersCount_; + + EventNotifier *fdEvent_; +}; + +} /* namespace libcamera */ + +#endif /* __LIBCAMERA_V4L2_VIDEODEVICE_H__ */ |