summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/libcamera/internal/byte_stream_buffer.h89
-rw-r--r--include/libcamera/internal/camera_controls.h30
-rw-r--r--include/libcamera/internal/camera_sensor.h88
-rw-r--r--include/libcamera/internal/control_serializer.h55
-rw-r--r--include/libcamera/internal/control_validator.h27
-rw-r--r--include/libcamera/internal/device_enumerator.h57
-rw-r--r--include/libcamera/internal/device_enumerator_sysfs.h32
-rw-r--r--include/libcamera/internal/device_enumerator_udev.h75
-rw-r--r--include/libcamera/internal/event_dispatcher_poll.h58
-rw-r--r--include/libcamera/internal/file.h71
-rw-r--r--include/libcamera/internal/formats.h58
-rw-r--r--include/libcamera/internal/ipa_context_wrapper.h50
-rw-r--r--include/libcamera/internal/ipa_manager.h51
-rw-r--r--include/libcamera/internal/ipa_module.h61
-rw-r--r--include/libcamera/internal/ipa_proxy.h70
-rw-r--r--include/libcamera/internal/ipc_unixsocket.h59
-rw-r--r--include/libcamera/internal/log.h130
-rw-r--r--include/libcamera/internal/media_device.h94
-rw-r--r--include/libcamera/internal/media_object.h124
-rw-r--r--include/libcamera/internal/meson.build35
-rw-r--r--include/libcamera/internal/message.h70
-rw-r--r--include/libcamera/internal/pipeline_handler.h151
-rw-r--r--include/libcamera/internal/process.h55
-rw-r--r--include/libcamera/internal/pub_key.h38
-rw-r--r--include/libcamera/internal/semaphore.h34
-rw-r--r--include/libcamera/internal/thread.h77
-rw-r--r--include/libcamera/internal/utils.h197
-rw-r--r--include/libcamera/internal/v4l2_controls.h31
-rw-r--r--include/libcamera/internal/v4l2_device.h60
-rw-r--r--include/libcamera/internal/v4l2_pixelformat.h49
-rw-r--r--include/libcamera/internal/v4l2_subdevice.h77
-rw-r--r--include/libcamera/internal/v4l2_videodevice.h277
-rw-r--r--include/libcamera/meson.build2
33 files changed, 2432 insertions, 0 deletions
diff --git a/include/libcamera/internal/byte_stream_buffer.h b/include/libcamera/internal/byte_stream_buffer.h
new file mode 100644
index 00000000..b3aaa8b9
--- /dev/null
+++ b/include/libcamera/internal/byte_stream_buffer.h
@@ -0,0 +1,89 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2019, Google Inc.
+ *
+ * byte_stream_buffer.h - Byte stream buffer
+ */
+#ifndef __LIBCAMERA_BYTE_STREAM_BUFFER_H__
+#define __LIBCAMERA_BYTE_STREAM_BUFFER_H__
+
+#include <stddef.h>
+#include <stdint.h>
+#include <type_traits>
+
+#include <libcamera/span.h>
+
+namespace libcamera {
+
+class ByteStreamBuffer
+{
+public:
+ ByteStreamBuffer(const uint8_t *base, size_t size);
+ ByteStreamBuffer(uint8_t *base, size_t size);
+ ByteStreamBuffer(ByteStreamBuffer &&other);
+ ByteStreamBuffer &operator=(ByteStreamBuffer &&other);
+
+ const uint8_t *base() const { return base_; }
+ uint32_t offset() const { return (write_ ? write_ : read_) - base_; }
+ size_t size() const { return size_; }
+ bool overflow() const { return overflow_; }
+
+ ByteStreamBuffer carveOut(size_t size);
+ int skip(size_t size);
+
+ template<typename T>
+ int read(T *t)
+ {
+ return read(reinterpret_cast<uint8_t *>(t), sizeof(*t));
+ }
+
+ template<typename T>
+ int read(const Span<T> &data)
+ {
+ return read(reinterpret_cast<uint8_t *>(data.data()),
+ data.size_bytes());
+ }
+
+ template<typename T>
+ const std::remove_reference_t<T> *read(size_t count = 1)
+ {
+ using return_type = const std::remove_reference_t<T> *;
+ return reinterpret_cast<return_type>(read(sizeof(T), count));
+ }
+
+ template<typename T>
+ int write(const T *t)
+ {
+ return write(reinterpret_cast<const uint8_t *>(t), sizeof(*t));
+ }
+
+ template<typename T>
+ int write(const Span<T> &data)
+ {
+ return write(reinterpret_cast<const uint8_t *>(data.data()),
+ data.size_bytes());
+ }
+
+private:
+ ByteStreamBuffer(const ByteStreamBuffer &other) = delete;
+ ByteStreamBuffer &operator=(const ByteStreamBuffer &other) = delete;
+
+ void setOverflow();
+
+ int read(uint8_t *data, size_t size);
+ const uint8_t *read(size_t size, size_t count);
+ int write(const uint8_t *data, size_t size);
+
+ ByteStreamBuffer *parent_;
+
+ const uint8_t *base_;
+ size_t size_;
+ bool overflow_;
+
+ const uint8_t *read_;
+ uint8_t *write_;
+};
+
+} /* namespace libcamera */
+
+#endif /* __LIBCAMERA_BYTE_STREAM_BUFFER_H__ */
diff --git a/include/libcamera/internal/camera_controls.h b/include/libcamera/internal/camera_controls.h
new file mode 100644
index 00000000..dc8b3ba8
--- /dev/null
+++ b/include/libcamera/internal/camera_controls.h
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2019, Google Inc.
+ *
+ * camera_controls.h - Camera controls
+ */
+#ifndef __LIBCAMERA_CAMERA_CONTROLS_H__
+#define __LIBCAMERA_CAMERA_CONTROLS_H__
+
+#include "libcamera/internal/control_validator.h"
+
+namespace libcamera {
+
+class Camera;
+
+class CameraControlValidator final : public ControlValidator
+{
+public:
+ CameraControlValidator(Camera *camera);
+
+ const std::string &name() const override;
+ bool validate(unsigned int id) const override;
+
+private:
+ Camera *camera_;
+};
+
+} /* namespace libcamera */
+
+#endif /* __LIBCAMERA_CAMERA_CONTROLS_H__ */
diff --git a/include/libcamera/internal/camera_sensor.h b/include/libcamera/internal/camera_sensor.h
new file mode 100644
index 00000000..d79bd9ce
--- /dev/null
+++ b/include/libcamera/internal/camera_sensor.h
@@ -0,0 +1,88 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2019, Google Inc.
+ *
+ * camera_sensor.h - A camera sensor
+ */
+#ifndef __LIBCAMERA_CAMERA_SENSOR_H__
+#define __LIBCAMERA_CAMERA_SENSOR_H__
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include <libcamera/controls.h>
+#include <libcamera/geometry.h>
+
+#include "libcamera/internal/formats.h"
+#include "libcamera/internal/log.h"
+
+namespace libcamera {
+
+class MediaEntity;
+class V4L2Subdevice;
+
+struct V4L2SubdeviceFormat;
+
+struct CameraSensorInfo {
+ std::string model;
+
+ uint32_t bitsPerPixel;
+
+ Size activeAreaSize;
+ Rectangle analogCrop;
+ Size outputSize;
+
+ uint64_t pixelRate;
+ uint32_t lineLength;
+};
+
+class CameraSensor : protected Loggable
+{
+public:
+ explicit CameraSensor(const MediaEntity *entity);
+ ~CameraSensor();
+
+ CameraSensor(const CameraSensor &) = delete;
+ CameraSensor &operator=(const CameraSensor &) = delete;
+
+ int init();
+
+ const std::string &model() const { return model_; }
+ const MediaEntity *entity() const { return entity_; }
+ const std::vector<unsigned int> &mbusCodes() const { return mbusCodes_; }
+ const std::vector<Size> &sizes() const { return sizes_; }
+ const Size &resolution() const { return resolution_; }
+
+ V4L2SubdeviceFormat getFormat(const std::vector<unsigned int> &mbusCodes,
+ const Size &size) const;
+ int setFormat(V4L2SubdeviceFormat *format);
+
+ const ControlInfoMap &controls() const;
+ ControlList getControls(const std::vector<uint32_t> &ids);
+ int setControls(ControlList *ctrls);
+
+ const ControlList &properties() const { return properties_; }
+ int sensorInfo(CameraSensorInfo *info) const;
+
+protected:
+ std::string logPrefix() const;
+
+private:
+ const MediaEntity *entity_;
+ std::unique_ptr<V4L2Subdevice> subdev_;
+ unsigned int pad_;
+
+ std::string model_;
+
+ ImageFormats formats_;
+ Size resolution_;
+ std::vector<unsigned int> mbusCodes_;
+ std::vector<Size> sizes_;
+
+ ControlList properties_;
+};
+
+} /* namespace libcamera */
+
+#endif /* __LIBCAMERA_CAMERA_SENSOR_H__ */
diff --git a/include/libcamera/internal/control_serializer.h b/include/libcamera/internal/control_serializer.h
new file mode 100644
index 00000000..99bacd92
--- /dev/null
+++ b/include/libcamera/internal/control_serializer.h
@@ -0,0 +1,55 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2019, Google Inc.
+ *
+ * control_serializer.h - Control (de)serializer
+ */
+#ifndef __LIBCAMERA_CONTROL_SERIALIZER_H__
+#define __LIBCAMERA_CONTROL_SERIALIZER_H__
+
+#include <map>
+#include <memory>
+#include <vector>
+
+#include <libcamera/controls.h>
+
+namespace libcamera {
+
+class ByteStreamBuffer;
+
+class ControlSerializer
+{
+public:
+ ControlSerializer();
+
+ void reset();
+
+ static size_t binarySize(const ControlInfoMap &infoMap);
+ static size_t binarySize(const ControlList &list);
+
+ int serialize(const ControlInfoMap &infoMap, ByteStreamBuffer &buffer);
+ int serialize(const ControlList &list, ByteStreamBuffer &buffer);
+
+ template<typename T>
+ T deserialize(ByteStreamBuffer &buffer);
+
+private:
+ static size_t binarySize(const ControlValue &value);
+ static size_t binarySize(const ControlInfo &info);
+
+ static void store(const ControlValue &value, ByteStreamBuffer &buffer);
+ static void store(const ControlInfo &info, ByteStreamBuffer &buffer);
+
+ ControlValue loadControlValue(ControlType type, ByteStreamBuffer &buffer,
+ bool isArray = false, unsigned int count = 1);
+ ControlInfo loadControlInfo(ControlType type, ByteStreamBuffer &buffer);
+
+ unsigned int serial_;
+ std::vector<std::unique_ptr<ControlId>> controlIds_;
+ std::map<unsigned int, ControlInfoMap> infoMaps_;
+ std::map<const ControlInfoMap *, unsigned int> infoMapHandles_;
+};
+
+} /* namespace libcamera */
+
+#endif /* __LIBCAMERA_CONTROL_SERIALIZER_H__ */
diff --git a/include/libcamera/internal/control_validator.h b/include/libcamera/internal/control_validator.h
new file mode 100644
index 00000000..f1c9110b
--- /dev/null
+++ b/include/libcamera/internal/control_validator.h
@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2019, Google Inc.
+ *
+ * control_validator.h - Control validator
+ */
+#ifndef __LIBCAMERA_CONTROL_VALIDATOR_H__
+#define __LIBCAMERA_CONTROL_VALIDATOR_H__
+
+#include <string>
+
+namespace libcamera {
+
+class ControlId;
+
+class ControlValidator
+{
+public:
+ virtual ~ControlValidator() {}
+
+ virtual const std::string &name() const = 0;
+ virtual bool validate(unsigned int id) const = 0;
+};
+
+} /* namespace libcamera */
+
+#endif /* __LIBCAMERA_CONTROL_VALIDATOR_H__ */
diff --git a/include/libcamera/internal/device_enumerator.h b/include/libcamera/internal/device_enumerator.h
new file mode 100644
index 00000000..433e357a
--- /dev/null
+++ b/include/libcamera/internal/device_enumerator.h
@@ -0,0 +1,57 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2018, Google Inc.
+ *
+ * device_enumerator.h - API to enumerate and find media devices
+ */
+#ifndef __LIBCAMERA_DEVICE_ENUMERATOR_H__
+#define __LIBCAMERA_DEVICE_ENUMERATOR_H__
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include <linux/media.h>
+
+namespace libcamera {
+
+class MediaDevice;
+
+class DeviceMatch
+{
+public:
+ DeviceMatch(const std::string &driver);
+
+ void add(const std::string &entity);
+
+ bool match(const MediaDevice *device) const;
+
+private:
+ std::string driver_;
+ std::vector<std::string> entities_;
+};
+
+class DeviceEnumerator
+{
+public:
+ static std::unique_ptr<DeviceEnumerator> create();
+
+ virtual ~DeviceEnumerator();
+
+ virtual int init() = 0;
+ virtual int enumerate() = 0;
+
+ std::shared_ptr<MediaDevice> search(const DeviceMatch &dm);
+
+protected:
+ std::unique_ptr<MediaDevice> createDevice(const std::string &deviceNode);
+ void addDevice(std::unique_ptr<MediaDevice> &&media);
+ void removeDevice(const std::string &deviceNode);
+
+private:
+ std::vector<std::shared_ptr<MediaDevice>> devices_;
+};
+
+} /* namespace libcamera */
+
+#endif /* __LIBCAMERA_DEVICE_ENUMERATOR_H__ */
diff --git a/include/libcamera/internal/device_enumerator_sysfs.h b/include/libcamera/internal/device_enumerator_sysfs.h
new file mode 100644
index 00000000..a63e737a
--- /dev/null
+++ b/include/libcamera/internal/device_enumerator_sysfs.h
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2019, Google Inc.
+ *
+ * device_enumerator_sysfs.h - sysfs-based device enumerator
+ */
+#ifndef __LIBCAMERA_DEVICE_ENUMERATOR_SYSFS_H__
+#define __LIBCAMERA_DEVICE_ENUMERATOR_SYSFS_H__
+
+#include <memory>
+#include <string>
+
+#include "libcamera/internal/device_enumerator.h"
+
+class MediaDevice;
+
+namespace libcamera {
+
+class DeviceEnumeratorSysfs final : public DeviceEnumerator
+{
+public:
+ int init();
+ int enumerate();
+
+private:
+ int populateMediaDevice(MediaDevice *media);
+ std::string lookupDeviceNode(int major, int minor);
+};
+
+} /* namespace libcamera */
+
+#endif /* __LIBCAMERA_DEVICE_ENUMERATOR_SYSFS_H__ */
diff --git a/include/libcamera/internal/device_enumerator_udev.h b/include/libcamera/internal/device_enumerator_udev.h
new file mode 100644
index 00000000..fdaa2096
--- /dev/null
+++ b/include/libcamera/internal/device_enumerator_udev.h
@@ -0,0 +1,75 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2018-2019, Google Inc.
+ *
+ * device_enumerator_udev.h - udev-based device enumerator
+ */
+#ifndef __LIBCAMERA_DEVICE_ENUMERATOR_UDEV_H__
+#define __LIBCAMERA_DEVICE_ENUMERATOR_UDEV_H__
+
+#include <list>
+#include <map>
+#include <memory>
+#include <set>
+#include <string>
+#include <sys/types.h>
+
+#include "libcamera/internal/device_enumerator.h"
+
+struct udev;
+struct udev_device;
+struct udev_monitor;
+
+namespace libcamera {
+
+class EventNotifier;
+class MediaDevice;
+class MediaEntity;
+
+class DeviceEnumeratorUdev : public DeviceEnumerator
+{
+public:
+ DeviceEnumeratorUdev();
+ ~DeviceEnumeratorUdev();
+
+ int init() final;
+ int enumerate() final;
+
+private:
+ struct udev *udev_;
+ struct udev_monitor *monitor_;
+ EventNotifier *notifier_;
+
+ using DependencyMap = std::map<dev_t, std::list<MediaEntity *>>;
+
+ struct MediaDeviceDeps {
+ MediaDeviceDeps(std::unique_ptr<MediaDevice> &&media,
+ DependencyMap &&deps)
+ : media_(std::move(media)), deps_(std::move(deps))
+ {
+ }
+
+ bool operator==(const MediaDeviceDeps &other) const
+ {
+ return media_ == other.media_;
+ }
+
+ std::unique_ptr<MediaDevice> media_;
+ DependencyMap deps_;
+ };
+
+ std::set<dev_t> orphans_;
+ std::list<MediaDeviceDeps> pending_;
+ std::map<dev_t, MediaDeviceDeps *> devMap_;
+
+ int addUdevDevice(struct udev_device *dev);
+ int populateMediaDevice(MediaDevice *media, DependencyMap *deps);
+ std::string lookupDeviceNode(dev_t devnum);
+
+ int addV4L2Device(dev_t devnum);
+ void udevNotify(EventNotifier *notifier);
+};
+
+} /* namespace libcamera */
+
+#endif /* __LIBCAMERA_DEVICE_ENUMERATOR_UDEV_H__ */
diff --git a/include/libcamera/internal/event_dispatcher_poll.h b/include/libcamera/internal/event_dispatcher_poll.h
new file mode 100644
index 00000000..1f073861
--- /dev/null
+++ b/include/libcamera/internal/event_dispatcher_poll.h
@@ -0,0 +1,58 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2019, Google Inc.
+ *
+ * event_dispatcher_poll.h - Poll-based event dispatcher
+ */
+#ifndef __LIBCAMERA_EVENT_DISPATCHER_POLL_H__
+#define __LIBCAMERA_EVENT_DISPATCHER_POLL_H__
+
+#include <list>
+#include <map>
+#include <vector>
+
+#include <libcamera/event_dispatcher.h>
+
+struct pollfd;
+
+namespace libcamera {
+
+class EventNotifier;
+class Timer;
+
+class EventDispatcherPoll final : public EventDispatcher
+{
+public:
+ EventDispatcherPoll();
+ ~EventDispatcherPoll();
+
+ void registerEventNotifier(EventNotifier *notifier);
+ void unregisterEventNotifier(EventNotifier *notifier);
+
+ void registerTimer(Timer *timer);
+ void unregisterTimer(Timer *timer);
+
+ void processEvents();
+ void interrupt();
+
+private:
+ struct EventNotifierSetPoll {
+ short events() const;
+ EventNotifier *notifiers[3];
+ };
+
+ std::map<int, EventNotifierSetPoll> notifiers_;
+ std::list<Timer *> timers_;
+ int eventfd_;
+
+ bool processingEvents_;
+
+ int poll(std::vector<struct pollfd> *pollfds);
+ void processInterrupt(const struct pollfd &pfd);
+ void processNotifiers(const std::vector<struct pollfd> &pollfds);
+ void processTimers();
+};
+
+} /* namespace libcamera */
+
+#endif /* __LIBCAMERA_EVENT_DISPATCHER_POLL_H__ */
diff --git a/include/libcamera/internal/file.h b/include/libcamera/internal/file.h
new file mode 100644
index 00000000..f020f2cc
--- /dev/null
+++ b/include/libcamera/internal/file.h
@@ -0,0 +1,71 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2020, Google Inc.
+ *
+ * file.h - File I/O operations
+ */
+#ifndef __LIBCAMERA_FILE_H__
+#define __LIBCAMERA_FILE_H__
+
+#include <map>
+#include <string>
+#include <sys/types.h>
+
+#include <libcamera/span.h>
+
+namespace libcamera {
+
+class File
+{
+public:
+ enum MapFlag {
+ MapNoOption = 0,
+ MapPrivate = (1 << 0),
+ };
+
+ enum OpenMode {
+ NotOpen = 0,
+ ReadOnly = (1 << 0),
+ WriteOnly = (1 << 1),
+ ReadWrite = ReadOnly | WriteOnly,
+ };
+
+ File(const std::string &name);
+ File();
+ ~File();
+
+ File(const File &) = delete;
+ File &operator=(const File &) = delete;
+
+ const std::string &fileName() const { return name_; }
+ void setFileName(const std::string &name);
+ bool exists() const;
+
+ bool open(OpenMode mode);
+ bool isOpen() const { return fd_ != -1; }
+ OpenMode openMode() const { return mode_; }
+ void close();
+
+ int error() const { return error_; }
+ ssize_t size() const;
+
+ Span<uint8_t> map(off_t offset = 0, ssize_t size = -1,
+ MapFlag flags = MapNoOption);
+ bool unmap(uint8_t *addr);
+
+ static bool exists(const std::string &name);
+
+private:
+ void unmapAll();
+
+ std::string name_;
+ int fd_;
+ OpenMode mode_;
+
+ int error_;
+ std::map<void *, size_t> maps_;
+};
+
+} /* namespace libcamera */
+
+#endif /* __LIBCAMERA_FILE_H__ */
diff --git a/include/libcamera/internal/formats.h b/include/libcamera/internal/formats.h
new file mode 100644
index 00000000..4092a93e
--- /dev/null
+++ b/include/libcamera/internal/formats.h
@@ -0,0 +1,58 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2019, Google Inc.
+ *
+ * formats.h - libcamera image formats
+ */
+
+#ifndef __LIBCAMERA_FORMATS_H__
+#define __LIBCAMERA_FORMATS_H__
+
+#include <map>
+#include <vector>
+
+#include <libcamera/geometry.h>
+#include <libcamera/pixelformats.h>
+
+#include "libcamera/internal/v4l2_pixelformat.h"
+
+namespace libcamera {
+
+class ImageFormats
+{
+public:
+ int addFormat(unsigned int format, const std::vector<SizeRange> &sizes);
+
+ bool isEmpty() const;
+ std::vector<unsigned int> formats() const;
+ const std::vector<SizeRange> &sizes(unsigned int format) const;
+ const std::map<unsigned int, std::vector<SizeRange>> &data() const;
+
+private:
+ std::map<unsigned int, std::vector<SizeRange>> data_;
+};
+
+class PixelFormatInfo
+{
+public:
+ enum ColourEncoding {
+ ColourEncodingRGB,
+ ColourEncodingYUV,
+ ColourEncodingRAW,
+ };
+
+ bool isValid() const { return format.isValid(); }
+
+ static const PixelFormatInfo &info(const PixelFormat &format);
+
+ /* \todo Add support for non-contiguous memory planes */
+ PixelFormat format;
+ V4L2PixelFormat v4l2Format;
+ unsigned int bitsPerPixel;
+ enum ColourEncoding colourEncoding;
+ bool packed;
+};
+
+} /* namespace libcamera */
+
+#endif /* __LIBCAMERA_FORMATS_H__ */
diff --git a/include/libcamera/internal/ipa_context_wrapper.h b/include/libcamera/internal/ipa_context_wrapper.h
new file mode 100644
index 00000000..a717d406
--- /dev/null
+++ b/include/libcamera/internal/ipa_context_wrapper.h
@@ -0,0 +1,50 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2019, Google Inc.
+ *
+ * ipa_context_wrapper.h - Image Processing Algorithm context wrapper
+ */
+#ifndef __LIBCAMERA_IPA_CONTEXT_WRAPPER_H__
+#define __LIBCAMERA_IPA_CONTEXT_WRAPPER_H__
+
+#include <ipa/ipa_interface.h>
+
+#include "libcamera/internal/control_serializer.h"
+
+namespace libcamera {
+
+class IPAContextWrapper final : public IPAInterface
+{
+public:
+ IPAContextWrapper(struct ipa_context *context);
+ ~IPAContextWrapper();
+
+ int init(const IPASettings &settings) override;
+ int start() override;
+ void stop() override;
+ void configure(const CameraSensorInfo &sensorInfo,
+ const std::map<unsigned int, IPAStream> &streamConfig,
+ const std::map<unsigned int, const ControlInfoMap &> &entityControls) override;
+
+ void mapBuffers(const std::vector<IPABuffer> &buffers) override;
+ void unmapBuffers(const std::vector<unsigned int> &ids) override;
+
+ virtual void processEvent(const IPAOperationData &data) override;
+
+private:
+ static void queue_frame_action(void *ctx, unsigned int frame,
+ struct ipa_operation_data &data);
+ static const struct ipa_callback_ops callbacks_;
+
+ void doQueueFrameAction(unsigned int frame,
+ const IPAOperationData &data);
+
+ struct ipa_context *ctx_;
+ IPAInterface *intf_;
+
+ ControlSerializer serializer_;
+};
+
+} /* namespace libcamera */
+
+#endif /* __LIBCAMERA_IPA_CONTEXT_WRAPPER_H__ */
diff --git a/include/libcamera/internal/ipa_manager.h b/include/libcamera/internal/ipa_manager.h
new file mode 100644
index 00000000..f07d91fc
--- /dev/null
+++ b/include/libcamera/internal/ipa_manager.h
@@ -0,0 +1,51 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2019, Google Inc.
+ *
+ * ipa_manager.h - Image Processing Algorithm module manager
+ */
+#ifndef __LIBCAMERA_IPA_MANAGER_H__
+#define __LIBCAMERA_IPA_MANAGER_H__
+
+#include <stdint.h>
+#include <vector>
+
+#include <ipa/ipa_interface.h>
+#include <ipa/ipa_module_info.h>
+
+#include "libcamera/internal/ipa_module.h"
+#include "libcamera/internal/pipeline_handler.h"
+#include "libcamera/internal/pub_key.h"
+
+namespace libcamera {
+
+class IPAManager
+{
+public:
+ static IPAManager *instance();
+
+ std::unique_ptr<IPAProxy> createIPA(PipelineHandler *pipe,
+ uint32_t maxVersion,
+ uint32_t minVersion);
+
+private:
+ std::vector<IPAModule *> modules_;
+
+ IPAManager();
+ ~IPAManager();
+
+ void parseDir(const char *libDir, unsigned int maxDepth,
+ std::vector<std::string> &files);
+ unsigned int addDir(const char *libDir, unsigned int maxDepth = 0);
+
+ bool isSignatureValid(IPAModule *ipa) const;
+
+#if HAVE_IPA_PUBKEY
+ static const uint8_t publicKeyData_[];
+ static const PubKey pubKey_;
+#endif
+};
+
+} /* namespace libcamera */
+
+#endif /* __LIBCAMERA_IPA_MANAGER_H__ */
diff --git a/include/libcamera/internal/ipa_module.h b/include/libcamera/internal/ipa_module.h
new file mode 100644
index 00000000..2f569db0
--- /dev/null
+++ b/include/libcamera/internal/ipa_module.h
@@ -0,0 +1,61 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2019, Google Inc.
+ *
+ * ipa_module.h - Image Processing Algorithm module
+ */
+#ifndef __LIBCAMERA_IPA_MODULE_H__
+#define __LIBCAMERA_IPA_MODULE_H__
+
+#include <stdint.h>
+#include <string>
+#include <vector>
+
+#include <ipa/ipa_interface.h>
+#include <ipa/ipa_module_info.h>
+
+#include "libcamera/internal/log.h"
+#include "libcamera/internal/pipeline_handler.h"
+
+namespace libcamera {
+
+class IPAModule : public Loggable
+{
+public:
+ explicit IPAModule(const std::string &libPath);
+ ~IPAModule();
+
+ bool isValid() const;
+
+ const struct IPAModuleInfo &info() const;
+ const std::vector<uint8_t> signature() const;
+ const std::string &path() const;
+
+ bool load();
+
+ struct ipa_context *createContext();
+
+ bool match(PipelineHandler *pipe,
+ uint32_t minVersion, uint32_t maxVersion) const;
+
+protected:
+ std::string logPrefix() const override;
+
+private:
+ struct IPAModuleInfo info_;
+ std::vector<uint8_t> signature_;
+
+ std::string libPath_;
+ bool valid_;
+ bool loaded_;
+
+ void *dlHandle_;
+ typedef struct ipa_context *(*IPAIntfFactory)(void);
+ IPAIntfFactory ipaCreate_;
+
+ int loadIPAModuleInfo();
+};
+
+} /* namespace libcamera */
+
+#endif /* __LIBCAMERA_IPA_MODULE_H__ */
diff --git a/include/libcamera/internal/ipa_proxy.h b/include/libcamera/internal/ipa_proxy.h
new file mode 100644
index 00000000..1111065b
--- /dev/null
+++ b/include/libcamera/internal/ipa_proxy.h
@@ -0,0 +1,70 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2019, Google Inc.
+ *
+ * ipa_proxy.h - Image Processing Algorithm proxy
+ */
+#ifndef __LIBCAMERA_IPA_PROXY_H__
+#define __LIBCAMERA_IPA_PROXY_H__
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include <ipa/ipa_interface.h>
+
+namespace libcamera {
+
+class IPAModule;
+
+class IPAProxy : public IPAInterface
+{
+public:
+ IPAProxy(IPAModule *ipam);
+ ~IPAProxy();
+
+ bool isValid() const { return valid_; }
+
+ std::string configurationFile(const std::string &file) const;
+
+protected:
+ std::string resolvePath(const std::string &file) const;
+
+ bool valid_;
+
+private:
+ IPAModule *ipam_;
+};
+
+class IPAProxyFactory
+{
+public:
+ IPAProxyFactory(const char *name);
+ virtual ~IPAProxyFactory() {}
+
+ virtual std::unique_ptr<IPAProxy> create(IPAModule *ipam) = 0;
+
+ const std::string &name() const { return name_; }
+
+ static void registerType(IPAProxyFactory *factory);
+ static std::vector<IPAProxyFactory *> &factories();
+
+private:
+ std::string name_;
+};
+
+#define REGISTER_IPA_PROXY(proxy) \
+class proxy##Factory final : public IPAProxyFactory \
+{ \
+public: \
+ proxy##Factory() : IPAProxyFactory(#proxy) {} \
+ std::unique_ptr<IPAProxy> create(IPAModule *ipam) \
+ { \
+ return std::make_unique<proxy>(ipam); \
+ } \
+}; \
+static proxy##Factory global_##proxy##Factory;
+
+} /* namespace libcamera */
+
+#endif /* __LIBCAMERA_IPA_PROXY_H__ */
diff --git a/include/libcamera/internal/ipc_unixsocket.h b/include/libcamera/internal/ipc_unixsocket.h
new file mode 100644
index 00000000..820d0561
--- /dev/null
+++ b/include/libcamera/internal/ipc_unixsocket.h
@@ -0,0 +1,59 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2019, Google Inc.
+ *
+ * ipc_unixsocket.h - IPC mechanism based on Unix sockets
+ */
+
+#ifndef __LIBCAMERA_IPC_UNIXSOCKET_H__
+#define __LIBCAMERA_IPC_UNIXSOCKET_H__
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <vector>
+
+#include <libcamera/event_notifier.h>
+
+namespace libcamera {
+
+class IPCUnixSocket
+{
+public:
+ struct Payload {
+ std::vector<uint8_t> data;
+ std::vector<int32_t> fds;
+ };
+
+ IPCUnixSocket();
+ ~IPCUnixSocket();
+
+ int create();
+ int bind(int fd);
+ void close();
+ bool isBound() const;
+
+ int send(const Payload &payload);
+ int receive(Payload *payload);
+
+ Signal<IPCUnixSocket *> readyRead;
+
+private:
+ struct Header {
+ uint32_t data;
+ uint8_t fds;
+ };
+
+ int sendData(const void *buffer, size_t length, const int32_t *fds, unsigned int num);
+ int recvData(void *buffer, size_t length, int32_t *fds, unsigned int num);
+
+ void dataNotifier(EventNotifier *notifier);
+
+ int fd_;
+ bool headerReceived_;
+ struct Header header_;
+ EventNotifier *notifier_;
+};
+
+} /* namespace libcamera */
+
+#endif /* __LIBCAMERA_IPC_UNIXSOCKET_H__ */
diff --git a/include/libcamera/internal/log.h b/include/libcamera/internal/log.h
new file mode 100644
index 00000000..cab2034a
--- /dev/null
+++ b/include/libcamera/internal/log.h
@@ -0,0 +1,130 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2018, Google Inc.
+ *
+ * log.h - Logging infrastructure
+ */
+#ifndef __LIBCAMERA_LOG_H__
+#define __LIBCAMERA_LOG_H__
+
+#include <chrono>
+#include <sstream>
+
+#include "libcamera/internal/utils.h"
+
+namespace libcamera {
+
+enum LogSeverity {
+ LogInvalid = -1,
+ LogDebug = 0,
+ LogInfo,
+ LogWarning,
+ LogError,
+ LogFatal,
+};
+
+class LogCategory
+{
+public:
+ explicit LogCategory(const char *name);
+ ~LogCategory();
+
+ const char *name() const { return name_; }
+ LogSeverity severity() const { return severity_; }
+ void setSeverity(LogSeverity severity);
+
+ static const LogCategory &defaultCategory();
+
+private:
+ const char *name_;
+ LogSeverity severity_;
+};
+
+#define LOG_DECLARE_CATEGORY(name) \
+extern const LogCategory &_LOG_CATEGORY(name)();
+
+#define LOG_DEFINE_CATEGORY(name) \
+const LogCategory &_LOG_CATEGORY(name)() \
+{ \
+ static LogCategory category(#name); \
+ return category; \
+}
+
+class LogMessage
+{
+public:
+ LogMessage(const char *fileName, unsigned int line,
+ LogSeverity severity);
+ LogMessage(const char *fileName, unsigned int line,
+ const LogCategory &category, LogSeverity severity);
+ LogMessage(const LogMessage &) = delete;
+ LogMessage(LogMessage &&);
+ ~LogMessage();
+
+ std::ostream &stream() { return msgStream_; }
+
+ const utils::time_point &timestamp() const { return timestamp_; }
+ LogSeverity severity() const { return severity_; }
+ const LogCategory &category() const { return category_; }
+ const std::string &fileInfo() const { return fileInfo_; }
+ const std::string msg() const { return msgStream_.str(); }
+
+private:
+ void init(const char *fileName, unsigned int line);
+
+ std::ostringstream msgStream_;
+ const LogCategory &category_;
+ LogSeverity severity_;
+ utils::time_point timestamp_;
+ std::string fileInfo_;
+};
+
+class Loggable
+{
+public:
+ virtual ~Loggable();
+
+protected:
+ virtual std::string logPrefix() const = 0;
+
+ LogMessage _log(const char *file, unsigned int line,
+ LogSeverity severity) const;
+ LogMessage _log(const char *file, unsigned int line,
+ const LogCategory &category,
+ LogSeverity severity) const;
+};
+
+LogMessage _log(const char *file, unsigned int line, LogSeverity severity);
+LogMessage _log(const char *file, unsigned int line,
+ const LogCategory &category, LogSeverity severity);
+
+#ifndef __DOXYGEN__
+#define _LOG_CATEGORY(name) logCategory##name
+
+#define _LOG1(severity) \
+ _log(__FILE__, __LINE__, Log##severity).stream()
+#define _LOG2(category, severity) \
+ _log(__FILE__, __LINE__, _LOG_CATEGORY(category)(), Log##severity).stream()
+
+/*
+ * Expand the LOG() macro to _LOG1() or _LOG2() based on the number of
+ * arguments.
+ */
+#define _LOG_MACRO(_1, _2, NAME, ...) NAME
+#define LOG(...) _LOG_MACRO(__VA_ARGS__, _LOG2, _LOG1)(__VA_ARGS__)
+#else /* __DOXYGEN___ */
+#define LOG(category, severity)
+#endif /* __DOXYGEN__ */
+
+#ifndef NDEBUG
+#define ASSERT(condition) static_cast<void>(({ \
+ if (!(condition)) \
+ LOG(Fatal) << "assertion \"" #condition "\" failed"; \
+}))
+#else
+#define ASSERT(condition) static_cast<void>(false && (condition))
+#endif
+
+} /* namespace libcamera */
+
+#endif /* __LIBCAMERA_LOG_H__ */
diff --git a/include/libcamera/internal/media_device.h b/include/libcamera/internal/media_device.h
new file mode 100644
index 00000000..9fe76c51
--- /dev/null
+++ b/include/libcamera/internal/media_device.h
@@ -0,0 +1,94 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2018, Google Inc.
+ *
+ * media_device.h - Media device handler
+ */
+#ifndef __LIBCAMERA_MEDIA_DEVICE_H__
+#define __LIBCAMERA_MEDIA_DEVICE_H__
+
+#include <map>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include <linux/media.h>
+
+#include <libcamera/signal.h>
+
+#include "libcamera/internal/log.h"
+#include "libcamera/internal/media_object.h"
+
+namespace libcamera {
+
+class MediaDevice : protected Loggable
+{
+public:
+ MediaDevice(const std::string &deviceNode);
+ ~MediaDevice();
+
+ bool acquire();
+ void release();
+ bool busy() const { return acquired_; }
+
+ bool lock();
+ void unlock();
+
+ int populate();
+ bool valid() const { return valid_; }
+
+ const std::string driver() const { return driver_; }
+ const std::string deviceNode() const { return deviceNode_; }
+ const std::string model() const { return model_; }
+ unsigned int version() const { return version_; }
+
+ const std::vector<MediaEntity *> &entities() const { return entities_; }
+ MediaEntity *getEntityByName(const std::string &name) const;
+
+ MediaLink *link(const std::string &sourceName, unsigned int sourceIdx,
+ const std::string &sinkName, unsigned int sinkIdx);
+ MediaLink *link(const MediaEntity *source, unsigned int sourceIdx,
+ const MediaEntity *sink, unsigned int sinkIdx);
+ MediaLink *link(const MediaPad *source, const MediaPad *sink);
+ int disableLinks();
+
+ Signal<MediaDevice *> disconnected;
+
+protected:
+ std::string logPrefix() const;
+
+private:
+ std::string driver_;
+ std::string deviceNode_;
+ std::string model_;
+ unsigned int version_;
+
+ int fd_;
+ bool valid_;
+ bool acquired_;
+ bool lockOwner_;
+
+ int open();
+ void close();
+
+ std::map<unsigned int, MediaObject *> objects_;
+ MediaObject *object(unsigned int id);
+ bool addObject(MediaObject *object);
+ void clear();
+
+ std::vector<MediaEntity *> entities_;
+
+ struct media_v2_interface *findInterface(const struct media_v2_topology &topology,
+ unsigned int entityId);
+ bool populateEntities(const struct media_v2_topology &topology);
+ bool populatePads(const struct media_v2_topology &topology);
+ bool populateLinks(const struct media_v2_topology &topology);
+ void fixupEntityFlags(struct media_v2_entity *entity);
+
+ friend int MediaLink::setEnabled(bool enable);
+ int setupLink(const MediaLink *link, unsigned int flags);
+};
+
+} /* namespace libcamera */
+
+#endif /* __LIBCAMERA_MEDIA_DEVICE_H__ */
diff --git a/include/libcamera/internal/media_object.h b/include/libcamera/internal/media_object.h
new file mode 100644
index 00000000..748eafdc
--- /dev/null
+++ b/include/libcamera/internal/media_object.h
@@ -0,0 +1,124 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2018, Google Inc.
+ *
+ * media_object.h - Media Device objects: entities, pads and links.
+ */
+#ifndef __LIBCAMERA_MEDIA_OBJECT_H__
+#define __LIBCAMERA_MEDIA_OBJECT_H__
+
+#include <string>
+#include <vector>
+
+#include <linux/media.h>
+
+namespace libcamera {
+
+class MediaDevice;
+class MediaEntity;
+class MediaPad;
+
+class MediaObject
+{
+public:
+ MediaDevice *device() { return dev_; }
+ unsigned int id() const { return id_; }
+
+protected:
+ friend class MediaDevice;
+
+ MediaObject(MediaDevice *dev, unsigned int id)
+ : dev_(dev), id_(id)
+ {
+ }
+ virtual ~MediaObject() {}
+
+ MediaDevice *dev_;
+ unsigned int id_;
+};
+
+class MediaLink : public MediaObject
+{
+public:
+ MediaPad *source() const { return source_; }
+ MediaPad *sink() const { return sink_; }
+ unsigned int flags() const { return flags_; }
+ int setEnabled(bool enable);
+
+private:
+ friend class MediaDevice;
+
+ MediaLink(const struct media_v2_link *link,
+ MediaPad *source, MediaPad *sink);
+ MediaLink(const MediaLink &) = delete;
+ ~MediaLink() {}
+
+ MediaPad *source_;
+ MediaPad *sink_;
+ unsigned int flags_;
+};
+
+class MediaPad : public MediaObject
+{
+public:
+ unsigned int index() const { return index_; }
+ MediaEntity *entity() const { return entity_; }
+ unsigned int flags() const { return flags_; }
+ const std::vector<MediaLink *> &links() const { return links_; }
+
+ void addLink(MediaLink *link);
+
+private:
+ friend class MediaDevice;
+
+ MediaPad(const struct media_v2_pad *pad, MediaEntity *entity);
+ MediaPad(const MediaPad &) = delete;
+ ~MediaPad();
+
+ unsigned int index_;
+ MediaEntity *entity_;
+ unsigned int flags_;
+
+ std::vector<MediaLink *> links_;
+};
+
+class MediaEntity : public MediaObject
+{
+public:
+ const std::string &name() const { return name_; }
+ unsigned int function() const { return function_; }
+ unsigned int flags() const { return flags_; }
+ const std::string &deviceNode() const { return deviceNode_; }
+ unsigned int deviceMajor() const { return major_; }
+ unsigned int deviceMinor() const { return minor_; }
+
+ const std::vector<MediaPad *> &pads() const { return pads_; }
+
+ const MediaPad *getPadByIndex(unsigned int index) const;
+ const MediaPad *getPadById(unsigned int id) const;
+
+ int setDeviceNode(const std::string &deviceNode);
+
+private:
+ friend class MediaDevice;
+
+ MediaEntity(MediaDevice *dev, const struct media_v2_entity *entity,
+ unsigned int major = 0, unsigned int minor = 0);
+ MediaEntity(const MediaEntity &) = delete;
+ ~MediaEntity();
+
+ std::string name_;
+ unsigned int function_;
+ unsigned int flags_;
+ std::string deviceNode_;
+ unsigned int major_;
+ unsigned int minor_;
+
+ std::vector<MediaPad *> pads_;
+
+ void addPad(MediaPad *pad);
+};
+
+} /* namespace libcamera */
+
+#endif /* __LIBCAMERA_MEDIA_OBJECT_H__ */
diff --git a/include/libcamera/internal/meson.build b/include/libcamera/internal/meson.build
new file mode 100644
index 00000000..1f6af579
--- /dev/null
+++ b/include/libcamera/internal/meson.build
@@ -0,0 +1,35 @@
+# SPDX-License-Identifier: CC0-1.0
+
+libcamera_headers = files([
+ 'byte_stream_buffer.h',
+ 'camera_controls.h',
+ 'camera_sensor.h',
+ 'control_serializer.h',
+ 'control_validator.h',
+ 'device_enumerator.h',
+ 'device_enumerator_sysfs.h',
+ 'device_enumerator_udev.h',
+ 'event_dispatcher_poll.h',
+ 'file.h',
+ 'formats.h',
+ 'ipa_context_wrapper.h',
+ 'ipa_manager.h',
+ 'ipa_module.h',
+ 'ipa_proxy.h',
+ 'ipc_unixsocket.h',
+ 'log.h',
+ 'media_device.h',
+ 'media_object.h',
+ 'message.h',
+ 'pipeline_handler.h',
+ 'process.h',
+ 'pub_key.h',
+ 'semaphore.h',
+ 'thread.h',
+ 'utils.h',
+ 'v4l2_controls.h',
+ 'v4l2_device.h',
+ 'v4l2_pixelformat.h',
+ 'v4l2_subdevice.h',
+ 'v4l2_videodevice.h',
+])
diff --git a/include/libcamera/internal/message.h b/include/libcamera/internal/message.h
new file mode 100644
index 00000000..8e8b013d
--- /dev/null
+++ b/include/libcamera/internal/message.h
@@ -0,0 +1,70 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2019, Google Inc.
+ *
+ * message.h - Message queue support
+ */
+#ifndef __LIBCAMERA_MESSAGE_H__
+#define __LIBCAMERA_MESSAGE_H__
+
+#include <atomic>
+
+#include <libcamera/bound_method.h>
+
+namespace libcamera {
+
+class BoundMethodBase;
+class Object;
+class Semaphore;
+class Thread;
+
+class Message
+{
+public:
+ enum Type {
+ None = 0,
+ InvokeMessage = 1,
+ ThreadMoveMessage = 2,
+ UserMessage = 1000,
+ };
+
+ Message(Type type);
+ virtual ~Message();
+
+ Type type() const { return type_; }
+ Object *receiver() const { return receiver_; }
+
+ static Type registerMessageType();
+
+private:
+ friend class Thread;
+
+ Type type_;
+ Object *receiver_;
+
+ static std::atomic_uint nextUserType_;
+};
+
+class InvokeMessage : public Message
+{
+public:
+ InvokeMessage(BoundMethodBase *method,
+ std::shared_ptr<BoundMethodPackBase> pack,
+ Semaphore *semaphore = nullptr,
+ bool deleteMethod = false);
+ ~InvokeMessage();
+
+ Semaphore *semaphore() const { return semaphore_; }
+
+ void invoke();
+
+private:
+ BoundMethodBase *method_;
+ std::shared_ptr<BoundMethodPackBase> pack_;
+ Semaphore *semaphore_;
+ bool deleteMethod_;
+};
+
+} /* namespace libcamera */
+
+#endif /* __LIBCAMERA_MESSAGE_H__ */
diff --git a/include/libcamera/internal/pipeline_handler.h b/include/libcamera/internal/pipeline_handler.h
new file mode 100644
index 00000000..428f5887
--- /dev/null
+++ b/include/libcamera/internal/pipeline_handler.h
@@ -0,0 +1,151 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2018, Google Inc.
+ *
+ * pipeline_handler.h - Pipeline handler infrastructure
+ */
+#ifndef __LIBCAMERA_PIPELINE_HANDLER_H__
+#define __LIBCAMERA_PIPELINE_HANDLER_H__
+
+#include <list>
+#include <map>
+#include <memory>
+#include <set>
+#include <string>
+#include <sys/types.h>
+#include <vector>
+
+#include <libcamera/controls.h>
+#include <libcamera/object.h>
+#include <libcamera/stream.h>
+
+#include "libcamera/internal/ipa_proxy.h"
+
+namespace libcamera {
+
+class Camera;
+class CameraConfiguration;
+class CameraManager;
+class DeviceEnumerator;
+class DeviceMatch;
+class FrameBuffer;
+class MediaDevice;
+class PipelineHandler;
+class Request;
+
+class CameraData
+{
+public:
+ explicit CameraData(PipelineHandler *pipe)
+ : pipe_(pipe)
+ {
+ }
+ virtual ~CameraData() {}
+
+ Camera *camera_;
+ PipelineHandler *pipe_;
+ std::list<Request *> queuedRequests_;
+ ControlInfoMap controlInfo_;
+ ControlList properties_;
+ std::unique_ptr<IPAProxy> ipa_;
+
+private:
+ CameraData(const CameraData &) = delete;
+ CameraData &operator=(const CameraData &) = delete;
+};
+
+class PipelineHandler : public std::enable_shared_from_this<PipelineHandler>,
+ public Object
+{
+public:
+ PipelineHandler(CameraManager *manager);
+ virtual ~PipelineHandler();
+
+ virtual bool match(DeviceEnumerator *enumerator) = 0;
+ MediaDevice *acquireMediaDevice(DeviceEnumerator *enumerator,
+ const DeviceMatch &dm);
+
+ bool lock();
+ void unlock();
+
+ const ControlInfoMap &controls(Camera *camera);
+ const ControlList &properties(Camera *camera);
+
+ virtual CameraConfiguration *generateConfiguration(Camera *camera,
+ const StreamRoles &roles) = 0;
+ virtual int configure(Camera *camera, CameraConfiguration *config) = 0;
+
+ virtual int exportFrameBuffers(Camera *camera, Stream *stream,
+ std::vector<std::unique_ptr<FrameBuffer>> *buffers) = 0;
+
+ virtual int start(Camera *camera) = 0;
+ virtual void stop(Camera *camera) = 0;
+
+ int queueRequest(Camera *camera, Request *request);
+
+ bool completeBuffer(Camera *camera, Request *request,
+ FrameBuffer *buffer);
+ void completeRequest(Camera *camera, Request *request);
+
+ const char *name() const { return name_; }
+
+protected:
+ void registerCamera(std::shared_ptr<Camera> camera,
+ std::unique_ptr<CameraData> data, dev_t devnum = 0);
+ void hotplugMediaDevice(MediaDevice *media);
+
+ virtual int queueRequestDevice(Camera *camera, Request *request) = 0;
+
+ CameraData *cameraData(const Camera *camera);
+
+ CameraManager *manager_;
+
+private:
+ void mediaDeviceDisconnected(MediaDevice *media);
+ virtual void disconnect();
+
+ std::vector<std::shared_ptr<MediaDevice>> mediaDevices_;
+ std::vector<std::weak_ptr<Camera>> cameras_;
+ std::map<const Camera *, std::unique_ptr<CameraData>> cameraData_;
+
+ const char *name_;
+
+ friend class PipelineHandlerFactory;
+};
+
+class PipelineHandlerFactory
+{
+public:
+ PipelineHandlerFactory(const char *name);
+ virtual ~PipelineHandlerFactory() {}
+
+ std::shared_ptr<PipelineHandler> create(CameraManager *manager);
+
+ const std::string &name() const { return name_; }
+
+ static void registerType(PipelineHandlerFactory *factory);
+ static std::vector<PipelineHandlerFactory *> &factories();
+
+private:
+ virtual PipelineHandler *createInstance(CameraManager *manager) = 0;
+
+ std::string name_;
+};
+
+#define REGISTER_PIPELINE_HANDLER(handler) \
+class handler##Factory final : public PipelineHandlerFactory \
+{ \
+public: \
+ handler##Factory() : PipelineHandlerFactory(#handler) {} \
+ \
+private: \
+ PipelineHandler *createInstance(CameraManager *manager) \
+ { \
+ return new handler(manager); \
+ } \
+}; \
+static handler##Factory global_##handler##Factory;
+
+} /* namespace libcamera */
+
+#endif /* __LIBCAMERA_PIPELINE_HANDLER_H__ */
diff --git a/include/libcamera/internal/process.h b/include/libcamera/internal/process.h
new file mode 100644
index 00000000..d322fce1
--- /dev/null
+++ b/include/libcamera/internal/process.h
@@ -0,0 +1,55 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2019, Google Inc.
+ *
+ * process.h - Process object
+ */
+#ifndef __LIBCAMERA_PROCESS_H__
+#define __LIBCAMERA_PROCESS_H__
+
+#include <string>
+#include <vector>
+
+#include <libcamera/event_notifier.h>
+
+namespace libcamera {
+
+class Process final
+{
+public:
+ enum ExitStatus {
+ NotExited,
+ NormalExit,
+ SignalExit,
+ };
+
+ Process();
+ ~Process();
+
+ int start(const std::string &path,
+ const std::vector<std::string> &args = std::vector<std::string>(),
+ const std::vector<int> &fds = std::vector<int>());
+
+ ExitStatus exitStatus() const { return exitStatus_; }
+ int exitCode() const { return exitCode_; }
+
+ void kill();
+
+ Signal<Process *, enum ExitStatus, int> finished;
+
+private:
+ void closeAllFdsExcept(const std::vector<int> &fds);
+ int isolate();
+ void died(int wstatus);
+
+ pid_t pid_;
+ bool running_;
+ enum ExitStatus exitStatus_;
+ int exitCode_;
+
+ friend class ProcessManager;
+};
+
+} /* namespace libcamera */
+
+#endif /* __LIBCAMERA_PROCESS_H__ */
diff --git a/include/libcamera/internal/pub_key.h b/include/libcamera/internal/pub_key.h
new file mode 100644
index 00000000..f35bf373
--- /dev/null
+++ b/include/libcamera/internal/pub_key.h
@@ -0,0 +1,38 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2020, Google Inc.
+ *
+ * pub_key.h - Public key signature verification
+ */
+#ifndef __LIBCAMERA_PUB_KEY_H__
+#define __LIBCAMERA_PUB_KEY_H__
+
+#include <stdint.h>
+
+#include <libcamera/span.h>
+
+#if HAVE_GNUTLS
+struct gnutls_pubkey_st;
+#endif
+
+namespace libcamera {
+
+class PubKey
+{
+public:
+ PubKey(Span<const uint8_t> key);
+ ~PubKey();
+
+ bool isValid() const { return valid_; }
+ bool verify(Span<const uint8_t> data, Span<const uint8_t> sig) const;
+
+private:
+ bool valid_;
+#if HAVE_GNUTLS
+ struct gnutls_pubkey_st *pubkey_;
+#endif
+};
+
+} /* namespace libcamera */
+
+#endif /* __LIBCAMERA_PUB_KEY_H__ */
diff --git a/include/libcamera/internal/semaphore.h b/include/libcamera/internal/semaphore.h
new file mode 100644
index 00000000..4d93077c
--- /dev/null
+++ b/include/libcamera/internal/semaphore.h
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2019, Google Inc.
+ *
+ * semaphore.h - General-purpose counting semaphore
+ */
+#ifndef __LIBCAMERA_SEMAPHORE_H__
+#define __LIBCAMERA_SEMAPHORE_H__
+
+#include <condition_variable>
+
+#include "libcamera/internal/thread.h"
+
+namespace libcamera {
+
+class Semaphore
+{
+public:
+ Semaphore(unsigned int n = 0);
+
+ unsigned int available();
+ void acquire(unsigned int n = 1);
+ bool tryAcquire(unsigned int n = 1);
+ void release(unsigned int n = 1);
+
+private:
+ Mutex mutex_;
+ std::condition_variable cv_;
+ unsigned int available_;
+};
+
+} /* namespace libcamera */
+
+#endif /* __LIBCAMERA_SEMAPHORE_H__ */
diff --git a/include/libcamera/internal/thread.h b/include/libcamera/internal/thread.h
new file mode 100644
index 00000000..6594c9b0
--- /dev/null
+++ b/include/libcamera/internal/thread.h
@@ -0,0 +1,77 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2019, Google Inc.
+ *
+ * thread.h - Thread support
+ */
+#ifndef __LIBCAMERA_THREAD_H__
+#define __LIBCAMERA_THREAD_H__
+
+#include <memory>
+#include <mutex>
+#include <sys/types.h>
+#include <thread>
+
+#include <libcamera/signal.h>
+
+#include "libcamera/internal/utils.h"
+
+namespace libcamera {
+
+class EventDispatcher;
+class Message;
+class Object;
+class ThreadData;
+class ThreadMain;
+
+using Mutex = std::mutex;
+using MutexLocker = std::unique_lock<std::mutex>;
+
+class Thread
+{
+public:
+ Thread();
+ virtual ~Thread();
+
+ void start();
+ void exit(int code = 0);
+ bool wait(utils::duration duration = utils::duration::max());
+
+ bool isRunning();
+
+ Signal<Thread *> finished;
+
+ static Thread *current();
+ static pid_t currentId();
+
+ EventDispatcher *eventDispatcher();
+ void setEventDispatcher(std::unique_ptr<EventDispatcher> dispatcher);
+
+ void dispatchMessages();
+
+protected:
+ int exec();
+ virtual void run();
+
+private:
+ void startThread();
+ void finishThread();
+
+ void postMessage(std::unique_ptr<Message> msg, Object *receiver);
+ void removeMessages(Object *receiver);
+
+ friend class Object;
+ friend class ThreadData;
+ friend class ThreadMain;
+
+ void moveObject(Object *object);
+ void moveObject(Object *object, ThreadData *currentData,
+ ThreadData *targetData);
+
+ std::thread thread_;
+ ThreadData *data_;
+};
+
+} /* namespace libcamera */
+
+#endif /* __LIBCAMERA_THREAD_H__ */
diff --git a/include/libcamera/internal/utils.h b/include/libcamera/internal/utils.h
new file mode 100644
index 00000000..3334ff16
--- /dev/null
+++ b/include/libcamera/internal/utils.h
@@ -0,0 +1,197 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2018, Google Inc.
+ *
+ * utils.h - Miscellaneous utility functions
+ */
+#ifndef __LIBCAMERA_UTILS_H__
+#define __LIBCAMERA_UTILS_H__
+
+#include <algorithm>
+#include <chrono>
+#include <memory>
+#include <ostream>
+#include <sstream>
+#include <string>
+#include <string.h>
+#include <sys/time.h>
+
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
+
+#ifndef __DOXYGEN__
+
+/* uClibc and uClibc-ng don't provide O_TMPFILE */
+#ifndef O_TMPFILE
+#define O_TMPFILE (020000000 | O_DIRECTORY)
+#endif
+
+#endif
+
+namespace libcamera {
+
+namespace utils {
+
+const char *basename(const char *path);
+
+char *secure_getenv(const char *name);
+std::string dirname(const std::string &path);
+
+template<class InputIt1, class InputIt2>
+unsigned int set_overlap(InputIt1 first1, InputIt1 last1,
+ InputIt2 first2, InputIt2 last2)
+{
+ unsigned int count = 0;
+
+ while (first1 != last1 && first2 != last2) {
+ if (*first1 < *first2) {
+ ++first1;
+ } else {
+ if (!(*first2 < *first1))
+ count++;
+ ++first2;
+ }
+ }
+
+ return count;
+}
+
+/* C++11 doesn't provide std::clamp */
+template <typename T>
+const T& clamp(const T& v, const T& lo, const T& hi)
+{
+ return std::max(lo, std::min(v, hi));
+}
+
+using clock = std::chrono::steady_clock;
+using duration = std::chrono::steady_clock::duration;
+using time_point = std::chrono::steady_clock::time_point;
+
+struct timespec duration_to_timespec(const duration &value);
+std::string time_point_to_string(const time_point &time);
+
+#ifndef __DOXYGEN__
+struct _hex {
+ uint64_t v;
+ unsigned int w;
+};
+
+std::basic_ostream<char, std::char_traits<char>> &
+operator<<(std::basic_ostream<char, std::char_traits<char>> &stream, const _hex &h);
+#endif
+
+template<typename T>
+_hex hex(T value, unsigned int width = 0);
+
+#ifndef __DOXYGEN__
+template<>
+inline _hex hex<int32_t>(int32_t value, unsigned int width)
+{
+ return { static_cast<uint64_t>(value), width ? width : 8 };
+}
+
+template<>
+inline _hex hex<uint32_t>(uint32_t value, unsigned int width)
+{
+ return { static_cast<uint64_t>(value), width ? width : 8 };
+}
+
+template<>
+inline _hex hex<int64_t>(int64_t value, unsigned int width)
+{
+ return { static_cast<uint64_t>(value), width ? width : 16 };
+}
+
+template<>
+inline _hex hex<uint64_t>(uint64_t value, unsigned int width)
+{
+ return { static_cast<uint64_t>(value), width ? width : 16 };
+}
+#endif
+
+size_t strlcpy(char *dst, const char *src, size_t size);
+
+#ifndef __DOXYGEN__
+template<typename Container, typename UnaryOp>
+std::string join(const Container &items, const std::string &sep, UnaryOp op)
+{
+ std::ostringstream ss;
+ bool first = true;
+
+ for (typename Container::const_iterator it = std::begin(items);
+ it != std::end(items); ++it) {
+ if (!first)
+ ss << sep;
+ else
+ first = false;
+
+ ss << op(*it);
+ }
+
+ return ss.str();
+}
+
+template<typename Container>
+std::string join(const Container &items, const std::string &sep)
+{
+ std::ostringstream ss;
+ bool first = true;
+
+ for (typename Container::const_iterator it = std::begin(items);
+ it != std::end(items); ++it) {
+ if (!first)
+ ss << sep;
+ else
+ first = false;
+
+ ss << *it;
+ }
+
+ return ss.str();
+}
+#else
+template<typename Container, typename UnaryOp>
+std::string join(const Container &items, const std::string &sep, UnaryOp op = nullptr);
+#endif
+
+namespace details {
+
+class StringSplitter
+{
+public:
+ StringSplitter(const std::string &str, const std::string &delim);
+
+ class iterator
+ {
+ public:
+ iterator(const StringSplitter *ss, std::string::size_type pos);
+
+ iterator &operator++();
+ std::string operator*() const;
+ bool operator!=(const iterator &other) const;
+
+ private:
+ const StringSplitter *ss_;
+ std::string::size_type pos_;
+ std::string::size_type next_;
+ };
+
+ iterator begin() const;
+ iterator end() const;
+
+private:
+ std::string str_;
+ std::string delim_;
+};
+
+} /* namespace details */
+
+details::StringSplitter split(const std::string &str, const std::string &delim);
+
+std::string libcameraBuildPath();
+std::string libcameraSourcePath();
+
+} /* namespace utils */
+
+} /* namespace libcamera */
+
+#endif /* __LIBCAMERA_UTILS_H__ */
diff --git a/include/libcamera/internal/v4l2_controls.h b/include/libcamera/internal/v4l2_controls.h
new file mode 100644
index 00000000..cffe9efd
--- /dev/null
+++ b/include/libcamera/internal/v4l2_controls.h
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2019, Google Inc.
+ *
+ * v4l2_controls.h - V4L2 Controls Support
+ */
+
+#ifndef __LIBCAMERA_V4L2_CONTROLS_H__
+#define __LIBCAMERA_V4L2_CONTROLS_H__
+
+#include <linux/videodev2.h>
+
+#include <libcamera/controls.h>
+
+namespace libcamera {
+
+class V4L2ControlId : public ControlId
+{
+public:
+ V4L2ControlId(const struct v4l2_query_ext_ctrl &ctrl);
+};
+
+class V4L2ControlInfo : public ControlInfo
+{
+public:
+ V4L2ControlInfo(const struct v4l2_query_ext_ctrl &ctrl);
+};
+
+} /* namespace libcamera */
+
+#endif /* __LIBCAMERA_V4L2_CONTROLS_H__ */
diff --git a/include/libcamera/internal/v4l2_device.h b/include/libcamera/internal/v4l2_device.h
new file mode 100644
index 00000000..d491eafd
--- /dev/null
+++ b/include/libcamera/internal/v4l2_device.h
@@ -0,0 +1,60 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2019, Google Inc.
+ *
+ * v4l2_device.h - Common base for V4L2 video devices and subdevices
+ */
+#ifndef __LIBCAMERA_V4L2_DEVICE_H__
+#define __LIBCAMERA_V4L2_DEVICE_H__
+
+#include <map>
+#include <memory>
+#include <vector>
+
+#include <linux/videodev2.h>
+
+#include "libcamera/internal/log.h"
+#include "libcamera/internal/v4l2_controls.h"
+
+namespace libcamera {
+
+class V4L2Device : protected Loggable
+{
+public:
+ void close();
+ bool isOpen() const { return fd_ != -1; }
+
+ const ControlInfoMap &controls() const { return controls_; }
+
+ ControlList getControls(const std::vector<uint32_t> &ids);
+ int setControls(ControlList *ctrls);
+
+ const std::string &deviceNode() const { return deviceNode_; }
+
+protected:
+ V4L2Device(const std::string &deviceNode);
+ ~V4L2Device();
+
+ int open(unsigned int flags);
+ int setFd(int fd);
+
+ int ioctl(unsigned long request, void *argp);
+
+ int fd() { return fd_; }
+
+private:
+ void listControls();
+ void updateControls(ControlList *ctrls,
+ const struct v4l2_ext_control *v4l2Ctrls,
+ unsigned int count);
+
+ std::map<unsigned int, struct v4l2_query_ext_ctrl> controlInfo_;
+ std::vector<std::unique_ptr<V4L2ControlId>> controlIds_;
+ ControlInfoMap controls_;
+ std::string deviceNode_;
+ int fd_;
+};
+
+} /* namespace libcamera */
+
+#endif /* __LIBCAMERA_V4L2_DEVICE_H__ */
diff --git a/include/libcamera/internal/v4l2_pixelformat.h b/include/libcamera/internal/v4l2_pixelformat.h
new file mode 100644
index 00000000..0fe8a017
--- /dev/null
+++ b/include/libcamera/internal/v4l2_pixelformat.h
@@ -0,0 +1,49 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2019, Google Inc.
+ * Copyright (C) 2020, Raspberry Pi (Trading) Ltd.
+ *
+ * v4l2_pixelformat.h - V4L2 Pixel Format
+ */
+#ifndef __LIBCAMERA_V4L2_PIXELFORMAT_H__
+#define __LIBCAMERA_V4L2_PIXELFORMAT_H__
+
+#include <stdint.h>
+#include <string>
+
+#include <linux/videodev2.h>
+
+#include <libcamera/pixelformats.h>
+
+namespace libcamera {
+
+class V4L2PixelFormat
+{
+public:
+ V4L2PixelFormat()
+ : fourcc_(0)
+ {
+ }
+
+ explicit V4L2PixelFormat(uint32_t fourcc)
+ : fourcc_(fourcc)
+ {
+ }
+
+ bool isValid() const { return fourcc_ != 0; }
+ uint32_t fourcc() const { return fourcc_; }
+ operator uint32_t() const { return fourcc_; }
+
+ std::string toString() const;
+
+ PixelFormat toPixelFormat() const;
+ static V4L2PixelFormat fromPixelFormat(const PixelFormat &pixelFormat,
+ bool multiplanar);
+
+private:
+ uint32_t fourcc_;
+};
+
+} /* namespace libcamera */
+
+#endif /* __LIBCAMERA_V4L2_PIXELFORMAT_H__ */
diff --git a/include/libcamera/internal/v4l2_subdevice.h b/include/libcamera/internal/v4l2_subdevice.h
new file mode 100644
index 00000000..1be454f0
--- /dev/null
+++ b/include/libcamera/internal/v4l2_subdevice.h
@@ -0,0 +1,77 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2019, Google Inc.
+ *
+ * v4l2_subdevice.h - V4L2 Subdevice
+ */
+#ifndef __LIBCAMERA_V4L2_SUBDEVICE_H__
+#define __LIBCAMERA_V4L2_SUBDEVICE_H__
+
+#include <string>
+#include <vector>
+
+#include <libcamera/geometry.h>
+
+#include "libcamera/internal/formats.h"
+#include "libcamera/internal/log.h"
+#include "libcamera/internal/media_object.h"
+#include "libcamera/internal/v4l2_device.h"
+
+namespace libcamera {
+
+class MediaDevice;
+
+struct V4L2SubdeviceFormat {
+ uint32_t mbus_code;
+ Size size;
+
+ const std::string toString() const;
+ uint8_t bitsPerPixel() const;
+};
+
+class V4L2Subdevice : public V4L2Device
+{
+public:
+ enum Whence {
+ ActiveFormat,
+ TryFormat,
+ };
+
+ explicit V4L2Subdevice(const MediaEntity *entity);
+ V4L2Subdevice(const V4L2Subdevice &) = delete;
+ V4L2Subdevice &operator=(const V4L2Subdevice &) = delete;
+ ~V4L2Subdevice();
+
+ int open();
+
+ const MediaEntity *entity() const { return entity_; }
+
+ int getSelection(unsigned int pad, unsigned int target,
+ Rectangle *rect);
+ int setSelection(unsigned int pad, unsigned int target,
+ Rectangle *rect);
+
+ ImageFormats formats(unsigned int pad);
+
+ int getFormat(unsigned int pad, V4L2SubdeviceFormat *format,
+ Whence whence = ActiveFormat);
+ int setFormat(unsigned int pad, V4L2SubdeviceFormat *format,
+ Whence whence = ActiveFormat);
+
+ static V4L2Subdevice *fromEntityName(const MediaDevice *media,
+ const std::string &entity);
+
+protected:
+ std::string logPrefix() const;
+
+private:
+ std::vector<unsigned int> enumPadCodes(unsigned int pad);
+ std::vector<SizeRange> enumPadSizes(unsigned int pad,
+ unsigned int code);
+
+ const MediaEntity *entity_;
+};
+
+} /* namespace libcamera */
+
+#endif /* __LIBCAMERA_V4L2_SUBDEVICE_H__ */
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__ */
diff --git a/include/libcamera/meson.build b/include/libcamera/meson.build
index cea47eb8..f9c8e64b 100644
--- a/include/libcamera/meson.build
+++ b/include/libcamera/meson.build
@@ -23,6 +23,8 @@ libcamera_api = files([
include_dir = join_paths(libcamera_include_dir, 'libcamera')
+subdir('internal')
+
install_headers(libcamera_api,
subdir : include_dir)