From patchwork Mon Mar 9 18:04:39 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 3078 Return-Path: Received: from relay2-d.mail.gandi.net (relay2-d.mail.gandi.net [217.70.183.194]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id B8127628BD for ; Mon, 9 Mar 2020 19:02:08 +0100 (CET) X-Originating-IP: 93.34.114.233 Received: from uno.lan (93-34-114-233.ip49.fastwebnet.it [93.34.114.233]) (Authenticated sender: jacopo@jmondi.org) by relay2-d.mail.gandi.net (Postfix) with ESMTPSA id 7FADE40005 for ; Mon, 9 Mar 2020 18:02:08 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Mon, 9 Mar 2020 19:04:39 +0100 Message-Id: <20200309180444.725757-2-jacopo@jmondi.org> X-Mailer: git-send-email 2.25.0 In-Reply-To: <20200309180444.725757-1-jacopo@jmondi.org> References: <20200309180444.725757-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 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: Mon, 09 Mar 2020 18:02:08 -0000 Add definition of pixel array related properties. Signed-off-by: Jacopo Mondi --- v2 -> v3: - Pluralize PixelAreaSizes - Use the new 'size' property in place of 'compound'. I tried to set meaningful values but it's not easy to get them right.. --- src/libcamera/property_ids.yaml | 177 ++++++++++++++++++++++++++++++++ 1 file changed, 177 insertions(+) diff --git a/src/libcamera/property_ids.yaml b/src/libcamera/property_ids.yaml index ce627fa042ba..4cecb5ad9ac3 100644 --- a/src/libcamera/property_ids.yaml +++ b/src/libcamera/property_ids.yaml @@ -386,4 +386,181 @@ controls: | | | | +--------------------+ + + - PixelArraySize: + type: float + size: [2] + description: | + The physical sizes of the pixel array (width and height), in + millimeters. + + - PixelArrayBounds: + type: int32_t + size: [2] + description: | + The camera sensor pixel array bounding rectangle vertical and + horizontal sizes. + + For image sensors with a rectangular pixel array the sizes described by + this property are the same as the PixelAreaSize property size. + + For image sensors with more complex pixel array displacements (such as + cross-shaped pixel arrays, non symmetrical pixel arrays etc) this + property represents the bounding rectangle in which all pixel array + dimensions are inscribed into. + + In example, the bounding rectangle sizes for image sensor with a + cross-shaped pixel array is described as + + + PixelArrayBound(0) = width + /-----------------/ + + (0,0)-> +----+------+----+ / + | |//////| | | + +----+//////+----+ | + |////////////////| | PixelArrayBound(1) = height + +----+//////+----+ | + | |//////| | | + +----+------+----+ / + | + -> Cross-shaped pixel area + + - PixelArrays: + type: int32_t + size: [8] + description: | + The sensor pixel array rectangles, relative to the rectangle described + by the PixelArrayBounds property. + + This property describes an arbitrary number of (likely overlapping) + rectangles, representing the pixel array areas the sensor is composed + of. + + Each rectangle is defined by its displacement from pixel (0, 0) of + the bounding rectangle described by the PixelArrayBound property. + + For image sensors with a rectangular pixel array, a single rectangle + is required. For sensors with more complex pixel array displacements + multiple rectangles shall be specified, ordered from the tallest to the + shorter one. + + For each rectangle, this property reports the full pixel array size, + including non-active pixels, black level calibration pixels etc. + + In example, a simple sensor with a rectangular pixel array is described + as + + PixelArrayBound(0) = width + /-----------------/ + x1 x2 + (0,0)-> +-o------------o-+ / + y1 o +------------+ | | + | |////////////| | | + | |////////////| | | PixelArrayBound(1) = height + | |////////////| | | + y2 o +------------+ | | + +----------------+ / + + PixelArray = (x1, y1, (x2 - x1), (y2 - y1)) + + A more complex sensor, with a cross shaped pixel array displacement + is described with 2 rectangles, with the vertical rectangle + described first + + PixelArrayBound(0) = width + /-----------------/ + x1 x2 x3 x4 W + (0,0)-> +o---o------o---o+ / + | |//////| | | + y1 o+---+------+---+| | + ||///|//////|///|| | PixelArrayBound(1) = height + y2 o+---+------+---+| | + | |//////| | | + H +----+------+----+ / + + + PixelArray = ( (x2, 0, (x3 - x2), H), + (x1, y1, (x4 - x1), (y2 - y1)) + + - ActiveAreaSizes: + type: int32_t + size: [8] + description: | + The sensor active pixel area sizes, represented as rectangles + inscribed in the ones described by the PixelArrays property. + + One ActiveAreaSize rectangle per each rectangle described in the + PixelArrays property is required. As a consequence, the two properties + shall transport the same number of elements. + + The ActiveAreaSize rectangles represent the maximum image sizes the + sensor can produce. + + - 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 represent the arrangement of color filters + in the top-left 2x2 pixel square. + + In 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 filer 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 standard + ... From patchwork Mon Mar 9 18:04:40 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 3079 Return-Path: Received: from relay2-d.mail.gandi.net (relay2-d.mail.gandi.net [217.70.183.194]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 40B2062923 for ; Mon, 9 Mar 2020 19:02:09 +0100 (CET) X-Originating-IP: 93.34.114.233 Received: from uno.lan (93-34-114-233.ip49.fastwebnet.it [93.34.114.233]) (Authenticated sender: jacopo@jmondi.org) by relay2-d.mail.gandi.net (Postfix) with ESMTPSA id DBCA640005 for ; Mon, 9 Mar 2020 18:02:08 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Mon, 9 Mar 2020 19:04:40 +0100 Message-Id: <20200309180444.725757-3-jacopo@jmondi.org> X-Mailer: git-send-email 2.25.0 In-Reply-To: <20200309180444.725757-1-jacopo@jmondi.org> References: <20200309180444.725757-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 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: Mon, 09 Mar 2020 18:02:10 -0000 Define properties that describe the optical characteristics of the image sensor. Signed-off-by: Jacopo Mondi --- v2 -> v3: - Pluralize names of properties which transport multiple values - Again 'size' vs 'compound' is hard to guess --- 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 4cecb5ad9ac3..80f9b1b3c264 100644 --- a/src/libcamera/property_ids.yaml +++ b/src/libcamera/property_ids.yaml @@ -563,4 +563,38 @@ controls: The range of supported ISO sensitivities, as documented by the ISO 12232:2006 standard + - LensApertures: + type: float + size: [16] + 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: [16] + 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: [16] + 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 Mon Mar 9 18:04:41 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 3081 Return-Path: Received: from relay2-d.mail.gandi.net (relay2-d.mail.gandi.net [217.70.183.194]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 86FCB62950 for ; Mon, 9 Mar 2020 19:02:09 +0100 (CET) X-Originating-IP: 93.34.114.233 Received: from uno.lan (93-34-114-233.ip49.fastwebnet.it [93.34.114.233]) (Authenticated sender: jacopo@jmondi.org) by relay2-d.mail.gandi.net (Postfix) with ESMTPSA id 4284C40009 for ; Mon, 9 Mar 2020 18:02:09 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Mon, 9 Mar 2020 19:04:41 +0100 Message-Id: <20200309180444.725757-4-jacopo@jmondi.org> X-Mailer: git-send-email 2.25.0 In-Reply-To: <20200309180444.725757-1-jacopo@jmondi.org> References: <20200309180444.725757-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 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: Mon, 09 Mar 2020 18:02:11 -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. Signed-off-by: Jacopo Mondi Reviewed-by: Kieran Bingham --- v2 -> v3: - Update documentation - Register sensor name as REGISTER_CAMERA_SENSOR() second parameter - Create camera sensor as unique_ptr - Match entity name and key with std::string::find() in CameraSensorFactory::createSensor() --- src/libcamera/camera_sensor.cpp | 136 ++++++++++++++++++ src/libcamera/include/camera_sensor.h | 32 +++++ src/libcamera/pipeline/ipu3/ipu3.cpp | 9 +- src/libcamera/pipeline/rkisp1/rkisp1.cpp | 17 +-- src/libcamera/pipeline/vimc.cpp | 6 +- test/camera-sensor.cpp | 9 +- .../v4l2_videodevice_test.cpp | 3 +- test/v4l2_videodevice/v4l2_videodevice_test.h | 6 +- 8 files changed, 187 insertions(+), 31 deletions(-) diff --git a/src/libcamera/camera_sensor.cpp b/src/libcamera/camera_sensor.cpp index 2219a4307436..8bfe02c9e8ff 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,138 @@ std::string CameraSensor::logPrefix() const return "'" + subdev_->entity()->name() + "'"; } +/** + * \class CameraSensorFactory + * \brief Factory of camera sensors + * + * The class provides to camera sensors 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 handlers use the REGISTER_CAMERA_SENSOR() macro to + * add themselves to the camera sensor factory. Users of the factory + * creates camera sensor handler instances by using the static + * CameraSensorFactory::createInstance() method, which returns a pointer + * to the opportune CameraSensor sub-class if any, 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 that represents the sensor + * + * Register a new camera sensor factory which creates sensor handler instances + * that 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 ensures 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 and associated with an entity \a + * name. When a camera sensor is created for a media entity with the + * createSensor() method, the name of the media entity there provided 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 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 as + * a 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; + + /* + * Match the name of the entity with the keys in the factories + * map. The factories map keys are provided by the CameraSensor + * sub-class at factory registration time as the sensor + * entity name. + * + * To support both canonical sensor entity names (in the + * "devname i2c-adapt:i2c-addr" format) and non-canonical sensor + * names such (as VIMC's "Sensor B" ones), search for the key + * in the entity name. + * + * \todo Delegate matching to the CameraSensor sub-class + * to support more complex matching criteria. + */ + if (name.find(key) == std::string::npos) + continue; + + LOG(CameraSensor, Info) << "Create camera sensor for '" + << name << "'"; + + CameraSensorFactory *factory = it.second; + return std::unique_ptr(factory->create(entity)); + } + + LOG(CameraSensor, Info) << "Unsupported sensor '" << entity->name() + << "': using generic camera sensor"; + return std::make_unique(entity); +} + +/** + * \def REGISTER_CAMERA_SENSOR(sensor, entityName) + * \brief Register camera sensor \a name with the sensor factory + * \param[in] sensor The name of the camera sensor class to register + * \param[in] entityName The name of the image sensor supported by the factory + * + * Register camera sensor factory \a sensor with the global list of factories. + * The camera sensor factory supports image sensors identified by \a entityName. + * The sensor name reported by the media entity that identifies it is usually + * composed by the here provided \a entityName and the I2C bus and device ids. + */ + } /* namespace libcamera */ diff --git a/src/libcamera/include/camera_sensor.h b/src/libcamera/include/camera_sensor.h index 99cff98128dc..633955591b36 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, entityName) \ +class sensor##Factory final : public CameraSensorFactory \ +{ \ +public: \ + sensor##Factory() : CameraSensorFactory(entityName) {} \ + \ +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 387bb070b505..adef6c6703b6 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_; @@ -294,7 +293,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()) @@ -1322,7 +1321,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 13433b216747..3e3b22018430 100644 --- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp +++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp @@ -114,20 +114,15 @@ class RkISP1CameraData : public CameraData { public: RkISP1CameraData(PipelineHandler *pipe) - : CameraData(pipe), sensor_(nullptr), frame_(0), + : 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_; @@ -389,7 +384,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; } @@ -444,7 +439,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()) @@ -557,7 +552,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; /* @@ -907,7 +902,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.cpp b/src/libcamera/pipeline/vimc.cpp index 529909714bf5..6f725c6dda98 100644 --- a/src/libcamera/pipeline/vimc.cpp +++ b/src/libcamera/pipeline/vimc.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -47,7 +48,6 @@ public: ~VimcCameraData() { - delete sensor_; delete debayer_; delete scaler_; delete video_; @@ -57,7 +57,7 @@ public: int init(MediaDevice *media); void bufferReady(FrameBuffer *buffer); - CameraSensor *sensor_; + std::unique_ptr sensor_; V4L2Subdevice *debayer_; V4L2Subdevice *scaler_; V4L2VideoDevice *video_; @@ -403,7 +403,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 577da4cb601c..ae038de74864 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 Mon Mar 9 18:04:42 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 3080 Return-Path: Received: from relay2-d.mail.gandi.net (relay2-d.mail.gandi.net [217.70.183.194]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id F190962934 for ; Mon, 9 Mar 2020 19:02:09 +0100 (CET) X-Originating-IP: 93.34.114.233 Received: from uno.lan (93-34-114-233.ip49.fastwebnet.it [93.34.114.233]) (Authenticated sender: jacopo@jmondi.org) by relay2-d.mail.gandi.net (Postfix) with ESMTPSA id B391140009 for ; Mon, 9 Mar 2020 18:02:09 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Mon, 9 Mar 2020 19:04:42 +0100 Message-Id: <20200309180444.725757-5-jacopo@jmondi.org> X-Mailer: git-send-email 2.25.0 In-Reply-To: <20200309180444.725757-1-jacopo@jmondi.org> References: <20200309180444.725757-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 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: Mon, 09 Mar 2020 18:02:10 -0000 Refactor the CameraSensor properties initialization to a dedicated virtual function that derived classes could override to register sensor-specific properties 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. Signed-off-by: Jacopo Mondi Reviewed-by: Kieran Bingham --- 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 8bfe02c9e8ff..354f4704299f 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 633955591b36..747c37e8b2e4 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 Mon Mar 9 18:04:43 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 3082 Return-Path: Received: from relay2-d.mail.gandi.net (relay2-d.mail.gandi.net [217.70.183.194]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id B9C9562923 for ; Mon, 9 Mar 2020 19:02:10 +0100 (CET) X-Originating-IP: 93.34.114.233 Received: from uno.lan (93-34-114-233.ip49.fastwebnet.it [93.34.114.233]) (Authenticated sender: jacopo@jmondi.org) by relay2-d.mail.gandi.net (Postfix) with ESMTPSA id 2118E4000C for ; Mon, 9 Mar 2020 18:02:09 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Mon, 9 Mar 2020 19:04:43 +0100 Message-Id: <20200309180444.725757-6-jacopo@jmondi.org> X-Mailer: git-send-email 2.25.0 In-Reply-To: <20200309180444.725757-1-jacopo@jmondi.org> References: <20200309180444.725757-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 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: Mon, 09 Mar 2020 18:02:11 -0000 Add OV5670CameraSensor class to handle Omnivision OV5670 image sensor and register it to the camera sensor factory and initialize its pixel array properties by overriding CameraSensor::initProperties() method. Signed-off-by: Jacopo Mondi Reviewed-by: Kieran Bingham --- v2 -> v3: - Squash class introduction and patches registration - Update to use the new properties names --- src/libcamera/meson.build | 1 + src/libcamera/sensor/meson.build | 3 ++ src/libcamera/sensor/ov5670.cpp | 60 ++++++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+) create mode 100644 src/libcamera/sensor/meson.build create mode 100644 src/libcamera/sensor/ov5670.cpp 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..a027a0816e58 --- /dev/null +++ b/src/libcamera/sensor/ov5670.cpp @@ -0,0 +1,60 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2020, Google Inc. + * + * ov5670.cpp - OV5670 camera sensor + */ + +#include + +#include "camera_sensor.h" + +/** + * \file ov5670.cpp + * \brief Omnivision OV5670 image sensor + */ + +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::PixelArrayBounds, { 2592, 1944 }); + properties_.set(properties::PixelArrays, { 2592, 1944 }); + properties_.set(properties::ActiveAreaSizes, { 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 Mon Mar 9 18:04:44 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 3083 Return-Path: Received: from relay2-d.mail.gandi.net (relay2-d.mail.gandi.net [217.70.183.194]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 28F4A62923 for ; Mon, 9 Mar 2020 19:02:11 +0100 (CET) X-Originating-IP: 93.34.114.233 Received: from uno.lan (93-34-114-233.ip49.fastwebnet.it [93.34.114.233]) (Authenticated sender: jacopo@jmondi.org) by relay2-d.mail.gandi.net (Postfix) with ESMTPSA id DE9B54000C for ; Mon, 9 Mar 2020 18:02:10 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Mon, 9 Mar 2020 19:04:44 +0100 Message-Id: <20200309180444.725757-7-jacopo@jmondi.org> X-Mailer: git-send-email 2.25.0 In-Reply-To: <20200309180444.725757-1-jacopo@jmondi.org> References: <20200309180444.725757-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 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: Mon, 09 Mar 2020 18:02:12 -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 --- v2 -> v3: - Update to use new properties names --- 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 a027a0816e58..75ad1f3ce81f 100644 --- a/src/libcamera/sensor/ov5670.cpp +++ b/src/libcamera/sensor/ov5670.cpp @@ -52,6 +52,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(); }