From patchwork Thu Mar 26 14:59:22 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 3329 Return-Path: Received: from relay7-d.mail.gandi.net (relay7-d.mail.gandi.net [217.70.183.200]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 704E360410 for ; Thu, 26 Mar 2020 15:56:33 +0100 (CET) X-Originating-IP: 2.224.242.101 Received: from localhost.localdomain (2-224-242-101.ip172.fastwebnet.it [2.224.242.101]) (Authenticated sender: jacopo@jmondi.org) by relay7-d.mail.gandi.net (Postfix) with ESMTPSA id EFE7B20008 for ; Thu, 26 Mar 2020 14:56:32 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Thu, 26 Mar 2020 15:59:22 +0100 Message-Id: <20200326145927.324919-2-jacopo@jmondi.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200326145927.324919-1-jacopo@jmondi.org> References: <20200326145927.324919-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v4 1/6] libcamera: properties: Define pixel array properties X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 26 Mar 2020 14:56:33 -0000 Add definition of pixel array related properties. Signed-off-by: Jacopo Mondi Reviewed-by: Niklas Söderlund --- src/libcamera/property_ids.yaml | 155 ++++++++++++++++++++++++++++++++ 1 file changed, 155 insertions(+) diff --git a/src/libcamera/property_ids.yaml b/src/libcamera/property_ids.yaml index ce627fa042ba..ea9d363fdef8 100644 --- a/src/libcamera/property_ids.yaml +++ b/src/libcamera/property_ids.yaml @@ -386,4 +386,159 @@ controls: | | | | +--------------------+ + + - PixelArraySize: + type: float + size: [2] + description: | + The physical sizes of the pixel array (width and height), in + millimeters. + + - PixelArray: + type: int32_t + size: [2] + description: | + The camera sensor pixel array vertical and horizontal sizes, in pixels. + + The property describes a rectangle with its top-left corner in position + (0, 0) and width and height described by the first and second values + of this property. + + The PixelArray property defines the rectangle that includes all possible + rectangles defined by the ActiveAreas property, and describes the full + pixel array, including non-active pixels, black level calibration + pixels etc. + + - ActiveAreas: + type: int32_t + size: [4 x n] + description: | + The camera sensor active pixel area rectangles, represented as + rectangles contained in the one described by the PixelArrays property. + + This property describes an arbitrary number of overlapping rectangles, + representing the active pixel portions of the camera sensor pixel array. + + Each rectangle is defined by its displacement from pixel (0, 0) of + the rectangle described by the PixelArray property, a width and an + height. + + Each rectangle described by this property represents the maximum image + size that the camera module can produce for a given image resolution. + + Example 1. + A sensor which only produces images in the 4:3 image resolution will + report a single ActiveArea rectangle, from which all other image formats + are obtained by either cropping the field-of-view and/or applying pixel + sub-sampling techniques such as pixel skipping or binning. + + PixelArray(0) + /-----------------/ + x1 x2 + (0,0)-> +-o------------o-+ / + y1 o +------------+ | | + | |////////////| | | + | |////////////| | | PixelArray(1) + | |////////////| | | + y2 o +------------+ | | + +----------------+ / + + The property reports a single rectangle + + ActiveArea = (x1, y1, (x2 - x1), (y2 - y1)) + + Example 2 + A camera sensor which can produce images in different native + resolutions, will report several overlapping rectangle, one for each + natively supported resolution, ordered from the tallest to the shortest + one. + + PixelArray(0) + /-----------------/ + x1 x2 x3 x4 + (0,0)-> +o---o------o---o+ / + y1 | +------+ | | + | |//////| | | + y2 o+---+------+---+| | + ||///|//////|///|| | PixelArray(1) + y3 o+---+------+---+| | + | |//////| | | + y4 | +------+ | | + +----+------+----+ / + + The property reports two rectangles + + PixelArray = ( (x2, y1, (x3 - x2), (y4 - 1), + (x1, y2, (x4 - x1), (y3 - y2)) + + The first rectangle describes the maximum field-of-view of all image + formats in the 4:3 resolutions, while the second one describes the + maximum field of view for all image formats in the 16:9 resolutions. + + - BayerFilterArrangement: + type: int32_t + description: | + The pixel array color filter displacement. + + This property describes the arrangement and readout sequence of the + three RGB color components of the sensor's Bayer Color Filter Array + (CFA). + + Color filters are usually displaced in line-alternating fashion on the + sensor pixel array. In example, one line might be composed of Red-Green + while the successive is composed of Blue-Green color information. + + The value of this property represents the arrangement of color filters + in the top-left 2x2 pixel square. + + For example, for a sensor with the following color filter displacement + + (0, 0) (max-col) + +---+ +--------------...---+ + |B|G|<---|B|G|B|G|B|G|B|...B|G| + |G|R|<---|G|R|G|R|G|R|G|...G|R| + +---+ |B|G|B|G|B|G|B|...B|G| + ... .. + ... .. + |G|R|G|R|G|R|G|...G|R| + |B|G|B|G|B|G|B|...B|G| (max-lines) + +--------------...---+ + + The filter arrangement is represented by the BGGR value, which + correspond to the pixel readout sequence in line interleaved mode. + + enum: + - name: BayerFilterRGGB + value: 0 + description: | + Color filter array displacement is Red-Green/Green-Blue + + - name: BayerFilterGRBG + value: 1 + description: | + Color filter array displacement is Green-Red/Blue-Green + + - name: BayerFilterGBRG + value: 2 + description: | + Color filter array displacement is Green-Blue/Red-Green + + - name: BayerFilterBGGR + value: 3 + description: | + Color filter array displacement is Blue-Green/Green-Red + + - name: BayerFilterNonStandard + value: 4 + description: | + The pixel array color filter does not use the standard Bayer RGB + color model + + - ISOSensitivityRange: + type: int32_t + size: [2] + description: | + The range of supported ISO sensitivities, as documented by the + ISO 12232:2006 (or later) standard. + ... From patchwork Thu Mar 26 14:59:23 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 3330 X-Patchwork-Delegate: jacopo@jmondi.org Return-Path: Received: from relay7-d.mail.gandi.net (relay7-d.mail.gandi.net [217.70.183.200]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id E426060410 for ; Thu, 26 Mar 2020 15:56:33 +0100 (CET) X-Originating-IP: 2.224.242.101 Received: from localhost.localdomain (2-224-242-101.ip172.fastwebnet.it [2.224.242.101]) (Authenticated sender: jacopo@jmondi.org) by relay7-d.mail.gandi.net (Postfix) with ESMTPSA id A6D8F20008 for ; Thu, 26 Mar 2020 14:56:33 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Thu, 26 Mar 2020 15:59:23 +0100 Message-Id: <20200326145927.324919-3-jacopo@jmondi.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200326145927.324919-1-jacopo@jmondi.org> References: <20200326145927.324919-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v4 2/6] libcamera: properties: Define 'lens' properties X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 26 Mar 2020 14:56:34 -0000 Define properties that describe the optical characteristics of the image sensor. Signed-off-by: Jacopo Mondi Reviewed-by: Niklas Söderlund --- src/libcamera/property_ids.yaml | 34 +++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/libcamera/property_ids.yaml b/src/libcamera/property_ids.yaml index ea9d363fdef8..a7897bc8e5dc 100644 --- a/src/libcamera/property_ids.yaml +++ b/src/libcamera/property_ids.yaml @@ -541,4 +541,38 @@ controls: The range of supported ISO sensitivities, as documented by the ISO 12232:2006 (or later) standard. + - LensApertures: + type: float + size: [n] + description: | + The available lens apertures, expressed as f numbers (the ratio between + the lens focal distance and the diameter of the pupil aperture). + + If the camera module has a fixed aperture, the property transports a + single value. + + - LensFocalLengths: + type: float + size: [n] + description: | + The available lens focal lengths, expressed in millimeters. + + If the camera module supports multiple focal lengths this property + reports the focal lengths associated with each discrete step. For + camera modules with a single focal length, a single value should be + instead reported. + + - LensHyperfocalDistances: + type: float + size: [n] + description: | + The hyperfocal distance of the camera module. The property is + particularly meaningful for modules with a single focal length. + + - LensMinimumFocusDistance: + type: float + description: | + The shortest distance in millimeters at which an object could be brought + into sharp focus. + ... From patchwork Thu Mar 26 14:59:24 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 3331 X-Patchwork-Delegate: jacopo@jmondi.org Return-Path: Received: from relay7-d.mail.gandi.net (relay7-d.mail.gandi.net [217.70.183.200]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id AA3F762B90 for ; Thu, 26 Mar 2020 15:56:34 +0100 (CET) X-Originating-IP: 2.224.242.101 Received: from localhost.localdomain (2-224-242-101.ip172.fastwebnet.it [2.224.242.101]) (Authenticated sender: jacopo@jmondi.org) by relay7-d.mail.gandi.net (Postfix) with ESMTPSA id 615F020009 for ; Thu, 26 Mar 2020 14:56:33 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Thu, 26 Mar 2020 15:59:24 +0100 Message-Id: <20200326145927.324919-4-jacopo@jmondi.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200326145927.324919-1-jacopo@jmondi.org> References: <20200326145927.324919-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v4 3/6] libcamera: camera_sensor: Introduce CameraSensorFactory X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 26 Mar 2020 14:56:36 -0000 Introduce a factory to create CameraSensor derived classes instances by inspecting the sensor media entity name and provide a convenience macro to register specialized camera sensor sub-classes. Reviewed-by: Kieran Bingham Reviewed-by: Laurent Pinchart Signed-off-by: Jacopo Mondi --- src/libcamera/camera_sensor.cpp | 132 ++++++++++++++++++ src/libcamera/include/camera_sensor.h | 32 +++++ src/libcamera/pipeline/ipu3/ipu3.cpp | 9 +- src/libcamera/pipeline/rkisp1/rkisp1.cpp | 18 +-- src/libcamera/pipeline/vimc/vimc.cpp | 6 +- test/camera-sensor.cpp | 9 +- .../v4l2_videodevice_test.cpp | 3 +- test/v4l2_videodevice/v4l2_videodevice_test.h | 6 +- 8 files changed, 183 insertions(+), 32 deletions(-) diff --git a/src/libcamera/camera_sensor.cpp b/src/libcamera/camera_sensor.cpp index fc24b3bd547d..c1a29e0b3cfc 100644 --- a/src/libcamera/camera_sensor.cpp +++ b/src/libcamera/camera_sensor.cpp @@ -12,6 +12,8 @@ #include #include #include +#include +#include #include @@ -366,4 +368,134 @@ std::string CameraSensor::logPrefix() const return "'" + subdev_->entity()->name() + "'"; } +/** + * \class CameraSensorFactory + * \brief Factory of camera sensors + * + * The class provides camera sensor with the ability to register themselves to + * the factory to allow the creation of their instances by matching the name of + * the media entity which represents the sensor. + * + * Camera sensor subclasses use the REGISTER_CAMERA_SENSOR() macro to register + * themselves to the camera sensor factory. Users of the factory create camera + * sensor instances for a media entity by using the static createInstance() + * method, which returns an instance of the CameraSensor sub-class matching the + * entity, or a newly created instance of the generic CameraSensor class. + */ + +/** + * \brief Construct a camera sensor factory + * \param[in] name The name of the media entity representing the sensor + * + * Register a new camera sensor factory which creates CameraSensor instances + * to support camera sensors represented by the media entity with \a name. + * + * Creating an instance of the factory registers it with the global list of + * factories, accessible through the factories() function. + */ +CameraSensorFactory::CameraSensorFactory(const char *name) +{ + registerFactory(name, this); +} + +/** + * \brief Retrieve the list of registered camera sensor factories + * + * The static factories map is defined inside the function to ensure it gets + * initialized on first use, without any dependency on link order. + * + * \return The static list of registered camera sensor factories + */ +CameraSensorFactory::FactoriesMap &CameraSensorFactory::factories() +{ + static FactoriesMap factories; + return factories; +} + +/** + * \brief Register a camera sensor factory + * \param[in] name The name of the media entity that represents the sensor + * \param[in] factory The factory instance to register + * + * The camera sensor \a factory is registered associated with an entity \a name. + * When a camera sensor is created for a media entity with createSensor(), the + * name of the media entity is used to select the corresponding factory. + * + * The caller is responsible for guaranteeing the uniqueness of the + * camera sensor entity name. + */ +void CameraSensorFactory::registerFactory(const char *name, + CameraSensorFactory *factory) +{ + FactoriesMap &map = factories(); + + if (map.find(name) != map.end()) { + LOG(CameraSensor, Error) + << "Unable to register camera sensor factory '" + << name << "': already registered"; + return; + } + + map[name] = factory; +} + +/** + * \brief Create a camera sensor corresponding to \a entity + * \param[in] entity The media entity that represents the camera sensor + * + * Create a new instance of a CameraSensor subclass for the sensor represented + * by \a entity using one of the registered factories. If no specific class is + * available for the sensor, an instance of the generic CameraSensor class is + * created and returned. + * + * Ownership of the created camera sensor instance is passed to the caller + * which is responsible for deleting the instance. + * + * Ownership of the created camera sensor instance is passed to the caller as + * an unique pointer. + * + * \return A unique pointer to the newly created camera sensor instance + */ +std::unique_ptr CameraSensorFactory::createSensor(const MediaEntity *entity) +{ + const std::string &name = entity->name(); + for (const auto &it : factories()) { + const std::string &key = it.first; + + /* + * Search for the key, provided by the CameraSensor sub-class at + * factory registration time, with the sensor entity name, to + * support both canonical sensor entity names (in the "devname + * i2c-adapt:i2c-addr" format) and non-canonical sensor names. + * + * \todo Delegate matching to the CameraSensor sub-class + * to support more complex matching criteria. + */ + if (name.find(key) == std::string::npos) + continue; + + LOG(CameraSensor, Debug) << "Create camera sensor for '" + << name << "'"; + + CameraSensorFactory *factory = it.second; + return std::unique_ptr(factory->create(entity)); + } + + LOG(CameraSensor, Debug) << "No specific support for sensor '" + << entity->name() + << "': using generic implementation"; + return std::make_unique(entity); +} + +/** + * \def REGISTER_CAMERA_SENSOR(sensor, sensorName) + * \brief Register camera sensor \a name with the sensor factory + * \param[in] sensor The name of the camera sensor class to register + * \param[in] sensorName The name of the image sensor supported by the factory + * + * Register camera sensor subclass \a sensor in the global list of factories. + * \a sensorName corresponds to the sensor entity name without the bus + * information, for instance "ov5670" for a sensor entity named "ov5645 4-003c". + */ + } /* namespace libcamera */ diff --git a/src/libcamera/include/camera_sensor.h b/src/libcamera/include/camera_sensor.h index 99cff98128dc..8ffc787e740f 100644 --- a/src/libcamera/include/camera_sensor.h +++ b/src/libcamera/include/camera_sensor.h @@ -7,6 +7,8 @@ #ifndef __LIBCAMERA_CAMERA_SENSOR_H__ #define __LIBCAMERA_CAMERA_SENSOR_H__ +#include +#include #include #include @@ -61,6 +63,36 @@ private: ControlList properties_; }; +class CameraSensorFactory +{ +public: + CameraSensorFactory(const char *name); + virtual ~CameraSensorFactory() {} + + static std::unique_ptr createSensor(const MediaEntity *entity); + +private: + using FactoriesMap = std::map; + static FactoriesMap &factories(); + static void registerFactory(const char *name, + CameraSensorFactory *factory); + virtual CameraSensor *create(const MediaEntity *entity) = 0; +}; + +#define REGISTER_CAMERA_SENSOR(sensor, sensorName) \ +class sensor##Factory final : public CameraSensorFactory \ +{ \ +public: \ + sensor##Factory() : CameraSensorFactory(sensorName) {} \ + \ +private: \ + CameraSensor *create(const MediaEntity *entity) \ + { \ + return new sensor(entity); \ + } \ +}; \ +static sensor##Factory global_##sensor##Factory + } /* namespace libcamera */ #endif /* __LIBCAMERA_CAMERA_SENSOR_H__ */ diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp index 1b44460e4d88..df2ab17cd5d6 100644 --- a/src/libcamera/pipeline/ipu3/ipu3.cpp +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp @@ -100,7 +100,7 @@ public: static constexpr unsigned int CIO2_BUFFER_COUNT = 4; CIO2Device() - : output_(nullptr), csi2_(nullptr), sensor_(nullptr) + : output_(nullptr), csi2_(nullptr) { } @@ -108,7 +108,6 @@ public: { delete output_; delete csi2_; - delete sensor_; } int init(const MediaDevice *media, unsigned int index); @@ -125,7 +124,7 @@ public: V4L2VideoDevice *output_; V4L2Subdevice *csi2_; - CameraSensor *sensor_; + std::unique_ptr sensor_; private: std::vector> buffers_; @@ -292,7 +291,7 @@ void IPU3CameraConfiguration::adjustStream(StreamConfiguration &cfg, bool scale) CameraConfiguration::Status IPU3CameraConfiguration::validate() { - const CameraSensor *sensor = data_->cio2_.sensor_; + const CameraSensor *sensor = data_->cio2_.sensor_.get(); Status status = Valid; if (config_.empty()) @@ -1313,7 +1312,7 @@ int CIO2Device::init(const MediaDevice *media, unsigned int index) MediaLink *link = links[0]; MediaEntity *sensorEntity = link->source()->entity(); - sensor_ = new CameraSensor(sensorEntity); + sensor_ = CameraSensorFactory::createSensor(sensorEntity); ret = sensor_->init(); if (ret) return ret; diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp index 2f909cef7c75..a0e6490909ed 100644 --- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp +++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp @@ -113,20 +113,14 @@ class RkISP1CameraData : public CameraData { public: RkISP1CameraData(PipelineHandler *pipe) - : CameraData(pipe), sensor_(nullptr), frame_(0), - frameInfo_(pipe) + : CameraData(pipe), frame_(0), frameInfo_(pipe) { } - ~RkISP1CameraData() - { - delete sensor_; - } - int loadIPA(); Stream stream_; - CameraSensor *sensor_; + std::unique_ptr sensor_; unsigned int frame_; std::vector ipaBuffers_; RkISP1Frames frameInfo_; @@ -386,7 +380,7 @@ void RkISP1CameraData::queueFrameAction(unsigned int frame, case RKISP1_IPA_ACTION_V4L2_SET: { const ControlList &controls = action.controls[0]; timeline_.scheduleAction(std::make_unique(frame, - sensor_, + sensor_.get(), controls)); break; } @@ -441,7 +435,7 @@ CameraConfiguration::Status RkISP1CameraConfiguration::validate() /* \todo Add support for 8-bit greyscale to DRM formats */ }; - const CameraSensor *sensor = data_->sensor_; + const CameraSensor *sensor = data_->sensor_.get(); Status status = Valid; if (config_.empty()) @@ -554,7 +548,7 @@ int PipelineHandlerRkISP1::configure(Camera *camera, CameraConfiguration *c) static_cast(c); RkISP1CameraData *data = cameraData(camera); StreamConfiguration &cfg = config->at(0); - CameraSensor *sensor = data->sensor_; + CameraSensor *sensor = data->sensor_.get(); int ret; /* @@ -889,7 +883,7 @@ int PipelineHandlerRkISP1::createCamera(MediaEntity *sensor) data->controlInfo_ = std::move(ctrls); - data->sensor_ = new CameraSensor(sensor); + data->sensor_ = CameraSensorFactory::createSensor(sensor); ret = data->sensor_->init(); if (ret) return ret; diff --git a/src/libcamera/pipeline/vimc/vimc.cpp b/src/libcamera/pipeline/vimc/vimc.cpp index b04a9726efa5..805bac0a7377 100644 --- a/src/libcamera/pipeline/vimc/vimc.cpp +++ b/src/libcamera/pipeline/vimc/vimc.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -46,7 +47,6 @@ public: ~VimcCameraData() { - delete sensor_; delete debayer_; delete scaler_; delete video_; @@ -56,7 +56,7 @@ public: int init(MediaDevice *media); void bufferReady(FrameBuffer *buffer); - CameraSensor *sensor_; + std::unique_ptr sensor_; V4L2Subdevice *debayer_; V4L2Subdevice *scaler_; V4L2VideoDevice *video_; @@ -398,7 +398,7 @@ int VimcCameraData::init(MediaDevice *media) return ret; /* Create and open the camera sensor, debayer, scaler and video device. */ - sensor_ = new CameraSensor(media->getEntityByName("Sensor B")); + sensor_ = CameraSensorFactory::createSensor(media->getEntityByName("Sensor B")); ret = sensor_->init(); if (ret) return ret; diff --git a/test/camera-sensor.cpp b/test/camera-sensor.cpp index 27c190fe7ace..8709e481dc7b 100644 --- a/test/camera-sensor.cpp +++ b/test/camera-sensor.cpp @@ -50,7 +50,7 @@ protected: return TestFail; } - sensor_ = new CameraSensor(entity); + sensor_ = CameraSensorFactory::createSensor(entity); if (sensor_->init() < 0) { cerr << "Unable to initialise camera sensor" << endl; return TestFail; @@ -100,15 +100,10 @@ protected: return TestPass; } - void cleanup() - { - delete sensor_; - } - private: std::unique_ptr enumerator_; std::shared_ptr media_; - CameraSensor *sensor_; + std::unique_ptr sensor_; }; TEST_REGISTER(CameraSensorTest) diff --git a/test/v4l2_videodevice/v4l2_videodevice_test.cpp b/test/v4l2_videodevice/v4l2_videodevice_test.cpp index 93b9e72da5b4..e1c8a886f2db 100644 --- a/test/v4l2_videodevice/v4l2_videodevice_test.cpp +++ b/test/v4l2_videodevice/v4l2_videodevice_test.cpp @@ -61,7 +61,7 @@ int V4L2VideoDeviceTest::init() return TestFail; if (driver_ == "vimc") { - sensor_ = new CameraSensor(media_->getEntityByName("Sensor A")); + sensor_ = CameraSensorFactory::createSensor(media_->getEntityByName("Sensor A")); if (sensor_->init()) return TestFail; @@ -97,6 +97,5 @@ void V4L2VideoDeviceTest::cleanup() capture_->close(); delete debayer_; - delete sensor_; delete capture_; } diff --git a/test/v4l2_videodevice/v4l2_videodevice_test.h b/test/v4l2_videodevice/v4l2_videodevice_test.h index 9acaceb84fe0..f635e0929efe 100644 --- a/test/v4l2_videodevice/v4l2_videodevice_test.h +++ b/test/v4l2_videodevice/v4l2_videodevice_test.h @@ -25,8 +25,8 @@ class V4L2VideoDeviceTest : public Test { public: V4L2VideoDeviceTest(const char *driver, const char *entity) - : driver_(driver), entity_(entity), sensor_(nullptr), - debayer_(nullptr), capture_(nullptr) + : driver_(driver), entity_(entity), debayer_(nullptr), + capture_(nullptr) { } @@ -38,7 +38,7 @@ protected: std::string entity_; std::unique_ptr enumerator_; std::shared_ptr media_; - CameraSensor *sensor_; + std::unique_ptr sensor_; V4L2Subdevice *debayer_; V4L2VideoDevice *capture_; std::vector> buffers_; From patchwork Thu Mar 26 14:59:25 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 3332 X-Patchwork-Delegate: jacopo@jmondi.org Return-Path: Received: from relay7-d.mail.gandi.net (relay7-d.mail.gandi.net [217.70.183.200]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 30EF1605D2 for ; Thu, 26 Mar 2020 15:56:35 +0100 (CET) X-Originating-IP: 2.224.242.101 Received: from localhost.localdomain (2-224-242-101.ip172.fastwebnet.it [2.224.242.101]) (Authenticated sender: jacopo@jmondi.org) by relay7-d.mail.gandi.net (Postfix) with ESMTPSA id E005A20009 for ; Thu, 26 Mar 2020 14:56:34 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Thu, 26 Mar 2020 15:59:25 +0100 Message-Id: <20200326145927.324919-5-jacopo@jmondi.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200326145927.324919-1-jacopo@jmondi.org> References: <20200326145927.324919-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v4 4/6] libcamera: camera_sensor: Break out properties initialization X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 26 Mar 2020 14:56:36 -0000 Refactor the CameraSensor properties initialization to a dedicated virtual function that derived classes could override to register sensor-specific property values. While at it, move documentation of the properties() method to match the declaration order in the class definition and make the properties_ and subdev_ fields protected to allow subclasses access. Reviewed-by: Kieran Bingham Signed-off-by: Jacopo Mondi Reviewed-by: Niklas Söderlund --- src/libcamera/camera_sensor.cpp | 115 +++++++++++++++----------- src/libcamera/include/camera_sensor.h | 7 +- 2 files changed, 73 insertions(+), 49 deletions(-) diff --git a/src/libcamera/camera_sensor.cpp b/src/libcamera/camera_sensor.cpp index c1a29e0b3cfc..09771fc40bbb 100644 --- a/src/libcamera/camera_sensor.cpp +++ b/src/libcamera/camera_sensor.cpp @@ -51,7 +51,7 @@ LOG_DEFINE_CATEGORY(CameraSensor); * Once constructed the instance must be initialized with init(). */ CameraSensor::CameraSensor(const MediaEntity *entity) - : entity_(entity), properties_(properties::properties) + : properties_(properties::properties), entity_(entity) { subdev_ = new V4L2Subdevice(entity); } @@ -93,45 +93,6 @@ int CameraSensor::init() if (ret < 0) return ret; - /* Retrieve and store the camera sensor properties. */ - const ControlInfoMap &controls = subdev_->controls(); - int32_t propertyValue; - - /* Camera Location: default is front location. */ - const auto &locationControl = controls.find(V4L2_CID_CAMERA_SENSOR_LOCATION); - if (locationControl != controls.end()) { - int32_t v4l2Location = - locationControl->second.def().get(); - - switch (v4l2Location) { - default: - LOG(CameraSensor, Warning) - << "Unsupported camera location " - << v4l2Location << ", setting to Front"; - /* Fall-through */ - case V4L2_LOCATION_FRONT: - propertyValue = properties::CameraLocationFront; - break; - case V4L2_LOCATION_BACK: - propertyValue = properties::CameraLocationBack; - break; - case V4L2_LOCATION_EXTERNAL: - propertyValue = properties::CameraLocationExternal; - break; - } - } else { - propertyValue = properties::CameraLocationFront; - } - properties_.set(properties::Location, propertyValue); - - /* Camera Rotation: default is 0 degrees. */ - const auto &rotationControl = controls.find(V4L2_CID_CAMERA_SENSOR_ROTATION); - if (rotationControl != controls.end()) - propertyValue = rotationControl->second.def().get(); - else - propertyValue = 0; - properties_.set(properties::Rotation, propertyValue); - /* Enumerate and cache media bus codes and sizes. */ const ImageFormats formats = subdev_->formats(0); if (formats.isEmpty()) { @@ -162,6 +123,58 @@ int CameraSensor::init() std::sort(mbusCodes_.begin(), mbusCodes_.end()); std::sort(sizes_.begin(), sizes_.end()); + return initProperties(); +} + +/** + * \brief Initialize the camera sensor standard properties + * + * This method initializes the camera sensor standard properties, by inspecting + * the control information reported by the sensor subdevice. + * + * Derived classes may override this method to register sensor-specific + * properties if needed. If they do so, they shall call the base + * initProperties() method to register standard properties. + * + * \return 0 on success, a negative error code otherwise + */ +int CameraSensor::initProperties() +{ + const ControlInfoMap &controlMap = subdev_->controls(); + int32_t propertyValue; + + /* Camera Location: default is front location. */ + const auto &locationControl = controlMap.find(V4L2_CID_CAMERA_SENSOR_LOCATION); + if (locationControl != controlMap.end()) { + int32_t v4l2Location = + locationControl->second.def().get(); + switch (v4l2Location) { + case V4L2_LOCATION_EXTERNAL: + propertyValue = properties::CameraLocationExternal; + break; + case V4L2_LOCATION_FRONT: + propertyValue = properties::CameraLocationFront; + break; + case V4L2_LOCATION_BACK: + propertyValue = properties::CameraLocationBack; + break; + default: + LOG(CameraSensor, Error) + << "Unsupported camera location: " << v4l2Location; + return -EINVAL; + } + } else { + propertyValue = properties::CameraLocationFront; + } + properties_.set(properties::Location, propertyValue); + + /* Camera Rotation: default is 0 degrees. */ + propertyValue = 0; + const auto &rotationControl = controlMap.find(V4L2_CID_CAMERA_SENSOR_ROTATION); + if (rotationControl != controlMap.end()) + propertyValue = rotationControl->second.def().get(); + properties_.set(properties::Rotation, propertyValue); + return 0; } @@ -327,12 +340,6 @@ int CameraSensor::getControls(ControlList *ctrls) return subdev_->getControls(ctrls); } -/** - * \fn CameraSensor::properties() - * \brief Retrieve the camera sensor properties - * \return The list of camera sensor properties - */ - /** * \brief Write controls to the sensor * \param[in] ctrls The list of controls to write @@ -363,11 +370,27 @@ int CameraSensor::setControls(ControlList *ctrls) return subdev_->setControls(ctrls); } +/** + * \fn CameraSensor::properties() + * \brief Retrieve the camera sensor properties + * \return The list of camera sensor properties + */ + std::string CameraSensor::logPrefix() const { return "'" + subdev_->entity()->name() + "'"; } +/** + * \var CameraSensor::properties_ + * \brief The list of camera sensor properties + */ + +/** + * \var CameraSensor::subdev_ + * \brief The camera sensor V4L2 subdevice + */ + /** * \class CameraSensorFactory * \brief Factory of camera sensors diff --git a/src/libcamera/include/camera_sensor.h b/src/libcamera/include/camera_sensor.h index 8ffc787e740f..6e4d2b0118bc 100644 --- a/src/libcamera/include/camera_sensor.h +++ b/src/libcamera/include/camera_sensor.h @@ -34,6 +34,7 @@ public: CameraSensor &operator=(const CameraSensor &) = delete; int init(); + virtual int initProperties(); const MediaEntity *entity() const { return entity_; } const std::vector &mbusCodes() const { return mbusCodes_; } @@ -53,14 +54,14 @@ public: protected: std::string logPrefix() const; + ControlList properties_; + V4L2Subdevice *subdev_; + private: const MediaEntity *entity_; - V4L2Subdevice *subdev_; std::vector mbusCodes_; std::vector sizes_; - - ControlList properties_; }; class CameraSensorFactory From patchwork Thu Mar 26 14:59:26 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 3333 X-Patchwork-Delegate: jacopo@jmondi.org Return-Path: Received: from relay7-d.mail.gandi.net (relay7-d.mail.gandi.net [217.70.183.200]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 943BF60414 for ; Thu, 26 Mar 2020 15:56:35 +0100 (CET) X-Originating-IP: 2.224.242.101 Received: from localhost.localdomain (2-224-242-101.ip172.fastwebnet.it [2.224.242.101]) (Authenticated sender: jacopo@jmondi.org) by relay7-d.mail.gandi.net (Postfix) with ESMTPSA id 599DD20006 for ; Thu, 26 Mar 2020 14:56:35 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Thu, 26 Mar 2020 15:59:26 +0100 Message-Id: <20200326145927.324919-6-jacopo@jmondi.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200326145927.324919-1-jacopo@jmondi.org> References: <20200326145927.324919-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v4 5/6] libcamera: sensor: Add OV5670 camera sensor X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 26 Mar 2020 14:56:36 -0000 Add an OV5670 class to handle the Omnivision OV5670 image sensor and register it to the camera sensor factory and initialize its pixel array properties by overriding CameraSensor::initProperties() method. Add the newly created src/libcamera/sensor/ directory to the Doxygen exclude paths, as the documentation of each CameraSensor sub-class does not belong to the library core documentation. Reviewed-by: Laurent Pinchart Reviewed-by: Kieran Bingham Signed-off-by: Jacopo Mondi --- Documentation/Doxyfile.in | 3 +- src/libcamera/meson.build | 1 + src/libcamera/sensor/meson.build | 3 ++ src/libcamera/sensor/ov5670.cpp | 54 ++++++++++++++++++++++++++++++++ 4 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 src/libcamera/sensor/meson.build create mode 100644 src/libcamera/sensor/ov5670.cpp diff --git a/Documentation/Doxyfile.in b/Documentation/Doxyfile.in index 3dffbf823398..0df93d593b25 100644 --- a/Documentation/Doxyfile.in +++ b/Documentation/Doxyfile.in @@ -846,7 +846,8 @@ EXCLUDE = @TOP_SRCDIR@/include/libcamera/span.h \ @TOP_SRCDIR@/src/libcamera/include/device_enumerator_sysfs.h \ @TOP_SRCDIR@/src/libcamera/include/device_enumerator_udev.h \ @TOP_SRCDIR@/src/libcamera/pipeline/ \ - @TOP_SRCDIR@/src/libcamera/proxy/ + @TOP_SRCDIR@/src/libcamera/proxy/ \ + @TOP_SRCDIR@/src/libcamera/sensor/ # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build index 87fa09cde63d..358c784baa20 100644 --- a/src/libcamera/meson.build +++ b/src/libcamera/meson.build @@ -57,6 +57,7 @@ includes = [ subdir('pipeline') subdir('proxy') +subdir('sensor') libatomic = cc.find_library('atomic', required : false) libdl = cc.find_library('dl') diff --git a/src/libcamera/sensor/meson.build b/src/libcamera/sensor/meson.build new file mode 100644 index 000000000000..7af70370cf5c --- /dev/null +++ b/src/libcamera/sensor/meson.build @@ -0,0 +1,3 @@ +libcamera_sources += files([ + 'ov5670.cpp', +]) diff --git a/src/libcamera/sensor/ov5670.cpp b/src/libcamera/sensor/ov5670.cpp new file mode 100644 index 000000000000..d7339b9792e1 --- /dev/null +++ b/src/libcamera/sensor/ov5670.cpp @@ -0,0 +1,54 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2020, Google Inc. + * + * ov5670.cpp - OV5670 camera sensor + */ + +#include + +#include "camera_sensor.h" + +namespace libcamera { + +class OV5670 final : public CameraSensor +{ +public: + OV5670(const MediaEntity *entity); + int initProperties(); +}; + +/* + * \class OV5670 + * \brief Camera sensor class for Omnivision OV5670 image sensor + */ + +/* + * \brief Construct the ov5670 sensor class + * \param[in] entity The media entity representing the sensor + */ +OV5670::OV5670(const MediaEntity *entity) + : CameraSensor(entity) +{ +} + +/* + * \brief Initialize Camera properties with ov5670 specific values + * \return 0 on success, a negative error code otherwise + */ +int OV5670::initProperties() +{ + /* Pixel Array Properties. */ + properties_.set(properties::PixelArraySize, { 2.9457f, 2.214f }); + properties_.set(properties::PixelArray, { 2592, 1944 }); + properties_.set(properties::ActiveAreas, { 16, 6, 2560, 1920 }); + properties_.set(properties::BayerFilterArrangement, + properties::BayerFilterGRBG); + properties_.set(properties::ISOSensitivityRange, { 50, 800 }); + + return CameraSensor::initProperties(); +} + +REGISTER_CAMERA_SENSOR(OV5670, "ov5670"); + +}; /* namespace libcamera */ From patchwork Thu Mar 26 14:59:27 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 3334 X-Patchwork-Delegate: jacopo@jmondi.org Return-Path: Received: from relay7-d.mail.gandi.net (relay7-d.mail.gandi.net [217.70.183.200]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 012AD62684 for ; Thu, 26 Mar 2020 15:56:36 +0100 (CET) X-Originating-IP: 2.224.242.101 Received: from localhost.localdomain (2-224-242-101.ip172.fastwebnet.it [2.224.242.101]) (Authenticated sender: jacopo@jmondi.org) by relay7-d.mail.gandi.net (Postfix) with ESMTPSA id B875A20015 for ; Thu, 26 Mar 2020 14:56:35 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Thu, 26 Mar 2020 15:59:27 +0100 Message-Id: <20200326145927.324919-7-jacopo@jmondi.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200326145927.324919-1-jacopo@jmondi.org> References: <20200326145927.324919-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v4 6/6] DNI: libcamera: sensor: ov5670: Add lens properties X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 26 Mar 2020 14:56:36 -0000 Register lens properties in the ov5670 sensor handler. This patch is not intended for merge as we know lens properties do no belong to the sensor handler, but I am including it anyhow to trigger discussions on where they would be more appropriately defined. Signed-off-by: Jacopo Mondi --- src/libcamera/sensor/ov5670.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/libcamera/sensor/ov5670.cpp b/src/libcamera/sensor/ov5670.cpp index d7339b9792e1..8c6a6114c9bf 100644 --- a/src/libcamera/sensor/ov5670.cpp +++ b/src/libcamera/sensor/ov5670.cpp @@ -46,6 +46,12 @@ int OV5670::initProperties() properties::BayerFilterGRBG); properties_.set(properties::ISOSensitivityRange, { 50, 800 }); + /* Lens Properties. */ + properties_.set(properties::LensApertures, { 0.0f }); + properties_.set(properties::LensFocalLengths, { 3.69f }); + properties_.set(properties::LensHyperfocalDistances, { 0.0f }); + properties_.set(properties::LensMinimumFocusDistance, 3.69f); + return CameraSensor::initProperties(); }