From 93e72b695e477ac1efc22a0bdddb177199cf2fb9 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 12 May 2020 00:58:34 +0300 Subject: libcamera: Move internal headers to include/libcamera/internal/ The libcamera internal headers are located in src/libcamera/include/. The directory is added to the compiler headers search path with a meson include_directories() directive, and internal headers are included with (e.g. for the internal semaphore.h header) #include "semaphore.h" All was well, until libcxx decided to implement the C++20 synchronization library. The __threading_support header gained a #include to include the pthread's semaphore support. As include_directories() adds src/libcamera/include/ to the compiler search path with -I, the internal semaphore.h is included instead of the pthread version. Needless to say, the compiler isn't happy. Three options have been considered to fix this issue: - Use -iquote instead of -I. The -iquote option instructs gcc to only consider the header search path for headers included with the "" version. Meson unfortunately doesn't support this option. - Rename the internal semaphore.h header. This was deemed to be the beginning of a long whack-a-mole game, where namespace clashes with system libraries would appear over time (possibly dependent on particular system configurations) and would need to be constantly fixed. - Move the internal headers to another directory to create a unique namespace through path components. This causes lots of churn in all the existing source files through the all project. The first option would be best, but isn't available to us due to missing support in meson. Even if -iquote support was added, we would need to fix the problem before a new version of meson containing the required support would be released. The third option is thus the only practical solution available. Bite the bullet, and do it, moving headers to include/libcamera/internal/. Signed-off-by: Laurent Pinchart Acked-by: Jacopo Mondi --- include/libcamera/internal/byte_stream_buffer.h | 89 +++++++ include/libcamera/internal/camera_controls.h | 30 +++ include/libcamera/internal/camera_sensor.h | 88 +++++++ include/libcamera/internal/control_serializer.h | 55 ++++ include/libcamera/internal/control_validator.h | 27 ++ include/libcamera/internal/device_enumerator.h | 57 +++++ .../libcamera/internal/device_enumerator_sysfs.h | 32 +++ .../libcamera/internal/device_enumerator_udev.h | 75 ++++++ include/libcamera/internal/event_dispatcher_poll.h | 58 +++++ include/libcamera/internal/file.h | 71 ++++++ include/libcamera/internal/formats.h | 58 +++++ include/libcamera/internal/ipa_context_wrapper.h | 50 ++++ include/libcamera/internal/ipa_manager.h | 51 ++++ include/libcamera/internal/ipa_module.h | 61 +++++ include/libcamera/internal/ipa_proxy.h | 70 ++++++ include/libcamera/internal/ipc_unixsocket.h | 59 +++++ include/libcamera/internal/log.h | 130 ++++++++++ include/libcamera/internal/media_device.h | 94 +++++++ include/libcamera/internal/media_object.h | 124 +++++++++ include/libcamera/internal/meson.build | 35 +++ include/libcamera/internal/message.h | 70 ++++++ include/libcamera/internal/pipeline_handler.h | 151 +++++++++++ include/libcamera/internal/process.h | 55 ++++ include/libcamera/internal/pub_key.h | 38 +++ include/libcamera/internal/semaphore.h | 34 +++ include/libcamera/internal/thread.h | 77 ++++++ include/libcamera/internal/utils.h | 197 +++++++++++++++ include/libcamera/internal/v4l2_controls.h | 31 +++ include/libcamera/internal/v4l2_device.h | 60 +++++ include/libcamera/internal/v4l2_pixelformat.h | 49 ++++ include/libcamera/internal/v4l2_subdevice.h | 77 ++++++ include/libcamera/internal/v4l2_videodevice.h | 277 +++++++++++++++++++++ include/libcamera/meson.build | 2 + 33 files changed, 2432 insertions(+) create mode 100644 include/libcamera/internal/byte_stream_buffer.h create mode 100644 include/libcamera/internal/camera_controls.h create mode 100644 include/libcamera/internal/camera_sensor.h create mode 100644 include/libcamera/internal/control_serializer.h create mode 100644 include/libcamera/internal/control_validator.h create mode 100644 include/libcamera/internal/device_enumerator.h create mode 100644 include/libcamera/internal/device_enumerator_sysfs.h create mode 100644 include/libcamera/internal/device_enumerator_udev.h create mode 100644 include/libcamera/internal/event_dispatcher_poll.h create mode 100644 include/libcamera/internal/file.h create mode 100644 include/libcamera/internal/formats.h create mode 100644 include/libcamera/internal/ipa_context_wrapper.h create mode 100644 include/libcamera/internal/ipa_manager.h create mode 100644 include/libcamera/internal/ipa_module.h create mode 100644 include/libcamera/internal/ipa_proxy.h create mode 100644 include/libcamera/internal/ipc_unixsocket.h create mode 100644 include/libcamera/internal/log.h create mode 100644 include/libcamera/internal/media_device.h create mode 100644 include/libcamera/internal/media_object.h create mode 100644 include/libcamera/internal/meson.build create mode 100644 include/libcamera/internal/message.h create mode 100644 include/libcamera/internal/pipeline_handler.h create mode 100644 include/libcamera/internal/process.h create mode 100644 include/libcamera/internal/pub_key.h create mode 100644 include/libcamera/internal/semaphore.h create mode 100644 include/libcamera/internal/thread.h create mode 100644 include/libcamera/internal/utils.h create mode 100644 include/libcamera/internal/v4l2_controls.h create mode 100644 include/libcamera/internal/v4l2_device.h create mode 100644 include/libcamera/internal/v4l2_pixelformat.h create mode 100644 include/libcamera/internal/v4l2_subdevice.h create mode 100644 include/libcamera/internal/v4l2_videodevice.h (limited to 'include') 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 +#include +#include + +#include + +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 + int read(T *t) + { + return read(reinterpret_cast(t), sizeof(*t)); + } + + template + int read(const Span &data) + { + return read(reinterpret_cast(data.data()), + data.size_bytes()); + } + + template + const std::remove_reference_t *read(size_t count = 1) + { + using return_type = const std::remove_reference_t *; + return reinterpret_cast(read(sizeof(T), count)); + } + + template + int write(const T *t) + { + return write(reinterpret_cast(t), sizeof(*t)); + } + + template + int write(const Span &data) + { + return write(reinterpret_cast(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 +#include +#include + +#include +#include + +#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 &mbusCodes() const { return mbusCodes_; } + const std::vector &sizes() const { return sizes_; } + const Size &resolution() const { return resolution_; } + + V4L2SubdeviceFormat getFormat(const std::vector &mbusCodes, + const Size &size) const; + int setFormat(V4L2SubdeviceFormat *format); + + const ControlInfoMap &controls() const; + ControlList getControls(const std::vector &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 subdev_; + unsigned int pad_; + + std::string model_; + + ImageFormats formats_; + Size resolution_; + std::vector mbusCodes_; + std::vector 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 +#include +#include + +#include + +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 + 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> controlIds_; + std::map infoMaps_; + std::map 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 + +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 +#include +#include + +#include + +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 entities_; +}; + +class DeviceEnumerator +{ +public: + static std::unique_ptr create(); + + virtual ~DeviceEnumerator(); + + virtual int init() = 0; + virtual int enumerate() = 0; + + std::shared_ptr search(const DeviceMatch &dm); + +protected: + std::unique_ptr createDevice(const std::string &deviceNode); + void addDevice(std::unique_ptr &&media); + void removeDevice(const std::string &deviceNode); + +private: + std::vector> 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 +#include + +#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 +#include +#include +#include +#include +#include + +#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>; + + struct MediaDeviceDeps { + MediaDeviceDeps(std::unique_ptr &&media, + DependencyMap &&deps) + : media_(std::move(media)), deps_(std::move(deps)) + { + } + + bool operator==(const MediaDeviceDeps &other) const + { + return media_ == other.media_; + } + + std::unique_ptr media_; + DependencyMap deps_; + }; + + std::set orphans_; + std::list pending_; + std::map 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 +#include +#include + +#include + +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 notifiers_; + std::list timers_; + int eventfd_; + + bool processingEvents_; + + int poll(std::vector *pollfds); + void processInterrupt(const struct pollfd &pfd); + void processNotifiers(const std::vector &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 +#include +#include + +#include + +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 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 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 +#include + +#include +#include + +#include "libcamera/internal/v4l2_pixelformat.h" + +namespace libcamera { + +class ImageFormats +{ +public: + int addFormat(unsigned int format, const std::vector &sizes); + + bool isEmpty() const; + std::vector formats() const; + const std::vector &sizes(unsigned int format) const; + const std::map> &data() const; + +private: + std::map> 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 + +#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 &streamConfig, + const std::map &entityControls) override; + + void mapBuffers(const std::vector &buffers) override; + void unmapBuffers(const std::vector &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 +#include + +#include +#include + +#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 createIPA(PipelineHandler *pipe, + uint32_t maxVersion, + uint32_t minVersion); + +private: + std::vector modules_; + + IPAManager(); + ~IPAManager(); + + void parseDir(const char *libDir, unsigned int maxDepth, + std::vector &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 +#include +#include + +#include +#include + +#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 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 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 +#include +#include + +#include + +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 create(IPAModule *ipam) = 0; + + const std::string &name() const { return name_; } + + static void registerType(IPAProxyFactory *factory); + static std::vector &factories(); + +private: + std::string name_; +}; + +#define REGISTER_IPA_PROXY(proxy) \ +class proxy##Factory final : public IPAProxyFactory \ +{ \ +public: \ + proxy##Factory() : IPAProxyFactory(#proxy) {} \ + std::unique_ptr create(IPAModule *ipam) \ + { \ + return std::make_unique(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 +#include +#include + +#include + +namespace libcamera { + +class IPCUnixSocket +{ +public: + struct Payload { + std::vector data; + std::vector fds; + }; + + IPCUnixSocket(); + ~IPCUnixSocket(); + + int create(); + int bind(int fd); + void close(); + bool isBound() const; + + int send(const Payload &payload); + int receive(Payload *payload); + + Signal 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 +#include + +#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 ×tamp() 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(({ \ + if (!(condition)) \ + LOG(Fatal) << "assertion \"" #condition "\" failed"; \ +})) +#else +#define ASSERT(condition) static_cast(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 +#include +#include +#include + +#include + +#include + +#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 &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 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 objects_; + MediaObject *object(unsigned int id); + bool addObject(MediaObject *object); + void clear(); + + std::vector 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 +#include + +#include + +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 &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 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 &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 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 + +#include + +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 pack, + Semaphore *semaphore = nullptr, + bool deleteMethod = false); + ~InvokeMessage(); + + Semaphore *semaphore() const { return semaphore_; } + + void invoke(); + +private: + BoundMethodBase *method_; + std::shared_ptr 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 +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#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 queuedRequests_; + ControlInfoMap controlInfo_; + ControlList properties_; + std::unique_ptr ipa_; + +private: + CameraData(const CameraData &) = delete; + CameraData &operator=(const CameraData &) = delete; +}; + +class PipelineHandler : public std::enable_shared_from_this, + 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> *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, + std::unique_ptr 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> mediaDevices_; + std::vector> cameras_; + std::map> cameraData_; + + const char *name_; + + friend class PipelineHandlerFactory; +}; + +class PipelineHandlerFactory +{ +public: + PipelineHandlerFactory(const char *name); + virtual ~PipelineHandlerFactory() {} + + std::shared_ptr create(CameraManager *manager); + + const std::string &name() const { return name_; } + + static void registerType(PipelineHandlerFactory *factory); + static std::vector &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 +#include + +#include + +namespace libcamera { + +class Process final +{ +public: + enum ExitStatus { + NotExited, + NormalExit, + SignalExit, + }; + + Process(); + ~Process(); + + int start(const std::string &path, + const std::vector &args = std::vector(), + const std::vector &fds = std::vector()); + + ExitStatus exitStatus() const { return exitStatus_; } + int exitCode() const { return exitCode_; } + + void kill(); + + Signal finished; + +private: + void closeAllFdsExcept(const std::vector &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 + +#include + +#if HAVE_GNUTLS +struct gnutls_pubkey_st; +#endif + +namespace libcamera { + +class PubKey +{ +public: + PubKey(Span key); + ~PubKey(); + + bool isValid() const { return valid_; } + bool verify(Span data, Span 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 + +#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 +#include +#include +#include + +#include + +#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; + +class Thread +{ +public: + Thread(); + virtual ~Thread(); + + void start(); + void exit(int code = 0); + bool wait(utils::duration duration = utils::duration::max()); + + bool isRunning(); + + Signal finished; + + static Thread *current(); + static pid_t currentId(); + + EventDispatcher *eventDispatcher(); + void setEventDispatcher(std::unique_ptr dispatcher); + + void dispatchMessages(); + +protected: + int exec(); + virtual void run(); + +private: + void startThread(); + void finishThread(); + + void postMessage(std::unique_ptr 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 +#include +#include +#include +#include +#include +#include +#include + +#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 +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 +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> & +operator<<(std::basic_ostream> &stream, const _hex &h); +#endif + +template +_hex hex(T value, unsigned int width = 0); + +#ifndef __DOXYGEN__ +template<> +inline _hex hex(int32_t value, unsigned int width) +{ + return { static_cast(value), width ? width : 8 }; +} + +template<> +inline _hex hex(uint32_t value, unsigned int width) +{ + return { static_cast(value), width ? width : 8 }; +} + +template<> +inline _hex hex(int64_t value, unsigned int width) +{ + return { static_cast(value), width ? width : 16 }; +} + +template<> +inline _hex hex(uint64_t value, unsigned int width) +{ + return { static_cast(value), width ? width : 16 }; +} +#endif + +size_t strlcpy(char *dst, const char *src, size_t size); + +#ifndef __DOXYGEN__ +template +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 +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 +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 + +#include + +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 +#include +#include + +#include + +#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 &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 controlInfo_; + std::vector> 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 +#include + +#include + +#include + +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 +#include + +#include + +#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 enumPadCodes(unsigned int pad); + std::vector 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 +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#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(v4l2_capability::driver); + } + const char *card() const + { + return reinterpret_cast(v4l2_capability::card); + } + const char *bus_info() const + { + return reinterpret_cast(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> &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 planes_; + }; + + std::atomic lastUsedCounter_; + std::vector 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> formats(uint32_t code = 0); + + int setSelection(unsigned int target, Rectangle *rect); + + int allocateBuffers(unsigned int count, + std::vector> *buffers); + int exportBuffers(unsigned int count, + std::vector> *buffers); + int importBuffers(unsigned int count); + int releaseBuffers(); + + int queueBuffer(FrameBuffer *buffer); + Signal bufferReady; + + int setFrameStartEnabled(bool enable); + Signal 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 enumPixelformats(uint32_t code); + std::vector enumSizes(V4L2PixelFormat pixelFormat); + + int requestBuffers(unsigned int count, enum v4l2_memory memoryType); + int createBuffers(unsigned int count, + std::vector> *buffers); + std::unique_ptr 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 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) -- cgit v1.2.1