summaryrefslogtreecommitdiff
path: root/include
AgeCommit message (Collapse)Author
2020-04-14libcamera: ipa: Remove IPAModuleInfo license fieldLaurent Pinchart
The IPAModuleInfo license field isn't needed anymore now that modules are cryptographically signed. Remove it. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
2020-04-14ipa: Add start() and stop() operationsNiklas Söderlund
Add two new operations to the IPA interface to start and stop it. The intention is that these functions shall be used by the IPA to perform actions when the camera is started and stopped. Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
2020-04-04libcamera: pixelformats: Replace set of modifiers with single valueKaaira Gupta
DRM fourccs look like they have a per-plane modifier, but in fact each of them should be same. Hence instead of passing a set of modifiers for each fourcc in PixelFormat class, we can pass just a single modifier. So, replace the set with a single value. Signed-off-by: Kaaira Gupta <kgupta@es.iitr.ac.in> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> [Fix compilation error in src/libcamera/pipeline/ipu3/ipu3.cpp] Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
2020-03-27libcamera: FrameBuffer: Add a setRequest() interfaceNiklas Söderlund
Add the ability to set the Request a buffer is associated with. This is needed for buffers that live inside a pipeline handler and is temporarily associated with a request as it's being processed inside the pipeline. While we are at it delete a stray semicolon. Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
2020-03-27libcamera: FrameBuffer: Add a method to copy buffer contentNiklas Söderlund
This method may be used to memory copy a whole FrameBuffer content from another buffer. The operation is not fast and should not be used without great care by pipelines. The intended use-case is to have an option to copy out RAW buffers from the middle of a pipeline. Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
2020-03-27include: drm_fourcc: Add Bayer FourCC and modifiersNiklas Söderlund
Add Bayer format and modifiers for patch submitted for upstream inclusion. The formats have not been accepted upstream yet but is needed to progress with RAW capture support in libcamera. Intention is to merge this in libcamera and update the header file the upstream patch is picked up upstream. Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se> Reviewed-by: Jacopo Mondi <jacopo@jmondi.org> Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
2020-03-27libcamera: stream: Add StillCaptureRaw roleNiklas Söderlund
Add a role for capturing high resolution, low frame rate, still images in RAW format. Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Jacopo Mondi <jacopo@jmondi.org>
2020-03-23libcamera: controls: Add zero-copy set API for ControlValueLaurent Pinchart
Extend the ControlValue class with a reserve() function to set the value without actually copying data, and a non-const data() function that allows writing data directly to the ControlValue storage. This allows allocating memory directly in ControlValue, potentially removing a data copy. Note that this change was implemented before ByteStreamBuffer gained the zero-copy read() variant, and doesn't actually save a copy in the control serializer. It however still simplifies ControlSerializer::loadControlValue(). Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Jacopo Mondi <jacopo@jmondi.org>
2020-03-20libcamera: controls: Don't over-optimize ControlValue layoutLaurent Pinchart
The ControlValue class size should be minimized to save space, as it can be instantiated in large numbers. The current implementation does so by specifying several members as bitfields, but does so too aggressively, resulting in fields being packed in an inefficient to access way on some platforms. For instance, on 32-bit x86, the numElements_ field is offset by 7 bits in a 32-bit word. This additionally causes a static assert that checks the size of the class to fail. Relax the constraints on the isArray_ and numElements_ fields to avoid inefficient access, and to ensure that the class size is identical across all platforms. This will need to be revisited anyway when stabilizing the ABI, so add a \todo comment as a reminder. Fixes: 1fa4b43402a0 ("libcamera: controls: Support array controls in ControlValue") Reported-by: Jan Engelhardt <jengelh@inai.de> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2020-03-20libcamera: controls: Move ControlValue size check to controls.cppLaurent Pinchart
The size of the ControlValue class is checked by a static_assert() to avoid accidental ABI breakages. There's no need to perform the check every time controls.h is included, move it to controls.cpp. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2020-03-20libcamera: controls: Add support for string controlsLaurent Pinchart
String controls are stored internally as an array of char, but the ControlValue constructor, get() and set() functions operate on an std::string for convenience. Array of strings are thus not supported. Unlike for other control types, the ControlInfo range reports the minimum and maximum allowed lengths of the string (the minimum will usually be 0), not the minimum and maximum value of each element. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Jacopo Mondi <jacopo@jmondi.org>
2020-03-20libcamera: controls: Rename ControlRange to ControlInfoLaurent Pinchart
To prepare for storage of additional information in the ControlRange structure, rename it to ControlInfo. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Jacopo Mondi <jacopo@jmondi.org>
2020-03-20libcamera: controls: Name all ControlInfoMap instance variables infoMapLaurent Pinchart
To prepare for the rename of ControlRange to ControlInfo, rename all the ControlInfoMap instance variables currently named info to infoMap. This will help avoiding namespace clashes. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Jacopo Mondi <jacopo@jmondi.org>
2020-03-19libcamera: geometry: Construct SizeRange from SizeLaurent Pinchart
The SizeRange constructors take minimum and maximum width and height values as separate arguments. We have a Size class to convey size information, use it in the constructors, and update the callers. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2020-03-18libcamera: framebuffer_allocator: Lift camera restrictions on allocatorLaurent Pinchart
The Camera class currently requires the allocator to have no allocated buffer before the camera is reconfigured, and the allocator to be destroyed before the camera is released. There's no basis for these restrictions anymore, remove them. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
2020-03-18libcamera: pipeline_handler: Decouple buffer import and exportLaurent Pinchart
Use the V4L2 buffer orphaning feature, exposed through V4L2VideoDevice::exportBuffers(), to decouple buffer import and export. The PipelineHandler::importFrameBuffers() function is now called for all streams regardless of whether exportFrameBuffers() has been called or not. This simplifies the Camera implementation slightly, and opens the door to additional simplifications. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
2020-03-18libcamera: PixelFormat: Mark all function arguments of type PixelFormat as ↵Niklas Söderlund
const reference PixelFormat was previously an alias for unsigned int but is now a class. Make all functions taking PixelFormat do so as a const reference. Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
2020-03-18libcamera: PixelFormat: Make constructor explicitLaurent Pinchart
To achieve the goal of preventing unwanted conversion between a DRM and a V4L2 FourCC, make the PixelFormat constructor that takes an integer value explicit. All users of pixel formats flagged by the compiler are fixed. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se> Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
2020-03-18libcamera: PixelFormat: Turn into a classNiklas Söderlund
Create a class to represent a pixel format. This is done to add support for modifiers for the formats. So far no modifiers are added by any pipeline handler, all plumbing to deal with them is however in place. Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
2020-03-18libcamera: pixelformats: include linux/drm_fourcc.hNiklas Söderlund
Instead of having to include linux/drm_fourcc.h everywhere a DRM FourCC is used in conjunction with PixelFormat include the header directly in pixelformats.h. Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
2020-03-08libcamera: controls: Fix strict aliasing violationLaurent Pinchart
gcc 8.3.0 for ARM complains about strict aliasing violations: ../../src/libcamera/controls.cpp: In member function ‘void libcamera::ControlValue::release()’: ../../src/libcamera/controls.cpp:111:13: error: dereferencing type-punned pointer will break strict-aliasing rules [-Werror=strict-aliasing] delete[] *reinterpret_cast<char **>(&storage_); Fix it and simplify the code at the same time. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2020-03-08include: libcamera: meson: Add libcamera.h to the libcamera_api arrayLaurent Pinchart
The libcamera_api array is meant to contain all the headers from the libcamera public API, for the purpose of generating documentation and creating the libcamera_dep dependency. libcamera.h is part of the libcamera public API, add it to the array. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com> Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
2020-03-08include: libcamera: meson: Add control headers to the libcamera_api arrayKieran Bingham
The libcamera_api array is meant to contain all the headers from the libcamera public API, for the purpose of generating documentation and creating the libcamera_dep dependency. The generated control headers are part of the libcamera public API, and used to be included in the libcamera_api array until commit f870591a9bf5 ("libcamera: properties: Add location property") inadvertently removed them. Add them back. Fixes: f870591a9bf5 ("libcamera: properties: Add location property") Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com> [Split the change out and reworded the commit message] Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
2020-03-08include: libcamera: Improve automation of libcamera.h generationLaurent Pinchart
The gen-header.sh script that generates libcamera.h takes all .h files in the include/libcamera/ directory, and manually adds the generated control_ids.h and version.h. This is fragile, as shown by the failure to add property_ids.h to the list in commit f870591a9bf5 ("libcamera: properties: Add location property"). To avoid future omissions, take all the .h.in files into account to generate libcamera.h. This also fixes the missing property_ids.h. Fixes: f870591a9bf5 ("libcamera: properties: Add location property") Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com> Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
2020-03-06libcamera: ipa: Support array controls in ipa_control_value_entryLaurent Pinchart
Report in a new field of the ipa_control_value_entry structure if the value contains an array. Reorganize the other fields of the structure to avoid increasing its size. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2020-03-06libcamera: controls: Add support for byte controlsJacopo Mondi
Add support for byte values to the control framework and to the control serializer. Signed-off-by: Jacopo Mondi <jacopo@jmondi.org> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2020-03-06libcamera: controls: Add support for float controlsJacopo Mondi
Add support for float values in Control<> and ControlValue classes. Signed-off-by: Jacopo Mondi <jacopo@jmondi.org> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2020-03-06libcamera: controls: Allow passing an std::initializer list to set()Laurent Pinchart
For array controls, the ControlList::set() function takes a value as a type convertible to Span<T>. This allows passing an std::array or an std::vector in addition to an explicit Span, but doesn't accept an std::initializer list as Span has no constructor that takes an initializer list. Callers are thus forced to create temporary objects explicitly, which isn't nice. Fix the issue by providing a ControlList::set() function that takes an std::initializer_list, and convert it to a Span internally. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2020-03-06libcamera: controls: Support array controls in ControlValueJacopo Mondi
Add array controls support to the ControlValue class. The polymorphic class can now store more than a single element and supports access and creation through the use of Span<>. Signed-off-by: Jacopo Mondi <jacopo@jmondi.org> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2020-03-06libcamera: controls: Expose raw data in ControlValueLaurent Pinchart
Add a data() function to the ControlValue class to expose the raw data stored by the class as a Span<const uint8_t>. This will be useful to simplify the serialization of ControlValue instances. The size computation for the raw data is moved from the ControlSerializer, which is updated accordingly to use the data() function in order to access the size. Simplification of the ControlSerializer will happen in a subsequent change. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2020-03-06libcamera: controls: Move Control constructor to controls.hLaurent Pinchart
To avoid defining all specializations of the Control constructor manually, move the definition of those functions to controls.h and turn them into a single template function. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2020-03-06libcamera: controls: Move ControlValue constructor to controls.hLaurent Pinchart
To avoid defining all specializations of the ControlValue constructor manually, move the definition of those functions to controls.h and turn them into a single template function. The default constructor is still kept in controls.cpp. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2020-03-06libcamera: controls: Move ControlValue get() and set() to controls.hLaurent Pinchart
To avoid defining all specializations of ControlValue::get() and ControlValue::set() manually, move the definition of those functions to controls.h and turn them into single template functions. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2020-03-06libcamera: controls: Add templates to convert a type T to a ControlTypeLaurent Pinchart
These will be used to implement ControlValue::get() and set() as template functions. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2020-03-06libcamera: controls: Return control by valueLaurent Pinchart
The ControlList::get() and ControlValue::get() methods return the control value by reference. This requires the ControlValue class to store the control value in the same form as the one returned by those functions. For the array controls that are soon to be added, the ControlValue class would need to store a span<> instance in addition to the control value itself, which would increase the required storage space. Prepare for support of array controls by returning from get() by value. As all control values are 8 bytes at most, this doesn't affect efficiency negatively. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2020-03-06libcamera: controls: Decouple control and value type in ControlList::set()Laurent Pinchart
The ControlList::set() method takes a reference to a Control<T>, and requires the value to be a reference to T. This prevents the set() method from being used with value types that are convertible to T, and in particular with std::array or std::vector value types when the Control type is a Span<> to support array controls. Fix this by decoupling the control type and value type in the template parameters. The compiler will still catch invalid conversions, including cases where the constructor of type T from the value type is explicit. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2020-03-06libcamera: controls: Reorder ControlValue methodsJacopo Mondi
Reorder functions in ControlValue class to group const methods together. Cosmetic change only. Signed-off-by: Jacopo Mondi <jacopo@jmondi.org> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2020-03-06libcamera: ipa: Make <ipa/ipa_controls.h> self-containedLaurent Pinchart
The <ipa/ipa_controls.h> header makes use of uint*_t types, but doesn't include stdint.h. Fix it, and include ipa_controls.h in ipa_controls.cpp to test compilation of the header on its own. While at it, fix the comment as the top of ipa_controls.cpp to refer to the correct file name. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2020-03-06libcamera: ipa: Remove unused IPA control typesJacopo Mondi
The ipa_control_range_data structure is only used to document the IPA control serialization format, but isn't used in code at all as the ControlRange entries are directly serialized to a byte stream buffer. This applies to the ipa_control_value_data structure that is solely used by ipa_control_range_data. Expand the documentation of the IPA control serialization format to describe the layout of the control range data in words and diagrams instead of through a C structure. Remove the unused structures as a result. Signed-off-by: Jacopo Mondi <jacopo@jmondi.org> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2020-03-06libcamera: Add a C++20-compliant std::span<> implementationJacopo Mondi
C++20 will contain a std::span<> class that provides view over a contiguous sequence of objects, the storage of which is owned by some other object. Add a compatible implementation to the utils namespace. This will be used to implement array controls. Signed-off-by: Jacopo Mondi <jacopo@jmondi.org> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Acked-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2020-02-18libcamera: Use C++14 std::*_t type traitsLaurent Pinchart
C++14 introduced useful type traits helpers named std::*_t as aliases to std::*<...>::type. Use them to simplify the code. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
2020-02-14libcamera: camera: Add Camera propertiesJacopo Mondi
Add a method to the Camera class to retrieve the Camera properties registered by the pipeline handler. While at it, reword the Camera::controls() operation documentation to specify that the camera control information are constant during the camera lifetime not their value, while the camera properties value are the actually static information. Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se> Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
2020-02-14libcamera: controls: Add default to ControlRangeJacopo Mondi
Augment the the ControlRange class to store the control default value. This is particularly relevant for v4l2 controls used to create Camera properties, which are constructed using immutable video device properties, whose value won't change at runtime. Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se> Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
2020-02-14libcamera: properties: Add location propertyJacopo Mondi
Re-use the Control generation infrastructure to generate libcamera properties and define the first 'Location' property. Introduce three additional files: - include/libcamera/property_ids.h Defines the properties ids - src/libcamera/property_ids.cpp Defines the properties Control<> instances - src/libcamera/property_ids.yaml Provide the first 'Location' property definition. Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
2020-02-14include: linux: Update v4l2-controls.hJacopo Mondi
Import a temporary version of the v4l2-controls.h with the newly added definition of V4L2_CID_CAMERA_SENSOR_LOCATION and V4L2_CID_CAMERA_SENSOR_ROTATION controls. Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
2020-01-23libcamera: camera: Move private data members to private implementationLaurent Pinchart
Use the d-pointer idiom ([1], [2]) to hide the private data members from the Camera class interface. This will ease maintaining ABI compatibility, and prepares for the implementation of the Camera class threading model. The FrameBufferAllocator class accesses the Camera private data members directly. In order to hide them, this pattern is replaced with new private member functions in the Camera class, and the FrameBufferAllocator is updated accordingly. [1] https://wiki.qt.io/D-Pointer [2] https://en.cppreference.com/w/cpp/language/pimpl Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
2020-01-23libcamera: camera_manager: Return a copy of the vector from cameras()Laurent Pinchart
Making CameraManager::cameras() thread-safe requires returning a copy of the cameras vector instead of a reference. This is also required for hot-plugging support and is thus desirable. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
2020-01-23libcamera: camera_manager: Move private data members to private implementationLaurent Pinchart
Use the d-pointer idiom ([1], [2]) to hide the private data members from the CameraManager class interface. This will ease maintaining ABI compatibility, and prepares for the implementation of the CameraManager class threading model. [1] https://wiki.qt.io/D-Pointer [2] https://en.cppreference.com/w/cpp/language/pimpl Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com> Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
2020-01-22libcamera: signal: Make slots list privateLaurent Pinchart
The slots list is touched from most of the Signal template functions. In order to prepare for thread-safety, move handling of the list to a small number of non-template functions in the SignalBase class. This incidently fixes a bug in signal disconnection handling where the signal wasn't removed from the object's signals list, as pointed out by the signals unit test. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Jacopo Mondi <jacopo@jmondi.org> Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
2020-01-22libcamera: bound_method: Use std::index_sequenceLaurent Pinchart
Now that we're using C++-14, replace the manual implementation of std::integer_sequence with std::index_sequence, a specialization of std::integer_sequence with the integer type equal to std::size_t. The template parameter S that denotes a sequence is replaced with I to align with the usage examples of cppreference.com. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Jacopo Mondi <jacopo@jmondi.org> Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
*pad : entity_->pads()) { if (pad->flags() & MEDIA_PAD_FL_SOURCE) { pad_ = pad->index(); break; } } if (pad_ == UINT_MAX) { LOG(CameraSensor, Error) << "Sensors with more than one pad are not supported"; return -EINVAL; } switch (entity_->function()) { case MEDIA_ENT_F_CAM_SENSOR: case MEDIA_ENT_F_PROC_VIDEO_ISP: break; default: LOG(CameraSensor, Error) << "Invalid sensor function " << utils::hex(entity_->function()); return -EINVAL; } /* Create and open the subdev. */ subdev_ = std::make_unique<V4L2Subdevice>(entity_); int ret = subdev_->open(); if (ret < 0) return ret; /* * Clear any flips to be sure we get the "native" Bayer order. This is * harmless for sensors where the flips don't affect the Bayer order. */ ControlList ctrls(subdev_->controls()); if (subdev_->controls().find(V4L2_CID_HFLIP) != subdev_->controls().end()) ctrls.set(V4L2_CID_HFLIP, 0); if (subdev_->controls().find(V4L2_CID_VFLIP) != subdev_->controls().end()) ctrls.set(V4L2_CID_VFLIP, 0); subdev_->setControls(&ctrls); /* Enumerate, sort and cache media bus codes and sizes. */ formats_ = subdev_->formats(pad_); if (formats_.empty()) { LOG(CameraSensor, Error) << "No image format found"; return -EINVAL; } mbusCodes_ = utils::map_keys(formats_); std::sort(mbusCodes_.begin(), mbusCodes_.end()); for (const auto &format : formats_) { const std::vector<SizeRange> &ranges = format.second; std::transform(ranges.begin(), ranges.end(), std::back_inserter(sizes_), [](const SizeRange &range) { return range.max; }); } std::sort(sizes_.begin(), sizes_.end()); /* Remove duplicates. */ auto last = std::unique(sizes_.begin(), sizes_.end()); sizes_.erase(last, sizes_.end()); /* * VIMC is a bit special, as it does not yet support all the mandatory * requirements regular sensors have to respect. * * Do not validate the driver if it's VIMC and initialize the sensor * properties with static information. * * \todo Remove the special case once the VIMC driver has been * updated in all test platforms. */ if (entity_->device()->driver() == "vimc") { initVimcDefaultProperties(); ret = initProperties(); if (ret) return ret; return discoverAncillaryDevices(); } /* Get the color filter array pattern (only for RAW sensors). */ for (unsigned int mbusCode : mbusCodes_) { const BayerFormat &bayerFormat = BayerFormat::fromMbusCode(mbusCode); if (bayerFormat.isValid()) { bayerFormat_ = &bayerFormat; break; } } ret = validateSensorDriver(); if (ret) return ret; ret = initProperties(); if (ret) return ret; ret = discoverAncillaryDevices(); if (ret) return ret; /* * Set HBLANK to the minimum to start with a well-defined line length, * allowing IPA modules that do not modify HBLANK to use the sensor * minimum line length in their calculations. * * At present, there is no way of knowing if a control is read-only. * As a workaround, assume that if the minimum and maximum values of * the V4L2_CID_HBLANK control are the same, it implies the control * is read-only. * * \todo The control API ought to have a flag to specify if a control * is read-only which could be used below. */ const ControlInfo hblank = ctrls.infoMap()->at(V4L2_CID_HBLANK); const int32_t hblankMin = hblank.min().get<int32_t>(); const int32_t hblankMax = hblank.max().get<int32_t>(); if (hblankMin != hblankMax) { ControlList ctrl(subdev_->controls()); ctrl.set(V4L2_CID_HBLANK, hblankMin); ret = subdev_->setControls(&ctrl); if (ret) return ret; } return applyTestPatternMode(controls::draft::TestPatternModeEnum::TestPatternModeOff); } int CameraSensor::validateSensorDriver() { int err = 0; /* * Optional controls are used to register optional sensor properties. If * not present, some values will be defaulted. */ static constexpr uint32_t optionalControls[] = { V4L2_CID_CAMERA_SENSOR_ROTATION, }; const ControlIdMap &controls = subdev_->controls().idmap(); for (uint32_t ctrl : optionalControls) { if (!controls.count(ctrl)) LOG(CameraSensor, Debug) << "Optional V4L2 control " << utils::hex(ctrl) << " not supported"; } /* * Recommended controls are similar to optional controls, but will * become mandatory in the near future. Be loud if they're missing. */ static constexpr uint32_t recommendedControls[] = { V4L2_CID_CAMERA_ORIENTATION, }; for (uint32_t ctrl : recommendedControls) { if (!controls.count(ctrl)) { LOG(CameraSensor, Warning) << "Recommended V4L2 control " << utils::hex(ctrl) << " not supported"; err = -EINVAL; } } /* * Verify if sensor supports horizontal/vertical flips * * \todo Handle horizontal and vertical flips independently. */ const struct v4l2_query_ext_ctrl *hflipInfo = subdev_->controlInfo(V4L2_CID_HFLIP); const struct v4l2_query_ext_ctrl *vflipInfo = subdev_->controlInfo(V4L2_CID_VFLIP); if (hflipInfo && !(hflipInfo->flags & V4L2_CTRL_FLAG_READ_ONLY) && vflipInfo && !(vflipInfo->flags & V4L2_CTRL_FLAG_READ_ONLY)) supportFlips_ = true; if (!supportFlips_) LOG(CameraSensor, Debug) << "Camera sensor does not support horizontal/vertical flip"; /* * Make sure the required selection targets are supported. * * Failures in reading any of the targets are not deemed to be fatal, * but some properties and features, like constructing a * IPACameraSensorInfo for the IPA module, won't be supported. * * \todo Make support for selection targets mandatory as soon as all * test platforms have been updated. */ Rectangle rect; int ret = subdev_->getSelection(pad_, V4L2_SEL_TGT_CROP_BOUNDS, &rect); if (ret) { /* * Default the pixel array size to the largest size supported * by the sensor. The sizes_ vector is sorted in ascending * order, the largest size is thus the last element. */ pixelArraySize_ = sizes_.back(); LOG(CameraSensor, Warning) << "The PixelArraySize property has been defaulted to " << pixelArraySize_; err = -EINVAL; } else { pixelArraySize_ = rect.size(); } ret = subdev_->getSelection(pad_, V4L2_SEL_TGT_CROP_DEFAULT, &activeArea_); if (ret) { activeArea_ = Rectangle(pixelArraySize_); LOG(CameraSensor, Warning) << "The PixelArrayActiveAreas property has been defaulted to " << activeArea_; err = -EINVAL; } ret = subdev_->getSelection(pad_, V4L2_SEL_TGT_CROP, &rect); if (ret) { LOG(CameraSensor, Warning) << "Failed to retrieve the sensor crop rectangle"; err = -EINVAL; } if (err) { LOG(CameraSensor, Warning) << "The sensor kernel driver needs to be fixed"; LOG(CameraSensor, Warning) << "See Documentation/sensor_driver_requirements.rst in the libcamera sources for more information"; } if (!bayerFormat_) return 0; /* * For raw sensors, make sure the sensor driver supports the controls * required by the CameraSensor class. */ static constexpr uint32_t mandatoryControls[] = { V4L2_CID_ANALOGUE_GAIN, V4L2_CID_EXPOSURE, V4L2_CID_HBLANK, V4L2_CID_PIXEL_RATE, V4L2_CID_VBLANK, }; err = 0; for (uint32_t ctrl : mandatoryControls) { if (!controls.count(ctrl)) { LOG(CameraSensor, Error) << "Mandatory V4L2 control " << utils::hex(ctrl) << " not available"; err = -EINVAL; } } if (err) { LOG(CameraSensor, Error) << "The sensor kernel driver needs to be fixed"; LOG(CameraSensor, Error) << "See Documentation/sensor_driver_requirements.rst in the libcamera sources for more information"; return err; } return 0; } /* * \brief Initialize properties that cannot be intialized by the * regular initProperties() function for VIMC */ void CameraSensor::initVimcDefaultProperties() { /* Use the largest supported size. */ pixelArraySize_ = sizes_.back(); activeArea_ = Rectangle(pixelArraySize_); } void CameraSensor::initStaticProperties() { staticProps_ = CameraSensorProperties::get(model_); if (!staticProps_) return; /* Register the properties retrieved from the sensor database. */ properties_.set(properties::UnitCellSize, staticProps_->unitCellSize); initTestPatternModes(); } void CameraSensor::initTestPatternModes() { const auto &v4l2TestPattern = controls().find(V4L2_CID_TEST_PATTERN); if (v4l2TestPattern == controls().end()) { LOG(CameraSensor, Debug) << "V4L2_CID_TEST_PATTERN is not supported"; return; } const auto &testPatternModes = staticProps_->testPatternModes; if (testPatternModes.empty()) { /* * The camera sensor supports test patterns but we don't know * how to map them so this should be fixed. */ LOG(CameraSensor, Debug) << "No static test pattern map for \'" << model() << "\'"; return; } /* * Create a map that associates the V4L2 control index to the test * pattern mode by reversing the testPatternModes map provided by the * camera sensor properties. This makes it easier to verify if the * control index is supported in the below for loop that creates the * list of supported test patterns. */ std::map<int32_t, controls::draft::TestPatternModeEnum> indexToTestPatternMode; for (const auto &it : testPatternModes) indexToTestPatternMode[it.second] = it.first; for (const ControlValue &value : v4l2TestPattern->second.values()) { const int32_t index = value.get<int32_t>(); const auto it = indexToTestPatternMode.find(index); if (it == indexToTestPatternMode.end()) { LOG(CameraSensor, Debug) << "Test pattern mode " << index << " ignored"; continue; } testPatternModes_.push_back(it->second); } } int CameraSensor::initProperties() { model_ = subdev_->model(); properties_.set(properties::Model, utils::toAscii(model_)); /* Generate a unique ID for the sensor. */ int ret = generateId(); if (ret) return ret; /* Initialize the static properties from the sensor database. */ initStaticProperties(); /* Retrieve and register properties from the kernel interface. */ const ControlInfoMap &controls = subdev_->controls(); int32_t propertyValue; const auto &orientation = controls.find(V4L2_CID_CAMERA_ORIENTATION); if (orientation != controls.end()) { int32_t v4l2Orientation = orientation->second.def().get<int32_t>(); switch (v4l2Orientation) { default: LOG(CameraSensor, Warning) << "Unsupported camera location " << v4l2Orientation << ", setting to External"; [[fallthrough]]; case V4L2_CAMERA_ORIENTATION_EXTERNAL: propertyValue = properties::CameraLocationExternal; break; case V4L2_CAMERA_ORIENTATION_FRONT: propertyValue = properties::CameraLocationFront; break; case V4L2_CAMERA_ORIENTATION_BACK: propertyValue = properties::CameraLocationBack; break; } properties_.set(properties::Location, propertyValue); } else { LOG(CameraSensor, Warning) << "Failed to retrieve the camera location"; } const auto &rotationControl = controls.find(V4L2_CID_CAMERA_SENSOR_ROTATION); if (rotationControl != controls.end()) { propertyValue = rotationControl->second.def().get<int32_t>(); properties_.set(properties::Rotation, propertyValue); } properties_.set(properties::PixelArraySize, pixelArraySize_); properties_.set(properties::PixelArrayActiveAreas, { activeArea_ }); /* Color filter array pattern, register only for RAW sensors. */ if (bayerFormat_) { int32_t cfa; switch (bayerFormat_->order) { case BayerFormat::BGGR: cfa = properties::draft::BGGR; break; case BayerFormat::GBRG: cfa = properties::draft::GBRG; break; case BayerFormat::GRBG: cfa = properties::draft::GRBG; break; case BayerFormat::RGGB: cfa = properties::draft::RGGB; break; case BayerFormat::MONO: cfa = properties::draft::MONO; break; } properties_.set(properties::draft::ColorFilterArrangement, cfa); } return 0; } /** * \brief Check for and initialise any ancillary devices * * Sensors sometimes have ancillary devices such as a Lens or Flash that could * be linked to their MediaEntity by the kernel. Search for and handle any * such device. * * \todo Handle MEDIA_ENT_F_FLASH too. */ int CameraSensor::discoverAncillaryDevices() { int ret; for (MediaEntity *ancillary : entity_->ancillaryEntities()) { switch (ancillary->function()) { case MEDIA_ENT_F_LENS: focusLens_ = std::make_unique<CameraLens>(ancillary); ret = focusLens_->init(); if (ret) { LOG(CameraSensor, Error) << "Lens initialisation failed, lens disabled"; focusLens_.reset(); } break; default: LOG(CameraSensor, Warning) << "Unsupported ancillary entity function " << ancillary->function(); break; } } return 0; } /** * \fn CameraSensor::model() * \brief Retrieve the sensor model name * * The sensor model name is a free-formed string that uniquely identifies the * sensor model. * * \return The sensor model name */ /** * \fn CameraSensor::id() * \brief Retrieve the sensor ID * * The sensor ID is a free-form string that uniquely identifies the sensor in * the system. The ID satisfies the requirements to be used as a camera ID. * * \return The sensor ID */ /** * \fn CameraSensor::entity() * \brief Retrieve the sensor media entity * \return The sensor media entity */ /** * \fn CameraSensor::mbusCodes() * \brief Retrieve the media bus codes supported by the camera sensor * * Any Bayer formats are listed using the sensor's native Bayer order, * that is, with the effect of V4L2_CID_HFLIP and V4L2_CID_VFLIP undone * (where these controls exist). * * \return The supported media bus codes sorted in increasing order */ /** * \brief Retrieve the supported frame sizes for a media bus code * \param[in] mbusCode The media bus code for which sizes are requested * * \return The supported frame sizes for \a mbusCode sorted in increasing order */ std::vector<Size> CameraSensor::sizes(unsigned int mbusCode) const { std::vector<Size> sizes; const auto &format = formats_.find(mbusCode); if (format == formats_.end()) return sizes; const std::vector<SizeRange> &ranges = format->second; std::transform(ranges.begin(), ranges.end(), std::back_inserter(sizes), [](const SizeRange &range) { return range.max; }); std::sort(sizes.begin(), sizes.end()); return sizes; } /** * \brief Retrieve the camera sensor resolution * * The camera sensor resolution is the active pixel area size, clamped to the * maximum frame size the sensor can produce if it is smaller than the active * pixel area. * * \todo Consider if it desirable to distinguish between the maximum resolution * the sensor can produce (also including upscaled ones) and the actual pixel * array size by splitting this function in two. * * \return The camera sensor resolution in pixels */ Size CameraSensor::resolution() const { return std::min(sizes_.back(), activeArea_.size()); } /** * \fn CameraSensor::testPatternModes() * \brief Retrieve all the supported test pattern modes of the camera sensor * The test pattern mode values correspond to the controls::TestPattern control. * * \return The list of test pattern modes */ /** * \brief Set the test pattern mode for the camera sensor * \param[in] mode The test pattern mode * * The new \a mode is applied to the sensor if it differs from the active test * pattern mode. Otherwise, this function is a no-op. Setting the same test * pattern mode for every frame thus incurs no performance penalty. */ int CameraSensor::setTestPatternMode(controls::draft::TestPatternModeEnum mode) { if (testPatternMode_ == mode) return 0; if (testPatternModes_.empty()) { LOG(CameraSensor, Error) << "Camera sensor does not support test pattern modes."; return -EINVAL; } return applyTestPatternMode(mode); } int CameraSensor::applyTestPatternMode(controls::draft::TestPatternModeEnum mode) { if (testPatternModes_.empty()) return 0; auto it = std::find(testPatternModes_.begin(), testPatternModes_.end(), mode); if (it == testPatternModes_.end()) { LOG(CameraSensor, Error) << "Unsupported test pattern mode " << mode; return -EINVAL; } LOG(CameraSensor, Debug) << "Apply test pattern mode " << mode; int32_t index = staticProps_->testPatternModes.at(mode); ControlList ctrls{ controls() }; ctrls.set(V4L2_CID_TEST_PATTERN, index); int ret = setControls(&ctrls); if (ret) return ret; testPatternMode_ = mode; return 0; } /** * \brief Retrieve the best sensor format for a desired output * \param[in] mbusCodes The list of acceptable media bus codes * \param[in] size The desired size * * Media bus codes are selected from \a mbusCodes, which lists all acceptable * codes in decreasing order of preference. Media bus codes supported by the * sensor but not listed in \a mbusCodes are ignored. If none of the desired * codes is supported, it returns an error. * * \a size indicates the desired size at the output of the sensor. This function * selects the best media bus code and size supported by the sensor according * to the following criteria. * * - The desired \a size shall fit in the sensor output size to avoid the need * to up-scale. * - The sensor output size shall match the desired aspect ratio to avoid the * need to crop the field of view. * - The sensor output size shall be as small as possible to lower the required * bandwidth. * - The desired \a size shall be supported by one of the media bus code listed * in \a mbusCodes. * * When multiple media bus codes can produce the same size, the code at the * lowest position in \a mbusCodes is selected. * * The use of this function is optional, as the above criteria may not match the * needs of all pipeline handlers. Pipeline handlers may implement custom * sensor format selection when needed. * * The returned sensor output format is guaranteed to be acceptable by the * setFormat() function without any modification. * * \return The best sensor output format matching the desired media bus codes * and size on success, or an empty format otherwise. */ V4L2SubdeviceFormat CameraSensor::getFormat(const std::vector<unsigned int> &mbusCodes, const Size &size) const { unsigned int desiredArea = size.width * size.height; unsigned int bestArea = UINT_MAX; float desiredRatio = static_cast<float>(size.width) / size.height; float bestRatio = FLT_MAX; const Size *bestSize = nullptr; uint32_t bestCode = 0; for (unsigned int code : mbusCodes) { const auto formats = formats_.find(code); if (formats == formats_.end()) continue; for (const SizeRange &range : formats->second) { const Size &sz = range.max; if (sz.width < size.width || sz.height < size.height) continue; float ratio = static_cast<float>(sz.width) / sz.height; float ratioDiff = fabsf(ratio - desiredRatio); unsigned int area = sz.width * sz.height; unsigned int areaDiff = area - desiredArea; if (ratioDiff > bestRatio) continue; if (ratioDiff < bestRatio || areaDiff < bestArea) { bestRatio = ratioDiff; bestArea = areaDiff; bestSize = &sz; bestCode = code; } } } if (!bestSize) { LOG(CameraSensor, Debug) << "No supported format or size found"; return {}; } V4L2SubdeviceFormat format{ .mbus_code = bestCode, .size = *bestSize, .colorSpace = ColorSpace::Raw, }; return format; } /** * \brief Set the sensor output format * \param[in] format The desired sensor output format * \param[in] transform The transform to be applied on the sensor. * Defaults to Identity. * * If flips are writable they are configured according to the desired Transform. * Transform::Identity always corresponds to H/V flip being disabled if the * controls are writable. Flips are set before the new format is applied as * they can effectively change the Bayer pattern ordering. * * The ranges of any controls associated with the sensor are also updated. * * \return 0 on success or a negative error code otherwise */ int CameraSensor::setFormat(V4L2SubdeviceFormat *format, Transform transform) { /* Configure flips if the sensor supports that. */ if (supportFlips_) { ControlList flipCtrls(subdev_->controls()); flipCtrls.set(V4L2_CID_HFLIP, static_cast<int32_t>(!!(transform & Transform::HFlip))); flipCtrls.set(V4L2_CID_VFLIP, static_cast<int32_t>(!!(transform & Transform::VFlip))); int ret = subdev_->setControls(&flipCtrls); if (ret) return ret; } /* Apply format on the subdev. */ int ret = subdev_->setFormat(pad_, format); if (ret) return ret; updateControlInfo(); return 0; } /** * \brief Retrieve the supported V4L2 controls and their information * * Control information is updated automatically to reflect the current sensor * configuration when the setFormat() function is called, without invalidating * any iterator on the ControlInfoMap. A manual update can also be forced by * calling the updateControlInfo() function for pipeline handlers that change * the sensor configuration wihtout using setFormat(). * * \return A map of the V4L2 controls supported by the sensor */ const ControlInfoMap &CameraSensor::controls() const { return subdev_->controls(); } /** * \brief Read V4L2 controls from the sensor * \param[in] ids The list of controls to read, specified by their ID * * This function reads the value of all controls contained in \a ids, and * returns their values as a ControlList. The control identifiers are defined by * the V4L2 specification (V4L2_CID_*). * * If any control in \a ids is not supported by the device, is disabled (i.e. * has the V4L2_CTRL_FLAG_DISABLED flag set), or if any other error occurs * during validation of the requested controls, no control is read and this * function returns an empty control list. * * \sa V4L2Device::getControls() * * \return The control values in a ControlList on success, or an empty list on * error */ ControlList CameraSensor::getControls(const std::vector<uint32_t> &ids) { return subdev_->getControls(ids); } /** * \brief Write V4L2 controls to the sensor * \param[in] ctrls The list of controls to write * * This function writes the value of all controls contained in \a ctrls, and * stores the values actually applied to the device in the corresponding \a * ctrls entry. The control identifiers are defined by the V4L2 specification * (V4L2_CID_*). * * If any control in \a ctrls is not supported by the device, is disabled (i.e. * has the V4L2_CTRL_FLAG_DISABLED flag set), is read-only, or if any other * error occurs during validation of the requested controls, no control is * written and this function returns -EINVAL. * * If an error occurs while writing the controls, the index of the first * control that couldn't be written is returned. All controls below that index * are written and their values are updated in \a ctrls, while all other * controls are not written and their values are not changed. * * \sa V4L2Device::setControls() * * \return 0 on success or an error code otherwise * \retval -EINVAL One of the control is not supported or not accessible * \retval i The index of the control that failed */ int CameraSensor::setControls(ControlList *ctrls) { return subdev_->setControls(ctrls); } /** * \fn CameraSensor::device() * \brief Retrieve the camera sensor device * \todo Remove this function by integrating DelayedControl with CameraSensor * \return The camera sensor device */ /** * \fn CameraSensor::properties() * \brief Retrieve the camera sensor properties * \return The list of camera sensor properties */ /** * \brief Assemble and return the camera sensor info * \param[out] info The camera sensor info * * This function fills \a info with information that describes the camera sensor * and its current configuration. The information combines static data (such as * the the sensor model or active pixel array size) and data specific to the * current sensor configuration (such as the line length and pixel rate). * * Sensor information is only available for raw sensors. When called for a YUV * sensor, this function returns -EINVAL. * * Pipeline handlers that do not change the sensor format using the setFormat() * function may need to call updateControlInfo() beforehand, to ensure all the * control ranges are up to date. * * \return 0 on success, a negative error code otherwise */ int CameraSensor::sensorInfo(IPACameraSensorInfo *info) const { if (!bayerFormat_) return -EINVAL; info->model = model(); /* * The active area size is a static property, while the crop * rectangle needs to be re-read as it depends on the sensor * configuration. */ info->activeAreaSize = { activeArea_.width, activeArea_.height }; /* * \todo Support for retreiving the crop rectangle is scheduled to * become mandatory. For the time being use the default value if it has * been initialized at sensor driver validation time. */ int ret = subdev_->getSelection(pad_, V4L2_SEL_TGT_CROP, &info->analogCrop); if (ret) { info->analogCrop = activeArea_; LOG(CameraSensor, Warning) << "The analogue crop rectangle has been defaulted to the active area size"; } /* * IPACameraSensorInfo::analogCrop::x and IPACameraSensorInfo::analogCrop::y * are defined relatively to the active pixel area, while V4L2's * TGT_CROP target is defined in respect to the full pixel array. * * Compensate it by subtracting the active area offset. */ info->analogCrop.x -= activeArea_.x; info->analogCrop.y -= activeArea_.y; /* The bit depth and image size depend on the currently applied format. */ V4L2SubdeviceFormat format{}; ret = subdev_->getFormat(pad_, &format); if (ret) return ret; info->bitsPerPixel = format.bitsPerPixel(); info->outputSize = format.size; /* * Retrieve the pixel rate, line length and minimum/maximum frame * duration through V4L2 controls. Support for the V4L2_CID_PIXEL_RATE, * V4L2_CID_HBLANK and V4L2_CID_VBLANK controls is mandatory. */ ControlList ctrls = subdev_->getControls({ V4L2_CID_PIXEL_RATE, V4L2_CID_HBLANK, V4L2_CID_VBLANK }); if (ctrls.empty()) { LOG(CameraSensor, Error) << "Failed to retrieve camera info controls"; return -EINVAL; } info->pixelRate = ctrls.get(V4L2_CID_PIXEL_RATE).get<int64_t>(); const ControlInfo hblank = ctrls.infoMap()->at(V4L2_CID_HBLANK); info->minLineLength = info->outputSize.width + hblank.min().get<int32_t>(); info->maxLineLength = info->outputSize.width + hblank.max().get<int32_t>(); const ControlInfo vblank = ctrls.infoMap()->at(V4L2_CID_VBLANK); info->minFrameLength = info->outputSize.height + vblank.min().get<int32_t>(); info->maxFrameLength = info->outputSize.height + vblank.max().get<int32_t>(); return 0; } /** * \fn void CameraSensor::updateControlInfo() * \brief Update the sensor's ControlInfoMap in case they have changed * \sa V4L2Device::updateControlInfo() */ void CameraSensor::updateControlInfo() { subdev_->updateControlInfo(); } /** * \fn CameraSensor::focusLens() * \brief Retrieve the focus lens controller * * \return The focus lens controller. nullptr if no focus lens controller is * connected to the sensor */ /** * \brief Validate a transform request against the sensor capabilities * \param[inout] transform The requested transformation, updated to match * the sensor capabilities * * The input \a transform is the transform that the caller wants, and it is * adjusted according to the capabilities of the sensor to represent the * "nearest" transform that can actually be delivered. * * The returned Transform is the transform applied to the sensor in order to * produce the input \a transform, It is also validated against the sensor's * ability to perform horizontal and vertical flips. * * For example, if the requested \a transform is Transform::Identity and the * sensor rotation is 180 degrees, the output transform will be * Transform::Rot180 to correct the images so that they appear to have * Transform::Identity, but only if the sensor can apply horizontal and vertical * flips. * * \return A Transform instance that represents which transformation has been * applied to the camera sensor */ Transform CameraSensor::validateTransform(Transform *transform) const { /* Adjust the requested transform to compensate the sensor rotation. */ int32_t rotation = properties().get(properties::Rotation).value_or(0); bool success; Transform rotationTransform = transformFromRotation(rotation, &success); if (!success) LOG(CameraSensor, Warning) << "Invalid rotation of " << rotation << " degrees - ignoring"; Transform combined = *transform * rotationTransform; /* * We combine the platform and user transform, but must "adjust away" * any combined result that includes a transposition, as we can't do * those. In this case, flipping only the transpose bit is helpful to * applications - they either get the transform they requested, or have * to do a simple transpose themselves (they don't have to worry about * the other possible cases). */ if (!!(combined & Transform::Transpose)) { /* * Flipping the transpose bit in "transform" flips it in the * combined result too (as it's the last thing that happens), * which is of course clearing it. */ *transform ^= Transform::Transpose; combined &= ~Transform::Transpose; } /* * We also check if the sensor doesn't do h/vflips at all, in which * case we clear them, and the application will have to do everything. */ if (!supportFlips_ && !!combined) { /* * If the sensor can do no transforms, then combined must be * changed to the identity. The only user transform that gives * rise to this is the inverse of the rotation. (Recall that * combined = transform * rotationTransform.) */ *transform = -rotationTransform; combined = Transform::Identity; } return combined; } std::string CameraSensor::logPrefix() const { return "'" + entity_->name() + "'"; } int CameraSensor::generateId() { const std::string devPath = subdev_->devicePath(); /* Try to get ID from firmware description. */ id_ = sysfs::firmwareNodePath(devPath); if (!id_.empty()) return 0; /* * Virtual sensors not described in firmware * * Verify it's a platform device and construct ID from the device path * and model of sensor. */ if (devPath.find("/sys/devices/platform/", 0) == 0) { id_ = devPath.substr(strlen("/sys/devices/")) + " " + model(); return 0; } LOG(CameraSensor, Error) << "Can't generate sensor ID"; return -EINVAL; } } /* namespace libcamera */