diff options
Diffstat (limited to 'include/libcamera/internal')
49 files changed, 1039 insertions, 146 deletions
diff --git a/include/libcamera/internal/bayer_format.h b/include/libcamera/internal/bayer_format.h index 7d3e37c6..5c14bb5f 100644 --- a/include/libcamera/internal/bayer_format.h +++ b/include/libcamera/internal/bayer_format.h @@ -1,8 +1,8 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ /* - * Copyright (C) 2020, Raspberry Pi (Trading) Ltd. + * Copyright (C) 2020, Raspberry Pi Ltd * - * bayer_format.h - Bayer Pixel Format + * Bayer Pixel Format */ #pragma once @@ -34,6 +34,8 @@ public: None = 0, CSI2 = 1, IPU3 = 2, + PISP1 = 3, + PISP2 = 4, }; constexpr BayerFormat() diff --git a/include/libcamera/internal/byte_stream_buffer.h b/include/libcamera/internal/byte_stream_buffer.h index 0f4fce6f..5b1c10ab 100644 --- a/include/libcamera/internal/byte_stream_buffer.h +++ b/include/libcamera/internal/byte_stream_buffer.h @@ -2,7 +2,7 @@ /* * Copyright (C) 2019, Google Inc. * - * byte_stream_buffer.h - Byte stream buffer + * Byte stream buffer */ #pragma once diff --git a/include/libcamera/internal/camera.h b/include/libcamera/internal/camera.h index 597426a6..0add0428 100644 --- a/include/libcamera/internal/camera.h +++ b/include/libcamera/internal/camera.h @@ -2,7 +2,7 @@ /* * Copyright (C) 2021, Google Inc. * - * camera.h - Camera private data + * Camera private data */ #pragma once @@ -50,6 +50,7 @@ private: CameraRunning, }; + bool isAcquired() const; bool isRunning() const; int isAccessAllowed(State state, bool allowDisconnected = false, const char *from = __builtin_FUNCTION()) const; diff --git a/include/libcamera/internal/camera_controls.h b/include/libcamera/internal/camera_controls.h index ee6d382f..4a5a3ebc 100644 --- a/include/libcamera/internal/camera_controls.h +++ b/include/libcamera/internal/camera_controls.h @@ -2,7 +2,7 @@ /* * Copyright (C) 2019, Google Inc. * - * camera_controls.h - Camera controls + * Camera controls */ #pragma once diff --git a/include/libcamera/internal/camera_lens.h b/include/libcamera/internal/camera_lens.h index 277417da..5a4b993b 100644 --- a/include/libcamera/internal/camera_lens.h +++ b/include/libcamera/internal/camera_lens.h @@ -2,7 +2,7 @@ /* * Copyright (C) 2021, Google Inc. * - * camera_lens.h - A camera lens controller + * A camera lens controller */ #pragma once diff --git a/include/libcamera/internal/camera_manager.h b/include/libcamera/internal/camera_manager.h new file mode 100644 index 00000000..af9ed60a --- /dev/null +++ b/include/libcamera/internal/camera_manager.h @@ -0,0 +1,69 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2023, Ideas on Board Oy. + * + * Camera manager private data + */ + +#pragma once + +#include <libcamera/camera_manager.h> + +#include <map> +#include <memory> +#include <sys/types.h> +#include <vector> + +#include <libcamera/base/class.h> +#include <libcamera/base/mutex.h> +#include <libcamera/base/thread.h> +#include <libcamera/base/thread_annotations.h> + +#include "libcamera/internal/ipa_manager.h" +#include "libcamera/internal/process.h" + +namespace libcamera { + +class Camera; +class DeviceEnumerator; + +class CameraManager::Private : public Extensible::Private, public Thread +{ + LIBCAMERA_DECLARE_PUBLIC(CameraManager) + +public: + Private(); + + int start(); + void addCamera(std::shared_ptr<Camera> camera) LIBCAMERA_TSA_EXCLUDES(mutex_); + void removeCamera(std::shared_ptr<Camera> camera) LIBCAMERA_TSA_EXCLUDES(mutex_); + +protected: + void run() override; + +private: + int init(); + void createPipelineHandlers(); + void pipelineFactoryMatch(const PipelineHandlerFactoryBase *factory); + void cleanup() LIBCAMERA_TSA_EXCLUDES(mutex_); + + /* + * This mutex protects + * + * - initialized_ and status_ during initialization + * - cameras_ after initialization + */ + mutable Mutex mutex_; + std::vector<std::shared_ptr<Camera>> cameras_ LIBCAMERA_TSA_GUARDED_BY(mutex_); + + ConditionVariable cv_; + bool initialized_ LIBCAMERA_TSA_GUARDED_BY(mutex_); + int status_ LIBCAMERA_TSA_GUARDED_BY(mutex_); + + std::unique_ptr<DeviceEnumerator> enumerator_; + + IPAManager ipaManager_; + ProcessManager processManager_; +}; + +} /* namespace libcamera */ diff --git a/include/libcamera/internal/camera_sensor.h b/include/libcamera/internal/camera_sensor.h index b9f4d786..fc44ab98 100644 --- a/include/libcamera/internal/camera_sensor.h +++ b/include/libcamera/internal/camera_sensor.h @@ -2,7 +2,7 @@ /* * Copyright (C) 2019, Google Inc. * - * camera_sensor.h - A camera sensor + * A camera sensor */ #pragma once @@ -17,20 +17,25 @@ #include <libcamera/control_ids.h> #include <libcamera/controls.h> #include <libcamera/geometry.h> +#include <libcamera/orientation.h> +#include <libcamera/transform.h> #include <libcamera/ipa/core_ipa_interface.h> +#include "libcamera/internal/bayer_format.h" #include "libcamera/internal/formats.h" #include "libcamera/internal/v4l2_subdevice.h" namespace libcamera { -class BayerFormat; class CameraLens; class MediaEntity; +class SensorConfiguration; struct CameraSensorProperties; +enum class Orientation; + class CameraSensor : protected Loggable { public: @@ -41,32 +46,40 @@ public: const std::string &model() const { return model_; } const std::string &id() const { return id_; } + const MediaEntity *entity() const { return entity_; } + V4L2Subdevice *device() { return subdev_.get(); } + + CameraLens *focusLens() { return focusLens_.get(); } + const std::vector<unsigned int> &mbusCodes() const { return mbusCodes_; } std::vector<Size> sizes(unsigned int mbusCode) const; Size resolution() const; - const std::vector<controls::draft::TestPatternModeEnum> &testPatternModes() const - { - return testPatternModes_; - } - int setTestPatternMode(controls::draft::TestPatternModeEnum mode); V4L2SubdeviceFormat getFormat(const std::vector<unsigned int> &mbusCodes, const Size &size) const; - int setFormat(V4L2SubdeviceFormat *format); + int setFormat(V4L2SubdeviceFormat *format, + Transform transform = Transform::Identity); + int tryFormat(V4L2SubdeviceFormat *format) const; - const ControlInfoMap &controls() const; - ControlList getControls(const std::vector<uint32_t> &ids); - int setControls(ControlList *ctrls); - - V4L2Subdevice *device() { return subdev_.get(); } + int applyConfiguration(const SensorConfiguration &config, + Transform transform = Transform::Identity, + V4L2SubdeviceFormat *sensorFormat = nullptr); const ControlList &properties() const { return properties_; } int sensorInfo(IPACameraSensorInfo *info) const; + Transform computeTransform(Orientation *orientation) const; + BayerFormat::Order bayerOrder(Transform t) const; - void updateControlInfo(); + const ControlInfoMap &controls() const; + ControlList getControls(const std::vector<uint32_t> &ids); + int setControls(ControlList *ctrls); - CameraLens *focusLens() { return focusLens_.get(); } + const std::vector<controls::draft::TestPatternModeEnum> &testPatternModes() const + { + return testPatternModes_; + } + int setTestPatternMode(controls::draft::TestPatternModeEnum mode); protected: std::string logPrefix() const override; @@ -80,8 +93,8 @@ private: void initStaticProperties(); void initTestPatternModes(); int initProperties(); - int applyTestPatternMode(controls::draft::TestPatternModeEnum mode); int discoverAncillaryDevices(); + int applyTestPatternMode(controls::draft::TestPatternModeEnum mode); const MediaEntity *entity_; std::unique_ptr<V4L2Subdevice> subdev_; @@ -101,6 +114,9 @@ private: Size pixelArraySize_; Rectangle activeArea_; const BayerFormat *bayerFormat_; + bool supportFlips_; + bool flipsAlterBayerOrder_; + Orientation mountingOrientation_; ControlList properties_; diff --git a/include/libcamera/internal/camera_sensor_properties.h b/include/libcamera/internal/camera_sensor_properties.h index 1ee3cb99..480ac121 100644 --- a/include/libcamera/internal/camera_sensor_properties.h +++ b/include/libcamera/internal/camera_sensor_properties.h @@ -2,7 +2,7 @@ /* * Copyright (C) 2021, Google Inc. * - * camera_sensor_properties.h - Database of camera sensor properties + * Database of camera sensor properties */ #pragma once diff --git a/include/libcamera/internal/control_serializer.h b/include/libcamera/internal/control_serializer.h index 99e57fee..8a63ae44 100644 --- a/include/libcamera/internal/control_serializer.h +++ b/include/libcamera/internal/control_serializer.h @@ -2,7 +2,7 @@ /* * Copyright (C) 2019, Google Inc. * - * control_serializer.h - Control (de)serializer + * Control (de)serializer */ #pragma once @@ -47,9 +47,9 @@ private: static void store(const ControlValue &value, ByteStreamBuffer &buffer); static void store(const ControlInfo &info, ByteStreamBuffer &buffer); - ControlValue loadControlValue(ControlType type, ByteStreamBuffer &buffer, + ControlValue loadControlValue(ByteStreamBuffer &buffer, bool isArray = false, unsigned int count = 1); - ControlInfo loadControlInfo(ControlType type, ByteStreamBuffer &buffer); + ControlInfo loadControlInfo(ByteStreamBuffer &buffer); unsigned int serial_; unsigned int serialSeed_; diff --git a/include/libcamera/internal/control_validator.h b/include/libcamera/internal/control_validator.h index 26412d8b..260602f2 100644 --- a/include/libcamera/internal/control_validator.h +++ b/include/libcamera/internal/control_validator.h @@ -2,7 +2,7 @@ /* * Copyright (C) 2019, Google Inc. * - * control_validator.h - Control validator + * Control validator */ #pragma once diff --git a/include/libcamera/internal/converter.h b/include/libcamera/internal/converter.h new file mode 100644 index 00000000..5d74db6b --- /dev/null +++ b/include/libcamera/internal/converter.h @@ -0,0 +1,108 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2020, Laurent Pinchart + * Copyright 2022 NXP + * + * Generic format converter interface + */ + +#pragma once + +#include <functional> +#include <initializer_list> +#include <map> +#include <memory> +#include <string> +#include <tuple> +#include <vector> + +#include <libcamera/base/class.h> +#include <libcamera/base/signal.h> + +#include <libcamera/geometry.h> + +namespace libcamera { + +class FrameBuffer; +class MediaDevice; +class PixelFormat; +struct StreamConfiguration; + +class Converter +{ +public: + Converter(MediaDevice *media); + virtual ~Converter(); + + virtual int loadConfiguration(const std::string &filename) = 0; + + virtual bool isValid() const = 0; + + virtual std::vector<PixelFormat> formats(PixelFormat input) = 0; + virtual SizeRange sizes(const Size &input) = 0; + + virtual std::tuple<unsigned int, unsigned int> + strideAndFrameSize(const PixelFormat &pixelFormat, const Size &size) = 0; + + virtual int configure(const StreamConfiguration &inputCfg, + const std::vector<std::reference_wrapper<StreamConfiguration>> &outputCfgs) = 0; + virtual int exportBuffers(unsigned int output, unsigned int count, + std::vector<std::unique_ptr<FrameBuffer>> *buffers) = 0; + + virtual int start() = 0; + virtual void stop() = 0; + + virtual int queueBuffers(FrameBuffer *input, + const std::map<unsigned int, FrameBuffer *> &outputs) = 0; + + Signal<FrameBuffer *> inputBufferReady; + Signal<FrameBuffer *> outputBufferReady; + + const std::string &deviceNode() const { return deviceNode_; } + +private: + std::string deviceNode_; +}; + +class ConverterFactoryBase +{ +public: + ConverterFactoryBase(const std::string name, std::initializer_list<std::string> compatibles); + virtual ~ConverterFactoryBase() = default; + + const std::vector<std::string> &compatibles() const { return compatibles_; } + + static std::unique_ptr<Converter> create(MediaDevice *media); + static std::vector<ConverterFactoryBase *> &factories(); + static std::vector<std::string> names(); + +private: + LIBCAMERA_DISABLE_COPY_AND_MOVE(ConverterFactoryBase) + + static void registerType(ConverterFactoryBase *factory); + + virtual std::unique_ptr<Converter> createInstance(MediaDevice *media) const = 0; + + std::string name_; + std::vector<std::string> compatibles_; +}; + +template<typename _Converter> +class ConverterFactory : public ConverterFactoryBase +{ +public: + ConverterFactory(const char *name, std::initializer_list<std::string> compatibles) + : ConverterFactoryBase(name, compatibles) + { + } + + std::unique_ptr<Converter> createInstance(MediaDevice *media) const override + { + return std::make_unique<_Converter>(media); + } +}; + +#define REGISTER_CONVERTER(name, converter, compatibles) \ + static ConverterFactory<converter> global_##converter##Factory(name, compatibles); + +} /* namespace libcamera */ diff --git a/include/libcamera/internal/converter/converter_v4l2_m2m.h b/include/libcamera/internal/converter/converter_v4l2_m2m.h new file mode 100644 index 00000000..1126050c --- /dev/null +++ b/include/libcamera/internal/converter/converter_v4l2_m2m.h @@ -0,0 +1,98 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2020, Laurent Pinchart + * Copyright 2022 NXP + * + * V4l2 M2M Format converter interface + */ + +#pragma once + +#include <functional> +#include <map> +#include <memory> +#include <string> +#include <tuple> +#include <vector> + +#include <libcamera/base/log.h> +#include <libcamera/base/signal.h> + +#include <libcamera/pixel_format.h> + +#include "libcamera/internal/converter.h" + +namespace libcamera { + +class FrameBuffer; +class MediaDevice; +class Size; +class SizeRange; +struct StreamConfiguration; +class V4L2M2MDevice; + +class V4L2M2MConverter : public Converter +{ +public: + V4L2M2MConverter(MediaDevice *media); + + int loadConfiguration([[maybe_unused]] const std::string &filename) { return 0; } + bool isValid() const { return m2m_ != nullptr; } + + std::vector<PixelFormat> formats(PixelFormat input); + SizeRange sizes(const Size &input); + + std::tuple<unsigned int, unsigned int> + strideAndFrameSize(const PixelFormat &pixelFormat, const Size &size); + + int configure(const StreamConfiguration &inputCfg, + const std::vector<std::reference_wrapper<StreamConfiguration>> &outputCfg); + int exportBuffers(unsigned int output, unsigned int count, + std::vector<std::unique_ptr<FrameBuffer>> *buffers); + + int start(); + void stop(); + + int queueBuffers(FrameBuffer *input, + const std::map<unsigned int, FrameBuffer *> &outputs); + +private: + class Stream : protected Loggable + { + public: + Stream(V4L2M2MConverter *converter, unsigned int index); + + bool isValid() const { return m2m_ != nullptr; } + + int configure(const StreamConfiguration &inputCfg, + const StreamConfiguration &outputCfg); + int exportBuffers(unsigned int count, + std::vector<std::unique_ptr<FrameBuffer>> *buffers); + + int start(); + void stop(); + + int queueBuffers(FrameBuffer *input, FrameBuffer *output); + + protected: + std::string logPrefix() const override; + + private: + void captureBufferReady(FrameBuffer *buffer); + void outputBufferReady(FrameBuffer *buffer); + + V4L2M2MConverter *converter_; + unsigned int index_; + std::unique_ptr<V4L2M2MDevice> m2m_; + + unsigned int inputBufferCount_; + unsigned int outputBufferCount_; + }; + + std::unique_ptr<V4L2M2MDevice> m2m_; + + std::vector<Stream> streams_; + std::map<FrameBuffer *, unsigned int> queue_; +}; + +} /* namespace libcamera */ diff --git a/include/libcamera/internal/converter/meson.build b/include/libcamera/internal/converter/meson.build new file mode 100644 index 00000000..891e79e7 --- /dev/null +++ b/include/libcamera/internal/converter/meson.build @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: CC0-1.0 + +libcamera_internal_headers += files([ + 'converter_v4l2_m2m.h', +]) diff --git a/include/libcamera/internal/delayed_controls.h b/include/libcamera/internal/delayed_controls.h index 703fdb66..e8d3014d 100644 --- a/include/libcamera/internal/delayed_controls.h +++ b/include/libcamera/internal/delayed_controls.h @@ -1,8 +1,8 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ /* - * Copyright (C) 2020, Raspberry Pi (Trading) Ltd. + * Copyright (C) 2020, Raspberry Pi Ltd * - * delayed_controls.h - Helper to deal with controls that take effect with a delay + * Helper to deal with controls that take effect with a delay */ #pragma once @@ -51,7 +51,7 @@ private: bool updated; }; - /* \todo: Make the listSize configurable at instance creation time. */ + /* \todo Make the listSize configurable at instance creation time. */ static constexpr int listSize = 16; class ControlRingBuffer : public std::array<Info, listSize> { @@ -72,9 +72,6 @@ private: std::unordered_map<const ControlId *, ControlParams> controlParams_; unsigned int maxDelay_; - bool running_; - uint32_t firstSequence_; - uint32_t queueCount_; uint32_t writeCount_; /* \todo Evaluate if we should index on ControlId * or unsigned int */ diff --git a/include/libcamera/internal/device_enumerator.h b/include/libcamera/internal/device_enumerator.h index 72ec9a60..db3532a9 100644 --- a/include/libcamera/internal/device_enumerator.h +++ b/include/libcamera/internal/device_enumerator.h @@ -2,7 +2,7 @@ /* * Copyright (C) 2018, Google Inc. * - * device_enumerator.h - API to enumerate and find media devices + * API to enumerate and find media devices */ #pragma once diff --git a/include/libcamera/internal/device_enumerator_sysfs.h b/include/libcamera/internal/device_enumerator_sysfs.h index 3e84b83f..a5bfc711 100644 --- a/include/libcamera/internal/device_enumerator_sysfs.h +++ b/include/libcamera/internal/device_enumerator_sysfs.h @@ -2,7 +2,7 @@ /* * Copyright (C) 2019, Google Inc. * - * device_enumerator_sysfs.h - sysfs-based device enumerator + * sysfs-based device enumerator */ #pragma once diff --git a/include/libcamera/internal/device_enumerator_udev.h b/include/libcamera/internal/device_enumerator_udev.h index 1b3360df..1378c190 100644 --- a/include/libcamera/internal/device_enumerator_udev.h +++ b/include/libcamera/internal/device_enumerator_udev.h @@ -2,7 +2,7 @@ /* * Copyright (C) 2018-2019, Google Inc. * - * device_enumerator_udev.h - udev-based device enumerator + * udev-based device enumerator */ #pragma once diff --git a/include/libcamera/internal/dma_heaps.h b/include/libcamera/internal/dma_heaps.h new file mode 100644 index 00000000..f0a8aa5d --- /dev/null +++ b/include/libcamera/internal/dma_heaps.h @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2020, Raspberry Pi Ltd + * + * Helper class for dma-heap allocations. + */ + +#pragma once + +#include <stddef.h> + +#include <libcamera/base/flags.h> +#include <libcamera/base/unique_fd.h> + +namespace libcamera { + +class DmaHeap +{ +public: + enum class DmaHeapFlag { + Cma = 1 << 0, + System = 1 << 1, + }; + + using DmaHeapFlags = Flags<DmaHeapFlag>; + + DmaHeap(DmaHeapFlags flags = DmaHeapFlag::Cma); + ~DmaHeap(); + bool isValid() const { return dmaHeapHandle_.isValid(); } + UniqueFD alloc(const char *name, std::size_t size); + +private: + UniqueFD dmaHeapHandle_; +}; + +LIBCAMERA_FLAGS_ENABLE_OPERATORS(DmaHeap::DmaHeapFlag) + +} /* namespace libcamera */ diff --git a/include/libcamera/internal/formats.h b/include/libcamera/internal/formats.h index ee599765..71895cd8 100644 --- a/include/libcamera/internal/formats.h +++ b/include/libcamera/internal/formats.h @@ -2,7 +2,7 @@ /* * Copyright (C) 2019, Google Inc. * - * formats.h - libcamera image formats + * libcamera image formats */ #pragma once @@ -53,10 +53,7 @@ public: /* \todo Add support for non-contiguous memory planes */ const char *name; PixelFormat format; - struct { - V4L2PixelFormat single; - V4L2PixelFormat multi; - } v4l2Formats; + std::vector<V4L2PixelFormat> v4l2Formats; unsigned int bitsPerPixel; enum ColourEncoding colourEncoding; bool packed; diff --git a/include/libcamera/internal/framebuffer.h b/include/libcamera/internal/framebuffer.h index 8a9cc98e..e6698a45 100644 --- a/include/libcamera/internal/framebuffer.h +++ b/include/libcamera/internal/framebuffer.h @@ -2,7 +2,7 @@ /* * Copyright (C) 2020, Google Inc. * - * framebuffer.h - Internal frame buffer handling + * Internal frame buffer handling */ #pragma once @@ -22,7 +22,7 @@ class FrameBuffer::Private : public Extensible::Private LIBCAMERA_DECLARE_PUBLIC(FrameBuffer) public: - Private(); + Private(const std::vector<Plane> &planes, uint64_t cookie = 0); virtual ~Private(); void setRequest(Request *request) { request_ = request; } @@ -31,9 +31,15 @@ public: Fence *fence() const { return fence_.get(); } void setFence(std::unique_ptr<Fence> fence) { fence_ = std::move(fence); } - void cancel() { LIBCAMERA_O_PTR()->metadata_.status = FrameMetadata::FrameCancelled; } + void cancel() { metadata_.status = FrameMetadata::FrameCancelled; } + + FrameMetadata &metadata() { return metadata_; } private: + std::vector<Plane> planes_; + FrameMetadata metadata_; + uint64_t cookie_; + std::unique_ptr<Fence> fence_; Request *request_; bool isContiguous_; diff --git a/include/libcamera/internal/ipa_data_serializer.h b/include/libcamera/internal/ipa_data_serializer.h index a87449c9..337c948c 100644 --- a/include/libcamera/internal/ipa_data_serializer.h +++ b/include/libcamera/internal/ipa_data_serializer.h @@ -2,7 +2,7 @@ /* * Copyright (C) 2020, Google Inc. * - * ipa_data_serializer.h - Image Processing Algorithm data serializer + * Image Processing Algorithm data serializer */ #pragma once @@ -14,6 +14,7 @@ #include <type_traits> #include <vector> +#include <libcamera/base/flags.h> #include <libcamera/base/log.h> #include <libcamera/control_ids.h> @@ -32,7 +33,7 @@ LOG_DECLARE_CATEGORY(IPADataSerializer) namespace { template<typename T, - typename std::enable_if_t<std::is_arithmetic_v<T>> * = nullptr> + std::enable_if_t<std::is_arithmetic_v<T>> * = nullptr> void appendPOD(std::vector<uint8_t> &vec, T val) { constexpr size_t byteWidth = sizeof(val); @@ -134,7 +135,7 @@ public: static std::vector<V> deserialize(std::vector<uint8_t> &data, ControlSerializer *cs = nullptr) { - return deserialize(data.cbegin(), data.end(), cs); + return deserialize(data.cbegin(), data.cend(), cs); } static std::vector<V> deserialize(std::vector<uint8_t>::const_iterator dataBegin, @@ -142,13 +143,13 @@ public: ControlSerializer *cs = nullptr) { std::vector<SharedFD> fds; - return deserialize(dataBegin, dataEnd, fds.cbegin(), fds.end(), cs); + return deserialize(dataBegin, dataEnd, fds.cbegin(), fds.cend(), cs); } static std::vector<V> deserialize(std::vector<uint8_t> &data, std::vector<SharedFD> &fds, ControlSerializer *cs = nullptr) { - return deserialize(data.cbegin(), data.end(), fds.cbegin(), fds.end(), cs); + return deserialize(data.cbegin(), data.cend(), fds.cbegin(), fds.cend(), cs); } static std::vector<V> deserialize(std::vector<uint8_t>::const_iterator dataBegin, @@ -240,7 +241,7 @@ public: static std::map<K, V> deserialize(std::vector<uint8_t> &data, ControlSerializer *cs = nullptr) { - return deserialize(data.cbegin(), data.end(), cs); + return deserialize(data.cbegin(), data.cend(), cs); } static std::map<K, V> deserialize(std::vector<uint8_t>::const_iterator dataBegin, @@ -248,13 +249,13 @@ public: ControlSerializer *cs = nullptr) { std::vector<SharedFD> fds; - return deserialize(dataBegin, dataEnd, fds.cbegin(), fds.end(), cs); + return deserialize(dataBegin, dataEnd, fds.cbegin(), fds.cend(), cs); } static std::map<K, V> deserialize(std::vector<uint8_t> &data, std::vector<SharedFD> &fds, ControlSerializer *cs = nullptr) { - return deserialize(data.cbegin(), data.end(), fds.cbegin(), fds.end(), cs); + return deserialize(data.cbegin(), data.cend(), fds.cbegin(), fds.cend(), cs); } static std::map<K, V> deserialize(std::vector<uint8_t>::const_iterator dataBegin, @@ -301,6 +302,51 @@ public: } }; +/* Serialization format for Flags is same as for PODs */ +template<typename E> +class IPADataSerializer<Flags<E>> +{ +public: + static std::tuple<std::vector<uint8_t>, std::vector<SharedFD>> + serialize(const Flags<E> &data, [[maybe_unused]] ControlSerializer *cs = nullptr) + { + std::vector<uint8_t> dataVec; + dataVec.reserve(sizeof(Flags<E>)); + appendPOD<uint32_t>(dataVec, static_cast<typename Flags<E>::Type>(data)); + + return { dataVec, {} }; + } + + static Flags<E> deserialize(std::vector<uint8_t> &data, + [[maybe_unused]] ControlSerializer *cs = nullptr) + { + return deserialize(data.cbegin(), data.cend()); + } + + static Flags<E> deserialize(std::vector<uint8_t>::const_iterator dataBegin, + std::vector<uint8_t>::const_iterator dataEnd, + [[maybe_unused]] ControlSerializer *cs = nullptr) + { + return Flags<E>{ static_cast<E>(readPOD<uint32_t>(dataBegin, 0, dataEnd)) }; + } + + static Flags<E> deserialize(std::vector<uint8_t> &data, + [[maybe_unused]] std::vector<SharedFD> &fds, + [[maybe_unused]] ControlSerializer *cs = nullptr) + { + return deserialize(data.cbegin(), data.cend()); + } + + static Flags<E> deserialize(std::vector<uint8_t>::const_iterator dataBegin, + std::vector<uint8_t>::const_iterator dataEnd, + [[maybe_unused]] std::vector<SharedFD>::const_iterator fdsBegin, + [[maybe_unused]] std::vector<SharedFD>::const_iterator fdsEnd, + [[maybe_unused]] ControlSerializer *cs = nullptr) + { + return deserialize(dataBegin, dataEnd); + } +}; + #endif /* __DOXYGEN__ */ } /* namespace libcamera */ diff --git a/include/libcamera/internal/ipa_manager.h b/include/libcamera/internal/ipa_manager.h index 7f36e58e..c6f74e11 100644 --- a/include/libcamera/internal/ipa_manager.h +++ b/include/libcamera/internal/ipa_manager.h @@ -2,7 +2,7 @@ /* * Copyright (C) 2019, Google Inc. * - * ipa_manager.h - Image Processing Algorithm module manager + * Image Processing Algorithm module manager */ #pragma once @@ -47,6 +47,13 @@ public: return proxy; } +#if HAVE_IPA_PUBKEY + static const PubKey &pubKey() + { + return pubKey_; + } +#endif + private: static IPAManager *self_; diff --git a/include/libcamera/internal/ipa_module.h b/include/libcamera/internal/ipa_module.h index 8038bdee..7c49d3f3 100644 --- a/include/libcamera/internal/ipa_module.h +++ b/include/libcamera/internal/ipa_module.h @@ -2,7 +2,7 @@ /* * Copyright (C) 2019, Google Inc. * - * ipa_module.h - Image Processing Algorithm module + * Image Processing Algorithm module */ #pragma once diff --git a/include/libcamera/internal/ipa_proxy.h b/include/libcamera/internal/ipa_proxy.h index 781c8b62..ed6a5bcf 100644 --- a/include/libcamera/internal/ipa_proxy.h +++ b/include/libcamera/internal/ipa_proxy.h @@ -2,7 +2,7 @@ /* * Copyright (C) 2019, Google Inc. * - * ipa_proxy.h - Image Processing Algorithm proxy + * Image Processing Algorithm proxy */ #pragma once diff --git a/include/libcamera/internal/ipc_pipe.h b/include/libcamera/internal/ipc_pipe.h index ab5dd67c..a4560752 100644 --- a/include/libcamera/internal/ipc_pipe.h +++ b/include/libcamera/internal/ipc_pipe.h @@ -2,7 +2,7 @@ /* * Copyright (C) 2020, Google Inc. * - * ipc_pipe.h - Image Processing Algorithm IPC module for IPA proxies + * Image Processing Algorithm IPC module for IPA proxies */ #pragma once diff --git a/include/libcamera/internal/ipc_pipe_unixsocket.h b/include/libcamera/internal/ipc_pipe_unixsocket.h index 004d9539..4a0f6d57 100644 --- a/include/libcamera/internal/ipc_pipe_unixsocket.h +++ b/include/libcamera/internal/ipc_pipe_unixsocket.h @@ -2,7 +2,7 @@ /* * Copyright (C) 2020, Google Inc. * - * ipc_pipe_unixsocket.h - Image Processing Algorithm IPC module using unix socket + * Image Processing Algorithm IPC module using unix socket */ #pragma once diff --git a/include/libcamera/internal/ipc_unixsocket.h b/include/libcamera/internal/ipc_unixsocket.h index 3963d182..48bb7a94 100644 --- a/include/libcamera/internal/ipc_unixsocket.h +++ b/include/libcamera/internal/ipc_unixsocket.h @@ -2,7 +2,7 @@ /* * Copyright (C) 2019, Google Inc. * - * ipc_unixsocket.h - IPC mechanism based on Unix sockets + * IPC mechanism based on Unix sockets */ #pragma once diff --git a/include/libcamera/internal/mapped_framebuffer.h b/include/libcamera/internal/mapped_framebuffer.h index fb39adbf..6aaabf50 100644 --- a/include/libcamera/internal/mapped_framebuffer.h +++ b/include/libcamera/internal/mapped_framebuffer.h @@ -2,7 +2,7 @@ /* * Copyright (C) 2021, Google Inc. * - * mapped_framebuffer.h - Frame buffer memory mapping support + * Frame buffer memory mapping support */ #pragma once diff --git a/include/libcamera/internal/media_device.h b/include/libcamera/internal/media_device.h index eb8cfde4..bf2e475d 100644 --- a/include/libcamera/internal/media_device.h +++ b/include/libcamera/internal/media_device.h @@ -2,7 +2,7 @@ /* * Copyright (C) 2018, Google Inc. * - * media_device.h - Media device handler + * Media device handler */ #pragma once diff --git a/include/libcamera/internal/media_object.h b/include/libcamera/internal/media_object.h index b1572968..c9d77511 100644 --- a/include/libcamera/internal/media_object.h +++ b/include/libcamera/internal/media_object.h @@ -2,7 +2,7 @@ /* * Copyright (C) 2018, Google Inc. * - * media_object.h - Media Device objects: entities, pads and links. + * Media Device objects: entities, pads and links. */ #pragma once diff --git a/include/libcamera/internal/meson.build b/include/libcamera/internal/meson.build index 7a780d48..160fdc37 100644 --- a/include/libcamera/internal/meson.build +++ b/include/libcamera/internal/meson.build @@ -4,9 +4,9 @@ subdir('tracepoints') libcamera_tracepoint_header = custom_target( 'tp_header', - input: ['tracepoints.h.in', tracepoint_files], - output: 'tracepoints.h', - command: [gen_tracepoints_header, '@OUTPUT@', '@INPUT@'], + input : ['tracepoints.h.in', tracepoint_files], + output : 'tracepoints.h', + command : [gen_tracepoints_header, include_build_dir, '@OUTPUT@', '@INPUT@'], ) libcamera_internal_headers = files([ @@ -15,14 +15,17 @@ libcamera_internal_headers = files([ 'camera.h', 'camera_controls.h', 'camera_lens.h', + 'camera_manager.h', 'camera_sensor.h', 'camera_sensor_properties.h', 'control_serializer.h', 'control_validator.h', + 'converter.h', 'delayed_controls.h', 'device_enumerator.h', 'device_enumerator_sysfs.h', 'device_enumerator_udev.h', + 'dma_heaps.h', 'formats.h', 'framebuffer.h', 'ipa_manager.h', @@ -36,6 +39,7 @@ libcamera_internal_headers = files([ 'process.h', 'pub_key.h', 'request.h', + 'shared_mem_object.h', 'source_paths.h', 'sysfs.h', 'v4l2_device.h', @@ -44,3 +48,6 @@ libcamera_internal_headers = files([ 'v4l2_videodevice.h', 'yaml_parser.h', ]) + +subdir('converter') +subdir('software_isp') diff --git a/include/libcamera/internal/pipeline_handler.h b/include/libcamera/internal/pipeline_handler.h index c3e4c258..746a34f8 100644 --- a/include/libcamera/internal/pipeline_handler.h +++ b/include/libcamera/internal/pipeline_handler.h @@ -2,7 +2,7 @@ /* * Copyright (C) 2018, Google Inc. * - * pipeline_handler.h - Pipeline handler infrastructure + * Pipeline handler infrastructure */ #pragma once @@ -45,11 +45,11 @@ public: MediaDevice *acquireMediaDevice(DeviceEnumerator *enumerator, const DeviceMatch &dm); - bool lock(); - void unlock(); + bool acquire(); + void release(Camera *camera); - virtual CameraConfiguration *generateConfiguration(Camera *camera, - const StreamRoles &roles) = 0; + virtual std::unique_ptr<CameraConfiguration> generateConfiguration(Camera *camera, + Span<const StreamRole> roles) = 0; virtual int configure(Camera *camera, CameraConfiguration *config) = 0; virtual int exportFrameBuffers(Camera *camera, Stream *stream, @@ -65,6 +65,9 @@ public: bool completeBuffer(Request *request, FrameBuffer *buffer); void completeRequest(Request *request); + std::string configurationFile(const std::string &subdir, + const std::string &name) const; + const char *name() const { return name_; } protected: @@ -74,9 +77,13 @@ protected: virtual int queueRequestDevice(Camera *camera, Request *request) = 0; virtual void stopDevice(Camera *camera) = 0; + virtual void releaseDevice(Camera *camera); + CameraManager *manager_; private: + void unlockMediaDevices(); + void mediaDeviceDisconnected(MediaDevice *media); virtual void disconnect(); @@ -91,42 +98,50 @@ private: const char *name_; Mutex lock_; - bool lockOwner_ LIBCAMERA_TSA_GUARDED_BY(lock_); /* *Not* ownership of lock_ */ + unsigned int useCount_ LIBCAMERA_TSA_GUARDED_BY(lock_); - friend class PipelineHandlerFactory; + friend class PipelineHandlerFactoryBase; }; -class PipelineHandlerFactory +class PipelineHandlerFactoryBase { public: - PipelineHandlerFactory(const char *name); - virtual ~PipelineHandlerFactory() = default; + PipelineHandlerFactoryBase(const char *name); + virtual ~PipelineHandlerFactoryBase() = default; - std::shared_ptr<PipelineHandler> create(CameraManager *manager); + std::shared_ptr<PipelineHandler> create(CameraManager *manager) const; const std::string &name() const { return name_; } - static void registerType(PipelineHandlerFactory *factory); - static std::vector<PipelineHandlerFactory *> &factories(); + static std::vector<PipelineHandlerFactoryBase *> &factories(); + static const PipelineHandlerFactoryBase *getFactoryByName(const std::string &name); private: - virtual PipelineHandler *createInstance(CameraManager *manager) = 0; + static void registerType(PipelineHandlerFactoryBase *factory); + + virtual std::unique_ptr<PipelineHandler> + createInstance(CameraManager *manager) const = 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; +template<typename _PipelineHandler> +class PipelineHandlerFactory final : public PipelineHandlerFactoryBase +{ +public: + PipelineHandlerFactory(const char *name) + : PipelineHandlerFactoryBase(name) + { + } + + std::unique_ptr<PipelineHandler> + createInstance(CameraManager *manager) const override + { + return std::make_unique<_PipelineHandler>(manager); + } +}; + +#define REGISTER_PIPELINE_HANDLER(handler, name) \ + static PipelineHandlerFactory<handler> global_##handler##Factory(name); } /* namespace libcamera */ diff --git a/include/libcamera/internal/process.h b/include/libcamera/internal/process.h index 95e67e10..b1d07a5a 100644 --- a/include/libcamera/internal/process.h +++ b/include/libcamera/internal/process.h @@ -2,7 +2,7 @@ /* * Copyright (C) 2019, Google Inc. * - * process.h - Process object + * Process object */ #pragma once diff --git a/include/libcamera/internal/pub_key.h b/include/libcamera/internal/pub_key.h index a22ba037..c8cc04cb 100644 --- a/include/libcamera/internal/pub_key.h +++ b/include/libcamera/internal/pub_key.h @@ -2,7 +2,7 @@ /* * Copyright (C) 2020, Google Inc. * - * pub_key.h - Public key signature verification + * Public key signature verification */ #pragma once @@ -11,7 +11,9 @@ #include <libcamera/base/span.h> -#if HAVE_GNUTLS +#if HAVE_CRYPTO +struct evp_pkey_st; +#elif HAVE_GNUTLS struct gnutls_pubkey_st; #endif @@ -28,7 +30,9 @@ public: private: bool valid_; -#if HAVE_GNUTLS +#if HAVE_CRYPTO + struct evp_pkey_st *pubkey_; +#elif HAVE_GNUTLS struct gnutls_pubkey_st *pubkey_; #endif }; diff --git a/include/libcamera/internal/request.h b/include/libcamera/internal/request.h index 9dadd6c6..f5d98069 100644 --- a/include/libcamera/internal/request.h +++ b/include/libcamera/internal/request.h @@ -2,10 +2,10 @@ /* * Copyright (C) 2019, Google Inc. * - * request.h - Request class private data + * Request class private data */ -#ifndef __LIBCAMERA_INTERNAL_REQUEST_H__ -#define __LIBCAMERA_INTERNAL_REQUEST_H__ + +#pragma once #include <chrono> #include <map> @@ -37,7 +37,7 @@ public: bool completeBuffer(FrameBuffer *buffer); void complete(); void cancel(); - void reuse(); + void reset(); void prepare(std::chrono::milliseconds timeout = 0ms); Signal<> prepared; @@ -62,5 +62,3 @@ private: }; } /* namespace libcamera */ - -#endif /* __LIBCAMERA_INTERNAL_REQUEST_H__ */ diff --git a/include/libcamera/internal/shared_mem_object.h b/include/libcamera/internal/shared_mem_object.h new file mode 100644 index 00000000..2ab0189f --- /dev/null +++ b/include/libcamera/internal/shared_mem_object.h @@ -0,0 +1,127 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2023 Raspberry Pi Ltd + * Copyright (C) 2024 Andrei Konovalov + * Copyright (C) 2024 Dennis Bonke + * + * Helpers for shared memory allocations + */ +#pragma once + +#include <stddef.h> +#include <stdint.h> +#include <string> +#include <sys/mman.h> +#include <type_traits> +#include <utility> + +#include <libcamera/base/class.h> +#include <libcamera/base/shared_fd.h> +#include <libcamera/base/span.h> + +namespace libcamera { + +class SharedMem +{ +public: + SharedMem(); + + SharedMem(const std::string &name, std::size_t size); + SharedMem(SharedMem &&rhs); + + virtual ~SharedMem(); + + SharedMem &operator=(SharedMem &&rhs); + + const SharedFD &fd() const + { + return fd_; + } + + Span<uint8_t> mem() const + { + return mem_; + } + + explicit operator bool() const + { + return !mem_.empty(); + } + +private: + LIBCAMERA_DISABLE_COPY(SharedMem) + + SharedFD fd_; + + Span<uint8_t> mem_; +}; + +template<class T, typename = std::enable_if_t<std::is_standard_layout<T>::value>> +class SharedMemObject : public SharedMem +{ +public: + static constexpr std::size_t kSize = sizeof(T); + + SharedMemObject() + : SharedMem(), obj_(nullptr) + { + } + + template<class... Args> + SharedMemObject(const std::string &name, Args &&...args) + : SharedMem(name, kSize), obj_(nullptr) + { + if (mem().empty()) + return; + + obj_ = new (mem().data()) T(std::forward<Args>(args)...); + } + + SharedMemObject(SharedMemObject<T> &&rhs) + : SharedMem(std::move(rhs)) + { + this->obj_ = rhs.obj_; + rhs.obj_ = nullptr; + } + + ~SharedMemObject() + { + if (obj_) + obj_->~T(); + } + + SharedMemObject<T> &operator=(SharedMemObject<T> &&rhs) + { + SharedMem::operator=(std::move(rhs)); + this->obj_ = rhs.obj_; + rhs.obj_ = nullptr; + return *this; + } + + T *operator->() + { + return obj_; + } + + const T *operator->() const + { + return obj_; + } + + T &operator*() + { + return *obj_; + } + + const T &operator*() const + { + return *obj_; + } + +private: + LIBCAMERA_DISABLE_COPY(SharedMemObject) + + T *obj_; +}; + +} /* namespace libcamera */ diff --git a/include/libcamera/internal/software_isp/debayer_params.h b/include/libcamera/internal/software_isp/debayer_params.h new file mode 100644 index 00000000..ce1b5945 --- /dev/null +++ b/include/libcamera/internal/software_isp/debayer_params.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2023, Red Hat Inc. + * + * Authors: + * Hans de Goede <hdegoede@redhat.com> + * + * DebayerParams header + */ + +#pragma once + +namespace libcamera { + +struct DebayerParams { + static constexpr unsigned int kGain10 = 256; + + unsigned int gainR; + unsigned int gainG; + unsigned int gainB; + + float gamma; + /** + * \brief Level of the black point, 0..255, 0 is no correction. + */ + unsigned int blackLevel; +}; + +} /* namespace libcamera */ diff --git a/include/libcamera/internal/software_isp/meson.build b/include/libcamera/internal/software_isp/meson.build new file mode 100644 index 00000000..508ddddc --- /dev/null +++ b/include/libcamera/internal/software_isp/meson.build @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: CC0-1.0 + +libcamera_internal_headers += files([ + 'debayer_params.h', + 'software_isp.h', + 'swisp_stats.h', +]) diff --git a/include/libcamera/internal/software_isp/software_isp.h b/include/libcamera/internal/software_isp/software_isp.h new file mode 100644 index 00000000..7e9fae6a --- /dev/null +++ b/include/libcamera/internal/software_isp/software_isp.h @@ -0,0 +1,99 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2023, Linaro Ltd + * + * Simple software ISP implementation + */ + +#pragma once + +#include <functional> +#include <initializer_list> +#include <map> +#include <memory> +#include <string> +#include <tuple> +#include <vector> + +#include <libcamera/base/class.h> +#include <libcamera/base/log.h> +#include <libcamera/base/signal.h> +#include <libcamera/base/thread.h> + +#include <libcamera/geometry.h> +#include <libcamera/pixel_format.h> + +#include <libcamera/ipa/soft_ipa_interface.h> +#include <libcamera/ipa/soft_ipa_proxy.h> + +#include "libcamera/internal/camera_sensor.h" +#include "libcamera/internal/dma_heaps.h" +#include "libcamera/internal/pipeline_handler.h" +#include "libcamera/internal/shared_mem_object.h" +#include "libcamera/internal/software_isp/debayer_params.h" + +namespace libcamera { + +class DebayerCpu; +class FrameBuffer; +class PixelFormat; +struct StreamConfiguration; + +LOG_DECLARE_CATEGORY(SoftwareIsp) + +class SoftwareIsp +{ +public: + SoftwareIsp(PipelineHandler *pipe, const CameraSensor *sensor); + ~SoftwareIsp(); + + int loadConfiguration([[maybe_unused]] const std::string &filename) { return 0; } + + bool isValid() const; + + std::vector<PixelFormat> formats(PixelFormat input); + + SizeRange sizes(PixelFormat inputFormat, const Size &inputSize); + + std::tuple<unsigned int, unsigned int> + strideAndFrameSize(const PixelFormat &outputFormat, const Size &size); + + int configure(const StreamConfiguration &inputCfg, + const std::vector<std::reference_wrapper<StreamConfiguration>> &outputCfgs, + const ControlInfoMap &sensorControls); + + int exportBuffers(unsigned int output, unsigned int count, + std::vector<std::unique_ptr<FrameBuffer>> *buffers); + + void processStats(const ControlList &sensorControls); + + int start(); + void stop(); + + int queueBuffers(FrameBuffer *input, + const std::map<unsigned int, FrameBuffer *> &outputs); + + void process(FrameBuffer *input, FrameBuffer *output); + + Signal<FrameBuffer *> inputBufferReady; + Signal<FrameBuffer *> outputBufferReady; + Signal<> ispStatsReady; + Signal<const ControlList &> setSensorControls; + +private: + void saveIspParams(); + void setSensorCtrls(const ControlList &sensorControls); + void statsReady(); + void inputReady(FrameBuffer *input); + void outputReady(FrameBuffer *output); + + std::unique_ptr<DebayerCpu> debayer_; + Thread ispWorkerThread_; + SharedMemObject<DebayerParams> sharedParams_; + DebayerParams debayerParams_; + DmaHeap dmaHeap_; + + std::unique_ptr<ipa::soft::IPAProxySoft> ipa_; +}; + +} /* namespace libcamera */ diff --git a/include/libcamera/internal/software_isp/swisp_stats.h b/include/libcamera/internal/software_isp/swisp_stats.h new file mode 100644 index 00000000..ae11f112 --- /dev/null +++ b/include/libcamera/internal/software_isp/swisp_stats.h @@ -0,0 +1,49 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2023, Linaro Ltd + * + * Statistics data format used by the software ISP and software IPA + */ + +#pragma once + +#include <array> +#include <stdint.h> + +namespace libcamera { + +/** + * \brief Struct that holds the statistics for the Software ISP + * + * The struct value types are large enough to not overflow. + * Should they still overflow for some reason, no check is performed and they + * wrap around. + */ +struct SwIspStats { + /** + * \brief Holds the sum of all sampled red pixels + */ + uint64_t sumR_; + /** + * \brief Holds the sum of all sampled green pixels + */ + uint64_t sumG_; + /** + * \brief Holds the sum of all sampled blue pixels + */ + uint64_t sumB_; + /** + * \brief Number of bins in the yHistogram + */ + static constexpr unsigned int kYHistogramSize = 64; + /** + * \brief Type of the histogram. + */ + using Histogram = std::array<uint32_t, kYHistogramSize>; + /** + * \brief A histogram of luminance values + */ + Histogram yHistogram; +}; + +} /* namespace libcamera */ diff --git a/include/libcamera/internal/source_paths.h b/include/libcamera/internal/source_paths.h index be6f153b..14e64717 100644 --- a/include/libcamera/internal/source_paths.h +++ b/include/libcamera/internal/source_paths.h @@ -2,7 +2,7 @@ /* * Copyright (C) 2021, Google Inc. * - * source_paths.h - Identify libcamera source and build paths + * Identify libcamera source and build paths */ #pragma once diff --git a/include/libcamera/internal/sysfs.h b/include/libcamera/internal/sysfs.h index 917457be..aca60fb6 100644 --- a/include/libcamera/internal/sysfs.h +++ b/include/libcamera/internal/sysfs.h @@ -2,7 +2,7 @@ /* * Copyright (C) 2020, Google Inc. * - * sysfs.h - Miscellaneous utility functions to access sysfs + * Miscellaneous utility functions to access sysfs */ #pragma once diff --git a/include/libcamera/internal/tracepoints.h.in b/include/libcamera/internal/tracepoints.h.in index d0fc1365..f0962091 100644 --- a/include/libcamera/internal/tracepoints.h.in +++ b/include/libcamera/internal/tracepoints.h.in @@ -2,7 +2,7 @@ /* * Copyright (C) {{year}}, Google Inc. * - * tracepoints.h - Tracepoints with lttng + * Tracepoints with lttng * * This file is auto-generated. Do not edit. */ diff --git a/include/libcamera/internal/tracepoints/request.tp b/include/libcamera/internal/tracepoints/request.tp index f1e54497..4f367e91 100644 --- a/include/libcamera/internal/tracepoints/request.tp +++ b/include/libcamera/internal/tracepoints/request.tp @@ -5,10 +5,10 @@ * request.tp - Tracepoints for the request object */ -#include <libcamera/internal/request.h> - #include <libcamera/framebuffer.h> +#include "libcamera/internal/request.h" + TRACEPOINT_EVENT_CLASS( libcamera, request, diff --git a/include/libcamera/internal/v4l2_device.h b/include/libcamera/internal/v4l2_device.h index a52a5f2c..f5aa5024 100644 --- a/include/libcamera/internal/v4l2_device.h +++ b/include/libcamera/internal/v4l2_device.h @@ -2,7 +2,7 @@ /* * Copyright (C) 2019, Google Inc. * - * v4l2_device.h - Common base for V4L2 video devices and subdevices + * Common base for V4L2 video devices and subdevices */ #pragma once @@ -22,6 +22,8 @@ #include <libcamera/color_space.h> #include <libcamera/controls.h> +#include "libcamera/internal/formats.h" + namespace libcamera { class EventNotifier; @@ -59,7 +61,8 @@ protected: int fd() const { return fd_.get(); } template<typename T> - static std::optional<ColorSpace> toColorSpace(const T &v4l2Format); + static std::optional<ColorSpace> toColorSpace(const T &v4l2Format, + PixelFormatInfo::ColourEncoding colourEncoding); template<typename T> static int fromColorSpace(const std::optional<ColorSpace> &colorSpace, T &v4l2Format); @@ -67,8 +70,8 @@ protected: private: static ControlType v4l2CtrlType(uint32_t ctrlType); static std::unique_ptr<ControlId> v4l2ControlId(const v4l2_query_ext_ctrl &ctrl); - ControlInfo v4l2ControlInfo(const v4l2_query_ext_ctrl &ctrl); - ControlInfo v4l2MenuControlInfo(const v4l2_query_ext_ctrl &ctrl); + std::optional<ControlInfo> v4l2ControlInfo(const v4l2_query_ext_ctrl &ctrl); + std::optional<ControlInfo> v4l2MenuControlInfo(const v4l2_query_ext_ctrl &ctrl); void listControls(); void updateControls(ControlList *ctrls, diff --git a/include/libcamera/internal/v4l2_pixelformat.h b/include/libcamera/internal/v4l2_pixelformat.h index fb2d5d0b..c836346b 100644 --- a/include/libcamera/internal/v4l2_pixelformat.h +++ b/include/libcamera/internal/v4l2_pixelformat.h @@ -1,16 +1,18 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * Copyright (C) 2019, Google Inc. - * Copyright (C) 2020, Raspberry Pi (Trading) Ltd. + * Copyright (C) 2020, Raspberry Pi Ltd * - * v4l2_pixelformat.h - V4L2 Pixel Format + * V4L2 Pixel Format */ #pragma once +#include <functional> #include <ostream> #include <stdint.h> #include <string> +#include <vector> #include <linux/videodev2.h> @@ -43,9 +45,9 @@ public: std::string toString() const; const char *description() const; - PixelFormat toPixelFormat() const; - static V4L2PixelFormat fromPixelFormat(const PixelFormat &pixelFormat, - bool multiplanar = false); + PixelFormat toPixelFormat(bool warn = true) const; + static const std::vector<V4L2PixelFormat> & + fromPixelFormat(const PixelFormat &pixelFormat); private: uint32_t fourcc_; @@ -54,3 +56,15 @@ private: std::ostream &operator<<(std::ostream &out, const V4L2PixelFormat &f); } /* namespace libcamera */ + +namespace std { + +template<> +struct hash<libcamera::V4L2PixelFormat> { + size_t operator()(libcamera::V4L2PixelFormat const &format) const noexcept + { + return format.fourcc(); + } +}; + +} /* namespace std */ diff --git a/include/libcamera/internal/v4l2_subdevice.h b/include/libcamera/internal/v4l2_subdevice.h index 6fda52ad..a1de0fb0 100644 --- a/include/libcamera/internal/v4l2_subdevice.h +++ b/include/libcamera/internal/v4l2_subdevice.h @@ -2,7 +2,7 @@ /* * Copyright (C) 2019, Google Inc. * - * v4l2_subdevice.h - V4L2 Subdevice + * V4L2 Subdevice */ #pragma once @@ -13,6 +13,8 @@ #include <string> #include <vector> +#include <linux/v4l2-subdev.h> + #include <libcamera/base/class.h> #include <libcamera/base/log.h> @@ -27,13 +29,43 @@ namespace libcamera { class MediaDevice; +class MediaBusFormatInfo +{ +public: + enum class Type { + Image, + Metadata, + EmbeddedData, + }; + + bool isValid() const { return code != 0; } + + static const MediaBusFormatInfo &info(uint32_t code); + + const char *name; + uint32_t code; + Type type; + unsigned int bitsPerPixel; + PixelFormatInfo::ColourEncoding colourEncoding; +}; + +struct V4L2SubdeviceCapability final : v4l2_subdev_capability { + bool isReadOnly() const + { + return capabilities & V4L2_SUBDEV_CAP_RO_SUBDEV; + } + bool hasStreams() const + { + return capabilities & V4L2_SUBDEV_CAP_STREAMS; + } +}; + struct V4L2SubdeviceFormat { - uint32_t mbus_code; + uint32_t code; Size size; std::optional<ColorSpace> colorSpace; const std::string toString() const; - uint8_t bitsPerPixel() const; }; std::ostream &operator<<(std::ostream &out, const V4L2SubdeviceFormat &f); @@ -44,10 +76,43 @@ public: using Formats = std::map<unsigned int, std::vector<SizeRange>>; enum Whence { - ActiveFormat, - TryFormat, + TryFormat = V4L2_SUBDEV_FORMAT_TRY, + ActiveFormat = V4L2_SUBDEV_FORMAT_ACTIVE, + }; + + struct Stream { + Stream() + : pad(0), stream(0) + { + } + + Stream(unsigned int p, unsigned int s) + : pad(p), stream(s) + { + } + + unsigned int pad; + unsigned int stream; }; + struct Route { + Route() + : flags(0) + { + } + + Route(const Stream &snk, const Stream &src, uint32_t f) + : sink(snk), source(src), flags(f) + { + } + + Stream sink; + Stream source; + uint32_t flags; + }; + + using Routing = std::vector<Route>; + explicit V4L2Subdevice(const MediaEntity *entity); ~V4L2Subdevice(); @@ -55,19 +120,45 @@ public: const MediaEntity *entity() const { return entity_; } - int getSelection(unsigned int pad, unsigned int target, + int getSelection(const Stream &stream, unsigned int target, Rectangle *rect); - int setSelection(unsigned int pad, unsigned int target, + int getSelection(unsigned int pad, unsigned int target, Rectangle *rect) + { + return getSelection({ pad, 0 }, target, rect); + } + int setSelection(const Stream &stream, unsigned int target, Rectangle *rect); - - Formats formats(unsigned int pad); - + int setSelection(unsigned int pad, unsigned int target, Rectangle *rect) + { + return setSelection({ pad, 0 }, target, rect); + } + + Formats formats(const Stream &stream); + Formats formats(unsigned int pad) + { + return formats({ pad, 0 }); + } + + int getFormat(const Stream &stream, V4L2SubdeviceFormat *format, + Whence whence = ActiveFormat); int getFormat(unsigned int pad, V4L2SubdeviceFormat *format, + Whence whence = ActiveFormat) + { + return getFormat({ pad, 0 }, format, whence); + } + int setFormat(const Stream &stream, V4L2SubdeviceFormat *format, Whence whence = ActiveFormat); int setFormat(unsigned int pad, V4L2SubdeviceFormat *format, - Whence whence = ActiveFormat); + Whence whence = ActiveFormat) + { + return setFormat({ pad, 0 }, format, whence); + } + + int getRouting(Routing *routing, Whence whence = ActiveFormat); + int setRouting(Routing *routing, Whence whence = ActiveFormat); const std::string &model(); + const V4L2SubdeviceCapability &caps() const { return caps_; } static std::unique_ptr<V4L2Subdevice> fromEntityName(const MediaDevice *media, const std::string &entity); @@ -78,13 +169,28 @@ protected: private: LIBCAMERA_DISABLE_COPY(V4L2Subdevice) - std::vector<unsigned int> enumPadCodes(unsigned int pad); - std::vector<SizeRange> enumPadSizes(unsigned int pad, + std::optional<ColorSpace> + toColorSpace(const v4l2_mbus_framefmt &format) const; + + std::vector<unsigned int> enumPadCodes(const Stream &stream); + std::vector<SizeRange> enumPadSizes(const Stream &stream, unsigned int code); const MediaEntity *entity_; std::string model_; + struct V4L2SubdeviceCapability caps_; }; +bool operator==(const V4L2Subdevice::Stream &lhs, const V4L2Subdevice::Stream &rhs); +static inline bool operator!=(const V4L2Subdevice::Stream &lhs, + const V4L2Subdevice::Stream &rhs) +{ + return !(lhs == rhs); +} + +std::ostream &operator<<(std::ostream &out, const V4L2Subdevice::Stream &stream); +std::ostream &operator<<(std::ostream &out, const V4L2Subdevice::Route &route); +std::ostream &operator<<(std::ostream &out, const V4L2Subdevice::Routing &routing); + } /* namespace libcamera */ diff --git a/include/libcamera/internal/v4l2_videodevice.h b/include/libcamera/internal/v4l2_videodevice.h index 8525acbc..9057be08 100644 --- a/include/libcamera/internal/v4l2_videodevice.h +++ b/include/libcamera/internal/v4l2_videodevice.h @@ -2,7 +2,7 @@ /* * Copyright (C) 2019, Google Inc. * - * v4l2_videodevice.h - V4L2 Video Device + * V4L2 Video Device */ #pragma once @@ -14,6 +14,7 @@ #include <ostream> #include <stdint.h> #include <string> +#include <unordered_set> #include <vector> #include <linux/videodev2.h> @@ -228,6 +229,8 @@ public: static std::unique_ptr<V4L2VideoDevice> fromEntityName(const MediaDevice *media, const std::string &entity); + V4L2PixelFormat toV4L2PixelFormat(const PixelFormat &pixelFormat) const; + protected: std::string logPrefix() const override; @@ -240,6 +243,8 @@ private: Stopped, }; + int initFormats(); + int getFormatMeta(V4L2DeviceFormat *format); int trySetFormatMeta(V4L2DeviceFormat *format, bool set); @@ -263,9 +268,13 @@ private: void watchdogExpired(); + template<typename T> + static std::optional<ColorSpace> toColorSpace(const T &v4l2Format); + V4L2Capability caps_; V4L2DeviceFormat format_; const PixelFormatInfo *formatInfo_; + std::unordered_set<V4L2PixelFormat> pixelFormats_; enum v4l2_buf_type bufferType_; enum v4l2_memory memoryType_; diff --git a/include/libcamera/internal/yaml_parser.h b/include/libcamera/internal/yaml_parser.h index 064cf443..b6979d73 100644 --- a/include/libcamera/internal/yaml_parser.h +++ b/include/libcamera/internal/yaml_parser.h @@ -2,13 +2,14 @@ /* * Copyright (C) 2022, Google Inc. * - * yaml_parser.h - libcamera YAML parsing helper + * libcamera YAML parsing helper */ #pragma once #include <iterator> #include <map> +#include <optional> #include <string> #include <vector> @@ -24,12 +25,21 @@ class YamlParserContext; class YamlObject { private: - using DictContainer = std::map<std::string, std::unique_ptr<YamlObject>>; + struct Value { + Value(std::string &&k, std::unique_ptr<YamlObject> &&v) + : key(std::move(k)), value(std::move(v)) + { + } + std::string key; + std::unique_ptr<YamlObject> value; + }; + + using Container = std::vector<Value>; using ListContainer = std::vector<std::unique_ptr<YamlObject>>; public: #ifndef __DOXYGEN__ - template<typename Container, typename Derived> + template<typename Derived> class Iterator { public: @@ -65,10 +75,10 @@ public: } protected: - typename Container::const_iterator it_; + Container::const_iterator it_; }; - template<typename Container, typename Iterator> + template<typename Iterator> class Adapter { public: @@ -91,7 +101,7 @@ public: const Container &container_; }; - class ListIterator : public Iterator<ListContainer, ListIterator> + class ListIterator : public Iterator<ListIterator> { public: using value_type = const YamlObject &; @@ -100,16 +110,16 @@ public: value_type operator*() const { - return *it_->get(); + return *it_->value.get(); } pointer operator->() const { - return it_->get(); + return it_->value.get(); } }; - class DictIterator : public Iterator<DictContainer, DictIterator> + class DictIterator : public Iterator<DictIterator> { public: using value_type = std::pair<const std::string &, const YamlObject &>; @@ -118,17 +128,17 @@ public: value_type operator*() const { - return { it_->first, *it_->second.get() }; + return { it_->key, *it_->value.get() }; } }; - class DictAdapter : public Adapter<DictContainer, DictIterator> + class DictAdapter : public Adapter<DictIterator> { public: using key_type = std::string; }; - class ListAdapter : public Adapter<ListContainer, ListIterator> + class ListAdapter : public Adapter<ListIterator> { }; #endif /* __DOXYGEN__ */ @@ -153,9 +163,35 @@ public: #ifndef __DOXYGEN__ template<typename T, - typename std::enable_if_t< + std::enable_if_t< + std::is_same_v<bool, T> || + std::is_same_v<double, T> || + std::is_same_v<int8_t, T> || + std::is_same_v<uint8_t, T> || + std::is_same_v<int16_t, T> || + std::is_same_v<uint16_t, T> || + std::is_same_v<int32_t, T> || + std::is_same_v<uint32_t, T> || + std::is_same_v<std::string, T> || + std::is_same_v<Size, T>> * = nullptr> +#else + template<typename T> +#endif + std::optional<T> get() const; + + template<typename T> + T get(const T &defaultValue) const + { + return get<T>().value_or(defaultValue); + } + +#ifndef __DOXYGEN__ + template<typename T, + std::enable_if_t< std::is_same_v<bool, T> || std::is_same_v<double, T> || + std::is_same_v<int8_t, T> || + std::is_same_v<uint8_t, T> || std::is_same_v<int16_t, T> || std::is_same_v<uint16_t, T> || std::is_same_v<int32_t, T> || @@ -165,9 +201,9 @@ public: #else template<typename T> #endif - T get(const T &defaultValue, bool *ok = nullptr) const; + std::optional<std::vector<T>> getList() const; - DictAdapter asDict() const { return DictAdapter{ dictionary_ }; } + DictAdapter asDict() const { return DictAdapter{ list_ }; } ListAdapter asList() const { return ListAdapter{ list_ }; } const YamlObject &operator[](std::size_t index) const; @@ -189,8 +225,8 @@ private: Type type_; std::string value_; - ListContainer list_; - DictContainer dictionary_; + Container list_; + std::map<std::string, YamlObject *> dictionary_; }; class YamlParser final |