From patchwork Fri Apr 24 21:52:52 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 3519 Return-Path: Received: from relay3-d.mail.gandi.net (relay3-d.mail.gandi.net [217.70.183.195]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id B9AD5603FC for ; Fri, 24 Apr 2020 23:50:02 +0200 (CEST) X-Originating-IP: 87.3.55.240 Received: from uno.homenet.telecomitalia.it (host240-55-dynamic.3-87-r.retail.telecomitalia.it [87.3.55.240]) (Authenticated sender: jacopo@jmondi.org) by relay3-d.mail.gandi.net (Postfix) with ESMTPSA id EB12460002; Fri, 24 Apr 2020 21:50:01 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Fri, 24 Apr 2020 23:52:52 +0200 Message-Id: <20200424215304.558317-2-jacopo@jmondi.org> X-Mailer: git-send-email 2.26.1 In-Reply-To: <20200424215304.558317-1-jacopo@jmondi.org> References: <20200424215304.558317-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 01/13] libcamera: geometry: Rename Rectangle fields 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: Fri, 24 Apr 2020 21:50:02 -0000 The Rectangle class members that represents the rectangle horizontal and vertical sizes are named 'w' and 'h', in contrast with the Size and SizeRange classes which use 'width' and 'height', resulting in having to look at class definition every time to know which names to use. Signed-off-by: Jacopo Mondi Reviewed-by: Laurent Pinchart --- include/libcamera/geometry.h | 4 ++-- src/libcamera/geometry.cpp | 8 ++++---- src/libcamera/pipeline/ipu3/ipu3.cpp | 4 ++-- src/libcamera/v4l2_subdevice.cpp | 8 ++++---- src/libcamera/v4l2_videodevice.cpp | 8 ++++---- 5 files changed, 16 insertions(+), 16 deletions(-) diff --git a/include/libcamera/geometry.h b/include/libcamera/geometry.h index 7f1b29fe8c19..2d364891858c 100644 --- a/include/libcamera/geometry.h +++ b/include/libcamera/geometry.h @@ -15,8 +15,8 @@ namespace libcamera { struct Rectangle { int x; int y; - unsigned int w; - unsigned int h; + unsigned int width; + unsigned int height; const std::string toString() const; }; diff --git a/src/libcamera/geometry.cpp b/src/libcamera/geometry.cpp index 13f642be526f..fd78cf2c0ab7 100644 --- a/src/libcamera/geometry.cpp +++ b/src/libcamera/geometry.cpp @@ -40,12 +40,12 @@ namespace libcamera { */ /** - * \var Rectangle::w + * \var Rectangle::width * \brief The distance between the left and right sides */ /** - * \var Rectangle::h + * \var Rectangle::height * \brief The distance between the top and bottom sides */ @@ -57,7 +57,7 @@ const std::string Rectangle::toString() const { std::stringstream ss; - ss << "(" << x << "x" << y << ")/" << w << "x" << h; + ss << "(" << x << "x" << y << ")/" << width << "x" << height; return ss.str(); } @@ -69,7 +69,7 @@ const std::string Rectangle::toString() const bool operator==(const Rectangle &lhs, const Rectangle &rhs) { return lhs.x == rhs.x && lhs.y == rhs.y && - lhs.w == rhs.w && lhs.h == rhs.h; + lhs.width == rhs.width && lhs.height == rhs.height; } /** diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp index 36ac571a0b06..b45900159d06 100644 --- a/src/libcamera/pipeline/ipu3/ipu3.cpp +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp @@ -1132,8 +1132,8 @@ int ImgUDevice::configureInput(const Size &size, Rectangle rect = { .x = 0, .y = 0, - .w = inputFormat->size.width, - .h = inputFormat->size.height, + .width = inputFormat->size.width, + .height = inputFormat->size.height, }; ret = imgu_->setCrop(PAD_INPUT, &rect); if (ret) diff --git a/src/libcamera/v4l2_subdevice.cpp b/src/libcamera/v4l2_subdevice.cpp index c28e591ba51a..5a479a96b795 100644 --- a/src/libcamera/v4l2_subdevice.cpp +++ b/src/libcamera/v4l2_subdevice.cpp @@ -355,8 +355,8 @@ int V4L2Subdevice::setSelection(unsigned int pad, unsigned int target, sel.r.left = rect->x; sel.r.top = rect->y; - sel.r.width = rect->w; - sel.r.height = rect->h; + sel.r.width = rect->width; + sel.r.height = rect->height; int ret = ioctl(VIDIOC_SUBDEV_S_SELECTION, &sel); if (ret < 0) { @@ -368,8 +368,8 @@ int V4L2Subdevice::setSelection(unsigned int pad, unsigned int target, rect->x = sel.r.left; rect->y = sel.r.top; - rect->w = sel.r.width; - rect->h = sel.r.height; + rect->width = sel.r.width; + rect->height = sel.r.height; return 0; } diff --git a/src/libcamera/v4l2_videodevice.cpp b/src/libcamera/v4l2_videodevice.cpp index a959cfe65c43..beeec3ebe869 100644 --- a/src/libcamera/v4l2_videodevice.cpp +++ b/src/libcamera/v4l2_videodevice.cpp @@ -1121,8 +1121,8 @@ int V4L2VideoDevice::setSelection(unsigned int target, Rectangle *rect) sel.r.left = rect->x; sel.r.top = rect->y; - sel.r.width = rect->w; - sel.r.height = rect->h; + sel.r.width = rect->width; + sel.r.height = rect->height; int ret = ioctl(VIDIOC_S_SELECTION, &sel); if (ret < 0) { @@ -1133,8 +1133,8 @@ int V4L2VideoDevice::setSelection(unsigned int target, Rectangle *rect) rect->x = sel.r.left; rect->y = sel.r.top; - rect->w = sel.r.width; - rect->h = sel.r.height; + rect->width = sel.r.width; + rect->height = sel.r.height; return 0; } From patchwork Fri Apr 24 21:52:53 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 3520 Return-Path: Received: from relay3-d.mail.gandi.net (relay3-d.mail.gandi.net [217.70.183.195]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 3FF73603FD for ; Fri, 24 Apr 2020 23:50:04 +0200 (CEST) X-Originating-IP: 87.3.55.240 Received: from uno.homenet.telecomitalia.it (host240-55-dynamic.3-87-r.retail.telecomitalia.it [87.3.55.240]) (Authenticated sender: jacopo@jmondi.org) by relay3-d.mail.gandi.net (Postfix) with ESMTPSA id EB1D860004; Fri, 24 Apr 2020 21:50:02 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Fri, 24 Apr 2020 23:52:53 +0200 Message-Id: <20200424215304.558317-3-jacopo@jmondi.org> X-Mailer: git-send-email 2.26.1 In-Reply-To: <20200424215304.558317-1-jacopo@jmondi.org> References: <20200424215304.558317-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 02/13] 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: Fri, 24 Apr 2020 21:50:04 -0000 Add definition of pixel array related properties. Reviewed-by: Niklas Söderlund Signed-off-by: Jacopo Mondi --- 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..8f6797723a9d 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 PixelArray 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 Fri Apr 24 21:52:54 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 3521 Return-Path: Received: from relay3-d.mail.gandi.net (relay3-d.mail.gandi.net [217.70.183.195]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 6AE8B603FD for ; Fri, 24 Apr 2020 23:50:06 +0200 (CEST) X-Originating-IP: 87.3.55.240 Received: from uno.homenet.telecomitalia.it (host240-55-dynamic.3-87-r.retail.telecomitalia.it [87.3.55.240]) (Authenticated sender: jacopo@jmondi.org) by relay3-d.mail.gandi.net (Postfix) with ESMTPSA id 71CCC60002; Fri, 24 Apr 2020 21:50:04 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Fri, 24 Apr 2020 23:52:54 +0200 Message-Id: <20200424215304.558317-4-jacopo@jmondi.org> X-Mailer: git-send-email 2.26.1 In-Reply-To: <20200424215304.558317-1-jacopo@jmondi.org> References: <20200424215304.558317-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 03/13] 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: Fri, 24 Apr 2020 21:50:06 -0000 Define properties that describe the optical characteristics of the image sensor. Reviewed-by: Niklas Söderlund Signed-off-by: Jacopo Mondi --- 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 8f6797723a9d..0402e317f170 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 Fri Apr 24 21:52:55 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 3522 Return-Path: Received: from relay3-d.mail.gandi.net (relay3-d.mail.gandi.net [217.70.183.195]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 92119603FD for ; Fri, 24 Apr 2020 23:50:07 +0200 (CEST) X-Originating-IP: 87.3.55.240 Received: from uno.homenet.telecomitalia.it (host240-55-dynamic.3-87-r.retail.telecomitalia.it [87.3.55.240]) (Authenticated sender: jacopo@jmondi.org) by relay3-d.mail.gandi.net (Postfix) with ESMTPSA id 9D33D60004; Fri, 24 Apr 2020 21:50:06 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Fri, 24 Apr 2020 23:52:55 +0200 Message-Id: <20200424215304.558317-5-jacopo@jmondi.org> X-Mailer: git-send-email 2.26.1 In-Reply-To: <20200424215304.558317-1-jacopo@jmondi.org> References: <20200424215304.558317-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 04/13] libcamera: v4l2_subdevice: Implement get selection 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: Fri, 24 Apr 2020 21:50:07 -0000 Implement get selection for the V4L2Subdevice class to support retrieving three targets: the subdevice native size, the analog crop and the active pixel area. Signed-off-by: Jacopo Mondi --- src/libcamera/include/v4l2_subdevice.h | 6 ++ src/libcamera/v4l2_subdevice.cpp | 92 ++++++++++++++++++++++++++ 2 files changed, 98 insertions(+) diff --git a/src/libcamera/include/v4l2_subdevice.h b/src/libcamera/include/v4l2_subdevice.h index 4a04eadfb1f9..763ffadb61fb 100644 --- a/src/libcamera/include/v4l2_subdevice.h +++ b/src/libcamera/include/v4l2_subdevice.h @@ -46,6 +46,10 @@ public: const MediaEntity *entity() const { return entity_; } + int getNativeSize(unsigned int pad, Size *size); + int getActiveArea(unsigned int pad, Rectangle *rect); + int getCropRectangle(unsigned int pad, Rectangle *rect); + int setCrop(unsigned int pad, Rectangle *rect); int setCompose(unsigned int pad, Rectangle *rect); @@ -67,6 +71,8 @@ private: std::vector enumPadSizes(unsigned int pad, unsigned int code); + int getSelection(unsigned int pad, unsigned int target, + Rectangle *rect); int setSelection(unsigned int pad, unsigned int target, Rectangle *rect); diff --git a/src/libcamera/v4l2_subdevice.cpp b/src/libcamera/v4l2_subdevice.cpp index 5a479a96b795..4dcf8ce48754 100644 --- a/src/libcamera/v4l2_subdevice.cpp +++ b/src/libcamera/v4l2_subdevice.cpp @@ -133,6 +133,68 @@ int V4L2Subdevice::open() * \return The subdevice's associated media entity. */ +/** + * \brief Get the sub-device native size + * \param[in] pad The 0-indexed pad number the rectangle is to be applied to + * \param[out] size The sub-device native area size + * + * Retrieve the size of the sub-device native area. + * If the sub-device represent an image sensor, the native area describes + * the pixel array dimensions, including inactive and calibration pixels. + * + * \return 0 on success or a negative error code otherwise + * \retval -ENOTTY The native size information is not available + */ +int V4L2Subdevice::getNativeSize(unsigned int pad, Size *size) +{ + Rectangle rect = {}; + int ret = getSelection(pad, V4L2_SEL_TGT_NATIVE_SIZE, &rect); + if (ret) + return ret; + + size->width = rect.width; + size->height = rect.height; + + return 0; +} + +/** + * \brief Get the active area rectangle + * \param[in] pad The 0-indexed pad number the rectangle is to be applied to + * \param[out] rect The rectangle describing the sub-device active area + * + * Retrieve the rectangle describing the sub-device active area. + * If the sub-device represent an image sensor, the active area describes + * the pixel array active portion. + * + * The returned \a rect 'x' and 'y' fields represent the displacement from the + * native size rectangle top-left corner. + * + * \return 0 on success or a negative error code otherwise + * \retval -ENOTTY The active areas size information is not available + */ +int V4L2Subdevice::getActiveArea(unsigned int pad, Rectangle *rect) +{ + return getSelection(pad, V4L2_SEL_TGT_CROP_DEFAULT, rect); +} + +/** + * \brief Get the crop rectangle + * \param[in] pad The 0-indexed pad number the rectangle is to be applied to + * \param[out] rect The rectangle describing the cropped area rectangle + * + * Retrieve the rectangle representing the cropped area. If the sub-device + * represents an image sensor, the cropped area describes the pixel array + * portion from which the final image is produced from. + * + * \return 0 on success or a negative error code otherwise + * \retval -ENOTTY The crop rectangle size information is not available + */ +int V4L2Subdevice::getCropRectangle(unsigned int pad, Rectangle *rect) +{ + return getSelection(pad, V4L2_SEL_TGT_CROP, rect); +} + /** * \brief Set a crop rectangle on one of the V4L2 subdevice pads * \param[in] pad The 0-indexed pad number the rectangle is to be applied to @@ -343,6 +405,36 @@ std::vector V4L2Subdevice::enumPadSizes(unsigned int pad, return sizes; } +int V4L2Subdevice::getSelection(unsigned int pad, unsigned int target, + Rectangle *rect) +{ + struct v4l2_subdev_selection sel = {}; + + sel.which = V4L2_SUBDEV_FORMAT_ACTIVE; + sel.pad = pad; + sel.target = target; + sel.flags = 0; + + int ret = ioctl(VIDIOC_SUBDEV_G_SELECTION, &sel); + if (ret < 0 && ret != -ENOTTY) { + LOG(V4L2, Error) + << "Unable to get rectangle " << target << " on pad " + << pad << ": " << strerror(-ret); + return ret; + } + if (ret == -ENOTTY) { + LOG(V4L2, Debug) << "Selection API not available"; + return ret; + } + + rect->x = sel.r.left; + rect->y = sel.r.top; + rect->width = sel.r.width; + rect->height = sel.r.height; + + return 0; +} + int V4L2Subdevice::setSelection(unsigned int pad, unsigned int target, Rectangle *rect) { From patchwork Fri Apr 24 21:52:56 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 3523 Return-Path: Received: from relay3-d.mail.gandi.net (relay3-d.mail.gandi.net [217.70.183.195]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 6FC7462E4D for ; Fri, 24 Apr 2020 23:50:09 +0200 (CEST) X-Originating-IP: 87.3.55.240 Received: from uno.homenet.telecomitalia.it (host240-55-dynamic.3-87-r.retail.telecomitalia.it [87.3.55.240]) (Authenticated sender: jacopo@jmondi.org) by relay3-d.mail.gandi.net (Postfix) with ESMTPSA id C272860002; Fri, 24 Apr 2020 21:50:07 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Fri, 24 Apr 2020 23:52:56 +0200 Message-Id: <20200424215304.558317-6-jacopo@jmondi.org> X-Mailer: git-send-email 2.26.1 In-Reply-To: <20200424215304.558317-1-jacopo@jmondi.org> References: <20200424215304.558317-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 05/13] 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: Fri, 24 Apr 2020 21:50:09 -0000 Refactor the CameraSensor properties initialization to a dedicated function as it is expected to grow as we augment the number of properties. While at it, move documentation of the properties() method to match the declaration order in the class definition. Reviewed-by: Kieran Bingham Reviewed-by: Niklas Söderlund Signed-off-by: Jacopo Mondi Reviewed-by: Laurent Pinchart --- src/libcamera/camera_sensor.cpp | 99 +++++++++++++++------------ src/libcamera/include/camera_sensor.h | 1 + 2 files changed, 55 insertions(+), 45 deletions(-) diff --git a/src/libcamera/camera_sensor.cpp b/src/libcamera/camera_sensor.cpp index 2219a4307436..8d7abc7147a7 100644 --- a/src/libcamera/camera_sensor.cpp +++ b/src/libcamera/camera_sensor.cpp @@ -91,45 +91,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()) { @@ -160,6 +121,54 @@ 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. + * + * \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; } @@ -325,12 +334,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 @@ -361,6 +364,12 @@ 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() + "'"; diff --git a/src/libcamera/include/camera_sensor.h b/src/libcamera/include/camera_sensor.h index 99cff98128dc..8fa4d450f959 100644 --- a/src/libcamera/include/camera_sensor.h +++ b/src/libcamera/include/camera_sensor.h @@ -32,6 +32,7 @@ public: CameraSensor &operator=(const CameraSensor &) = delete; int init(); + int initProperties(); const MediaEntity *entity() const { return entity_; } const std::vector &mbusCodes() const { return mbusCodes_; } From patchwork Fri Apr 24 21:52:57 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 3524 Return-Path: Received: from relay3-d.mail.gandi.net (relay3-d.mail.gandi.net [217.70.183.195]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 4B52762F37 for ; Fri, 24 Apr 2020 23:50:10 +0200 (CEST) X-Originating-IP: 87.3.55.240 Received: from uno.homenet.telecomitalia.it (host240-55-dynamic.3-87-r.retail.telecomitalia.it [87.3.55.240]) (Authenticated sender: jacopo@jmondi.org) by relay3-d.mail.gandi.net (Postfix) with ESMTPSA id A0B1E60004; Fri, 24 Apr 2020 21:50:09 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Fri, 24 Apr 2020 23:52:57 +0200 Message-Id: <20200424215304.558317-7-jacopo@jmondi.org> X-Mailer: git-send-email 2.26.1 In-Reply-To: <20200424215304.558317-1-jacopo@jmondi.org> References: <20200424215304.558317-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 06/13] libcamera: camera_sensor: Collect 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: Fri, 24 Apr 2020 21:50:10 -0000 Collect the sensor pixel array properties by retrieving the subdevice native size and active pixel array size. Signed-off-by: Jacopo Mondi --- src/libcamera/camera_sensor.cpp | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/libcamera/camera_sensor.cpp b/src/libcamera/camera_sensor.cpp index 8d7abc7147a7..a54751fecf5a 100644 --- a/src/libcamera/camera_sensor.cpp +++ b/src/libcamera/camera_sensor.cpp @@ -169,6 +169,29 @@ int CameraSensor::initProperties() propertyValue = rotationControl->second.def().get(); properties_.set(properties::Rotation, propertyValue); + /* + * Sensor pixel array properties. Conditionally register them if the + * sub-device provides support for the selection API. + */ + Size size{}; + int ret = subdev_->getNativeSize(0, &size); + if (ret && ret != -ENOTTY) + return ret; + if (!ret) + properties_.set(properties::PixelArray, { static_cast(size.width), + static_cast(size.height) }); + + /* + * \todo The sub-device API only support a single active area rectangle + */ + Rectangle rect{}; + ret = subdev_->getActiveArea(0, &rect); + if (ret && ret != -ENOTTY) + return ret; + if (!ret) + properties_.set(properties::ActiveAreas, { rect.x, rect.y, + static_cast(rect.width), + static_cast(rect.height) }); return 0; } From patchwork Fri Apr 24 21:52:58 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 3525 Return-Path: Received: from relay3-d.mail.gandi.net (relay3-d.mail.gandi.net [217.70.183.195]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 2898E62E5D for ; Fri, 24 Apr 2020 23:50:11 +0200 (CEST) X-Originating-IP: 87.3.55.240 Received: from uno.homenet.telecomitalia.it (host240-55-dynamic.3-87-r.retail.telecomitalia.it [87.3.55.240]) (Authenticated sender: jacopo@jmondi.org) by relay3-d.mail.gandi.net (Postfix) with ESMTPSA id 73D8C60004; Fri, 24 Apr 2020 21:50:10 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Fri, 24 Apr 2020 23:52:58 +0200 Message-Id: <20200424215304.558317-8-jacopo@jmondi.org> X-Mailer: git-send-email 2.26.1 In-Reply-To: <20200424215304.558317-1-jacopo@jmondi.org> References: <20200424215304.558317-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 07/13] libcamera: camera_sensor: Define CameraSensorInfo 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: Fri, 24 Apr 2020 21:50:11 -0000 Define the CameraSensorInfo structure that reports the current image sensor configuration. Signed-off-by: Jacopo Mondi --- src/libcamera/camera_sensor.cpp | 99 +++++++++++++++++++++++++++ src/libcamera/include/camera_sensor.h | 13 ++++ 2 files changed, 112 insertions(+) diff --git a/src/libcamera/camera_sensor.cpp b/src/libcamera/camera_sensor.cpp index a54751fecf5a..e39f277622ae 100644 --- a/src/libcamera/camera_sensor.cpp +++ b/src/libcamera/camera_sensor.cpp @@ -28,6 +28,105 @@ namespace libcamera { LOG_DEFINE_CATEGORY(CameraSensor); +/** + * \struct CameraSensorInfo + * \brief Report the image sensor characteristics + * + * The structure reports image sensor characteristics used by IPA modules to + * tune their algorithms based on the image sensor model currently in use and + * its configuration. + * + * The here reported information describe the sensor's intrinsics + * characteristics, such as its pixel array size and the sensor model name, + * as well as information relative to the currently configured mode, such as + * the produced image size and the bit depth of the requested image format. + * + * Instances of this structure are meant to be assembled by the CameraSensor + * class and its specialized subclasses by inspecting the sensor static + * properties as well as the currently configured sensor mode. + */ + +/** + * \var CameraSensorInfo::name + * \brief The image sensor name + */ + +/** + * \var CameraSensorInfo::bitsPerPixel + * \brief The bits per-pixel of the image format produced by the image sensor + */ + +/** + * \var CameraSensorInfo::activeAreaSize + * \brief The size of the active pixel array area of the sensor + * \sa properties::PixelArray + */ + +/** + * \var CameraSensorInfo::analogCrop + * \brief The portion of the pixel array active area which is read-out and + * processed + * + * The analog crop rectangle top-left corner is defined as the displacement + * from the top-left corner of the pixel array active area. The rectangle + * horizontal and vertical sizes define the portion of the pixel matrix which + * is read-out and provided to the sensor's on-board processing pipeline, before + * any pixel sub-sampling method, such as pixel binning, skipping and averaging + * take place. + */ + +/** + * \var CameraSensorInfo::outputSize + * \brief The size of the images produced by the camera sensor + * + * The output image size defines the horizontal and vertical sizes of the images + * produced by the image sensor. The final output image size is defined as the + * end result of the sensor's on-board image processing pipeline stages, applied + * on the pixel array portion defined by the analog crop rectangle. Each image + * processing stage that performs pixel sub-sampling techniques, such as pixel + * binning or skipping, or perform any additional digital scaling concur in + * the definition of the final output image size. + */ + +/** + * \var CameraSensorInfo::lineLength + * \brief Total line length in pixels + * + * The total line length in pixels, including blanking and synchronism signal + * active state duration. + * + * In example: + * + * \verbatim + _______ _______ ___ + HREF ... ___| |___| |___| ... + _ _ _ + HSYNC ... _| |_________| |_________| |__ ... + + Valid ... ....xxxxxxxx....xxxxxxxx....xxx ... + Data + + Line ... /-----------/-----------/--- ... + Length + + \endverbatim + */ + +/** + * \var CameraSensorInfo::pixelClock + * \brief The pixel clock in Hz + * + * The pixel read out frequency in Hz. The property describes how many pixel + * per second are produced by the camera sensor, including blankings and + * synchronism signal active state duration. + * + * To obtain the read-out time in second of a full line: + * + * \verbatim + LineDuration(s) = lineLength(pixel) / pixelClock(Hz) + \endverbatim + */ + /** * \class CameraSensor * \brief A camera sensor based on V4L2 subdevices diff --git a/src/libcamera/include/camera_sensor.h b/src/libcamera/include/camera_sensor.h index 8fa4d450f959..e19852d4cabe 100644 --- a/src/libcamera/include/camera_sensor.h +++ b/src/libcamera/include/camera_sensor.h @@ -22,6 +22,19 @@ class V4L2Subdevice; struct V4L2SubdeviceFormat; +struct CameraSensorInfo { + std::string name; + + uint32_t bitsPerPixel; + + Size activeAreaSize; + Rectangle analogCrop; + Size outputSize; + + uint32_t pixelClock; + uint32_t lineLength; +}; + class CameraSensor : protected Loggable { public: From patchwork Fri Apr 24 21:52:59 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 3526 Return-Path: Received: from relay3-d.mail.gandi.net (relay3-d.mail.gandi.net [217.70.183.195]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 1EACC62E67 for ; Fri, 24 Apr 2020 23:50:12 +0200 (CEST) X-Originating-IP: 87.3.55.240 Received: from uno.homenet.telecomitalia.it (host240-55-dynamic.3-87-r.retail.telecomitalia.it [87.3.55.240]) (Authenticated sender: jacopo@jmondi.org) by relay3-d.mail.gandi.net (Postfix) with ESMTPSA id 5D7D160002; Fri, 24 Apr 2020 21:50:11 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Fri, 24 Apr 2020 23:52:59 +0200 Message-Id: <20200424215304.558317-9-jacopo@jmondi.org> X-Mailer: git-send-email 2.26.1 In-Reply-To: <20200424215304.558317-1-jacopo@jmondi.org> References: <20200424215304.558317-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 08/13] libcamera: v4l2_subdevice: Add format information 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: Fri, 24 Apr 2020 21:50:12 -0000 Define a map of static information associated with a media bus code. Start by reporting the bits-per-pixel for each media bus code defined by the V4L2 kernel API, to later expand it when necessary. Add to the V4L2SubdeviceFormat class a method to return the bits per pixel, retrieved by inspecting the static map of format information. Signed-off-by: Jacopo Mondi Reviewed-by: Laurent Pinchart --- src/libcamera/include/v4l2_subdevice.h | 3 + src/libcamera/v4l2_subdevice.cpp | 113 +++++++++++++++++++++++++ 2 files changed, 116 insertions(+) diff --git a/src/libcamera/include/v4l2_subdevice.h b/src/libcamera/include/v4l2_subdevice.h index 763ffadb61fb..43953a0a5a6c 100644 --- a/src/libcamera/include/v4l2_subdevice.h +++ b/src/libcamera/include/v4l2_subdevice.h @@ -23,10 +23,13 @@ namespace libcamera { class MediaDevice; struct V4L2SubdeviceFormat { + using infoMap = std::map; + uint32_t mbus_code; Size size; const std::string toString() const; + uint8_t bitsPerPixel() const; }; class V4L2Subdevice : public V4L2Device diff --git a/src/libcamera/v4l2_subdevice.cpp b/src/libcamera/v4l2_subdevice.cpp index 4dcf8ce48754..6f72c363fc7f 100644 --- a/src/libcamera/v4l2_subdevice.cpp +++ b/src/libcamera/v4l2_subdevice.cpp @@ -14,6 +14,7 @@ #include #include +#include #include #include @@ -32,6 +33,92 @@ namespace libcamera { LOG_DECLARE_CATEGORY(V4L2) +namespace { + +/* + * \var formatInfoMap + * \brief A map that associates information to V4L2 media bus codes + */ +const V4L2SubdeviceFormat::infoMap formatInfoMap = { + { V4L2_MBUS_FMT_RGB444_2X8_PADHI_BE, 16 }, + { V4L2_MBUS_FMT_RGB444_2X8_PADHI_LE, 16 }, + { V4L2_MBUS_FMT_RGB555_2X8_PADHI_BE, 16 }, + { V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE, 16 }, + { V4L2_MBUS_FMT_BGR565_2X8_BE, 16 }, + { V4L2_MBUS_FMT_BGR565_2X8_LE, 16 }, + { V4L2_MBUS_FMT_RGB565_2X8_BE, 16 }, + { V4L2_MBUS_FMT_RGB565_2X8_LE, 16 }, + { V4L2_MBUS_FMT_RGB666_1X18, 18 }, + { V4L2_MBUS_FMT_RGB888_1X24, 24 }, + { V4L2_MBUS_FMT_RGB888_2X12_BE, 24 }, + { V4L2_MBUS_FMT_RGB888_2X12_LE, 24 }, + { V4L2_MBUS_FMT_ARGB8888_1X32, 32 }, + { V4L2_MBUS_FMT_Y8_1X8, 8 }, + { V4L2_MBUS_FMT_UV8_1X8, 8 }, + { V4L2_MBUS_FMT_UYVY8_1_5X8, 40 }, + { V4L2_MBUS_FMT_VYUY8_1_5X8, 40 }, + { V4L2_MBUS_FMT_YUYV8_1_5X8, 40 }, + { V4L2_MBUS_FMT_YVYU8_1_5X8, 40 }, + { V4L2_MBUS_FMT_UYVY8_2X8, 16 }, + { V4L2_MBUS_FMT_VYUY8_2X8, 16 }, + { V4L2_MBUS_FMT_YUYV8_2X8, 16 }, + { V4L2_MBUS_FMT_YVYU8_2X8, 16 }, + { V4L2_MBUS_FMT_Y10_1X10, 10 }, + { V4L2_MBUS_FMT_UYVY10_2X10, 20 }, + { V4L2_MBUS_FMT_VYUY10_2X10, 20 }, + { V4L2_MBUS_FMT_YUYV10_2X10, 20 }, + { V4L2_MBUS_FMT_YVYU10_2X10, 20 }, + { V4L2_MBUS_FMT_Y12_1X12, 12 }, + { V4L2_MBUS_FMT_UYVY8_1X16, 16 }, + { V4L2_MBUS_FMT_VYUY8_1X16, 16 }, + { V4L2_MBUS_FMT_YUYV8_1X16, 16 }, + { V4L2_MBUS_FMT_YVYU8_1X16, 16 }, + { V4L2_MBUS_FMT_YDYUYDYV8_1X16, 16 }, + { V4L2_MBUS_FMT_UYVY10_1X20, 20 }, + { V4L2_MBUS_FMT_VYUY10_1X20, 20 }, + { V4L2_MBUS_FMT_YUYV10_1X20, 20 }, + { V4L2_MBUS_FMT_YVYU10_1X20, 20 }, + { V4L2_MBUS_FMT_YUV10_1X30, 30 }, + { V4L2_MBUS_FMT_AYUV8_1X32, 32 }, + { V4L2_MBUS_FMT_UYVY12_2X12, 24 }, + { V4L2_MBUS_FMT_VYUY12_2X12, 24 }, + { V4L2_MBUS_FMT_YUYV12_2X12, 24 }, + { V4L2_MBUS_FMT_YVYU12_2X12, 24 }, + { V4L2_MBUS_FMT_UYVY12_1X24, 24 }, + { V4L2_MBUS_FMT_VYUY12_1X24, 24 }, + { V4L2_MBUS_FMT_YUYV12_1X24, 24 }, + { V4L2_MBUS_FMT_YVYU12_1X24, 24 }, + { V4L2_MBUS_FMT_SBGGR8_1X8, 8 }, + { V4L2_MBUS_FMT_SGBRG8_1X8, 8 }, + { V4L2_MBUS_FMT_SGRBG8_1X8, 8 }, + { V4L2_MBUS_FMT_SRGGB8_1X8, 8 }, + { V4L2_MBUS_FMT_SBGGR10_ALAW8_1X8, 8 }, + { V4L2_MBUS_FMT_SGBRG10_ALAW8_1X8, 8 }, + { V4L2_MBUS_FMT_SGRBG10_ALAW8_1X8, 8 }, + { V4L2_MBUS_FMT_SRGGB10_ALAW8_1X8, 8 }, + { V4L2_MBUS_FMT_SBGGR10_DPCM8_1X8, 8 }, + { V4L2_MBUS_FMT_SGBRG10_DPCM8_1X8, 8 }, + { V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8, 8 }, + { V4L2_MBUS_FMT_SRGGB10_DPCM8_1X8, 8 }, + { V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_BE, 16 }, + { V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE, 16 }, + { V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_BE, 16 }, + { V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_LE, 16 }, + { V4L2_MBUS_FMT_SBGGR10_1X10, 10 }, + { V4L2_MBUS_FMT_SGBRG10_1X10, 10 }, + { V4L2_MBUS_FMT_SGRBG10_1X10, 10 }, + { V4L2_MBUS_FMT_SRGGB10_1X10, 10 }, + { V4L2_MBUS_FMT_SBGGR12_1X12, 24 }, + { V4L2_MBUS_FMT_SGBRG12_1X12, 24 }, + { V4L2_MBUS_FMT_SGRBG12_1X12, 24 }, + { V4L2_MBUS_FMT_SRGGB12_1X12, 24 }, + { V4L2_MBUS_FMT_JPEG_1X8, 8 }, + { V4L2_MBUS_FMT_S5C_UYVY_JPEG_1X8, 8 }, + { V4L2_MBUS_FMT_AHSV8888_1X32, 32 }, +}; + +}; /* namespace */ + /** * \struct V4L2SubdeviceFormat * \brief The V4L2 sub-device image format and sizes @@ -60,6 +147,14 @@ LOG_DECLARE_CATEGORY(V4L2) * Section 4.15.3.1 of the above mentioned Linux kernel documentation section. */ +/** + * \typedef V4L2SubdeviceFormat::infoMap + * \brief Map of static information associated with a V4L2 subdevice format + * + * \todo Expand with additional information. At the moment only the + * bits-per-pixel information is reported. + */ + /** * \var V4L2SubdeviceFormat::mbus_code * \brief The image format bus code @@ -81,6 +176,24 @@ const std::string V4L2SubdeviceFormat::toString() const return ss.str(); } +/** + * \brief Retrieve the number of bits per pixel for the V4L2 subdevice format + * \return The number of bits per pixel for the format, or default it to 8 if + * the format's mbus code is not supported + */ +uint8_t V4L2SubdeviceFormat::bitsPerPixel() const +{ + const auto it = formatInfoMap.find(mbus_code); + if (it == formatInfoMap.end()) { + LOG(V4L2, Error) << "No information available for format: '" + << toString() << "'"; + /* Return 8 to avoid divisions by 0. */ + return 8; + } + + return it->second; +} + /** * \class V4L2Subdevice * \brief A V4L2 subdevice as exposed by the Linux kernel From patchwork Fri Apr 24 21:53:00 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 3527 Return-Path: Received: from relay3-d.mail.gandi.net (relay3-d.mail.gandi.net [217.70.183.195]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 2194C62E5D for ; Fri, 24 Apr 2020 23:50:13 +0200 (CEST) X-Originating-IP: 87.3.55.240 Received: from uno.homenet.telecomitalia.it (host240-55-dynamic.3-87-r.retail.telecomitalia.it [87.3.55.240]) (Authenticated sender: jacopo@jmondi.org) by relay3-d.mail.gandi.net (Postfix) with ESMTPSA id 4F43060002; Fri, 24 Apr 2020 21:50:12 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Fri, 24 Apr 2020 23:53:00 +0200 Message-Id: <20200424215304.558317-10-jacopo@jmondi.org> X-Mailer: git-send-email 2.26.1 In-Reply-To: <20200424215304.558317-1-jacopo@jmondi.org> References: <20200424215304.558317-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 09/13] libcamera: v4l2_device: Add method to read a control 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: Fri, 24 Apr 2020 21:50:13 -0000 Add a method to the V4L2Device class to read a single control from a device. The current procedure to read a V4L2 Control from a device requires the user to setup a list and populate it using ControlList::set(), with a value that is ignored if the only interest is reading the control out. Provide a method to read a single control by just providing its id. The newly added method only supports non-span e non-string control but could be easily expanded later. Signed-off-by: Jacopo Mondi --- src/libcamera/include/v4l2_device.h | 18 ++++++++++++++++++ src/libcamera/v4l2_device.cpp | 11 +++++++++++ 2 files changed, 29 insertions(+) diff --git a/src/libcamera/include/v4l2_device.h b/src/libcamera/include/v4l2_device.h index ce8edd98a01d..23cff08bbfd0 100644 --- a/src/libcamera/include/v4l2_device.h +++ b/src/libcamera/include/v4l2_device.h @@ -11,6 +11,7 @@ #include #include +#include #include #include "log.h" @@ -27,6 +28,23 @@ public: const ControlInfoMap &controls() const { return controls_; } int getControls(ControlList *ctrls); + template::value && + !std::is_same>::value, + std::nullptr_t> = nullptr> + int getControl(unsigned int id, T *val) + { + ControlList list(controls_); + /* Reuse 'val' as we're only interested in reading. */ + list.set(id, *val); + + int ret = getControls(&list); + if (ret) + return ret; + *val = list.get(id).get(); + + return 0; + } + int setControls(ControlList *ctrls); const std::string &deviceNode() const { return deviceNode_; } diff --git a/src/libcamera/v4l2_device.cpp b/src/libcamera/v4l2_device.cpp index 03e305165096..9d67e0f63b1e 100644 --- a/src/libcamera/v4l2_device.cpp +++ b/src/libcamera/v4l2_device.cpp @@ -242,6 +242,17 @@ int V4L2Device::getControls(ControlList *ctrls) return ret; } +/** + * \fn int V4L2Device::getControl(unsigned int id, T *val) const + * \brief Get the value of the V4L2 control \a id from the device + * \param[in] id The V4L2 control ID + * \param[out] val The control value + * + * \todo This only supports non-span and non-string controls. + * + * \return 0 on success, a negative error code otherwise + */ + /** * \brief Write controls to the device * \param[in] ctrls The list of controls to write From patchwork Fri Apr 24 21:53:01 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 3528 Return-Path: Received: from relay3-d.mail.gandi.net (relay3-d.mail.gandi.net [217.70.183.195]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 261DD62E5D for ; Fri, 24 Apr 2020 23:50:14 +0200 (CEST) X-Originating-IP: 87.3.55.240 Received: from uno.homenet.telecomitalia.it (host240-55-dynamic.3-87-r.retail.telecomitalia.it [87.3.55.240]) (Authenticated sender: jacopo@jmondi.org) by relay3-d.mail.gandi.net (Postfix) with ESMTPSA id 6904C60002; Fri, 24 Apr 2020 21:50:13 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Fri, 24 Apr 2020 23:53:01 +0200 Message-Id: <20200424215304.558317-11-jacopo@jmondi.org> X-Mailer: git-send-email 2.26.1 In-Reply-To: <20200424215304.558317-1-jacopo@jmondi.org> References: <20200424215304.558317-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 10/13] test: v4l2_device: Test getControl() API 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: Fri, 24 Apr 2020 21:50:14 -0000 Add a simple test for the newly added method. Signed-off-by: Jacopo Mondi --- test/v4l2_videodevice/controls.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/test/v4l2_videodevice/controls.cpp b/test/v4l2_videodevice/controls.cpp index da9e0111e221..cf3d599c43ff 100644 --- a/test/v4l2_videodevice/controls.cpp +++ b/test/v4l2_videodevice/controls.cpp @@ -121,6 +121,22 @@ protected: return TestFail; } + /* Test the getControl() API. */ + int32_t oldBrightness = ctrls.get(V4L2_CID_BRIGHTNESS).get(); + int32_t newBrightness; + ret = capture_->getControl(V4L2_CID_BRIGHTNESS, &newBrightness); + if (ret) { + cerr << "Failed to read a single control" << endl; + return TestFail; + } + + if (newBrightness != oldBrightness) { + cerr << "Wrong control value read from device: " + << "got: " << newBrightness << " expected: " + << oldBrightness << endl; + return TestFail; + } + return TestPass; } }; From patchwork Fri Apr 24 21:53:02 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 3529 Return-Path: Received: from relay3-d.mail.gandi.net (relay3-d.mail.gandi.net [217.70.183.195]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 276EA62F6D for ; Fri, 24 Apr 2020 23:50:15 +0200 (CEST) X-Originating-IP: 87.3.55.240 Received: from uno.homenet.telecomitalia.it (host240-55-dynamic.3-87-r.retail.telecomitalia.it [87.3.55.240]) (Authenticated sender: jacopo@jmondi.org) by relay3-d.mail.gandi.net (Postfix) with ESMTPSA id 70E2F60002; Fri, 24 Apr 2020 21:50:14 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Fri, 24 Apr 2020 23:53:02 +0200 Message-Id: <20200424215304.558317-12-jacopo@jmondi.org> X-Mailer: git-send-email 2.26.1 In-Reply-To: <20200424215304.558317-1-jacopo@jmondi.org> References: <20200424215304.558317-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 11/13] libcamera: camera_sensor: Add method to get sensor info 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: Fri, 24 Apr 2020 21:50:15 -0000 Add method to retrieve the CameraSensorInfo to the CameraSensor class. Signed-off-by: Jacopo Mondi --- src/libcamera/camera_sensor.cpp | 84 +++++++++++++++++++++++++++ src/libcamera/include/camera_sensor.h | 1 + 2 files changed, 85 insertions(+) diff --git a/src/libcamera/camera_sensor.cpp b/src/libcamera/camera_sensor.cpp index e39f277622ae..c1ef4adb579c 100644 --- a/src/libcamera/camera_sensor.cpp +++ b/src/libcamera/camera_sensor.cpp @@ -492,6 +492,90 @@ int CameraSensor::setControls(ControlList *ctrls) * \return The list of camera sensor properties */ +/** + * \brief Assemble and return the camera sensor info + * \param[out] info The camera sensor info that report the sensor information + * + * The CameraSensorInfo content is assembled by inspecting the currently + * applied sensor configuration and the sensor static properties. + * + * \return 0 on success, a negative error code otherwise + */ +int CameraSensor::sensorInfo(CameraSensorInfo *info) const +{ + /* + * Make sure the sub-device exports all the controls we need to operate. + * + * Currently V4L2_CID_PIXEL_RATE and V4L2_CID_HBLANK are required. + * + * \todo This is an hard policy that all sensors that want to export + * a properly populated CameraSensorInfo have to adhere to. Consider if + * it's worth relaxing it and providing default values instead. + */ + const ControlInfoMap &controlMap = subdev_->controls(); + if (controlMap.find(V4L2_CID_PIXEL_RATE) == controlMap.end()) { + LOG(CameraSensor, Error) << "'Pixel rate' control not available"; + return -EINVAL; + } + + if (controlMap.find(V4L2_CID_HBLANK) == controlMap.end()) { + LOG(CameraSensor, Error) << "'HBLANK' control not available"; + return -EINVAL; + } + + /* + * Construct the camera sensor name using the media entity name. + * + * \todo There is no standardized naming scheme for sensor entities + * in the Linux kernel at the moment. The most common naming scheme + * is the one obtained by associating the sensor name and its I2C + * device and bus addresses in the form of: "devname i2c-adapt:i2c-addr" + * Assume this is the standard naming scheme and parse the first part + * of the entity name to obtain "devname". + */ + std::string entityName = subdev_->entity()->name(); + info->name = *utils::split(entityName, " ").begin(); + + /* + * Get the active area size from the ActiveAreas property. + * + * \todo The ActiveAreas property aims to describe multiple + * active area rectangles. At the moment only a single active + * area rectangle is exposed by the subdevice API. Use that single + * rectangle width and height to construct the ActiveAreaSize. + */ + Span activeArea = properties_.get(properties::ActiveAreas); + info->activeAreaSize = { static_cast(activeArea[2]), + static_cast(activeArea[3]) }; + + /* The bit-depth and image size depend on the currently applied format. */ + V4L2SubdeviceFormat format{}; + int ret = subdev_->getFormat(0, &format); + if (ret) + return ret; + info->bitsPerPixel = format.bitsPerPixel(); + info->outputSize = format.size; + + /* It's mandatory for the subdevice to report its crop rectangle. */ + ret = subdev_->getCropRectangle(0, &info->analogCrop); + if (ret) { + LOG(CameraSensor, Error) + << "Failed to construct camera sensor info: " + << "the camera sensor does not report the crop rectangle"; + return ret; + } + + int64_t pixelRate; + subdev_->getControl(V4L2_CID_PIXEL_RATE, &pixelRate); + info->pixelClock = pixelRate; + + int32_t hblank; + subdev_->getControl(V4L2_CID_HBLANK, &hblank); + info->lineLength = info->outputSize.width + hblank; + + return 0; +} + std::string CameraSensor::logPrefix() const { return "'" + subdev_->entity()->name() + "'"; diff --git a/src/libcamera/include/camera_sensor.h b/src/libcamera/include/camera_sensor.h index e19852d4cabe..b162c3886b1d 100644 --- a/src/libcamera/include/camera_sensor.h +++ b/src/libcamera/include/camera_sensor.h @@ -61,6 +61,7 @@ public: int setControls(ControlList *ctrls); const ControlList &properties() const { return properties_; } + int sensorInfo(CameraSensorInfo *info) const; protected: std::string logPrefix() const; From patchwork Fri Apr 24 21:53:03 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 3530 Return-Path: Received: from relay3-d.mail.gandi.net (relay3-d.mail.gandi.net [217.70.183.195]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id F38CB62E67 for ; Fri, 24 Apr 2020 23:50:15 +0200 (CEST) X-Originating-IP: 87.3.55.240 Received: from uno.homenet.telecomitalia.it (host240-55-dynamic.3-87-r.retail.telecomitalia.it [87.3.55.240]) (Authenticated sender: jacopo@jmondi.org) by relay3-d.mail.gandi.net (Postfix) with ESMTPSA id 56F0B60002; Fri, 24 Apr 2020 21:50:15 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Fri, 24 Apr 2020 23:53:03 +0200 Message-Id: <20200424215304.558317-13-jacopo@jmondi.org> X-Mailer: git-send-email 2.26.1 In-Reply-To: <20200424215304.558317-1-jacopo@jmondi.org> References: <20200424215304.558317-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 12/13] libcamera: v4l2_device: Update documentation 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: Fri, 24 Apr 2020 21:50:16 -0000 Compound controls are now supported, but they're still listed as unsupported in some parts of the V4L2Device class documentation. Fix this by removing those parts. Signed-off-by: Jacopo Mondi Reviewed-by: Laurent Pinchart --- src/libcamera/v4l2_device.cpp | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/libcamera/v4l2_device.cpp b/src/libcamera/v4l2_device.cpp index 9d67e0f63b1e..da7eb2bc5849 100644 --- a/src/libcamera/v4l2_device.cpp +++ b/src/libcamera/v4l2_device.cpp @@ -153,9 +153,9 @@ void V4L2Device::close() * their values in the corresponding \a ctrls entry. * * 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 a compound control, or if any - * other error occurs during validation of the requested controls, no control is - * read and this method returns -EINVAL. + * 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 + * method returns -EINVAL. * * If an error occurs while reading the controls, the index of the first control * that couldn't be read is returned. The value of all controls below that index @@ -262,10 +262,9 @@ int V4L2Device::getControls(ControlList *ctrls) * \a ctrls entry. * * 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, is a - * compound control, or if any other error occurs during validation of - * the requested controls, no control is written and this method returns - * -EINVAL. + * has the V4L2_CTRL_FLAG_DISABLED flag set), is read-only, if any other error + * occurs during validation of the requested controls, no control is written and + * this method 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 @@ -395,7 +394,7 @@ void V4L2Device::listControls() ControlInfoMap::Map ctrls; struct v4l2_query_ext_ctrl ctrl = {}; - /* \todo Add support for menu and compound controls. */ + /* \todo Add support for menu controls. */ while (1) { ctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL | V4L2_CTRL_FLAG_NEXT_COMPOUND; @@ -468,8 +467,8 @@ void V4L2Device::updateControls(ControlList *ctrls, default: /* - * \todo To be changed when support for string and - * compound controls will be added. + * \todo To be changed when support for string controls + * will be added. */ value.set(v4l2Ctrl->value); break; From patchwork Fri Apr 24 21:53:04 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 3531 Return-Path: Received: from relay3-d.mail.gandi.net (relay3-d.mail.gandi.net [217.70.183.195]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 67DE762F5E for ; Fri, 24 Apr 2020 23:50:17 +0200 (CEST) X-Originating-IP: 87.3.55.240 Received: from uno.homenet.telecomitalia.it (host240-55-dynamic.3-87-r.retail.telecomitalia.it [87.3.55.240]) (Authenticated sender: jacopo@jmondi.org) by relay3-d.mail.gandi.net (Postfix) with ESMTPSA id 3367A60002; Fri, 24 Apr 2020 21:50:16 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Fri, 24 Apr 2020 23:53:04 +0200 Message-Id: <20200424215304.558317-14-jacopo@jmondi.org> X-Mailer: git-send-email 2.26.1 In-Reply-To: <20200424215304.558317-1-jacopo@jmondi.org> References: <20200424215304.558317-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 13/13] libcamera: ipa: Add support for CameraSensorInfo 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: Fri, 24 Apr 2020 21:50:17 -0000 Add support for camera sensor information in the libcamera IPA protocol. Define a new 'struct ipa_sensor_info' structure in the IPA context and use it to perform translation between the C and the C++ API. Update the IPAInterface::configure() operation to accept a new CameraSensorInfo parameter and port all users of that function to the new interface. Signed-off-by: Jacopo Mondi --- include/ipa/ipa_interface.h | 21 +++++++- src/ipa/libipa/ipa_interface_wrapper.cpp | 19 ++++++- src/ipa/libipa/ipa_interface_wrapper.h | 1 + src/ipa/rkisp1/rkisp1.cpp | 13 ++++- src/ipa/vimc/vimc.cpp | 4 +- src/libcamera/include/ipa_context_wrapper.h | 4 +- src/libcamera/ipa_context_wrapper.cpp | 24 +++++++-- src/libcamera/ipa_interface.cpp | 60 +++++++++++++++++++++ src/libcamera/pipeline/rkisp1/rkisp1.cpp | 9 +++- src/libcamera/proxy/ipa_proxy_linux.cpp | 4 +- src/libcamera/proxy/ipa_proxy_thread.cpp | 9 ++-- test/ipa/ipa_wrappers_test.cpp | 21 +++++++- 12 files changed, 173 insertions(+), 16 deletions(-) diff --git a/include/ipa/ipa_interface.h b/include/ipa/ipa_interface.h index e65844bc7b34..a7acc09c4715 100644 --- a/include/ipa/ipa_interface.h +++ b/include/ipa/ipa_interface.h @@ -18,6 +18,22 @@ struct ipa_context { const struct ipa_context_ops *ops; }; +struct ipa_sensor_info { +#define CAMERA_SENSOR_NAME_LEN 32 + char name[CAMERA_SENSOR_NAME_LEN]; + uint8_t bits_per_pixel; + uint32_t active_area_width; + uint32_t active_area_height; + int32_t analog_crop_left; + int32_t analog_crop_top; + uint32_t analog_crop_width; + uint32_t analog_crop_height; + uint32_t output_width; + uint32_t output_height; + uint32_t pixel_clock; + uint32_t line_length; +}; + struct ipa_stream { unsigned int id; unsigned int pixel_format; @@ -70,6 +86,7 @@ struct ipa_context_ops { const struct ipa_callback_ops *callbacks, void *cb_ctx); void (*configure)(struct ipa_context *ctx, + const struct ipa_sensor_info *sensor_info, const struct ipa_stream *streams, unsigned int num_streams, const struct ipa_control_info_map *maps, @@ -96,6 +113,7 @@ struct ipa_context *ipaCreate(); #include #include +#include "camera_sensor.h" #include "v4l2_controls.h" namespace libcamera { @@ -125,7 +143,8 @@ public: virtual int start() = 0; virtual void stop() = 0; - virtual void configure(const std::map &streamConfig, + virtual void configure(const CameraSensorInfo &sensorInfo, + const std::map &streamConfig, const std::map &entityControls) = 0; virtual void mapBuffers(const std::vector &buffers) = 0; diff --git a/src/ipa/libipa/ipa_interface_wrapper.cpp b/src/ipa/libipa/ipa_interface_wrapper.cpp index f50f93a0185a..049b9dd1eefc 100644 --- a/src/ipa/libipa/ipa_interface_wrapper.cpp +++ b/src/ipa/libipa/ipa_interface_wrapper.cpp @@ -15,6 +15,7 @@ #include #include "byte_stream_buffer.h" +#include "camera_sensor.h" /** * \file ipa_interface_wrapper.h @@ -111,6 +112,7 @@ void IPAInterfaceWrapper::register_callbacks(struct ipa_context *_ctx, } void IPAInterfaceWrapper::configure(struct ipa_context *_ctx, + const struct ipa_sensor_info *sensor_info, const struct ipa_stream *streams, unsigned int num_streams, const struct ipa_control_info_map *maps, @@ -120,6 +122,21 @@ void IPAInterfaceWrapper::configure(struct ipa_context *_ctx, ctx->serializer_.reset(); + /* Translate the IPA sensor info. */ + CameraSensorInfo sensorInfo{}; + sensorInfo.name = sensor_info->name; + sensorInfo.bitsPerPixel = sensor_info->bits_per_pixel; + sensorInfo.activeAreaSize = { sensor_info->active_area_width, + sensor_info->active_area_height, }; + sensorInfo.analogCrop = { sensor_info->analog_crop_left, + sensor_info->analog_crop_top, + sensor_info->analog_crop_width, + sensor_info->analog_crop_height, }; + sensorInfo.outputSize = { sensor_info->output_width, + sensor_info->output_height, }; + sensorInfo.pixelClock = sensor_info->pixel_clock; + sensorInfo.lineLength = sensor_info->line_length; + /* Translate the IPA stream configurations map. */ std::map ipaStreams; @@ -145,7 +162,7 @@ void IPAInterfaceWrapper::configure(struct ipa_context *_ctx, entityControls.emplace(id, infoMaps[id]); } - ctx->ipa_->configure(ipaStreams, entityControls); + ctx->ipa_->configure(sensorInfo, ipaStreams, entityControls); } void IPAInterfaceWrapper::map_buffers(struct ipa_context *_ctx, diff --git a/src/ipa/libipa/ipa_interface_wrapper.h b/src/ipa/libipa/ipa_interface_wrapper.h index e4bc6dd4535d..febd6e66d0c4 100644 --- a/src/ipa/libipa/ipa_interface_wrapper.h +++ b/src/ipa/libipa/ipa_interface_wrapper.h @@ -30,6 +30,7 @@ private: const struct ipa_callback_ops *callbacks, void *cb_ctx); static void configure(struct ipa_context *ctx, + const struct ipa_sensor_info *sensor_info, const struct ipa_stream *streams, unsigned int num_streams, const struct ipa_control_info_map *maps, diff --git a/src/ipa/rkisp1/rkisp1.cpp b/src/ipa/rkisp1/rkisp1.cpp index acbbe58c7a2e..8b081359afff 100644 --- a/src/ipa/rkisp1/rkisp1.cpp +++ b/src/ipa/rkisp1/rkisp1.cpp @@ -22,6 +22,7 @@ #include #include +#include "camera_sensor.h" #include "log.h" #include "utils.h" @@ -36,7 +37,8 @@ public: int start() override { return 0; } void stop() override {} - void configure(const std::map &streamConfig, + void configure(const CameraSensorInfo &info, + const std::map &streamConfig, const std::map &entityControls) override; void mapBuffers(const std::vector &buffers) override; void unmapBuffers(const std::vector &ids) override; @@ -66,7 +68,14 @@ private: uint32_t maxGain_; }; -void IPARkISP1::configure(const std::map &streamConfig, +/** + * \todo The RkISP1 pipeline currently provides an empty CameraSensorInfo + * if the connected sensor does not provide enough information to properly + * assemble one. Make sure the reported sensor information are relevant + * befor accessing them. + */ +void IPARkISP1::configure(const CameraSensorInfo &info, + const std::map &streamConfig, const std::map &entityControls) { if (entityControls.empty()) diff --git a/src/ipa/vimc/vimc.cpp b/src/ipa/vimc/vimc.cpp index d2267e11737f..b8aadd8588cb 100644 --- a/src/ipa/vimc/vimc.cpp +++ b/src/ipa/vimc/vimc.cpp @@ -19,6 +19,7 @@ #include +#include "camera_sensor.h" #include "log.h" namespace libcamera { @@ -36,7 +37,8 @@ public: int start() override; void stop() override; - void configure(const std::map &streamConfig, + void configure(const CameraSensorInfo &sensorInfo, + const std::map &streamConfig, const std::map &entityControls) override {} void mapBuffers(const std::vector &buffers) override {} void unmapBuffers(const std::vector &ids) override {} diff --git a/src/libcamera/include/ipa_context_wrapper.h b/src/libcamera/include/ipa_context_wrapper.h index 0a48bfe732c8..e11e7b6a894d 100644 --- a/src/libcamera/include/ipa_context_wrapper.h +++ b/src/libcamera/include/ipa_context_wrapper.h @@ -9,6 +9,7 @@ #include +#include "camera_sensor.h" #include "control_serializer.h" namespace libcamera { @@ -22,7 +23,8 @@ public: int init() override; int start() override; void stop() override; - void configure(const std::map &streamConfig, + void configure(const CameraSensorInfo &sensorInfo, + const std::map &streamConfig, const std::map &entityControls) override; void mapBuffers(const std::vector &buffers) override; diff --git a/src/libcamera/ipa_context_wrapper.cpp b/src/libcamera/ipa_context_wrapper.cpp index ab6ce396b88a..b1ff83aa8be8 100644 --- a/src/libcamera/ipa_context_wrapper.cpp +++ b/src/libcamera/ipa_context_wrapper.cpp @@ -12,6 +12,7 @@ #include #include "byte_stream_buffer.h" +#include "camera_sensor.h" #include "utils.h" /** @@ -104,17 +105,34 @@ void IPAContextWrapper::stop() ctx_->ops->stop(ctx_); } -void IPAContextWrapper::configure(const std::map &streamConfig, +void IPAContextWrapper::configure(const CameraSensorInfo &sensorInfo, + const std::map &streamConfig, const std::map &entityControls) { if (intf_) - return intf_->configure(streamConfig, entityControls); + return intf_->configure(sensorInfo, streamConfig, entityControls); if (!ctx_) return; serializer_.reset(); + /* Translate the camera sensor info. */ + struct ipa_sensor_info sensor_info = {}; + strncpy(sensor_info.name, sensorInfo.name.c_str(), + sensorInfo.name.length()); + sensor_info.bits_per_pixel = sensorInfo.bitsPerPixel; + sensor_info.active_area_width = sensorInfo.activeAreaSize.width; + sensor_info.active_area_height = sensorInfo.activeAreaSize.height; + sensor_info.analog_crop_left = sensorInfo.analogCrop.x; + sensor_info.analog_crop_top = sensorInfo.analogCrop.y; + sensor_info.analog_crop_width = sensorInfo.analogCrop.width; + sensor_info.analog_crop_height = sensorInfo.analogCrop.height; + sensor_info.output_width = sensorInfo.outputSize.width; + sensor_info.output_height = sensorInfo.outputSize.height; + sensor_info.pixel_clock = sensorInfo.pixelClock; + sensor_info.line_length = sensorInfo.lineLength; + /* Translate the IPA stream configurations map. */ struct ipa_stream c_streams[streamConfig.size()]; @@ -154,7 +172,7 @@ void IPAContextWrapper::configure(const std::map &strea ++i; } - ctx_->ops->configure(ctx_, c_streams, streamConfig.size(), + ctx_->ops->configure(ctx_, &sensor_info, c_streams, streamConfig.size(), c_info_maps, entityControls.size()); } diff --git a/src/libcamera/ipa_interface.cpp b/src/libcamera/ipa_interface.cpp index 890d4340e4f3..22a3567bc1d0 100644 --- a/src/libcamera/ipa_interface.cpp +++ b/src/libcamera/ipa_interface.cpp @@ -92,6 +92,65 @@ * \brief The IPA context operations */ +/** + * \struct ipa_sensor_info + * \brief Camera sensor information for the IPA context operations + * \sa libcamera::CameraSensorInfo + * + * \def CAMERA_SENSOR_NAME_LEN + * \brief The camera sensor name maximum length + * + * \var ipa_sensor_info::name + * \brief The camera sensor name + * \todo Remove this field as soon as no IPA depends on it anymore + * + * \var ipa_sensor_info::bits_per_pixel + * \brief The camera sensor image format bit depth + * \sa libcamera::CameraSensorInfo::bitsPerPixel + * + * \var ipa_sensor_info::active_area_width + * \brief The camera sensor pixel array active area width + * \sa libcamera::CameraSensorInfo::activeAreaSize + * + * \var ipa_sensor_info::active_area_height + * \brief The camera sensor pixel array active area height + * \sa libcamera::CameraSensorInfo::activeAreaSize + * + * \var ipa_sensor_info::analog_crop_left + * \brief The horizontal displacement from the active area top-left corner of + * the cropped portion of the pixel array matrix + * \sa libcamera::CameraSensorInfo::analogCrop + * + * \var ipa_sensor_info::analog_crop_top + * \brief The vertical displacement from the active area top-left corner of + * the cropped portion of the pixel array matrix + * \sa libcamera::CameraSensorInfo::analogCrop + * + * \var ipa_sensor_info::analog_crop_width + * \brief The horizontal size of the cropped portion of the pixel array matrix + * \sa libcamera::CameraSensorInfo::analogCrop + * + * \var ipa_sensor_info::analog_crop_height + * \brief The vertical size of the cropped portion of the pixel array matrix + * \sa libcamera::CameraSensorInfo::analogCrop + * + * \var ipa_sensor_info::output_width + * \brief The horizontal size of the output image + * \sa libcamera::CameraSensorInfo::outputSize + * + * \var ipa_sensor_info::output_height + * \brief The vertical size of the output image + * \sa libcamera::CameraSensorInfo::outputSize + * + * \var ipa_sensor_info::pixel_clock + * \brief the pixel clock out frequency in Hz + * \sa libcamera::CameraSensorInfo::pixelClock + * + * \var ipa_sensor_info::line_length + * \brief The full line length, including blanking, in pixel units + * \sa libcamera::CameraSensorInfo::lineLength + */ + /** * \struct ipa_stream * \brief Stream information for the IPA context operations @@ -447,6 +506,7 @@ namespace libcamera { /** * \fn IPAInterface::configure() * \brief Configure the IPA stream and sensor settings + * \param[in] sensorInfo Camera sensor information * \param[in] streamConfig Configuration of all active streams * \param[in] entityControls Controls provided by the pipeline entities * diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp index f42264361785..169492e8313f 100644 --- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp +++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp @@ -822,6 +822,13 @@ int PipelineHandlerRkISP1::start(Camera *camera) activeCamera_ = camera; /* Inform IPA of stream configuration and sensor controls. */ + CameraSensorInfo sensorInfo = {}; + ret = data->sensor_->sensorInfo(&sensorInfo); + if (ret) { + LOG(RkISP1, Info) << "Camera sensor information not available"; + sensorInfo = {}; + } + std::map streamConfig; streamConfig[0] = { .pixelFormat = data->stream_.configuration().pixelFormat, @@ -831,7 +838,7 @@ int PipelineHandlerRkISP1::start(Camera *camera) std::map entityControls; entityControls.emplace(0, data->sensor_->controls()); - data->ipa_->configure(streamConfig, entityControls); + data->ipa_->configure(sensorInfo, streamConfig, entityControls); return ret; } diff --git a/src/libcamera/proxy/ipa_proxy_linux.cpp b/src/libcamera/proxy/ipa_proxy_linux.cpp index 2aa80b946704..54b1abc4727b 100644 --- a/src/libcamera/proxy/ipa_proxy_linux.cpp +++ b/src/libcamera/proxy/ipa_proxy_linux.cpp @@ -10,6 +10,7 @@ #include #include +#include "camera_sensor.h" #include "ipa_module.h" #include "ipa_proxy.h" #include "ipc_unixsocket.h" @@ -29,7 +30,8 @@ public: int init() override { return 0; } int start() override { return 0; } void stop() override {} - void configure(const std::map &streamConfig, + void configure(const CameraSensorInfo &sensorInfo, + const std::map &streamConfig, const std::map &entityControls) override {} void mapBuffers(const std::vector &buffers) override {} void unmapBuffers(const std::vector &ids) override {} diff --git a/src/libcamera/proxy/ipa_proxy_thread.cpp b/src/libcamera/proxy/ipa_proxy_thread.cpp index 368ccca1cf60..b06734371b39 100644 --- a/src/libcamera/proxy/ipa_proxy_thread.cpp +++ b/src/libcamera/proxy/ipa_proxy_thread.cpp @@ -10,6 +10,7 @@ #include #include +#include "camera_sensor.h" #include "ipa_context_wrapper.h" #include "ipa_module.h" #include "ipa_proxy.h" @@ -29,7 +30,8 @@ public: int start() override; void stop() override; - void configure(const std::map &streamConfig, + void configure(const CameraSensorInfo &sensorInfo, + const std::map &streamConfig, const std::map &entityControls) override; void mapBuffers(const std::vector &buffers) override; void unmapBuffers(const std::vector &ids) override; @@ -126,10 +128,11 @@ void IPAProxyThread::stop() thread_.wait(); } -void IPAProxyThread::configure(const std::map &streamConfig, +void IPAProxyThread::configure(const CameraSensorInfo &sensorInfo, + const std::map &streamConfig, const std::map &entityControls) { - ipa_->configure(streamConfig, entityControls); + ipa_->configure(sensorInfo, streamConfig, entityControls); } void IPAProxyThread::mapBuffers(const std::vector &buffers) diff --git a/test/ipa/ipa_wrappers_test.cpp b/test/ipa/ipa_wrappers_test.cpp index fae1d56b67c7..2cd10f981ecc 100644 --- a/test/ipa/ipa_wrappers_test.cpp +++ b/test/ipa/ipa_wrappers_test.cpp @@ -15,6 +15,7 @@ #include #include +#include "camera_sensor.h" #include "device_enumerator.h" #include "ipa_context_wrapper.h" #include "media_device.h" @@ -60,9 +61,19 @@ public: report(Op_stop, TestPass); } - void configure(const std::map &streamConfig, + void configure(const CameraSensorInfo &sensorInfo, + const std::map &streamConfig, const std::map &entityControls) override { + /* Verify sensorInfo. */ + if (sensorInfo.outputSize.width != 2560 || + sensorInfo.outputSize.height != 1940) { + cerr << "configure(): Invalid sensor info sizes: (" + << sensorInfo.outputSize.width << "x" + << sensorInfo.outputSize.height << ")" << endl; + return report(Op_configure, TestFail); + } + /* Verify streamConfig. */ if (streamConfig.size() != 2) { cerr << "configure(): Invalid number of streams " @@ -287,13 +298,19 @@ protected: int ret; /* Test configure(). */ + CameraSensorInfo sensorInfo = { "sensor", 8, + { 2576, 1956 }, + { 8, 8, 2560, 1940 }, + { 2560, 1940 }, + 96000000, + 2918, }; std::map config{ { 1, { V4L2_PIX_FMT_YUYV, { 1024, 768 } } }, { 2, { V4L2_PIX_FMT_NV12, { 800, 600 } } }, }; std::map controlInfo; controlInfo.emplace(42, subdev_->controls()); - ret = INVOKE(configure, config, controlInfo); + ret = INVOKE(configure, sensorInfo, config, controlInfo); if (ret == TestFail) return TestFail;