summaryrefslogtreecommitdiff
path: root/include/libcamera/internal/v4l2_videodevice.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/libcamera/internal/v4l2_videodevice.h')
-rw-r--r--include/libcamera/internal/v4l2_videodevice.h277
1 files changed, 277 insertions, 0 deletions
diff --git a/include/libcamera/internal/v4l2_videodevice.h b/include/libcamera/internal/v4l2_videodevice.h
new file mode 100644
index 00000000..dc259523
--- /dev/null
+++ b/include/libcamera/internal/v4l2_videodevice.h
@@ -0,0 +1,277 @@
+/* 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 <memory>
+#include <stdint.h>
+#include <string>
+#include <vector>
+
+#include <linux/videodev2.h>
+
+#include <libcamera/buffer.h>
+#include <libcamera/geometry.h>
+#include <libcamera/pixelformats.h>
+#include <libcamera/signal.h>
+
+#include "libcamera/internal/formats.h"
+#include "libcamera/internal/log.h"
+#include "libcamera/internal/v4l2_device.h"
+#include "libcamera/internal/v4l2_pixelformat.h"
+
+namespace libcamera {
+
+class EventNotifier;
+class FileDescriptor;
+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 |
+ V4L2_CAP_VIDEO_M2M_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 isM2M() const
+ {
+ return device_caps() & (V4L2_CAP_VIDEO_M2M |
+ V4L2_CAP_VIDEO_M2M_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 V4L2BufferCache
+{
+public:
+ V4L2BufferCache(unsigned int numEntries);
+ V4L2BufferCache(const std::vector<std::unique_ptr<FrameBuffer>> &buffers);
+ ~V4L2BufferCache();
+
+ int get(const FrameBuffer &buffer);
+ void put(unsigned int index);
+
+private:
+ class Entry
+ {
+ public:
+ Entry();
+ Entry(bool free, uint64_t lastUsed, const FrameBuffer &buffer);
+
+ bool operator==(const FrameBuffer &buffer) const;
+
+ bool free;
+ uint64_t lastUsed;
+
+ private:
+ struct Plane {
+ Plane(const FrameBuffer::Plane &plane)
+ : fd(plane.fd.fd()), length(plane.length)
+ {
+ }
+
+ int fd;
+ unsigned int length;
+ };
+
+ std::vector<Plane> planes_;
+ };
+
+ std::atomic<uint64_t> lastUsedCounter_;
+ std::vector<Entry> cache_;
+ /* \todo Expose the miss counter through an instrumentation API. */
+ unsigned int missCounter_;
+};
+
+class V4L2DeviceFormat
+{
+public:
+ V4L2PixelFormat fourcc;
+ Size size;
+
+ struct {
+ uint32_t size;
+ uint32_t bpl;
+ } planes[3];
+ unsigned int planesCount;
+
+ const std::string toString() const;
+};
+
+class V4L2VideoDevice : public V4L2Device
+{
+public:
+ explicit V4L2VideoDevice(const std::string &deviceNode);
+ explicit V4L2VideoDevice(const MediaEntity *entity);
+ V4L2VideoDevice(const V4L2VideoDevice &) = delete;
+ ~V4L2VideoDevice();
+
+ V4L2VideoDevice &operator=(const V4L2VideoDevice &) = delete;
+
+ int open();
+ int open(int handle, enum v4l2_buf_type type);
+ 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 V4L2Capability &caps() const { return caps_; }
+
+ int getFormat(V4L2DeviceFormat *format);
+ int setFormat(V4L2DeviceFormat *format);
+ std::map<V4L2PixelFormat, std::vector<SizeRange>> formats(uint32_t code = 0);
+
+ int setSelection(unsigned int target, Rectangle *rect);
+
+ int allocateBuffers(unsigned int count,
+ std::vector<std::unique_ptr<FrameBuffer>> *buffers);
+ int exportBuffers(unsigned int count,
+ std::vector<std::unique_ptr<FrameBuffer>> *buffers);
+ int importBuffers(unsigned int count);
+ int releaseBuffers();
+
+ int queueBuffer(FrameBuffer *buffer);
+ Signal<FrameBuffer *> bufferReady;
+
+ int setFrameStartEnabled(bool enable);
+ Signal<uint32_t> frameStart;
+
+ int streamOn();
+ int streamOff();
+
+ static V4L2VideoDevice *fromEntityName(const MediaDevice *media,
+ const std::string &entity);
+
+ V4L2PixelFormat toV4L2PixelFormat(const PixelFormat &pixelFormat);
+
+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);
+
+ std::vector<V4L2PixelFormat> enumPixelformats(uint32_t code);
+ std::vector<SizeRange> enumSizes(V4L2PixelFormat pixelFormat);
+
+ int requestBuffers(unsigned int count, enum v4l2_memory memoryType);
+ int createBuffers(unsigned int count,
+ std::vector<std::unique_ptr<FrameBuffer>> *buffers);
+ std::unique_ptr<FrameBuffer> createBuffer(unsigned int index);
+ FileDescriptor exportDmabufFd(unsigned int index, unsigned int plane);
+
+ void bufferAvailable(EventNotifier *notifier);
+ FrameBuffer *dequeueBuffer();
+
+ void eventAvailable(EventNotifier *notifier);
+
+ V4L2Capability caps_;
+
+ enum v4l2_buf_type bufferType_;
+ enum v4l2_memory memoryType_;
+
+ V4L2BufferCache *cache_;
+ std::map<unsigned int, FrameBuffer *> queuedBuffers_;
+
+ EventNotifier *fdBufferNotifier_;
+ EventNotifier *fdEventNotifier_;
+
+ bool frameStartEnabled_;
+};
+
+class V4L2M2MDevice
+{
+public:
+ V4L2M2MDevice(const std::string &deviceNode);
+ ~V4L2M2MDevice();
+
+ int open();
+ void close();
+
+ V4L2VideoDevice *output() { return output_; }
+ V4L2VideoDevice *capture() { return capture_; }
+
+private:
+ std::string deviceNode_;
+
+ V4L2VideoDevice *output_;
+ V4L2VideoDevice *capture_;
+};
+
+} /* namespace libcamera */
+
+#endif /* __LIBCAMERA_V4L2_VIDEODEVICE_H__ */